/*- * The servername extension is treated as follows: * * - Only the hostname type is supported with a maximum length of 255. * - The servername is rejected if too long or if it contains zeros, * in which case an fatal alert is generated. * - The servername field is maintained together with the session cache. * - When a session is resumed, the servername call back invoked in order * to allow the application to position itself to the right context. * - The servername is acknowledged if it is new for a session or when * it is identical to a previously used for the same session. * Applications can control the behaviour. They can at any time * set a 'desirable' servername for a new SSL object. This can be the * case for example with HTTPS when a Host: header field is received and * a renegotiation is requested. In this case, a possible servername * presented in the new client hello is only acknowledged if it matches * the value of the Host: field. * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION * if they provide for changing an explicit servername context for the * session, i.e. when the session has been established with a servername * extension. * - On session reconnect, the servername extension may be absent. */ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, int *al) { unsigned int servname_type; PACKET sni, hostname; if (!PACKET_as_length_prefixed_2(pkt, &sni) /* ServerNameList must be at least 1 byte long. */ || PACKET_remaining(&sni) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } /* * Although the server_name extension was intended to be * extensible to new name types, RFC 4366 defined the * syntax inextensibly and OpenSSL 1.0.x parses it as * such. * RFC 6066 corrected the mistake but adding new name types * is nevertheless no longer feasible, so act as if no other * SNI types can exist, to simplify parsing. * * Also note that the RFC permits only one SNI value per type, * i.e., we can only have a single hostname. */ if (!PACKET_get_1(&sni, &servname_type) || servname_type != TLSEXT_NAMETYPE_host_name || !PACKET_as_length_prefixed_2(&sni, &hostname)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } if (PACKET_contains_zero_byte(&hostname)) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } if (!PACKET_strndup(&hostname, &s->session->tlsext_hostname)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } s->servername_done = 1; } else { /* * TODO(openssl-team): if the SNI doesn't match, we MUST * fall back to a full handshake. */ s->servername_done = s->session->tlsext_hostname && PACKET_equal(&hostname, s->session->tlsext_hostname, strlen(s->session->tlsext_hostname)); } return 1; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!PACKET_memdup(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
/* * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN * extension, not including type and length. |al| is a pointer to the alert * value to send in the event of a failure. Returns: 1 on success, 0 on error. */ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET protocol_list, save_protocol_list, protocol; if (!SSL_IS_FIRST_HANDSHAKE(s)) return 1; if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) || PACKET_remaining(&protocol_list) < 2) { *al = SSL_AD_DECODE_ERROR; return 0; } save_protocol_list = protocol_list; do { /* Protocol names can't be empty. */ if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) || PACKET_remaining(&protocol) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } } while (PACKET_remaining(&protocol_list) != 0); OPENSSL_free(s->s3->alpn_proposed); s->s3->alpn_proposed = NULL; s->s3->alpn_proposed_len = 0; if (!PACKET_memdup(&save_protocol_list, &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } return 1; }
/* * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN * extension, not including type and length. |al| is a pointer to the alert * value to send in the event of a failure. Returns: 1 on success, 0 on error. */ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, int *al) { PACKET protocol_list, save_protocol_list, protocol; if (s->s3->tmp.finish_md_len != 0) return 1; if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) || PACKET_remaining(&protocol_list) < 2) { *al = SSL_AD_DECODE_ERROR; return 0; } save_protocol_list = protocol_list; do { /* Protocol names can't be empty. */ if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) || PACKET_remaining(&protocol) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } } while (PACKET_remaining(&protocol_list) != 0); if (!PACKET_memdup(&save_protocol_list, &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } return 1; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!tls1_save_u16(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, int *al) { 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_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_get_net_2(pkt, &group_id)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, 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_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } skey = ssl_generate_pkey(ckey); if (skey == NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_MALLOC_FAILURE); 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_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } if (ssl_derive(s, ckey, skey, 1) == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); EVP_PKEY_free(skey); return 0; } EVP_PKEY_free(skey); return 1; }
static int test_PACKET_as_length_prefixed_2() { unsigned char buf[1024]; const size_t len = 516; /* 0x0204 */ unsigned int i; PACKET pkt, exact_pkt, subpkt = {0}; for (i = 1; i <= 1024; i++) buf[i-1] = (i * 2) & 0xff; if (!TEST_true(PACKET_buf_init(&pkt, buf, 1024)) || !TEST_true(PACKET_buf_init(&exact_pkt, buf, len + 2)) || !TEST_false(PACKET_as_length_prefixed_2(&pkt, &subpkt)) || !TEST_size_t_eq(PACKET_remaining(&pkt), 1024) || !TEST_true(PACKET_as_length_prefixed_2(&exact_pkt, &subpkt)) || !TEST_size_t_eq(PACKET_remaining(&exact_pkt), 0) || !TEST_size_t_eq(PACKET_remaining(&subpkt), len)) return 0; return 1; }
static int get_sni_from_client_hello(BIO *bio, char **sni) { long len; unsigned char *data; PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0}, pkt4 = {0}, pkt5 = {0}; unsigned int servname_type = 0, type = 0; int ret = 0; len = BIO_get_mem_data(bio, (char **)&data); if (!TEST_true(PACKET_buf_init(&pkt, data, len)) /* Skip the record header */ || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH) /* Skip the handshake message header */ || !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH)) /* Skip client version and random */ || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN + SSL3_RANDOM_SIZE)) /* Skip session id */ || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2)) /* Skip ciphers */ || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2)) /* Skip compression */ || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2)) /* Extensions len */ || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2))) goto end; /* Loop through all extensions for SNI */ while (PACKET_remaining(&pkt2)) { if (!TEST_true(PACKET_get_net_2(&pkt2, &type)) || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3))) goto end; if (type == TLSEXT_TYPE_server_name) { if (!TEST_true(PACKET_get_length_prefixed_2(&pkt3, &pkt4)) || !TEST_uint_ne(PACKET_remaining(&pkt4), 0) || !TEST_true(PACKET_get_1(&pkt4, &servname_type)) || !TEST_uint_eq(servname_type, TLSEXT_NAMETYPE_host_name) || !TEST_true(PACKET_get_length_prefixed_2(&pkt4, &pkt5)) || !TEST_uint_le(PACKET_remaining(&pkt5), TLSEXT_MAXLEN_host_name) || !TEST_false(PACKET_contains_zero_byte(&pkt5)) || !TEST_true(PACKET_strndup(&pkt5, sni))) goto end; ret = 1; goto end; } } end: return ret; }
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET supported_sig_algs; if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) || PACKET_remaining(&supported_sig_algs) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) { *al = SSL_AD_DECODE_ERROR; return 0; } return 1; }
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, int *al) { PACKET supported_sig_algs; if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) || (PACKET_remaining(&supported_sig_algs) % 2) != 0 || PACKET_remaining(&supported_sig_algs) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit && !tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs), PACKET_remaining(&supported_sig_algs))) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } return 1; }
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET supported_sig_algs; if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) || PACKET_remaining(&supported_sig_algs) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION); return 0; } return 1; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, int *al) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit && !PACKET_memdup(&supported_groups_list, &s->session->tlsext_supportedgroupslist, &s->session->tlsext_supportedgroupslist_length)) { *al = SSL_AD_DECODE_ERROR; return 0; } return 1; }
/* * 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. */ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 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; if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (clnt_num_curves == 0) { /* * This can only happen if the supported_groups extension was not sent, * because we verify that the length is non-zero when we process that * extension. */ *al = SSL_AD_MISSING_EXTENSION; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); 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_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } #endif return 1; }
/* * 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. */ int tls_parse_ctos_key_share(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; if (s->hit) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* * Get the clients list of supported curves. * TODO(TLS1.3): We should validate that we actually received * supported_groups! */ if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, 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_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } return 1; }
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET responder_id_list, exts; /* Not defined if we get one of these in a client Certificate */ if (x != NULL) return 1; if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) { /* * We don't know what to do with any other type so ignore it. */ s->ext.status_type = TLSEXT_STATUSTYPE_nothing; return 1; } if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) { *al = SSL_AD_DECODE_ERROR; return 0; } /* * We remove any OCSP_RESPIDs from a previous handshake * to prevent unbounded memory growth - CVE-2016-6304 */ sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free); if (PACKET_remaining(&responder_id_list) > 0) { s->ext.ocsp.ids = sk_OCSP_RESPID_new_null(); if (s->ext.ocsp.ids == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } else { s->ext.ocsp.ids = NULL; } while (PACKET_remaining(&responder_id_list) > 0) { OCSP_RESPID *id; PACKET responder_id; const unsigned char *id_data; if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id) || PACKET_remaining(&responder_id) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } id_data = PACKET_data(&responder_id); /* TODO(size_t): Convert d2i_* to size_t */ id = d2i_OCSP_RESPID(NULL, &id_data, (int)PACKET_remaining(&responder_id)); if (id == NULL) { *al = SSL_AD_DECODE_ERROR; return 0; } if (id_data != PACKET_end(&responder_id)) { OCSP_RESPID_free(id); *al = SSL_AD_DECODE_ERROR; return 0; } if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) { OCSP_RESPID_free(id); *al = SSL_AD_INTERNAL_ERROR; return 0; } } /* Read in request_extensions */ if (!PACKET_as_length_prefixed_2(pkt, &exts)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (PACKET_remaining(&exts) > 0) { const unsigned char *ext_data = PACKET_data(&exts); sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, X509_EXTENSION_free); s->ext.ocsp.exts = d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts)); if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) { *al = SSL_AD_DECODE_ERROR; return 0; } } return 1; }
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 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_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_get_net_2(pkt, &group_id)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } if ((context & EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) { unsigned const char *pcurves = NULL; size_t i, num_curves; if (PACKET_remaining(pkt) != 0) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* * It is an error if the HelloRetryRequest wants a key_share that we * already sent in the first ClientHello */ if (group_id == s->s3->group_id) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } /* Validate the selected group is one we support */ pcurves = s->ext.supportedgroups; if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) { SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } for (i = 0; i < num_curves; i++, pcurves += 2) { if (group_id == bytestogroup(pcurves)) break; } if (i >= num_curves || !tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } s->s3->group_id = group_id; EVP_PKEY_free(s->s3->tmp.pkey); s->s3->tmp.pkey = NULL; return 1; } 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_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } skey = ssl_generate_pkey(ckey); if (skey == NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_MALLOC_FAILURE); 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_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT); EVP_PKEY_free(skey); return 0; } if (ssl_derive(s, ckey, skey, 1) == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); EVP_PKEY_free(skey); return 0; } EVP_PKEY_free(skey); #endif return 1; }
/* * 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. */ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 unsigned int group_id; PACKET key_share_list, encoded_pt; const uint16_t *clntgroups, *srvrgroups; size_t clnt_num_groups, srvr_num_groups; int found = 0; if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* Get our list of supported groups */ tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups); /* Get the clients list of supported groups. */ tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); if (clnt_num_groups == 0) { /* * This can only happen if the supported_groups extension was not sent, * because we verify that the length is non-zero when we process that * extension. */ SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); 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) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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, clntgroups, clnt_num_groups, 0)) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 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, srvrgroups, srvr_num_groups, 1)) { /* Share not suitable */ continue; } if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); return 0; } s->s3->group_id = group_id; if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } #endif return 1; }
/*- * The servername extension is treated as follows: * * - Only the hostname type is supported with a maximum length of 255. * - The servername is rejected if too long or if it contains zeros, * in which case an fatal alert is generated. * - The servername field is maintained together with the session cache. * - When a session is resumed, the servername call back invoked in order * to allow the application to position itself to the right context. * - The servername is acknowledged if it is new for a session or when * it is identical to a previously used for the same session. * Applications can control the behaviour. They can at any time * set a 'desirable' servername for a new SSL object. This can be the * case for example with HTTPS when a Host: header field is received and * a renegotiation is requested. In this case, a possible servername * presented in the new client hello is only acknowledged if it matches * the value of the Host: field. * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION * if they provide for changing an explicit servername context for the * session, i.e. when the session has been established with a servername * extension. * - On session reconnect, the servername extension may be absent. */ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { unsigned int servname_type; PACKET sni, hostname; if (!PACKET_as_length_prefixed_2(pkt, &sni) /* ServerNameList must be at least 1 byte long. */ || PACKET_remaining(&sni) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } /* * Although the intent was for server_name to be extensible, RFC 4366 * was not clear about it; and so OpenSSL among other implementations, * always and only allows a 'host_name' name types. * RFC 6066 corrected the mistake but adding new name types * is nevertheless no longer feasible, so act as if no other * SNI types can exist, to simplify parsing. * * Also note that the RFC permits only one SNI value per type, * i.e., we can only have a single hostname. */ if (!PACKET_get_1(&sni, &servname_type) || servname_type != TLSEXT_NAMETYPE_host_name || !PACKET_as_length_prefixed_2(&sni, &hostname)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } if (PACKET_contains_zero_byte(&hostname)) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } OPENSSL_free(s->session->ext.hostname); s->session->ext.hostname = NULL; if (!PACKET_strndup(&hostname, &s->session->ext.hostname)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } s->servername_done = 1; } else { /* * TODO(openssl-team): if the SNI doesn't match, we MUST * fall back to a full handshake. */ s->servername_done = s->session->ext.hostname && PACKET_equal(&hostname, s->session->ext.hostname, strlen(s->session->ext.hostname)); } return 1; }
static int test_client_hello(int currtest) { SSL_CTX *ctx; SSL *con = NULL; BIO *rbio; BIO *wbio; long len; unsigned char *data; PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0}; char *dummytick = "Hello World!"; unsigned int type = 0; int testresult = 0; size_t msglen; BIO *sessbio = NULL; SSL_SESSION *sess = NULL; #ifdef OPENSSL_NO_TLS1_3 if (currtest == TEST_ADD_PADDING_AND_PSK) return 1; #endif /* * For each test set up an SSL_CTX and SSL and see what ClientHello gets * produced when we try to connect */ ctx = SSL_CTX_new(TLS_method()); if (!TEST_ptr(ctx)) goto end; switch(currtest) { case TEST_SET_SESSION_TICK_DATA_VER_NEG: /* Testing for session tickets <= TLS1.2; not relevant for 1.3 */ if (!TEST_true(SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION))) goto end; break; case TEST_ADD_PADDING_AND_PSK: case TEST_ADD_PADDING: case TEST_PADDING_NOT_NEEDED: SSL_CTX_set_options(ctx, SSL_OP_TLSEXT_PADDING); /* * Add lots of ciphersuites so that the ClientHello is at least * F5_WORKAROUND_MIN_MSG_LEN bytes long - meaning padding will be * needed. Also add some dummy ALPN protocols in case we still don't * have enough. */ if (currtest == TEST_ADD_PADDING && (!TEST_true(SSL_CTX_set_cipher_list(ctx, "ALL")) || !TEST_false(SSL_CTX_set_alpn_protos(ctx, (unsigned char *)alpn_prots, sizeof(alpn_prots) - 1)))) goto end; break; default: goto end; } con = SSL_new(ctx); if (!TEST_ptr(con)) goto end; if (currtest == TEST_ADD_PADDING_AND_PSK) { sessbio = BIO_new_file(sessionfile, "r"); if (!TEST_ptr(sessbio)) { TEST_info("Unable to open session.pem"); goto end; } sess = PEM_read_bio_SSL_SESSION(sessbio, NULL, NULL, NULL); if (!TEST_ptr(sess)) { TEST_info("Unable to load SSL_SESSION"); goto end; } /* * We reset the creation time so that we don't discard the session as * too old. */ if (!TEST_true(SSL_SESSION_set_time(sess, time(NULL))) || !TEST_true(SSL_set_session(con, sess))) goto end; } rbio = BIO_new(BIO_s_mem()); wbio = BIO_new(BIO_s_mem()); if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) { BIO_free(rbio); BIO_free(wbio); goto end; } SSL_set_bio(con, rbio, wbio); SSL_set_connect_state(con); if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) { if (!TEST_true(SSL_set_session_ticket_ext(con, dummytick, strlen(dummytick)))) goto end; } if (!TEST_int_le(SSL_connect(con), 0)) { /* This shouldn't succeed because we don't have a server! */ goto end; } len = BIO_get_mem_data(wbio, (char **)&data); if (!TEST_true(PACKET_buf_init(&pkt, data, len)) /* Skip the record header */ || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH)) goto end; msglen = PACKET_remaining(&pkt); /* Skip the handshake message header */ if (!TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH)) /* Skip client version and random */ || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN + SSL3_RANDOM_SIZE)) /* Skip session id */ || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2)) /* Skip ciphers */ || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2)) /* Skip compression */ || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2)) /* Extensions len */ || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2))) goto end; /* Loop through all extensions */ while (PACKET_remaining(&pkt2)) { if (!TEST_true(PACKET_get_net_2(&pkt2, &type)) || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3))) goto end; if (type == TLSEXT_TYPE_session_ticket) { if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) { if (TEST_true(PACKET_equal(&pkt3, dummytick, strlen(dummytick)))) { /* Ticket data is as we expected */ testresult = 1; } goto end; } } if (type == TLSEXT_TYPE_padding) { if (!TEST_false(currtest == TEST_PADDING_NOT_NEEDED)) goto end; else if (TEST_true(currtest == TEST_ADD_PADDING || currtest == TEST_ADD_PADDING_AND_PSK)) testresult = TEST_true(msglen == F5_WORKAROUND_MAX_MSG_LEN); } } if (currtest == TEST_PADDING_NOT_NEEDED) testresult = 1; end: SSL_free(con); SSL_CTX_free(ctx); SSL_SESSION_free(sess); BIO_free(sessbio); return testresult; }