diff options
author | Kenny Root <kroot@google.com> | 2015-09-25 00:26:37 +0000 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2015-09-25 00:26:37 +0000 |
commit | a04d78d392463df4e69a64360c952ffa5abd22f7 (patch) | |
tree | dc62c249d595198e0d99e43890019d21e901fbec /src/ssl/s3_clnt.c | |
parent | 1e4884f615b20946411a74e41eb9c6aa65e2d5f3 (diff) | |
download | external_boringssl-a04d78d392463df4e69a64360c952ffa5abd22f7.zip external_boringssl-a04d78d392463df4e69a64360c952ffa5abd22f7.tar.gz external_boringssl-a04d78d392463df4e69a64360c952ffa5abd22f7.tar.bz2 |
Revert "external/boringssl: sync with upstream."
This reverts commit 1e4884f615b20946411a74e41eb9c6aa65e2d5f3.
This breaks some x86 builds.
Change-Id: I4d4310663ce52bc0a130e6b9dbc22b868ff4fb25
Diffstat (limited to 'src/ssl/s3_clnt.c')
-rw-r--r-- | src/ssl/s3_clnt.c | 811 |
1 files changed, 499 insertions, 312 deletions
diff --git a/src/ssl/s3_clnt.c b/src/ssl/s3_clnt.c index 559db72..d334e1d 100644 --- a/src/ssl/s3_clnt.c +++ b/src/ssl/s3_clnt.c @@ -148,26 +148,21 @@ * 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/dh.h> -#include <openssl/ec_key.h> -#include <openssl/ecdsa.h> +#include <openssl/rand.h> +#include <openssl/obj.h> #include <openssl/err.h> #include <openssl/evp.h> -#include <openssl/md5.h> #include <openssl/mem.h> -#include <openssl/obj.h> -#include <openssl/rand.h> +#include <openssl/md5.h> +#include <openssl/dh.h> +#include <openssl/bn.h> #include <openssl/x509.h> -#include <openssl/x509v3.h> #include "internal.h" #include "../crypto/dh/internal.h" @@ -222,8 +217,8 @@ int ssl3_connect(SSL *s) { /* don't push the buffering BIO quite yet */ - if (!ssl3_init_handshake_buffer(s)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + if (!ssl3_init_finished_mac(s)) { + OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR); ret = -1; goto end; } @@ -278,7 +273,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_VERIFY_SERVER_CERT; + s->state = SSL3_ST_CR_KEY_EXCH_A; } } else { skip = 1; @@ -287,16 +282,6 @@ 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); @@ -305,6 +290,13 @@ 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: @@ -364,7 +356,6 @@ 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; @@ -442,9 +433,11 @@ 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. */ - ret = tls1_record_handshake_hashes_for_channel_id(s); - if (ret <= 0) { - goto end; + if (s->s3->tlsext_channel_id_new) { + 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) && @@ -480,7 +473,7 @@ int ssl3_connect(SSL *s) { if (ret <= 0) { goto end; } - s->state = SSL3_ST_VERIFY_SERVER_CERT; + s->state = SSL3_ST_CR_KEY_EXCH_A; s->init_num = 0; break; @@ -543,16 +536,11 @@ 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; - if (is_initial_handshake) { - /* Renegotiations do not participate in session resumption. */ - ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); - } + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); ret = 1; /* s->server=0; */ @@ -564,7 +552,7 @@ int ssl3_connect(SSL *s) { goto end; default: - OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); + OPENSSL_PUT_ERROR(SSL, ssl3_connect, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } @@ -600,7 +588,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, SSL_R_WRONG_SSL_VERSION); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_WRONG_SSL_VERSION); goto err; } s->version = max_version; @@ -673,7 +661,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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR); goto err; } memcpy(p, s->session->session_id, i); @@ -683,7 +671,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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR); goto err; } *(p++) = s->d1->cookie_len; @@ -694,7 +682,8 @@ 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, SSL_R_NO_CIPHERS_AVAILABLE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, + SSL_R_NO_CIPHERS_AVAILABLE); goto err; } s2n(i, p); @@ -705,10 +694,15 @@ 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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR); goto err; } @@ -752,7 +746,8 @@ 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, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO); } return n; } @@ -766,14 +761,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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, 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, SSL_R_UNSUPPORTED_PROTOCOL); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, 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. */ @@ -788,7 +783,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, SSL_R_WRONG_SSL_VERSION); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION); al = SSL_AD_PROTOCOL_VERSION; goto f_err; } @@ -804,7 +799,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, + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); goto f_err; } @@ -825,7 +820,8 @@ int ssl3_get_server_hello(SSL *s) { if (c == NULL) { /* unknown cipher */ al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + SSL_R_UNKNOWN_CIPHER_RETURNED); goto f_err; } /* ct->mask_ssl was computed from client capabilities. Now @@ -841,7 +837,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, SSL_R_WRONG_CIPHER_RETURNED); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED); goto f_err; } @@ -849,46 +845,45 @@ 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, SSL_R_WRONG_CIPHER_RETURNED); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, 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, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + 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, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + 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, the handshake buffer may be released. */ - if (!SSL_USE_SIGALGS(s) || s->hit) { - ssl3_free_handshake_buffer(s); + * 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; } /* Only the NULL compression algorithm is supported. */ if (compression_method != 0) { al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); goto f_err; } /* TLS extensions */ if (!ssl_parse_serverhello_tlsext(s, &server_hello)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_PARSE_TLSEXT); goto err; } @@ -896,7 +891,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, SSL_R_BAD_PACKET_LENGTH); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_BAD_PACKET_LENGTH); goto f_err; } @@ -904,9 +899,11 @@ 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, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION); } else { - OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, + SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION); } goto f_err; } @@ -919,49 +916,12 @@ 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, ok, ret = -1; + int al, i, 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; @@ -978,15 +938,14 @@ int ssl3_get_server_certificate(SSL *s) { sk = sk_X509_new_null(); if (sk == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, 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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_LENGTH_MISMATCH); goto f_err; } @@ -994,45 +953,90 @@ 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, SSL_R_CERT_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, + 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, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_ASN1_LIB); goto f_err; } if (data != CBS_data(&certificate) + CBS_len(&certificate)) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, + SSL_R_CERT_LENGTH_MISMATCH); goto f_err; } if (!sk_X509_push(sk, x)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE); goto err; } x = NULL; } - X509 *leaf = sk_X509_value(sk, 0); - if (!ssl3_check_certificate_for_cipher(leaf, s->s3->tmp.new_cipher)) { - al = SSL_AD_ILLEGAL_PARAMETER; + 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); goto f_err; } + ERR_clear_error(); /* but we keep s->verify_result */ + + sc = ssl_sess_cert_new(); + if (sc == NULL) { + goto err; + } - /* 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; + 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); 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; + } + X509_free(sc->peer_cert); + sc->peer_cert = X509_up_ref(x); X509_free(s->session->peer); - s->session->peer = X509_up_ref(leaf); + s->session->peer = X509_up_ref(x); s->session->verify_result = s->verify_result; + x = NULL; ret = 1; if (0) { @@ -1071,14 +1075,25 @@ 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, SSL_R_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + SSL_R_UNEXPECTED_MESSAGE); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); return -1; } - /* In plain PSK ciphersuite, ServerKeyExchange may be omitted to send no - * identity hint. */ + /* In plain PSK ciphersuite, ServerKeyExchange can be + omitted if no identity hint is sent. Set session->sess_cert anyway to + avoid problems later.*/ 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); @@ -1092,6 +1107,18 @@ 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); @@ -1103,7 +1130,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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); goto f_err; } @@ -1117,14 +1144,16 @@ 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, SSL_R_DATA_LENGTH_TOO_LONG); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + ERR_R_MALLOC_FAILURE); goto f_err; } } @@ -1139,13 +1168,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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); goto f_err; } dh = DH_new(); if (dh == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_DH_LIB); goto err; } @@ -1153,17 +1182,22 @@ 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, ERR_R_BN_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB); goto err; } - 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); + if (DH_num_bits(dh) < 1024) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + SSL_R_BAD_DH_P_LENGTH); goto err; } - DH_free(s->s3->tmp.peer_dh_tmp); - s->s3->tmp.peer_dh_tmp = dh; + + if (alg_a & SSL_aRSA) { + pkey = X509_get_pubkey(s->session->sess_cert->peer_cert); + } + /* else anonymous DH, so no certificate or pkey. */ + + s->session->sess_cert->peer_dh_tmp = dh; dh = NULL; } else if (alg_k & SSL_kECDHE) { uint16_t curve_id; @@ -1176,21 +1210,22 @@ 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, SSL_R_WRONG_CURVE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, 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, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + 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, ERR_R_EC_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + ERR_R_EC_LIB); goto err; } @@ -1199,25 +1234,35 @@ 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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + 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, SSL_R_BAD_ECPOINT); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, 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|SSL_aECDSA)) { + pkey = X509_get_pubkey(s->session->sess_cert->peer_cert); + } else { + /* Otherwise this is ECDHE_PSK, so no public key. */ + assert(alg_a == SSL_aPSK); + } EC_KEY_set_public_key(ecdh, srvr_ecpoint); - EC_KEY_free(s->s3->tmp.peer_ecdh_tmp); - s->s3->tmp.peer_ecdh_tmp = ecdh; + s->session->sess_cert->peer_ecdh_tmp = ecdh; ecdh = NULL; BN_CTX_free(bn_ctx); bn_ctx = NULL; @@ -1225,7 +1270,8 @@ 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, SSL_R_UNEXPECTED_MESSAGE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + SSL_R_UNEXPECTED_MESSAGE); goto f_err; } @@ -1235,12 +1281,9 @@ 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)); - /* 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 it was signed, check the signature */ + if (pkey != NULL) { + CBS signature; if (SSL_USE_SIGALGS(s)) { if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) { @@ -1253,11 +1296,10 @@ 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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR); goto f_err; } @@ -1272,16 +1314,24 @@ int ssl3_get_server_key_exchange(SSL *s) { CBS_len(&signature))) { /* bad signature */ al = SSL_AD_DECRYPT_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE); goto f_err; } } else { - /* PSK ciphers are the only supported certificate-less ciphers. */ - assert(alg_a == SSL_aPSK); - + 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 */ if (CBS_len(&server_key_exchange) > 0) { al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, + SSL_R_EXTRA_DATA_IN_MESSAGE); goto f_err; } } @@ -1328,15 +1378,19 @@ 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 the handshake buffer as we won't be doing - * client auth. */ - ssl3_free_handshake_buffer(s); + /* 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; + } 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, SSL_R_WRONG_MESSAGE_TYPE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, + SSL_R_WRONG_MESSAGE_TYPE); goto err; } @@ -1344,14 +1398,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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, 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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR); goto err; } @@ -1363,10 +1417,16 @@ 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) || - !tls1_parse_peer_sigalgs(s, &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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR); + goto err; + } + + if (!tls1_process_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); goto err; } } @@ -1374,7 +1434,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, SSL_R_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_LENGTH_MISMATCH); goto err; } @@ -1383,7 +1443,8 @@ 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, SSL_R_CA_DN_TOO_LONG); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, + SSL_R_CA_DN_TOO_LONG); goto err; } @@ -1392,24 +1453,26 @@ 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, ERR_R_ASN1_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, 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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, 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, SSL_R_CA_DN_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, + SSL_R_CA_DN_LENGTH_MISMATCH); goto err; } if (!sk_X509_NAME_push(ca_sk, xn)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, + ERR_R_MALLOC_FAILURE); goto err; } } @@ -1453,9 +1516,18 @@ int ssl3_get_new_session_ticket(SSL *s) { OPENSSL_free(bytes); if (new_session == NULL) { /* This should never happen. */ - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_INTERNAL_ERROR); goto err; } + if (s->session->sess_cert != NULL) { + /* |sess_cert| is not serialized and must be duplicated explicitly. */ + assert(new_session->sess_cert == NULL); + new_session->sess_cert = ssl_sess_cert_dup(s->session->sess_cert); + if (new_session->sess_cert == NULL) { + SSL_SESSION_free(new_session); + goto err; + } + } SSL_SESSION_free(s->session); s->session = new_session; @@ -1468,13 +1540,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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, SSL_R_DECODE_ERROR); goto f_err; } if (!CBS_stow(&ticket, &s->session->tlsext_tick, &s->session->tlsext_ticklen)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_MALLOC_FAILURE); goto err; } @@ -1522,14 +1594,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, SSL_R_DECODE_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE); goto f_err; } return 1; @@ -1555,7 +1627,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, SSL_R_LENGTH_MISMATCH); + OPENSSL_PUT_ERROR(SSL, ssl3_get_server_done, SSL_R_LENGTH_MISMATCH); return -1; } @@ -1593,7 +1665,8 @@ int ssl3_send_client_key_exchange(SSL *s) { size_t identity_len; if (s->psk_client_callback == NULL) { - OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + SSL_R_PSK_NO_CLIENT_CB); goto err; } @@ -1602,24 +1675,28 @@ 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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_INTERNAL_ERROR); goto err; } else if (psk_len == 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + 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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_MALLOC_FAILURE); goto err; } @@ -1638,20 +1715,28 @@ 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_MALLOC_FAILURE); goto err; } - pkey = X509_get_pubkey(s->session->peer); + 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_cert); if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + 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); @@ -1671,7 +1756,8 @@ 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, SSL_R_BAD_RSA_ENCRYPT); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + SSL_R_BAD_RSA_ENCRYPT); goto err; } n += enc_pms_len; @@ -1688,23 +1774,32 @@ 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 (s->s3->tmp.peer_dh_tmp == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + 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); goto err; } - dh_srvr = s->s3->tmp.peer_dh_tmp; + dh_srvr = scert->peer_dh_tmp; /* generate a new random key */ dh_clnt = DHparams_dup(dh_srvr); if (dh_clnt == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB); goto err; } if (!DH_generate_key(dh_clnt)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB); DH_free(dh_clnt); goto err; } @@ -1712,14 +1807,15 @@ 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + 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, ERR_R_DH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB); DH_free(dh_clnt); goto err; } @@ -1737,53 +1833,64 @@ int ssl3_send_client_key_exchange(SSL *s) { EC_KEY *tkey; int field_size = 0, ecdh_len; - if (s->s3->tmp.peer_ecdh_tmp == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + 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; } - tkey = s->s3->tmp.peer_ecdh_tmp; + if (s->session->sess_cert->peer_ecdh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } + + tkey = s->session->sess_cert->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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_INTERNAL_ERROR); goto err; } clnt_ecdh = EC_KEY_new(); if (clnt_ecdh == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_MALLOC_FAILURE); goto err; } if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_EC_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB); goto err; } /* Generate a new ECDH key pair */ if (!EC_KEY_generate_key(clnt_ecdh)) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB); goto err; } field_size = EC_GROUP_get_degree(srvr_group); if (field_size <= 0) { - OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB); goto err; } pms_len = (field_size + 7) / 8; pms = OPENSSL_malloc(pms_len); if (pms == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + 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, ERR_R_ECDH_LIB); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB); goto err; } pms_len = ecdh_len; @@ -1797,7 +1904,8 @@ 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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_MALLOC_FAILURE); goto err; } @@ -1830,13 +1938,15 @@ int ssl3_send_client_key_exchange(SSL *s) { pms_len = psk_len; pms = OPENSSL_malloc(pms_len); if (pms == NULL) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + 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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_INTERNAL_ERROR); goto err; } @@ -1847,15 +1957,19 @@ int ssl3_send_client_key_exchange(SSL *s) { uint8_t *new_pms; size_t new_pms_len; - CBB_zero(&cbb); - if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len) || - !CBB_add_u16_length_prefixed(&cbb, &child) || + 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_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, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, + ERR_R_INTERNAL_ERROR); goto err; } OPENSSL_cleanse(pms, pms_len); @@ -1897,87 +2011,87 @@ err: } int ssl3_send_cert_verify(SSL *s) { - 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; - } + 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; - /* 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; - } + buf = (uint8_t *)s->init_buf->data; - /* The handshake buffer is no longer necessary. */ - ssl3_free_handshake_buffer(s); + if (s->state == SSL3_ST_CW_CERT_VRFY_A) { + p = ssl_handshake_start(s); + pkey = s->cert->key->privatekey; - /* 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; + /* 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; } + p += 2; + n += 2; + } - 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); + /* Compute the digest. */ + if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) { + goto err; } - if (sign_result == ssl_private_key_retry) { - s->state = SSL3_ST_CW_CERT_VRFY_B; - return -1; + /* The handshake buffer is no longer necessary. */ + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + goto err; } - s->rwstate = SSL_NOTHING; - if (sign_result != ssl_private_key_success) { - return -1; + + /* Sign the digest. */ + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + goto err; + } + + /* 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; + } + + 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 (!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; } s2n(signature_length, p); n += signature_length + 2; + if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) { - return -1; + goto err; } - s->state = SSL3_ST_CW_CERT_VRFY_C; + s->state = SSL3_ST_CW_CERT_VRFY_B; } + 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 *ssl) { - return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl); +static int ssl3_has_client_certificate(SSL *s) { + return s->cert && s->cert->key->x509 && s->cert->key->privatekey; } int ssl3_send_client_certificate(SSL *s) { @@ -2025,7 +2139,8 @@ int ssl3_send_client_certificate(SSL *s) { } } else if (i == 1) { i = 0; - OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + OPENSSL_PUT_ERROR(SSL, ssl3_send_client_certificate, + SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); } X509_free(x509); @@ -2042,7 +2157,11 @@ 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. */ - ssl3_free_handshake_buffer(s); + 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; + } } } @@ -2051,23 +2170,80 @@ int ssl3_send_client_certificate(SSL *s) { } if (s->state == SSL3_ST_CW_CERT_C) { - 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)) { + CERT_PKEY *cert_pkey = (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key; + if (!ssl3_output_cert_chain(s, cert_pkey)) { 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) { + long alg_k, alg_a; + 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; + + int cert_type = X509_certificate_type(sc->peer_cert, NULL); + if (cert_type & EVP_PK_EC) { + if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_cert, 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; + } + + /* Check that we have a certificate if we require one */ + if ((alg_a & SSL_aRSA) && !has_bits(cert_type, 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(cert_type, 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) && 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; @@ -2097,6 +2273,7 @@ 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; @@ -2118,48 +2295,72 @@ int ssl3_send_channel_id(SSL *s) { } s->rwstate = SSL_NOTHING; - 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); + if (s->s3->tlsext_channel_id_new) { + s2n(TLSEXT_TYPE_channel_id_new, d); + } else { + s2n(TLSEXT_TYPE_channel_id, d); + } s2n(TLSEXT_CHANNEL_ID_SIZE, d); EVP_MD_CTX_init(&md_ctx); - public_key_len = i2o_ECPublicKey(ec_key, NULL); + public_key_len = i2d_PublicKey(s->tlsext_channel_id_private, NULL); if (public_key_len <= 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY); + OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, + SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY); goto err; } - /* i2o_ECPublicKey will produce an ANSI X9.62 public key which, for a + /* i2d_PublicKey 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, SSL_R_CHANNEL_ID_NOT_P256); + OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_CHANNEL_ID_NOT_P256); goto err; } public_key = OPENSSL_malloc(public_key_len); if (!public_key) { - OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE); goto err; } derp = public_key; - i2o_ECPublicKey(ec_key, &derp); + i2d_PublicKey(s->tlsext_channel_id_private, &derp); - uint8_t digest[EVP_MAX_MD_SIZE]; - size_t digest_len; - if (!tls1_channel_id_hash(s, digest, &digest_len)) { + 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; + } + + if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, + SSL_R_EVP_DIGESTSIGNFINAL_FAILED); goto err; } - sig = ECDSA_do_sign(digest, digest_len, ec_key); + 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); + goto err; + } + + derp = der_sig; + sig = d2i_ECDSA_SIG(NULL, (const uint8_t **)&derp, sig_len); if (sig == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_D2I_ECDSA_SIG); goto err; } @@ -2168,7 +2369,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, ERR_R_INTERNAL_ERROR); + OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_INTERNAL_ERROR); goto err; } @@ -2196,17 +2397,3 @@ 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; -} |