Blame SOURCES/libgcrypt-1.5.3-rsa-fips-keygen.patch

f268f1
diff -up libgcrypt-1.5.3/cipher/primegen.c.fips-keygen libgcrypt-1.5.3/cipher/primegen.c
f268f1
--- libgcrypt-1.5.3/cipher/primegen.c.fips-keygen	2014-10-21 15:05:59.434189992 +0200
f268f1
+++ libgcrypt-1.5.3/cipher/primegen.c	2014-10-21 15:05:59.458190534 +0200
f268f1
@@ -1189,6 +1189,22 @@ gcry_prime_check (gcry_mpi_t x, unsigned
f268f1
   return gcry_error (err);
f268f1
 }
f268f1
 
f268f1
+/* Check whether the number X is prime according to FIPS 186-4 table C.2.  */
f268f1
+gpg_err_code_t
f268f1
+_gcry_fips186_4_prime_check (gcry_mpi_t x, unsigned int bits)
f268f1
+{
f268f1
+  gpg_err_code_t ec = GPG_ERR_NO_ERROR;
f268f1
+  gcry_mpi_t val_2 = mpi_alloc_set_ui (2); /* Used by the Fermat test. */
f268f1
+
f268f1
+  /* We use 5 or 4 rounds as specified in table C.2 */
f268f1
+  if (! check_prime (x, val_2, bits > 1024 ? 4 : 5, NULL, NULL))
f268f1
+    ec = GPG_ERR_NO_PRIME;
f268f1
+
f268f1
+  mpi_free (val_2);
f268f1
+
f268f1
+  return ec;
f268f1
+}
f268f1
+
f268f1
 /* Find a generator for PRIME where the factorization of (prime-1) is
f268f1
    in the NULL terminated array FACTORS. Return the generator as a
f268f1
    newly allocated MPI in R_G.  If START_G is not NULL, use this as s
f268f1
diff -up libgcrypt-1.5.3/cipher/rsa.c.fips-keygen libgcrypt-1.5.3/cipher/rsa.c
f268f1
--- libgcrypt-1.5.3/cipher/rsa.c.fips-keygen	2014-10-21 15:05:59.423189744 +0200
f268f1
+++ libgcrypt-1.5.3/cipher/rsa.c	2014-10-21 15:12:45.200350340 +0200
f268f1
@@ -328,6 +328,279 @@ generate_std (RSA_secret_key *sk, unsign
f268f1
 }
f268f1
 
f268f1
 
f268f1
+/****************
f268f1
+ * Generate a key pair with a key of size NBITS.
f268f1
+ * USE_E = 0 let Libcgrypt decide what exponent to use.
f268f1
+ *       = 1 request the use of a "secure" exponent; this is required by some
f268f1
+ *           specification to be 65537.
f268f1
+ *       > 2 Use this public exponent.  If the given exponent
f268f1
+ *           is not odd one is internally added to it.
f268f1
+ * TESTPARMS: If set, do not generate but test whether the p,q is probably prime
f268f1
+ *            Returns key with zeroes to not break code calling this function.
f268f1
+ * TRANSIENT_KEY:  If true, generate the primes using the standard RNG.
f268f1
+ * Returns: 2 structures filled with all needed values
f268f1
+ */
f268f1
+static gpg_err_code_t
f268f1
+generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
f268f1
+               gcry_sexp_t testparms, int transient_key)
f268f1
+{
f268f1
+  gcry_mpi_t p, q; /* the two primes */
f268f1
+  gcry_mpi_t d;    /* the private key */
f268f1
+  gcry_mpi_t u;
f268f1
+  gcry_mpi_t p1, q1;
f268f1
+  gcry_mpi_t n;    /* the public key */
f268f1
+  gcry_mpi_t e;    /* the exponent */
f268f1
+  gcry_mpi_t g;
f268f1
+  gcry_mpi_t minp;
f268f1
+  gcry_mpi_t diff, mindiff;
f268f1
+  gcry_random_level_t random_level;
f268f1
+  unsigned int pbits = nbits/2;
f268f1
+  unsigned int i;
f268f1
+  int pqswitch;
f268f1
+  gpg_err_code_t ec = GPG_ERR_NO_PRIME;
f268f1
+
f268f1
+  if (nbits < 1024 || (nbits & 0x1FF))
f268f1
+      return GPG_ERR_INV_VALUE;
f268f1
+  if (_gcry_enforced_fips_mode() && nbits != 2048 && nbits != 3072)
f268f1
+      return GPG_ERR_INV_VALUE;
f268f1
+
f268f1
+  /* The random quality depends on the transient_key flag.  */
f268f1
+  random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
f268f1
+
f268f1
+  if (testparms)
f268f1
+      {
f268f1
+        /* Parameters to derive the key are given.  */
f268f1
+        /* Note that we explicitly need to setup the values of tbl
f268f1
+           because some compilers (e.g. OpenWatcom, IRIX) don't allow
f268f1
+           to initialize a structure with automatic variables.  */
f268f1
+        struct { const char *name; gcry_mpi_t *value; } tbl[] = {
f268f1
+          { "e" },
f268f1
+          { "p" },
f268f1
+          { "q" },
f268f1
+          { NULL }
f268f1
+        };
f268f1
+        int idx;
f268f1
+        gcry_sexp_t oneparm;
f268f1
+
f268f1
+        tbl[0].value = &e;
f268f1
+        tbl[1].value = &p;
f268f1
+        tbl[2].value = &q;
f268f1
+
f268f1
+        for (idx=0; tbl[idx].name; idx++)
f268f1
+          {
f268f1
+            oneparm = gcry_sexp_find_token (testparms, tbl[idx].name, 0);
f268f1
+            if (oneparm)
f268f1
+              {
f268f1
+                *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1,
f268f1
+                                                     GCRYMPI_FMT_USG);
f268f1
+                gcry_sexp_release (oneparm);
f268f1
+              }
f268f1
+          }
f268f1
+        for (idx=0; tbl[idx].name; idx++)
f268f1
+          if (!*tbl[idx].value)
f268f1
+            break;
f268f1
+        if (tbl[idx].name)
f268f1
+          {
f268f1
+            /* At least one parameter is missing.  */
f268f1
+            for (idx=0; tbl[idx].name; idx++)
f268f1
+              gcry_mpi_release (*tbl[idx].value);
f268f1
+            return GPG_ERR_MISSING_VALUE;
f268f1
+          }
f268f1
+      }
f268f1
+  else
f268f1
+      {
f268f1
+        if (use_e < 65537)
f268f1
+          use_e = 65537;  /* This is the smallest value allowed by FIPS */
f268f1
+
f268f1
+        e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
f268f1
+
f268f1
+        use_e |= 1; /* make sure this is odd */
f268f1
+        mpi_set_ui (e, use_e);
f268f1
+
f268f1
+        p = gcry_mpi_snew (pbits);
f268f1
+        q = gcry_mpi_snew (pbits);
f268f1
+      }
f268f1
+
f268f1
+  n = gcry_mpi_new (nbits);
f268f1
+  d = gcry_mpi_snew (nbits);
f268f1
+  u = gcry_mpi_snew (nbits);
f268f1
+
f268f1
+  /* prepare approximate minimum p and q */
f268f1
+  minp = gcry_mpi_new (pbits);
f268f1
+  mpi_set_ui (minp, 0xB504F334);
f268f1
+  gcry_mpi_lshift (minp, minp, pbits - 32); 
f268f1
+
f268f1
+  /* prepare minimum p and q difference */
f268f1
+  diff = gcry_mpi_new (pbits);
f268f1
+  mindiff = gcry_mpi_new (pbits - 99);
f268f1
+  mpi_set_ui (mindiff, 1);
f268f1
+  gcry_mpi_lshift (mindiff, mindiff, pbits - 100);
f268f1
+
f268f1
+  p1 = gcry_mpi_snew (pbits);
f268f1
+  q1 = gcry_mpi_snew (pbits);
f268f1
+  g  = gcry_mpi_snew (pbits);
f268f1
+
f268f1
+retry:
f268f1
+  /* generate p and q */
f268f1
+  for (i = 0; i < 5 * pbits; i++)
f268f1
+    {
f268f1
+    ploop:
f268f1
+      if (!testparms)
f268f1
+        {
f268f1
+          gcry_mpi_randomize (p, pbits, random_level);
f268f1
+        }
f268f1
+      if (mpi_cmp (p, minp) < 0)
f268f1
+        {
f268f1
+          if (testparms) goto err;
f268f1
+          goto ploop;
f268f1
+        }
f268f1
+
f268f1
+      mpi_sub_ui (p1, p, 1);
f268f1
+      if (gcry_mpi_gcd (g, p1, e))
f268f1
+        {
f268f1
+          if (_gcry_fips186_4_prime_check (p, pbits) != GPG_ERR_NO_ERROR)
f268f1
+            {
f268f1
+              /* not a prime */
f268f1
+              if (testparms) goto err;
f268f1
+            }
f268f1
+          else
f268f1
+            break;
f268f1
+        } 
f268f1
+      else if (testparms) goto err;
f268f1
+    }
f268f1
+  if (i >= 5 * pbits)
f268f1
+    goto err;
f268f1
+
f268f1
+  for (i = 0; i < 5 * pbits; i++)
f268f1
+    {
f268f1
+    qloop:
f268f1
+      if (!testparms)
f268f1
+        {
f268f1
+          gcry_mpi_randomize (q, pbits, random_level);
f268f1
+        }
f268f1
+      if (mpi_cmp (q, minp) < 0)
f268f1
+        {
f268f1
+          if (testparms) goto err;
f268f1
+          goto qloop;
f268f1
+        }
c0f8d1
+      if (mpi_cmp (p, q) > 0)
f268f1
+        {
f268f1
+          pqswitch = 1;
c0f8d1
+          mpi_sub (diff, p, q);
f268f1
+        }      
f268f1
+      else
f268f1
+        {
f268f1
+          pqswitch = 0;
c0f8d1
+          mpi_sub (diff, q, p);
f268f1
+        }
f268f1
+      if (mpi_cmp (diff, mindiff) < 0)
f268f1
+        {
f268f1
+          if (testparms) goto err;
f268f1
+          goto qloop;
f268f1
+        }
f268f1
+
f268f1
+      mpi_sub_ui (q1, q, 1);
f268f1
+      if (gcry_mpi_gcd (g, q1, e))
f268f1
+        {
f268f1
+          if (_gcry_fips186_4_prime_check (q, pbits) != GPG_ERR_NO_ERROR)
f268f1
+            {
f268f1
+              /* not a prime */
f268f1
+              if (testparms) goto err;
f268f1
+            }
f268f1
+          else
f268f1
+            break;
f268f1
+        }
f268f1
+      else if (testparms) goto err;
f268f1
+    }
f268f1
+  if (i >= 5 * pbits)
f268f1
+    goto err;
f268f1
+
f268f1
+  if (testparms)
f268f1
+    {
f268f1
+       mpi_clear (p);
f268f1
+       mpi_clear (q);
f268f1
+    }
f268f1
+  else
f268f1
+    {
f268f1
+      gcry_mpi_t f;
f268f1
+
f268f1
+      if (pqswitch)
f268f1
+        {
f268f1
+          gcry_mpi_t tmp;
f268f1
+
f268f1
+          tmp = p;
f268f1
+          p = q;
f268f1
+          q = tmp;
f268f1
+        }
f268f1
+
f268f1
+      f = gcry_mpi_snew (nbits);
f268f1
+
f268f1
+      /* calculate the modulus */
f268f1
+      mpi_mul(n, p, q);
f268f1
+
f268f1
+      /* calculate the secret key d = e^1 mod phi */
f268f1
+      gcry_mpi_gcd (g, p1, q1);
f268f1
+      mpi_fdiv_q (f, p1, g);
f268f1
+      mpi_mul (f, f, q1);
f268f1
+      
f268f1
+      mpi_invm (d, e, f);
f268f1
+
f268f1
+      gcry_mpi_release (f);
f268f1
+
f268f1
+      if (mpi_get_nbits (d) < pbits) goto retry;
f268f1
+
f268f1
+      /* calculate the inverse of p and q (used for chinese remainder theorem)*/
f268f1
+      mpi_invm(u, p, q );
f268f1
+    }
f268f1
+
f268f1
+  ec = 0;
f268f1
+
f268f1
+  if( DBG_CIPHER )
f268f1
+    {
f268f1
+      log_mpidump("  p= ", p );
f268f1
+      log_mpidump("  q= ", q );
f268f1
+      log_mpidump("  n= ", n );
f268f1
+      log_mpidump("  e= ", e );
f268f1
+      log_mpidump("  d= ", d );
f268f1
+      log_mpidump("  u= ", u );
f268f1
+    }
f268f1
+
f268f1
+err:
f268f1
+
f268f1
+  gcry_mpi_release (p1);
f268f1
+  gcry_mpi_release (q1);
f268f1
+  gcry_mpi_release (g);
f268f1
+  gcry_mpi_release (minp);
f268f1
+  gcry_mpi_release (mindiff);
f268f1
+  gcry_mpi_release (diff);
f268f1
+
f268f1
+  sk->n = n;
f268f1
+  sk->e = e;
f268f1
+  sk->p = p;
f268f1
+  sk->q = q;
f268f1
+  sk->d = d;
f268f1
+  sk->u = u;
f268f1
+
f268f1
+  /* Now we can test our keys. */
f268f1
+  if (ec || (!testparms && test_keys (sk, nbits - 64)))
f268f1
+    {
f268f1
+      gcry_mpi_release (sk->n); sk->n = NULL;
f268f1
+      gcry_mpi_release (sk->e); sk->e = NULL;
f268f1
+      gcry_mpi_release (sk->p); sk->p = NULL;
f268f1
+      gcry_mpi_release (sk->q); sk->q = NULL;
f268f1
+      gcry_mpi_release (sk->d); sk->d = NULL;
f268f1
+      gcry_mpi_release (sk->u); sk->u = NULL;
f268f1
+      if (!ec)
f268f1
+        {
f268f1
+          fips_signal_error ("self-test after key generation failed");
f268f1
+          return GPG_ERR_SELFTEST_FAILED;
f268f1
+        }
f268f1
+    }
f268f1
+
f268f1
+  return ec;
f268f1
+}
f268f1
+
f268f1
+
f268f1
 /* Helper for generate_x931.  */
f268f1
 static gcry_mpi_t
f268f1
 gen_x931_parm_xp (unsigned int nbits)
f268f1
@@ -812,7 +1085,7 @@ rsa_generate_ext (int algo, unsigned int
f268f1
         }
f268f1
     }
f268f1
 
f268f1
-  if (deriveparms || use_x931 || fips_mode ())
f268f1
+  if (deriveparms || use_x931)
f268f1
     {
f268f1
       int swapped;
f268f1
       ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped);
f268f1
@@ -841,8 +1114,14 @@ rsa_generate_ext (int algo, unsigned int
f268f1
           transient_key = 1;
f268f1
           gcry_sexp_release (l1);
f268f1
         }
f268f1
+      deriveparms = (genparms?
f268f1
+                 gcry_sexp_find_token (genparms, "test-parms", 0) : NULL);
f268f1
       /* Generate.  */
f268f1
-      ec = generate_std (&sk, nbits, evalue, transient_key);
f268f1
+      if (deriveparms || fips_mode())
f268f1
+	ec = generate_fips (&sk, nbits, evalue, deriveparms, transient_key);
f268f1
+      else
f268f1
+        ec = generate_std (&sk, nbits, evalue, transient_key);
f268f1
+      gcry_sexp_release (deriveparms);
f268f1
     }
f268f1
 
f268f1
   if (!ec)
f268f1
diff -up libgcrypt-1.5.3/src/g10lib.h.fips-keygen libgcrypt-1.5.3/src/g10lib.h
f268f1
--- libgcrypt-1.5.3/src/g10lib.h.fips-keygen	2013-07-25 11:10:04.000000000 +0200
f268f1
+++ libgcrypt-1.5.3/src/g10lib.h	2014-10-21 15:05:59.459190556 +0200
f268f1
@@ -195,6 +195,9 @@ gpg_err_code_t _gcry_generate_fips186_3_
f268f1
                   int *r_counter,
f268f1
                   void **r_seed, size_t *r_seedlen, int *r_hashalgo);
f268f1
 
f268f1
+gpg_err_code_t _gcry_fips186_4_prime_check
f268f1
+                 (const gcry_mpi_t x, unsigned int bits);
f268f1
+
f268f1
 
f268f1
 /* Replacements of missing functions (missing-string.c).  */
f268f1
 #ifndef HAVE_STPCPY
f268f1
diff -up libgcrypt-1.5.3/tests/keygen.c.fips-keygen libgcrypt-1.5.3/tests/keygen.c
f268f1
--- libgcrypt-1.5.3/tests/keygen.c.fips-keygen	2014-10-21 15:05:59.424189766 +0200
f268f1
+++ libgcrypt-1.5.3/tests/keygen.c	2014-10-21 15:05:59.459190556 +0200
f268f1
@@ -190,12 +190,12 @@ check_rsa_keys (void)
f268f1
 
f268f1
 
f268f1
   if (verbose)
f268f1
-    fprintf (stderr, "creating 1024 bit RSA key with e=257\n");
f268f1
+    fprintf (stderr, "creating 1024 bit RSA key with e=65539\n");
f268f1
   rc = gcry_sexp_new (&keyparm,
f268f1
                       "(genkey\n"
f268f1
                       " (rsa\n"
f268f1
                       "  (nbits 4:1024)\n"
f268f1
-                      "  (rsa-use-e 3:257)\n"
f268f1
+                      "  (rsa-use-e 5:65539)\n"
f268f1
                       " ))", 0, 1);
f268f1
   if (rc)
f268f1
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
f268f1
@@ -204,7 +204,7 @@ check_rsa_keys (void)
f268f1
   if (rc)
f268f1
     die ("error generating RSA key: %s\n", gpg_strerror (rc));
f268f1
 
f268f1
-  check_generated_rsa_key (key, 257);
f268f1
+  check_generated_rsa_key (key, 65539);
f268f1
   gcry_sexp_release (key);
f268f1
 
f268f1
   if (verbose)