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

svn author wk cvs at cvs.gnupg.org
Mon Nov 24 17:37:51 CET 2008


Author: wk
Date: 2008-11-24 17:37:50 +0100 (Mon, 24 Nov 2008)
New Revision: 1358

Modified:
   trunk/cipher/ChangeLog
   trunk/cipher/dsa.c
   trunk/cipher/ecc.c
   trunk/cipher/elgamal.c
   trunk/cipher/primegen.c
   trunk/cipher/pubkey.c
   trunk/cipher/rsa.c
   trunk/doc/gcrypt.texi
   trunk/src/ChangeLog
   trunk/src/cipher-proto.h
   trunk/src/cipher.h
   trunk/src/g10lib.h
   trunk/tests/ChangeLog
   trunk/tests/cavs_driver.pl
   trunk/tests/fipsdrv.c
   trunk/tests/pubkey.c
Log:
Cleaned up the public key module calling conventions.
Add a way to derive RSA keys according to X9.31.


[The diff below has been truncated]

Modified: trunk/cipher/ChangeLog
===================================================================
--- trunk/cipher/ChangeLog	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/ChangeLog	2008-11-24 16:37:50 UTC (rev 1358)
@@ -1,3 +1,38 @@
+2008-11-24  Werner Koch  <wk at g10code.com>
+
+	* pubkey.c (gcry_pk_genkey): Remove parsing of almost all
+	parameters and pass the parameter S-expression to pubkey_generate.
+	(pubkey_generate): Simplify by requitring modules to parse the
+	parameters. Remove the special cases for Elgamal and ECC.
+	(sexp_elements_extract_ecc): Add arg EXTRASPEC and use it.  Fix
+	small memory leak.
+	(sexp_to_key): Pass EXTRASPEC to sexp_elements_extract_ecc.
+	(pubkey_table) [USE_ELGAMAL]: Add real extraspec.
+	* rsa.c (rsa_generate_ext): Adjust for new calling convention.
+	* dsa.c (dsa_generate_ext): Ditto.
+	* elgamal.c (_gcry_elg_generate): Ditto. Rename to elg_generate_ext.
+	(elg_generate): New.
+	(_gcry_elg_generate_using_x): Remove after merging code with
+	elg_generate_ext.
+	(_gcry_pubkey_extraspec_elg): New.
+	(_gcry_elg_check_secret_key, _gcry_elg_encrypt, _gcry_elg_sign) 
+	(_gcry_elg_verify, _gcry_elg_get_nbits): Make static and remove
+	_gcry_ prefix.
+	* ecc.c (_gcry_ecc_generate): Rename to ecc_generate_ext and
+	adjust for new calling convention.
+	(_gcry_ecc_get_param): Rename to ecc_get_param and make static.
+	(_gcry_pubkey_extraspec_ecdsa): Add ecc_generate_ext and
+	ecc_get_param.
+	
+2008-11-20  Werner Koch  <wk at g10code.com>
+
+	* pubkey.c (pubkey_generate): Add arg DERIVEPARMS.
+	(gcry_pk_genkey): Parse derive-parms and pass it to above.
+	* rsa.c (generate_x931): New.
+	(rsa_generate_ext): Add arg DERIVEPARMS and call new function in
+	fips mode or if DERIVEPARMS is given.
+	* primegen.c (_gcry_derive_x931_prime, find_x931_prime): New.
+
 2008-11-19  Werner Koch  <wk at g10code.com>
 
 	* rsa.c (rsa_decrypt): Use gcry_create_nonce for blinding.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/src/ChangeLog	2008-11-24 16:37:50 UTC (rev 1358)
@@ -1,3 +1,11 @@
+2008-11-24  Werner Koch  <wk at g10code.com>
+
+	* cipher-proto.h (pk_ext_generate_t): Simplify. 
+	(pk_get_param): New.
+	(pk_extra_spec_t): Add field GET_PARAM.
+	* cipher.h (PUBKEY_FLAG_TRANSIENT_KEY): Remove.
+	(_gcry_pubkey_extraspec_elg): New.
+
 2008-11-05  Werner Koch  <wk at g10code.com>
 
 	* cipher.h (CIPHER_INFO_NO_WEAK_KEY): New.

Modified: trunk/tests/ChangeLog
===================================================================
--- trunk/tests/ChangeLog	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/tests/ChangeLog	2008-11-24 16:37:50 UTC (rev 1358)
@@ -1,3 +1,7 @@
+2008-11-24  Werner Koch  <wk at g10code.com>
+
+	* pubkey.c (check_x931_derived_key): New.
+
 2008-11-07  Werner Koch  <wk at g10code.com>
 
 	* fipsdrv.c (run_cipher_mct_loop, get_current_iv): New.

Modified: trunk/cipher/dsa.c
===================================================================
--- trunk/cipher/dsa.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/dsa.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -459,21 +459,41 @@
  *********************************************/
 
 static gcry_err_code_t
-dsa_generate_ext (int algo, unsigned int nbits, unsigned int qbits, 
-                  unsigned long use_e,
-                  const char *name, const gcry_sexp_t domain,
-                  unsigned int keygen_flags,
+dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
+                  const gcry_sexp_t genparms,
                   gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   gpg_err_code_t ec;
   DSA_secret_key sk;
+  gcry_sexp_t l1;
+  unsigned int qbits = 0;
 
-  (void)algo;
-  (void)use_e;
-  (void)name;
-  (void)domain;
-  (void)keygen_flags;
+  (void)algo;    /* No need to check it.  */
+  (void)evalue;  /* Not required for DSA. */
 
+  /* Parse the optional qbits element. */
+  if (genparms)
+    {
+      l1 = gcry_sexp_find_token (genparms, "qbits", 0);
+      if (l1)
+        {
+          char buf[50];
+          const char *s;
+          size_t n;
+          
+          s = gcry_sexp_nth_data (l1, 1, &n);
+          if (!s || n >= DIM (buf) - 1 )
+            {
+              gcry_sexp_release (l1);
+              return GPG_ERR_INV_OBJ; /* No value or value too large.  */
+            }
+          memcpy (buf, s, n);
+          buf[n] = 0;
+          qbits = (unsigned int)strtoul (buf, NULL, 0);
+          gcry_sexp_release (l1);
+        }
+    }
+
   ec = generate (&sk, nbits, qbits, retfactors);
   if (!ec)
     {
@@ -489,11 +509,11 @@
 
 
 static gcry_err_code_t
-dsa_generate (int algo, unsigned int nbits, unsigned long dummy,
+dsa_generate (int algo, unsigned int nbits, unsigned long evalue,
               gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
-  (void)dummy;
-  return dsa_generate_ext (algo, nbits, 0, 0, NULL, NULL, 0, skey, retfactors);
+  (void)evalue;
+  return dsa_generate_ext (algo, nbits, 0, NULL, skey, retfactors);
 }
 
 

Modified: trunk/cipher/ecc.c
===================================================================
--- trunk/cipher/ecc.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/ecc.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -949,35 +949,47 @@
   return 0;
 }
 
-/* Extended version of ecc_generate which is called directly by
-   pubkey.c.  If CURVE is not NULL, that name will be used to select
-   the domain parameters.  NBITS is not used in this case.  */
-gcry_err_code_t
-_gcry_ecc_generate (int algo, unsigned int nbits, const char *curve,
-                    gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+
+/* Extended version of ecc_generate.  */
+static gcry_err_code_t
+ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
+                  const gcry_sexp_t genparms,
+                  gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
-  gpg_err_code_t err;
+  gpg_err_code_t ec;
   ECC_secret_key sk;
   gcry_mpi_t g_x, g_y, q_x, q_y;
+  char *curve_name = NULL;
+  gcry_sexp_t l1;
 
   (void)algo;
+  (void)evalue;
 
-  /* Make an empty list of factors.  */
-  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
-  if (!*retfactors)
-    return gpg_err_code_from_syserror ();
+  if (genparms)
+    {
+      /* Parse the optional "curve" parameter. */
+      l1 = gcry_sexp_find_token (genparms, "curve", 0);
+      if (l1)
+        {
+          curve_name = _gcry_sexp_nth_string (l1, 1);
+          gcry_sexp_release (l1);
+          if (!curve_name)
+            return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
+        }
+    }
 
+  /* NBITS is required if no curve name has been given.  */
+  if (!nbits && !curve_name)
+    return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
+
   g_x = mpi_new (0);
   g_y = mpi_new (0);
   q_x = mpi_new (0);
   q_y = mpi_new (0);
-  err = generate_key (&sk, nbits, curve, g_x, g_y, q_x, q_y);
-  if (err)
-    {
-      gcry_free (*retfactors);
-      *retfactors = NULL;
-      return err;
-    }
+  ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y);
+  gcry_free (curve_name);
+  if (ec)
+    return ec;
 
   skey[0] = sk.E.p;
   skey[1] = sk.E.a;
@@ -992,12 +1004,27 @@
   point_free (&sk.E.G);
   point_free (&sk.Q);
 
+  /* Make an empty list of factors.  */
+  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
+  if (!*retfactors)
+    return gpg_err_code_from_syserror ();
+
   return 0;
 }
 
+
+static gcry_err_code_t
+ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
+              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+{
+  (void)evalue;
+  return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors);
+}
+
+
 /* Return the parameters of the curve NAME.  */
-gcry_err_code_t
-_gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
+static gcry_err_code_t
+ecc_get_param (const char *name, gcry_mpi_t *pkey)
 {
   gpg_err_code_t err;
   unsigned int nbits;
@@ -1027,15 +1054,7 @@
   return 0;
 }
 
-static gcry_err_code_t
-ecc_generate (int algo, unsigned int nbits, unsigned long dummy,
-              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-{
-  (void)dummy;
-  return _gcry_ecc_generate (algo, nbits, NULL, skey, retfactors);
-}
 
-
 static gcry_err_code_t
 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
 {
@@ -1230,7 +1249,7 @@
           ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
           goto leave;
         }
-      ec = _gcry_ecc_get_param (curve, tmpvalues);
+      ec = ecc_get_param (curve, tmpvalues);
       gcry_free (curve);
       if (ec)
         goto leave;
@@ -1358,10 +1377,12 @@
     ecc_verify,
     ecc_get_nbits
   };
+
 pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = 
   {
     run_selftests,
-    NULL,
-    compute_keygrip
+    ecc_generate_ext,
+    compute_keygrip,
+    ecc_get_param
   };
 

Modified: trunk/cipher/elgamal.c
===================================================================
--- trunk/cipher/elgamal.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/elgamal.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -1,10 +1,11 @@
 /* Elgamal.c  -  Elgamal Public Key encryption
- * Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2000, 2001, 2002, 2003,
+ *               2008  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  * Libgcrypt is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser general Public License as
+ * it under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
@@ -14,8 +15,7 @@
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * For a description of the algorithm, see:
  *   Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
@@ -612,50 +612,70 @@
  **************  interface  ******************
  *********************************************/
 
-gcry_err_code_t
-_gcry_elg_generate (int algo, unsigned int nbits, unsigned long dummy,
-                    gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+static gpg_err_code_t
+elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
+                  const gcry_sexp_t genparms,
+                  gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
+  gpg_err_code_t ec;
   ELG_secret_key sk;
+  gcry_mpi_t xvalue = NULL;
+  gcry_sexp_t l1;
 
   (void)algo;
-  (void)dummy;
+  (void)evalue;
 
-  generate (&sk, nbits, retfactors);
+  if (genparms)
+    {
+      /* Parse the optional xvalue element. */
+      l1 = gcry_sexp_find_token (genparms, "xvalue", 0);
+      if (l1)
+        {
+          xvalue = gcry_sexp_nth_mpi (l1, 1, 0);
+          gcry_sexp_release (l1);
+          if (!xvalue)
+            return GPG_ERR_BAD_MPI;
+        }
+    }
+
+  if (xvalue)
+    ec = generate_using_x (&sk, nbits, xvalue, retfactors);
+  else
+    {
+      generate (&sk, nbits, retfactors);
+      ec = 0;
+    }
+
   skey[0] = sk.p;
   skey[1] = sk.g;
   skey[2] = sk.y;
   skey[3] = sk.x;
   
-  return GPG_ERR_NO_ERROR;
+  return ec;
 }
 
 
-/* This is a specila generate function which is not called via the
-   module interface.  */
-gcry_err_code_t
-_gcry_elg_generate_using_x (int algo, unsigned int nbits, gcry_mpi_t x,
-                            gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+static gcry_err_code_t
+elg_generate (int algo, unsigned int nbits, unsigned long evalue,
+              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
-  gcry_err_code_t ec;
   ELG_secret_key sk;
 
   (void)algo;
+  (void)evalue;
 
-  ec = generate_using_x (&sk, nbits, x, retfactors);
-  if (!ec)
-    {
-      skey[0] = sk.p;
-      skey[1] = sk.g;
-      skey[2] = sk.y;
-      skey[3] = sk.x;
-    }
-  return ec;
+  generate (&sk, nbits, retfactors);
+  skey[0] = sk.p;
+  skey[1] = sk.g;
+  skey[2] = sk.y;
+  skey[3] = sk.x;
+  
+  return GPG_ERR_NO_ERROR;
 }
 
 
-gcry_err_code_t
-_gcry_elg_check_secret_key (int algo, gcry_mpi_t *skey)
+static gcry_err_code_t
+elg_check_secret_key (int algo, gcry_mpi_t *skey)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   ELG_secret_key sk;
@@ -679,9 +699,9 @@
 }
 
 
-gcry_err_code_t
-_gcry_elg_encrypt (int algo, gcry_mpi_t *resarr,
-                   gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
+static gcry_err_code_t
+elg_encrypt (int algo, gcry_mpi_t *resarr,
+             gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   ELG_public_key pk;
@@ -704,9 +724,9 @@
 }
 
 
-gcry_err_code_t
-_gcry_elg_decrypt (int algo, gcry_mpi_t *result,
-                   gcry_mpi_t *data, gcry_mpi_t *skey, int flags)
+static gcry_err_code_t
+elg_decrypt (int algo, gcry_mpi_t *result,
+             gcry_mpi_t *data, gcry_mpi_t *skey, int flags)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   ELG_secret_key sk;
@@ -730,8 +750,8 @@
 }
 
 
-gcry_err_code_t
-_gcry_elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
+static gcry_err_code_t
+elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   ELG_secret_key sk;
@@ -755,9 +775,10 @@
   return err;
 }
 
-gcry_err_code_t
-_gcry_elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
-		  int (*cmp) (void *, gcry_mpi_t), void *opaquev)
+
+static gcry_err_code_t
+elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
+            int (*cmp) (void *, gcry_mpi_t), void *opaquev)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   ELG_public_key pk;
@@ -782,14 +803,15 @@
 }
 
 
-unsigned int
-_gcry_elg_get_nbits (int algo, gcry_mpi_t *pkey)
+static unsigned int
+elg_get_nbits (int algo, gcry_mpi_t *pkey)
 {
   (void)algo;
 
   return mpi_get_nbits (pkey[0]);
 }
 
+
 static const char *elg_names[] =
   {
     "elg",
@@ -804,11 +826,19 @@
     "ELG", elg_names,
     "pgy", "pgyx", "ab", "rs", "pgy",
     GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR,
-    _gcry_elg_generate,
-    _gcry_elg_check_secret_key,
-    _gcry_elg_encrypt,
-    _gcry_elg_decrypt,
-    _gcry_elg_sign,
-    _gcry_elg_verify,
-    _gcry_elg_get_nbits,
+    elg_generate,
+    elg_check_secret_key,
+    elg_encrypt,
+    elg_decrypt,
+    elg_sign,
+    elg_verify,
+    elg_get_nbits
   };
+
+pk_extra_spec_t _gcry_pubkey_extraspec_elg = 
+  {
+    NULL,
+    elg_generate_ext,
+    NULL
+  };
+

Modified: trunk/cipher/primegen.c
===================================================================
--- trunk/cipher/primegen.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/primegen.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -1,6 +1,6 @@
 /* primegen.c - prime number generator
  * Copyright (C) 1998, 2000, 2001, 2002, 2003
- *               2004 Free Software Foundation, Inc.
+ *               2004, 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -1272,3 +1272,142 @@
       gcry_free (factors);
     }
 }
+
+
+/* Helper for _gcry_generate_x931_prime.  */
+static gcry_mpi_t
+find_x931_prime (const gcry_mpi_t pfirst)
+{
+  gcry_mpi_t val_2 = mpi_alloc_set_ui (2); 
+  gcry_mpi_t prime;
+  
+  prime = gcry_mpi_copy (pfirst);
+  /* If P is even add 1.  */ 
+  mpi_set_bit (prime, 0);
+
+  /* We use 64 Rabin-Miller rounds which is better and thus
+     sufficient.  We do not have a Lucas test implementaion thus we
+     can't do it in the X9.31 preferred way of running a few
+     Rabin-Miller followed by one Lucas test.  */
+  while ( !check_prime (prime, val_2, 64, NULL, NULL) )
+    mpi_add_ui (prime, prime, 2);
+
+  mpi_free (val_2);
+
+  return prime;
+}
+
+
+/* Generate a prime using the algorithm from X9.31 appendix B.4. 
+
+   This function requires that the provided public exponent E is odd.
+   XP, XP1 and XP2 are the seed values.  All values are mandatory.
+
+   On success the prime is returned.  If R_P1 or R_P2 are given the
+   internal values P1 and P2 are saved at these addresses.  On error
+   NULL is returned.  */
+gcry_mpi_t
+_gcry_derive_x931_prime (const gcry_mpi_t xp, 
+                         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)
+{
+  gcry_mpi_t p1, p2, p1p2, yp0;
+
+  if (!xp || !xp1 || !xp2)
+    return NULL;
+  if (!e || !mpi_test_bit (e, 0))
+    return NULL;  /* We support only odd values for E.  */
+
+  p1 = find_x931_prime (xp1);
+  p2 = find_x931_prime (xp2);
+  p1p2 = mpi_alloc_like (xp);
+  mpi_mul (p1p2, p1, p2);
+
+  {
+    gcry_mpi_t r1, tmp;
+  
+    /* r1 = (p2^{-1} mod p1)p2 - (p1^{-1} mod p2) */
+    tmp = mpi_alloc_like (p1);
+    mpi_invm (tmp, p2, p1);
+    mpi_mul (tmp, tmp, p2);
+    r1 = tmp;
+    
+    tmp = mpi_alloc_like (p2);
+    mpi_invm (tmp, p1, p2);
+    mpi_mul (tmp, tmp, p1);
+    mpi_sub (r1, r1, tmp);
+
+    /* Fixup a negative value.  */
+    if (mpi_is_neg (r1)) 
+      mpi_add (r1, r1, p1p2);
+
+    /* yp0 = xp + (r1 - xp mod p1*p2)  */
+    yp0 = tmp; tmp = NULL;
+    mpi_subm (yp0, r1, xp, p1p2);
+    mpi_add (yp0, yp0, xp);
+    mpi_free (r1);
+
+    /* Fixup a negative value.  */
+    if (mpi_cmp (yp0, xp) < 0 ) 
+      mpi_add (yp0, yp0, p1p2);
+  }
+
+  /* yp0 is now the first integer greater than xp with p1 being a
+     large prime factor of yp0-1 and p2 a large prime factor of yp0+1.  */
+
+  /* Note that the first example from X9.31 (D.1.1) which uses
+       (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)
+       (Xq2 #134E4CAA16D2350A21D775C404#)
+       (Xq  #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+             7C9953388F97DDDC3E1CA19C35CA659EDC2FC325
+             6D29C2627479C086A699A49C4C9CEE7EF7BD1B34
+             321DE34A#))))
+     returns an yp0 of
+            #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+             7C9953388F97DDDC3E1CA19C35CA659EDC2FC4E3
+             BF20CB896EE37E098A906313271422162CB6C642
+             75C1201F#
+     and not
+            #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+             7C9953388F97DDDC3E1CA19C35CA659EDC2FC2E6
+             C88FE299D52D78BE405A97E01FD71DD7819ECB91
+             FA85A076#
+     as stated in the standard.  This seems to be a bug in X9.31.
+   */
+
+  {
+    gcry_mpi_t val_2 = mpi_alloc_set_ui (2); 
+    gcry_mpi_t gcdtmp = mpi_alloc_like (yp0);
+    int gcdres;
+  
+    mpi_sub_ui (p1p2, p1p2, 1); /* Adjust for loop body.  */
+    mpi_sub_ui (yp0, yp0, 1);   /* Ditto.  */
+    for (;;)
+      {
+        gcdres = gcry_mpi_gcd (gcdtmp, e, yp0);
+        mpi_add_ui (yp0, yp0, 1);
+        if (!gcdres)
+          progress ('/');  /* gcd (e, yp0-1) != 1  */
+        else if (check_prime (yp0, val_2, 64, NULL, NULL))
+          break; /* Found.  */
+        /* We add p1p2-1 because yp0 is incremented after the gcd test.  */
+        mpi_add (yp0, yp0, p1p2);
+      }
+    mpi_free (gcdtmp);
+    mpi_free (val_2);
+  }
+
+  mpi_free (p1p2);
+
+  progress('\n');
+  if (r_p1)
+    *r_p1 = p1;
+  else
+    mpi_free (p1);
+  if (r_p2)
+    *r_p2 = p2;
+  else
+    mpi_free (p2);
+  return yp0;
+}

Modified: trunk/cipher/pubkey.c
===================================================================
--- trunk/cipher/pubkey.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/pubkey.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -64,9 +64,9 @@
 #endif
 #if USE_ELGAMAL
     { &_gcry_pubkey_spec_elg,
-      &dummy_extra_spec,             GCRY_PK_ELG   },
+      &_gcry_pubkey_extraspec_elg,    GCRY_PK_ELG   },
     { &_gcry_pubkey_spec_elg,
-      &dummy_extra_spec,             GCRY_PK_ELG_E },
+      &_gcry_pubkey_extraspec_elg,    GCRY_PK_ELG_E },
 #endif
 #if USE_DSA
     { &_gcry_pubkey_spec_dsa,
@@ -530,17 +530,18 @@
 
 
 /* Generate a new public key with algorithm ALGORITHM of size NBITS
-   and return it at SKEY. The use of the arguments QBITS, USE_E,
-   XVALUE, CURVE_NAME and DOMAIN depend on the ALGORITHM.  RETFACTOR
-   is used by some algorithms to return certain additional information
-   which are in general not required.
+   and return it at SKEY.  USE_E depends on the ALGORITHM.  GENPARMS
+   is passed to the algorithm module if it features an extended
+   generation function.  RETFACTOR is used by some algorithms to
+   return certain additional information which are in general not
+   required.
 
    The function returns the error code number or 0 on success. */
 static gcry_err_code_t
-pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
-                 unsigned long use_e, gcry_mpi_t xvalue,
-                 const char *curve_name, gcry_sexp_t domain,
-                 unsigned int keygen_flags,
+pubkey_generate (int algorithm,
+                 unsigned int nbits,
+                 unsigned long use_e,
+                 gcry_sexp_t genparms,
                  gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   gcry_err_code_t ec = GPG_ERR_PUBKEY_ALGO;
@@ -554,44 +555,12 @@
     {
       pk_extra_spec_t *extraspec = pubkey->extraspec;
 
-      if (keygen_flags && (!extraspec || !extraspec->ext_generate))
+      if (extraspec && extraspec->ext_generate)
         {
-          /* A keygen flag has been given but the module does not
-             provide an ext_generate function.  We don't want to
-             ignore such a condition as it might eventually be
-             security sensitive..  */
-          ec = GPG_ERR_INV_FLAG;
+          /* Use the extended generate function.  */
+          ec = extraspec->ext_generate 
+            (algorithm, nbits, use_e, genparms, skey, retfactors);
         }
-#ifdef USE_ELGAMAL
-      else if (xvalue && pubkey->spec == &_gcry_pubkey_spec_elg)
-        {
-          /* Fixme: Merge this into an ext_generate fucntion.  */
-          ec = _gcry_elg_generate_using_x
-            (algorithm, nbits, xvalue, skey, retfactors);
-        }
-#endif /*USE_ELGAMAL*/
-#ifdef USE_ECC
-      else if (curve_name && pubkey->spec == &_gcry_pubkey_spec_ecdsa)
-        {
-          /* Fixme: Merge this into an ext_generate fucntion.  */
-          ec = _gcry_ecc_generate
-            (algorithm, nbits, curve_name, skey, retfactors);
-        }
-#endif /*USE_ECC*/
-      else if (extraspec && extraspec->ext_generate)
-        {
-          /* Use the extended generate function if available.  */
-          ec = extraspec->ext_generate (algorithm, nbits, qbits, use_e,
-                                        NULL, domain, keygen_flags,
-                                        skey, retfactors);
-        }
-      else if (qbits || domain)
-        {
-          /* A qbits or domain parameter is specified but the
-             algorithm does not feature an extended generation
-             function.  */
-          ec = GPG_ERR_INV_PARAMETER;
-        }
       else
         {
           /* Use the standard generate function.  */
@@ -605,6 +574,7 @@
   return ec;
 }
 
+
 static gcry_err_code_t
 pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey)
 {
@@ -868,11 +838,13 @@
   return err;
 }
 
+
 /* Internal function used for ecc.  Note, that this function makes use
    of its intimate knowledge about the ECC parameters from ecc.c. */
 static gcry_err_code_t
 sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
-                           gcry_mpi_t *elements)
+                           gcry_mpi_t *elements, pk_extra_spec_t *extraspec)
+
 {
   gcry_err_code_t err = 0;
   int idx;
@@ -907,35 +879,41 @@
   list = gcry_sexp_find_token (key_sexp, "curve", 5);
   if (list)
     {
-#if USE_ECC
-      char *curve;
-      gcry_mpi_t params[6];
-
-      for (idx = 0; idx < DIM(params); idx++)
-        params[idx] = NULL;
-
-      curve = _gcry_sexp_nth_string (list, 1);
-      if (!curve)
+      if (extraspec->get_param)
         {
-          err = GPG_ERR_INV_OBJ; /* No curve name given (or out of core). */
-          goto leave;
+          char *curve;
+          gcry_mpi_t params[6];
+          
+          for (idx = 0; idx < DIM(params); idx++)
+            params[idx] = NULL;
+          
+          curve = _gcry_sexp_nth_string (list, 1);
+          gcry_sexp_release (list);
+          if (!curve)
+            {
+              /* No curve name given (or out of core). */
+              err = GPG_ERR_INV_OBJ; 
+              goto leave;
+            }
+          err = extraspec->get_param (curve, params);
+          gcry_free (curve);
+          if (err)
+            goto leave;
+          
+          for (idx = 0; idx < DIM(params); idx++)
+            {
+              if (!elements[idx])
+                elements[idx] = params[idx];
+              else
+                mpi_free (params[idx]);
+            }
         }
-      err = _gcry_ecc_get_param (curve, params);
-      gcry_free (curve);
-      if (err)
-        goto leave;
-
-      for (idx = 0; idx < DIM(params); idx++)
+      else
         {
-          if (!elements[idx])
-            elements[idx] = params[idx];
-          else
-            mpi_free (params[idx]);
+          gcry_sexp_release (list);
+          err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
+          goto leave;
         }
-#else /* !USE_ECC */
-      err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
-      goto leave;
-#endif /* !USE_ECC */
     }
 
   /* Check that all parameters are known.  */
@@ -1001,6 +979,7 @@
   gcry_mpi_t *array;
   gcry_module_t module;
   gcry_pk_spec_t *pubkey;
+  pk_extra_spec_t *extraspec;
   int is_ecc;
 
   /* Check that the first element is valid.  */
@@ -1038,7 +1017,10 @@
       return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
     }
   else
-    pubkey = (gcry_pk_spec_t *) module->spec;
+    {
+      pubkey = (gcry_pk_spec_t *) module->spec;
+      extraspec = module->extraspec;
+    }
 
   elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
   array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
@@ -1047,7 +1029,7 @@
   if (!err)
     {
       if (is_ecc)
-        err = sexp_elements_extract_ecc (list, elems, array);
+        err = sexp_elements_extract_ecc (list, elems, array, extraspec);
       else
         err = sexp_elements_extract (list, elems, array, pubkey->name);
     }
@@ -2084,7 +2066,9 @@
 {
   gcry_pk_spec_t *pubkey = NULL;
   gcry_module_t module = NULL;
-  gcry_sexp_t list = NULL, l2 = NULL;
+  gcry_sexp_t list = NULL;
+  gcry_sexp_t l2 = NULL;
+  gcry_sexp_t l3 = NULL;
   char *name = NULL;
   size_t n;
   gcry_err_code_t rc = GPG_ERR_NO_ERROR;
@@ -2095,10 +2079,6 @@
   gcry_mpi_t skey[12], *factors = NULL;
   unsigned int nbits = 0;
   unsigned long use_e = 0;
-  unsigned int qbits;
-  gcry_mpi_t xvalue = NULL;
-  char *curve = NULL;
-  unsigned int keygen_flags = 0;
 
   skey[0] = NULL;
   *r_key = NULL;
@@ -2150,7 +2130,9 @@
   if (strlen (sec_elems) >= DIM(skey))
     BUG ();
 
-  /* Handle the optional rsa-use-e element. */
+  /* Handle the optional rsa-use-e element.  Actually this belong into
+     the algorithm module but we have this parameter in the public
+     moudle API, so we need to parse it right here.  */
   l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
   if (l2)
     {
@@ -2172,8 +2154,9 @@
   else
     use_e = 65537; /* Not given, use the value generated by old versions. */
 
-  /* Handle the optional qbits element. */
-  l2 = gcry_sexp_find_token (list, "qbits", 0);
+
+  /* Get the "nbits" parameter.  */
+  l2 = gcry_sexp_find_token (list, "nbits", 0);
   if (l2)
     {
       char buf[50];
@@ -2182,91 +2165,24 @@
       s = gcry_sexp_nth_data (l2, 1, &n);
       if (!s || n >= DIM (buf) - 1 )
         {
-          rc = GPG_ERR_INV_OBJ; /* No value or value too large.  */
-          goto leave;
-        }
-      memcpy (buf, s, n);
-      buf[n] = 0;
-      qbits = (unsigned int)strtoul (buf, NULL, 0);
-      gcry_sexp_release (l2);
-      l2 = NULL;
-    }
-  else
-    qbits = 0;
-
-  /* Parse the optional xvalue element. */
-  l2 = gcry_sexp_find_token (list, "xvalue", 0);
-  if (l2)
-    {
-      xvalue = gcry_sexp_nth_mpi (l2, 1, 0);
-      if (!xvalue)
-        {
-          rc = GPG_ERR_BAD_MPI;
-          goto leave;
-        }
-    }
-
-  /* Parse the optional "curve" parameter. */
-  l2 = gcry_sexp_find_token (list, "curve", 0);
-  if (l2)
-    {
-      curve = _gcry_sexp_nth_string (l2, 1);
-      if (!curve)
-        {
-          rc = GPG_ERR_INV_OBJ; /* No curve name or value too large. */
-          goto leave;
-        }
-      gcry_sexp_release (l2);
-      l2 = NULL;
-    }
-
-  /* Parse the optional "transient-key" flag. */
-  l2 = gcry_sexp_find_token (list, "transient-key", 0);
-  if (l2)
-    {
-      keygen_flags |= PUBKEY_FLAG_TRANSIENT_KEY;
-      gcry_sexp_release (l2);
-      l2 = NULL;
-    }
-
-
-  /* Unless a curve name has been given, the "nbits" parameter is
-     required.  */
-  l2 = gcry_sexp_find_token (list, "nbits", 0);
-  gcry_sexp_release (list);
-  list = l2;
-  l2 = NULL;
-  if (!list && !curve)
-    {
-      rc = GPG_ERR_NO_OBJ; /* No nbits parameter. */
-      goto leave;
-    }
-  if (list)
-    {
-      char buf[50];
-      const char *s;
-
-      s = gcry_sexp_nth_data (list, 1, &n);
-      if (!s || n >= DIM (buf) - 1 )
-        {
           rc = GPG_ERR_INV_OBJ; /* NBITS given without a cdr.  */
           goto leave;
         }
       memcpy (buf, s, n);
       buf[n] = 0;
       nbits = (unsigned int)strtoul (buf, NULL, 0);
+      gcry_sexp_release (l2); l2 = NULL;
     }
   else 
     nbits = 0;
 
-  /* Extract the optional domain parameter and call the key generation.  */
-  l2 = gcry_sexp_find_token (list, "domain", 0);
-  rc = pubkey_generate (module->mod_id, nbits, qbits, use_e, xvalue,
-                        curve, l2, keygen_flags, skey, &factors);
-  gcry_sexp_release (l2);
+  /* Pass control to the algorithm module. */
+  rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey, &factors);
+  gcry_sexp_release (list); list = NULL;
   if (rc)
     goto leave;
 
+  /* Key generation succeeded: Build an S-expression.  */
   {
     char *string, *p;
     size_t nelem=0, nelem_cp = 0, needed=0;
@@ -2312,7 +2228,7 @@
       }
     p = stpcpy (p, "))");
 
-    /* Very ugly hack to make release_mpi_array() work FIXME */
+    /* Hack to make release_mpi_array() work.  */
     skey[i] = NULL;
 
     if (factors[0])
@@ -2359,22 +2275,18 @@
 
  leave:
   gcry_free (name);
-  gcry_free (curve);
   release_mpi_array (skey);
-  /* Don't free SKEY itself, it is a static array. */
+  /* Don't free SKEY itself, it is an stack allocated array. */
 
-  gcry_mpi_release (xvalue);
-  
   if (factors)
     {
       release_mpi_array ( factors );
       gcry_free (factors);
     }
   
-  if (l2)
-    gcry_sexp_release (l2);
-  if (list)
-    gcry_sexp_release (list);
+  gcry_sexp_release (l3);
+  gcry_sexp_release (l2);
+  gcry_sexp_release (list);
 
   if (module)
     {

Modified: trunk/cipher/rsa.c
===================================================================
--- trunk/cipher/rsa.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/cipher/rsa.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -207,8 +207,8 @@
   if ( (nbits&1) )
     nbits++; 
 
-  if (use_e == 1)   /* Alias for a secure value. */
-    use_e = 65537;  /* as demanded by Spinx. */
+  if (use_e == 1)   /* Alias for a secure value */
+    use_e = 65537;  /* as demanded by Sphinx. */
 
   /* Public exponent:
      In general we use 41 as this is quite fast and more secure than the
@@ -328,6 +328,191 @@
 }
 
 
+/* Variant of the standard key generation code using the algorithm
+   from X9.31.  Using this algorithm has the advantage that the
+   generation can be made deterministic which is required for CAVS
+   testing.  */
+static gpg_err_code_t
+generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
+               gcry_sexp_t deriveparms, int *swapped)
+{
+  gcry_mpi_t p, q; /* The two primes.  */
+  gcry_mpi_t e;    /* The public exponent.  */
+  gcry_mpi_t n;    /* The public key.  */
+  gcry_mpi_t d;    /* The private key */
+  gcry_mpi_t u;    /* The inverse of p and q.  */
+  gcry_mpi_t pm1;  /* p - 1  */
+  gcry_mpi_t qm1;  /* q - 1  */
+  gcry_mpi_t phi;  /* Euler totient.  */
+  gcry_mpi_t f, g; /* Helper.  */
+
+  *swapped = 0;
+
+  if (e_value == 1)   /* Alias for a secure value. */
+    e_value = 65537; 
+
+  /* Point 1 of section 4.1:  k = 1024 + 256s with S >= 0  */
+  if (nbits < 1024 || (nbits % 256))
+    return GPG_ERR_INV_VALUE;
+  
+  /* Point 2:  2 <= bitlength(e) < 2^{k-2}
+     Note that we do not need to check the upper bound because we use
+     an unsigned long for E and thus there is no way for E to reach
+     that limit.  */
+  if (e_value < 3)
+    return GPG_ERR_INV_VALUE;
+     
+  /* Our implementaion requires E to be odd.  */
+  if (!(e_value & 1))
+    return GPG_ERR_INV_VALUE;
+
+  /* Point 3:  e > 0 or e 0 if it is to be randomly generated.
+     We support only a fixed E and thus there is no need for an extra test.  */
+
+
+  /* Compute or extract the derive parameters.  */
+  {
+    gcry_mpi_t xp1 = NULL;
+    gcry_mpi_t xp2 = NULL;
+    gcry_mpi_t xp  = NULL;
+    gcry_mpi_t xq1 = NULL;
+    gcry_mpi_t xq2 = NULL;
+    gcry_mpi_t xq  = NULL;
+
+    if (!deriveparms)
+      {
+        /* Fixme: Create them.  */
+        return GPG_ERR_INV_VALUE;
+      }
+    else
+      {
+        struct { const char *name; gcry_mpi_t *value; } tbl[] = {
+          { "Xp1", &xp1 },
+          { "Xp2", &xp2 },
+          { "Xp",  &xp  },
+          { "Xq1", &xq1 },
+          { "Xq2", &xq2 },
+          { "Xq",  &xq  },
+          { NULL,  NULL }
+        };
+        int idx;
+        gcry_sexp_t oneparm;
+        
+        for (idx=0; tbl[idx].name; idx++)
+          {
+            oneparm = gcry_sexp_find_token (deriveparms, tbl[idx].name, 0);
+            if (oneparm)
+              {
+                *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1,
+                                                     GCRYMPI_FMT_USG);
+                gcry_sexp_release (oneparm);
+              }
+          }
+        for (idx=0; tbl[idx].name; idx++)
+          if (!*tbl[idx].value)
+            break;
+        if (tbl[idx].name)
+          {
+            /* At least one parameter is missing.  */
+            for (idx=0; tbl[idx].name; idx++)
+              gcry_mpi_release (*tbl[idx].value);
+            return GPG_ERR_MISSING_VALUE;
+          }
+      }
+    
+    e = mpi_alloc_set_ui (e_value); 
+
+    /* Find two prime numbers.  */
+    p = _gcry_derive_x931_prime (xp, xp1, xp2, e, NULL, NULL);
+    q = _gcry_derive_x931_prime (xq, xq1, xq2, e, NULL, NULL);
+    gcry_mpi_release (xp);  xp  = NULL;
+    gcry_mpi_release (xp1); xp1 = NULL;
+    gcry_mpi_release (xp2); xp2 = NULL;
+    gcry_mpi_release (xq);  xq  = NULL; 
+    gcry_mpi_release (xq1); xq1 = NULL;
+    gcry_mpi_release (xq2); xq2 = NULL;
+    if (!p || !q)
+      {
+        gcry_mpi_release (p);
+        gcry_mpi_release (q);
+        gcry_mpi_release (e);
+        return GPG_ERR_NO_PRIME;
+      }
+  }
+
+
+  /* Compute the public modulus.  We make sure that p is smaller than
+     q to allow the use of the CRT.  */
+  if (mpi_cmp (p, q) > 0 )
+    {
+      mpi_swap (p, q);
+      *swapped = 1;
+    }
+  n = gcry_mpi_new (nbits);
+  mpi_mul (n, p, q);
+
+  /* Compute the Euler totient:  phi = (p-1)(q-1)  */
+  pm1 = gcry_mpi_snew (nbits/2);
+  qm1 = gcry_mpi_snew (nbits/2);
+  phi = gcry_mpi_snew (nbits);
+  mpi_sub_ui (pm1, p, 1);
+  mpi_sub_ui (qm1, q, 1);
+  mpi_mul (phi, pm1, qm1);
+
+  g = gcry_mpi_snew (nbits);
+  gcry_assert (gcry_mpi_gcd (g, e, phi));
+
+  /* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */
+  gcry_mpi_gcd (g, pm1, qm1);
+  f = pm1; pm1 = NULL;
+  gcry_mpi_release (qm1); qm1 = NULL;
+  mpi_fdiv_q (f, phi, g);
+  gcry_mpi_release (phi); phi = NULL;
+  d = g; g = NULL;
+  /* Compute the secret key:  d = e^{-1} mod lcm(p-1,q-1) */
+  mpi_invm (d, e, f);
+
+  /* Compute the inverse of p and q.  */
+  u = f; f = NULL;
+  mpi_invm (u, p, q );
+
+  if( DBG_CIPHER )
+    {
+      if (swapped)
+        log_debug ("p and q are swapped\n");
+      log_mpidump("  p", p );
+      log_mpidump("  q", q );
+      log_mpidump("  n", n );
+      log_mpidump("  e", e );
+      log_mpidump("  d", d );
+      log_mpidump("  u", u );
+    }
+
+
+  sk->n = n;
+  sk->e = e;
+  sk->p = p;
+  sk->q = q;
+  sk->d = d;
+  sk->u = u;
+
+  /* Now we can test our keys. */
+  if (test_keys (sk, nbits - 64))
+    {
+      gcry_mpi_release (sk->n); sk->n = NULL;
+      gcry_mpi_release (sk->e); sk->e = NULL;
+      gcry_mpi_release (sk->p); sk->p = NULL;
+      gcry_mpi_release (sk->q); sk->q = NULL;
+      gcry_mpi_release (sk->d); sk->d = NULL;
+      gcry_mpi_release (sk->u); sk->u = NULL;
+      fips_signal_error ("self-test after key generation failed");
+      return GPG_ERR_SELFTEST_FAILED;
+    }
+
+  return 0;
+}
+
+
 /****************
  * Test wether the secret key is valid.
  * Returns: true if this is a valid key.
@@ -530,23 +715,42 @@
  *********************************************/
 
 static gcry_err_code_t
-rsa_generate_ext (int algo, unsigned int nbits, unsigned int qbits,
-                  unsigned long use_e,
-                  const char *name, const gcry_sexp_t domain,
-                  unsigned int keygen_flags,
+rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
+                  const gcry_sexp_t genparms,
                   gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
   RSA_secret_key sk;
   gpg_err_code_t ec;
+  gcry_sexp_t deriveparms;
+  int transient_key = 0;
+  gcry_sexp_t l1;
+  int swapped;
   int i;
 
   (void)algo;
-  (void)qbits;
-  (void)name;
-  (void)domain;
 
-  ec = generate_std (&sk, nbits, use_e,
-                     !!(keygen_flags & PUBKEY_FLAG_TRANSIENT_KEY) );
+  deriveparms = (genparms?
+                 gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL);
+
+  if (deriveparms || fips_mode ())
+    {
+      ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped);
+      gcry_sexp_release (deriveparms);
+    }
+  else
+    {
+      /* Parse the optional "transient-key" flag. */
+      l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
+      if (l1)
+        {
+          transient_key = 1;
+          gcry_sexp_release (l1);
+          l1 = NULL;
+        }
+      /* Generate.  */
+      ec = generate_std (&sk, nbits, evalue, transient_key);
+    }
+
   if (!ec)
     {
       skey[0] = sk.n;
@@ -576,11 +780,10 @@
 
 
 static gcry_err_code_t
-rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
+rsa_generate (int algo, unsigned int nbits, unsigned long evalue,
               gcry_mpi_t *skey, gcry_mpi_t **retfactors)
 {
-  return rsa_generate_ext (algo, nbits, 0, use_e, NULL, NULL, 0,
-                           skey, retfactors);
+  return rsa_generate_ext (algo, nbits, evalue, NULL, skey, retfactors);
 }
 
 

Modified: trunk/doc/gcrypt.texi
===================================================================
--- trunk/doc/gcrypt.texi	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/doc/gcrypt.texi	2008-11-24 16:37:50 UTC (rev 1358)
@@ -2725,6 +2725,33 @@
 The @code{seed}, @code{counter} and @code{h} domain parameters are
 optional and currently not used.
 
+ at item derive-parms
+This is currently only meaningful for RSA keys.  If given, it is used
+to derive the RSA keys using the given parameters.  This is in general
+only useful for key generation tests.  If given for an RSA key the
+X9.31 key generation algorithm is used even if libgcrypt is not in
+FIPS mode.
+
+ at example
+(genkey
+  (rsa
+    (nbits 4:1024)
+    (rsa-use-e 1:3)
+    (derive-parms
+      (Xp1 #1A1916DDB29B4EB7EB6732E128#)
+      (Xp2 #192E8AAC41C576C822D93EA433#)
+      (Xp  #D8CD81F035EC57EFE822955149D3BFF70C53520D
+            769D6D76646C7A792E16EBD89FE6FC5B605A6493
+            39DFC925A86A4C6D150B71B9EEA02D68885F5009
+            B98BD984#)
+      (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)
+      (Xq2 #134E4CAA16D2350A21D775C404#)
+      (Xq  #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
+            7C9953388F97DDDC3E1CA19C35CA659EDC2FC325
+            6D29C2627479C086A699A49C4C9CEE7EF7BD1B34
+            321DE34A#))))
+ at end example
+
 @end table
 @c end table of parameters
 
@@ -2750,16 +2777,17 @@
       (y @var{y-mpi})
       (x @var{x-mpi})))
   (misc-key-info
-    (pm1-factors @var{n1 n2 ... nn})))
+    (pm1-factors @var{n1 n2 ... nn}))
 @end example
 
 @noindent
-As you can see, some of the information is duplicated, but this provides
-an easy way to extract either the public or the private key.  Note that
-the order of the elements is not defined, e.g. the private key may be
-stored before the public key. @var{n1 n2 ... nn} is a list of prime
-numbers used to composite @var{p-mpi}; this is in general not a very
-useful information.
+As you can see, some of the information is duplicated, but this
+provides an easy way to extract either the public or the private key.
+Note that the order of the elements is not defined, e.g. the private
+key may be stored before the public key. @var{n1 n2 ... nn} is a list
+of prime numbers used to composite @var{p-mpi}; this is in general not
+a very useful information and only available if the key generation
+algorithm provides them.  
 @end deftypefun
 @c end gcry_pk_genkey
 

Modified: trunk/src/cipher-proto.h
===================================================================
--- trunk/src/cipher-proto.h	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/src/cipher-proto.h	2008-11-24 16:37:50 UTC (rev 1358)
@@ -43,18 +43,19 @@
 typedef gcry_err_code_t (*pk_ext_generate_t)
      (int algo,
       unsigned int nbits,
-      unsigned int qbits,
-      unsigned long use_e,
-      const char *name,
-      gcry_sexp_t domain,
-      unsigned int keygen_flags, 
+      unsigned long evalue,
+      gcry_sexp_t genparms,
       gcry_mpi_t *skey,
       gcry_mpi_t **retfactors);
 
-/* The type is used to compute the keygrip.  */
+/* The type used to compute the keygrip.  */
 typedef gpg_err_code_t (*pk_comp_keygrip_t)
      (gcry_md_hd_t md, gcry_sexp_t keyparm);
 
+/* The type used to quert ECC curve parameters.  */
+typedef gcry_err_code_t (*pk_get_param_t)
+     (const char *name, gcry_mpi_t *pkey);
+
 /* The type used to convey additional information to a cipher.  */
 typedef gpg_err_code_t (*cipher_set_extra_info_t)
      (void *c, int what, const void *buffer, size_t buflen);
@@ -79,6 +80,7 @@
   selftest_func_t selftest;
   pk_ext_generate_t ext_generate;
   pk_comp_keygrip_t comp_keygrip;
+  pk_get_param_t get_param;
 } pk_extra_spec_t;
 
 

Modified: trunk/src/cipher.h
===================================================================
--- trunk/src/cipher.h	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/src/cipher.h	2008-11-24 16:37:50 UTC (rev 1358)
@@ -27,7 +27,6 @@
 #include "../random/random.h"
 
 #define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
-#define PUBKEY_FLAG_TRANSIENT_KEY  (1 << 1)
 
 #define CIPHER_INFO_NO_WEAK_KEY    1
 
@@ -62,18 +61,11 @@
 /*-- elgamal.c --*/
 void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb,
                                      void *cb_data);
-gcry_err_code_t _gcry_elg_generate_using_x (int algo, unsigned int nbits,
-                                            gcry_mpi_t x, 
-                                            gcry_mpi_t *skey,
-                                            gcry_mpi_t **retfactors);
 
+
 /*-- ecc.c --*/
 void _gcry_register_pk_ecc_progress (gcry_handler_progress_t cbc,
                                      void *cb_data);
-gcry_err_code_t _gcry_ecc_generate (int algo, unsigned int nbits,
-                                    const char *curve,
-                                    gcry_mpi_t *skey, gcry_mpi_t **retfactors);
-gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey);
 
 
 /*-- primegen.c --*/
@@ -138,6 +130,7 @@
 
 extern pk_extra_spec_t _gcry_pubkey_extraspec_rsa; 
 extern pk_extra_spec_t _gcry_pubkey_extraspec_dsa; 
+extern pk_extra_spec_t _gcry_pubkey_extraspec_elg; 
 extern pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa; 
 
 

Modified: trunk/src/g10lib.h
===================================================================
--- trunk/src/g10lib.h	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/src/g10lib.h	2008-11-24 16:37:50 UTC (rev 1358)
@@ -175,6 +175,10 @@
 gcry_mpi_t _gcry_generate_elg_prime (int mode, 
                                      unsigned int pbits, unsigned int qbits,
                                      gcry_mpi_t g, gcry_mpi_t **factors);
+gcry_mpi_t _gcry_derive_x931_prime (const gcry_mpi_t xp, 
+                                    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);
 
 
 /* replacements of missing functions (missing-string.c)*/

Modified: trunk/tests/cavs_driver.pl
===================================================================
--- trunk/tests/cavs_driver.pl	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/tests/cavs_driver.pl	2008-11-24 16:37:50 UTC (rev 1358)
@@ -1035,6 +1035,7 @@
                 my $old_calc_data;
                 my $old_old_calc_data;
                 my $ov;
+                my $iv_arg;
 
 		$out .= "COUNT = $i\n";
 		if (defined($key2)) {
@@ -1059,10 +1060,15 @@
                         $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n";
                 }
 
+                # Need to provide a dummy IV in case of ECB mode.
+                $iv_arg =  (defined($iv) && $iv ne "")
+                             ? bin2hex($iv)
+                             : "00"x(length($source_data)); 
+
                 print $CI "1\n"
                           .$iloop."\n"
                           .bin2hex($key1)."\n"
-                          .bin2hex($iv)."\n"
+                          .$iv_arg."\n"
                           .bin2hex($source_data)."\n\n" or die;
                 
                 # fixme: We should skip over empty lines here.
@@ -1130,7 +1136,7 @@
 		}
 
                 if ($ciph =~ /des/) {
-                    $iv = $ov;
+                    $iv = $ov if (defined($iv) && $iv ne "");
                     if ($cipher =~ /des-ede3-ofb/) {
                         $source_data = $source_data ^ $next_source;
                     } else {

Modified: trunk/tests/fipsdrv.c
===================================================================
--- trunk/tests/fipsdrv.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/tests/fipsdrv.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -240,6 +240,8 @@
       any = 1;
     }
   while (*line == '#');  /* Always skip comment lines.  */
+  if (verbose > 1)
+    fprintf (stderr, PGM ": received line: %s\n", line);
   return gcry_xstrdup (line);
 }
 
@@ -800,6 +802,8 @@
     {
       const unsigned char *p = buffer;
       
+      if (verbose > 1)
+        showhex ("sent line", buffer, length);
       while (length-- && !ferror (stdout) )
         printf ("%02X", *p++);
       if (ferror (stdout))
@@ -1099,6 +1103,8 @@
   putchar ('\n');
   print_buffer (input, blocklen);   /* Next input text. */
   putchar ('\n');
+  if (verbose > 1)
+    showhex ("sent line", "", 0);
   putchar ('\n');
   fflush (stdout);
 

Modified: trunk/tests/pubkey.c
===================================================================
--- trunk/tests/pubkey.c	2008-11-19 13:52:48 UTC (rev 1357)
+++ trunk/tests/pubkey.c	2008-11-24 16:37:50 UTC (rev 1358)
@@ -114,6 +114,23 @@
 }
 
 static void
+show_sexp (const char *prefix, gcry_sexp_t a)
+{
+  char *buf;
+  size_t size;
+
+  if (prefix)
+    fputs (prefix, stderr);
+  size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+  buf = gcry_xmalloc (size);
+




More information about the Gnupg-commits mailing list