ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
- case TLS_ST_CW_CLNT_HELLO:
- /* We only hit this in the case of HelloRetryRequest */
- return WRITE_TRAN_FINISHED;
-
case TLS_ST_CR_FINISHED:
if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
|| s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING)
st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
+ else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && !s->hello_retry_request)
+ st->hand_state = TLS_ST_CW_CHANGE;
else
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
/* Fall through */
case TLS_ST_CW_END_OF_EARLY_DATA:
+ case TLS_ST_CW_CHANGE:
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
break;
case TLS_ST_CW_CHANGE:
+ if (SSL_IS_TLS13(s))
+ break;
s->session->cipher = s->s3->tmp.new_cipher;
#ifdef OPENSSL_NO_COMP
s->session->compress_meth = 0;
SSL_COMP *comp;
#endif
SSL_SESSION *sess = s->session;
+ unsigned char *session_id;
if (!WPACKET_set_max_size(pkt, SSL3_RT_MAX_PLAIN_LENGTH)) {
/* Should not happen */
if (sess == NULL
|| !ssl_version_supported(s, sess->ssl_version)
|| !SSL_SESSION_is_resumable(sess)) {
- if (!ssl_get_new_session(s, 0)) {
+ if (!s->hello_retry_request && !ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
return 0;
}
}
/* Session ID */
- if (s->new_session || s->session->ssl_version == TLS1_3_VERSION)
- sess_id_len = 0;
- else
+ session_id = s->session->session_id;
+ if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) {
+ if (s->version == TLS1_3_VERSION
+ && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) {
+ sess_id_len = sizeof(s->tmp_session_id);
+ s->tmp_session_id_len = sess_id_len;
+ session_id = s->tmp_session_id;
+ if (!s->hello_retry_request
+ && ssl_randbytes(s, s->tmp_session_id,
+ sess_id_len) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ } else {
+ sess_id_len = 0;
+ }
+ } else {
sess_id_len = s->session->session_id_length;
+ if (s->version == TLS1_3_VERSION) {
+ s->tmp_session_id_len = sess_id_len;
+ memcpy(s->tmp_session_id, s->session->session_id, sess_id_len);
+ }
+ }
if (sess_id_len > sizeof(s->session->session_id)
|| !WPACKET_start_sub_packet_u8(pkt)
- || (sess_id_len != 0 && !WPACKET_memcpy(pkt, s->session->session_id,
+ || (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id,
sess_id_len))
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
- /* ssl_cipher_list_to_bytes() raises SSLerr if appropriate */
+
if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) {
/* SSLfatal() already called */
return 0;
PACKET session_id, extpkt;
size_t session_id_len;
const unsigned char *cipherchars;
- int al = SSL_AD_INTERNAL_ERROR;
unsigned int compression;
unsigned int sversion;
unsigned int context;
- int protverr, discard;
+ int discard;
RAW_EXTENSION *extensions = NULL;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp;
goto err;
}
- /*
- * We do this immediately so we know what format the ServerHello is in.
- * Must be done after reading the random data so we can check for the
- * TLSv1.3 downgrade sentinels
- */
- protverr = ssl_choose_client_version(s, sversion, 1, &al);
- if (protverr != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- protverr);
+ /* Get the session-id. */
+ if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
goto err;
}
-
- /*
- * In TLSv1.3 a ServerHello message signals a key change so the end of the
- * message must be on a record boundary.
- */
- if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_NOT_ON_RECORD_BOUNDARY);
+ session_id_len = PACKET_remaining(&session_id);
+ if (session_id_len > sizeof(s->session->session_id)
+ || session_id_len > SSL3_SESSION_ID_SIZE) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_SSL3_SESSION_ID_TOO_LONG);
goto err;
}
- /* Get the session-id. */
- if (!SSL_IS_TLS13(s)) {
- if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- session_id_len = PACKET_remaining(&session_id);
- if (session_id_len > sizeof s->session->session_id
- || session_id_len > SSL3_SESSION_ID_SIZE) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_SSL3_SESSION_ID_TOO_LONG);
- goto err;
- }
- } else {
- PACKET_null_init(&session_id);
- session_id_len = 0;
- }
-
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
- if (!SSL_IS_TLS13(s)) {
- if (!PACKET_get_1(pkt, &compression)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
- } else {
- compression = 0;
+ if (!PACKET_get_1(pkt, &compression)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
}
/* TLS extensions */
goto err;
}
+ if (!tls_collect_extensions(s, &extpkt,
+ SSL_EXT_TLS1_2_SERVER_HELLO
+ | SSL_EXT_TLS1_3_SERVER_HELLO,
+ &extensions, NULL, 1)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ if (!ssl_choose_client_version(s, sversion, extensions)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ /*
+ * Now we have chosen the version we need to check again that the extensions
+ * are appropriate for this version.
+ */
context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
: SSL_EXT_TLS1_2_SERVER_HELLO;
- if (!tls_collect_extensions(s, &extpkt, context, &extensions, NULL, 1)) {
- /* SSLfatal() already called */
+ if (!tls_validate_all_contexts(s, context, extensions)) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_BAD_EXTENSION);
goto err;
}
s->hit = 0;
if (SSL_IS_TLS13(s)) {
+ /*
+ * In TLSv1.3 a ServerHello message signals a key change so the end of
+ * the message must be on a record boundary.
+ */
+ if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+ SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ goto err;
+ }
+
+ if (compression != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_INVALID_COMPRESSION_ALGORITHM);
+ goto err;
+ }
+
+ if (session_id_len != s->tmp_session_id_len
+ || memcmp(PACKET_data(&session_id), s->tmp_session_id,
+ session_id_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
+ goto err;
+ }
+
/* This will set s->hit if we are resuming */
if (!tls_parse_extension(s, TLSEXT_IDX_psk,
SSL_EXT_TLS1_3_SERVER_HELLO,
- extensions, NULL, 0l)) {
+ extensions, NULL, 0)) {
/* SSLfatal() already called */
goto err;
}
}
s->session->ssl_version = s->version;
- s->session->session_id_length = session_id_len;
- /* session_id_len could be 0 */
- if (session_id_len > 0)
- memcpy(s->session->session_id, PACKET_data(&session_id),
- session_id_len);
+ /*
+ * In TLSv1.2 and below we save the session id we were sent so we can
+ * resume it later. In TLSv1.3 the session id we were sent is just an
+ * echo of what we originally sent in the ClientHello and should not be
+ * used for resumption.
+ */
+ if (!SSL_IS_TLS13(s)) {
+ s->session->session_id_length = session_id_len;
+ /* session_id_len could be 0 */
+ if (session_id_len > 0)
+ memcpy(s->session->session_id, PACKET_data(&session_id),
+ session_id_len);
+ }
}
/* Session version and negotiated protocol version should match */
#else
if (s->hit && compression != s->session->compress_meth) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
+ SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
goto err;
}
if (compression == 0)
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
+ ERR_R_MALLOC_FAILURE);
goto err;
}
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
- ERR_R_MALLOC_FAILURE);
+ ERR_R_MALLOC_FAILURE);
return 0;
}
}
return 1;
err:
EVP_PKEY_free(ckey);
-#endif
+ return 0;
+#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
ERR_R_INTERNAL_ERROR);
return 0;
+#endif
}
static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), NULL, 0, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
+ SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
+ ERR_R_INTERNAL_ERROR);
goto err;
}
* state and thus ssl3_send_alert may crash.
*/
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
- SSL_R_CANNOT_CHANGE_CIPHER);
+ SSL_R_CANNOT_CHANGE_CIPHER);
return 0;
}
{
if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
- SSLerr(SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}