File libgcrypt-FIPS-SLI-Rejection-by-GCRYCTL_FIPS_REJECT_NON_FIPS-not-by-open-flags.patch of Package libgcrypt.38414

From d060dd58b82882dec0d8bfcc593536bc0083b4b1 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Fri, 20 Dec 2024 09:38:13 +0900
Subject: [PATCH 24/24] fips: Rejection by GCRYCTL_FIPS_REJECT_NON_FIPS, not by
 open flags.

* src/gcrypt.h.in (GCRY_CIPHER_FLAG_REJECT_NON_FIPS): Remove.
(GCRY_MD_FLAG_REJECT_NON_FIPS): Remove.
(GCRY_MAC_FLAG_REJECT_NON_FIPS): Remove.
* tests/t-fips-service-ind.c: Update tests with
GCRYCTL_FIPS_REJECT_NON_FIPS.
* cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey): Use
fips_check_rejection.
* cipher/mac.c (mac_open): Likewise.
* cipher/md.c (struct gcry_md_context): Remove reject_non_fips.
(md_open, md_enable): Use fips_check_rejection.
(_gcry_md_enable, md_copy): Likewise.

--

GnuPG-bug-id: 7338
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mulling <lucas.mulling@suse.com>
---
 cipher/cipher.c            |  8 ++--
 cipher/mac.c               |  5 +--
 cipher/md.c                | 81 ++++++++++++++++++++++++++++++--------
 src/gcrypt.h.in            |  7 +---
 tests/t-fips-service-ind.c | 59 +++++++++++----------------
 5 files changed, 94 insertions(+), 66 deletions(-)

Index: libgcrypt-1.10.3/cipher/cipher.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/cipher.c
+++ libgcrypt-1.10.3/cipher/cipher.c
@@ -496,7 +496,6 @@ _gcry_cipher_open_internal (gcry_cipher_
 			    int algo, int mode, unsigned int flags)
 {
   int secure = !!(flags & GCRY_CIPHER_SECURE);
-  int reject_non_fips = !!(flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS);
   gcry_cipher_spec_t *spec;
   gcry_cipher_hd_t h = NULL;
   gcry_err_code_t err;
@@ -512,7 +511,7 @@ _gcry_cipher_open_internal (gcry_cipher_
     err = GPG_ERR_CIPHER_ALGO;
   else if (!spec->flags.fips && fips_mode ())
     {
-      if (reject_non_fips)
+      if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER))
         err = GPG_ERR_CIPHER_ALGO;
       else
         {
@@ -530,8 +529,7 @@ _gcry_cipher_open_internal (gcry_cipher_
 		     | GCRY_CIPHER_ENABLE_SYNC
 		     | GCRY_CIPHER_CBC_CTS
 		     | GCRY_CIPHER_CBC_MAC
-                     | GCRY_CIPHER_EXTENDED
-                     | GCRY_CIPHER_FLAG_REJECT_NON_FIPS))
+                     | GCRY_CIPHER_EXTENDED))
 	  || ((flags & GCRY_CIPHER_CBC_CTS) && (flags & GCRY_CIPHER_CBC_MAC))))
     err = GPG_ERR_CIPHER_ALGO;
 
@@ -762,7 +760,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte
 	     Key Generation Requirements" for details.  */
 	  if (buf_eq_const (key, key + keylen, keylen))
             {
-              if ((c->flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS))
+              if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER))
                 return GPG_ERR_WEAK_KEY;
               else
                 fips_service_indicator_mark_non_compliant ();
Index: libgcrypt-1.10.3/cipher/mac.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/mac.c
+++ libgcrypt-1.10.3/cipher/mac.c
@@ -487,7 +487,6 @@ mac_open (gcry_mac_hd_t * hd, int algo,
   gcry_err_code_t err;
   gcry_mac_hd_t h;
   int secure = !!(flags & GCRY_MAC_FLAG_SECURE);
-  int reject_non_fips = !!(flags & GCRY_MAC_FLAG_REJECT_NON_FIPS);
 
   spec = spec_from_algo (algo);
   if (!spec)
@@ -496,7 +495,7 @@ mac_open (gcry_mac_hd_t * hd, int algo,
     return GPG_ERR_MAC_ALGO;
   else if (!spec->flags.fips && fips_mode ())
     {
-      if (reject_non_fips)
+      if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MAC))
         return GPG_ERR_MAC_ALGO;
       else
         fips_service_indicator_mark_non_compliant ();
@@ -618,7 +617,7 @@ _gcry_mac_open (gcry_mac_hd_t * h, int a
   gcry_err_code_t rc;
   gcry_mac_hd_t hd = NULL;
 
-  if ((flags & ~(GCRY_MAC_FLAG_SECURE | GCRY_MAC_FLAG_REJECT_NON_FIPS)))
+  if ((flags & ~GCRY_MAC_FLAG_SECURE))
     rc = GPG_ERR_INV_ARG;
   else
     rc = mac_open (&hd, algo, flags, ctx);
Index: libgcrypt-1.10.3/cipher/md.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/md.c
+++ libgcrypt-1.10.3/cipher/md.c
@@ -266,7 +266,6 @@ struct gcry_md_context
     unsigned int finalized:1;
     unsigned int bugemu1:1;
     unsigned int hmac:1;
-    unsigned int reject_non_fips:1;
   } flags;
   size_t actual_handle_size;     /* Allocated size of this handle. */
   FILE  *debug;
@@ -500,7 +499,6 @@ md_open (gcry_md_hd_t *h, int algo, unsi
       ctx->flags.secure = secure;
       ctx->flags.hmac = hmac;
       ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
-      ctx->flags.reject_non_fips = !!(flags & GCRY_MD_FLAG_REJECT_NON_FIPS);
     }
 
   if (! err)
@@ -535,14 +533,11 @@ _gcry_md_open (gcry_md_hd_t *h, int algo
 
   if ((flags & ~(GCRY_MD_FLAG_SECURE
                  | GCRY_MD_FLAG_HMAC
-                 | GCRY_MD_FLAG_REJECT_NON_FIPS
                  | GCRY_MD_FLAG_BUGEMU1)))
     rc = GPG_ERR_INV_ARG;
   else
     rc = md_open (&hd, algo, flags);
 
-  *h = rc? NULL : hd;
-
   if (!rc && fips_mode ())
     {
       GcryDigestEntry *entry = hd->ctx->list;
@@ -557,9 +552,26 @@ _gcry_md_open (gcry_md_hd_t *h, int algo
         }
 
       if (!is_compliant_algo)
-        fips_service_indicator_mark_non_compliant ();
+        {
+          int reject = 0;
+
+          if (algo == GCRY_MD_MD5)
+            reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+          else
+            reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+
+          if (reject)
+            {
+              md_close (hd);
+              hd = NULL;
+              rc = GPG_ERR_DIGEST_ALGO;
+            }
+          else
+            fips_service_indicator_mark_non_compliant ();
+        }
     }
 
+  *h = rc? NULL : hd;
   return rc;
 }
 
@@ -572,12 +584,17 @@ md_enable (gcry_md_hd_t hd, int algorith
   const gcry_md_spec_t *spec;
   GcryDigestEntry *entry;
   gcry_err_code_t err = 0;
-  int reject_non_fips = h->flags.reject_non_fips;
+  int reject;
 
   for (entry = h->list; entry; entry = entry->next)
     if (entry->spec->algo == algorithm)
       return 0; /* Already enabled */
 
+  if (algorithm == GCRY_MD_MD5)
+    reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+  else
+    reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+
   spec = spec_from_algo (algorithm);
   if (!spec)
     {
@@ -589,7 +606,7 @@ md_enable (gcry_md_hd_t hd, int algorith
     err = GPG_ERR_DIGEST_ALGO;
 
   /* Any non-FIPS algorithm should go this way */
-  if (!err && reject_non_fips && !spec->flags.fips && fips_mode ())
+  if (!err && reject && !spec->flags.fips && fips_mode ())
     err = GPG_ERR_DIGEST_ALGO;
 
   if (!err && h->flags.hmac && spec->read == NULL)
@@ -648,7 +665,19 @@ _gcry_md_enable (gcry_md_hd_t hd, int al
         }
 
       if (!is_compliant_algo)
-        fips_service_indicator_mark_non_compliant ();
+        {
+          int reject = 0;
+
+          if (algorithm == GCRY_MD_MD5)
+            reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+          else
+            reject = fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+
+          if (reject)
+            rc = GPG_ERR_DIGEST_ALGO;
+          else
+            fips_service_indicator_mark_non_compliant ();
+        }
     }
 
   return rc;
@@ -658,13 +687,14 @@ _gcry_md_enable (gcry_md_hd_t hd, int al
 static gcry_err_code_t
 md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
 {
-  gcry_err_code_t err = 0;
+  gcry_err_code_t rc = 0;
   struct gcry_md_context *a = ahd->ctx;
   struct gcry_md_context *b;
   GcryDigestEntry *ar, *br;
   gcry_md_hd_t bhd;
   size_t n;
   int is_compliant_algo = 1;
+  int reject = 0;
 
   if (ahd->bufpos)
     md_write (ahd, NULL, 0);
@@ -677,7 +707,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t
 
   if (!bhd)
     {
-      err = gpg_err_code_from_syserror ();
+      rc = gpg_err_code_from_syserror ();
       goto leave;
     }
 
@@ -706,12 +736,20 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t
         br = xtrymalloc (ar->actual_struct_size);
       if (!br)
         {
-          err = gpg_err_code_from_syserror ();
+          rc = gpg_err_code_from_syserror ();
           md_close (bhd);
           goto leave;
         }
 
-      is_compliant_algo &= spec->flags.fips;
+      if (!spec->flags.fips)
+        {
+          is_compliant_algo = 0;
+
+          if (spec->algo == GCRY_MD_MD5)
+            reject |= fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_MD5);
+          else
+            reject |= fips_check_rejection (GCRY_FIPS_FLAG_REJECT_MD_OTHERS);
+        }
 
       memcpy (br, ar, ar->actual_struct_size);
       br->next = b->list;
@@ -721,13 +759,22 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t
   if (a->debug)
     md_start_debug (bhd, "unknown");
 
-  *b_hd = bhd;
+  if (!is_compliant_algo && fips_mode ())
+    {
+      if (reject)
+        {
+          rc = GPG_ERR_DIGEST_ALGO;
+          md_close (bhd);
+        }
+      else
+        fips_service_indicator_mark_non_compliant ();
+    }
 
-  if (!is_compliant_algo)
-    fips_service_indicator_mark_non_compliant ();
+  if (!rc)
+    *b_hd = bhd;
 
  leave:
-  return err;
+  return rc;
 }
 
 
Index: libgcrypt-1.10.3/src/gcrypt.h.in
===================================================================
--- libgcrypt-1.10.3.orig/src/gcrypt.h.in
+++ libgcrypt-1.10.3/src/gcrypt.h.in
@@ -990,8 +990,7 @@ enum gcry_cipher_flags
     GCRY_CIPHER_ENABLE_SYNC = 2,  /* Enable CFB sync mode. */
     GCRY_CIPHER_CBC_CTS     = 4,  /* Enable CBC cipher text stealing (CTS). */
     GCRY_CIPHER_CBC_MAC     = 8,  /* Enable CBC message auth. code (MAC).  */
-    GCRY_CIPHER_EXTENDED    = 16, /* Enable extended AES-WRAP.  */
-    GCRY_CIPHER_FLAG_REJECT_NON_FIPS = 32 /* Reject non-FIPS-compliant algo.  */
+    GCRY_CIPHER_EXTENDED    = 16  /* Enable extended AES-WRAP.  */
   };
 
 /* GCM works only with blocks of 128 bits */
@@ -1298,7 +1297,6 @@ enum gcry_md_flags
   {
     GCRY_MD_FLAG_SECURE = 1,  /* Allocate all buffers in "secure" memory.  */
     GCRY_MD_FLAG_HMAC   = 2,  /* Make an HMAC out of this algorithm.  */
-    GCRY_MD_FLAG_REJECT_NON_FIPS = 4,  /* Reject non-FIPS-compliant algo.  */
     GCRY_MD_FLAG_BUGEMU1 = 0x0100
   };
 
@@ -1521,8 +1519,7 @@ enum gcry_mac_algos
 /* Flags used with the open function.  */
 enum gcry_mac_flags
   {
-    GCRY_MAC_FLAG_SECURE = 1,  /* Allocate all buffers in "secure" memory.  */
-    GCRY_MAC_FLAG_REJECT_NON_FIPS = 2   /* Reject non-FIPS-compliant algo.  */
+    GCRY_MAC_FLAG_SECURE = 1  /* Allocate all buffers in "secure" memory.  */
   };
 
 /* Create a MAC handle for algorithm ALGO.  FLAGS may be given as an bitwise OR
Index: libgcrypt-1.10.3/tests/t-fips-service-ind.c
===================================================================
--- libgcrypt-1.10.3.orig/tests/t-fips-service-ind.c
+++ libgcrypt-1.10.3/tests/t-fips-service-ind.c
@@ -250,7 +250,7 @@ check_pk_hash_sign_verify (void)
 /* Check gcry_cipher_open, gcry_cipher_setkey, gcry_cipher_encrypt,
    gcry_cipher_decrypt, gcry_cipher_close API.  */
 static void
-check_cipher_o_s_e_d_c (void)
+check_cipher_o_s_e_d_c (int reject)
 {
   static struct {
     int algo;
@@ -258,18 +258,12 @@ check_cipher_o_s_e_d_c (void)
     int keylen;
     const char *expect;
     int expect_failure;
-    unsigned int flags;
   } tv[] = {
 #if USE_DES
       { GCRY_CIPHER_3DES,
 	"\xe3\x34\x7a\x6b\x0b\xc1\x15\x2c\x64\x2a\x25\xcb\xd3\xbc\x31\xab"
 	"\xfb\xa1\x62\xa8\x1f\x19\x7c\x15", 24,
         "\x3f\x1a\xb8\x83\x18\x8b\xb5\x97", 1 },
-      { GCRY_CIPHER_3DES,
-	"\xe3\x34\x7a\x6b\x0b\xc1\x15\x2c\x64\x2a\x25\xcb\xd3\xbc\x31\xab"
-	"\xfb\xa1\x62\xa8\x1f\x19\x7c\x15", 24,
-        "\x3f\x1a\xb8\x83\x18\x8b\xb5\x97",
-        1, GCRY_CIPHER_FLAG_REJECT_NON_FIPS },
 #endif
       { GCRY_CIPHER_AES,
 	"\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
@@ -297,12 +291,10 @@ check_cipher_o_s_e_d_c (void)
       assert (blklen != 0);
       assert (blklen <= ptlen);
       assert (blklen <= DIM (out));
-      err = gcry_cipher_open (&h, tv[tvidx].algo, GCRY_CIPHER_MODE_ECB,
-                              tv[tvidx].flags);
+      err = gcry_cipher_open (&h, tv[tvidx].algo, GCRY_CIPHER_MODE_ECB, 0);
       if (err)
         {
-          if (in_fips_mode && (tv[tvidx].flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS)
-              && tv[tvidx].expect_failure)
+          if (in_fips_mode && reject && tv[tvidx].expect_failure)
             /* Here, an error is expected */
             ;
           else
@@ -312,8 +304,7 @@ check_cipher_o_s_e_d_c (void)
         }
       else
         {
-          if (in_fips_mode && (tv[tvidx].flags & GCRY_CIPHER_FLAG_REJECT_NON_FIPS)
-              && tv[tvidx].expect_failure)
+          if (in_fips_mode && reject && tv[tvidx].expect_failure)
             /* This case, an error is expected, but we observed success */
             fail ("gcry_cipher_open test %d unexpectedly succeeded\n", tvidx);
         }
@@ -398,7 +389,7 @@ check_cipher_o_s_e_d_c (void)
 /* Check gcry_mac_open, gcry_mac_write, gcry_mac_write, gcry_mac_read,
    gcry_mac_close API.  */
 static void
-check_mac_o_w_r_c (void)
+check_mac_o_w_r_c (int reject)
 {
   static struct {
     int algo;
@@ -408,14 +399,10 @@ check_mac_o_w_r_c (void)
     int keylen;
     const char *expect;
     int expect_failure;
-    unsigned int flags;
   } tv[] = {
 #if USE_MD5
     { GCRY_MAC_HMAC_MD5, "hmac input abc", 14, "hmac key input", 14,
       "\x0d\x72\xd0\x60\xaf\x34\xf2\xca\x33\x58\xa9\xcc\xd3\x5a\xac\xb5", 1 },
-    { GCRY_MAC_HMAC_MD5, "hmac input abc", 14, "hmac key input", 14,
-      "\x0d\x72\xd0\x60\xaf\x34\xf2\xca\x33\x58\xa9\xcc\xd3\x5a\xac\xb5", 1,
-      GCRY_MAC_FLAG_REJECT_NON_FIPS },
 #endif
 #if USE_SHA1
     { GCRY_MAC_HMAC_SHA1, "hmac input abc", 14, "hmac key input", 14,
@@ -471,11 +458,10 @@ check_mac_o_w_r_c (void)
       expectlen = gcry_mac_get_algo_maclen (tv[tvidx].algo);
       assert (expectlen != 0);
       assert (expectlen <= DIM (mac));
-      err = gcry_mac_open (&h, tv[tvidx].algo, tv[tvidx].flags, NULL);
+      err = gcry_mac_open (&h, tv[tvidx].algo, 0, NULL);
       if (err)
         {
-          if (in_fips_mode && (tv[tvidx].flags & GCRY_MAC_FLAG_REJECT_NON_FIPS)
-              && tv[tvidx].expect_failure)
+          if (in_fips_mode && reject && tv[tvidx].expect_failure)
             /* Here, an error is expected */
             ;
           else
@@ -485,8 +471,7 @@ check_mac_o_w_r_c (void)
         }
       else
         {
-          if (in_fips_mode && (tv[tvidx].flags & GCRY_MAC_FLAG_REJECT_NON_FIPS)
-              && tv[tvidx].expect_failure)
+          if (in_fips_mode && reject && tv[tvidx].expect_failure)
             /* This case, an error is expected, but we observed success */
             fail ("gcry_mac_open test %d unexpectedly succeeded\n", tvidx);
         }
@@ -563,7 +548,7 @@ check_mac_o_w_r_c (void)
 /* Check gcry_md_open, gcry_md_write, gcry_md_write, gcry_md_read,
    gcry_md_close API.  */
 static void
-check_md_o_w_r_c (void)
+check_md_o_w_r_c (int reject)
 {
   static struct {
     int algo;
@@ -571,14 +556,10 @@ check_md_o_w_r_c (void)
     int datalen;
     const char *expect;
     int expect_failure;
-    unsigned int flags;
   } tv[] = {
 #if USE_MD5
     { GCRY_MD_MD5, "abc", 3,
       "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72", 1 },
-    { GCRY_MD_MD5, "abc", 3,
-      "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72", 1,
-      GCRY_MD_FLAG_REJECT_NON_FIPS },
 #endif
 #if USE_SHA1
     { GCRY_MD_SHA1, "abc", 3,
@@ -632,11 +613,10 @@ check_md_o_w_r_c (void)
 
       expectlen = gcry_md_get_algo_dlen (tv[tvidx].algo);
       assert (expectlen != 0);
-      err = gcry_md_open (&h, tv[tvidx].algo, tv[tvidx].flags);
+      err = gcry_md_open (&h, tv[tvidx].algo, 0);
       if (err)
         {
-          if (in_fips_mode && (tv[tvidx].flags & GCRY_MD_FLAG_REJECT_NON_FIPS)
-              && tv[tvidx].expect_failure)
+          if (in_fips_mode && reject && tv[tvidx].expect_failure)
             /* Here, an error is expected */
             ;
           else
@@ -646,8 +626,7 @@ check_md_o_w_r_c (void)
         }
       else
         {
-          if (in_fips_mode && (tv[tvidx].flags & GCRY_MD_FLAG_REJECT_NON_FIPS)
-              && tv[tvidx].expect_failure)
+          if (in_fips_mode && reject && tv[tvidx].expect_failure)
             /* This case, an error is expected, but we observed success */
             fail ("gcry_md_open test %d unexpectedly succeeded\n", tvidx);
         }
@@ -1143,10 +1122,18 @@ main (int argc, char **argv)
   check_kdf_derive ();
   check_hash_buffer ();
   check_hash_buffers ();
-  check_md_o_w_r_c ();
-  check_mac_o_w_r_c ();
-  check_cipher_o_s_e_d_c ();
+  check_md_o_w_r_c (0);
+  check_mac_o_w_r_c (0);
+  check_cipher_o_s_e_d_c (0);
   check_pk_hash_sign_verify ();
 
+  xgcry_control ((GCRYCTL_FIPS_REJECT_NON_FIPS,
+                  (GCRY_FIPS_FLAG_REJECT_MD_MD5
+                   | GCRY_FIPS_FLAG_REJECT_COMPAT110)));
+
+  check_md_o_w_r_c (1);
+  check_mac_o_w_r_c (1);
+  check_cipher_o_s_e_d_c (1);
+
   return !!error_count;
 }
openSUSE Build Service is sponsored by