From 72ceb6a6923456d9ff036cd81014024cf54280c4 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Fri, 16 Jun 2017 19:23:47 +0100 Subject: [PATCH] Convert key exchange to one shot call Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/3585) --- ssl/statem/statem_clnt.c | 27 ++++++++++++++++----------- ssl/statem/statem_lib.c | 18 ++++++++++++++++++ ssl/statem/statem_locl.h | 2 ++ ssl/statem/statem_srvr.c | 27 +++++++++++++++------------ 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 9629c1068a..46439359fb 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2170,6 +2170,9 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) PACKET params; int maxsig; const EVP_MD *md = NULL; + unsigned char *tbs; + size_t tbslen; + int rv; /* * |pkt| now points to the beginning of the signature, so the difference @@ -2185,7 +2188,6 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) if (SSL_USE_SIGALGS(s)) { unsigned int sigalg; - int rv; if (!PACKET_get_net_2(pkt, &sigalg)) { al = SSL_AD_DECODE_ERROR; @@ -2255,19 +2257,22 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) goto err; } } - if (EVP_DigestVerifyUpdate(md_ctx, &(s->s3->client_random[0]), - SSL3_RANDOM_SIZE) <= 0 - || EVP_DigestVerifyUpdate(md_ctx, &(s->s3->server_random[0]), - SSL3_RANDOM_SIZE) <= 0 - || EVP_DigestVerifyUpdate(md_ctx, PACKET_data(¶ms), - PACKET_remaining(¶ms)) <= 0) { + tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(¶ms), + PACKET_remaining(¶ms)); + if (tbslen == 0) { al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB); + SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto err; } - if (EVP_DigestVerifyFinal(md_ctx, PACKET_data(&signature), - PACKET_remaining(&signature)) <= 0) { - /* bad signature */ + + rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature), + PACKET_remaining(&signature), tbs, tbslen); + OPENSSL_free(tbs); + if (rv < 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB); + goto err; + } else if (rv == 0) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE); goto err; diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 539cc71521..abdeb56a30 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -2132,3 +2132,21 @@ int construct_ca_names(SSL *s, WPACKET *pkt) return 1; } + +/* Create a buffer containing data to be signed for server key exchange */ +size_t construct_key_exchange_tbs(const SSL *s, unsigned char **ptbs, + const void *param, size_t paramlen) +{ + size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen; + unsigned char *tbs = OPENSSL_malloc(tbslen); + + if (tbs == NULL) + return 0; + memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE); + memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE); + + memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen); + + *ptbs = tbs; + return tbslen; +} diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h index 673822a7c5..b6ce4cc965 100644 --- a/ssl/statem/statem_locl.h +++ b/ssl/statem/statem_locl.h @@ -63,6 +63,8 @@ int check_in_list(SSL *s, unsigned int group_id, const unsigned char *groups, int create_synthetic_message_hash(SSL *s); int parse_ca_names(SSL *s, PACKET *pkt, int *al); int construct_ca_names(SSL *s, WPACKET *pkt); +size_t construct_key_exchange_tbs(const SSL *s, unsigned char **ptbs, + const void *param, size_t paramlen); /* * TLS/DTLS client state machine functions diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 1cde8c83d2..6168b98ede 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -2410,9 +2410,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) /* not anonymous */ if (lu != NULL) { EVP_PKEY *pkey = s->s3->tmp.cert->privatekey; - const EVP_MD *md = ssl_md(lu->hash_idx); - unsigned char *sigbytes1, *sigbytes2; - size_t siglen; + const EVP_MD *md; + unsigned char *sigbytes1, *sigbytes2, *tbs; + size_t siglen, tbslen; + int rv; if (pkey == NULL || md == NULL) { /* Should never happen */ @@ -2456,15 +2457,17 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) goto f_err; } } - if (EVP_DigestSignUpdate(md_ctx, &(s->s3->client_random[0]), - SSL3_RANDOM_SIZE) <= 0 - || EVP_DigestSignUpdate(md_ctx, &(s->s3->server_random[0]), - SSL3_RANDOM_SIZE) <= 0 - || EVP_DigestSignUpdate(md_ctx, - s->init_buf->data + paramoffset, - paramlen) <= 0 - || EVP_DigestSignFinal(md_ctx, sigbytes1, &siglen) <= 0 - || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) + tbslen = construct_key_exchange_tbs(s, &tbs, + s->init_buf->data + paramoffset, + paramlen); + if (tbslen == 0) { + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_MALLOC_FAILURE); + goto f_err; + } + rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen); + OPENSSL_free(tbs); + if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2) || sigbytes1 != sigbytes2) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); -- 2.25.1