[svn] gcry - r1360 - in trunk: . cipher doc src tests

svn author wk cvs at cvs.gnupg.org
Tue Nov 25 22:09:55 CET 2008


Author: wk
Date: 2008-11-25 22:09:55 +0100 (Tue, 25 Nov 2008)
New Revision: 1360

Modified:
   trunk/NEWS
   trunk/cipher/ChangeLog
   trunk/cipher/dsa.c
   trunk/cipher/primegen.c
   trunk/cipher/rsa.c
   trunk/doc/gcrypt.texi
   trunk/src/g10lib.h
   trunk/tests/pubkey.c
Log:
Implement FIPS 186-2 key generation.


Modified: trunk/cipher/ChangeLog
===================================================================
--- trunk/cipher/ChangeLog	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/ChangeLog	2008-11-25 21:09:55 UTC (rev 1360)
@@ -1,3 +1,10 @@
+2008-11-25  Werner Koch  <wk at g10code.com>
+
+	* dsa.c (generate_fips186): New.
+	(dsa_generate_ext): Use new function if derive-parms are given or
+	if in FIPS mode.
+	* primegen.c (_gcry_generate_fips186_2_prime): New.
+
 2008-11-24  Werner Koch  <wk at g10code.com>
 
 	* pubkey.c (gcry_pk_genkey): Insert code to output extrainfo.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/NEWS	2008-11-25 21:09:55 UTC (rev 1360)
@@ -8,7 +8,10 @@
 
  * Fixed HMAC for SHA-384 and SHA-512 with keys longer than 64 bytes.
 
+ * In fips mode, RSA keys are now generated using the X9.31 algorithm
+   and DSA keys using the FIPS 186-2 algorithm.
 
+
 Noteworthy changes in version 1.4.3 (2008-09-18)
 ------------------------------------------------
 

Modified: trunk/cipher/dsa.c
===================================================================
--- trunk/cipher/dsa.c	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/dsa.c	2008-11-25 21:09:55 UTC (rev 1360)
@@ -325,11 +325,11 @@
   if( DBG_CIPHER ) 
     {
       progress('\n');
-      log_mpidump("dsa  p= ", p );
-      log_mpidump("dsa  q= ", q );
-      log_mpidump("dsa  g= ", g );
-      log_mpidump("dsa  y= ", y );
-      log_mpidump("dsa  x= ", x );
+      log_mpidump("dsa  p", p );
+      log_mpidump("dsa  q", q );
+      log_mpidump("dsa  g", g );
+      log_mpidump("dsa  y", y );
+      log_mpidump("dsa  x", x );
     }
 
   /* Copy the stuff to the key structures. */
@@ -354,7 +354,147 @@
 }
 
 
+/* Generate a DSA key pair with a key of size NBITS using the
+   algorithm given in FIPS-186.  At the time of implementation FIPS
+   186-3 was not released; the Draft from November 2008 was used
+   instead to avoid limiting ourself to FIPS 186-2.  */
+static gpg_err_code_t
+generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
+                  int *r_counter, void **r_seed, size_t *r_seedlen,
+                  gcry_mpi_t *r_h)
+{
+  gpg_err_code_t ec;
+  gcry_mpi_t prime_q = NULL; 
+  gcry_mpi_t prime_p = NULL; 
+  gcry_mpi_t value_g = NULL; /* The generator. */
+  gcry_mpi_t value_y = NULL; /* g^x mod p */
+  gcry_mpi_t value_x = NULL; /* The secret exponent. */
+  gcry_mpi_t value_h = NULL; /* Helper.  */
+  gcry_mpi_t value_e = NULL; /* Helper.  */
 
+  /* Preset return values.  */
+  *r_counter = 0;
+  *r_seed = NULL;
+  *r_seedlen = 0;
+  *r_h = NULL;
+
+  /* Derive QBITS from NBITS if requested  */
+  if (!qbits)
+    {
+      if (nbits == 1024)
+        qbits = 160;
+      else if (nbits == 2048)
+        qbits = 224;
+      else if (nbits == 3072)
+        qbits = 256;
+    }
+
+  /* Check that QBITS and NBITS match the standard.  Note that FIPS
+     186-3 uses N for QBITS and L for NBITS.  */
+  if (nbits == 1024 && qbits == 160)
+    ;
+  else if (nbits == 2048 && qbits == 224)
+    ;
+  else if (nbits == 2048 && qbits == 256)
+    ;
+  else if (nbits == 2048 && qbits == 256)
+    ;
+  else
+    return GPG_ERR_INV_VALUE;
+
+  /* Note that we currently do not yet support 186-3 for prime
+     generation becuase it is not clear whether CAVS is prepared for
+     it.  */
+  ec = _gcry_generate_fips186_2_prime (nbits, qbits, NULL, 0,
+                                       &prime_q, &prime_p, 
+                                       r_counter,
+                                       r_seed, r_seedlen);
+  if (ec)
+    goto leave;
+
+  /* Find a generator g (h and e are helpers).
+     e = (p-1)/q */
+  value_e = mpi_alloc_like (prime_p);
+  mpi_sub_ui (value_e, prime_p, 1);
+  mpi_fdiv_q (value_e, value_e, prime_q );
+  value_g = mpi_alloc_like (prime_p);
+  value_h = mpi_alloc_set_ui (1); 
+  do
+    {
+      mpi_add_ui (value_h, value_h, 1);
+      /* g = h^e mod p */
+      mpi_powm (value_g, value_h, value_e, prime_p);
+    } 
+  while (!mpi_cmp_ui (value_g, 1));  /* Continue until g != 1.  */
+
+  /* Select a random number x with:  0 < x < q  */
+  value_x = gcry_mpi_snew (qbits);
+  do 
+    {
+      if( DBG_CIPHER )
+        progress('.');
+      gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM);
+      mpi_clear_highbit (value_x, qbits+1);
+    } 
+  while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0));
+
+  /* y = g^x mod p */
+  value_y = mpi_alloc_like (prime_p);
+  gcry_mpi_powm (value_y, value_g, value_x, prime_p);
+
+  if (DBG_CIPHER) 
+    {
+      progress('\n');
+      log_mpidump("dsa  p", prime_p );
+      log_mpidump("dsa  q", prime_q );
+      log_mpidump("dsa  g", value_g );
+      log_mpidump("dsa  y", value_y );
+      log_mpidump("dsa  x", value_x );
+      log_mpidump("dsa  h", value_h );
+    }
+
+  /* Copy the stuff to the key structures. */
+  sk->p = prime_p; prime_p = NULL;
+  sk->q = prime_q; prime_q = NULL;
+  sk->g = value_g; value_g = NULL;
+  sk->y = value_y; value_y = NULL;
+  sk->x = value_x; value_x = NULL;
+  *r_h = value_h; value_h = NULL;
+
+ leave:
+  gcry_mpi_release (prime_p);
+  gcry_mpi_release (prime_q);
+  gcry_mpi_release (value_g);
+  gcry_mpi_release (value_y);
+  gcry_mpi_release (value_x);
+  gcry_mpi_release (value_h);
+  gcry_mpi_release (value_e);
+
+  /* As a last step test this keys (this should never fail of course). */
+  if (!ec && test_keys (sk, qbits) )
+    {
+      gcry_mpi_release (sk->p); sk->p = NULL;
+      gcry_mpi_release (sk->q); sk->q = NULL;
+      gcry_mpi_release (sk->g); sk->g = NULL;
+      gcry_mpi_release (sk->y); sk->y = NULL;
+      gcry_mpi_release (sk->x); sk->x = NULL;
+      fips_signal_error ("self-test after key generation failed");
+      ec = GPG_ERR_SELFTEST_FAILED;
+    }
+
+  if (ec)
+    {
+      *r_counter = 0;
+      gcry_free (*r_seed); *r_seed = NULL;
+      *r_seedlen = 0;
+      gcry_mpi_release (*r_h); *r_h = NULL;
+    }
+
+  return ec;
+}
+
+
+
 /*
    Test whether the secret key is valid.
    Returns: if this is a valid key.
@@ -468,13 +608,17 @@
   DSA_secret_key sk;
   gcry_sexp_t l1;
   unsigned int qbits = 0;
+  gcry_sexp_t deriveparms = NULL;
+  gcry_sexp_t seedinfo = NULL;
+  int use_fips186 = 0;
+  
 
   (void)algo;    /* No need to check it.  */
   (void)evalue;  /* Not required for DSA. */
 
-  /* Parse the optional qbits element. */
   if (genparms)
     {
+      /* Parse the optional qbits element.  */
       l1 = gcry_sexp_find_token (genparms, "qbits", 0);
       if (l1)
         {
@@ -493,9 +637,50 @@
           qbits = (unsigned int)strtoul (buf, NULL, 0);
           gcry_sexp_release (l1);
         }
+
+      deriveparms = gcry_sexp_find_token (genparms, "derive-parms", 0);
+
+      /* Parse the optional "use-fips186" flag.  */
+      l1 = gcry_sexp_find_token (genparms, "use-fips186", 0);
+      if (l1)
+        {
+          use_fips186 = 1;
+          gcry_sexp_release (l1);
+        }
     }
 
-  ec = generate (&sk, nbits, qbits, retfactors);
+  if (deriveparms || use_fips186 || fips_mode ())
+    {
+      int counter;
+      void *seed;
+      size_t seedlen;
+      gcry_mpi_t h_value;
+
+      ec = generate_fips186 (&sk, nbits, qbits, 
+                             &counter, &seed, &seedlen, &h_value);
+      gcry_sexp_release (deriveparms);
+      if (!ec)
+        {
+          ec = gpg_err_code (gcry_sexp_build 
+                             (&seedinfo, NULL,
+                              "(seed-values(counter %d)(seed %b)(h %m))",
+                              counter, (int)seedlen, seed, h_value));
+          if (ec)
+            {
+              gcry_mpi_release (sk.p); sk.p = NULL;
+              gcry_mpi_release (sk.q); sk.q = NULL;
+              gcry_mpi_release (sk.g); sk.g = NULL;
+              gcry_mpi_release (sk.y); sk.y = NULL;
+              gcry_mpi_release (sk.x); sk.x = NULL;
+            }
+          gcry_free (seed);
+          gcry_mpi_release (h_value);
+        }
+    }
+  else
+    {
+      ec = generate (&sk, nbits, qbits, retfactors);
+    }
   if (!ec)
     {
       skey[0] = sk.p;
@@ -509,9 +694,9 @@
           /* Old style interface - return the factors - if any - at
              retfactors.  */
         }
-      else if (r_extrainfo && !*retfactors)
+      else if (!*retfactors && !seedinfo)
         {
-          /* No factors, thus there is nothing to return.  */
+          /* No factors and no seedinfo, thus there is nothing to return.  */
           *r_extrainfo = NULL;
         }
       else
@@ -520,36 +705,46 @@
              to make use of the new interface.  Note that the factors
              are not confidential thus we can store them in standard
              memory.  */
-          int nfactors, i;
+          int nfactors, i, j;
           char *p;
           char *format = NULL;
           void **arg_list = NULL;
 
-          for (nfactors=0; (*retfactors)[nfactors]; nfactors++)
+          for (nfactors=0; *retfactors && (*retfactors)[nfactors]; nfactors++)
             ;
           /* Allocate space for the format string:
-               "(misc-key-info(pm1-factors%m))"
-             with one "%m" for each factor and build the string  */
-          format = gcry_malloc (40 + 2*nfactors);
+               "(misc-key-info%S(pm1-factors%m))"
+             with one "%m" for each factor and construct it.  */
+          format = gcry_malloc (50 + 2*nfactors);
           if (!format)
             ec = gpg_err_code_from_syserror ();
           else
             {
-              p = stpcpy (format, "(misc-key-info(pm1-factors");
-              for (i=0; i < nfactors; i++)
-                p = stpcpy (p, "%m");
-              p = stpcpy (p, "))");
+              p = stpcpy (format, "(misc-key-info");
+              if (seedinfo)
+                p = stpcpy (p, "%S");
+              if (nfactors)
+                {
+                  p = stpcpy (p, "(pm1-factors");
+                  for (i=0; i < nfactors; i++)
+                    p = stpcpy (p, "%m");
+                  p = stpcpy (p, ")");
+                }
+              p = stpcpy (p, ")");
               
-              /* Allocate space for the argument list plus an extra
-                 NULL entry for safety and fill it with the
-                 factors.  */
-              arg_list = gcry_calloc (nfactors+1, sizeof *arg_list);
+              /* Allocate space for the list of factors plus one for
+                 an S-expression plus an extra NULL entry for safety
+                 and fill it with the factors.  */
+              arg_list = gcry_calloc (nfactors+1+1, sizeof *arg_list);
               if (!arg_list)
                 ec = gpg_err_code_from_syserror ();
               else
                 {
-                  for (i=0; i < nfactors; i++)
-                    arg_list[i] = (*retfactors) + i;
+                  i = 0;
+                  if (seedinfo)
+                    arg_list[i++] = &seedinfo;
+                  for (j=0; j < nfactors; j++)
+                    arg_list[i++] = (*retfactors) + j;
                   arg_list[i] = NULL;
                   
                   ec = gpg_err_code (gcry_sexp_build_array 
@@ -576,6 +771,7 @@
         }
     }
 
+  gcry_sexp_release (seedinfo);
   return ec;
 }
 

Modified: trunk/cipher/primegen.c
===================================================================
--- trunk/cipher/primegen.c	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/primegen.c	2008-11-25 21:09:55 UTC (rev 1360)
@@ -1274,7 +1274,8 @@
 }
 
 
-/* Helper for _gcry_generate_x931_prime.  */
+
+/* Helper for _gcry_derive_x931_prime.  */
 static gcry_mpi_t
 find_x931_prime (const gcry_mpi_t pfirst)
 {
@@ -1411,3 +1412,207 @@
     mpi_free (p2);
   return yp0;
 }
+
+
+
+/* Generate the two prime used for DSA using the algorithm specified
+   in FIPS 186-2.  PBITS is the desired length of the prime P and a
+   QBIST the length of the prime Q.  If SEED is not supplied and
+   SEEDLEN is 0 the function generates an appropriate SEED.  On
+   success the generated primes are stored at R_Q and R_P, the counter
+   value is stored at R_COUNTER and the seed actually used for
+   generation is stored at R_SEED and R_SEEDVALUE.  */
+gpg_err_code_t
+_gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits,
+                                const void *seed, size_t seedlen,
+                                gcry_mpi_t *r_q, gcry_mpi_t *r_p,
+                                int *r_counter,
+                                void **r_seed, size_t *r_seedlen)
+{
+  gpg_err_code_t ec;
+  unsigned char seed_help_buffer[160/8];  /* Used to hold a generated SEED. */
+  unsigned char *seed_plus;     /* Malloced buffer to hold SEED+x.  */
+  unsigned char digest[160/8];  /* Helper buffer for SHA-1 digest.  */
+  gcry_mpi_t val_2 = NULL;      /* Helper for the prime test.  */
+  gcry_mpi_t tmpval = NULL;     /* Helper variable.  */
+  int i;
+
+  unsigned char value_u[160/8];
+  int value_n, value_b, value_k;
+  int counter;
+  gcry_mpi_t value_w = NULL;
+  gcry_mpi_t value_x = NULL;
+  gcry_mpi_t prime_q = NULL;
+  gcry_mpi_t prime_p = NULL;
+
+  /* FIPS 186-2 allows only for 1024/160 bit.  */
+  if (pbits != 1024 || qbits != 160)
+    return GPG_ERR_INV_KEYLEN;
+
+  if (!seed && !seedlen)
+    ; /* No seed value given:  We are asked to generate it.  */
+  else if (!seed || seedlen < qbits/8)
+    return GPG_ERR_INV_ARG;
+  
+  /* Allocate a buffer to later compute SEED+some_increment. */
+  seed_plus = gcry_malloc (seedlen < 20? 20:seedlen);
+  if (!seed_plus)
+    {
+      ec = gpg_err_code_from_syserror ();
+      goto leave;
+    }
+
+  val_2   = mpi_alloc_set_ui (2);
+  value_n = (pbits - 1) / qbits;
+  value_b = (pbits - 1) - value_n * qbits;
+  value_w = gcry_mpi_new (pbits);
+  value_x = gcry_mpi_new (pbits);
+
+ restart:  
+  /* Generate Q.  */
+  for (;;)
+    {
+      /* Step 1: Generate a (new) seed unless one has been supplied.  */
+      if (!seed)
+        {
+          seedlen = sizeof seed_help_buffer;
+          gcry_create_nonce (seed_help_buffer, seedlen);
+          seed = seed_help_buffer;
+        }
+      
+      /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits})  */
+      memcpy (seed_plus, seed, seedlen);
+      for (i=seedlen-1; i >= 0; i--)
+        {
+          seed_plus[i]++;
+          if (seed_plus[i])
+            break;
+        }
+      gcry_md_hash_buffer (GCRY_MD_SHA1, value_u, seed, seedlen);
+      gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+      for (i=0; i < sizeof value_u; i++)
+        value_u[i] ^= digest[i];
+  
+      /* Step 3:  Form q from U  */
+      gcry_mpi_release (prime_q); prime_q = NULL;
+      ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, 
+                                        value_u, sizeof value_u, NULL));
+      if (ec)
+        goto leave;
+      mpi_set_highbit (prime_q, qbits-1 );
+      mpi_set_bit (prime_q, 0);
+      
+      /* Step 4:  Test whether Q is prime using 64 round of Rabin-Miller.  */
+      if (check_prime (prime_q, val_2, 64, NULL, NULL))
+        break; /* Yes, Q is prime.  */
+
+      /* Step 5.  */
+      seed = NULL;  /* Force a new seed at Step 1.  */
+    }
+  
+  /* Step 6.  Note that we do no use an explicit offset but increment
+     SEED_PLUS accordingly.  SEED_PLUS is currently SEED+1.  */
+  counter = 0;
+
+  /* Generate P. */
+  prime_p = gcry_mpi_new (pbits);
+  for (;;)
+    {
+      /* Step 7: For k = 0,...n let 
+                   V_k = sha1(seed+offset+k) mod 2^{qbits}  
+         Step 8: W = V_0 + V_1*2^160 + 
+                         ... 
+                         + V_{n-1}*2^{(n-1)*160}
+                         + (V_{n} mod 2^b)*2^{n*160}                
+       */
+      mpi_set_ui (value_w, 0);
+      for (value_k=0; value_k <= value_n; value_k++)
+        {
+          /* There is no need to have an explicit offset variable:  In
+             the first round we shall have an offset of 2, this is
+             achieved by using SEED_PLUS which is already at SEED+1,
+             thus we just need to increment it once again.  The
+             requirement for the next round is to update offset by N,
+             which we implictly did at the end of this loop, and then
+             to add one; this one is the same as in the first round.  */
+          for (i=seedlen-1; i >= 0; i--)
+            {
+              seed_plus[i]++;
+              if (seed_plus[i])
+                break;
+            }
+          gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+          
+          gcry_mpi_release (tmpval); tmpval = NULL;
+          ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
+                                            digest, sizeof digest, NULL));
+          if (ec)
+            goto leave;
+          if (value_k == value_n)
+            mpi_clear_highbit (tmpval, value_b+1); /* (V_n mod 2^b) */
+          mpi_lshift (tmpval, tmpval, value_k*qbits);
+          mpi_add (value_w, value_w, tmpval);
+        }
+
+      /* Step 8 continued: X = W + 2^{L-1}  */
+      mpi_set_ui (value_x, 0);
+      mpi_set_highbit (value_x, pbits-1);
+      mpi_add (value_x, value_x, value_w);
+
+      /* Step 9:  c = X mod 2q,  p = X - (c - 1)  */
+      mpi_mul_2exp (tmpval, prime_q, 1);
+      mpi_mod (tmpval, value_x, tmpval);
+      mpi_sub_ui (tmpval, tmpval, 1);
+      mpi_sub (prime_p, value_x, tmpval);
+
+      /* Step 10: If  p < 2^{L-1}  skip the primality test.  */
+      /* Step 11 and 12: Primality test.  */
+      if (mpi_get_nbits (prime_p) >= pbits-1
+          && check_prime (prime_p, val_2, 64, NULL, NULL) )
+        break; /* Yes, P is prime, continue with Step 15.  */
+      
+      /* Step 13: counter = counter + 1, offset = offset + n + 1. */
+      counter++;
+
+      /* Step 14: If counter >= 2^12  goto Step 1.  */
+      if (counter >= 4096)
+        goto restart;
+    }
+
+  /* Step 15:  Save p, q, counter and seed.  */
+/*   log_debug ("fips186-2 nbits p=%u q=%u counter=%d\n", */
+/*              mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */
+/*   log_printhex("fips186-2 seed:", seed, seedlen);  */
+/*   log_mpidump ("fips186-2 prime p", prime_p); */
+/*   log_mpidump ("fips186-2 prime q", prime_q); */
+  if (r_q)
+    {
+      *r_q = prime_q;
+      prime_q = NULL;
+    }
+  if (r_p)
+    {
+      *r_p = prime_p;
+      prime_p = NULL;
+    }
+  if (r_counter)
+    *r_counter = counter;
+  if (r_seed && r_seedlen)
+    {
+      memcpy (seed_plus, seed, seedlen);
+      *r_seed = seed_plus;
+      seed_plus = NULL;
+      *r_seedlen = seedlen;
+    }
+
+
+ leave:
+  gcry_mpi_release (tmpval);
+  gcry_mpi_release (value_x);
+  gcry_mpi_release (value_w);
+  gcry_mpi_release (prime_p);
+  gcry_mpi_release (prime_q);
+  gcry_free (seed_plus);
+  gcry_mpi_release (val_2);
+  return ec;
+}

Modified: trunk/cipher/rsa.c
===================================================================
--- trunk/cipher/rsa.c	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/rsa.c	2008-11-25 21:09:55 UTC (rev 1360)
@@ -793,7 +793,7 @@
                  gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL);
   if (!deriveparms)
     {
-      /* Parse the optional "rsa-use-x931" flag. */
+      /* Parse the optional "use-x931" flag. */
       l1 = gcry_sexp_find_token (genparms, "use-x931", 0);
       if (l1)
         {

Modified: trunk/doc/gcrypt.texi
===================================================================
--- trunk/doc/gcrypt.texi	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/doc/gcrypt.texi	2008-11-25 21:09:55 UTC (rev 1360)
@@ -2755,10 +2755,18 @@
 @item use-x931
 Force the use of the ANSI X9.31 key generation algorithm instead of
 the default algorithm. This flag is only meaningful for RSA and
-usullat not required.  Note that this algorithm is implicitly used if
-either @code{derive-parms} are given or Libgcrypt is in FIPS mode.
+usually not required.  Note that this algorithm is implicitly used if
+either @code{derive-parms} is given or Libgcrypt is in FIPS mode.
 
+ at item use-fips186
+Force the use of the FIPS 186-2 key generation algorithm instead of
+the default algorithm.  This flag is only meaningful for DSA and
+usually not required.  Note that this algorithm is implicitly used if
+either @code{derive-parms} is given or Libgcrypt is in FIPS mode.
+This implementation may be changed in future to use the forthcoming
+FIPS 186-3 algorithm.
 
+
 @end table
 @c end table of parameters
 

Modified: trunk/src/g10lib.h
===================================================================
--- trunk/src/g10lib.h	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/src/g10lib.h	2008-11-25 21:09:55 UTC (rev 1360)
@@ -179,6 +179,12 @@
                                     const gcry_mpi_t xp1, const gcry_mpi_t xp2,
                                     const gcry_mpi_t e,
                                     gcry_mpi_t *r_p1, gcry_mpi_t *r_p2);
+gpg_err_code_t _gcry_generate_fips186_2_prime
+                 (unsigned int pbits, unsigned int qbits,
+                  const void *seed, size_t seedlen,
+                  gcry_mpi_t *r_q, gcry_mpi_t *r_p,
+                  int *r_counter,
+                  void **r_seed, size_t *r_seedlen);
 
 
 /* replacements of missing functions (missing-string.c)*/

Modified: trunk/tests/pubkey.c
===================================================================
--- trunk/tests/pubkey.c	2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/tests/pubkey.c	2008-11-25 21:09:55 UTC (rev 1360)
@@ -364,7 +364,7 @@
   rc = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (rc)
-    die ("error generating Elgamal key: %s\n", gcry_strerror (rc));
+    die ("error generating DSA key: %s\n", gcry_strerror (rc));
     
   if (verbose > 1)
     show_sexp ("generated DSA key:\n", key);
@@ -384,6 +384,37 @@
 
 
 static void
+get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
+{
+  gcry_sexp_t key_spec, key, pub_key, sec_key;
+  int rc;
+
+  rc = gcry_sexp_new 
+    (&key_spec, "(genkey (dsa (nbits 4:1024)(use-fips186)))",  0, 1);
+  if (rc)
+    die ("error creating S-expression: %s\n", gcry_strerror (rc));
+  rc = gcry_pk_genkey (&key, key_spec);
+  gcry_sexp_release (key_spec);
+  if (rc)
+    die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    
+  if (verbose > 1)
+    show_sexp ("generated DSA key (fips 186):\n", key);
+
+  pub_key = gcry_sexp_find_token (key, "public-key", 0);
+  if (!pub_key)
+    die ("public part missing in key\n");
+
+  sec_key = gcry_sexp_find_token (key, "private-key", 0);
+  if (!sec_key)
+    die ("private part missing in key\n");
+
+  gcry_sexp_release (key);
+  *pkey = pub_key;
+  *skey = sec_key;
+}
+
+static void
 check_run (void)
 {
   gpg_error_t err;
@@ -440,6 +471,13 @@
   /* Fixme:  Add a check function for DSA keys.  */
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+
+  if (verbose)
+    fprintf (stderr, "Generating DSA key (FIPS 186).\n");
+  get_dsa_key_fips186_new (&pkey, &skey);
+  /* Fixme:  Add a check function for DSA keys.  */
+  gcry_sexp_release (pkey);
+  gcry_sexp_release (skey);
 }
 
 
@@ -684,7 +722,7 @@
   for (i=0; i < 2; i++)
     check_run ();
 
-  for (i=0; i < 4; i++) 
+  for (i=0; i < 4; i++)
     check_x931_derived_key (i);
   
   return 0;




More information about the Gnupg-commits mailing list