pk: Move s-expr creation for genkey to the modules.
authorWerner Koch <wk@gnupg.org>
Sat, 7 Sep 2013 08:06:46 +0000 (10:06 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 19 Sep 2013 14:43:33 +0000 (16:43 +0200)
* cipher/pubkey.c (pubkey_generate): Fold into gcry_pk_genkey
(gcry_pk_genkey): Move result s-exp creation into the modules.
* cipher/dsa.c (dsa_generate): Create result as s-exp.
* cipher/elgamal.c (elg_generate): Ditto.
* cipher/rsa.c (rsa_generate): Ditto.
* cipher/ecc.c (ecc_generate): Ditto.
* src/cipher-proto.h (pk_ext_generate_t): Remove type
(gcry_pk_spec): and remove from struct.

Signed-off-by: Werner Koch <wk@gnupg.org>
cipher/dsa.c
cipher/ecc.c
cipher/elgamal.c
cipher/pubkey.c
cipher/rsa.c
src/cipher-proto.h

index 13a4fc2..ceff947 100644 (file)
@@ -271,7 +271,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
    * part.  The random quality depends on the transient_key flag.  */
   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
   if (DBG_CIPHER)
-    log_debug("choosing a random x%s", transient_key? " (transient-key)":"");
+    log_debug("choosing a random x%s\n", transient_key? " (transient-key)":"");
   gcry_assert( qbits >= 160 );
   x = mpi_alloc_secure( mpi_get_nlimbs(q) );
   mpi_sub_ui( h, q, 1 );  /* put q-1 into h */
@@ -689,25 +689,26 @@ verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_public_key *pkey )
  *********************************************/
 
 static gcry_err_code_t
-dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
-                  const gcry_sexp_t genparms,
-                  gcry_mpi_t *skey, gcry_mpi_t **retfactors,
-                  gcry_sexp_t *r_extrainfo)
+dsa_generate (int algo, unsigned int nbits, unsigned long evalue,
+              const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 {
-  gpg_err_code_t ec;
+  gpg_err_code_t rc;
   DSA_secret_key sk;
   gcry_sexp_t l1;
   unsigned int qbits = 0;
   gcry_sexp_t deriveparms = NULL;
   gcry_sexp_t seedinfo = NULL;
+  gcry_sexp_t misc_info = NULL;
   int transient_key = 0;
   int use_fips186_2 = 0;
   int use_fips186 = 0;
   dsa_domain_t domain;
+  gcry_mpi_t *factors = NULL;
 
   (void)algo;    /* No need to check it.  */
   (void)evalue;  /* Not required for DSA. */
 
+  memset (&sk, 0, sizeof sk);
   memset (&domain, 0, sizeof domain);
 
   if (genparms)
@@ -809,141 +810,116 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
       size_t seedlen;
       gcry_mpi_t h_value;
 
-      ec = generate_fips186 (&sk, nbits, qbits, deriveparms, use_fips186_2,
+      rc = generate_fips186 (&sk, nbits, qbits, deriveparms, use_fips186_2,
                              &domain,
                              &counter, &seed, &seedlen, &h_value);
-      gcry_sexp_release (deriveparms);
-      if (!ec && h_value)
+      if (!rc && h_value)
         {
           /* Format the seed-values unless domain parameters are used
              for which a H_VALUE of NULL is an indication.  */
-          ec = gpg_err_code (gcry_sexp_build
+          rc = 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, transient_key, &domain, retfactors);
+      rc = generate (&sk, nbits, qbits, transient_key, &domain, &factors);
     }
 
-  gcry_mpi_release (domain.p);
-  gcry_mpi_release (domain.q);
-  gcry_mpi_release (domain.g);
-
-  if (!ec)
+  if (!rc)
     {
-      skey[0] = sk.p;
-      skey[1] = sk.q;
-      skey[2] = sk.g;
-      skey[3] = sk.y;
-      skey[4] = sk.x;
-
-      if (!r_extrainfo)
-        {
-          /* Old style interface - return the factors - if any - at
-             retfactors.  */
-        }
-      else if (!*retfactors && !seedinfo)
-        {
-          /* No factors and no seedinfo, thus there is nothing to return.  */
-          *r_extrainfo = NULL;
-        }
+      /* Put the factors into MISC_INFO.  Note that the factors are
+         not confidential thus we can store them in standard memory.  */
+      int nfactors, i, j;
+      char *p;
+      char *format = NULL;
+      void **arg_list = NULL;
+
+      for (nfactors=0; factors && factors[nfactors]; nfactors++)
+        ;
+      /* Allocate space for the format string:
+         "(misc-key-info%S(pm1-factors%m))"
+         with one "%m" for each factor and construct it.  */
+      format = gcry_malloc (50 + 2*nfactors);
+      if (!format)
+        rc = gpg_err_code_from_syserror ();
       else
         {
-          /* Put the factors into extrainfo and set retfactors to NULL
-             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, j;
-          char *p;
-          char *format = NULL;
-          void **arg_list = NULL;
-
-          for (nfactors=0; *retfactors && (*retfactors)[nfactors]; nfactors++)
-            ;
-          /* Allocate space for the format string:
-               "(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");
+          if (seedinfo)
+            p = stpcpy (p, "%S");
+          if (nfactors)
             {
-              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, "(pm1-factors");
+              for (i=0; i < nfactors; i++)
+                p = stpcpy (p, "%m");
               p = stpcpy (p, ")");
-
-              /* 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
-                {
-                  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
-                                     (r_extrainfo, NULL, format, arg_list));
-                }
             }
-
-          gcry_free (arg_list);
-          gcry_free (format);
-          for (i=0; i < nfactors; i++)
-            {
-              gcry_mpi_release ((*retfactors)[i]);
-              (*retfactors)[i] = NULL;
-            }
-          gcry_free (*retfactors);
-          *retfactors = NULL;
-          if (ec)
+          p = stpcpy (p, ")");
+
+          /* Allocate space for the list of factors plus one for the
+             seedinfo s-exp 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)
+            rc = gpg_err_code_from_syserror ();
+          else
             {
-              for (i=0; i < 5; i++)
-                {
-                  gcry_mpi_release (skey[i]);
-                  skey[i] = NULL;
-                }
+              i = 0;
+              if (seedinfo)
+                arg_list[i++] = &seedinfo;
+              for (j=0; j < nfactors; j++)
+                arg_list[i++] = factors + j;
+              arg_list[i] = NULL;
+
+              rc = gpg_err_code (gcry_sexp_build_array
+                                 (&misc_info, NULL, format, arg_list));
             }
         }
+
+      gcry_free (arg_list);
+      gcry_free (format);
     }
 
-  gcry_sexp_release (seedinfo);
-  return ec;
-}
+  if (!rc)
+    rc = gcry_err_code (gcry_sexp_build
+                        (r_skey, NULL,
+                         "(key-data"
+                         " (public-key"
+                         "  (dsa(p%m)(q%m)(g%m)(y%m)))"
+                         " (private-key"
+                         "  (dsa(p%m)(q%m)(g%m)(y%m)(x%m)))"
+                         " %S)",
+                         sk.p, sk.q, sk.g, sk.y,
+                         sk.p, sk.q, sk.g, sk.y, sk.x,
+                         misc_info));
+
+
+  gcry_mpi_release (sk.p);
+  gcry_mpi_release (sk.q);
+  gcry_mpi_release (sk.g);
+  gcry_mpi_release (sk.y);
+  gcry_mpi_release (sk.x);
 
+  gcry_mpi_release (domain.p);
+  gcry_mpi_release (domain.q);
+  gcry_mpi_release (domain.g);
 
-static gcry_err_code_t
-dsa_generate (int algo, unsigned int nbits, unsigned long evalue,
-              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-{
-  (void)evalue;
-  return dsa_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
+  gcry_sexp_release (seedinfo);
+  gcry_sexp_release (misc_info);
+  gcry_sexp_release (deriveparms);
+  if (factors)
+    {
+      gcry_mpi_t *mp;
+      for (mp = factors; *mp; mp++)
+        mpi_free (*mp);
+      gcry_free (factors);
+    }
+  return rc;
 }
 
 
@@ -1223,6 +1199,5 @@ gcry_pk_spec_t _gcry_pubkey_spec_dsa =
     dsa_sign,
     dsa_verify,
     dsa_get_nbits,
-    run_selftests,
-    dsa_generate_ext
+    run_selftests
   };
index b7d6239..9a9c21b 100644 (file)
@@ -1152,12 +1152,9 @@ verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey,
  **************  interface  ******************
  *********************************************/
 
-/* 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,
-                  gcry_sexp_t *r_extrainfo)
+ecc_generate (int algo, unsigned int nbits, unsigned long evalue,
+              const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 {
   gpg_err_code_t rc;
   elliptic_curve_t E;
@@ -1169,10 +1166,17 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
   int transient_key = 0;
   gcry_random_level_t random_level;
   mpi_ec_t ctx = NULL;
+  gcry_sexp_t curve_info = NULL;
+  gcry_mpi_t base = NULL;
+  gcry_mpi_t public = NULL;
+  gcry_mpi_t secret = NULL;
 
   (void)algo;
   (void)evalue;
 
+  memset (&E, 0, sizeof E);
+  memset (&sk, 0, sizeof sk);
+
   if (genparms)
     {
       /* Parse the optional "curve" parameter. */
@@ -1240,7 +1244,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
   /* Copy data to the result.  */
   if (_gcry_mpi_ec_get_affine (x, y, &sk.E.G, ctx))
     log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
-  skey[3] = _gcry_ecc_ec2os (x, y, sk.E.p);
+  base = _gcry_ecc_ec2os (x, y, sk.E.p);
   if (sk.E.dialect == ECC_DIALECT_ED25519)
     {
       unsigned char *encpk;
@@ -1249,68 +1253,69 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
       rc = eddsa_encodepoint (&sk.Q, 256/8, ctx, x, y, &encpk, &encpklen);
       if (rc)
         return rc;
-      skey[5] = mpi_new (0);
-      gcry_mpi_set_opaque (skey[5], encpk, encpklen*8);
+      public = mpi_new (0);
+      gcry_mpi_set_opaque (public, encpk, encpklen*8);
       encpk = NULL;
-      if (DBG_CIPHER)
-        log_printmpi ("ecgen      e_pk", skey[5]);
     }
   else
     {
       if (_gcry_mpi_ec_get_affine (x, y, &sk.Q, ctx))
         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
-      skey[5] = _gcry_ecc_ec2os (x, y, sk.E.p);
+      public = _gcry_ecc_ec2os (x, y, sk.E.p);
     }
-  skey[0] = sk.E.p; sk.E.p = NULL;
-  skey[1] = sk.E.a; sk.E.a = NULL;
-  skey[2] = sk.E.b; sk.E.b = NULL;
-  skey[4] = sk.E.n; sk.E.n = NULL;
-  skey[6] = sk.d; sk.d = NULL;
-
-  if (E.name)  /* Fixme: No error return checking.  */
-    gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", E.name);
-
-  /* Make an dummy list of factors.  */
-  *retfactors = gcry_calloc ( 1, sizeof **retfactors );
-  if (!*retfactors)
+  secret = sk.d; sk.d = NULL;
+  if (E.name)
     {
-      rc = gpg_err_code_from_syserror ();
-      goto leave;
+      rc = gcry_sexp_build (&curve_info, NULL, "(curve %s)", E.name);
+      if (rc)
+        goto leave;
     }
 
+  rc = gcry_err_code (gcry_sexp_build
+                      (r_skey, NULL,
+                       "(key-data"
+                       " (public-key"
+                       "  (ecc%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))"
+                       " (private-key"
+                       "  (ecc%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))"
+                       " )",
+                       curve_info,
+                       sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public,
+                       curve_info,
+                       sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret));
+  if (rc)
+    goto leave;
+
   if (DBG_CIPHER)
     {
-      log_printmpi ("ecgen result  p", skey[0]);
-      log_printmpi ("ecgen result  a", skey[1]);
-      log_printmpi ("ecgen result  b", skey[2]);
-      log_printmpi ("ecgen result  G", skey[3]);
-      log_printmpi ("ecgen result  n", skey[4]);
-      log_printmpi ("ecgen result  Q", skey[5]);
-      log_printmpi ("ecgen result  d", skey[6]);
+      log_printmpi ("ecgen result  p", sk.E.p);
+      log_printmpi ("ecgen result  a", sk.E.a);
+      log_printmpi ("ecgen result  b", sk.E.b);
+      log_printmpi ("ecgen result  G", base);
+      log_printmpi ("ecgen result  n", sk.E.n);
+      log_printmpi ("ecgen result  Q", public);
+      log_printmpi ("ecgen result  d", secret);
     }
-  rc = 0;
 
  leave:
-  point_free (&sk.E.G);
-  point_free (&sk.Q);
-  _gcry_mpi_ec_free (ctx);
+  mpi_free (secret);
+  mpi_free (public);
+  mpi_free (base);
+  {
+    _gcry_ecc_curve_free (&sk.E);
+    point_free (&sk.Q);
+    mpi_free (sk.d);
+  }
   _gcry_ecc_curve_free (&E);
-  gcry_mpi_release (x);
-  gcry_mpi_release (y);
+  mpi_free (x);
+  mpi_free (y);
+  _gcry_mpi_ec_free (ctx);
+  gcry_sexp_release (curve_info);
   return rc;
 }
 
 
 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, NULL);
-}
-
-
-static gcry_err_code_t
 ecc_check_secret_key (int algo, gcry_mpi_t *skey)
 {
   gpg_err_code_t err;
@@ -2020,7 +2025,6 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa =
     ecc_verify,
     ecc_get_nbits,
     run_selftests,
-    ecc_generate_ext,
     compute_keygrip,
     _gcry_ecc_get_param,
     _gcry_ecc_get_curve,
@@ -2041,7 +2045,6 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdh =
     NULL,
     ecc_get_nbits,
     run_selftests,
-    ecc_generate_ext,
     compute_keygrip,
     _gcry_ecc_get_param,
     _gcry_ecc_get_curve,
index 447d089..c2a953b 100644 (file)
@@ -1,6 +1,7 @@
 /* Elgamal.c  -  Elgamal Public Key encryption
  * Copyright (C) 1998, 2000, 2001, 2002, 2003,
  *               2008  Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -197,7 +198,7 @@ gen_k( gcry_mpi_t p, int small_k )
 
   nbytes = (nbits+7)/8;
   if( DBG_CIPHER )
-    log_debug("choosing a random k ");
+    log_debug("choosing a random k\n");
   mpi_sub_ui( p_1, p, 1);
   for(;;)
     {
@@ -292,7 +293,7 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors )
     BUG();
   x = gcry_mpi_snew ( xbits );
   if( DBG_CIPHER )
-    log_debug("choosing a random x of size %u", xbits );
+    log_debug("choosing a random x of size %u\n", xbits );
   rndbuf = NULL;
   do
     {
@@ -330,11 +331,11 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors )
 
   if( DBG_CIPHER )
     {
-      progress('\n');
-      log_mpidump("elg  p= ", p );
-      log_mpidump("elg  g= ", g );
-      log_mpidump("elg  y= ", y );
-      log_mpidump("elg  x= ", x );
+      progress ('\n');
+      log_mpidump ("elg  p", p );
+      log_mpidump ("elg  g", g );
+      log_mpidump ("elg  y", y );
+      log_mpidump ("elg  x", x );
     }
 
   /* Copy the stuff to the key structures */
@@ -402,10 +403,10 @@ generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x,
   if ( DBG_CIPHER )
     {
       progress ('\n');
-      log_mpidump ("elg  p", p );
-      log_mpidump ("elg  g", g );
-      log_mpidump ("elg  y", y );
-      log_mpidump ("elg  x", x );
+      log_mpidump ("elg  p", p );
+      log_mpidump ("elg  g", g );
+      log_mpidump ("elg  y", y );
+      log_mpidump ("elg  x", x );
     }
 
   /* Copy the stuff to the key structures */
@@ -469,12 +470,12 @@ do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
 #if 0
   if( DBG_CIPHER )
     {
-      log_mpidump("elg encrypted y", pkey->y);
-      log_mpidump("elg encrypted p", pkey->p);
-      log_mpidump("elg encrypted k", k);
-      log_mpidump("elg encrypted M", input);
-      log_mpidump("elg encrypted a", a);
-      log_mpidump("elg encrypted b", b);
+      log_mpidump("elg encrypted y", pkey->y);
+      log_mpidump("elg encrypted p", pkey->p);
+      log_mpidump("elg encrypted k", k);
+      log_mpidump("elg encrypted M", input);
+      log_mpidump("elg encrypted a", a);
+      log_mpidump("elg encrypted b", b);
     }
 #endif
   mpi_free(k);
@@ -495,11 +496,11 @@ decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey )
 #if 0
   if( DBG_CIPHER )
     {
-      log_mpidump("elg decrypted x= ", skey->x);
-      log_mpidump("elg decrypted p= ", skey->p);
-      log_mpidump("elg decrypted a= ", a);
-      log_mpidump("elg decrypted b= ", b);
-      log_mpidump("elg decrypted M= ", output);
+      log_mpidump ("elg decrypted x", skey->x);
+      log_mpidump ("elg decrypted p", skey->p);
+      log_mpidump ("elg decrypted a", a);
+      log_mpidump ("elg decrypted b", b);
+      log_mpidump ("elg decrypted M", output);
     }
 #endif
   mpi_free(t1);
@@ -535,14 +536,14 @@ sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey )
 #if 0
     if( DBG_CIPHER )
       {
-       log_mpidump("elg sign p= ", skey->p);
-       log_mpidump("elg sign g= ", skey->g);
-       log_mpidump("elg sign y= ", skey->y);
-       log_mpidump("elg sign x= ", skey->x);
-       log_mpidump("elg sign k= ", k);
-       log_mpidump("elg sign M= ", input);
-       log_mpidump("elg sign a= ", a);
-       log_mpidump("elg sign b= ", b);
+       log_mpidump ("elg sign p", skey->p);
+       log_mpidump ("elg sign g", skey->g);
+       log_mpidump ("elg sign y", skey->y);
+       log_mpidump ("elg sign x", skey->x);
+       log_mpidump ("elg sign k", k);
+       log_mpidump ("elg sign M", input);
+       log_mpidump ("elg sign a", a);
+       log_mpidump ("elg sign b", b);
       }
 #endif
     mpi_free(k);
@@ -613,19 +614,20 @@ verify(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
  *********************************************/
 
 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,
-                  gcry_sexp_t *r_extrainfo)
+elg_generate (int algo, unsigned int nbits, unsigned long evalue,
+              const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 {
-  gpg_err_code_t ec;
+  gpg_err_code_t rc;
   ELG_secret_key sk;
   gcry_mpi_t xvalue = NULL;
   gcry_sexp_t l1;
+  gcry_mpi_t *factors = NULL;
+  gcry_sexp_t misc_info = NULL;
 
   (void)algo;
   (void)evalue;
-  (void)r_extrainfo;
+
+  memset (&sk, 0, sizeof sk);
 
   if (genparms)
     {
@@ -642,40 +644,79 @@ elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
   if (xvalue)
     {
-      ec = generate_using_x (&sk, nbits, xvalue, retfactors);
+      rc = generate_using_x (&sk, nbits, xvalue, &factors);
       mpi_free (xvalue);
     }
   else
     {
-      generate (&sk, nbits, retfactors);
-      ec = 0;
+      generate (&sk, nbits, &factors);
+      rc = 0;
     }
+  if (rc)
+    goto leave;
 
-  skey[0] = sk.p;
-  skey[1] = sk.g;
-  skey[2] = sk.y;
-  skey[3] = sk.x;
-
-  return ec;
-}
-
-
-static gcry_err_code_t
-elg_generate (int algo, unsigned int nbits, unsigned long evalue,
-              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-{
-  ELG_secret_key sk;
-
-  (void)algo;
-  (void)evalue;
+  if (factors && factors[0])
+    {
+      int nfac;
+      void **arg_list;
+      char *buffer, *p;
+
+      for (nfac = 0; factors[nfac]; nfac++)
+        ;
+      arg_list = gcry_calloc (nfac+1, sizeof *arg_list);
+      if (!arg_list)
+        {
+          rc = gpg_err_code_from_syserror ();
+          goto leave;
+        }
+      buffer = gcry_malloc (30 + nfac*2 + 2 + 1);
+      if (!buffer)
+        {
+          rc = gpg_err_code_from_syserror ();
+          gcry_free (arg_list);
+          goto leave;
+        }
+      p = stpcpy (buffer, "(misc-key-info(pm1-factors");
+      for(nfac = 0; factors[nfac]; nfac++)
+        {
+          p = stpcpy (p, "%m");
+          arg_list[nfac] = factors + nfac;
+        }
+      p = stpcpy (p, "))");
+      rc = gcry_sexp_build_array (&misc_info, NULL, buffer, arg_list);
+      gcry_free (arg_list);
+      gcry_free (buffer);
+      if (rc)
+        goto leave;
+    }
 
-  generate (&sk, nbits, retfactors);
-  skey[0] = sk.p;
-  skey[1] = sk.g;
-  skey[2] = sk.y;
-  skey[3] = sk.x;
+  rc = gcry_err_code (gcry_sexp_build
+                      (r_skey, NULL,
+                       "(key-data"
+                       " (public-key"
+                       "  (elg(p%m)(g%m)(y%m)))"
+                       " (private-key"
+                       "  (elg(p%m)(g%m)(y%m)(x%m)))"
+                       " %S)",
+                       sk.p, sk.g, sk.y,
+                       sk.p, sk.g, sk.y, sk.x,
+                       misc_info));
+
+ leave:
+  mpi_free (sk.p);
+  mpi_free (sk.g);
+  mpi_free (sk.y);
+  mpi_free (sk.x);
+  gcry_sexp_release (misc_info);
+  if (factors)
+    {
+      gcry_mpi_t *mp;
+      for (mp = factors; *mp; mp++)
+        mpi_free (*mp);
+      gcry_free (factors);
+    }
 
-  return GPG_ERR_NO_ERROR;
+  return rc;
 }
 
 
@@ -863,8 +904,6 @@ gcry_pk_spec_t _gcry_pubkey_spec_elg =
     elg_sign,
     elg_verify,
     elg_get_nbits,
-    NULL,
-    elg_generate_ext
   };
 
 gcry_pk_spec_t _gcry_pubkey_spec_elg_e =
@@ -879,7 +918,5 @@ gcry_pk_spec_t _gcry_pubkey_spec_elg_e =
     elg_decrypt,
     elg_sign,
     elg_verify,
-    elg_get_nbits,
-    NULL,
-    elg_generate_ext
+    elg_get_nbits
   };
index 2585981..736d4b9 100644 (file)
@@ -247,39 +247,6 @@ pubkey_get_nenc (int algo)
 }
 
 
-/* Generate a new public key with algorithm ALGO of size NBITS
-   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 algo,
-                 unsigned int nbits,
-                 unsigned long use_e,
-                 gcry_sexp_t genparms,
-                 gcry_mpi_t *skey, gcry_mpi_t **retfactors,
-                 gcry_sexp_t *r_extrainfo)
-{
-  gcry_err_code_t rc;
-  gcry_pk_spec_t *spec = spec_from_algo (algo);
-
-  if (spec && spec->ext_generate)
-    rc = spec->ext_generate (algo, nbits, use_e, genparms,
-                             skey, retfactors, r_extrainfo);
-  else if (spec && spec->generate)
-    rc = spec->generate (algo, nbits, use_e, skey, retfactors);
-  else if (spec)
-    rc = GPG_ERR_NOT_IMPLEMENTED;
-  else
-    rc = GPG_ERR_PUBKEY_ALGO;
-
-  return rc;
-}
-
-
 static gcry_err_code_t
 pubkey_check_secret_key (int algo, gcry_mpi_t *skey)
 {
@@ -1942,16 +1909,9 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   char *name = NULL;
   size_t n;
   gcry_err_code_t rc = GPG_ERR_NO_ERROR;
-  int i, j;
-  const char *algo_name = NULL;
-  const char *sec_elems = NULL, *pub_elems = NULL;
-  gcry_mpi_t skey[12];
-  gcry_mpi_t *factors = NULL;
-  gcry_sexp_t extrainfo = NULL;
   unsigned int nbits = 0;
   unsigned long use_e = 0;
 
-  skey[0] = NULL;
   *r_key = NULL;
 
   list = gcry_sexp_find_token (s_parms, "genkey", 0);
@@ -1987,14 +1947,6 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
       goto leave;
     }
 
-  algo_name = spec->aliases? *spec->aliases : NULL;
-  if (!algo_name || !*algo_name)
-    algo_name = spec->name;
-  pub_elems = spec->elements_pkey;
-  sec_elems = spec->elements_skey;
-  if (strlen (sec_elems) >= DIM(skey))
-    BUG ();
-
   /* Handle the optional rsa-use-e element.  Actually this belong into
      the algorithm module but we have this parameter in the public
      module API, so we need to parse it right here.  */
@@ -2041,164 +1993,14 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   else
     nbits = 0;
 
-  /* Pass control to the algorithm module. */
-  rc = pubkey_generate (spec->algo, nbits, use_e, list, skey,
-                        &factors, &extrainfo);
-  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;
-    gcry_mpi_t mpis[30];
-    int percent_s_idx = -1;
-    int percent_s_idx2 = -1;
-
-    /* Estimate size of format string.  */
-    nelem = strlen (pub_elems) + strlen (sec_elems);
-    if (factors)
-      {
-        for (i = 0; factors[i]; i++)
-          nelem++;
-      }
-    if (extrainfo)
-      nelem += 2;
-    nelem_cp = nelem;
-
-    needed += nelem * 10;
-    /* (+10 for two times EXTRAINFO ("%S")).  */
-    needed += 2 * strlen (algo_name) + 300 + 10;
-    if (nelem > DIM (mpis))
-      BUG ();
-
-    /* Build the string. */
-    nelem = 0;
-    string = p = gcry_malloc (needed);
-    if (!string)
-      {
-        rc = gpg_err_code_from_syserror ();
-        goto leave;
-      }
-    p = stpcpy (p, "(key-data");
-    p = stpcpy (p, "(public-key(");
-    p = stpcpy (p, algo_name);
-    for(i = 0; pub_elems[i]; i++)
-      {
-        *p++ = '(';
-        *p++ = pub_elems[i];
-        p = stpcpy (p, "%m)");
-        mpis[nelem++] = skey[i];
-      }
-    if (extrainfo
-        && (spec->algo == GCRY_PK_ECDSA || spec->algo == GCRY_PK_ECDH))
-      {
-        /* Very ugly hack to insert the used curve parameter into the
-           list of public key parameters.  */
-        percent_s_idx = nelem++;
-        p = stpcpy (p, "%S");
-      }
-    p = stpcpy (p, "))");
-    p = stpcpy (p, "(private-key(");
-    p = stpcpy (p, algo_name);
-    for (i = 0; sec_elems[i]; i++)
-      {
-        *p++ = '(';
-        *p++ = sec_elems[i];
-        p = stpcpy (p, "%m)");
-        mpis[nelem++] = skey[i];
-      }
-    if (extrainfo
-        && (spec->algo == GCRY_PK_ECDSA || spec->algo == GCRY_PK_ECDH))
-      {
-        percent_s_idx2 = nelem++;
-        p = stpcpy (p, "%S");
-      }
-    p = stpcpy (p, "))");
-
-    /* Hack to make release_mpi_array() work.  */
-    skey[i] = NULL;
-
-    if (extrainfo)
-      {
-        /* If we have extrainfo we should not have any factors.  */
-        if (percent_s_idx == -1)
-          {
-            percent_s_idx = nelem++;
-            p = stpcpy (p, "%S");
-          }
-      }
-    else if (factors && factors[0])
-      {
-        p = stpcpy (p, "(misc-key-info(pm1-factors");
-        for(i = 0; factors[i]; i++)
-          {
-            p = stpcpy (p, "%m");
-            mpis[nelem++] = factors[i];
-          }
-        p = stpcpy (p, "))");
-      }
-    strcpy (p, ")");
-    gcry_assert (p - string < needed);
-
-    while (nelem < DIM (mpis))
-      mpis[nelem++] = NULL;
-
-    {
-      int elem_n = strlen (pub_elems) + strlen (sec_elems);
-      void **arg_list;
-
-      if (percent_s_idx != -1)
-        elem_n++;
-      if (percent_s_idx2 != -1)
-        elem_n++;
-
-      arg_list = gcry_calloc (nelem_cp, sizeof *arg_list);
-      if (!arg_list)
-        {
-          rc = gpg_err_code_from_syserror ();
-          goto leave;
-        }
-      for (i = j = 0; i < elem_n; i++)
-        {
-          if (i == percent_s_idx)
-            arg_list[j++] = &extrainfo;
-          else if (i == percent_s_idx2)
-            arg_list[j++] = &extrainfo;
-          else
-            arg_list[j++] = mpis + i;
-        }
-      if (extrainfo)
-        ;
-      else if (factors && factors[0])
-        {
-          for (; i < nelem_cp; i++)
-            arg_list[j++] = factors + i - elem_n;
-        }
-      rc = gcry_sexp_build_array (r_key, NULL, string, arg_list);
-      gcry_free (arg_list);
-      if (rc)
-       BUG ();
-      gcry_assert (DIM (mpis) == 30); /* Reminder to make sure that
-                                         the array gets increased if
-                                         new parameters are added. */
-    }
-    gcry_free (string);
-  }
+  if (spec->generate)
+    rc = spec->generate (spec->algo, nbits, use_e, list, r_key);
+  else
+    rc = GPG_ERR_NOT_IMPLEMENTED;
 
  leave:
+  gcry_sexp_release (list); list = NULL;
   gcry_free (name);
-  gcry_sexp_release (extrainfo);
-  release_mpi_array (skey);
-  /* Don't free SKEY itself, it is an stack allocated array. */
-
-  if (factors)
-    {
-      release_mpi_array ( factors );
-      gcry_free (factors);
-    }
-
   gcry_sexp_release (l3);
   gcry_sexp_release (l2);
   gcry_sexp_release (list);
index 91349db..5754e43 100644 (file)
@@ -783,10 +783,8 @@ rsa_unblind (gcry_mpi_t x, gcry_mpi_t ri, gcry_mpi_t n)
  *********************************************/
 
 static gcry_err_code_t
-rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
-                  const gcry_sexp_t genparms,
-                  gcry_mpi_t *skey, gcry_mpi_t **retfactors,
-                  gcry_sexp_t *r_extrainfo)
+rsa_generate (int algo, unsigned int nbits, unsigned long evalue,
+              const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 {
   RSA_secret_key sk;
   gpg_err_code_t ec;
@@ -794,10 +792,11 @@ rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
   int transient_key = 0;
   int use_x931 = 0;
   gcry_sexp_t l1;
+  gcry_sexp_t swap_info = NULL;
 
   (void)algo;
 
-  *retfactors = NULL; /* We don't return them.  */
+  memset (&sk, 0, sizeof sk);
 
   deriveparms = (genparms?
                  gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL);
@@ -817,20 +816,8 @@ rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
       int swapped;
       ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped);
       gcry_sexp_release (deriveparms);
-      if (!ec && r_extrainfo && swapped)
-        {
-          ec = gcry_sexp_new (r_extrainfo,
-                              "(misc-key-info(p-q-swapped))", 0, 1);
-          if (ec)
-            {
-              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;
-            }
-        }
+      if (!ec && swapped)
+        ec = gcry_sexp_new (&swap_info, "(misc-key-info(p-q-swapped))", 0, 1);
     }
   else
     {
@@ -847,23 +834,28 @@ rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
   if (!ec)
     {
-      skey[0] = sk.n;
-      skey[1] = sk.e;
-      skey[2] = sk.d;
-      skey[3] = sk.p;
-      skey[4] = sk.q;
-      skey[5] = sk.u;
+      ec = gcry_err_code (gcry_sexp_build
+                          (r_skey, NULL,
+                           "(key-data"
+                           " (public-key"
+                           "  (rsa(n%m)(e%m)))"
+                           " (private-key"
+                           "  (rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))"
+                           " %S)",
+                           sk.n, sk.e,
+                           sk.n, sk.e, sk.d, sk.p, sk.q, sk.u,
+                           swap_info));
     }
 
-  return ec;
-}
-
+  mpi_free (sk.n);
+  mpi_free (sk.e);
+  mpi_free (sk.p);
+  mpi_free (sk.q);
+  mpi_free (sk.d);
+  mpi_free (sk.u);
+  gcry_sexp_release (swap_info);
 
-static gcry_err_code_t
-rsa_generate (int algo, unsigned int nbits, unsigned long evalue,
-              gcry_mpi_t *skey, gcry_mpi_t **retfactors)
-{
-  return rsa_generate_ext (algo, nbits, evalue, NULL, skey, retfactors, NULL);
+  return ec;
 }
 
 
@@ -1440,6 +1432,5 @@ gcry_pk_spec_t _gcry_pubkey_spec_rsa =
     rsa_verify,
     rsa_get_nbits,
     run_selftests,
-    rsa_generate_ext,
     compute_keygrip
   };
index 121d9f5..1285fe8 100644 (file)
@@ -49,18 +49,10 @@ typedef gpg_err_code_t (*selftest_func_t)
 
 /* Type for the pk_generate function.  */
 typedef gcry_err_code_t (*gcry_pk_generate_t) (int algo,
-                                              unsigned int nbits,
-                                              unsigned long use_e,
-                                              gcry_mpi_t *skey,
-                                              gcry_mpi_t **retfactors);
-/* Type for the extended generate function.  */
-typedef gcry_err_code_t (*pk_ext_generate_t) (int algo,
-                                              unsigned int nbits,
-                                              unsigned long evalue,
-                                              gcry_sexp_t genparms,
-                                              gcry_mpi_t *skey,
-                                              gcry_mpi_t **retfactors,
-                                              gcry_sexp_t *extrainfo);
+                                               unsigned int nbits,
+                                               unsigned long evalue,
+                                               gcry_sexp_t genparms,
+                                               gcry_sexp_t *r_skey);
 
 /* Type for the pk_check_secret_key function.  */
 typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo,
@@ -143,7 +135,6 @@ typedef struct gcry_pk_spec
   gcry_pk_verify_t verify;
   gcry_pk_get_nbits_t get_nbits;
   selftest_func_t selftest;
-  pk_ext_generate_t ext_generate;
   pk_comp_keygrip_t comp_keygrip;
   pk_get_param_t get_param;
   pk_get_curve_t get_curve;