Convert key exchange to one shot call
authorDr. Stephen Henson <steve@openssl.org>
Fri, 16 Jun 2017 18:23:47 +0000 (19:23 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 21 Jun 2017 13:11:01 +0000 (14:11 +0100)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3585)

ssl/statem/statem_clnt.c
ssl/statem/statem_lib.c
ssl/statem/statem_locl.h
ssl/statem/statem_srvr.c

index 9629c10..4643935 100644 (file)
@@ -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(&params),
-                                          PACKET_remaining(&params)) <= 0) {
+        tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(&params),
+                                            PACKET_remaining(&params));
+        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;
index 539cc71..abdeb56 100644 (file)
@@ -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;
+}
index 673822a..b6ce4cc 100644 (file)
@@ -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
index 1cde8c8..6168b98 100644 (file)
@@ -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);