diff options
Diffstat (limited to 'freebsd/crypto/openssl/ssl/statem')
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/extensions.c | 12 | ||||
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/extensions_clnt.c | 13 | ||||
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/statem.c | 5 | ||||
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/statem_clnt.c | 12 | ||||
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/statem_lib.c | 59 | ||||
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/statem_locl.h | 3 | ||||
-rw-r--r-- | freebsd/crypto/openssl/ssl/statem/statem_srvr.c | 44 |
7 files changed, 112 insertions, 36 deletions
diff --git a/freebsd/crypto/openssl/ssl/statem/extensions.c b/freebsd/crypto/openssl/ssl/statem/extensions.c index a6491c3d..d75460f2 100644 --- a/freebsd/crypto/openssl/ssl/statem/extensions.c +++ b/freebsd/crypto/openssl/ssl/statem/extensions.c @@ -964,7 +964,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent) */ if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) { tsan_counter(&s->ctx->stats.sess_accept); - tsan_counter(&s->session_ctx->stats.sess_accept); + tsan_decr(&s->session_ctx->stats.sess_accept); } /* @@ -1200,7 +1200,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; @@ -1213,7 +1213,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; } @@ -1532,10 +1532,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; diff --git a/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c b/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c index d58ae79b..a64d5367 100644 --- a/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c +++ b/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c @@ -117,7 +117,7 @@ EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, #ifndef OPENSSL_NO_EC static int use_ecc(SSL *s) { - int i, end; + int i, end, ret = 0; unsigned long alg_k, alg_a; STACK_OF(SSL_CIPHER) *cipher_stack = NULL; @@ -125,7 +125,7 @@ static int use_ecc(SSL *s) if (s->version == SSL3_VERSION) return 0; - cipher_stack = SSL_get_ciphers(s); + cipher_stack = SSL_get1_supported_ciphers(s); end = sk_SSL_CIPHER_num(cipher_stack); for (i = 0; i < end; i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); @@ -134,11 +134,14 @@ static int use_ecc(SSL *s) alg_a = c->algorithm_auth; if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) || (alg_a & SSL_aECDSA) - || c->min_tls >= TLS1_3_VERSION) - return 1; + || c->min_tls >= TLS1_3_VERSION) { + ret = 1; + break; + } } - return 0; + sk_SSL_CIPHER_free(cipher_stack); + return ret; } EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt, diff --git a/freebsd/crypto/openssl/ssl/statem/statem.c b/freebsd/crypto/openssl/ssl/statem/statem.c index 32e87690..ad50677d 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem.c +++ b/freebsd/crypto/openssl/ssl/statem/statem.c @@ -120,11 +120,12 @@ void ossl_statem_set_renegotiate(SSL *s) void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file, int line) { + ERR_put_error(ERR_LIB_SSL, func, reason, file, line); /* We shouldn't call SSLfatal() twice. Once is enough */ - assert(s->statem.state != MSG_FLOW_ERROR); + if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR) + return; s->statem.in_init = 1; s->statem.state = MSG_FLOW_ERROR; - ERR_put_error(ERR_LIB_SSL, func, reason, file, line); if (al != SSL_AD_NO_ALERT && s->statem.enc_write_state != ENC_WRITE_STATE_INVALID) ssl3_send_alert(s, SSL3_AL_FATAL, al); diff --git a/freebsd/crypto/openssl/ssl/statem/statem_clnt.c b/freebsd/crypto/openssl/ssl/statem/statem_clnt.c index 574ec01e..154a9d45 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem_clnt.c +++ b/freebsd/crypto/openssl/ssl/statem/statem_clnt.c @@ -1097,6 +1097,7 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst) ERR_R_INTERNAL_ERROR); return WORK_ERROR; + case TLS_ST_CR_CERT_VRFY: case TLS_ST_CR_CERT_REQ: return tls_prepare_client_certificate(s, wst); } @@ -2565,6 +2566,17 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) /* we should setup a certificate to return.... */ s->s3->tmp.cert_req = 1; + /* + * In TLSv1.3 we don't prepare the client certificate yet. We wait until + * after the CertificateVerify message has been received. This is because + * in TLSv1.3 the CertificateRequest arrives before the Certificate message + * but in TLSv1.2 it is the other way around. We want to make sure that + * SSL_get_peer_certificate() returns something sensible in + * client_cert_cb. + */ + if (SSL_IS_TLS13(s) && s->post_handshake_auth != SSL_PHA_REQUESTED) + return MSG_PROCESS_CONTINUE_READING; + return MSG_PROCESS_CONTINUE_PROCESSING; } diff --git a/freebsd/crypto/openssl/ssl/statem/statem_lib.c b/freebsd/crypto/openssl/ssl/statem/statem_lib.c index 1ea719c7..e8c96f27 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem_lib.c +++ b/freebsd/crypto/openssl/ssl/statem/statem_lib.c @@ -205,9 +205,10 @@ static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs, *hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen; } else { size_t retlen; + long retlen_l; - retlen = BIO_get_mem_data(s->s3->handshake_buffer, hdata); - if (retlen <= 0) { + retlen = retlen_l = BIO_get_mem_data(s->s3->handshake_buffer, hdata); + if (retlen_l <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA, ERR_R_INTERNAL_ERROR); return 0; @@ -496,7 +497,18 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) } } - ret = MSG_PROCESS_CONTINUE_READING; + /* + * In TLSv1.3 on the client side we make sure we prepare the client + * certificate after the CertVerify instead of when we get the + * CertificateRequest. This is because in TLSv1.3 the CertificateRequest + * comes *before* the Certificate message. In TLSv1.2 it comes after. We + * want to make sure that SSL_get_peer_certificate() will return the actual + * server certificate from the client_cert_cb callback. + */ + if (!s->server && SSL_IS_TLS13(s) && s->s3->tmp.cert_req == 1) + ret = MSG_PROCESS_CONTINUE_PROCESSING; + else + ret = MSG_PROCESS_CONTINUE_READING; err: BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; @@ -1497,6 +1509,10 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method) static int is_tls13_capable(const SSL *s) { int i; +#ifndef OPENSSL_NO_EC + int curve; + EC_KEY *eckey; +#endif #ifndef OPENSSL_NO_PSK if (s->psk_server_callback != NULL) @@ -1517,8 +1533,25 @@ static int is_tls13_capable(const SSL *s) default: break; } - if (ssl_has_cert(s, i)) + if (!ssl_has_cert(s, i)) + continue; +#ifndef OPENSSL_NO_EC + if (i != SSL_PKEY_ECC) + return 1; + /* + * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is + * more restrictive so check that our sig algs are consistent with this + * EC cert. See section 4.2.3 of RFC8446. + */ + eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey); + if (eckey == NULL) + continue; + curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + if (tls_check_sigalg_curve(s, curve)) return 1; +#else + return 1; +#endif } return 0; @@ -2263,10 +2296,24 @@ int parse_ca_names(SSL *s, PACKET *pkt) return 0; } -int construct_ca_names(SSL *s, WPACKET *pkt) +const STACK_OF(X509_NAME) *get_ca_names(SSL *s) { - const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s); + const STACK_OF(X509_NAME) *ca_sk = NULL;; + + if (s->server) { + ca_sk = SSL_get_client_CA_list(s); + if (ca_sk != NULL && sk_X509_NAME_num(ca_sk) == 0) + ca_sk = NULL; + } + + if (ca_sk == NULL) + ca_sk = SSL_get0_CA_list(s); + return ca_sk; +} + +int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt) +{ /* Start sub-packet for client CA list */ if (!WPACKET_start_sub_packet_u16(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES, diff --git a/freebsd/crypto/openssl/ssl/statem/statem_locl.h b/freebsd/crypto/openssl/ssl/statem/statem_locl.h index 25e56e4e..6b8cf37f 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem_locl.h +++ b/freebsd/crypto/openssl/ssl/statem/statem_locl.h @@ -61,7 +61,8 @@ int create_synthetic_message_hash(SSL *s, const unsigned char *hashval, size_t hashlen, const unsigned char *hrr, size_t hrrlen); int parse_ca_names(SSL *s, PACKET *pkt); -int construct_ca_names(SSL *s, WPACKET *pkt); +const STACK_OF(X509_NAME) *get_ca_names(SSL *s); +int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, WPACKET *pkt); size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs, const void *param, size_t paramlen); diff --git a/freebsd/crypto/openssl/ssl/statem/statem_srvr.c b/freebsd/crypto/openssl/ssl/statem/statem_srvr.c index f9c06aaf..c9bee6ba 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem_srvr.c +++ b/freebsd/crypto/openssl/ssl/statem/statem_srvr.c @@ -1521,8 +1521,10 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) * So check cookie length... */ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { - if (clienthello->dtls_cookie_len == 0) + if (clienthello->dtls_cookie_len == 0) { + OPENSSL_free(clienthello); return MSG_PROCESS_FINISHED_READING; + } } } @@ -2058,10 +2060,6 @@ static int tls_early_post_process_client_hello(SSL *s) #else s->session->compress_meth = (comp == NULL) ? 0 : comp->id; #endif - if (!tls1_set_server_sigalgs(s)) { - /* SSLfatal() already called */ - goto err; - } } sk_SSL_CIPHER_free(ciphers); @@ -2229,19 +2227,25 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) if (wst == WORK_MORE_B) { if (!s->hit || SSL_IS_TLS13(s)) { /* Let cert callback update server certificates if required */ - if (!s->hit && s->cert->cert_cb != NULL) { - int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); - if (rv == 0) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, - SSL_R_CERT_CB_ERROR); - goto err; + if (!s->hit) { + if (s->cert->cert_cb != NULL) { + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, + SSL_R_CERT_CB_ERROR); + goto err; + } + if (rv < 0) { + s->rwstate = SSL_X509_LOOKUP; + return WORK_MORE_B; + } + s->rwstate = SSL_NOTHING; } - if (rv < 0) { - s->rwstate = SSL_X509_LOOKUP; - return WORK_MORE_B; + if (!tls1_set_server_sigalgs(s)) { + /* SSLfatal already called */ + goto err; } - s->rwstate = SSL_NOTHING; } /* In TLSv1.3 we selected the ciphersuite before resumption */ @@ -2878,7 +2882,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) } } - if (!construct_ca_names(s, pkt)) { + if (!construct_ca_names(s, get_ca_names(s), pkt)) { /* SSLfatal() already called */ return 0; } @@ -3224,6 +3228,12 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt) SSL_R_LENGTH_MISMATCH); goto err; } + if (skey == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, + SSL_R_MISSING_TMP_ECDH_KEY); + goto err; + } + ckey = EVP_PKEY_new(); if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE, |