File libgcrypt-FIPS-HMAC-short-keylen.patch of Package libgcrypt

From 76aad97dd312e83f2f9b8d086553f2b72ab6546f Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Wed, 19 Jan 2022 11:41:40 +0900
Subject: [PATCH 2/2] fips: Reject shorter key for HMAC in FIPS mode.

* cipher/md.c (prepare_macpads): Reject < 112-bit key.
* cipher/kdf.c (selftest_pbkdf2): Remove selftest cases with shorter
key.
* cipher/mac-hmac.c (selftests_sha224, selftests_sha256): Likewise.
(selftests_sha384, selftests_sha512, selftests_sha3): Likewise.
* tests/basic.c (check_one_hmac) Handle an error when shorter key
is rejected.
(check_one_mac): Likewise.
* tests/t-kdf.c (check_pbkdf2, check_scrypt): Likewise.

--

GnuPG-bug-id: 5512
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
---
 cipher/kdf.c      | 76 ++---------------------------------------------
 cipher/mac-hmac.c | 67 -----------------------------------------
 cipher/md.c       |  3 ++
 tests/basic.c     | 29 +++++++++++++++---
 tests/t-kdf.c     | 38 ++++++++++++++++++++----
 5 files changed, 62 insertions(+), 151 deletions(-)

Index: libgcrypt-1.9.4/cipher/kdf.c
===================================================================
--- libgcrypt-1.9.4.orig/cipher/kdf.c
+++ libgcrypt-1.9.4/cipher/kdf.c
@@ -324,6 +324,10 @@ check_one (int algo, int hash_algo,
   unsigned char key[512]; /* hardcoded to avoid allocation */
   size_t keysize = expectlen;
 
+  /* Skip test with shoter passphrase in FIPS mode.  */
+  if (fips_mode () && passphraselen < 14)
+    return NULL;
+
   if (keysize > sizeof(key))
     return "invalid tests data";
 
Index: libgcrypt-1.9.4/cipher/mac-hmac.c
===================================================================
--- libgcrypt-1.9.4.orig/cipher/mac-hmac.c
+++ libgcrypt-1.9.4/cipher/mac-hmac.c
@@ -241,6 +241,11 @@ check_one (int algo,
   const unsigned char *digest;
 
 /*   printf ("HMAC algo %d\n", algo); */
+
+  /* Skip test with shoter key in FIPS mode.  */
+  if (fips_mode () && keylen < 14)
+    return NULL;
+
   if (trunc)
     {
       if (_gcry_md_get_algo_dlen (algo) < expectlen)
Index: libgcrypt-1.9.4/cipher/md.c
===================================================================
--- libgcrypt-1.9.4.orig/cipher/md.c
+++ libgcrypt-1.9.4/cipher/md.c
@@ -903,6 +903,9 @@ prepare_macpads (gcry_md_hd_t a, const u
 {
   GcryDigestEntry *r;
 
+  if (fips_mode () && keylen < 14)
+    return GPG_ERR_INV_VALUE;
+
   if (!a->ctx->list)
     return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled.  */
 
Index: libgcrypt-1.9.4/tests/basic.c
===================================================================
--- libgcrypt-1.9.4.orig/tests/basic.c
+++ libgcrypt-1.9.4/tests/basic.c
@@ -12016,7 +12016,19 @@ check_one_hmac (int algo, const char *da
       return;
     }
 
-  gcry_md_setkey( hd, key, keylen );
+  err = gcry_md_setkey( hd, key, keylen );
+  if (err)
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr,
+                     "  shorter key (%d) rejected correctly in fips mode\n",
+                     keylen);
+        }
+      gcry_md_close (hd);
+      return;
+    }
 
   gcry_md_write (hd, data, datalen);
 
@@ -12420,9 +12432,18 @@ check_one_mac (int algo, const char *dat
   clutter_vector_registers();
   err = gcry_mac_setkey (hd, key, keylen);
   if (err)
-    fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err));
-  if (err)
-    goto out;
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr,
+                     "  shorter key (%d) rejected correctly in fips mode\n",
+                     keylen);
+        }
+      else
+        fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err));
+      goto out;
+    }
 
   if (ivlen && iv)
     {
Index: libgcrypt-1.9.4/tests/t-kdf.c
===================================================================
--- libgcrypt-1.9.4.orig/tests/t-kdf.c
+++ libgcrypt-1.9.4/tests/t-kdf.c
@@ -31,6 +31,8 @@
 #define PGM "t-kdf"
 #include "t-common.h"
 
+static int in_fips_mode;
+
 
 static void
 dummy_consumer (volatile char *buffer, size_t buflen)
@@ -858,8 +860,7 @@ check_openpgp (void)
       if (tv[tvidx].disabled)
         continue;
       /* MD5 isn't supported in fips mode */
-      if (gcry_fips_mode_active()
-          && tv[tvidx].hashalgo == GCRY_MD_MD5)
+      if (in_fips_mode && tv[tvidx].hashalgo == GCRY_MD_MD5)
         continue;
       if (verbose)
         fprintf (stderr, "checking S2K test vector %d\n", tvidx);
@@ -1104,7 +1105,7 @@ check_pbkdf2 (void)
                              GCRY_KDF_PBKDF2, tv[tvidx].hashalgo,
                              tv[tvidx].salt, tv[tvidx].saltlen,
                              tv[tvidx].c, tv[tvidx].dklen, outbuf);
-      if (gcry_fips_mode_active() && tvidx > 6)
+      if (in_fips_mode && tvidx > 6)
         {
           if (!err)
             fail ("pbkdf2 test %d unexpectedly passed in FIPS mode: %s\n",
@@ -1112,7 +1113,17 @@ check_pbkdf2 (void)
           continue;
         }
       if (err)
-        fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err));
+        {
+          if (in_fips_mode && tv[tvidx].plen < 14)
+            {
+              if (verbose)
+                fprintf (stderr,
+                         "  shorter key (%u) rejected correctly in fips mode\n",
+                         (unsigned int)tv[tvidx].plen);
+            }
+          else
+            fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err));
+        }
       else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen))
         {
           fail ("pbkdf2 test %d failed: mismatch\n", tvidx);
@@ -1209,7 +1220,17 @@ check_scrypt (void)
                              tv[tvidx].salt, tv[tvidx].saltlen,
                              tv[tvidx].parm_p, tv[tvidx].dklen, outbuf);
       if (err)
-        fail ("scrypt test %d failed: %s\n", tvidx, gpg_strerror (err));
+        {
+          if (in_fips_mode && tv[tvidx].plen < 14)
+            {
+              if (verbose)
+                fprintf (stderr,
+                         "  shorter key (%u) rejected correctly in fips mode\n",
+                         (unsigned int)tv[tvidx].plen);
+            }
+          else
+            fail ("scrypt test %d failed: %s\n", tvidx, gpg_strerror (err));
+        }
       else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen))
         {
           fail ("scrypt test %d failed: mismatch\n", tvidx);
@@ -1281,7 +1302,12 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  if (!in_fips_mode)
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+
   xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
     xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
openSUSE Build Service is sponsored by