From e2cb423767cc39f187da28ef6f1facf31d5b76f8 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Wed, 23 Jun 2021 18:14:22 -0400 Subject: [PATCH] Deduplicate our three ServerHello parsers. We do this enough that it's worth extracting a common parser. And this gives a struct we can pass around. Note this moves the server extensions block parsing out of ssl_scan_serverhello_tlsext. I've also consolidated a few error conditions to tighten the code up a bit: the TLS 1.2 code distinguishes unknown from unadvertised cipher, while the TLS 1.3 code didn't. And seeing the wrong legacy version number in TLS 1.3 is really just a syntax error since it's not the version field anymore. (RFC8446 specifies the value.) Change-Id: Ia2f44ff9a3899b5a594569f1b258f2b487930496 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48908 Commit-Queue: David Benjamin Reviewed-by: Adam Langley --- ssl/extensions.cc | 16 ++--- ssl/handshake_client.cc | 147 +++++++++++++++++++------------------- ssl/internal.h | 17 ++++- ssl/test/runner/runner.go | 4 +- ssl/tls13_client.cc | 105 ++++++++++++--------------- 5 files changed, 141 insertions(+), 148 deletions(-) diff --git a/ssl/extensions.cc b/ssl/extensions.cc index 9af928cec..6fec44584 100644 --- a/ssl/extensions.cc +++ b/ssl/extensions.cc @@ -3716,18 +3716,10 @@ bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs, return true; } -static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs, +static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs, int *out_alert) { - SSL *const ssl = hs->ssl; - // Before TLS 1.3, ServerHello extensions blocks may be omitted if empty. - if (CBS_len(cbs) == 0 && ssl_protocol_version(ssl) < TLS1_3_VERSION) { - return true; - } - - // 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; + if (!tls1_check_duplicate_extensions(&extensions)) { *out_alert = SSL_AD_DECODE_ERROR; return false; } @@ -3849,7 +3841,7 @@ static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) { return true; } -bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs) { +bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs) { SSL *const ssl = hs->ssl; int alert = SSL_AD_DECODE_ERROR; if (!ssl_scan_serverhello_tlsext(hs, cbs, &alert)) { diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc index ba8f4b748..b5199baaf 100644 --- a/ssl/handshake_client.cc +++ b/ssl/handshake_client.cc @@ -354,42 +354,36 @@ bool ssl_add_client_hello(SSL_HANDSHAKE *hs) { return ssl->method->add_message(ssl, std::move(msg)); } -static bool parse_supported_versions(SSL_HANDSHAKE *hs, uint16_t *version, - const CBS *in) { - // If the outer version is not TLS 1.2, or there is no extensions block, use - // the outer version. - if (*version != TLS1_2_VERSION || CBS_len(in) == 0) { +static bool parse_server_version(const SSL_HANDSHAKE *hs, uint16_t *out_version, + uint8_t *out_alert, + const ParsedServerHello &server_hello) { + // If the outer version is not TLS 1.2, use it. + // TODO(davidben): This function doesn't quite match the RFC8446 formulation. + if (server_hello.legacy_version != TLS1_2_VERSION) { + *out_version = server_hello.legacy_version; return true; } - SSL *const ssl = hs->ssl; - CBS copy = *in, extensions; - if (!CBS_get_u16_length_prefixed(©, &extensions) || - CBS_len(©) != 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return false; - } - bool have_supported_versions; CBS supported_versions; const SSL_EXTENSION_TYPE ext_types[] = { - {TLSEXT_TYPE_supported_versions, &have_supported_versions, - &supported_versions}, + {TLSEXT_TYPE_supported_versions, &have_supported_versions, + &supported_versions}, }; - - uint8_t alert = SSL_AD_DECODE_ERROR; - if (!ssl_parse_extensions(&extensions, &alert, ext_types, + CBS extensions = server_hello.extensions; + if (!ssl_parse_extensions(&extensions, out_alert, ext_types, /*ignore_unknown=*/true)) { - ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return false; } - // Override the outer version with the extension, if present. - if (have_supported_versions && - (!CBS_get_u16(&supported_versions, version) || - CBS_len(&supported_versions) != 0)) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + if (!have_supported_versions) { + *out_version = server_hello.legacy_version; + return true; + } + + if (!CBS_get_u16(&supported_versions, out_version) || + CBS_len(&supported_versions) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; return false; } @@ -657,6 +651,37 @@ static enum ssl_hs_wait_t do_read_hello_verify_request(SSL_HANDSHAKE *hs) { return ssl_hs_flush; } +bool ssl_parse_server_hello(ParsedServerHello *out, uint8_t *out_alert, + const SSLMessage &msg) { + if (msg.type != SSL3_MT_SERVER_HELLO) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); + *out_alert = SSL_AD_UNEXPECTED_MESSAGE; + return false; + } + CBS body = msg.body; + if (!CBS_get_u16(&body, &out->legacy_version) || + !CBS_get_bytes(&body, &out->random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&body, &out->session_id) || + CBS_len(&out->session_id) > SSL3_SESSION_ID_SIZE || + !CBS_get_u16(&body, &out->cipher_suite) || + !CBS_get_u8(&body, &out->compression_method)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + *out_alert = SSL_AD_DECODE_ERROR; + return false; + } + // In TLS 1.2 and below, empty extensions blocks may be omitted. In TLS 1.3, + // ServerHellos always have extensions, so this can be applied generically. + CBS_init(&out->extensions, nullptr, 0); + if ((CBS_len(&body) != 0 && + !CBS_get_u16_length_prefixed(&body, &out->extensions)) || + CBS_len(&body) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + *out_alert = SSL_AD_DECODE_ERROR; + return false; + } + return true; +} + static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; SSLMessage msg; @@ -664,26 +689,12 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_read_server_hello; } - if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { - return ssl_hs_error; - } - - CBS server_hello = msg.body, server_random, session_id; - uint16_t server_version, cipher_suite; - uint8_t compression_method; - if (!CBS_get_u16(&server_hello, &server_version) || - !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&server_hello, &session_id) || - CBS_len(&session_id) > SSL3_SESSION_ID_SIZE || - !CBS_get_u16(&server_hello, &cipher_suite) || - !CBS_get_u8(&server_hello, &compression_method)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } - - // Use the supported_versions extension if applicable. - if (!parse_supported_versions(hs, &server_version, &server_hello)) { + ParsedServerHello server_hello; + uint16_t server_version; + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!ssl_parse_server_hello(&server_hello, &alert, msg) || + !parse_server_version(hs, &server_version, &alert, server_hello)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } @@ -737,7 +748,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { } // Copy over the server random. - OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random), + OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_hello.random), SSL3_RANDOM_SIZE); // Enforce the TLS 1.3 anti-downgrade feature. @@ -760,28 +771,26 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { } } - const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); - if (cipher == NULL) { - OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); - return ssl_hs_error; - } - hs->new_cipher = cipher; - // The cipher must be allowed in the selected version and enabled. + const SSL_CIPHER *cipher = SSL_get_cipher_by_value(server_hello.cipher_suite); uint32_t mask_a, mask_k; ssl_get_client_disabled(hs, &mask_a, &mask_k); - if ((cipher->algorithm_mkey & mask_k) || (cipher->algorithm_auth & mask_a) || + if (cipher == nullptr || + (cipher->algorithm_mkey & mask_k) || + (cipher->algorithm_auth & mask_a) || SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) || SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl) || - !sk_SSL_CIPHER_find(SSL_get_ciphers(ssl), NULL, cipher)) { + !sk_SSL_CIPHER_find(SSL_get_ciphers(ssl), nullptr, cipher)) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } + hs->new_cipher = cipher; + if (hs->session_id_len != 0 && - CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len)) { + CBS_mem_equal(&server_hello.session_id, hs->session_id, + hs->session_id_len)) { // Echoing the ClientHello session ID in TLS 1.2, whether from the session // or a synthetic one, indicates resumption. If there was no session (or if // the session was only offered in ECH ClientHelloInner), this was the @@ -799,7 +808,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } - if (ssl->session->cipher != cipher) { + if (ssl->session->cipher != hs->new_cipher) { OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; @@ -822,10 +831,11 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } // Note: session_id could be empty. - hs->new_session->session_id_length = CBS_len(&session_id); - OPENSSL_memcpy(hs->new_session->session_id, CBS_data(&session_id), - CBS_len(&session_id)); - hs->new_session->cipher = cipher; + hs->new_session->session_id_length = CBS_len(&server_hello.session_id); + OPENSSL_memcpy(hs->new_session->session_id, + CBS_data(&server_hello.session_id), + CBS_len(&server_hello.session_id)); + hs->new_session->cipher = hs->new_cipher; } // Now that the cipher is known, initialize the handshake hash and hash the @@ -845,26 +855,17 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { } // Only the NULL compression algorithm is supported. - if (compression_method != 0) { + if (server_hello.compression_method != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } - // TLS extensions - if (!ssl_parse_serverhello_tlsext(hs, &server_hello)) { + if (!ssl_parse_serverhello_tlsext(hs, &server_hello.extensions)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); return ssl_hs_error; } - // There should be nothing left over in the record. - if (CBS_len(&server_hello) != 0) { - // wrong packet length - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - return ssl_hs_error; - } - if (ssl->session != NULL && hs->extended_master_secret != ssl->session->extended_master_secret) { if (ssl->session->extended_master_secret) { diff --git a/ssl/internal.h b/ssl/internal.h index 7505e5dcd..0c91724b2 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -2163,6 +2163,21 @@ bool ssl_write_client_hello_without_extensions(const SSL_HANDSHAKE *hs, // flight. It returns true on success and false on error. bool ssl_add_client_hello(SSL_HANDSHAKE *hs); +struct ParsedServerHello { + uint16_t legacy_version = 0; + CBS random; + CBS session_id; + uint16_t cipher_suite = 0; + uint8_t compression_method = 0; + CBS extensions; +}; + +// ssl_parse_server_hello parses |msg| as a ServerHello. On success, it writes +// the result to |*out| and returns true. Otherwise, it returns false and sets +// |*out_alert| to an alert to send to the peer. +bool ssl_parse_server_hello(ParsedServerHello *out, uint8_t *out_alert, + const SSLMessage &msg); + enum ssl_cert_verify_context_t { ssl_cert_verify_server, ssl_cert_verify_client, @@ -3304,7 +3319,7 @@ bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded, bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out); bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs, const SSL_CLIENT_HELLO *client_hello); -bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs); +bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *extensions); #define tlsext_tick_md EVP_sha256 diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 03dcbf150..1953b885b 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -3833,7 +3833,7 @@ func addCipherSuiteTests() { }, }, shouldFail: true, - expectedError: ":UNKNOWN_CIPHER_RETURNED:", + expectedError: ":WRONG_CIPHER_RETURNED:", }) testCases = append(testCases, testCase{ name: "ServerHelloBogusCipher-TLS13", @@ -13884,7 +13884,7 @@ func addTLS13HandshakeTests() { }, }, shouldFail: true, - expectedError: ":WRONG_VERSION_NUMBER:", + expectedError: ":DECODE_ERROR:", }) testCases = append(testCases, testCase{ diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc index bc137aa72..7a19b2abe 100644 --- a/ssl/tls13_client.cc +++ b/ssl/tls13_client.cc @@ -101,6 +101,25 @@ static bool close_early_data(SSL_HANDSHAKE *hs, ssl_encryption_level_t level) { return true; } +static bool parse_server_hello_tls13(const SSL_HANDSHAKE *hs, + ParsedServerHello *out, uint8_t *out_alert, + const SSLMessage &msg) { + if (!ssl_parse_server_hello(out, out_alert, msg)) { + return false; + } + // The RFC8446 version of the structure fixes some legacy values. + // Additionally, the session ID must echo the original one. + if (out->legacy_version != TLS1_2_VERSION || + out->compression_method != 0 || + !CBS_mem_equal(&out->session_id, hs->session_id, hs->session_id_len) || + CBS_len(&out->extensions) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + *out_alert = SSL_AD_DECODE_ERROR; + return false; + } + return true; +} + static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; assert(ssl->s3->have_version); @@ -117,32 +136,17 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { - return ssl_hs_error; - } - - CBS body = msg.body, extensions, server_random, session_id; - uint16_t server_version, cipher_suite; - uint8_t compression_method; - if (!CBS_get_u16(&body, &server_version) || - !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&body, &session_id) || - !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) || - !CBS_get_u16(&body, &cipher_suite) || - !CBS_get_u8(&body, &compression_method) || - compression_method != 0 || - !CBS_get_u16_length_prefixed(&body, &extensions) || - CBS_len(&extensions) == 0 || - CBS_len(&body) != 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + ParsedServerHello server_hello; + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!parse_server_hello_tls13(hs, &server_hello, &alert, msg)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } // The cipher suite must be one we offered. We currently offer all supported // TLS 1.3 ciphers, so check the version. - const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); - if (cipher == NULL || + const SSL_CIPHER *cipher = SSL_get_cipher_by_value(server_hello.cipher_suite); + if (cipher == nullptr || SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) || SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); @@ -152,7 +156,8 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) { hs->new_cipher = cipher; - if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { + if (!CBS_mem_equal(&server_hello.random, kHelloRetryRequest, + SSL3_RANDOM_SIZE)) { hs->tls13_state = state_read_server_hello; return ssl_hs_ok; } @@ -166,8 +171,7 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) { &supported_versions}, }; - uint8_t alert = SSL_AD_DECODE_ERROR; - if (!ssl_parse_extensions(&extensions, &alert, ext_types, + if (!ssl_parse_extensions(&server_hello.extensions, &alert, ext_types, /*ignore_unknown=*/false)) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; @@ -287,49 +291,29 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { if (!ssl->method->get_message(ssl, &msg)) { return ssl_hs_read_message; } - if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { - return ssl_hs_error; - } - - CBS body = msg.body, server_random, session_id, extensions; - uint16_t server_version; - uint16_t cipher_suite; - uint8_t compression_method; - if (!CBS_get_u16(&body, &server_version) || - !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&body, &session_id) || - !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) || - !CBS_get_u16(&body, &cipher_suite) || - !CBS_get_u8(&body, &compression_method) || - compression_method != 0 || - !CBS_get_u16_length_prefixed(&body, &extensions) || - CBS_len(&body) != 0) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); - return ssl_hs_error; - } - - if (server_version != TLS1_2_VERSION) { - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); + ParsedServerHello server_hello; + uint8_t alert = SSL_AD_DECODE_ERROR; + if (!parse_server_hello_tls13(hs, &server_hello, &alert, msg)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } // Forbid a second HelloRetryRequest. - if (CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { + if (CBS_mem_equal(&server_hello.random, kHelloRetryRequest, + SSL3_RANDOM_SIZE)) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); return ssl_hs_error; } // Check the cipher suite, in case this is after HelloRetryRequest. - if (SSL_CIPHER_get_value(hs->new_cipher) != cipher_suite) { + if (SSL_CIPHER_get_value(hs->new_cipher) != server_hello.cipher_suite) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } - OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random), + OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_hello.random), SSL3_RANDOM_SIZE); // Parse out the extensions. @@ -343,8 +327,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { &supported_versions}, }; - uint8_t alert = SSL_AD_DECODE_ERROR; - if (!ssl_parse_extensions(&extensions, &alert, ext_types, + if (!ssl_parse_extensions(&server_hello.extensions, &alert, ext_types, /*ignore_unknown=*/false)) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; @@ -521,17 +504,19 @@ static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - CBS body = msg.body; - if (!ssl_parse_serverhello_tlsext(hs, &body)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); - return ssl_hs_error; - } - if (CBS_len(&body) != 0) { + CBS body = msg.body, extensions; + if (!CBS_get_u16_length_prefixed(&body, &extensions) || + CBS_len(&body) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } + if (!ssl_parse_serverhello_tlsext(hs, &extensions)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); + return ssl_hs_error; + } + if (ssl->s3->early_data_accepted) { // The extension parser checks the server resumed the session. assert(ssl->s3->session_reused);