X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fextensions.c;h=c3d3441a1c63a066409c20f16a33d66b0b075741;hp=209b4df7825226deabef6a7c6902ea5fb793360d;hb=72a7a7021fa8bc82a11bc08bac1b0241a92143d0;hpb=bceae201b45fdbc7898adada6aebe2a1b6145009 diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 209b4df782..c3d3441a1c 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -348,10 +348,12 @@ static const EXTENSION_DEFINITION ext_defs[] = { { /* * Special unsolicited ServerHello extension only used when - * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set + * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but + * ignore it. */ TLSEXT_TYPE_cryptopro_bug, - SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_2_AND_BELOW_ONLY, NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL }, { @@ -623,7 +625,12 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context, && type != TLSEXT_TYPE_cookie && type != TLSEXT_TYPE_renegotiate && type != TLSEXT_TYPE_signed_certificate_timestamp - && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0) { + && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0 +#ifndef OPENSSL_NO_GOST + && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0 + && type == TLSEXT_TYPE_cryptopro_bug) +#endif + ) { SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION); goto err; @@ -810,7 +817,7 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context, } if ((context & SSL_EXT_CLIENT_HELLO) != 0) { - reason = ssl_get_min_max_version(s, &min_version, &max_version); + reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL); if (reason != 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS, reason); @@ -904,15 +911,19 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent) static int init_server_name(SSL *s, unsigned int context) { - if (s->server) + if (s->server) { s->servername_done = 0; + OPENSSL_free(s->ext.hostname); + s->ext.hostname = NULL; + } + return 1; } static int final_server_name(SSL *s, unsigned int context, int sent) { - int ret = SSL_TLSEXT_ERR_NOACK, discard; + int ret = SSL_TLSEXT_ERR_NOACK; int altmp = SSL_AD_UNRECOGNIZED_NAME; int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0; @@ -929,9 +940,25 @@ static int final_server_name(SSL *s, unsigned int context, int sent) ret = s->session_ctx->ext.servername_cb(s, &altmp, s->session_ctx->ext.servername_arg); - if (!sent) { - OPENSSL_free(s->session->ext.hostname); - s->session->ext.hostname = NULL; + /* + * For servers, propagate the SNI hostname from the temporary + * storage in the SSL to the persistent SSL_SESSION, now that we + * know we accepted it. + * Clients make this copy when parsing the server's response to + * the extension, which is when they find out that the negotiation + * was successful. + */ + if (s->server) { + /* TODO(OpenSSL1.2) revisit !sent case */ + if (sent && ret == SSL_TLSEXT_ERR_OK && (!s->hit || SSL_IS_TLS13(s))) { + /* Only store the hostname in the session if we accepted it. */ + OPENSSL_free(s->session->ext.hostname); + s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname); + if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, + ERR_R_INTERNAL_ERROR); + } + } } /* @@ -941,10 +968,8 @@ static int final_server_name(SSL *s, unsigned int context, int sent) * exceed sess_accept (zero) for the new context. */ if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) { - CRYPTO_atomic_add(&s->ctx->stats.sess_accept, 1, &discard, - s->ctx->lock); - CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, -1, &discard, - s->session_ctx->lock); + tsan_counter(&s->ctx->stats.sess_accept); + tsan_decr(&s->session_ctx->stats.sess_accept); } /* @@ -984,7 +1009,9 @@ static int final_server_name(SSL *s, unsigned int context, int sent) return 0; case SSL_TLSEXT_ERR_ALERT_WARNING: - ssl3_send_alert(s, SSL3_AL_WARNING, altmp); + /* TLSv1.3 doesn't have warning alerts so we suppress this */ + if (!SSL_IS_TLS13(s)) + ssl3_send_alert(s, SSL3_AL_WARNING, altmp); return 1; case SSL_TLSEXT_ERR_NOACK: @@ -1178,7 +1205,7 @@ static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, X509 *x, size_t chainidx) { - const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s); + const STACK_OF(X509_NAME) *ca_sk = get_ca_names(s); if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0) return EXT_RETURN_NOT_SENT; @@ -1191,7 +1218,7 @@ static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt, return EXT_RETURN_FAIL; } - if (!construct_ca_names(s, pkt)) { + if (!construct_ca_names(s, ca_sk, pkt)) { /* SSLfatal() already called */ return EXT_RETURN_FAIL; } @@ -1421,13 +1448,11 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, EVP_MD_CTX *mctx = NULL; unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE]; unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE]; - unsigned char tmppsk[EVP_MAX_MD_SIZE]; - unsigned char *early_secret, *psk; - const char resumption_label[] = "res binder"; - const char external_label[] = "ext binder"; - const char nonce_label[] = "resumption"; - const char *label; - size_t bindersize, labelsize, psklen, hashsize; + unsigned char *early_secret; + static const unsigned char resumption_label[] = "res binder"; + static const unsigned char external_label[] = "ext binder"; + const unsigned char *label; + size_t bindersize, labelsize, hashsize; int hashsizei = EVP_MD_size(md); int ret = -1; int usepskfored = 0; @@ -1454,21 +1479,6 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, labelsize = sizeof(resumption_label) - 1; } - if (external) { - psk = sess->master_key; - psklen = sess->master_key_length; - } else { - psk = tmppsk; - psklen = hashsize; - if (!tls13_hkdf_expand(s, md, sess->master_key, - (const unsigned char *)nonce_label, - sizeof(nonce_label) - 1, sess->ext.tick_nonce, - sess->ext.tick_nonce_len, psk, hashsize)) { - /* SSLfatal() already called */ - goto err; - } - } - /* * Generate the early_secret. On the server side we've selected a PSK to * resume with (internal or external) so we always do this. On the client @@ -1481,7 +1491,9 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, early_secret = (unsigned char *)s->early_secret; else early_secret = (unsigned char *)sess->early_secret; - if (!tls13_generate_secret(s, md, NULL, psk, psklen, early_secret)) { + + if (!tls13_generate_secret(s, md, NULL, sess->master_key, + sess->master_key_length, early_secret)) { /* SSLfatal() already called */ goto err; } @@ -1500,8 +1512,8 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, } /* Generate the binder key */ - if (!tls13_hkdf_expand(s, md, early_secret, (unsigned char *)label, - labelsize, hash, hashsize, binderkey, hashsize)) { + if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash, + hashsize, binderkey, hashsize, 1)) { /* SSLfatal() already called */ goto err; } @@ -1525,10 +1537,12 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, */ if (s->hello_retry_request == SSL_HRR_PENDING) { size_t hdatalen; + long hdatalen_l; void *hdata; - hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); - if (hdatalen <= 0) { + hdatalen = hdatalen_l = + BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen_l <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, SSL_R_BAD_HANDSHAKE_LENGTH); goto err; @@ -1635,7 +1649,10 @@ static int final_early_data(SSL *s, unsigned int context, int sent) || s->session->ext.tick_identity != 0 || s->early_data_state != SSL_EARLY_DATA_ACCEPTING || !s->ext.early_data_ok - || s->hello_retry_request != SSL_HRR_NONE) { + || s->hello_retry_request != SSL_HRR_NONE + || (s->ctx->allow_early_data_cb != NULL + && !s->ctx->allow_early_data_cb(s, + s->ctx->allow_early_data_cb_data))) { s->ext.early_data = SSL_EARLY_DATA_REJECTED; } else { s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;