File libgcrypt-FIPS-SLI-Check-DATA-in-gcry_pk_sign-verify-in-FIPS-mode.patch of Package libgcrypt.38414

From 53c97483b17fee280e24f595bc0d82d9b362ffde Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 26 Dec 2024 11:12:48 +0900
Subject: [PATCH 3/3] fips,ecc: Check DATA in gcry_pk_sign/verify in FIPS mode.

* src/gcrypt.h.in (GCRY_FIPS_FLAG_REJECT_PK_MD): New.
(GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2): New.

* cipher/ecc.c (ecc_sign): Check if GOST or SM2.  Check if hash is
compliant.
(ecc_verify): Likewise.
* tests/t-fips-service-ind.c (check_pk_s_v): Modify tests including
hash compliance.

--

GnuPG-bug-id: 7338
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mulling <lucas.mulling@suse.com>
---
 cipher/ecc.c               | 70 +++++++++++++++++++++++++++++++++++---
 src/gcrypt.h.in            |  4 ++-
 tests/t-fips-service-ind.c | 52 ++++++++++++++++++++--------
 3 files changed, 107 insertions(+), 19 deletions(-)

diff --git a/cipher/ecc.c b/cipher/ecc.c
index 8896afd0..525523ed 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -941,6 +941,18 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if (rc)
     goto leave;
 
+  if (fips_mode ()
+      && ((ctx.flags & PUBKEY_FLAG_GOST) || (ctx.flags & PUBKEY_FLAG_SM2)))
+    {
+      if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2))
+        {
+          rc = GPG_ERR_INV_DATA;
+          goto leave;
+        }
+      else
+        fips_service_indicator_mark_non_compliant ();
+    }
+
   /* Hash algo is determined by curve in EdDSA.  */
   if ((ctx.flags & PUBKEY_FLAG_EDDSA))
     {
@@ -953,10 +965,12 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
                       && ctx.hash_algo != GCRY_MD_SHAKE256)))
             {
               if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
-                rc = GPG_ERR_DIGEST_ALGO;
+                {
+                  rc = GPG_ERR_DIGEST_ALGO;
+                  goto leave;
+                }
               else
                 fips_service_indicator_mark_non_compliant ();
-              goto leave;
             }
         }
       else
@@ -967,6 +981,23 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
             ctx.hash_algo = GCRY_MD_SHAKE256;
         }
     }
+  else
+    {
+      if (fips_mode ())
+        {
+          if (_gcry_md_algo_info (ctx.hash_algo, GCRYCTL_TEST_ALGO, NULL, NULL)
+              || ctx.hash_algo == GCRY_MD_SHA1)
+            {
+              if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_MD))
+                {
+                  rc = GPG_ERR_DIGEST_ALGO;
+                  goto leave;
+                }
+              else
+                fips_service_indicator_mark_non_compliant ();
+            }
+        }
+    }
 
   sig_r = mpi_new (0);
   sig_s = mpi_new (0);
@@ -1066,6 +1097,18 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   if (DBG_CIPHER)
     log_mpidump ("ecc_verify data", data);
 
+  if (fips_mode ()
+      && ((ctx.flags & PUBKEY_FLAG_GOST) || (ctx.flags & PUBKEY_FLAG_SM2)))
+    {
+      if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2))
+        {
+          rc = GPG_ERR_INV_DATA;
+          goto leave;
+        }
+      else
+        fips_service_indicator_mark_non_compliant ();
+    }
+
   /* Hash algo is determined by curve in EdDSA.  */
   if ((ctx.flags & PUBKEY_FLAG_EDDSA))
     {
@@ -1078,10 +1121,12 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
                       && ctx.hash_algo != GCRY_MD_SHAKE256)))
             {
               if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK))
-                rc = GPG_ERR_DIGEST_ALGO;
+                {
+                  rc = GPG_ERR_DIGEST_ALGO;
+                  goto leave;
+                }
               else
                 fips_service_indicator_mark_non_compliant ();
-              goto leave;
             }
         }
       else
@@ -1092,6 +1137,23 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
             ctx.hash_algo = GCRY_MD_SHAKE256;
         }
     }
+  else
+    {
+      if (fips_mode ())
+        {
+          if (_gcry_md_algo_info (ctx.hash_algo, GCRYCTL_TEST_ALGO, NULL, NULL)
+              || ctx.hash_algo == GCRY_MD_SHA1)
+            {
+              if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_MD))
+                {
+                  rc = GPG_ERR_DIGEST_ALGO;
+                  goto leave;
+                }
+              else
+                fips_service_indicator_mark_non_compliant ();
+            }
+        }
+    }
 
   /*
    * Extract the signature value.
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 7bee45e9..fcb6a327 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1986,11 +1986,13 @@ char *gcry_get_config (int mode, const char *what);
 #define GCRY_FIPS_FLAG_REJECT_MAC           (1 << 3)
 #define GCRY_FIPS_FLAG_REJECT_CIPHER        (1 << 4)
 #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_MD \
   (GCRY_FIPS_FLAG_REJECT_MD_MD5 | GCRY_FIPS_FLAG_REJECT_MD_OTHERS)
 
-/* Note: Don't reject MD5 */
+/* Note: Don't reject MD5, PK MD, PK GOST and PK SM2 */
 #define GCRY_FIPS_FLAG_REJECT_COMPAT110 \
   (GCRY_FIPS_FLAG_REJECT_MD_OTHERS      \
    | GCRY_FIPS_FLAG_REJECT_MAC          \
diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c
index 90d92c70..fe963fa5 100644
--- a/tests/t-fips-service-ind.c
+++ b/tests/t-fips-service-ind.c
@@ -228,6 +228,7 @@ check_pk_s_v (int reject)
   static struct {
     const char *prvkey;
     const char *pubkey;
+    const char *data;
     int expect_failure;
   } tv[] = {
     {
@@ -236,6 +237,8 @@ check_pk_s_v (int reject)
       "(public-key (ecc (curve nistp256)"
       " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83"
       "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))",
+      "(data (flags raw)(hash sha256 "
+      "#00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F#))",
       0
     },
     {                           /* non-compliant curve */
@@ -244,28 +247,40 @@ check_pk_s_v (int reject)
       "(public-key (ecc (curve secp256k1)"
       " (q #046fcc37ea5e9e09fec6c83e5fbd7a745e3eee81d16ebd861c9e66f55518c19798"
       "4e9f113c07f875691df8afc1029496fc4cb9509b39dcd38f251a83359cc8b4f7#)))",
+      "(data (flags raw)(hash sha256 "
+      "#00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F#))",
       1
-    }
+    },
+    {                           /* non-compliant hash */
+      "(private-key (ecc (curve nistp256)"
+      " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))",
+      "(public-key (ecc (curve nistp256)"
+      " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83"
+      "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))",
+      "(data (flags raw)(hash ripemd160 "
+      "#00112233445566778899AABBCCDDEEFF00010203#))",
+      1
+    },
+    {                           /* non-compliant hash for signing */
+      "(private-key (ecc (curve nistp256)"
+      " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))",
+      "(public-key (ecc (curve nistp256)"
+      " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83"
+      "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))",
+      "(data (flags raw)(hash sha1 "
+      "#00112233445566778899AABBCCDDEEFF00010203#))",
+      1
+    },
   };
   int tvidx;
   gpg_error_t err;
   gpg_err_code_t ec;
-  const char *data = "(data (flags raw)"
-    "(hash sha256 #00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F#))";
-  gcry_sexp_t s_data = NULL;
-
-  err = gcry_sexp_build (&s_data, NULL, data);
-  if (err)
-    {
-      fail ("error building SEXP for test, %s: %s",
-            "data", gpg_strerror (err));
-      return;
-    }
 
   for (tvidx=0; tvidx < DIM(tv); tvidx++)
     {
       gcry_sexp_t s_pk = NULL;
       gcry_sexp_t s_sk = NULL;
+      gcry_sexp_t s_data = NULL;
       gcry_sexp_t s_sig= NULL;
 
       if (verbose)
@@ -287,6 +302,14 @@ check_pk_s_v (int reject)
           goto next;
         }
 
+      err = gcry_sexp_build (&s_data, NULL, tv[tvidx].data);
+      if (err)
+        {
+          fail ("error building SEXP for test, %s: %s",
+                "data", gpg_strerror (err));
+          goto next;
+        }
+
       err = gcry_pk_sign (&s_sig, s_data, s_sk);
       if (err)
         {
@@ -363,11 +386,10 @@ check_pk_s_v (int reject)
 
     next:
       gcry_sexp_release (s_sig);
+      gcry_sexp_release (s_data);
       gcry_sexp_release (s_pk);
       gcry_sexp_release (s_sk);
     }
-
-  gcry_sexp_release (s_data);
 }
 
 /* Check gcry_pk_hash_sign, gcry_pk_hash_verify API.  */
@@ -1461,6 +1483,8 @@ main (int argc, char **argv)
 
   xgcry_control ((GCRYCTL_FIPS_REJECT_NON_FIPS,
                   (GCRY_FIPS_FLAG_REJECT_MD_MD5
+                   | GCRY_FIPS_FLAG_REJECT_PK_MD
+                   | GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2
                    | GCRY_FIPS_FLAG_REJECT_COMPAT110)));
 
   check_md_o_w_r_c (1);
-- 
2.47.1

openSUSE Build Service is sponsored by