[openssl] master update

Matt Caswell matt at openssl.org
Mon Jan 6 10:55:28 UTC 2020


The branch master has been updated
       via  b1558c0bc895afd93170378053bae800efacee1e (commit)
      from  60a3399721a48931b137ae4d966a9ef4b6a85d11 (commit)


- Log -----------------------------------------------------------------
commit b1558c0bc895afd93170378053bae800efacee1e
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: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10747)

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

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 6d4d24d77b..a94550a37a 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 788721ef1f..d6fd4f39e0 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 893e6169b4..a4a9c849b9 100644
--- a/test/hmactest.c
+++ b/test/hmactest.c
@@ -169,6 +169,27 @@ static int test_hmac_run(void)
     if (!TEST_str_eq(p, 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, 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, test[6].digest))
+        goto err;
+
     ret = 1;
 err:
     HMAC_CTX_free(ctx);


More information about the openssl-commits mailing list