[openssl] OpenSSL_1_1_1-stable update

Matt Caswell matt at openssl.org
Tue Jan 7 11:57:14 UTC 2020


The branch OpenSSL_1_1_1-stable has been updated
       via  16d92fa873975b2a32d3ea01b7d63c64f7fd9ee7 (commit)
      from  0fcc6e70bc8970c4aee5e55d517aa1cc522a3ee8 (commit)


- Log -----------------------------------------------------------------
commit 16d92fa873975b2a32d3ea01b7d63c64f7fd9ee7
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jan 3 09:37:19 2020 +0000

    Don't store an HMAC key for longer than we need
    
    The HMAC_CTX structure stores the original key in case the ctx is reused
    without changing the key.
    
    However, HMAC_Init_ex() checks its parameters such that the only code path
    where the stored key is ever used is in the case where HMAC_Init_ex is
    called with a NULL key and an explicit md is provided which is the same as
    the md that was provided previously. But in that case we can actually reuse
    the pre-digested key that we calculated last time, so we can refactor the
    code not to use the stored key at all.
    
    With that refactor done it is no longer necessary to store the key in the
    ctx at all. This means that long running ctx's will not keep the key in
    memory for any longer than required. Note though that the digested key
    *is* still kept in memory for the duration of the life of the ctx.
    
    Fixes #10743
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10763)

-----------------------------------------------------------------------

Summary of changes:
 crypto/hmac/hmac.c       | 40 +++++++++++++++++++---------------------
 crypto/hmac/hmac_local.h |  2 --
 test/hmactest.c          | 21 +++++++++++++++++++++
 3 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c
index 51dd91237c..bc49b26ab1 100644
--- a/crypto/hmac/hmac.c
+++ b/crypto/hmac/hmac.c
@@ -18,16 +18,17 @@
 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
                  const EVP_MD *md, ENGINE *impl)
 {
-    int rv = 0;
-    int i, j, reset = 0;
+    int rv = 0, reset = 0;
+    int i, j;
     unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE];
+    unsigned int keytmp_length;
+    unsigned char keytmp[HMAC_MAX_MD_CBLOCK_SIZE];
 
     /* If we are changing MD then we must have a key */
     if (md != NULL && md != ctx->md && (key == NULL || len < 0))
         return 0;
 
     if (md != NULL) {
-        reset = 1;
         ctx->md = md;
     } else if (ctx->md) {
         md = ctx->md;
@@ -44,35 +45,34 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
 
     if (key != NULL) {
         reset = 1;
+
         j = EVP_MD_block_size(md);
-        if (!ossl_assert(j <= (int)sizeof(ctx->key)))
+        if (!ossl_assert(j <= (int)sizeof(keytmp)))
             return 0;
         if (j < len) {
             if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl)
                     || !EVP_DigestUpdate(ctx->md_ctx, key, len)
-                    || !EVP_DigestFinal_ex(ctx->md_ctx, ctx->key,
-                                           &ctx->key_length))
+                    || !EVP_DigestFinal_ex(ctx->md_ctx, keytmp,
+                                           &keytmp_length))
                 return 0;
         } else {
-            if (len < 0 || len > (int)sizeof(ctx->key))
+            if (len < 0 || len > (int)sizeof(keytmp))
                 return 0;
-            memcpy(ctx->key, key, len);
-            ctx->key_length = len;
+            memcpy(keytmp, key, len);
+            keytmp_length = len;
         }
-        if (ctx->key_length != HMAC_MAX_MD_CBLOCK_SIZE)
-            memset(&ctx->key[ctx->key_length], 0,
-                   HMAC_MAX_MD_CBLOCK_SIZE - ctx->key_length);
-    }
+        if (keytmp_length != HMAC_MAX_MD_CBLOCK_SIZE)
+            memset(&keytmp[keytmp_length], 0,
+                   HMAC_MAX_MD_CBLOCK_SIZE - keytmp_length);
 
-    if (reset) {
         for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
-            pad[i] = 0x36 ^ ctx->key[i];
+            pad[i] = 0x36 ^ keytmp[i];
         if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl)
                 || !EVP_DigestUpdate(ctx->i_ctx, pad, EVP_MD_block_size(md)))
             goto err;
 
         for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
-            pad[i] = 0x5c ^ ctx->key[i];
+            pad[i] = 0x5c ^ keytmp[i];
         if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl)
                 || !EVP_DigestUpdate(ctx->o_ctx, pad, EVP_MD_block_size(md)))
             goto err;
@@ -81,8 +81,10 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
         goto err;
     rv = 1;
  err:
-    if (reset)
+    if (reset) {
+        OPENSSL_cleanse(keytmp, sizeof(keytmp));
         OPENSSL_cleanse(pad, sizeof(pad));
+    }
     return rv;
 }
 
@@ -149,8 +151,6 @@ static void hmac_ctx_cleanup(HMAC_CTX *ctx)
     EVP_MD_CTX_reset(ctx->o_ctx);
     EVP_MD_CTX_reset(ctx->md_ctx);
     ctx->md = NULL;
-    ctx->key_length = 0;
-    OPENSSL_cleanse(ctx->key, sizeof(ctx->key));
 }
 
 void HMAC_CTX_free(HMAC_CTX *ctx)
@@ -201,8 +201,6 @@ int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
         goto err;
     if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx))
         goto err;
-    memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK_SIZE);
-    dctx->key_length = sctx->key_length;
     dctx->md = sctx->md;
     return 1;
  err:
diff --git a/crypto/hmac/hmac_local.h b/crypto/hmac/hmac_local.h
index ed855e89a4..1f40e01a59 100644
--- a/crypto/hmac/hmac_local.h
+++ b/crypto/hmac/hmac_local.h
@@ -18,8 +18,6 @@ struct hmac_ctx_st {
     EVP_MD_CTX *md_ctx;
     EVP_MD_CTX *i_ctx;
     EVP_MD_CTX *o_ctx;
-    unsigned int key_length;
-    unsigned char key[HMAC_MAX_MD_CBLOCK_SIZE];
 };
 
 #endif
diff --git a/test/hmactest.c b/test/hmactest.c
index ca775773a6..e12c48fd8d 100644
--- a/test/hmactest.c
+++ b/test/hmactest.c
@@ -173,6 +173,27 @@ static int test_hmac_run(void)
     if (!TEST_str_eq(p, (char *)test[6].digest))
         goto err;
 
+    /* Test reusing a key */
+    if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL))
+        || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
+        || !TEST_true(HMAC_Final(ctx, buf, &len)))
+        goto err;
+    p = pt(buf, len);
+    if (!TEST_str_eq(p, (char *)test[6].digest))
+        goto err;
+
+    /*
+     * Test reusing a key where the digest is provided again but is the same as
+     * last time
+     */
+    if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL))
+        || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len))
+        || !TEST_true(HMAC_Final(ctx, buf, &len)))
+        goto err;
+    p = pt(buf, len);
+    if (!TEST_str_eq(p, (char *)test[6].digest))
+        goto err;
+
     ret = 1;
 err:
     HMAC_CTX_free(ctx);


More information about the openssl-commits mailing list