File libgcrypt-FIPS-service-indicators.patch of Package libgcrypt.25788

Index: libgcrypt-1.9.4/src/fips.c
===================================================================
--- libgcrypt-1.9.4.orig/src/fips.c
+++ libgcrypt-1.9.4/src/fips.c
@@ -437,6 +437,54 @@ _gcry_fips_test_operational (void)
 }
 
 
+int
+_gcry_fips_indicator_cipher (va_list arg_ptr)
+{
+  enum gcry_cipher_algos alg = va_arg (arg_ptr, enum gcry_cipher_algos);
+  enum gcry_cipher_modes mode;
+
+  switch (alg)
+    {
+    case GCRY_CIPHER_AES:
+    case GCRY_CIPHER_AES192:
+    case GCRY_CIPHER_AES256:
+      mode = va_arg (arg_ptr, enum gcry_cipher_modes);
+      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_GCM:
+        case GCRY_CIPHER_MODE_XTS:
+          return GPG_ERR_NO_ERROR;
+        default:
+          return GPG_ERR_NOT_SUPPORTED;
+        }
+    default:
+      return GPG_ERR_NOT_SUPPORTED;
+    }
+}
+
+
+int
+_gcry_fips_indicator_kdf (va_list arg_ptr)
+{
+  enum gcry_kdf_algos alg = va_arg (arg_ptr, enum gcry_kdf_algos);
+
+  switch (alg)
+    {
+    case GCRY_KDF_PBKDF2:
+      return GPG_ERR_NO_ERROR;
+    default:
+      return GPG_ERR_NOT_SUPPORTED;
+    }
+}
+
+
 /* This is a test on whether the library is in the error or
    operational state. */
 int
Index: libgcrypt-1.9.4/src/g10lib.h
===================================================================
--- libgcrypt-1.9.4.orig/src/g10lib.h
+++ libgcrypt-1.9.4/src/g10lib.h
@@ -487,6 +487,9 @@ void _gcry_fips_signal_error (const char
            _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a))
 #endif
 
+int _gcry_fips_indicator_cipher (va_list arg_ptr);
+int _gcry_fips_indicator_kdf (va_list arg_ptr);
+
 int _gcry_fips_is_operational (void);
 
 /* Return true if the library is in the operational state.  */
Index: libgcrypt-1.9.4/src/gcrypt.h.in
===================================================================
--- libgcrypt-1.9.4.orig/src/gcrypt.h.in
+++ libgcrypt-1.9.4/src/gcrypt.h.in
@@ -334,7 +334,9 @@ enum gcry_ctl_cmds
     GCRYCTL_GET_TAGLEN = 76,
     GCRYCTL_REINIT_SYSCALL_CLAMP = 77,
     GCRYCTL_AUTO_EXPAND_SECMEM = 78,
-    GCRYCTL_SET_ALLOW_WEAK_KEY = 79
+    GCRYCTL_SET_ALLOW_WEAK_KEY = 79,
+    GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER = 81,
+    GCRYCTL_FIPS_SERVICE_INDICATOR_KDF = 82
   };
 
 /* Perform various operations defined by CMD. */
Index: libgcrypt-1.9.4/src/global.c
===================================================================
--- libgcrypt-1.9.4.orig/src/global.c
+++ libgcrypt-1.9.4/src/global.c
@@ -755,6 +755,19 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd,
       rc = _gcry_fips_run_selftests (1);
       break;
 
+    case GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER:
+      /* Get FIPS Service Indicator for a given symmetric algorithm and
+       * optional mode. Returns GPG_ERR_NO_ERROR if algorithm is allowed or
+       * GPG_ERR_NOT_SUPPORTED otherwise */
+      rc = _gcry_fips_indicator_cipher (arg_ptr);
+      break;
+
+    case GCRYCTL_FIPS_SERVICE_INDICATOR_KDF:
+      /* Get FIPS Service Indicator for a given KDF. Returns GPG_ERR_NO_ERROR
+       * if algorithm is allowed or GPG_ERR_NOT_SUPPORTED otherwise */
+      rc = _gcry_fips_indicator_kdf (arg_ptr);
+      break;
+
     case PRIV_CTL_INIT_EXTRNG_TEST:  /* Init external random test.  */
       rc = GPG_ERR_NOT_SUPPORTED;
       break;
Index: libgcrypt-1.9.4/tests/basic.c
===================================================================
--- libgcrypt-1.9.4.orig/tests/basic.c
+++ libgcrypt-1.9.4/tests/basic.c
@@ -6383,6 +6383,16 @@ do_check_ocb_cipher (int inplace)
       assert (tv[tidx].taglen <= ciphlen);
       assert (tv[tidx].taglen <= sizeof tag);
 
+      /* Verify the FIPS indicator marks this as non-approved */
+      if (in_fips_mode)
+        {
+          err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                              tv[tidx].algo, GCRY_CIPHER_MODE_OCB);
+          if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+            fail ("cipher-ocb, gcry_control did not fail as expected (tv %d): %s\n",
+                  tidx, gpg_strerror (err));
+        }
+
       err = gcry_cipher_open (&hde, tv[tidx].algo, GCRY_CIPHER_MODE_OCB, 0);
       if (!err)
         err = gcry_cipher_open (&hdd, tv[tidx].algo, GCRY_CIPHER_MODE_OCB, 0);
@@ -6644,6 +6654,16 @@ check_ocb_cipher_largebuf_split (int alg
       memcpy(inbuf + i, hash, 16);
     }
 
+  /* Verify the FIPS indicator marks this as non-approved */
+  if (in_fips_mode)
+    {
+      err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                          algo, GCRY_CIPHER_MODE_OCB);
+      if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+        fail ("cipher-ocb, gcry_control did not fail as expected (large, algo %d): %s\n",
+              algo, gpg_strerror (err));
+    }
+
   err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0);
   if (!err)
     err = gcry_cipher_open (&hdd, algo, GCRY_CIPHER_MODE_OCB, 0);
@@ -6842,7 +6862,17 @@ check_ocb_cipher_checksum (int algo, int
       blk[byteidx] |= 1 << bitpos;
     }
 
-  err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0);
+  /* Verify the FIPS indicator marks this as non-approved */
+  if (in_fips_mode)
+    {
+      err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                          algo, GCRY_CIPHER_MODE_OCB);
+      if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+        fail ("cipher-ocb, gcry_control did not fail as expected (checksum, algo %d): %s\n",
+              algo, gpg_strerror (err));
+    }
+
+ err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0);
   if (!err)
     err = gcry_cipher_open (&hde2, algo, GCRY_CIPHER_MODE_OCB, 0);
   if (!err)
@@ -7110,6 +7140,16 @@ check_ocb_cipher_splitaad (void)
       aad[2] = tv[tidx].aad2? hex2buffer (tv[tidx].aad2, aadlen+2) : NULL;
       aad[3] = tv[tidx].aad3? hex2buffer (tv[tidx].aad3, aadlen+3) : NULL;
 
+      /* Verify the FIPS indicator marks this as non-approved */
+      if (in_fips_mode)
+        {
+          err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                              GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB);
+          if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+            fail ("cipher-ocb-splitaad, gcry_control did not fail as expected: %s\n",
+                  gpg_strerror (err));
+        }
+
       err = gcry_cipher_open (&hde, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB, 0);
       if (err)
         {
@@ -9044,6 +9084,17 @@ check_bulk_cipher_modes (void)
         fprintf (stderr, "    checking bulk encryption for %s [%i], mode %d\n",
 		 gcry_cipher_algo_name (tv[i].algo),
 		 tv[i].algo, tv[i].mode);
+
+      /* Verify the FIPS indicator marks approved cipher/modes combinations */
+      if (in_fips_mode)
+        {
+          err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                              tv[i].algo, tv[i].mode);
+          if (gpg_err_code (err) != GPG_ERR_NO_ERROR)
+            fail ("gcry_control unexpectedly failed for algo = %s, mode = %d : %s\n",
+                 gcry_cipher_algo_name (tv[i].algo), tv[i].mode, gpg_strerror (err));
+        }
+
       err = gcry_cipher_open (&hde, tv[i].algo, tv[i].mode, 0);
       if (!err)
         err = gcry_cipher_open (&hdd, tv[i].algo, tv[i].mode, 0);
Index: libgcrypt-1.9.4/doc/gcrypt.texi
===================================================================
--- libgcrypt-1.9.4.orig/doc/gcrypt.texi
+++ libgcrypt-1.9.4/doc/gcrypt.texi
@@ -961,6 +961,19 @@ been registered with Libgpg-error and ad
 clamp again.  Obviously this control code may only be used before a
 second thread is started in a process.
 
+@item GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER; Arguments: enum gcry_cipher_algos [, enum gcry_cipher_modes]
+
+Check if the given symmetric cipher and optional cipher mode combination
+is approved under the current FIPS 140-3 certification. If the
+combination is approved, this function returns @code{GPG_ERR_NO_ERROR}.
+Otherwise @code{GPG_ERR_NOT_SUPPORTED} is returned.
+
+@item GCRYCTL_FIPS_SERVICE_INDICATOR_KDF; Arguments: enum gcry_kdf_algos
+
+Check if the given KDF is approved under the current FIPS 140-3
+certification. If the KDF is approved, this function returns
+@code{GPG_ERR_NO_ERROR}. Otherwise @code{GPG_ERR_NOT_SUPPORTED}
+is returned.
 
 @end table
 
@@ -980,7 +993,7 @@ descriptive message to the user and canc
 
 Some error values do not indicate a system error or an error in the
 operation, but the result of an operation that failed properly.  For
-example, if you try to decrypt a tempered message, the decryption will
+example, if you try to decrypt a tampered message, the decryption will
 fail.  Another error value actually means that the end of a data
 buffer or list has been reached.  The following descriptions explain
 for many error codes what they mean usually.  Some error values have
@@ -6320,25 +6333,6 @@ The following symmetric encryption algor
 power-up:
 
 @table @asis
-@item 3DES
-To test the 3DES 3-key EDE encryption in ECB mode these tests are
-run:
-@enumerate
-@item
-A known answer test is run on a 64 bit test vector processed by 64
-rounds of Single-DES block encryption and decryption using a key
-changed with each round.
-@item
-A known answer test is run on a 64 bit test vector processed by 16
-rounds of 2-key and 3-key Triple-DES block encryption and decryptions
-using a key changed with each round.
-@item
-10 known answer tests using 3-key Triple-DES EDE encryption, comparing
-the ciphertext to the known value, then running a decryption and
-comparing it to the initial plaintext.
-@end enumerate
-(@code{cipher/des.c:selftest})
-
 @item AES-128
 A known answer tests is run using one test vector and one test
 key with AES in ECB mode. (@code{cipher/rijndael.c:selftest_basic_128})
@@ -6394,6 +6388,9 @@ A known answer test using 28 byte of dat
 @item HMAC SHA-512
 A known answer test using 28 byte of data and a 4 byte key is run.
 (@code{cipher/hmac-tests.c:selftests_sha512})
+@item CMAC AES
+A known answer test using 40 byte of data and a 16 byte key is run.
+(@code{cipher/mac-cmac.c:selftests_cmac_aes})
 @end table
 
 @subsection Random Number Power-Up Test
@@ -6416,7 +6413,7 @@ The public key algorithms are tested dur
 
 @table @asis
 @item RSA
-A pre-defined 1024 bit RSA key is used and these tests are run
+A pre-defined 2048 bit RSA key is used and these tests are run
 in turn:
 @enumerate
 @item
@@ -6426,14 +6423,14 @@ Conversion of S-expression to internal f
 Private key consistency check.
 (@code{cipher/@/rsa.c:@/selftests_rsa})
 @item
-A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-1.
+A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-256.
 The result is verified using the public key against the original data
-and against modified data.  (@code{cipher/@/rsa.c:@/selftest_sign_1024})
+and against modified data.  (@code{cipher/@/rsa.c:@/selftest_sign_2048})
 @item
-A 1000 bit random value is encrypted and checked that it does not
-match the original random value.  The encrypted result is then
+A predefined 66 byte value is encrypted and checked that it matches
+reference encyrpted message.  The encrypted result is then
 decrypted and checked that it matches the original random value.
-(@code{cipher/@/rsa.c:@/selftest_encr_1024})
+(@code{cipher/@/rsa.c:@/selftest_encr_2048})
 @end enumerate
 
 @item DSA
@@ -6463,15 +6461,6 @@ of the same name but with a single dot a
 @file{.hmac}.
 
 
-@subsection Critical Functions Power-Up Tests
-
-The 3DES weak key detection is tested during power-up by calling the
-detection function with keys taken from a table listening all weak
-keys.  The table itself is protected using a SHA-1 hash.
-(@code{cipher/@/des.c:@/selftest})
-
-
-
 @c --------------------------------
 @section Conditional Tests
 
@@ -6645,8 +6634,6 @@ If Libgcrypt is used in FIPS mode these
 The cryptographic algorithms are restricted to this list:
 
 @table @asis
-@item GCRY_CIPHER_3DES
-3 key EDE Triple-DES symmetric encryption.
 @item GCRY_CIPHER_AES128
 AES 128 bit symmetric encryption.
 @item GCRY_CIPHER_AES192
@@ -6673,6 +6660,8 @@ HMAC using a SHA-256 message digest.
 HMAC using a SHA-384 message digest.
 @item GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC
 HMAC using a SHA-512 message digest.
+@item GCRY_MAC_CMAC_AES
+CMAC using a AES key.
 @item GCRY_PK_RSA
 RSA encryption and signing.
 @item GCRY_PK_DSA
@@ -6683,8 +6672,8 @@ Note that the CRC algorithms are not con
 and thus are in addition available.
 
 @item
-RSA key generation refuses to create a key with a keysize of
-less than 1024 bits.
+RSA key generation refuses to create and uyse ea key with a keysize of
+less than 2048 bits.
 
 @item
 DSA key generation refuses to create a key with a keysize other
@@ -6697,8 +6686,9 @@ The @code{transient-key} flag for RSA an
 Support for the VIA Padlock engine is disabled.
 
 @item
-FIPS mode may only be used on systems with a /dev/random device.
-Switching into FIPS mode on other systems will fail at runtime.
+FIPS mode may only be used on systems with a /dev/random device or
+with a getentropy syscall. Switching into FIPS mode on other systems
+will fail at runtime.
 
 @item
 Saving and loading a random seed file is ignored.
@@ -6731,11 +6721,15 @@ disables FIPS mode unless Enforced FIPS
 Libgcrypt will enter the error state.
 
 @item
+The signatures using SHA-1 digest algorithm may not be used.
+
+@item
 In Enforced FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is
 ignored.  In standard FIPS mode it disables FIPS mode.
 
 @item
 A handler set by @code{gcry_set_outofcore_handler} is ignored.
+
 @item
 A handler set by @code{gcry_set_fatalerror_handler} is ignored.
 
openSUSE Build Service is sponsored by