summaryrefslogtreecommitdiffstats
path: root/src/ssl/s3_clnt.c
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2015-09-25 00:37:00 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-09-25 00:37:00 +0000
commit00bc53f6f4436972b7a8dcf2c1e5fd0ad7515872 (patch)
treedc62c249d595198e0d99e43890019d21e901fbec /src/ssl/s3_clnt.c
parent3781a60670f92c3c6fca860cb4589495cefa2e56 (diff)
parenta04d78d392463df4e69a64360c952ffa5abd22f7 (diff)
downloadexternal_boringssl-00bc53f6f4436972b7a8dcf2c1e5fd0ad7515872.zip
external_boringssl-00bc53f6f4436972b7a8dcf2c1e5fd0ad7515872.tar.gz
external_boringssl-00bc53f6f4436972b7a8dcf2c1e5fd0ad7515872.tar.bz2
am a04d78d3: Revert "external/boringssl: sync with upstream."
* commit 'a04d78d392463df4e69a64360c952ffa5abd22f7': Revert "external/boringssl: sync with upstream."
Diffstat (limited to 'src/ssl/s3_clnt.c')
-rw-r--r--src/ssl/s3_clnt.c811
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(&parameter, 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;
-}