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