X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=ssl%2Ft1_lib.c;h=74022eeb2e6fa31e0cb097cee8989447dd0cd83d;hb=beacb0f0c1ae7b0542fe053b95307f515b578eb7;hp=46ca29099e6e6c9c71e89ef7d574005bf5fa3dd0;hpb=0f1e51ea115beef8a5fdd80d5a6c13ee289f980a;p=oweals%2Fopenssl.git diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 46ca29099e..74022eeb2e 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1048,7 +1048,7 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) break; } } - } else if (s->version >= TLS1_3_VERSION) { + } else if (SSL_IS_TLS13(s)) { /* * TODO(TLS1.3): We always use ECC for TLSv1.3 at the moment. This will * change if we implement DH key shares @@ -1056,7 +1056,7 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) using_ecc = 1; } #else - if (s->version >= TLS1_3_VERSION) { + if (SSL_IS_TLS13(s)) { /* Shouldn't happen! */ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return 0; @@ -1423,57 +1423,57 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) * now, just send one */ for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) { - if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) { - unsigned char *encodedPoint = NULL; - unsigned int curve_id = 0; - EVP_PKEY *key_share_key = NULL; - size_t encodedlen; - - if (s->s3->tmp.pkey != NULL) { - /* Shouldn't happen! */ - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, - ERR_R_INTERNAL_ERROR); - return 0; - } - - /* Generate a key for this key_share */ - curve_id = (pcurves[0] << 8) | pcurves[1]; - key_share_key = ssl_generate_pkey_curve(curve_id); - if (key_share_key == NULL) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB); - return 0; - } + unsigned char *encodedPoint = NULL; + unsigned int curve_id = 0; + EVP_PKEY *key_share_key = NULL; + size_t encodedlen; + + if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) + continue; + + if (s->s3->tmp.pkey != NULL) { + /* Shouldn't happen! */ + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, + ERR_R_INTERNAL_ERROR); + return 0; + } - /* Encode the public key. */ - encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key, - &encodedPoint); - if (encodedlen == 0) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EC_LIB); - EVP_PKEY_free(key_share_key); - return 0; - } + /* Generate a key for this key_share */ + curve_id = (pcurves[0] << 8) | pcurves[1]; + key_share_key = ssl_generate_pkey_curve(curve_id); + if (key_share_key == NULL) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB); + return 0; + } - /* Create KeyShareEntry */ - if (!WPACKET_put_bytes_u16(pkt, curve_id) - || !WPACKET_sub_memcpy_u16(pkt, encodedPoint, - encodedlen)) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, - ERR_R_INTERNAL_ERROR); - EVP_PKEY_free(key_share_key); - OPENSSL_free(encodedPoint); - return 0; - } + /* Encode the public key. */ + encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key, + &encodedPoint); + if (encodedlen == 0) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_EC_LIB); + EVP_PKEY_free(key_share_key); + return 0; + } - /* - * TODO(TLS1.3): When changing to send more than one key_share - * we're going to need to be able to save more than one EVP_PKEY - * For now we reuse the existing tmp.pkey - */ - s->s3->group_id = curve_id; - s->s3->tmp.pkey = key_share_key; - sharessent++; + /* Create KeyShareEntry */ + if (!WPACKET_put_bytes_u16(pkt, curve_id) + || !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, + ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(key_share_key); OPENSSL_free(encodedPoint); + return 0; } + + /* + * TODO(TLS1.3): When changing to send more than one key_share we're + * going to need to be able to save more than one EVP_PKEY. For now + * we reuse the existing tmp.pkey + */ + s->s3->group_id = curve_id; + s->s3->tmp.pkey = key_share_key; + sharessent++; + OPENSSL_free(encodedPoint); } if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); @@ -1516,6 +1516,59 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) return 1; } +/* + * Add the key_share extension. + * + * Returns 1 on success or 0 on failure. + */ +static int add_client_key_share_ext(SSL *s, WPACKET *pkt, int *al) +{ + unsigned char *encodedPoint; + size_t encoded_pt_len = 0; + EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL; + + if (ckey == NULL) { + SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) { + SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + skey = ssl_generate_pkey(ckey); + + /* Generate encoding of server key */ + encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint); + if (encoded_pt_len == 0) { + SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_EC_LIB); + EVP_PKEY_free(skey); + return 0; + } + + if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len) + || !WPACKET_close(pkt)) { + SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(skey); + OPENSSL_free(encodedPoint); + return 0; + } + OPENSSL_free(encodedPoint); + + /* This causes the crypto state to be updated based on the derived keys */ + s->s3->tmp.pkey = skey; + if (ssl_derive(s, skey, ckey, 1) == 0) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_ADD_CLIENT_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al) { #ifndef OPENSSL_NO_NEXTPROTONEG @@ -1649,51 +1702,8 @@ int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al) } #endif - if (s->version == TLS1_3_VERSION) { - unsigned char *encodedPoint; - size_t encoded_pt_len = 0; - EVP_PKEY *ckey = NULL, *skey = NULL; - - ckey = s->s3->peer_tmp; - if (ckey == NULL) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return 0; - } - - skey = ssl_generate_pkey(ckey); - - /* Generate encoding of server key */ - encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint); - if (encoded_pt_len == 0) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_EC_LIB); - EVP_PKEY_free(skey); - return 0; - } - - if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len) - || !WPACKET_close(pkt)) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - EVP_PKEY_free(skey); - OPENSSL_free(encodedPoint); - return 0; - } - OPENSSL_free(encodedPoint); - - s->s3->tmp.pkey = skey; - - if (ssl_derive(s, skey, ckey, 1) == 0) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return 0; - } - } + if (SSL_IS_TLS13(s) && !s->hit && !add_client_key_share_ext(s, pkt, al)) + return 0; if (!custom_ext_add(s, 1, pkt, al)) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); @@ -1885,6 +1895,198 @@ static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello) } #endif /* !OPENSSL_NO_EC */ + +/* + * Process the supported_groups extension if present. Returns success if the + * extension is absent, or if it has been successfully processed. + * + * Returns 1 on success or 0 on failure + */ +static int tls_process_supported_groups(SSL *s, CLIENTHELLO_MSG *hello) +{ +#ifndef OPENSSL_NO_EC + PACKET supported_groups_list; + RAW_EXTENSION *suppgroups = tls_get_extension_by_type(hello->pre_proc_exts, + hello->num_extensions, + TLSEXT_TYPE_supported_groups); + + if (suppgroups == NULL) + return 1; + + /* Each group is 2 bytes and we must have at least 1. */ + if (!PACKET_as_length_prefixed_2(&suppgroups->data, + &supported_groups_list) + || PACKET_remaining(&supported_groups_list) == 0 + || (PACKET_remaining(&supported_groups_list) % 2) != 0) { + return 0; + } + + if (!s->hit + && !PACKET_memdup(&supported_groups_list, + &s->session->tlsext_supportedgroupslist, + &s->session->tlsext_supportedgroupslist_length)) { + return 0; + } +#endif + return 1; +} + +/* + * Checks a list of |groups| to determine if the |group_id| is in it. If it is + * and |checkallow| is 1 then additionally check if the group is allowed to be + * used. Returns 1 if the group is in the list (and allowed if |checkallow| is + * 1) or 0 otherwise. + */ +static int check_in_list(SSL *s, unsigned int group_id, + const unsigned char *groups, size_t num_groups, + int checkallow) +{ + size_t i; + + if (groups == NULL || num_groups == 0) + return 0; + + for (i = 0; i < num_groups; i++, groups += 2) { + unsigned int share_id = (groups[0] << 8) | (groups[1]); + + if (group_id == share_id + && (!checkallow || tls_curve_allowed(s, groups, + SSL_SECOP_CURVE_CHECK))) { + break; + } + } + + /* If i == num_groups then not in the list */ + return i < num_groups; +} + +/* + * Process a key_share extension received in the ClientHello. |pkt| contains + * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. + * If a failure occurs then |*al| is set to an appropriate alert value. + */ +static int process_key_share_ext(SSL *s, PACKET *pkt, int *al) +{ + unsigned int group_id; + PACKET key_share_list, encoded_pt; + const unsigned char *clntcurves, *srvrcurves; + size_t clnt_num_curves, srvr_num_curves; + int group_nid, found = 0; + unsigned int curve_flags; + + /* Sanity check */ + if (s->s3->peer_tmp != NULL) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* Get our list of supported curves */ + if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, + ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Get the clients list of supported curves */ + if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, + ERR_R_INTERNAL_ERROR); + return 0; + } + + while (PACKET_remaining(&key_share_list) > 0) { + if (!PACKET_get_net_2(&key_share_list, &group_id) + || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) + || PACKET_remaining(&encoded_pt) == 0) { + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + /* + * If we already found a suitable key_share we loop through the + * rest to verify the structure, but don't process them. + */ + if (found) + continue; + + /* Check if this share is in supported_groups sent from client */ + if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) { + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, + SSL_R_BAD_KEY_SHARE); + return 0; + } + + /* Check if this share is for a group we can use */ + if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) { + /* Share not suitable */ + continue; + } + + group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags); + + if (group_nid == 0) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, + SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + return 0; + } + + if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { + /* Can happen for some curves, e.g. X25519 */ + EVP_PKEY *key = EVP_PKEY_new(); + + if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, ERR_R_EVP_LIB); + EVP_PKEY_free(key); + return 0; + } + s->s3->peer_tmp = key; + } else { + /* Set up EVP_PKEY with named curve as parameters */ + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (pctx == NULL + || EVP_PKEY_paramgen_init(pctx) <= 0 + || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, + group_nid) <= 0 + || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, ERR_R_EVP_LIB); + EVP_PKEY_CTX_free(pctx); + return 0; + } + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + } + s->s3->group_id = group_id; + + if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, + PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + *al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_PROCESS_KEY_SHARE_EXT, SSL_R_BAD_ECPOINT); + return 0; + } + + found = 1; + } + + return 1; +} + /* * Loop through all remaining ClientHello extensions that we collected earlier * and haven't already processed. For each one parse it and update the SSL @@ -1933,6 +2135,15 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) s->srtp_profile = NULL; + /* + * We process the supported_groups extension first so that is done before + * we get to key_share which needs to use the information in it. + */ + if (!tls_process_supported_groups(s, hello)) { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } + /* * We parse all extensions to ensure the ClientHello is well-formed but, * unless an extension specifies otherwise, we ignore extensions upon @@ -2074,26 +2285,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) return 0; } } - } else if (currext->type == TLSEXT_TYPE_supported_groups) { - PACKET supported_groups_list; - - /* Each group is 2 bytes and we must have at least 1. */ - if (!PACKET_as_length_prefixed_2(&currext->data, - &supported_groups_list) - || PACKET_remaining(&supported_groups_list) == 0 - || (PACKET_remaining(&supported_groups_list) % 2) != 0) { - return 0; - } - - if (!s->hit) { - if (!PACKET_memdup(&supported_groups_list, - &s->session->tlsext_supportedgroupslist, - &s-> - session->tlsext_supportedgroupslist_length)) { - *al = TLS1_AD_INTERNAL_ERROR; - return 0; - } - } } #endif /* OPENSSL_NO_EC */ else if (currext->type == TLSEXT_TYPE_session_ticket) { @@ -2251,105 +2442,9 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) && !(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) { s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; } else if (currext->type == TLSEXT_TYPE_key_share - && s->version == TLS1_3_VERSION) { - unsigned int group_id; - PACKET key_share_list, encoded_pt; - const unsigned char *curves; - size_t num_curves, i; - int group_nid; - unsigned int curve_flags; - - /* Sanity check */ - if (s->s3->peer_tmp != NULL) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!PACKET_as_length_prefixed_2(&currext->data, &key_share_list)) { - *al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, - SSL_R_LENGTH_MISMATCH); - return 0; - } - - while (PACKET_remaining(&key_share_list) > 0) { - if (!PACKET_get_net_2(&key_share_list, &group_id) - || !PACKET_get_length_prefixed_2(&key_share_list, - &encoded_pt)) { - *al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, - SSL_R_LENGTH_MISMATCH); - return 0; - } - - /* Find a share that we can use */ - if (!tls1_get_curvelist(s, 0, &curves, &num_curves)) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, - ERR_R_INTERNAL_ERROR); - return 0; - } - for (i = 0; i < num_curves; i++, curves += 2) { - unsigned int share_id = (curves[0] << 8) | (curves[1]); - if (group_id == share_id - && tls_curve_allowed(s, curves, - SSL_SECOP_CURVE_CHECK)) { - break; - } - } - - if (i == num_curves) { - /* Share not suitable */ - continue; - } - - group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags); - - if (group_nid == 0) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, - SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); - return 0; - } - - if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { - /* Can happen for some curves, e.g. X25519 */ - EVP_PKEY *key = EVP_PKEY_new(); - - if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB); - EVP_PKEY_free(key); - return 0; - } - s->s3->peer_tmp = key; - } else { - /* Set up EVP_PKEY with named curve as parameters */ - EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); - if (pctx == NULL - || EVP_PKEY_paramgen_init(pctx) <= 0 - || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, - group_nid) <= 0 - || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { - *al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, ERR_R_EVP_LIB); - EVP_PKEY_CTX_free(pctx); - return 0; - } - EVP_PKEY_CTX_free(pctx); - pctx = NULL; - } - s->s3->group_id = group_id; - - if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, - PACKET_data(&encoded_pt), - PACKET_remaining(&encoded_pt))) { - *al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, SSL_R_BAD_ECPOINT); - return 0; - } - } + && SSL_IS_TLS13(s) && !s->hit + && !process_key_share_ext(s, &currext->data, al)) { + return 0; } /* * Note: extended master secret extension handled in @@ -2640,12 +2735,12 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4) s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; } else if (type == TLSEXT_TYPE_extended_master_secret && - (SSL_IS_DTLS(s) || s->version < TLS1_3_VERSION)) { + (SSL_IS_DTLS(s) || !SSL_IS_TLS13(s))) { s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; if (!s->hit) s->session->flags |= SSL_SESS_FLAG_EXTMS; } else if (type == TLSEXT_TYPE_key_share - && s->version == TLS1_3_VERSION) { + && SSL_IS_TLS13(s)) { unsigned int group_id; PACKET encoded_pt; EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL; @@ -2675,15 +2770,15 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) return 0; } - skey = ssl_generate_pkey(ckey); - - if (!PACKET_as_length_prefixed_2(&spkt, &encoded_pt)) { + if (!PACKET_as_length_prefixed_2(&spkt, &encoded_pt) + || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_LENGTH_MISMATCH); return 0; } + skey = ssl_generate_pkey(ckey); if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_DECODE_ERROR;