[svn] gcry - r1360 - in trunk: . cipher doc src tests
svn author wk
cvs at cvs.gnupg.org
Tue Nov 25 22:09:55 CET 2008
Author: wk
Date: 2008-11-25 22:09:55 +0100 (Tue, 25 Nov 2008)
New Revision: 1360
Modified:
trunk/NEWS
trunk/cipher/ChangeLog
trunk/cipher/dsa.c
trunk/cipher/primegen.c
trunk/cipher/rsa.c
trunk/doc/gcrypt.texi
trunk/src/g10lib.h
trunk/tests/pubkey.c
Log:
Implement FIPS 186-2 key generation.
Modified: trunk/cipher/ChangeLog
===================================================================
--- trunk/cipher/ChangeLog 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/ChangeLog 2008-11-25 21:09:55 UTC (rev 1360)
@@ -1,3 +1,10 @@
+2008-11-25 Werner Koch <wk at g10code.com>
+
+ * dsa.c (generate_fips186): New.
+ (dsa_generate_ext): Use new function if derive-parms are given or
+ if in FIPS mode.
+ * primegen.c (_gcry_generate_fips186_2_prime): New.
+
2008-11-24 Werner Koch <wk at g10code.com>
* pubkey.c (gcry_pk_genkey): Insert code to output extrainfo.
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/NEWS 2008-11-25 21:09:55 UTC (rev 1360)
@@ -8,7 +8,10 @@
* Fixed HMAC for SHA-384 and SHA-512 with keys longer than 64 bytes.
+ * In fips mode, RSA keys are now generated using the X9.31 algorithm
+ and DSA keys using the FIPS 186-2 algorithm.
+
Noteworthy changes in version 1.4.3 (2008-09-18)
------------------------------------------------
Modified: trunk/cipher/dsa.c
===================================================================
--- trunk/cipher/dsa.c 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/dsa.c 2008-11-25 21:09:55 UTC (rev 1360)
@@ -325,11 +325,11 @@
if( DBG_CIPHER )
{
progress('\n');
- log_mpidump("dsa p= ", p );
- log_mpidump("dsa q= ", q );
- log_mpidump("dsa g= ", g );
- log_mpidump("dsa y= ", y );
- log_mpidump("dsa x= ", x );
+ log_mpidump("dsa p", p );
+ log_mpidump("dsa q", q );
+ log_mpidump("dsa g", g );
+ log_mpidump("dsa y", y );
+ log_mpidump("dsa x", x );
}
/* Copy the stuff to the key structures. */
@@ -354,7 +354,147 @@
}
+/* Generate a DSA key pair with a key of size NBITS using the
+ algorithm given in FIPS-186. At the time of implementation FIPS
+ 186-3 was not released; the Draft from November 2008 was used
+ instead to avoid limiting ourself to FIPS 186-2. */
+static gpg_err_code_t
+generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
+ int *r_counter, void **r_seed, size_t *r_seedlen,
+ gcry_mpi_t *r_h)
+{
+ gpg_err_code_t ec;
+ gcry_mpi_t prime_q = NULL;
+ gcry_mpi_t prime_p = NULL;
+ gcry_mpi_t value_g = NULL; /* The generator. */
+ gcry_mpi_t value_y = NULL; /* g^x mod p */
+ gcry_mpi_t value_x = NULL; /* The secret exponent. */
+ gcry_mpi_t value_h = NULL; /* Helper. */
+ gcry_mpi_t value_e = NULL; /* Helper. */
+ /* Preset return values. */
+ *r_counter = 0;
+ *r_seed = NULL;
+ *r_seedlen = 0;
+ *r_h = NULL;
+
+ /* Derive QBITS from NBITS if requested */
+ if (!qbits)
+ {
+ if (nbits == 1024)
+ qbits = 160;
+ else if (nbits == 2048)
+ qbits = 224;
+ else if (nbits == 3072)
+ qbits = 256;
+ }
+
+ /* Check that QBITS and NBITS match the standard. Note that FIPS
+ 186-3 uses N for QBITS and L for NBITS. */
+ if (nbits == 1024 && qbits == 160)
+ ;
+ else if (nbits == 2048 && qbits == 224)
+ ;
+ else if (nbits == 2048 && qbits == 256)
+ ;
+ else if (nbits == 2048 && qbits == 256)
+ ;
+ else
+ return GPG_ERR_INV_VALUE;
+
+ /* Note that we currently do not yet support 186-3 for prime
+ generation becuase it is not clear whether CAVS is prepared for
+ it. */
+ ec = _gcry_generate_fips186_2_prime (nbits, qbits, NULL, 0,
+ &prime_q, &prime_p,
+ r_counter,
+ r_seed, r_seedlen);
+ if (ec)
+ goto leave;
+
+ /* Find a generator g (h and e are helpers).
+ e = (p-1)/q */
+ value_e = mpi_alloc_like (prime_p);
+ mpi_sub_ui (value_e, prime_p, 1);
+ mpi_fdiv_q (value_e, value_e, prime_q );
+ value_g = mpi_alloc_like (prime_p);
+ value_h = mpi_alloc_set_ui (1);
+ do
+ {
+ mpi_add_ui (value_h, value_h, 1);
+ /* g = h^e mod p */
+ mpi_powm (value_g, value_h, value_e, prime_p);
+ }
+ while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */
+
+ /* Select a random number x with: 0 < x < q */
+ value_x = gcry_mpi_snew (qbits);
+ do
+ {
+ if( DBG_CIPHER )
+ progress('.');
+ gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM);
+ mpi_clear_highbit (value_x, qbits+1);
+ }
+ while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0));
+
+ /* y = g^x mod p */
+ value_y = mpi_alloc_like (prime_p);
+ gcry_mpi_powm (value_y, value_g, value_x, prime_p);
+
+ if (DBG_CIPHER)
+ {
+ progress('\n');
+ log_mpidump("dsa p", prime_p );
+ log_mpidump("dsa q", prime_q );
+ log_mpidump("dsa g", value_g );
+ log_mpidump("dsa y", value_y );
+ log_mpidump("dsa x", value_x );
+ log_mpidump("dsa h", value_h );
+ }
+
+ /* Copy the stuff to the key structures. */
+ sk->p = prime_p; prime_p = NULL;
+ sk->q = prime_q; prime_q = NULL;
+ sk->g = value_g; value_g = NULL;
+ sk->y = value_y; value_y = NULL;
+ sk->x = value_x; value_x = NULL;
+ *r_h = value_h; value_h = NULL;
+
+ leave:
+ gcry_mpi_release (prime_p);
+ gcry_mpi_release (prime_q);
+ gcry_mpi_release (value_g);
+ gcry_mpi_release (value_y);
+ gcry_mpi_release (value_x);
+ gcry_mpi_release (value_h);
+ gcry_mpi_release (value_e);
+
+ /* As a last step test this keys (this should never fail of course). */
+ if (!ec && test_keys (sk, qbits) )
+ {
+ gcry_mpi_release (sk->p); sk->p = NULL;
+ gcry_mpi_release (sk->q); sk->q = NULL;
+ gcry_mpi_release (sk->g); sk->g = NULL;
+ gcry_mpi_release (sk->y); sk->y = NULL;
+ gcry_mpi_release (sk->x); sk->x = NULL;
+ fips_signal_error ("self-test after key generation failed");
+ ec = GPG_ERR_SELFTEST_FAILED;
+ }
+
+ if (ec)
+ {
+ *r_counter = 0;
+ gcry_free (*r_seed); *r_seed = NULL;
+ *r_seedlen = 0;
+ gcry_mpi_release (*r_h); *r_h = NULL;
+ }
+
+ return ec;
+}
+
+
+
/*
Test whether the secret key is valid.
Returns: if this is a valid key.
@@ -468,13 +608,17 @@
DSA_secret_key sk;
gcry_sexp_t l1;
unsigned int qbits = 0;
+ gcry_sexp_t deriveparms = NULL;
+ gcry_sexp_t seedinfo = NULL;
+ int use_fips186 = 0;
+
(void)algo; /* No need to check it. */
(void)evalue; /* Not required for DSA. */
- /* Parse the optional qbits element. */
if (genparms)
{
+ /* Parse the optional qbits element. */
l1 = gcry_sexp_find_token (genparms, "qbits", 0);
if (l1)
{
@@ -493,9 +637,50 @@
qbits = (unsigned int)strtoul (buf, NULL, 0);
gcry_sexp_release (l1);
}
+
+ deriveparms = gcry_sexp_find_token (genparms, "derive-parms", 0);
+
+ /* Parse the optional "use-fips186" flag. */
+ l1 = gcry_sexp_find_token (genparms, "use-fips186", 0);
+ if (l1)
+ {
+ use_fips186 = 1;
+ gcry_sexp_release (l1);
+ }
}
- ec = generate (&sk, nbits, qbits, retfactors);
+ if (deriveparms || use_fips186 || fips_mode ())
+ {
+ int counter;
+ void *seed;
+ size_t seedlen;
+ gcry_mpi_t h_value;
+
+ ec = generate_fips186 (&sk, nbits, qbits,
+ &counter, &seed, &seedlen, &h_value);
+ gcry_sexp_release (deriveparms);
+ if (!ec)
+ {
+ ec = gpg_err_code (gcry_sexp_build
+ (&seedinfo, NULL,
+ "(seed-values(counter %d)(seed %b)(h %m))",
+ counter, (int)seedlen, seed, h_value));
+ if (ec)
+ {
+ gcry_mpi_release (sk.p); sk.p = NULL;
+ gcry_mpi_release (sk.q); sk.q = NULL;
+ gcry_mpi_release (sk.g); sk.g = NULL;
+ gcry_mpi_release (sk.y); sk.y = NULL;
+ gcry_mpi_release (sk.x); sk.x = NULL;
+ }
+ gcry_free (seed);
+ gcry_mpi_release (h_value);
+ }
+ }
+ else
+ {
+ ec = generate (&sk, nbits, qbits, retfactors);
+ }
if (!ec)
{
skey[0] = sk.p;
@@ -509,9 +694,9 @@
/* Old style interface - return the factors - if any - at
retfactors. */
}
- else if (r_extrainfo && !*retfactors)
+ else if (!*retfactors && !seedinfo)
{
- /* No factors, thus there is nothing to return. */
+ /* No factors and no seedinfo, thus there is nothing to return. */
*r_extrainfo = NULL;
}
else
@@ -520,36 +705,46 @@
to make use of the new interface. Note that the factors
are not confidential thus we can store them in standard
memory. */
- int nfactors, i;
+ int nfactors, i, j;
char *p;
char *format = NULL;
void **arg_list = NULL;
- for (nfactors=0; (*retfactors)[nfactors]; nfactors++)
+ for (nfactors=0; *retfactors && (*retfactors)[nfactors]; nfactors++)
;
/* Allocate space for the format string:
- "(misc-key-info(pm1-factors%m))"
- with one "%m" for each factor and build the string */
- format = gcry_malloc (40 + 2*nfactors);
+ "(misc-key-info%S(pm1-factors%m))"
+ with one "%m" for each factor and construct it. */
+ format = gcry_malloc (50 + 2*nfactors);
if (!format)
ec = gpg_err_code_from_syserror ();
else
{
- p = stpcpy (format, "(misc-key-info(pm1-factors");
- for (i=0; i < nfactors; i++)
- p = stpcpy (p, "%m");
- p = stpcpy (p, "))");
+ p = stpcpy (format, "(misc-key-info");
+ if (seedinfo)
+ p = stpcpy (p, "%S");
+ if (nfactors)
+ {
+ p = stpcpy (p, "(pm1-factors");
+ for (i=0; i < nfactors; i++)
+ p = stpcpy (p, "%m");
+ p = stpcpy (p, ")");
+ }
+ p = stpcpy (p, ")");
- /* Allocate space for the argument list plus an extra
- NULL entry for safety and fill it with the
- factors. */
- arg_list = gcry_calloc (nfactors+1, sizeof *arg_list);
+ /* Allocate space for the list of factors plus one for
+ an S-expression plus an extra NULL entry for safety
+ and fill it with the factors. */
+ arg_list = gcry_calloc (nfactors+1+1, sizeof *arg_list);
if (!arg_list)
ec = gpg_err_code_from_syserror ();
else
{
- for (i=0; i < nfactors; i++)
- arg_list[i] = (*retfactors) + i;
+ i = 0;
+ if (seedinfo)
+ arg_list[i++] = &seedinfo;
+ for (j=0; j < nfactors; j++)
+ arg_list[i++] = (*retfactors) + j;
arg_list[i] = NULL;
ec = gpg_err_code (gcry_sexp_build_array
@@ -576,6 +771,7 @@
}
}
+ gcry_sexp_release (seedinfo);
return ec;
}
Modified: trunk/cipher/primegen.c
===================================================================
--- trunk/cipher/primegen.c 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/primegen.c 2008-11-25 21:09:55 UTC (rev 1360)
@@ -1274,7 +1274,8 @@
}
-/* Helper for _gcry_generate_x931_prime. */
+
+/* Helper for _gcry_derive_x931_prime. */
static gcry_mpi_t
find_x931_prime (const gcry_mpi_t pfirst)
{
@@ -1411,3 +1412,207 @@
mpi_free (p2);
return yp0;
}
+
+
+
+/* Generate the two prime used for DSA using the algorithm specified
+ in FIPS 186-2. PBITS is the desired length of the prime P and a
+ QBIST the length of the prime Q. If SEED is not supplied and
+ SEEDLEN is 0 the function generates an appropriate SEED. On
+ success the generated primes are stored at R_Q and R_P, the counter
+ value is stored at R_COUNTER and the seed actually used for
+ generation is stored at R_SEED and R_SEEDVALUE. */
+gpg_err_code_t
+_gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits,
+ const void *seed, size_t seedlen,
+ gcry_mpi_t *r_q, gcry_mpi_t *r_p,
+ int *r_counter,
+ void **r_seed, size_t *r_seedlen)
+{
+ gpg_err_code_t ec;
+ unsigned char seed_help_buffer[160/8]; /* Used to hold a generated SEED. */
+ unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */
+ unsigned char digest[160/8]; /* Helper buffer for SHA-1 digest. */
+ gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */
+ gcry_mpi_t tmpval = NULL; /* Helper variable. */
+ int i;
+
+ unsigned char value_u[160/8];
+ int value_n, value_b, value_k;
+ int counter;
+ gcry_mpi_t value_w = NULL;
+ gcry_mpi_t value_x = NULL;
+ gcry_mpi_t prime_q = NULL;
+ gcry_mpi_t prime_p = NULL;
+
+ /* FIPS 186-2 allows only for 1024/160 bit. */
+ if (pbits != 1024 || qbits != 160)
+ return GPG_ERR_INV_KEYLEN;
+
+ if (!seed && !seedlen)
+ ; /* No seed value given: We are asked to generate it. */
+ else if (!seed || seedlen < qbits/8)
+ return GPG_ERR_INV_ARG;
+
+ /* Allocate a buffer to later compute SEED+some_increment. */
+ seed_plus = gcry_malloc (seedlen < 20? 20:seedlen);
+ if (!seed_plus)
+ {
+ ec = gpg_err_code_from_syserror ();
+ goto leave;
+ }
+
+ val_2 = mpi_alloc_set_ui (2);
+ value_n = (pbits - 1) / qbits;
+ value_b = (pbits - 1) - value_n * qbits;
+ value_w = gcry_mpi_new (pbits);
+ value_x = gcry_mpi_new (pbits);
+
+ restart:
+ /* Generate Q. */
+ for (;;)
+ {
+ /* Step 1: Generate a (new) seed unless one has been supplied. */
+ if (!seed)
+ {
+ seedlen = sizeof seed_help_buffer;
+ gcry_create_nonce (seed_help_buffer, seedlen);
+ seed = seed_help_buffer;
+ }
+
+ /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits}) */
+ memcpy (seed_plus, seed, seedlen);
+ for (i=seedlen-1; i >= 0; i--)
+ {
+ seed_plus[i]++;
+ if (seed_plus[i])
+ break;
+ }
+ gcry_md_hash_buffer (GCRY_MD_SHA1, value_u, seed, seedlen);
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+ for (i=0; i < sizeof value_u; i++)
+ value_u[i] ^= digest[i];
+
+ /* Step 3: Form q from U */
+ gcry_mpi_release (prime_q); prime_q = NULL;
+ ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG,
+ value_u, sizeof value_u, NULL));
+ if (ec)
+ goto leave;
+ mpi_set_highbit (prime_q, qbits-1 );
+ mpi_set_bit (prime_q, 0);
+
+ /* Step 4: Test whether Q is prime using 64 round of Rabin-Miller. */
+ if (check_prime (prime_q, val_2, 64, NULL, NULL))
+ break; /* Yes, Q is prime. */
+
+ /* Step 5. */
+ seed = NULL; /* Force a new seed at Step 1. */
+ }
+
+ /* Step 6. Note that we do no use an explicit offset but increment
+ SEED_PLUS accordingly. SEED_PLUS is currently SEED+1. */
+ counter = 0;
+
+ /* Generate P. */
+ prime_p = gcry_mpi_new (pbits);
+ for (;;)
+ {
+ /* Step 7: For k = 0,...n let
+ V_k = sha1(seed+offset+k) mod 2^{qbits}
+ Step 8: W = V_0 + V_1*2^160 +
+ ...
+ + V_{n-1}*2^{(n-1)*160}
+ + (V_{n} mod 2^b)*2^{n*160}
+ */
+ mpi_set_ui (value_w, 0);
+ for (value_k=0; value_k <= value_n; value_k++)
+ {
+ /* There is no need to have an explicit offset variable: In
+ the first round we shall have an offset of 2, this is
+ achieved by using SEED_PLUS which is already at SEED+1,
+ thus we just need to increment it once again. The
+ requirement for the next round is to update offset by N,
+ which we implictly did at the end of this loop, and then
+ to add one; this one is the same as in the first round. */
+ for (i=seedlen-1; i >= 0; i--)
+ {
+ seed_plus[i]++;
+ if (seed_plus[i])
+ break;
+ }
+ gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+
+ gcry_mpi_release (tmpval); tmpval = NULL;
+ ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
+ digest, sizeof digest, NULL));
+ if (ec)
+ goto leave;
+ if (value_k == value_n)
+ mpi_clear_highbit (tmpval, value_b+1); /* (V_n mod 2^b) */
+ mpi_lshift (tmpval, tmpval, value_k*qbits);
+ mpi_add (value_w, value_w, tmpval);
+ }
+
+ /* Step 8 continued: X = W + 2^{L-1} */
+ mpi_set_ui (value_x, 0);
+ mpi_set_highbit (value_x, pbits-1);
+ mpi_add (value_x, value_x, value_w);
+
+ /* Step 9: c = X mod 2q, p = X - (c - 1) */
+ mpi_mul_2exp (tmpval, prime_q, 1);
+ mpi_mod (tmpval, value_x, tmpval);
+ mpi_sub_ui (tmpval, tmpval, 1);
+ mpi_sub (prime_p, value_x, tmpval);
+
+ /* Step 10: If p < 2^{L-1} skip the primality test. */
+ /* Step 11 and 12: Primality test. */
+ if (mpi_get_nbits (prime_p) >= pbits-1
+ && check_prime (prime_p, val_2, 64, NULL, NULL) )
+ break; /* Yes, P is prime, continue with Step 15. */
+
+ /* Step 13: counter = counter + 1, offset = offset + n + 1. */
+ counter++;
+
+ /* Step 14: If counter >= 2^12 goto Step 1. */
+ if (counter >= 4096)
+ goto restart;
+ }
+
+ /* Step 15: Save p, q, counter and seed. */
+/* log_debug ("fips186-2 nbits p=%u q=%u counter=%d\n", */
+/* mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */
+/* log_printhex("fips186-2 seed:", seed, seedlen); */
+/* log_mpidump ("fips186-2 prime p", prime_p); */
+/* log_mpidump ("fips186-2 prime q", prime_q); */
+ if (r_q)
+ {
+ *r_q = prime_q;
+ prime_q = NULL;
+ }
+ if (r_p)
+ {
+ *r_p = prime_p;
+ prime_p = NULL;
+ }
+ if (r_counter)
+ *r_counter = counter;
+ if (r_seed && r_seedlen)
+ {
+ memcpy (seed_plus, seed, seedlen);
+ *r_seed = seed_plus;
+ seed_plus = NULL;
+ *r_seedlen = seedlen;
+ }
+
+
+ leave:
+ gcry_mpi_release (tmpval);
+ gcry_mpi_release (value_x);
+ gcry_mpi_release (value_w);
+ gcry_mpi_release (prime_p);
+ gcry_mpi_release (prime_q);
+ gcry_free (seed_plus);
+ gcry_mpi_release (val_2);
+ return ec;
+}
Modified: trunk/cipher/rsa.c
===================================================================
--- trunk/cipher/rsa.c 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/cipher/rsa.c 2008-11-25 21:09:55 UTC (rev 1360)
@@ -793,7 +793,7 @@
gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL);
if (!deriveparms)
{
- /* Parse the optional "rsa-use-x931" flag. */
+ /* Parse the optional "use-x931" flag. */
l1 = gcry_sexp_find_token (genparms, "use-x931", 0);
if (l1)
{
Modified: trunk/doc/gcrypt.texi
===================================================================
--- trunk/doc/gcrypt.texi 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/doc/gcrypt.texi 2008-11-25 21:09:55 UTC (rev 1360)
@@ -2755,10 +2755,18 @@
@item use-x931
Force the use of the ANSI X9.31 key generation algorithm instead of
the default algorithm. This flag is only meaningful for RSA and
-usullat not required. Note that this algorithm is implicitly used if
-either @code{derive-parms} are given or Libgcrypt is in FIPS mode.
+usually not required. Note that this algorithm is implicitly used if
+either @code{derive-parms} is given or Libgcrypt is in FIPS mode.
+ at item use-fips186
+Force the use of the FIPS 186-2 key generation algorithm instead of
+the default algorithm. This flag is only meaningful for DSA and
+usually not required. Note that this algorithm is implicitly used if
+either @code{derive-parms} is given or Libgcrypt is in FIPS mode.
+This implementation may be changed in future to use the forthcoming
+FIPS 186-3 algorithm.
+
@end table
@c end table of parameters
Modified: trunk/src/g10lib.h
===================================================================
--- trunk/src/g10lib.h 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/src/g10lib.h 2008-11-25 21:09:55 UTC (rev 1360)
@@ -179,6 +179,12 @@
const gcry_mpi_t xp1, const gcry_mpi_t xp2,
const gcry_mpi_t e,
gcry_mpi_t *r_p1, gcry_mpi_t *r_p2);
+gpg_err_code_t _gcry_generate_fips186_2_prime
+ (unsigned int pbits, unsigned int qbits,
+ const void *seed, size_t seedlen,
+ gcry_mpi_t *r_q, gcry_mpi_t *r_p,
+ int *r_counter,
+ void **r_seed, size_t *r_seedlen);
/* replacements of missing functions (missing-string.c)*/
Modified: trunk/tests/pubkey.c
===================================================================
--- trunk/tests/pubkey.c 2008-11-25 11:05:14 UTC (rev 1359)
+++ trunk/tests/pubkey.c 2008-11-25 21:09:55 UTC (rev 1360)
@@ -364,7 +364,7 @@
rc = gcry_pk_genkey (&key, key_spec);
gcry_sexp_release (key_spec);
if (rc)
- die ("error generating Elgamal key: %s\n", gcry_strerror (rc));
+ die ("error generating DSA key: %s\n", gcry_strerror (rc));
if (verbose > 1)
show_sexp ("generated DSA key:\n", key);
@@ -384,6 +384,37 @@
static void
+get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
+{
+ gcry_sexp_t key_spec, key, pub_key, sec_key;
+ int rc;
+
+ rc = gcry_sexp_new
+ (&key_spec, "(genkey (dsa (nbits 4:1024)(use-fips186)))", 0, 1);
+ if (rc)
+ die ("error creating S-expression: %s\n", gcry_strerror (rc));
+ rc = gcry_pk_genkey (&key, key_spec);
+ gcry_sexp_release (key_spec);
+ if (rc)
+ die ("error generating DSA key: %s\n", gcry_strerror (rc));
+
+ if (verbose > 1)
+ show_sexp ("generated DSA key (fips 186):\n", key);
+
+ pub_key = gcry_sexp_find_token (key, "public-key", 0);
+ if (!pub_key)
+ die ("public part missing in key\n");
+
+ sec_key = gcry_sexp_find_token (key, "private-key", 0);
+ if (!sec_key)
+ die ("private part missing in key\n");
+
+ gcry_sexp_release (key);
+ *pkey = pub_key;
+ *skey = sec_key;
+}
+
+static void
check_run (void)
{
gpg_error_t err;
@@ -440,6 +471,13 @@
/* Fixme: Add a check function for DSA keys. */
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
+
+ if (verbose)
+ fprintf (stderr, "Generating DSA key (FIPS 186).\n");
+ get_dsa_key_fips186_new (&pkey, &skey);
+ /* Fixme: Add a check function for DSA keys. */
+ gcry_sexp_release (pkey);
+ gcry_sexp_release (skey);
}
@@ -684,7 +722,7 @@
for (i=0; i < 2; i++)
check_run ();
- for (i=0; i < 4; i++)
+ for (i=0; i < 4; i++)
check_x931_derived_key (i);
return 0;
More information about the Gnupg-commits
mailing list