X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=044c403ebf77cea01eebfa297bda01d191d854ce;hp=1c2ee52328ebf8a562e54366cdd72e76b95d402a;hb=ef7daaf915d7e0b7b48027f9ac4d47493adef0bb;hpb=6438632420cee9821409221ef6717edc5ee408c1 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 1c2ee52328..044c403ebf 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -268,8 +268,8 @@ static int tls1_get_curvelist(SSL *s, int sess, { size_t pcurveslen = 0; if (sess) { - *pcurves = s->session->tlsext_ellipticcurvelist; - pcurveslen = s->session->tlsext_ellipticcurvelist_length; + *pcurves = s->session->tlsext_supportedgroupslist; + pcurveslen = s->session->tlsext_supportedgroupslist_length; } else { /* For Suite B mode only include P-256, P-384 */ switch (tls1_suiteb(s)) { @@ -288,8 +288,8 @@ static int tls1_get_curvelist(SSL *s, int sess, pcurveslen = 2; break; default: - *pcurves = s->tlsext_ellipticcurvelist; - pcurveslen = s->tlsext_ellipticcurvelist_length; + *pcurves = s->tlsext_supportedgroupslist; + pcurveslen = s->tlsext_supportedgroupslist_length; } if (!*pcurves) { *pcurves = eccurves_default; @@ -356,13 +356,13 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) } /*- - * For nmatch >= 0, return the NID of the |nmatch|th shared curve or NID_undef + * For nmatch >= 0, return the NID of the |nmatch|th shared group or NID_undef * if there is no match. * For nmatch == -1, return number of matches - * For nmatch == -2, return the NID of the curve to use for + * For nmatch == -2, return the NID of the group to use for * an EC tmp key, or NID_undef if there is no match. */ -int tls1_shared_curve(SSL *s, int nmatch) +int tls1_shared_group(SSL *s, int nmatch) { const unsigned char *pref, *supp; size_t num_pref, num_supp, i, j; @@ -434,34 +434,35 @@ int tls1_shared_curve(SSL *s, int nmatch) return NID_undef; } -int tls1_set_curves(unsigned char **pext, size_t *pextlen, - int *curves, size_t ncurves) +int tls1_set_groups(unsigned char **pext, size_t *pextlen, + int *groups, size_t ngroups) { - unsigned char *clist, *p; + unsigned char *glist, *p; size_t i; /* - * Bitmap of curves included to detect duplicates: only works while curve + * Bitmap of groups included to detect duplicates: only works while group * ids < 32 */ unsigned long dup_list = 0; - clist = OPENSSL_malloc(ncurves * 2); - if (clist == NULL) + glist = OPENSSL_malloc(ngroups * 2); + if (glist == NULL) return 0; - for (i = 0, p = clist; i < ncurves; i++) { + for (i = 0, p = glist; i < ngroups; i++) { unsigned long idmask; int id; - id = tls1_ec_nid2curve_id(curves[i]); + /* TODO(TLS1.3): Convert for DH groups */ + id = tls1_ec_nid2curve_id(groups[i]); idmask = 1L << id; if (!id || (dup_list & idmask)) { - OPENSSL_free(clist); + OPENSSL_free(glist); return 0; } dup_list |= idmask; s2n(id, p); } OPENSSL_free(*pext); - *pext = clist; - *pextlen = ncurves * 2; + *pext = glist; + *pextlen = ngroups * 2; return 1; } @@ -500,8 +501,8 @@ static int nid_cb(const char *elem, int len, void *arg) return 1; } -/* Set curves based on a colon separate list */ -int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, const char *str) +/* Set groups based on a colon separate list */ +int tls1_set_groups_list(unsigned char **pext, size_t *pextlen, const char *str) { nid_cb_st ncb; ncb.nidcnt = 0; @@ -509,7 +510,7 @@ int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, const char *str) return 0; if (pext == NULL) return 1; - return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt); + return tls1_set_groups(pext, pextlen, ncb.nid_arr, ncb.nidcnt); } /* For an EC key set TLS id and required compression based on parameters */ @@ -706,7 +707,7 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid) return 1; } /* Need a shared curve */ - if (tls1_shared_curve(s, 0)) + if (tls1_shared_group(s, 0)) return 1; return 0; } @@ -1025,9 +1026,13 @@ static int tls1_check_duplicate_extensions(const PACKET *packet) int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) { #ifndef OPENSSL_NO_EC - /* See if we support any ECC ciphersuites */ + const unsigned char *pcurves = NULL; + size_t num_curves = 0; int using_ecc = 0; - if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) { + + /* See if we support any ECC ciphersuites */ + if ((s->version >= TLS1_VERSION && s->version <= TLS1_2_VERSION) + || SSL_IS_DTLS(s)) { int i; unsigned long alg_k, alg_a; STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); @@ -1043,6 +1048,18 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) break; } } + } else if (s->version >= TLS1_3_VERSION) { + /* + * TODO(TLS1.3): We always use ECC for TLSv1.3 at the moment. This will + * change if we implement DH key shares + */ + using_ecc = 1; + } +#else + if (s->version >= TLS1_3_VERSION) { + /* Shouldn't happen! */ + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return 0; } #endif @@ -1101,8 +1118,8 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) /* * Add TLS extension ECPointFormats to the ClientHello message */ - const unsigned char *pcurves, *pformats; - size_t num_curves, num_formats; + const unsigned char *pformats, *pcurvestmp; + size_t num_formats; size_t i; tls1_get_formatlist(s, &pformats, &num_formats); @@ -1117,26 +1134,28 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) } /* - * Add TLS extension EllipticCurves to the ClientHello message + * Add TLS extension supported_groups to the ClientHello message */ - pcurves = s->tlsext_ellipticcurvelist; + /* TODO(TLS1.3): Add support for DHE groups */ + pcurves = s->tlsext_supportedgroupslist; if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return 0; } + pcurvestmp = pcurves; - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_elliptic_curves) - /* Sub-packet for curves extension */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) + /* Sub-packet for supported_groups extension */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u16(pkt)) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return 0; } /* Copy curve ID if supported */ - for (i = 0; i < num_curves; i++, pcurves += 2) { + for (i = 0; i < num_curves; i++, pcurvestmp += 2) { if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) { - if (!WPACKET_put_bytes_u8(pkt, pcurves[0]) - || !WPACKET_put_bytes_u8(pkt, pcurves[1])) { + if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0]) + || !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return 0; @@ -1252,30 +1271,6 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) } } #endif -#ifndef OPENSSL_NO_HEARTBEATS - if (SSL_IS_DTLS(s)) { - unsigned int mode; - - /*- - * Set mode: - * 1: peer may send requests - * 2: peer not allowed to send requests - */ - if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS) - mode = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; - else - mode = SSL_DTLSEXT_HB_ENABLED; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_heartbeat) - /* Sub-packet for Hearbeat extension */ - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u8(pkt, mode) - || !WPACKET_close(pkt)) { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return 0; - } - } -#endif #ifndef OPENSSL_NO_NEXTPROTONEG if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) { @@ -1371,6 +1366,121 @@ int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al) return 0; } + /* TLS1.3 specific extensions */ + if (SSL_IS_TLS13(s)) { + int min_version, max_version, reason, currv; + size_t i, sharessent = 0; + + /* TODO(TLS1.3): Should we add this extension for versions < TLS1.3? */ + /* supported_versions extension */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_start_sub_packet_u8(pkt)) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return 0; + } + reason = ssl_get_client_min_max_version(s, &min_version, &max_version); + if (reason != 0) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, reason); + return 0; + } + /* + * TODO(TLS1.3): There is some discussion on the TLS list as to wheter + * we should include versions = min_version; currv--) { + /* TODO(TLS1.3): Remove this first if clause prior to release!! */ + if (currv == TLS1_3_VERSION) { + if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, + ERR_R_INTERNAL_ERROR); + return 0; + } + } else if (!WPACKET_put_bytes_u16(pkt, currv)) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return 0; + } + } + if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + + /* key_share extension */ + if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) + /* Extension data sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt) + /* KeyShare list sub-packet */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * TODO(TLS1.3): Make the number of key_shares sent configurable. For + * 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; + } + + /* 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; + } + + /* 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); + return 0; + } + } + /* * Add padding to workaround bugs in F5 terminators. See * https://tools.ietf.org/html/draft-agl-tls-padding-03 NB: because this @@ -1516,30 +1626,6 @@ int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al) return 0; } } -#ifndef OPENSSL_NO_HEARTBEATS - /* Add Heartbeat extension if we've received one */ - if (SSL_IS_DTLS(s) && (s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED)) { - unsigned int mode; - /*- - * Set mode: - * 1: peer may send requests - * 2: peer not allowed to send requests - */ - if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS) - mode = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; - else - mode = SSL_DTLSEXT_HB_ENABLED; - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_heartbeat) - || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u8(pkt, mode) - || !WPACKET_close(pkt)) { - SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return 0; - } - - } -#endif #ifndef OPENSSL_NO_NEXTPROTONEG next_proto_neg_seen = s->s3->next_proto_neg_seen; @@ -1562,6 +1648,53 @@ int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al) } } #endif + + if (s->version == TLS1_3_VERSION && !s->hit) { + 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 (!custom_ext_add(s, 1, pkt, al)) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return 0; @@ -1690,7 +1823,7 @@ static int tls1_alpn_handle_client_hello_late(SSL *s, int *al) #ifndef OPENSSL_NO_EC /*- * ssl_check_for_safari attempts to fingerprint Safari using OS X - * SecureTransport using the TLS extension block in |pkt|. + * SecureTransport using the TLS extension block in |hello|. * Safari, since 10.6, sends exactly these extensions, in this order: * SNI, * elliptic_curves @@ -1701,7 +1834,7 @@ static int tls1_alpn_handle_client_hello_late(SSL *s, int *al) * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from * 10.8..10.8.3 (which don't work). */ -static void ssl_check_for_safari(SSL *s, CLIENTHELLO_MSG *hello) +static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello) { unsigned int type; PACKET sni, tmppkt; @@ -1752,6 +1885,79 @@ static void ssl_check_for_safari(SSL *s, 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 + * 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) + * 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) { + /* Not in list */ + return 0; + } + + 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 @@ -1782,10 +1988,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) OPENSSL_free(s->s3->alpn_proposed); s->s3->alpn_proposed = NULL; s->s3->alpn_proposed_len = 0; -#ifndef OPENSSL_NO_HEARTBEATS - s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED | - SSL_DTLSEXT_HB_DONT_SEND_REQUESTS); -#endif #ifndef OPENSSL_NO_EC if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) @@ -1804,6 +2006,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 @@ -1945,26 +2156,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) return 0; } } - } else if (currext->type == TLSEXT_TYPE_elliptic_curves) { - PACKET elliptic_curve_list; - - /* Each NamedCurve is 2 bytes and we must have at least 1. */ - if (!PACKET_as_length_prefixed_2(&currext->data, - &elliptic_curve_list) - || PACKET_remaining(&elliptic_curve_list) == 0 - || (PACKET_remaining(&elliptic_curve_list) % 2) != 0) { - return 0; - } - - if (!s->hit) { - if (!PACKET_memdup(&elliptic_curve_list, - &s->session->tlsext_ellipticcurvelist, - &s-> - session->tlsext_ellipticcurvelist_length)) { - *al = TLS1_AD_INTERNAL_ERROR; - return 0; - } - } } #endif /* OPENSSL_NO_EC */ else if (currext->type == TLSEXT_TYPE_session_ticket) { @@ -2077,29 +2268,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) s->tlsext_status_type = -1; } } -#ifndef OPENSSL_NO_HEARTBEATS - else if (SSL_IS_DTLS(s) && currext->type == TLSEXT_TYPE_heartbeat) { - unsigned int hbtype; - - if (!PACKET_get_1(&currext->data, &hbtype) - || PACKET_remaining(&currext->data)) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } - switch (hbtype) { - case 0x01: /* Client allows us to send HB requests */ - s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; - break; - case 0x02: /* Client doesn't accept HB requests */ - s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; - s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; - break; - default: - *al = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - } -#endif #ifndef OPENSSL_NO_NEXTPROTONEG else if (currext->type == TLSEXT_TYPE_next_proto_neg && s->s3->tmp.finish_md_len == 0) { @@ -2142,8 +2310,114 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CLIENTHELLO_MSG *hello, int *al) } #endif else if (currext->type == TLSEXT_TYPE_encrypt_then_mac - && !(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)) + && !(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 && !s->hit) { + unsigned int group_id; + PACKET key_share_list, encoded_pt; + const unsigned char *curves; + size_t num_curves; + 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; + } + + /* Check this share is in supported_groups */ + if (!tls1_get_curvelist(s, 1, &curves, &num_curves)) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, + ERR_R_INTERNAL_ERROR); + return 0; + } + if (!check_in_list(s, group_id, curves, num_curves, 0)) { + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, + SSL_R_BAD_KEY_SHARE); + 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; + } + if (!check_in_list(s, group_id, curves, 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_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; + } + } + } /* * Note: extended master secret extension handled in * tls_check_client_ems_support() @@ -2231,10 +2505,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) OPENSSL_free(s->s3->alpn_selected); s->s3->alpn_selected = NULL; -#ifndef OPENSSL_NO_HEARTBEATS - s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED | - SSL_DTLSEXT_HB_DONT_SEND_REQUESTS); -#endif s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; @@ -2424,27 +2694,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) } s->s3->alpn_selected_len = len; } -#ifndef OPENSSL_NO_HEARTBEATS - else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_heartbeat) { - unsigned int hbtype; - if (!PACKET_get_1(&spkt, &hbtype)) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } - switch (hbtype) { - case 0x01: /* Server allows us to send HB requests */ - s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; - break; - case 0x02: /* Server doesn't accept HB requests */ - s->tlsext_heartbeat |= SSL_DTLSEXT_HB_ENABLED; - s->tlsext_heartbeat |= SSL_DTLSEXT_HB_DONT_SEND_REQUESTS; - break; - default: - *al = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - } -#endif #ifndef OPENSSL_NO_SRTP else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) { if (ssl_parse_serverhello_use_srtp_ext(s, &spkt, al)) @@ -2457,16 +2706,70 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD && 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) { + } else if (type == TLSEXT_TYPE_extended_master_secret && + (SSL_IS_DTLS(s) || s->version < TLS1_3_VERSION)) { 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) { + unsigned int group_id; + PACKET encoded_pt; + EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL; + + /* Sanity check */ + if (ckey == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!PACKET_get_net_2(&spkt, &group_id)) { + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (group_id != s->s3->group_id) { + /* + * This isn't for the group that we sent in the original + * key_share! + */ + *al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, + SSL_R_BAD_KEY_SHARE); + return 0; + } + + skey = ssl_generate_pkey(ckey); + + if (!PACKET_as_length_prefixed_2(&spkt, &encoded_pt)) { + *al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, + SSL_R_LENGTH_MISMATCH); + return 0; + } + + if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt), + PACKET_remaining(&encoded_pt))) { + *al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_BAD_ECPOINT); + return 0; + } + + if (ssl_derive(s, ckey, skey, 1) == 0) { + *al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + EVP_PKEY_free(skey); + return 0; + } + EVP_PKEY_free(skey); /* * If this extension type was not otherwise handled, but matches a * custom_cli_ext_record, then send it to the c callback */ - else if (custom_ext_parse(s, 0, type, data, size, al) <= 0) + } else if (custom_ext_parse(s, 0, type, data, size, al) <= 0) return 0; } @@ -2792,8 +3095,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt) * * Returns a pointer to the found RAW_EXTENSION data, or NULL if not found. */ -static RAW_EXTENSION *get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, - unsigned int type) +RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, + unsigned int type) { size_t loop; @@ -2851,9 +3154,9 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, if (s->version <= SSL3_VERSION || !tls_use_ticket(s)) return 0; - ticketext = get_extension_by_type(hello->pre_proc_exts, - hello->num_extensions, - TLSEXT_TYPE_session_ticket); + ticketext = tls_get_extension_by_type(hello->pre_proc_exts, + hello->num_extensions, + TLSEXT_TYPE_session_ticket); if (ticketext == NULL) return 0; @@ -2900,22 +3203,24 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, /* * Sets the extended master secret flag if the extension is present in the - * ClientHello + * ClientHello and we can support it * Returns: * 1 on success * 0 on error */ -int tls_check_client_ems_support(SSL *s, CLIENTHELLO_MSG *hello) +int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello) { RAW_EXTENSION *emsext; s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS; - if (s->version <= SSL3_VERSION) + if (!SSL_IS_DTLS(s) && (s->version < TLS1_VERSION + || s->version > TLS1_2_VERSION)) return 1; - emsext = get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, - TLSEXT_TYPE_extended_master_secret); + emsext = tls_get_extension_by_type(hello->pre_proc_exts, + hello->num_extensions, + TLSEXT_TYPE_extended_master_secret); /* * No extensions is a success - we have successfully discovered that the