File libgcrypt-FIPS-SLI-mark-non-compliant-cipher-modes-as-non-approved-in-the-SLI.patch of Package libgcrypt.37939

Index: libgcrypt-1.10.3/cipher/cipher.c
===================================================================
--- libgcrypt-1.10.3.orig/cipher/cipher.c
+++ libgcrypt-1.10.3/cipher/cipher.c
@@ -490,6 +490,26 @@ _gcry_cipher_open (gcry_cipher_hd_t *han
   return rc;
 }
 
+int
+_gcry_cipher_is_mode_fips_compliant(int mode)
+{
+  switch (mode)
+    {
+    case GCRY_CIPHER_MODE_ECB:
+    case GCRY_CIPHER_MODE_CBC:
+    case GCRY_CIPHER_MODE_CFB:
+    case GCRY_CIPHER_MODE_CFB8:
+    case GCRY_CIPHER_MODE_OFB:
+    case GCRY_CIPHER_MODE_CTR:
+    case GCRY_CIPHER_MODE_CCM:
+    case GCRY_CIPHER_MODE_XTS:
+    case GCRY_CIPHER_MODE_AESWRAP:
+      return GPG_ERR_NO_ERROR;
+    default:
+      return GPG_ERR_NOT_SUPPORTED;
+    }
+}
+
 
 gcry_err_code_t
 _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
@@ -509,14 +529,25 @@ _gcry_cipher_open_internal (gcry_cipher_
     err = GPG_ERR_CIPHER_ALGO;
   else if (spec->flags.disabled)
     err = GPG_ERR_CIPHER_ALGO;
-  else if (!spec->flags.fips && fips_mode ())
+  else if (fips_mode ())
     {
-      if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER))
-        err = GPG_ERR_CIPHER_ALGO;
-      else
+      if (!spec->flags.fips)
+        {
+          if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER))
+            err = GPG_ERR_CIPHER_ALGO;
+          else
+            {
+              fips_service_indicator_mark_non_compliant ();
+              err = 0;
+            }
+        }
+      else if ((err = _gcry_cipher_is_mode_fips_compliant(mode)))
         {
-          fips_service_indicator_mark_non_compliant ();
-          err = 0;
+          if (!fips_check_rejection (GCRY_FIPS_FLAG_REJECT_CIPHER_MODE))
+            {
+              fips_service_indicator_mark_non_compliant ();
+              err = 0;
+            }
         }
     }
   else
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
@@ -606,27 +606,41 @@ check_cipher_o_s_e_d_c (int reject)
 {
   static struct {
     int algo;
+    int mode;
     const char *key;
     int keylen;
+    const char *tag;
+    int taglen;
     const char *expect;
     int expect_failure;
   } 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 },
-#endif
-      { GCRY_CIPHER_AES,
-	"\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
-        "\x5c\x71\xd8\x5d\x26\x5e\xcd\xb5\x95\x40\x41\xab\xff\x25\x6f\xd1" }
+   { GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_ECB,
+	 "\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,
+     "", -1,
+     "\x3f\x1a\xb8\x83\x18\x8b\xb5\x97", 1 },
+#endif
+   { GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB,
+	 "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+     "", -1,
+     "\x5c\x71\xd8\x5d\x26\x5e\xcd\xb5\x95\x40\x41\xab\xff\x25\x6f\xd1" },
+   { GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_SIV,
+	 "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
+	 "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 32,
+     "\x51\x66\x54\xc4\xe1\xb5\xd9\x37\x31\x52\xdb\xea\x35\x10\x8b\x7b", 16,
+     "\x83\x69\xf6\xf3\x20\xff\xa2\x72\x31\x67\x15\xcf\xf4\x75\x01\x9a", 1 }
   };
+
   const char *pt = "Shohei Ohtani 2024: 54 HR, 59 SB";
   int ptlen;
   int tvidx;
   unsigned char out[MAX_DATA_LEN];
   gpg_error_t err;
 
+  unsigned char tag[16];
+  size_t taglen = 0;
+
   ptlen = strlen (pt);
   assert (ptlen == 32);
   for (tvidx=0; tvidx < DIM(tv); tvidx++)
@@ -640,10 +654,12 @@ check_cipher_o_s_e_d_c (int reject)
                  tvidx);
 
       blklen = gcry_cipher_get_algo_blklen (tv[tvidx].algo);
+
       assert (blklen != 0);
       assert (blklen <= ptlen);
       assert (blklen <= DIM (out));
-      err = gcry_cipher_open (&h, tv[tvidx].algo, GCRY_CIPHER_MODE_ECB, 0);
+      assert (tv[tvidx].taglen <= 16);
+      err = gcry_cipher_open (&h, tv[tvidx].algo, tv[tvidx].mode, 0);
       if (err)
         {
           if (in_fips_mode && reject && tv[tvidx].expect_failure)
@@ -694,6 +710,18 @@ check_cipher_o_s_e_d_c (int reject)
           continue;
         }
 
+      if (tv[tvidx].taglen >= 0)
+        {
+          err = gcry_cipher_info (h, GCRYCTL_GET_TAGLEN, NULL, &taglen);
+          if (err)
+              fail ("gcry_cipher_info %d failed: %s\n", tvidx,
+                    gpg_strerror (err));
+
+          if (taglen != tv[tvidx].taglen)
+              fail ("gcry_cipher_info %d failed: taglen mismatch %d != %ld\n", tvidx,
+                    tv[tvidx].taglen, taglen);
+        }
+
       err = gcry_cipher_encrypt (h, out, MAX_DATA_LEN, pt, blklen);
       if (err)
         {
@@ -714,6 +742,35 @@ check_cipher_o_s_e_d_c (int reject)
           putc ('\n', stderr);
         }
 
+      if (tv[tvidx].taglen >= 0)
+        {
+           err = gcry_cipher_gettag (h, tag, tv[tvidx].taglen);
+           if (err)
+              fail ("gcry_cipher_gettag %d failed: %s", tvidx,
+                     gpg_strerror(err));
+
+          if (memcmp (tv[tvidx].tag, tag, tv[tvidx].taglen))
+            {
+              int i;
+
+              fail ("gcry_cipher_gettag %d: tag mismatch\n", tvidx);
+              fputs ("got:", stderr);
+              for (i=0; i < 16 ; i++)
+                fprintf (stderr, " %02x", tag[i]);
+              putc ('\n', stderr);
+            }
+
+          err = gcry_cipher_reset (h);
+          if (err)
+            fail("gcry_cipher_reset %d failed: %s", tvidx,
+                  gpg_strerror(err));
+
+          err = gcry_cipher_set_decryption_tag (h, tag, 16);
+          if (err)
+            fail ("gcry_cipher_set_decryption_tag %d failed: %s\n", tvidx<
+                   gpg_strerror (err));
+      }
+
       err = gcry_cipher_decrypt (h, out, blklen, NULL, 0);
       if (err)
         {
@@ -1483,6 +1540,7 @@ main (int argc, char **argv)
 
   xgcry_control ((GCRYCTL_FIPS_REJECT_NON_FIPS,
                   (GCRY_FIPS_FLAG_REJECT_MD_MD5
+                   | GCRY_FIPS_FLAG_REJECT_CIPHER_MODE
                    | GCRY_FIPS_FLAG_REJECT_PK_MD
                    | GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2
                    | GCRY_FIPS_FLAG_REJECT_COMPAT110)));
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
@@ -1805,6 +1805,7 @@ char *gcry_get_config (int mode, const c
 #define GCRY_FIPS_FLAG_REJECT_PK            (1 << 5)
 #define GCRY_FIPS_FLAG_REJECT_PK_MD         (1 << 6)
 #define GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2   (1 << 7)
+#define GCRY_FIPS_FLAG_REJECT_CIPHER_MODE   (1 << 8)
 
 #define GCRY_FIPS_FLAG_REJECT_MD \
   (GCRY_FIPS_FLAG_REJECT_MD_MD5 | GCRY_FIPS_FLAG_REJECT_MD_OTHERS)
openSUSE Build Service is sponsored by