File libgcrypt-FIPS-RSA-keylen.patch of Package libgcrypt

From 40d63d09b2d06631f4d2c3d1b167a620d50c99f8 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 5 Nov 2021 14:19:23 +0100
Subject: [PATCH 198/200] rsa: Check keylen constraints for key operations.

* cipher/rsa.c (rsa_check_keysize): New.
(generate_fips): Factor out the bits check.
(rsa_encrypt): Add checking key length.
(rsa_decrypt, rsa_sign, rsa_verify): Likewise.
--

GnuPG-bug-id: 5512
Co-authored-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
---
 cipher/rsa.c | 58 ++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 15 deletions(-)

Index: libgcrypt-1.9.4/cipher/rsa.c
===================================================================
--- libgcrypt-1.9.4.orig/cipher/rsa.c
+++ libgcrypt-1.9.4/cipher/rsa.c
@@ -301,14 +301,6 @@ generate_std (RSA_secret_key *sk, unsign
   gcry_mpi_t f;
   gcry_random_level_t random_level;
 
-  if (fips_mode ())
-    {
-      if (nbits < 1024)
-        return GPG_ERR_INV_VALUE;
-      if (transient_key)
-        return GPG_ERR_INV_VALUE;
-    }
-
   /* The random quality depends on the transient_key flag.  */
   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
 
@@ -437,6 +429,17 @@ generate_std (RSA_secret_key *sk, unsign
 }
 
 
+/* Check the RSA key length is acceptable for key generation or usage */
+static gpg_err_code_t
+rsa_check_keysize (unsigned int nbits)
+{
+  if (fips_mode() && nbits < 2048)
+    return GPG_ERR_INV_VALUE;
+
+  return GPG_ERR_NO_ERROR;
+}
+
+
 /****************
  * Generate a key pair with a key of size NBITS.
  * USE_E = 0 let Libcgrypt decide what exponent to use.
@@ -466,12 +469,15 @@ generate_fips (RSA_secret_key *sk, unsig
   unsigned int pbits = nbits/2;
   unsigned int i;
   int pqswitch;
-  gpg_err_code_t ec = GPG_ERR_NO_PRIME;
+  gpg_err_code_t ec;
 
   if (nbits < 1024 || (nbits & 0x1FF))
     return GPG_ERR_INV_VALUE;
-  if (fips_mode() && nbits < 2048)
-      return GPG_ERR_INV_VALUE;
+  ec = rsa_check_keysize (nbits);
+  if (ec)
+    return ec;
+
+  ec = GPG_ERR_NO_PRIME;
 
   /* The random quality depends on the transient_key flag.  */
   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
@@ -1360,9 +1366,13 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_s
   gcry_mpi_t data = NULL;
   RSA_public_key pk = {NULL, NULL};
   gcry_mpi_t ciph = NULL;
+  unsigned int nbits = rsa_get_nbits (keyparms);
+
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
-                                   rsa_get_nbits (keyparms));
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1432,9 +1442,13 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_
   gcry_mpi_t plain = NULL;
   unsigned char *unpad = NULL;
   size_t unpadlen = 0;
+  unsigned int nbits = rsa_get_nbits (keyparms);
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
-                                   rsa_get_nbits (keyparms));
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
+
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx);
@@ -1477,7 +1491,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_
   mpi_fdiv_r (data, data, sk.n);
 
   /* Allocate MPI for the plaintext.  */
-  plain = mpi_snew (ctx.nbits);
+  plain = mpi_snew (nbits);
 
   /* We use blinding by default to mitigate timing attacks which can
      be practically mounted over the network as shown by Brumley and
@@ -1485,7 +1499,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_
   if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
     secret (plain, data, &sk);
   else
-    secret_blinded (plain, data, &sk, ctx.nbits);
+    secret_blinded (plain, data, &sk, nbits);
 
   if (DBG_CIPHER)
     log_printmpi ("rsa_decrypt  res", plain);
@@ -1494,7 +1508,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_
   switch (ctx.encoding)
     {
     case PUBKEY_ENC_PKCS1:
-      rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain);
+      rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain);
       mpi_free (plain);
       plain = NULL;
       if (!rc)
@@ -1503,7 +1517,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_
 
     case PUBKEY_ENC_OAEP:
       rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
-                                  ctx.nbits, ctx.hash_algo,
+                                  nbits, ctx.hash_algo,
                                   plain, ctx.label, ctx.labellen);
       mpi_free (plain);
       plain = NULL;
@@ -1548,9 +1562,13 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_
   RSA_public_key pk;
   gcry_mpi_t sig = NULL;
   gcry_mpi_t result = NULL;
+  unsigned int nbits = rsa_get_nbits (keyparms);
+
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
-                                   rsa_get_nbits (keyparms));
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1588,7 +1606,7 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_
   if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
     secret (sig, data, &sk);
   else
-    secret_blinded (sig, data, &sk, ctx.nbits);
+    secret_blinded (sig, data, &sk, nbits);
   if (DBG_CIPHER)
     log_printmpi ("rsa_sign    res", sig);
 
@@ -1650,9 +1668,13 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp
   gcry_mpi_t data = NULL;
   RSA_public_key pk = { NULL, NULL };
   gcry_mpi_t result = NULL;
+  unsigned int nbits = rsa_get_nbits (keyparms);
+
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
-                                   rsa_get_nbits (keyparms));
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
Index: libgcrypt-1.9.4/tests/basic.c
===================================================================
--- libgcrypt-1.9.4.orig/tests/basic.c
+++ libgcrypt-1.9.4/tests/basic.c
@@ -14172,6 +14172,62 @@ check_pubkey (void)
       "\x4a\xa6\xf9\xeb\x23\xbf\xa9\x12\x2d\x5b" }
   },
   {
+    GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP, /* 2k RSA */
+    {
+      "(private-key"
+      " (rsa"
+      "  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+      "      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+      "      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+      "      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+      "      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+      "      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+      "      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+      "      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+      "      CB#)\n"
+      "   (e #010001#)\n"
+      "   (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
+      "       8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
+      "       7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
+      "       771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
+      "       5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
+      "       EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
+      "       69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
+      "       3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401"
+      "       #)\n"
+      "   (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0"
+      "       79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B"
+      "       441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF"
+      "       54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17"
+      "       83#)\n"
+      "   (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46"
+      "       79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77"
+      "       88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E"
+      "       8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9"
+      "       19#)\n"
+      "   (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
+      "       479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
+      "       A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
+      "       AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7"
+      "       #)))\n",
+
+      "(public-key\n"
+      " (rsa\n"
+      "  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+      "      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+      "      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+      "      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+      "      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+      "      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+      "      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+      "      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+      "      CB#)\n"
+      "   (e #010001#)))\n",
+
+      "\xe0\x08\x98\x9b\xb6\x44\xa2\x9a\x83\x37"
+      "\x47\xdd\x69\x55\xdb\x3a\xac\x89\x6e\x40"}
+  },
+  {
     GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT | FLAG_GRIP,
     {
       "(private-key\n"
openSUSE Build Service is sponsored by