diff options
Diffstat (limited to 'src/ssl/s3_clnt.c')
-rw-r--r-- | src/ssl/s3_clnt.c | 835 |
1 files changed, 332 insertions, 503 deletions
diff --git a/src/ssl/s3_clnt.c b/src/ssl/s3_clnt.c index 159e2d7..559db72 100644 --- a/src/ssl/s3_clnt.c +++ b/src/ssl/s3_clnt.c @@ -148,21 +148,26 @@ * OTHERWISE. */ +#include <openssl/ssl.h> + #include <assert.h> #include <stdio.h> #include <string.h> +#include <openssl/bn.h> #include <openssl/buf.h> #include <openssl/bytestring.h> -#include <openssl/rand.h> -#include <openssl/obj.h> +#include <openssl/dh.h> +#include <openssl/ec_key.h> +#include <openssl/ecdsa.h> #include <openssl/err.h> #include <openssl/evp.h> -#include <openssl/mem.h> #include <openssl/md5.h> -#include <openssl/dh.h> -#include <openssl/bn.h> +#include <openssl/mem.h> +#include <openssl/obj.h> +#include <openssl/rand.h> #include <openssl/x509.h> +#include <openssl/x509v3.h> #include "internal.h" #include "../crypto/dh/internal.h" @@ -217,8 +222,8 @@ int ssl3_connect(SSL *s) { /* don't push the buffering BIO quite yet */ - if (!ssl3_init_finished_mac(s)) { - OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR); + if (!ssl3_init_handshake_buffer(s)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } @@ -273,7 +278,7 @@ int ssl3_connect(SSL *s) { if (s->s3->tmp.certificate_status_expected) { s->state = SSL3_ST_CR_CERT_STATUS_A; } else { - s->state = SSL3_ST_CR_KEY_EXCH_A; + s->state = SSL3_ST_VERIFY_SERVER_CERT; } } else { skip = 1; @@ -282,6 +287,16 @@ int ssl3_connect(SSL *s) { s->init_num = 0; break; + case SSL3_ST_VERIFY_SERVER_CERT: + ret = ssl3_verify_server_cert(s); + if (ret <= 0) { + goto end; + } + + s->state = SSL3_ST_CR_KEY_EXCH_A; + s->init_num = 0; + break; + case SSL3_ST_CR_KEY_EXCH_A: case SSL3_ST_CR_KEY_EXCH_B: ret = ssl3_get_server_key_exchange(s); @@ -290,13 +305,6 @@ int ssl3_connect(SSL *s) { } s->state = SSL3_ST_CR_CERT_REQ_A; s->init_num = 0; - - /* at this point we check that we have the - * required stuff from the server */ - if (!ssl3_check_cert_and_algorithm(s)) { - ret = -1; - goto end; - } break; case SSL3_ST_CR_CERT_REQ_A: @@ -356,6 +364,7 @@ int ssl3_connect(SSL *s) { case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: + case SSL3_ST_CW_CERT_VRFY_C: ret = ssl3_send_cert_verify(s); if (ret <= 0) { goto end; @@ -433,11 +442,9 @@ int ssl3_connect(SSL *s) { * record the handshake hashes at this point in the session so that * any resumption of this session with ChannelID can sign those * hashes. */ - if (s->s3->tlsext_channel_id_new) { - ret = tls1_record_handshake_hashes_for_channel_id(s); - if (ret <= 0) { - goto end; - } + ret = tls1_record_handshake_hashes_for_channel_id(s); + if (ret <= 0) { + goto end; } if ((SSL_get_mode(s) & SSL_MODE_ENABLE_FALSE_START) && ssl3_can_false_start(s) && @@ -473,7 +480,7 @@ int ssl3_connect(SSL *s) { if (ret <= 0) { goto end; } - s->state = SSL3_ST_CR_KEY_EXCH_A; + s->state = SSL3_ST_VERIFY_SERVER_CERT; s->init_num = 0; break; @@ -536,11 +543,16 @@ int ssl3_connect(SSL *s) { /* Remove write buffering now. */ ssl_free_wbio_buffer(s); + const int is_initial_handshake = !s->s3->initial_handshake_complete; + s->init_num = 0; s->s3->tmp.in_false_start = 0; s->s3->initial_handshake_complete = 1; - ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + if (is_initial_handshake) { + /* Renegotiations do not participate in session resumption. */ + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + } ret = 1; /* s->server=0; */ @@ -552,7 +564,7 @@ int ssl3_connect(SSL *s) { goto end; default: - OPENSSL_PUT_ERROR(SSL, ssl3_connect, SSL_R_UNKNOWN_STATE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } @@ -588,7 +600,7 @@ int ssl3_send_client_hello(SSL *s) { uint16_t max_version = ssl3_get_max_client_version(s); /* Disabling all versions is silly: return an error. */ if (max_version == 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_WRONG_SSL_VERSION); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION); goto err; } s->version = max_version; @@ -661,7 +673,7 @@ int ssl3_send_client_hello(SSL *s) { *(p++) = i; if (i != 0) { if (i > (int)sizeof(s->session->session_id)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } memcpy(p, s->session->session_id, i); @@ -671,7 +683,7 @@ int ssl3_send_client_hello(SSL *s) { /* cookie stuff for DTLS */ if (SSL_IS_DTLS(s)) { if (s->d1->cookie_len > sizeof(s->d1->cookie)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } *(p++) = s->d1->cookie_len; @@ -682,8 +694,7 @@ int ssl3_send_client_hello(SSL *s) { /* Ciphers supported */ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]); if (i == 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, - SSL_R_NO_CIPHERS_AVAILABLE); + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE); goto err; } s2n(i, p); @@ -694,15 +705,10 @@ int ssl3_send_client_hello(SSL *s) { *(p++) = 0; /* Add the NULL method */ /* TLS extensions*/ - if (ssl_prepare_clienthello_tlsext(s) <= 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } - p = ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH, p - buf); if (p == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } @@ -746,8 +752,7 @@ int ssl3_get_server_hello(SSL *s) { * parameters. Note: this error code comes after the original one. * * See https://crbug.com/446505. */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO); + OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO); } return n; } @@ -761,14 +766,14 @@ int ssl3_get_server_hello(SSL *s) { !CBS_get_u16(&server_hello, &cipher_suite) || !CBS_get_u8(&server_hello, &compression_method)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } assert(s->s3->have_version == s->s3->initial_handshake_complete); if (!s->s3->have_version) { if (!ssl3_is_version_enabled(s, server_version)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL); s->version = server_version; /* Mark the version as fixed so the record-layer version is not clamped * to TLS 1.0. */ @@ -783,7 +788,7 @@ int ssl3_get_server_hello(SSL *s) { * fixed. Begin enforcing the record-layer version. */ s->s3->have_version = 1; } else if (server_version != s->version) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION); al = SSL_AD_PROTOCOL_VERSION; goto f_err; } @@ -799,7 +804,7 @@ int ssl3_get_server_hello(SSL *s) { memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { /* actually a client application bug */ al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + OPENSSL_PUT_ERROR(SSL, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); goto f_err; } @@ -820,8 +825,7 @@ int ssl3_get_server_hello(SSL *s) { if (c == NULL) { /* unknown cipher */ al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_UNKNOWN_CIPHER_RETURNED); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED); goto f_err; } /* ct->mask_ssl was computed from client capabilities. Now @@ -837,7 +841,7 @@ int ssl3_get_server_hello(SSL *s) { (c->algorithm_mkey & ct->mask_k) || (c->algorithm_auth & ct->mask_a)) { al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); goto f_err; } @@ -845,45 +849,46 @@ int ssl3_get_server_hello(SSL *s) { if (!sk_SSL_CIPHER_find(sk, NULL, c)) { /* we did not say we would use this cipher */ al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); goto f_err; } if (s->hit) { if (s->session->cipher != c) { al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); goto f_err; } if (s->session->ssl_version != s->version) { al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_OLD_SESSION_VERSION_NOT_RETURNED); + OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED); goto f_err; } } s->s3->tmp.new_cipher = c; + /* Now that the cipher is known, initialize the handshake hash. */ + if (!ssl3_init_handshake_hash(s)) { + goto f_err; + } + /* If doing a full handshake with TLS 1.2, the server may request a client * certificate which requires hashing the handshake transcript under a - * different hash. Otherwise, release the handshake buffer. */ - if ((!SSL_USE_SIGALGS(s) || s->hit) && - !ssl3_digest_cached_records(s, free_handshake_buffer)) { - goto f_err; + * different hash. Otherwise, the handshake buffer may be released. */ + if (!SSL_USE_SIGALGS(s) || s->hit) { + ssl3_free_handshake_buffer(s); } /* Only the NULL compression algorithm is supported. */ if (compression_method != 0) { al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); goto f_err; } /* TLS extensions */ if (!ssl_parse_serverhello_tlsext(s, &server_hello)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_PARSE_TLSEXT); + OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); goto err; } @@ -891,7 +896,7 @@ int ssl3_get_server_hello(SSL *s) { if (CBS_len(&server_hello) != 0) { /* wrong packet length */ al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_BAD_PACKET_LENGTH); + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH); goto f_err; } @@ -899,11 +904,9 @@ int ssl3_get_server_hello(SSL *s) { s->s3->tmp.extended_master_secret != s->session->extended_master_secret) { al = SSL_AD_HANDSHAKE_FAILURE; if (s->session->extended_master_secret) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); + OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); } else { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, - SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION); + OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION); } goto f_err; } @@ -916,12 +919,49 @@ err: return -1; } +/* ssl3_check_certificate_for_cipher returns one if |leaf| is a suitable server + * certificate type for |cipher|. Otherwise, it returns zero and pushes an error + * on the error queue. */ +static int ssl3_check_certificate_for_cipher(X509 *leaf, + const SSL_CIPHER *cipher) { + int ret = 0; + EVP_PKEY *pkey = X509_get_pubkey(leaf); + if (pkey == NULL) { + goto err; + } + + /* Check the certificate's type matches the cipher. */ + int expected_type = ssl_cipher_get_key_type(cipher); + assert(expected_type != EVP_PKEY_NONE); + if (pkey->type != expected_type) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE); + goto err; + } + + /* TODO(davidben): This behavior is preserved from upstream. Should key usages + * be checked in other cases as well? */ + if (cipher->algorithm_auth & SSL_aECDSA) { + /* This call populates the ex_flags field correctly */ + X509_check_purpose(leaf, -1, 0); + if ((leaf->ex_flags & EXFLAG_KUSAGE) && + !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING); + goto err; + } + } + + ret = 1; + +err: + EVP_PKEY_free(pkey); + return ret; +} + int ssl3_get_server_certificate(SSL *s) { - int al, i, ok, ret = -1; + int al, ok, ret = -1; unsigned long n; X509 *x = NULL; STACK_OF(X509) *sk = NULL; - SESS_CERT *sc; EVP_PKEY *pkey = NULL; CBS cbs, certificate_list; const uint8_t *data; @@ -938,14 +978,15 @@ int ssl3_get_server_certificate(SSL *s) { sk = sk_X509_new_null(); if (sk == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) || + CBS_len(&certificate_list) == 0 || CBS_len(&cbs) != 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } @@ -953,92 +994,45 @@ int ssl3_get_server_certificate(SSL *s) { CBS certificate; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, - SSL_R_CERT_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } data = CBS_data(&certificate); x = d2i_X509(NULL, &data, CBS_len(&certificate)); if (x == NULL) { al = SSL_AD_BAD_CERTIFICATE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); goto f_err; } if (data != CBS_data(&certificate) + CBS_len(&certificate)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, - SSL_R_CERT_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } if (!sk_X509_push(sk, x)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } x = NULL; } - i = ssl_verify_cert_chain(s, sk); - if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) { - al = ssl_verify_alarm_type(s->verify_result); - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, - SSL_R_CERTIFICATE_VERIFY_FAILED); + X509 *leaf = sk_X509_value(sk, 0); + if (!ssl3_check_certificate_for_cipher(leaf, s->s3->tmp.new_cipher)) { + al = SSL_AD_ILLEGAL_PARAMETER; goto f_err; } - ERR_clear_error(); /* but we keep s->verify_result */ - - sc = ssl_sess_cert_new(); - if (sc == NULL) { - goto err; - } - ssl_sess_cert_free(s->session->sess_cert); - s->session->sess_cert = sc; - - sc->cert_chain = sk; - /* Inconsistency alert: cert_chain does include the peer's certificate, which - * we don't include in s3_srvr.c */ - x = sk_X509_value(sk, 0); + /* NOTE: Unlike the server half, the client's copy of |cert_chain| includes + * the leaf. */ + sk_X509_pop_free(s->session->cert_chain, X509_free); + s->session->cert_chain = sk; sk = NULL; - /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/ - - pkey = X509_get_pubkey(x); - - if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) { - x = NULL; - al = SSL3_AL_FATAL; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, - SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); - goto f_err; - } - - i = ssl_cert_type(pkey); - if (i < 0) { - x = NULL; - al = SSL3_AL_FATAL; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, - SSL_R_UNKNOWN_CERTIFICATE_TYPE); - goto f_err; - } - - int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); - if (exp_idx >= 0 && i != exp_idx) { - x = NULL; - al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, - SSL_R_WRONG_CERTIFICATE_TYPE); - goto f_err; - } - sc->peer_cert_type = i; - X509_free(sc->peer_pkeys[i].x509); - sc->peer_pkeys[i].x509 = X509_up_ref(x); - sc->peer_key = &(sc->peer_pkeys[i]); X509_free(s->session->peer); - s->session->peer = X509_up_ref(x); + s->session->peer = X509_up_ref(leaf); s->session->verify_result = s->verify_result; - x = NULL; ret = 1; if (0) { @@ -1077,25 +1071,14 @@ int ssl3_get_server_key_exchange(SSL *s) { if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - SSL_R_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); return -1; } - /* In plain PSK ciphersuite, ServerKeyExchange can be - omitted if no identity hint is sent. Set session->sess_cert anyway to - avoid problems later.*/ + /* In plain PSK ciphersuite, ServerKeyExchange may be omitted to send no + * identity hint. */ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) { - /* PSK ciphersuites that also send a Certificate would have already - * initialized |sess_cert|. */ - if (s->session->sess_cert == NULL) { - s->session->sess_cert = ssl_sess_cert_new(); - if (s->session->sess_cert == NULL) { - return -1; - } - } - /* TODO(davidben): This should be reset in one place with the rest of the * handshake state. */ OPENSSL_free(s->s3->tmp.peer_psk_identity_hint); @@ -1109,18 +1092,6 @@ int ssl3_get_server_key_exchange(SSL *s) { CBS_init(&server_key_exchange, s->init_msg, n); server_key_exchange_orig = server_key_exchange; - if (s->session->sess_cert != NULL) { - DH_free(s->session->sess_cert->peer_dh_tmp); - s->session->sess_cert->peer_dh_tmp = NULL; - EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); - s->session->sess_cert->peer_ecdh_tmp = NULL; - } else { - s->session->sess_cert = ssl_sess_cert_new(); - if (s->session->sess_cert == NULL) { - return -1; - } - } - alg_k = s->s3->tmp.new_cipher->algorithm_mkey; alg_a = s->s3->tmp.new_cipher->algorithm_auth; EVP_MD_CTX_init(&md_ctx); @@ -1132,7 +1103,7 @@ int ssl3_get_server_key_exchange(SSL *s) { if (!CBS_get_u16_length_prefixed(&server_key_exchange, &psk_identity_hint)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } @@ -1146,16 +1117,14 @@ int ssl3_get_server_key_exchange(SSL *s) { if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN || CBS_contains_zero_byte(&psk_identity_hint)) { al = SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - SSL_R_DATA_LENGTH_TOO_LONG); + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); goto f_err; } /* Save the identity hint as a C string. */ if (!CBS_strdup(&psk_identity_hint, &s->s3->tmp.peer_psk_identity_hint)) { al = SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto f_err; } } @@ -1170,13 +1139,13 @@ int ssl3_get_server_key_exchange(SSL *s) { !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) || CBS_len(&dh_Ys) == 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } dh = DH_new(); if (dh == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); goto err; } @@ -1184,23 +1153,17 @@ int ssl3_get_server_key_exchange(SSL *s) { (dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL || (dh->pub_key = BN_bin2bn(CBS_data(&dh_Ys), CBS_len(&dh_Ys), NULL)) == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_BN_LIB); goto err; } - if (DH_num_bits(dh) < 1024) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - SSL_R_BAD_DH_P_LENGTH); + s->session->key_exchange_info = DH_num_bits(dh); + if (s->session->key_exchange_info < 1024) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH); goto err; } - - if (alg_a & SSL_aRSA) { - pkey = X509_get_pubkey( - s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); - } - /* else anonymous DH, so no certificate or pkey. */ - - s->session->sess_cert->peer_dh_tmp = dh; + DH_free(s->s3->tmp.peer_dh_tmp); + s->s3->tmp.peer_dh_tmp = dh; dh = NULL; } else if (alg_k & SSL_kECDHE) { uint16_t curve_id; @@ -1213,22 +1176,21 @@ int ssl3_get_server_key_exchange(SSL *s) { * invalid curve. */ if (!tls1_check_curve(s, &server_key_exchange, &curve_id)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_WRONG_CURVE); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE); goto f_err; } curve_nid = tls1_ec_curve_id2nid(curve_id); if (curve_nid == 0) { al = SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); goto f_err; } ecdh = EC_KEY_new_by_curve_name(curve_nid); + s->session->key_exchange_info = curve_id; if (ecdh == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - ERR_R_EC_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_EC_LIB); goto err; } @@ -1237,37 +1199,25 @@ int ssl3_get_server_key_exchange(SSL *s) { /* Next, get the encoded ECPoint */ if (!CBS_get_u8_length_prefixed(&server_key_exchange, &point)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) || ((bn_ctx = BN_CTX_new()) == NULL)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_oct2point(group, srvr_ecpoint, CBS_data(&point), CBS_len(&point), bn_ctx)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_ECPOINT); + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT); goto f_err; } - - /* The ECC/TLS specification does not mention the use of DSA to sign - * ECParameters in the server key exchange message. We do support RSA and - * ECDSA. */ - if (alg_a & SSL_aRSA) { - pkey = X509_get_pubkey( - s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); - } else if (alg_a & SSL_aECDSA) { - pkey = - X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); - } - /* else anonymous ECDH, so no certificate or pkey. */ EC_KEY_set_public_key(ecdh, srvr_ecpoint); - s->session->sess_cert->peer_ecdh_tmp = ecdh; + EC_KEY_free(s->s3->tmp.peer_ecdh_tmp); + s->s3->tmp.peer_ecdh_tmp = ecdh; ecdh = NULL; BN_CTX_free(bn_ctx); bn_ctx = NULL; @@ -1275,8 +1225,7 @@ int ssl3_get_server_key_exchange(SSL *s) { srvr_ecpoint = NULL; } else if (!(alg_k & SSL_kPSK)) { al = SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - SSL_R_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } @@ -1286,9 +1235,12 @@ int ssl3_get_server_key_exchange(SSL *s) { CBS_init(¶meter, CBS_data(&server_key_exchange_orig), CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange)); - /* if it was signed, check the signature */ - if (pkey != NULL) { - CBS signature; + /* ServerKeyExchange should be signed by the server's public key. */ + if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { + pkey = X509_get_pubkey(s->session->peer); + if (pkey == NULL) { + goto err; + } if (SSL_USE_SIGALGS(s)) { if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) { @@ -1301,10 +1253,11 @@ int ssl3_get_server_key_exchange(SSL *s) { } /* The last field in |server_key_exchange| is the signature. */ + CBS signature; if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) || CBS_len(&server_key_exchange) != 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } @@ -1319,24 +1272,16 @@ int ssl3_get_server_key_exchange(SSL *s) { CBS_len(&signature))) { /* bad signature */ al = SSL_AD_DECRYPT_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE); + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE); goto f_err; } } else { - if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { - /* Might be wrong key type, check it */ - if (ssl3_check_cert_and_algorithm(s)) { - /* Otherwise this shouldn't happen */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - ERR_R_INTERNAL_ERROR); - } - goto err; - } - /* still data left over */ + /* PSK ciphers are the only supported certificate-less ciphers. */ + assert(alg_a == SSL_aPSK); + if (CBS_len(&server_key_exchange) > 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, - SSL_R_EXTRA_DATA_IN_MESSAGE); + OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE); goto f_err; } } @@ -1383,19 +1328,15 @@ int ssl3_get_certificate_request(SSL *s) { if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE) { s->s3->tmp.reuse_message = 1; - /* If we get here we don't need any cached handshake records as we wont be - * doing client auth. */ - if (s->s3->handshake_buffer && - !ssl3_digest_cached_records(s, free_handshake_buffer)) { - goto err; - } + /* If we get here we don't need the handshake buffer as we won't be doing + * client auth. */ + ssl3_free_handshake_buffer(s); return 1; } if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, - SSL_R_WRONG_MESSAGE_TYPE); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_MESSAGE_TYPE); goto err; } @@ -1403,14 +1344,14 @@ int ssl3_get_certificate_request(SSL *s) { ca_sk = sk_X509_NAME_new(ca_dn_cmp); if (ca_sk == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* get the certificate types */ if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } @@ -1422,16 +1363,10 @@ int ssl3_get_certificate_request(SSL *s) { if (SSL_USE_SIGALGS(s)) { CBS supported_signature_algorithms; - if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR); - goto err; - } - - if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) { + if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) || + !tls1_parse_peer_sigalgs(s, &supported_signature_algorithms)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, - SSL_R_SIGNATURE_ALGORITHMS_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } } @@ -1439,7 +1374,7 @@ int ssl3_get_certificate_request(SSL *s) { /* get the CA RDNs */ if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH); goto err; } @@ -1448,8 +1383,7 @@ int ssl3_get_certificate_request(SSL *s) { if (!CBS_get_u16_length_prefixed(&certificate_authorities, &distinguished_name)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, - SSL_R_CA_DN_TOO_LONG); + OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG); goto err; } @@ -1458,26 +1392,24 @@ int ssl3_get_certificate_request(SSL *s) { xn = d2i_X509_NAME(NULL, &data, CBS_len(&distinguished_name)); if (xn == NULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); goto err; } if (!CBS_skip(&distinguished_name, data - CBS_data(&distinguished_name))) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } if (CBS_len(&distinguished_name) != 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, - SSL_R_CA_DN_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_LENGTH_MISMATCH); goto err; } if (!sk_X509_NAME_push(ca_sk, xn)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } @@ -1508,6 +1440,27 @@ int ssl3_get_new_session_ticket(SSL *s) { return n; } + if (s->hit) { + /* The server is sending a new ticket for an existing session. Sessions are + * immutable once established, so duplicate all but the ticket of the + * existing session. */ + uint8_t *bytes; + size_t bytes_len; + if (!SSL_SESSION_to_bytes_for_ticket(s->session, &bytes, &bytes_len)) { + goto err; + } + SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len); + OPENSSL_free(bytes); + if (new_session == NULL) { + /* This should never happen. */ + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + goto err; + } + + SSL_SESSION_free(s->session); + s->session = new_session; + } + CBS_init(&new_session_ticket, s->init_msg, n); if (!CBS_get_u32(&new_session_ticket, @@ -1515,13 +1468,13 @@ int ssl3_get_new_session_ticket(SSL *s) { !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) || CBS_len(&new_session_ticket) != 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } if (!CBS_stow(&ticket, &s->session->tlsext_tick, &s->session->tlsext_ticklen)) { - OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } @@ -1569,14 +1522,14 @@ int ssl3_get_cert_status(SSL *s) { CBS_len(&ocsp_response) == 0 || CBS_len(&certificate_status) != 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto f_err; } if (!CBS_stow(&ocsp_response, &s->session->ocsp_response, &s->session->ocsp_response_length)) { al = SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto f_err; } return 1; @@ -1602,7 +1555,7 @@ int ssl3_get_server_done(SSL *s) { if (n > 0) { /* should contain no data */ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - OPENSSL_PUT_ERROR(SSL, ssl3_get_server_done, SSL_R_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH); return -1; } @@ -1640,8 +1593,7 @@ int ssl3_send_client_key_exchange(SSL *s) { size_t identity_len; if (s->psk_client_callback == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - SSL_R_PSK_NO_CLIENT_CB); + OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB); goto err; } @@ -1650,28 +1602,24 @@ int ssl3_send_client_key_exchange(SSL *s) { s->psk_client_callback(s, s->s3->tmp.peer_psk_identity_hint, identity, sizeof(identity), psk, sizeof(psk)); if (psk_len > PSK_MAX_PSK_LEN) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } else if (psk_len == 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - SSL_R_PSK_IDENTITY_NOT_FOUND); + OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; } identity_len = OPENSSL_strnlen(identity, sizeof(identity)); if (identity_len > PSK_MAX_IDENTITY_LEN) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } OPENSSL_free(s->session->psk_identity); s->session->psk_identity = BUF_strdup(identity); if (s->session->psk_identity == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } @@ -1690,29 +1638,20 @@ int ssl3_send_client_key_exchange(SSL *s) { pms_len = SSL_MAX_MASTER_KEY_LENGTH; pms = OPENSSL_malloc(pms_len); if (pms == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } - if (s->session->sess_cert == NULL) { - /* We should always have a server certificate with SSL_kRSA. */ - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); - goto err; - } - - pkey = X509_get_pubkey( - s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); + pkey = X509_get_pubkey(s->session->peer); if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); EVP_PKEY_free(pkey); goto err; } + s->session->key_exchange_info = EVP_PKEY_bits(pkey); rsa = pkey->pkey.rsa; EVP_PKEY_free(pkey); @@ -1732,8 +1671,7 @@ int ssl3_send_client_key_exchange(SSL *s) { } if (!RSA_encrypt(rsa, &enc_pms_len, p, RSA_size(rsa), pms, pms_len, RSA_PKCS1_PADDING)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - SSL_R_BAD_RSA_ENCRYPT); + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_RSA_ENCRYPT); goto err; } n += enc_pms_len; @@ -1750,32 +1688,23 @@ int ssl3_send_client_key_exchange(SSL *s) { } } else if (alg_k & SSL_kDHE) { DH *dh_srvr, *dh_clnt; - SESS_CERT *scert = s->session->sess_cert; int dh_len; size_t pub_len; - if (scert == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - SSL_R_UNEXPECTED_MESSAGE); - goto err; - } - - if (scert->peer_dh_tmp == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + if (s->s3->tmp.peer_dh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } - dh_srvr = scert->peer_dh_tmp; + dh_srvr = s->s3->tmp.peer_dh_tmp; /* generate a new random key */ dh_clnt = DHparams_dup(dh_srvr); if (dh_clnt == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); goto err; } if (!DH_generate_key(dh_clnt)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); DH_free(dh_clnt); goto err; } @@ -1783,15 +1712,14 @@ int ssl3_send_client_key_exchange(SSL *s) { pms_len = DH_size(dh_clnt); pms = OPENSSL_malloc(pms_len); if (pms == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); DH_free(dh_clnt); goto err; } dh_len = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt); if (dh_len <= 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); DH_free(dh_clnt); goto err; } @@ -1809,64 +1737,53 @@ int ssl3_send_client_key_exchange(SSL *s) { EC_KEY *tkey; int field_size = 0, ecdh_len; - if (s->session->sess_cert == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - SSL_R_UNEXPECTED_MESSAGE); - goto err; - } - - if (s->session->sess_cert->peer_ecdh_tmp == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + if (s->s3->tmp.peer_ecdh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } - tkey = s->session->sess_cert->peer_ecdh_tmp; + tkey = s->s3->tmp.peer_ecdh_tmp; srvr_group = EC_KEY_get0_group(tkey); srvr_ecpoint = EC_KEY_get0_public_key(tkey); if (srvr_group == NULL || srvr_ecpoint == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } clnt_ecdh = EC_KEY_new(); if (clnt_ecdh == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_EC_LIB); goto err; } /* Generate a new ECDH key pair */ if (!EC_KEY_generate_key(clnt_ecdh)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB); goto err; } field_size = EC_GROUP_get_degree(srvr_group); if (field_size <= 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB); goto err; } pms_len = (field_size + 7) / 8; pms = OPENSSL_malloc(pms_len); if (pms == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } ecdh_len = ECDH_compute_key(pms, pms_len, srvr_ecpoint, clnt_ecdh, NULL); if (ecdh_len <= 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB); + OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB); goto err; } pms_len = ecdh_len; @@ -1880,8 +1797,7 @@ int ssl3_send_client_key_exchange(SSL *s) { (uint8_t *)OPENSSL_malloc(encoded_pt_len * sizeof(uint8_t)); bn_ctx = BN_CTX_new(); if (encodedPoint == NULL || bn_ctx == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } @@ -1914,15 +1830,13 @@ int ssl3_send_client_key_exchange(SSL *s) { pms_len = psk_len; pms = OPENSSL_malloc(pms_len); if (pms == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } memset(pms, 0, pms_len); } else { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } @@ -1933,19 +1847,15 @@ int ssl3_send_client_key_exchange(SSL *s) { uint8_t *new_pms; size_t new_pms_len; - if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_MALLOC_FAILURE); - goto err; - } - if (!CBB_add_u16_length_prefixed(&cbb, &child) || + CBB_zero(&cbb); + if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len) || + !CBB_add_u16_length_prefixed(&cbb, &child) || !CBB_add_bytes(&child, pms, pms_len) || !CBB_add_u16_length_prefixed(&cbb, &child) || !CBB_add_bytes(&child, psk, psk_len) || !CBB_finish(&cbb, &new_pms, &new_pms_len)) { CBB_cleanup(&cbb); - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, - ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } OPENSSL_cleanse(pms, pms_len); @@ -1987,87 +1897,87 @@ err: } int ssl3_send_cert_verify(SSL *s) { - uint8_t *buf, *p; - const EVP_MD *md = NULL; - uint8_t digest[EVP_MAX_MD_SIZE]; - size_t digest_length; - EVP_PKEY *pkey; - EVP_PKEY_CTX *pctx = NULL; - size_t signature_length = 0; - unsigned long n = 0; - - buf = (uint8_t *)s->init_buf->data; - - if (s->state == SSL3_ST_CW_CERT_VRFY_A) { - p = ssl_handshake_start(s); - pkey = s->cert->key->privatekey; - - /* Write out the digest type if needbe. */ - if (SSL_USE_SIGALGS(s)) { - md = tls1_choose_signing_digest(s, pkey); - if (!tls12_get_sigandhash(p, pkey, md)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_INTERNAL_ERROR); - goto err; + if (s->state == SSL3_ST_CW_CERT_VRFY_A || + s->state == SSL3_ST_CW_CERT_VRFY_B) { + enum ssl_private_key_result_t sign_result; + uint8_t *p = ssl_handshake_start(s); + size_t signature_length = 0; + unsigned long n = 0; + assert(ssl_has_private_key(s)); + + if (s->state == SSL3_ST_CW_CERT_VRFY_A) { + uint8_t *buf = (uint8_t *)s->init_buf->data; + const EVP_MD *md = NULL; + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_length; + + /* Write out the digest type if need be. */ + if (SSL_USE_SIGALGS(s)) { + md = tls1_choose_signing_digest(s); + if (!tls12_get_sigandhash(s, p, md)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; + } + p += 2; + n += 2; } - p += 2; - n += 2; - } - /* Compute the digest. */ - if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) { - goto err; - } + /* Compute the digest. */ + const int pkey_type = ssl_private_key_type(s); + if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey_type)) { + return -1; + } - /* The handshake buffer is no longer necessary. */ - if (s->s3->handshake_buffer && - !ssl3_digest_cached_records(s, free_handshake_buffer)) { - goto err; - } + /* The handshake buffer is no longer necessary. */ + ssl3_free_handshake_buffer(s); - /* Sign the digest. */ - pctx = EVP_PKEY_CTX_new(pkey, NULL); - if (pctx == NULL) { - goto err; - } + /* Sign the digest. */ + signature_length = ssl_private_key_max_signature_len(s); + if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); + return -1; + } - /* Initialize the EVP_PKEY_CTX and determine the size of the signature. */ - if (!EVP_PKEY_sign_init(pctx) || !EVP_PKEY_CTX_set_signature_md(pctx, md) || - !EVP_PKEY_sign(pctx, NULL, &signature_length, digest, digest_length)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB); - goto err; + s->rwstate = SSL_PRIVATE_KEY_OPERATION; + sign_result = ssl_private_key_sign(s, &p[2], &signature_length, + signature_length, md, digest, + digest_length); + } else { + if (SSL_USE_SIGALGS(s)) { + /* The digest has already been selected and written. */ + p += 2; + n += 2; + } + signature_length = ssl_private_key_max_signature_len(s); + s->rwstate = SSL_PRIVATE_KEY_OPERATION; + sign_result = ssl_private_key_sign_complete(s, &p[2], &signature_length, + signature_length); } - if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, SSL_R_DATA_LENGTH_TOO_LONG); - goto err; + if (sign_result == ssl_private_key_retry) { + s->state = SSL3_ST_CW_CERT_VRFY_B; + return -1; } - - if (!EVP_PKEY_sign(pctx, &p[2], &signature_length, digest, digest_length)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB); - goto err; + s->rwstate = SSL_NOTHING; + if (sign_result != ssl_private_key_success) { + return -1; } s2n(signature_length, p); n += signature_length + 2; - if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) { - goto err; + return -1; } - s->state = SSL3_ST_CW_CERT_VRFY_B; + s->state = SSL3_ST_CW_CERT_VRFY_C; } - EVP_PKEY_CTX_free(pctx); return ssl_do_write(s); - -err: - EVP_PKEY_CTX_free(pctx); - return -1; } /* ssl3_has_client_certificate returns true if a client certificate is * configured. */ -static int ssl3_has_client_certificate(SSL *s) { - return s->cert && s->cert->key->x509 && s->cert->key->privatekey; +static int ssl3_has_client_certificate(SSL *ssl) { + return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl); } int ssl3_send_client_certificate(SSL *s) { @@ -2115,8 +2025,7 @@ int ssl3_send_client_certificate(SSL *s) { } } else if (i == 1) { i = 0; - OPENSSL_PUT_ERROR(SSL, ssl3_send_client_certificate, - SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); } X509_free(x509); @@ -2133,11 +2042,7 @@ int ssl3_send_client_certificate(SSL *s) { s->s3->tmp.cert_req = 2; /* There is no client certificate, so the handshake buffer may be * released. */ - if (s->s3->handshake_buffer && - !ssl3_digest_cached_records(s, free_handshake_buffer)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); - return -1; - } + ssl3_free_handshake_buffer(s); } } @@ -2146,88 +2051,23 @@ int ssl3_send_client_certificate(SSL *s) { } if (s->state == SSL3_ST_CW_CERT_C) { - CERT_PKEY *cert_pkey = (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key; - if (!ssl3_output_cert_chain(s, cert_pkey)) { + if (s->s3->tmp.cert_req == 2) { + /* Send an empty Certificate message. */ + uint8_t *p = ssl_handshake_start(s); + l2n3(0, p); + if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, 3)) { + return -1; + } + } else if (!ssl3_output_cert_chain(s)) { return -1; } + s->state = SSL3_ST_CW_CERT_D; } /* SSL3_ST_CW_CERT_D */ return ssl_do_write(s); } -#define has_bits(i, m) (((i) & (m)) == (m)) - -int ssl3_check_cert_and_algorithm(SSL *s) { - int i, idx; - long alg_k, alg_a; - EVP_PKEY *pkey = NULL; - SESS_CERT *sc; - DH *dh; - - /* we don't have a certificate */ - if (!ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { - return 1; - } - - alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - alg_a = s->s3->tmp.new_cipher->algorithm_auth; - - sc = s->session->sess_cert; - if (sc == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, ERR_R_INTERNAL_ERROR); - goto err; - } - - dh = s->session->sess_cert->peer_dh_tmp; - - /* This is the passed certificate */ - - idx = sc->peer_cert_type; - if (idx == SSL_PKEY_ECC) { - if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) { - /* check failed */ - OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_BAD_ECC_CERT); - goto f_err; - } else { - return 1; - } - } else if (alg_a & SSL_aECDSA) { - OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, - SSL_R_MISSING_ECDSA_SIGNING_CERT); - goto f_err; - } - pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509); - i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey); - EVP_PKEY_free(pkey); - - /* Check that we have a certificate if we require one */ - if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_SIGN)) { - OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, - SSL_R_MISSING_RSA_SIGNING_CERT); - goto f_err; - } - - if ((alg_k & SSL_kRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { - OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, - SSL_R_MISSING_RSA_ENCRYPTING_CERT); - goto f_err; - } - - if ((alg_k & SSL_kDHE) && - !(has_bits(i, EVP_PK_DH | EVP_PKT_EXCH) || dh != NULL)) { - OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_DH_KEY); - goto f_err; - } - - return 1; - -f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); -err: - return 0; -} - int ssl3_send_next_proto(SSL *s) { unsigned int len, padding_len; uint8_t *d, *p; @@ -2257,7 +2097,6 @@ int ssl3_send_channel_id(SSL *s) { uint8_t *d; int ret = -1, public_key_len; EVP_MD_CTX md_ctx; - size_t sig_len; ECDSA_SIG *sig = NULL; uint8_t *public_key = NULL, *derp, *der_sig = NULL; @@ -2279,72 +2118,48 @@ int ssl3_send_channel_id(SSL *s) { } s->rwstate = SSL_NOTHING; - d = ssl_handshake_start(s); - if (s->s3->tlsext_channel_id_new) { - s2n(TLSEXT_TYPE_channel_id_new, d); - } else { - s2n(TLSEXT_TYPE_channel_id, d); + if (EVP_PKEY_id(s->tlsext_channel_id_private) != EVP_PKEY_EC) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return -1; } + EC_KEY *ec_key = s->tlsext_channel_id_private->pkey.ec; + + d = ssl_handshake_start(s); + s2n(TLSEXT_TYPE_channel_id, d); s2n(TLSEXT_CHANNEL_ID_SIZE, d); EVP_MD_CTX_init(&md_ctx); - public_key_len = i2d_PublicKey(s->tlsext_channel_id_private, NULL); + public_key_len = i2o_ECPublicKey(ec_key, NULL); if (public_key_len <= 0) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, - SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY); + OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY); goto err; } - /* i2d_PublicKey will produce an ANSI X9.62 public key which, for a + /* i2o_ECPublicKey will produce an ANSI X9.62 public key which, for a * P-256 key, is 0x04 (meaning uncompressed) followed by the x and y * field elements as 32-byte, big-endian numbers. */ if (public_key_len != 65) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_CHANNEL_ID_NOT_P256); + OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256); goto err; } public_key = OPENSSL_malloc(public_key_len); if (!public_key) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } derp = public_key; - i2d_PublicKey(s->tlsext_channel_id_private, &derp); - - if (EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, - s->tlsext_channel_id_private) != 1) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, - SSL_R_EVP_DIGESTSIGNINIT_FAILED); - goto err; - } - - if (!tls1_channel_id_hash(&md_ctx, s)) { - goto err; - } + i2o_ECPublicKey(ec_key, &derp); - if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, - SSL_R_EVP_DIGESTSIGNFINAL_FAILED); - goto err; - } - - der_sig = OPENSSL_malloc(sig_len); - if (!der_sig) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EVP_DigestSignFinal(&md_ctx, der_sig, &sig_len)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, - SSL_R_EVP_DIGESTSIGNFINAL_FAILED); + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_len; + if (!tls1_channel_id_hash(s, digest, &digest_len)) { goto err; } - derp = der_sig; - sig = d2i_ECDSA_SIG(NULL, (const uint8_t **)&derp, sig_len); + sig = ECDSA_do_sign(digest, digest_len, ec_key); if (sig == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_D2I_ECDSA_SIG); goto err; } @@ -2353,7 +2168,7 @@ int ssl3_send_channel_id(SSL *s) { d += 64; if (!BN_bn2bin_padded(d, 32, sig->r) || !BN_bn2bin_padded(d + 32, 32, sig->s)) { - OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } @@ -2381,3 +2196,17 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) { } return i; } + +int ssl3_verify_server_cert(SSL *s) { + int ret = ssl_verify_cert_chain(s, s->session->cert_chain); + if (s->verify_mode != SSL_VERIFY_NONE && ret <= 0) { + int al = ssl_verify_alarm_type(s->verify_result); + ssl3_send_alert(s, SSL3_AL_FATAL, al); + OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED); + } else { + ret = 1; + ERR_clear_error(); /* but we keep s->verify_result */ + } + + return ret; +} |