Finished RSA X9.31 key generation.
authorWerner Koch <wk@gnupg.org>
Tue, 25 Nov 2008 11:05:14 +0000 (11:05 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 25 Nov 2008 11:05:14 +0000 (11:05 +0000)
14 files changed:
cipher/ChangeLog
cipher/dsa.c
cipher/ecc.c
cipher/elgamal.c
cipher/pubkey.c
cipher/rsa.c
doc/gcrypt.texi
src/ChangeLog
src/cipher-proto.h
src/gcrypt.h.in
src/sexp.c
tests/ChangeLog
tests/pubkey.c
tests/tsexp.c

index b93ac02..bfb20ae 100644 (file)
@@ -1,5 +1,15 @@
 2008-11-24  Werner Koch  <wk@g10code.com>
 
+       * pubkey.c (gcry_pk_genkey): Insert code to output extrainfo.
+       (pubkey_generate): Add arg R_EXTRAINFO and pass it to the extended
+       key generation function.
+       * rsa.c (gen_x931_parm_xp, gen_x931_parm_xi): New.
+       (generate_x931): Generate params if not given.
+       (rsa_generate_ext): Parse use-x931 flag.  Return p-q-swapped
+       indicator.
+       * dsa.c (dsa_generate_ext): Put RETFACTORS into R_EXTRAINFO if
+       possible.
+
        * 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
index fb5654e..639c1a9 100644 (file)
@@ -461,7 +461,8 @@ 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_mpi_t *skey, gcry_mpi_t **retfactors,
+                  gcry_sexp_t *r_extrainfo)
 {
   gpg_err_code_t ec;
   DSA_secret_key sk;
@@ -502,6 +503,77 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
       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 (r_extrainfo && !*retfactors)
+        {
+          /* No factors, thus there is nothing to return.  */
+          *r_extrainfo = NULL;
+        }
+      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;
+          char *p;
+          char *format = NULL;
+          void **arg_list = NULL;
+
+          for (nfactors=0; (*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);
+          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, "))");
+              
+              /* 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);
+              if (!arg_list)
+                ec = gpg_err_code_from_syserror ();
+              else
+                {
+                  for (i=0; i < nfactors; i++)
+                    arg_list[i] = (*retfactors) + i;
+                  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;
+            }
+          *retfactors = NULL;
+          if (ec)
+            {
+              for (i=0; i < 5; i++)
+                {
+                  gcry_mpi_release (skey[i]);
+                  skey[i] = NULL;
+                }
+            }
+        }
     }
 
   return ec;
@@ -513,7 +585,7 @@ 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);
+  return dsa_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
 }
 
 
index 5df22b0..978c6d1 100644 (file)
@@ -954,7 +954,8 @@ os2ec (mpi_point_t *result, gcry_mpi_t value)
 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_mpi_t *skey, gcry_mpi_t **retfactors,
+                  gcry_sexp_t *r_extrainfo)
 {
   gpg_err_code_t ec;
   ECC_secret_key sk;
@@ -964,6 +965,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
   (void)algo;
   (void)evalue;
+  (void)r_extrainfo;
 
   if (genparms)
     {
@@ -1018,7 +1020,7 @@ 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 ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL);
 }
 
 
index a3eaf2a..0b0c07c 100644 (file)
@@ -615,7 +615,8 @@ 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_mpi_t *skey, gcry_mpi_t **retfactors,
+                  gcry_sexp_t *r_extrainfo)
 {
   gpg_err_code_t ec;
   ELG_secret_key sk;
@@ -624,6 +625,7 @@ elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
   (void)algo;
   (void)evalue;
+  (void)r_extrainfo;
 
   if (genparms)
     {
index 6bc248c..08abcbf 100644 (file)
@@ -542,7 +542,8 @@ pubkey_generate (int algorithm,
                  unsigned int nbits,
                  unsigned long use_e,
                  gcry_sexp_t genparms,
-                 gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+                 gcry_mpi_t *skey, gcry_mpi_t **retfactors,
+                 gcry_sexp_t *r_extrainfo)
 {
   gcry_err_code_t ec = GPG_ERR_PUBKEY_ALGO;
   gcry_module_t pubkey;
@@ -559,7 +560,7 @@ pubkey_generate (int algorithm,
         {
           /* Use the extended generate function.  */
           ec = extraspec->ext_generate 
-            (algorithm, nbits, use_e, genparms, skey, retfactors);
+            (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo);
         }
       else
         {
@@ -2076,7 +2077,9 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   const char *algo_name = NULL;
   int algo;
   const char *sec_elems = NULL, *pub_elems = NULL;
-  gcry_mpi_t skey[12], *factors = 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;
 
@@ -2132,7 +2135,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
 
   /* 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.  */
+     module API, so we need to parse it right here.  */
   l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
   if (l2)
     {
@@ -2177,7 +2180,8 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
     nbits = 0;
 
   /* Pass control to the algorithm module. */
-  rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey, &factors);
+  rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey, 
+                        &factors, &extrainfo);
   gcry_sexp_release (list); list = NULL;
   if (rc)
     goto leave;
@@ -2188,13 +2192,18 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
     size_t nelem=0, nelem_cp = 0, needed=0;
     gcry_mpi_t mpis[30];
     
+    /* Estimate size of format string.  */
     nelem = strlen (pub_elems) + strlen (sec_elems);
-    for (i = 0; factors[i]; i++)
-      nelem++;
+    if (factors)
+      {
+        for (i = 0; factors[i]; i++)
+          nelem++;
+      }
     nelem_cp = nelem;
 
     needed += nelem * 10;
-    needed += 2 * strlen (algo_name) + 300;
+    /* (+5 is for EXTRAINFO ("%S")).  */
+    needed += 2 * strlen (algo_name) + 300 + 5;
     if (nelem > DIM (mpis))
       BUG ();
 
@@ -2231,7 +2240,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
     /* Hack to make release_mpi_array() work.  */
     skey[i] = NULL;
 
-    if (factors[0])
+    if (extrainfo)
+      {
+        /* If we have extrainfo we should not have any factors.  */
+        p = stpcpy (p, "%S");
+      }
+    else if (factors && factors[0])
       {
         p = stpcpy (p, "(misc-key-info(pm1-factors");
         for(i = 0; factors[i]; i++)
@@ -2251,7 +2265,8 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
       int elem_n = strlen (pub_elems) + strlen (sec_elems);
       void **arg_list;
 
-      arg_list = malloc (nelem_cp * sizeof *arg_list);
+      /* Allocate one extra for EXTRAINFO ("%S").  */
+      arg_list = gcry_calloc (nelem_cp+1, sizeof *arg_list);
       if (!arg_list)
         {
           rc = gpg_err_code_from_errno (errno);
@@ -2259,11 +2274,16 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
         }
       for (i = 0; i < elem_n; i++)
         arg_list[i] = mpis + i;
-      for (; i < nelem_cp; i++)
-        arg_list[i] = factors + i - elem_n;
+      if (extrainfo)
+        arg_list[i] = &extrainfo;
+      else if (factors && factors[0])
+        {
+          for (; i < nelem_cp; i++)
+            arg_list[i] = factors + i - elem_n;
+        }
       
       rc = gcry_sexp_build_array (r_key, NULL, string, arg_list);
-      free (arg_list);
+      gcry_free (arg_list);
       if (rc)
        BUG ();
       gcry_assert (DIM (mpis) == 30); /* Reminder to make sure that
@@ -2275,6 +2295,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
 
  leave:
   gcry_free (name);
+  gcry_sexp_release (extrainfo);
   release_mpi_array (skey);
   /* Don't free SKEY itself, it is an stack allocated array. */
 
index 8823af7..967b693 100644 (file)
@@ -328,6 +328,46 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
 }
 
 
+/* Helper for generate_x931.  */
+static gcry_mpi_t 
+gen_x931_parm_xp (unsigned int nbits)
+{
+  gcry_mpi_t xp;
+
+  xp = gcry_mpi_snew (nbits);
+  gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM);
+      
+  /* The requirement for Xp is:
+
+       sqrt{2}*2^{nbits-1} <= xp <= 2^{nbits} - 1
+
+     We set the two high order bits to 1 to satisfy the lower bound.
+     By using mpi_set_highbit we make sure that the upper bound is
+     satisfied as well.  */
+  mpi_set_highbit (xp, nbits-1);
+  mpi_set_bit (xp, nbits-2);
+  gcry_assert ( mpi_get_nbits (xp) == nbits );
+  
+  return xp;
+}     
+
+
+/* Helper for generate_x931.  */
+static gcry_mpi_t 
+gen_x931_parm_xi (void)
+{
+  gcry_mpi_t xi;
+
+  xi = gcry_mpi_snew (101);
+  gcry_mpi_randomize (xi, 101, GCRY_VERY_STRONG_RANDOM);
+  mpi_set_highbit (xi, 100);
+  gcry_assert ( mpi_get_nbits (xi) == 101 );
+  
+  return xi;
+}     
+
+
+
 /* 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
@@ -378,14 +418,32 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
     gcry_mpi_t xq1 = NULL;
     gcry_mpi_t xq2 = NULL;
     gcry_mpi_t xq  = NULL;
+    gcry_mpi_t tmpval;
 
     if (!deriveparms)
       {
-        /* Fixme: Create them.  */
-        return GPG_ERR_INV_VALUE;
+        /* Not given: Generate them.  */
+        xp = gen_x931_parm_xp (nbits/2);
+        /* Make sure that |xp - xq| > 2^{nbits - 100} holds.  */
+        tmpval = gcry_mpi_snew (nbits/2);
+        do
+          {
+            gcry_mpi_release (xq);
+            xq = gen_x931_parm_xp (nbits/2);
+            mpi_sub (tmpval, xp, xq);
+          }
+        while (mpi_get_nbits (tmpval) <= (nbits/2 - 100));
+        gcry_mpi_release (tmpval);
+
+        xp1 = gen_x931_parm_xi ();
+        xp2 = gen_x931_parm_xi ();
+        xq1 = gen_x931_parm_xi ();
+        xq2 = gen_x931_parm_xi ();
+
       }
     else
       {
+        /* Parameters to derive the key are given.  */
         struct { const char *name; gcry_mpi_t *value; } tbl[] = {
           { "Xp1", &xp1 },
           { "Xp2", &xp2 },
@@ -478,7 +536,7 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
 
   if( DBG_CIPHER )
     {
-      if (swapped)
+      if (*swapped)
         log_debug ("p and q are swapped\n");
       log_mpidump("  p", p );
       log_mpidump("  q", q );
@@ -717,25 +775,52 @@ 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_mpi_t *skey, gcry_mpi_t **retfactors,
+                  gcry_sexp_t *r_extrainfo)
 {
   RSA_secret_key sk;
   gpg_err_code_t ec;
   gcry_sexp_t deriveparms;
   int transient_key = 0;
+  int use_x931 = 0;
   gcry_sexp_t l1;
-  int swapped;
-  int i;
 
   (void)algo;
+  
+  *retfactors = NULL; /* We don't return them.  */
 
   deriveparms = (genparms?
                  gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL);
+  if (!deriveparms)
+    {
+      /* Parse the optional "rsa-use-x931" flag. */
+      l1 = gcry_sexp_find_token (genparms, "use-x931", 0);
+      if (l1)
+        {
+          use_x931 = 1;
+          gcry_sexp_release (l1);
+        }
+    }
 
-  if (deriveparms || fips_mode ())
+  if (deriveparms || use_x931 || fips_mode ())
     {
+      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;
+            }
+        }
     }
   else
     {
@@ -745,7 +830,6 @@ rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
         {
           transient_key = 1;
           gcry_sexp_release (l1);
-          l1 = NULL;
         }
       /* Generate.  */
       ec = generate_std (&sk, nbits, evalue, transient_key);
@@ -759,20 +843,6 @@ rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
       skey[3] = sk.p;
       skey[4] = sk.q;
       skey[5] = sk.u;
-  
-      /* Make an empty list of factors.  */
-      *retfactors = gcry_calloc ( 1, sizeof **retfactors );
-      if (!*retfactors)
-        {
-          ec = gpg_err_code_from_syserror ();
-          for (i=0; i <= 5; i++)
-            {
-              gcry_mpi_release (skey[i]);
-              skey[i] = NULL;
-            }
-        }
-      else
-        ec = 0;
     }
   
   return ec;
@@ -783,7 +853,7 @@ 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);
+  return rsa_generate_ext (algo, nbits, evalue, NULL, skey, retfactors, NULL);
 }
 
 
index e8d85b8..04f174c 100644 (file)
@@ -2752,6 +2752,13 @@ FIPS mode.
             321DE34A#))))
 @end example
 
+@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.
+
+
 @end table
 @c end table of parameters
 
index d503dd3..beda9b2 100644 (file)
@@ -1,5 +1,10 @@
 2008-11-24  Werner Koch  <wk@g10code.com>
 
+       * sexp.c (get_internal_buffer): New.
+       (sexp_sscan): Add format character S.
+       * cipher-proto.h (pk_ext_generate_t): Add field EXTRAINFO  changed
+       all implementors.
+
        * cipher-proto.h (pk_ext_generate_t): Simplify. 
        (pk_get_param): New.
        (pk_extra_spec_t): Add field GET_PARAM.
index 31bf6ba..2153236 100644 (file)
@@ -46,7 +46,8 @@ typedef gcry_err_code_t (*pk_ext_generate_t)
       unsigned long evalue,
       gcry_sexp_t genparms,
       gcry_mpi_t *skey,
-      gcry_mpi_t **retfactors);
+      gcry_mpi_t **retfactors,
+      gcry_sexp_t *extrainfo);
 
 /* The type used to compute the keygrip.  */
 typedef gpg_err_code_t (*pk_comp_keygrip_t)
index 864a300..33b65e5 100644 (file)
@@ -1654,8 +1654,8 @@ void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
 
 
 /* Set the big integer W to a random value of NBITS using a random
-   generator with quality LEVEL.  Note that using a level of
-   GCRY_WEAK_RANDOM here, uses gcry_create_nonce internally. */
+   generator with quality LEVEL.  Note that by using a level of
+   GCRY_WEAK_RANDOM gcry_create_nonce is used internally. */
 void gcry_mpi_randomize (gcry_mpi_t w,
                          unsigned int nbits, enum gcry_random_level level);
 
index 721069e..59a4e7e 100644 (file)
@@ -1,6 +1,6 @@
 /* sexp.c  -  S-Expression handling
  * Copyright (C) 1999, 2000, 2001, 2002, 2003,
- *               2004, 2006, 2007 Free Software Foundation, Inc.
+ *               2004, 2006, 2007, 2008  Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -191,7 +191,7 @@ normalize ( gcry_sexp_t list )
 }
 
 /* Create a new S-expression object by reading LENGTH bytes from
-   BUFFER, assuming it is canonilized encoded or autodetected encoding
+   BUFFER, assuming it is canonical encoded or autodetected encoding
    when AUTODETECT is set to 1.  With FREEFNC not NULL, ownership of
    the buffer is transferred to the newly created object.  FREEFNC
    should be the freefnc used to release BUFFER; there is no guarantee
@@ -492,6 +492,47 @@ gcry_sexp_length( const gcry_sexp_t list )
 }
 
 
+/* Return the internal lengths offset of LIST.  That is the size of
+   the buffer from the first ST_OPEN, which is retruned at R_OFF, to
+   the corresponding ST_CLOSE inclusive.  */
+static size_t
+get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
+{
+  const unsigned char *p;
+  DATALEN n;
+  int type;
+  int level = 0;
+  
+  *r_off = 0;
+  if (list)
+    {
+      p = list->d;
+      while ( (type=*p) != ST_STOP ) 
+        {
+          p++;
+          if (type == ST_DATA) 
+            {
+              memcpy (&n, p, sizeof n);
+              p += sizeof n + n;
+            }
+          else if (type == ST_OPEN)
+            {
+              if (!level)
+                *r_off = (p-1) - list->d;
+              level++;
+            }
+          else if ( type == ST_CLOSE )
+            {
+              level--;
+              if (!level)
+                return p - list->d;
+            }
+        }
+    }
+  return 0; /* Not a proper list.  */
+}
+
+
 
 /* Extract the CAR of the given list.  May return NULL for bad lists
    or memory failure.  */
@@ -920,6 +961,9 @@ unquote_string (const char *string, size_t length, unsigned char *buf)
  *     %d - integer stored as string (no autoswitch to secure allocation)
  *      %b - memory buffer; this takes _two_ arguments: an integer with the 
  *           length of the buffer and a pointer to the buffer.
+ *      %S - Copy an gcry_sexp_t here.  The S-expression needs to be a
+ *           regular one, starting with a parenthesis. 
+ *           (no autoswitch to secure allocation)
  *  all other format elements are currently not defined and return an error.
  *  this includes the "%%" sequence becauce the percent sign is not an
  *  allowed character.
@@ -966,7 +1010,7 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
 #define ARG_NEXT(storage, type)                          \
   do                                                     \
     {                                                    \
-      if (!arg_list)                                    \
+      if (!arg_list)                                     \
        storage = va_arg (arg_ptr, type);                \
       else                                               \
        storage = *((type *) (arg_list[arg_counter++])); \
@@ -1310,6 +1354,21 @@ sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
              memcpy (c.pos, buf, alen);
              c.pos += alen;
            }
+         else if (*p == 'S')
+           {
+             /* Insert a gcry_sexp_t.  */
+             gcry_sexp_t asexp;
+             size_t alen, aoff;
+
+             ARG_NEXT (asexp, gcry_sexp_t);
+              alen = get_internal_buffer (asexp, &aoff);
+              if (alen)
+                {
+                  MAKE_SPACE (alen);
+                  memcpy (c.pos, asexp->d + aoff, alen);
+                  c.pos += alen;
+                }
+           }
          else
            {
              *erroff = p - buffer;
index 9867c27..229fd1c 100644 (file)
@@ -1,6 +1,14 @@
+2008-11-25  Werner Koch  <wk@g10code.com>
+
+       * pubkey.c (get_dsa_key_new): New.
+
 2008-11-24  Werner Koch  <wk@g10code.com>
 
+       * tsexp.c (basic): Add test for format character S.
+
        * pubkey.c (check_x931_derived_key): New.
+       (get_keys_x931_new): New.
+       (check_run): Check X9.31 generated RSA key.
 
 2008-11-07  Werner Koch  <wk@g10code.com>
 
index d5b0a7c..6c6d1c6 100644 (file)
@@ -266,6 +266,9 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   if (rc)
     die ("error generating RSA key: %s\n", gcry_strerror (rc));
     
+  if (verbose > 1)
+    show_sexp ("generated RSA key:\n", key);
+
   pub_key = gcry_sexp_find_token (key, "public-key", 0);
   if (! pub_key)
     die ("public part missing in key\n");
@@ -281,6 +284,38 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
 
 
 static void
+get_keys_x931_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 (rsa (nbits 4:1024)(use-x931)))", 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 RSA key: %s\n", gcry_strerror (rc));
+    
+  if (verbose > 1)
+    show_sexp ("generated RSA (X9.31) key:\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
 get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x)
 {
   gcry_sexp_t key_spec, key, pub_key, sec_key;
@@ -300,6 +335,40 @@ get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x)
   if (rc)
     die ("error generating Elgamal key: %s\n", gcry_strerror (rc));
     
+  if (verbose > 1)
+    show_sexp ("generated ELG key:\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
+get_dsa_key_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)))",  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 Elgamal key: %s\n", gcry_strerror (rc));
+    
+  if (verbose > 1)
+    show_sexp ("generated DSA key:\n", key);
+
   pub_key = gcry_sexp_find_token (key, "public-key", 0);
   if (!pub_key)
     die ("public part missing in key\n");
@@ -345,6 +414,13 @@ check_run (void)
   gcry_sexp_release (skey);
 
   if (verbose)
+    fprintf (stderr, "Checking generated RSA key (X9.31).\n");
+  get_keys_x931_new (&pkey, &skey);
+  check_keys (pkey, skey, 800, 0);
+  gcry_sexp_release (pkey);
+  gcry_sexp_release (skey);
+
+  if (verbose)
     fprintf (stderr, "Checking generated Elgamal key.\n");
   get_elg_key_new (&pkey, &skey, 0);
   check_keys (pkey, skey, 400, 0);
@@ -357,6 +433,13 @@ check_run (void)
   check_keys (pkey, skey, 800, 0);
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+
+  if (verbose)
+    fprintf (stderr, "Generating DSA key.\n");
+  get_dsa_key_new (&pkey, &skey);
+  /* Fixme:  Add a check function for DSA keys.  */
+  gcry_sexp_release (pkey);
+  gcry_sexp_release (skey);
 }
 
 
@@ -377,6 +460,7 @@ key_param_from_sexp (gcry_sexp_t sexp, const char *topname, const char *name)
       gcry_sexp_release (l1);
       return NULL;
     }
+
   result = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
   gcry_sexp_release (l2);
   gcry_sexp_release (l1);
@@ -552,8 +636,9 @@ check_x931_derived_key (int what)
   if (err)
     die ("error converting string [%d]\n", what);
 
-  if (verbose)
-    show_sexp ("generated private key:\n", sec_key);
+  if (verbose > 1)
+    show_sexp ("generated key:\n", key);
+
   d_have = key_param_from_sexp (sec_key, "rsa", "d");
   if (!d_have)
     die ("parameter d not found in RSA secret key [%d]\n", what);
@@ -582,7 +667,10 @@ main (int argc, char **argv)
   if (argc > 1 && !strcmp (argv[1], "--verbose"))
     verbose = 1;
   else if (argc > 1 && !strcmp (argv[1], "--debug"))
-    verbose = debug = 1;
+    {
+      verbose = 2;
+      debug = 1;
+    }
 
   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
   if (!gcry_check_version (GCRYPT_VERSION))
index 530aa4c..21d54a6 100644 (file)
@@ -130,6 +130,31 @@ basic (void)
           if (!gcry_is_secure (sexp))
             fail ("gcry_sexp_build did not switch to secure memory\n");
           break;
+
+        case 3:
+          {
+            gcry_sexp_t help_sexp;
+
+            if (gcry_sexp_new (&help_sexp,
+                               "(foobar-parms (xp #1234#)(xq #03#))", 0, 1))
+              {
+                fail (" scanning fixed string failed\n");
+                return;
+              }
+
+            string = ("(public-key (dsa (p #41424344#) (parm %S) "
+                      "(y dummy)(q %b) (g %m)))");
+            if ( gcry_sexp_build (&sexp, NULL, string, help_sexp,
+                                  secure_buffer_len, secure_buffer,
+                                  gcry_mpi_set_ui (NULL, 17)) )
+              {
+                fail (" scanning `%s' failed\n", string);
+                return;
+              }
+            gcry_sexp_release (help_sexp);
+          }
+          break;
+          
           
         default:
           return; /* Ready. */
@@ -416,7 +441,7 @@ check_sscan (void)
 int
 main (int argc, char **argv)
 {
-  if (argc > 1 && !strcmp (argv[1], "-v"))
+  if (argc > 1 && !strcmp (argv[1], "--verbose"))
     verbose = 1;
 
   gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);