diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index af77f991..d8c472d8 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2919,6 +2919,9 @@ struct ssl_early_callback_ctx { SSL *ssl; const uint8_t *client_hello; size_t client_hello_len; + uint16_t version; + const uint8_t *random; + size_t random_len; const uint8_t *session_id; size_t session_id_len; const uint8_t *cipher_suites; diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c index a6d26d15..d10d7f53 100644 --- a/ssl/handshake_server.c +++ b/ssl/handshake_server.c @@ -534,74 +534,54 @@ static int ssl3_get_client_hello(SSL *ssl) { int al = SSL_AD_INTERNAL_ERROR, ret = -1; const SSL_CIPHER *c; STACK_OF(SSL_CIPHER) *ciphers = NULL; - struct ssl_early_callback_ctx early_ctx; - CBS client_hello; - uint16_t client_wire_version; - CBS client_random, session_id, cipher_suites, compression_methods; SSL_SESSION *session = NULL; - /* We do this so that we will respond with our native type. If we are TLSv1 - * and we get SSLv3, we will respond with TLSv1, This down switching should - * be handled by a different method. If we are SSLv3, we will respond with - * SSLv3, even if prompted with TLSv1. */ - switch (ssl->state) { - case SSL3_ST_SR_CLNT_HELLO_A: { - int msg_ret = ssl->method->ssl_get_message(ssl, SSL3_MT_CLIENT_HELLO, - ssl_hash_message); - if (msg_ret <= 0) { - return msg_ret; - } - - ssl->state = SSL3_ST_SR_CLNT_HELLO_B; + if (ssl->state == SSL3_ST_SR_CLNT_HELLO_A) { + /* The first time around, read the ClientHello. */ + int msg_ret = ssl->method->ssl_get_message(ssl, SSL3_MT_CLIENT_HELLO, + ssl_hash_message); + if (msg_ret <= 0) { + return msg_ret; } - /* fallthrough */ - case SSL3_ST_SR_CLNT_HELLO_B: - case SSL3_ST_SR_CLNT_HELLO_C: - if (!ssl_early_callback_init(ssl, &early_ctx, ssl->init_msg, - ssl->init_num)) { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); - goto f_err; - } - if (ssl->state == SSL3_ST_SR_CLNT_HELLO_B && - ssl->ctx->select_certificate_cb != NULL) { - ssl->state = SSL3_ST_SR_CLNT_HELLO_C; - switch (ssl->ctx->select_certificate_cb(&early_ctx)) { - case 0: - ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; - goto err; - - case -1: - /* Connection rejected. */ - al = SSL_AD_ACCESS_DENIED; - OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); - goto f_err; - - default: - /* fallthrough */; - } - } - ssl->state = SSL3_ST_SR_CLNT_HELLO_C; - break; - - default: - OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); - return -1; + ssl->state = SSL3_ST_SR_CLNT_HELLO_B; } - CBS_init(&client_hello, ssl->init_msg, ssl->init_num); - if (!CBS_get_u16(&client_hello, &client_wire_version)) { + struct ssl_early_callback_ctx client_hello; + if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg, + ssl->init_num)) { al = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } - uint16_t client_version = ssl->method->version_from_wire(client_wire_version); + if (ssl->state == SSL3_ST_SR_CLNT_HELLO_B) { + /* Unlike other callbacks, the early callback is not run a second time if + * paused. */ + ssl->state = SSL3_ST_SR_CLNT_HELLO_C; - /* use version from inside client hello, not from record header (may differ: - * see RFC 2246, Appendix E, second paragraph) */ - ssl->client_version = client_wire_version; + /* Run the early callback. */ + if (ssl->ctx->select_certificate_cb != NULL) { + switch (ssl->ctx->select_certificate_cb(&client_hello)) { + case 0: + ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; + goto err; + + case -1: + /* Connection rejected. */ + al = SSL_AD_ACCESS_DENIED; + OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); + goto f_err; + + default: + /* fallthrough */; + } + } + } + + uint16_t client_version = + ssl->method->version_from_wire(client_hello.version); + ssl->client_version = client_hello.version; uint16_t min_version, max_version; if (!ssl_get_version_range(ssl, &min_version, &max_version)) { @@ -642,30 +622,16 @@ static int ssl3_get_client_hello(SSL *ssl) { return 1; } - if (!CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&client_hello, &session_id) || - CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - goto f_err; - } - /* Load the client random. */ - memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); - - if (SSL_is_dtls(ssl)) { - CBS cookie; - - if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || - CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - goto f_err; - } + if (client_hello.random_len != SSL3_RANDOM_SIZE) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; } + memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len); int send_new_ticket = 0; - switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) { + switch ( + ssl_get_prev_session(ssl, &session, &send_new_ticket, &client_hello)) { case ssl_session_success: break; case ssl_session_error: @@ -683,7 +649,7 @@ static int ssl3_get_client_hello(SSL *ssl) { CBS ems; int have_extended_master_secret = ssl->version != SSL3_VERSION && - ssl_early_callback_get_extension(&early_ctx, &ems, + ssl_early_callback_get_extension(&client_hello, &ems, TLSEXT_TYPE_extended_master_secret) && CBS_len(&ems) == 0; @@ -725,24 +691,14 @@ static int ssl3_get_client_hello(SSL *ssl) { } if (ssl->ctx->dos_protection_cb != NULL && - ssl->ctx->dos_protection_cb(&early_ctx) == 0) { + ssl->ctx->dos_protection_cb(&client_hello) == 0) { /* Connection rejected for DOS reasons. */ al = SSL_AD_ACCESS_DENIED; OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); goto f_err; } - if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || - CBS_len(&cipher_suites) == 0 || - CBS_len(&cipher_suites) % 2 != 0 || - !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || - CBS_len(&compression_methods) == 0) { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - goto f_err; - } - - ciphers = ssl_bytes_to_cipher_list(ssl, &cipher_suites, max_version); + ciphers = ssl_parse_client_cipher_list(ssl, &client_hello, max_version); if (ciphers == NULL) { goto err; } @@ -771,28 +727,19 @@ static int ssl3_get_client_hello(SSL *ssl) { } /* Only null compression is supported. */ - if (memchr(CBS_data(&compression_methods), 0, - CBS_len(&compression_methods)) == NULL) { + if (memchr(client_hello.compression_methods, 0, + client_hello.compression_methods_len) == NULL) { al = SSL_AD_ILLEGAL_PARAMETER; OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMPRESSION_SPECIFIED); goto f_err; } /* TLS extensions. */ - if (ssl->version >= SSL3_VERSION && - !ssl_parse_clienthello_tlsext(ssl, &client_hello)) { + if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); goto err; } - /* There should be nothing left over in the record. */ - if (CBS_len(&client_hello) != 0) { - /* wrong packet length */ - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); - goto f_err; - } - if (have_extended_master_secret != ssl->s3->tmp.extended_master_secret) { al = SSL_AD_INTERNAL_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_EMS_STATE_INCONSISTENT); diff --git a/ssl/internal.h b/ssl/internal.h index f64dc626..77759e46 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -958,6 +958,20 @@ int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret, size_t secret_len); +/* ClientHello functions. */ + +int ssl_early_callback_init(SSL *ssl, struct ssl_early_callback_ctx *ctx, + const uint8_t *in, size_t in_len); + +int ssl_early_callback_get_extension(const struct ssl_early_callback_ctx *ctx, + CBS *out, uint16_t extension_type); + +STACK_OF(SSL_CIPHER) * + ssl_parse_client_cipher_list(SSL *ssl, + const struct ssl_early_callback_ctx *ctx, + uint16_t max_version); + + /* Underdocumented functions. * * Functions below here haven't been touched up and may be underdocumented. */ @@ -1239,8 +1253,6 @@ enum ssl_session_result_t ssl_get_prev_session( OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int include_ticket); -STACK_OF(SSL_CIPHER) * - ssl_bytes_to_cipher_list(SSL *ssl, const CBS *cbs, uint16_t max_version); void ssl_cipher_preference_list_free( struct ssl_cipher_preference_list_st *cipher_list); struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *ssl); @@ -1370,12 +1382,6 @@ int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len); int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster, size_t premaster_len); -int ssl_early_callback_init(SSL *ssl, struct ssl_early_callback_ctx *ctx, - const uint8_t *in, size_t in_len); - -int ssl_early_callback_get_extension(const struct ssl_early_callback_ctx *ctx, - CBS *out, uint16_t extension_type); - /* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the * list of allowed group IDs. If |get_peer_groups| is non-zero, return the * peer's group list. Otherwise, return the preferred list. */ @@ -1412,7 +1418,8 @@ int tls1_check_ec_cert(SSL *ssl, X509 *x); int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len); int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out); -int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs); +int ssl_parse_clienthello_tlsext( + SSL *ssl, const struct ssl_early_callback_ctx *client_hello); int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs); #define tlsext_tick_md EVP_sha256 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 6a2dae86..04477e59 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1630,21 +1630,15 @@ int SSL_set_cipher_list(SSL *ssl, const char *str) { } STACK_OF(SSL_CIPHER) * - ssl_bytes_to_cipher_list(SSL *ssl, const CBS *cbs, uint16_t max_version) { - CBS cipher_suites = *cbs; - const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) *sk; + ssl_parse_client_cipher_list(SSL *ssl, + const struct ssl_early_callback_ctx *ctx, + uint16_t max_version) { + CBS cipher_suites; + CBS_init(&cipher_suites, ctx->cipher_suites, ctx->cipher_suites_len); - if (ssl->s3) { - ssl->s3->send_connection_binding = 0; - } + ssl->s3->send_connection_binding = 0; - if (CBS_len(&cipher_suites) % 2 != 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); - return NULL; - } - - sk = sk_SSL_CIPHER_new_null(); + STACK_OF(SSL_CIPHER) *sk = sk_SSL_CIPHER_new_null(); if (sk == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; @@ -1654,7 +1648,7 @@ STACK_OF(SSL_CIPHER) * uint16_t cipher_suite; if (!CBS_get_u16(&cipher_suites, &cipher_suite)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); goto err; } @@ -1680,7 +1674,7 @@ STACK_OF(SSL_CIPHER) * continue; } - c = SSL_get_cipher_by_value(cipher_suite); + const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_suite); if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 695f081d..64b2dacf 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -209,43 +209,39 @@ int ssl_early_callback_init(SSL *ssl, struct ssl_early_callback_ctx *ctx, ctx->client_hello = in; ctx->client_hello_len = in_len; - CBS client_hello, session_id, cipher_suites, compression_methods, extensions; + CBS client_hello, random, session_id; CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len); - - if (/* Skip client version. */ - !CBS_skip(&client_hello, 2) || - /* Skip client nonce. */ - !CBS_skip(&client_hello, 32) || - /* Extract session_id. */ - !CBS_get_u8_length_prefixed(&client_hello, &session_id)) { + if (!CBS_get_u16(&client_hello, &ctx->version) || + !CBS_get_bytes(&client_hello, &random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&client_hello, &session_id) || + CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { return 0; } + ctx->random = CBS_data(&random); + ctx->random_len = CBS_len(&random); ctx->session_id = CBS_data(&session_id); ctx->session_id_len = CBS_len(&session_id); /* Skip past DTLS cookie */ if (SSL_is_dtls(ctx->ssl)) { CBS cookie; - - if (!CBS_get_u8_length_prefixed(&client_hello, &cookie)) { + if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || + CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) { return 0; } } - /* Extract cipher_suites. */ + CBS cipher_suites, compression_methods; if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || - CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0) { - return 0; - } - ctx->cipher_suites = CBS_data(&cipher_suites); - ctx->cipher_suites_len = CBS_len(&cipher_suites); - - /* Extract compression_methods. */ - if (!CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || + CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 || + !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || CBS_len(&compression_methods) < 1) { return 0; } + + ctx->cipher_suites = CBS_data(&cipher_suites); + ctx->cipher_suites_len = CBS_len(&cipher_suites); ctx->compression_methods = CBS_data(&compression_methods); ctx->compression_methods_len = CBS_len(&compression_methods); @@ -258,11 +254,13 @@ int ssl_early_callback_init(SSL *ssl, struct ssl_early_callback_ctx *ctx, } /* Extract extensions and check it is valid. */ + CBS extensions; if (!CBS_get_u16_length_prefixed(&client_hello, &extensions) || !tls1_check_duplicate_extensions(&extensions) || CBS_len(&client_hello) != 0) { return 0; } + ctx->extensions = CBS_data(&extensions); ctx->extensions_len = CBS_len(&extensions); @@ -2512,7 +2510,9 @@ err: return 0; } -static int ssl_scan_clienthello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) { +static int ssl_scan_clienthello_tlsext( + SSL *ssl, const struct ssl_early_callback_ctx *client_hello, + int *out_alert) { size_t i; for (i = 0; i < kNumExtensions; i++) { if (kExtensions[i].init != NULL) { @@ -2527,53 +2527,44 @@ static int ssl_scan_clienthello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) { * sent as an SCSV. */ assert(kExtensions[0].value == TLSEXT_TYPE_renegotiate); - /* There may be no extensions. */ - if (CBS_len(cbs) != 0) { - /* Decode the extensions block and check it is valid. */ - CBS extensions; - if (!CBS_get_u16_length_prefixed(cbs, &extensions) || - !tls1_check_duplicate_extensions(&extensions)) { + CBS extensions; + CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len); + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; + + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { *out_alert = SSL_AD_DECODE_ERROR; return 0; } - while (CBS_len(&extensions) != 0) { - uint16_t type; - CBS extension; + /* RFC 5746 made the existence of extensions in SSL 3.0 somewhat + * ambiguous. Ignore all but the renegotiation_info extension. */ + if (ssl->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) { + continue; + } - /* Decode the next extension. */ - if (!CBS_get_u16(&extensions, &type) || - !CBS_get_u16_length_prefixed(&extensions, &extension)) { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + unsigned ext_index; + const struct tls_extension *const ext = + tls_extension_find(&ext_index, type); - /* RFC 5746 made the existence of extensions in SSL 3.0 somewhat - * ambiguous. Ignore all but the renegotiation_info extension. */ - if (ssl->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) { - continue; - } - - unsigned ext_index; - const struct tls_extension *const ext = - tls_extension_find(&ext_index, type); - - if (ext == NULL) { - if (!custom_ext_parse_clienthello(ssl, out_alert, type, &extension)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); - return 0; - } - continue; - } - - ssl->s3->tmp.extensions.received |= (1u << ext_index); - uint8_t alert = SSL_AD_DECODE_ERROR; - if (!ext->parse_clienthello(ssl, &alert, &extension)) { - *out_alert = alert; + if (ext == NULL) { + if (!custom_ext_parse_clienthello(ssl, out_alert, type, &extension)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); - ERR_add_error_dataf("extension: %u", (unsigned)type); return 0; } + continue; + } + + ssl->s3->tmp.extensions.received |= (1u << ext_index); + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!ext->parse_clienthello(ssl, &alert, &extension)) { + *out_alert = alert; + OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)type); + return 0; } } @@ -2594,9 +2585,10 @@ static int ssl_scan_clienthello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) { return 1; } -int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs) { +int ssl_parse_clienthello_tlsext( + SSL *ssl, const struct ssl_early_callback_ctx *client_hello) { int alert = -1; - if (ssl_scan_clienthello_tlsext(ssl, cbs, &alert) <= 0) { + if (ssl_scan_clienthello_tlsext(ssl, client_hello, &alert) <= 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return 0; } diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c index 1ece1048..96ceb793 100644 --- a/ssl/tls13_server.c +++ b/ssl/tls13_server.c @@ -105,36 +105,22 @@ static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) { return ssl_hs_error; } - struct ssl_early_callback_ctx early_ctx; - if (!ssl_early_callback_init(ssl, &early_ctx, ssl->init_msg, + struct ssl_early_callback_ctx client_hello; + if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } - CBS cbs, client_random, session_id, cipher_suites, compression_methods; - uint16_t client_wire_version; - CBS_init(&cbs, ssl->init_msg, ssl->init_num); - if (!CBS_get_u16(&cbs, &client_wire_version) || - !CBS_get_bytes(&cbs, &client_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&cbs, &session_id) || - CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } - - uint16_t min_version, max_version; - if (!ssl_get_version_range(ssl, &min_version, &max_version)) { - ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - return ssl_hs_error; - } - assert(ssl->s3->have_version); /* Load the client random. */ - memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); + if (client_hello.random_len != SSL3_RANDOM_SIZE) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len); SSL_set_session(ssl, NULL); if (!ssl_get_new_session(ssl, 1 /* server */)) { @@ -143,44 +129,27 @@ static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) { } if (ssl->ctx->dos_protection_cb != NULL && - ssl->ctx->dos_protection_cb(&early_ctx) == 0) { + ssl->ctx->dos_protection_cb(&client_hello) == 0) { /* Connection rejected for DOS reasons. */ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED); return ssl_hs_error; } - if (!CBS_get_u16_length_prefixed(&cbs, &cipher_suites) || - CBS_len(&cipher_suites) == 0 || - CBS_len(&cipher_suites) % 2 != 0 || - !CBS_get_u8_length_prefixed(&cbs, &compression_methods) || - CBS_len(&compression_methods) == 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } - /* TLS 1.3 requires the peer only advertise the null compression. */ - if (CBS_len(&compression_methods) != 1 || - CBS_data(&compression_methods)[0] != 0) { + if (client_hello.compression_methods_len != 1 || + client_hello.compression_methods[0] != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } /* TLS extensions. */ - if (!ssl_parse_clienthello_tlsext(ssl, &cbs)) { + if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); return ssl_hs_error; } - /* There should be nothing left over in the message. */ - if (CBS_len(&cbs) != 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); - ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } - /* Let cert callback update server certificates if required. * * TODO(davidben): Can this get run earlier? */ @@ -197,8 +166,14 @@ static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) { } } + uint16_t min_version, max_version; + if (!ssl_get_version_range(ssl, &min_version, &max_version)) { + ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return ssl_hs_error; + } + STACK_OF(SSL_CIPHER) *ciphers = - ssl_bytes_to_cipher_list(ssl, &cipher_suites, max_version); + ssl_parse_client_cipher_list(ssl, &client_hello, max_version); if (ciphers == NULL) { return ssl_hs_error; } @@ -232,7 +207,7 @@ static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) { /* Resolve ECDHE and incorporate it into the secret. */ int need_retry; - if (!resolve_ecdhe_secret(ssl, &need_retry, &early_ctx)) { + if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) { if (need_retry) { hs->state = state_send_hello_retry_request; return ssl_hs_ok; @@ -276,8 +251,8 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl, return ssl_hs_error; } - struct ssl_early_callback_ctx early_ctx; - if (!ssl_early_callback_init(ssl, &early_ctx, ssl->init_msg, + struct ssl_early_callback_ctx client_hello; + if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -285,7 +260,7 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl, } int need_retry; - if (!resolve_ecdhe_secret(ssl, &need_retry, &early_ctx)) { + if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) { if (need_retry) { /* Only send one HelloRetryRequest. */ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);