summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-11-25 11:05:14 +0000
committerWerner Koch <wk@gnupg.org>2008-11-25 11:05:14 +0000
commit2e6ec80233084146b47cd5f10a9c5762cd30c6ae (patch)
treeff9c6882bcf6084555656271673b7ad1626ead0f
parent8cc2eb702eeed951907db225f25a1088db4e5c44 (diff)
downloadlibgcrypt-2e6ec80233084146b47cd5f10a9c5762cd30c6ae.tar.gz
Finished RSA X9.31 key generation.
-rw-r--r--cipher/ChangeLog10
-rw-r--r--cipher/dsa.c76
-rw-r--r--cipher/ecc.c6
-rw-r--r--cipher/elgamal.c4
-rw-r--r--cipher/pubkey.c47
-rw-r--r--cipher/rsa.c116
-rw-r--r--doc/gcrypt.texi7
-rw-r--r--src/ChangeLog5
-rw-r--r--src/cipher-proto.h3
-rw-r--r--src/gcrypt.h.in4
-rw-r--r--src/sexp.c65
-rw-r--r--tests/ChangeLog8
-rw-r--r--tests/pubkey.c94
-rw-r--r--tests/tsexp.c27
14 files changed, 421 insertions, 51 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index b93ac023..bfb20ae7 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -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
diff --git a/cipher/dsa.c b/cipher/dsa.c
index fb5654e8..639c1a9e 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -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);
}
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 5df22b01..978c6d12 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -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);
}
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index a3eaf2ae..0b0c07cb 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -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)
{
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 6bc248c3..08abcbfd 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -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. */
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 8823af7e..967b6934 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -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);
}
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index e8d85b87..04f174c9 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -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
diff --git a/src/ChangeLog b/src/ChangeLog
index d503dd35..beda9b28 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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.
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 31bf6ba3..21532367 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -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)
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 864a300a..33b65e53 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -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);
diff --git a/src/sexp.c b/src/sexp.c
index 721069ea..59a4e7ed 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -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;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9867c278..229fd1c3 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -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>
diff --git a/tests/pubkey.c b/tests/pubkey.c
index d5b0a7ce..6c6d1c67 100644
--- a/tests/pubkey.c
+++ b/tests/pubkey.c
@@ -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))
diff --git a/tests/tsexp.c b/tests/tsexp.c
index 530aa4c8..21d54a62 100644
--- a/tests/tsexp.c
+++ b/tests/tsexp.c
@@ -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);