summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-02-23 17:47:56 +0000
committerWerner Koch <wk@gnupg.org>2007-02-23 17:47:56 +0000
commiteaba8d58acda66f428870794115cb22c2590ec5e (patch)
tree26b91c662001beff12e128f0b2c9ededc9e5a55b
parent1cfac9fd5f628c2d505b6c01d2cc0657840299ed (diff)
downloadlibgcrypt-eaba8d58acda66f428870794115cb22c2590ec5e.tar.gz
Ported last changes from 1.2.
Updated some tests. Support for passphrase generated Elgamal keys.
-rw-r--r--cipher/ChangeLog9
-rw-r--r--cipher/elgamal.c148
-rw-r--r--cipher/pubkey.c43
-rw-r--r--mpi/ChangeLog7
-rw-r--r--mpi/mpi-pow.c3
-rw-r--r--mpi/mpiutil.c11
-rw-r--r--src/cipher.h5
-rw-r--r--tests/ChangeLog15
-rw-r--r--tests/Makefile.am10
-rw-r--r--tests/ac-data.c7
-rw-r--r--tests/pubkey.c76
-rw-r--r--tests/random.c255
12 files changed, 539 insertions, 50 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index b8ff7c5a..9c1e5128 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,12 @@
+2007-02-23 Werner Koch <wk@g10code.com>
+
+ * elgamal.c (generate): Removed unused variable TEMP.
+ (test_keys): New arg NODIE.
+ (generate_using_x, _gcry_elg_generate_using_x): New.
+ * pubkey.c (pubkey_generate): New arg XVALUE and direct call to
+ the new elgamal generate fucntion.
+ (gcry_pk_genkey): Parse the new "xvalue" tag.
+
2007-02-22 Werner Koch <wk@g10code.com>
* pubkey.c (sexp_data_to_mpi): Handle dynamically allocated
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 066ffb61..4a76e910 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -1,4 +1,4 @@
-/* Elgamal.c - ElGamal Public Key encryption
+/* Elgamal.c - Elgamal Public Key encryption
* Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
@@ -47,7 +47,7 @@ typedef struct
} ELG_secret_key;
-static void test_keys (ELG_secret_key *sk, unsigned nbits);
+static int test_keys (ELG_secret_key *sk, unsigned int nbits, int nodie);
static gcry_mpi_t gen_k (gcry_mpi_t p, int small_k);
static void generate (ELG_secret_key *sk, unsigned nbits, gcry_mpi_t **factors);
static int check_secret_key (ELG_secret_key *sk);
@@ -123,34 +123,46 @@ wiener_map( unsigned int n )
return n / 8 + 200;
}
-static void
-test_keys( ELG_secret_key *sk, unsigned nbits )
+static int
+test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie )
{
ELG_public_key pk;
gcry_mpi_t test = gcry_mpi_new ( 0 );
gcry_mpi_t out1_a = gcry_mpi_new ( nbits );
gcry_mpi_t out1_b = gcry_mpi_new ( nbits );
gcry_mpi_t out2 = gcry_mpi_new ( nbits );
+ int failed = 0;
pk.p = sk->p;
pk.g = sk->g;
pk.y = sk->y;
- gcry_mpi_randomize( test, nbits, GCRY_WEAK_RANDOM );
+ gcry_mpi_randomize ( test, nbits, GCRY_WEAK_RANDOM );
- do_encrypt( out1_a, out1_b, test, &pk );
- decrypt( out2, out1_a, out1_b, sk );
- if( mpi_cmp( test, out2 ) )
- log_fatal("ElGamal operation: encrypt, decrypt failed\n");
+ do_encrypt ( out1_a, out1_b, test, &pk );
+ decrypt ( out2, out1_a, out1_b, sk );
+ if ( mpi_cmp( test, out2 ) )
+ failed |= 1;
- sign( out1_a, out1_b, test, sk );
- if( !verify( out1_a, out1_b, test, &pk ) )
- log_fatal("ElGamal operation: sign, verify failed\n");
+ sign ( out1_a, out1_b, test, sk );
+ if ( !verify( out1_a, out1_b, test, &pk ) )
+ failed |= 2;
gcry_mpi_release ( test );
gcry_mpi_release ( out1_a );
gcry_mpi_release ( out1_b );
gcry_mpi_release ( out2 );
+
+ if (failed && !nodie)
+ log_fatal ("Elgamal test key for %s %s failed\n",
+ (failed & 1)? "encrypt+decrypt":"",
+ (failed & 2)? "sign+verify":"");
+ if (failed && DBG_CIPHER)
+ log_debug ("Elgamal test key for %s %s failed\n",
+ (failed & 1)? "encrypt+decrypt":"",
+ (failed & 2)? "sign+verify":"");
+
+ return failed;
}
@@ -239,7 +251,7 @@ gen_k( gcry_mpi_t p, int small_k )
/****************
* Generate a key pair with a key of size NBITS
- * Returns: 2 structures filles with all needed values
+ * Returns: 2 structures filled with all needed values
* and an array with n-1 factors of (p-1)
*/
static void
@@ -250,13 +262,11 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors )
gcry_mpi_t g;
gcry_mpi_t x; /* the secret exponent */
gcry_mpi_t y;
- gcry_mpi_t temp;
unsigned int qbits;
unsigned int xbits;
byte *rndbuf;
p_min1 = gcry_mpi_new ( nbits );
- temp = gcry_mpi_new( nbits );
qbits = wiener_map( nbits );
if( qbits & 1 ) /* better have a even one */
qbits++;
@@ -332,11 +342,90 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors )
sk->y = y;
sk->x = x;
+ gcry_mpi_release ( p_min1 );
+
/* Now we can test our keys (this should never fail!) */
- test_keys( sk, nbits - 64 );
+ test_keys ( sk, nbits - 64, 0 );
+}
+
+
+/* Generate a key pair with a key of size NBITS not using a random
+ value for the secret key but the one given as X. This is useful to
+ implement a passphrase based decryption for a public key based
+ encryption. It has appliactions in backup systems.
+
+ Returns: A structure filled with all needed values and an array
+ with n-1 factors of (p-1). */
+static gcry_err_code_t
+generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x,
+ gcry_mpi_t **ret_factors )
+{
+ gcry_mpi_t p; /* The prime. */
+ gcry_mpi_t p_min1; /* The prime minus 1. */
+ gcry_mpi_t g; /* The generator. */
+ gcry_mpi_t y; /* g^x mod p. */
+ unsigned int qbits;
+ unsigned int xbits;
+
+ sk->p = NULL;
+ sk->g = NULL;
+ sk->y = NULL;
+ sk->x = NULL;
+
+ /* Do a quick check to see whether X is suitable. */
+ xbits = mpi_get_nbits (x);
+ if ( xbits < 64 || xbits >= nbits )
+ return GPG_ERR_INV_VALUE;
+
+ p_min1 = gcry_mpi_new ( nbits );
+ qbits = wiener_map ( nbits );
+ if ( (qbits & 1) ) /* Better have an even one. */
+ qbits++;
+ g = mpi_alloc (1);
+ p = _gcry_generate_elg_prime ( 0, nbits, qbits, g, ret_factors );
+ mpi_sub_ui (p_min1, p, 1);
+
+ if (DBG_CIPHER)
+ log_debug ("using a supplied x of size %u", xbits );
+ if ( !(mpi_cmp_ui ( x, 0 ) > 0 && mpi_cmp ( x, p_min1 ) <0 ) )
+ {
+ gcry_mpi_release ( p_min1 );
+ gcry_mpi_release ( p );
+ gcry_mpi_release ( g );
+ return GPG_ERR_INV_VALUE;
+ }
+
+ y = gcry_mpi_new (nbits);
+ gcry_mpi_powm ( y, g, x, p );
+
+ 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 );
+ }
+
+ /* Copy the stuff to the key structures */
+ sk->p = p;
+ sk->g = g;
+ sk->y = y;
+ sk->x = gcry_mpi_copy (x);
gcry_mpi_release ( p_min1 );
- gcry_mpi_release ( temp );
+
+ /* Now we can test our keys. */
+ if ( test_keys ( sk, nbits - 64, 1 ) )
+ {
+ gcry_mpi_release ( sk->p ); sk->p = 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;
+ return GPG_ERR_BAD_SECKEY;
+ }
+
+ return 0;
}
@@ -523,7 +612,7 @@ verify(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
*********************************************/
gcry_err_code_t
-_gcry_elg_generate (int algo, unsigned nbits, unsigned long dummy,
+_gcry_elg_generate (int algo, unsigned int nbits, unsigned long dummy,
gcry_mpi_t *skey, gcry_mpi_t **retfactors)
{
ELG_secret_key sk;
@@ -541,6 +630,29 @@ _gcry_elg_generate (int algo, unsigned nbits, unsigned long dummy,
}
+/* This is a specila generate function which is not called via the
+ module interface. */
+gcry_err_code_t
+_gcry_elg_generate_using_x (int algo, unsigned int nbits, gcry_mpi_t x,
+ gcry_mpi_t *skey, gcry_mpi_t **retfactors)
+{
+ gcry_err_code_t ec;
+ ELG_secret_key sk;
+
+ (void)algo;
+
+ ec = generate_using_x (&sk, nbits, x, retfactors);
+ if (!ec)
+ {
+ skey[0] = sk.p;
+ skey[1] = sk.g;
+ skey[2] = sk.y;
+ skey[3] = sk.x;
+ }
+ return ec;
+}
+
+
gcry_err_code_t
_gcry_elg_check_secret_key (int algo, gcry_mpi_t *skey)
{
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index a833c3dd..0b14cb80 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -497,7 +497,7 @@ pubkey_get_nenc (int algorithm)
static gcry_err_code_t
pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
- unsigned long use_e,
+ unsigned long use_e, gcry_mpi_t xvalue,
gcry_mpi_t *skey, gcry_mpi_t **retfactors)
{
gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
@@ -511,11 +511,22 @@ pubkey_generate (int algorithm, unsigned int nbits, unsigned int qbits,
{
/* Hack to pass QBITS to the DSA generation. */
if (qbits && pubkey->spec == &_gcry_pubkey_spec_dsa)
- err = _gcry_dsa_generate2
- (algorithm, nbits, qbits, 0, skey, retfactors);
+ {
+ err = _gcry_dsa_generate2
+ (algorithm, nbits, qbits, 0, skey, retfactors);
+ }
+#ifdef USE_ELGAMAL
+ else if (xvalue && pubkey->spec == &_gcry_pubkey_spec_elg)
+ {
+ err = _gcry_elg_generate_using_x
+ (algorithm, nbits, xvalue, skey, retfactors);
+ }
+#endif /*USE_ELGAMAL*/
else
- err = ((gcry_pk_spec_t *) pubkey->spec)->generate
- (algorithm, nbits, use_e, skey, retfactors);
+ {
+ err = ((gcry_pk_spec_t *) pubkey->spec)->generate
+ (algorithm, nbits, use_e, skey, retfactors);
+ }
_gcry_module_release (pubkey);
}
ath_mutex_unlock (&pubkeys_registered_lock);
@@ -1918,6 +1929,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
unsigned int nbits = 0;
unsigned long use_e = 0;
unsigned int qbits;
+ gcry_mpi_t xvalue = NULL;
char *name_terminated;
REGISTER_DEFAULT_PUBKEYS;
@@ -2018,6 +2030,18 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
else
qbits = 0;
+ /* Parse the optional xvalue element. */
+ l2 = gcry_sexp_find_token (list, "xvalue", 0);
+ if (l2)
+ {
+ xvalue = gcry_sexp_nth_mpi (l2, 1, 0);
+ if (!xvalue)
+ {
+ rc = GPG_ERR_BAD_MPI;
+ goto leave;
+ }
+ }
+
/* Now parse the required nbits element. */
l2 = gcry_sexp_find_token (list, "nbits", 0);
gcry_sexp_release (list);
@@ -2048,7 +2072,8 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
nbits = (unsigned int) strtoul (name_terminated, NULL, 0);
gcry_free (name_terminated);
- rc = pubkey_generate (module->mod_id, nbits, qbits, use_e, skey, &factors);
+ rc = pubkey_generate (module->mod_id, nbits, qbits, use_e, xvalue,
+ skey, &factors);
if (rc)
goto leave;
@@ -2140,7 +2165,9 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
leave:
release_mpi_array (skey);
/* Don't free SKEY itself, it is a static array. */
-
+
+ gcry_mpi_release (xvalue);
+
if (factors)
{
release_mpi_array ( factors );
@@ -2151,7 +2178,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
gcry_sexp_release (l2);
if (list)
gcry_sexp_release (list);
-
+
if (module)
{
ath_mutex_lock (&pubkeys_registered_lock);
diff --git a/mpi/ChangeLog b/mpi/ChangeLog
index 9a1e9dd6..dc6556d2 100644
--- a/mpi/ChangeLog
+++ b/mpi/ChangeLog
@@ -1,3 +1,10 @@
+2007-02-23 Werner Koch <wk@g10code.com>
+
+ * mpi-pow.c (gcry_mpi_powm): Remove unused var ESIGN.
+
+ * mpiutil.c (gcry_mpi_get_flag): Let it return a value to silent
+ MIPSpro cc warning.
+
2007-02-21 Werner Koch <wk@g10code.com>
* mpicoder.c (_gcry_mpi_set_buffer): Made BUFFER a void*.
diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c
index 61a115f4..4f3d73e4 100644
--- a/mpi/mpi-pow.c
+++ b/mpi/mpi-pow.c
@@ -41,7 +41,7 @@ gcry_mpi_powm( gcry_mpi_t res, gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod)
{
mpi_ptr_t rp, ep, mp, bp;
mpi_size_t esize, msize, bsize, rsize;
- int esign, msign, bsign, rsign;
+ int msign, bsign, rsign;
int esec, msec, bsec, rsec;
mpi_size_t size;
int mod_shift_cnt;
@@ -58,7 +58,6 @@ gcry_mpi_powm( gcry_mpi_t res, gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod)
esize = expo->nlimbs;
msize = mod->nlimbs;
size = 2 * msize;
- esign = expo->sign;
msign = mod->sign;
esec = mpi_is_secure(expo);
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index d74a1f89..20e1ff02 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -463,10 +463,13 @@ gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
int
gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
{
- switch( flag ) {
- case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
- case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
- default: log_bug("invalid flag value\n");
+ switch (flag)
+ {
+ case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
+ case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
+ default: log_bug("invalid flag value\n");
}
+ /*NOTREACHED*/
+ return 0;
}
diff --git a/src/cipher.h b/src/cipher.h
index 7aeaef6a..17002ab3 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -45,6 +45,11 @@ gcry_err_code_t _gcry_dsa_generate2 (int algo, unsigned int nbits,
/*-- elgamal.c --*/
void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb, void *cb_data);
+gcry_err_code_t _gcry_elg_generate_using_x (int algo, unsigned int nbits,
+ gcry_mpi_t x,
+ gcry_mpi_t *skey,
+ gcry_mpi_t **retfactors);
+
/*-- primegen.c --*/
void _gcry_register_primegen_progress (gcry_handler_progress_t cb, void *cb_data);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 07d5af04..f7811626 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,18 @@
+2007-02-23 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (TEST): Run benchmark as last.
+
+ * ac-data.c (check_sexp_conversion): Print label only in verbose
+ mode.
+
+ * pubkey.c (main): Run test just 2 times instead of 10.
+ (get_elg_key_new): New.
+ (check_run): Also run tests with Elgamal keys.
+ (check_keys): New arg NBITS_DATA.
+ (get_elg_key_new): Use only 400 for the 512 bit Elgamal test.
+
+ * random.c: New.
+
2007-02-22 Werner Koch <wk@g10code.com>
* basic.c (check_pubkey_sign): Also try signing using an OID.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6539d885..b13e16b1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -19,14 +19,18 @@
## Process this file with automake to produce Makefile.in
TESTS = t-mpi-bit prime register ac ac-schemes ac-data basic \
- tsexp keygen pubkey benchmark hmac keygrip
+ tsexp keygen pubkey hmac keygrip
# pkbench uses mmap for no good reason. Needs to be fixed. Code for
-# this can be found in libksba/tests.
+# this can be found in libksba/tests.
+# random tests forking thus no a test for W32 does not make any sense.
if !HAVE_W32_SYSTEM
-TESTS += pkbench
+TESTS += pkbench random
endif
+# The last test to run.
+TESTS += benchmark
+
# Need to include ../src in addition to top_srcdir because gcrypt.h is
# a built header.
diff --git a/tests/ac-data.c b/tests/ac-data.c
index fc4be8a5..792c3dc5 100644
--- a/tests/ac-data.c
+++ b/tests/ac-data.c
@@ -78,8 +78,11 @@ check_sexp_conversion (gcry_ac_data_t data, const char **identifiers)
assert_err (err);
err = gcry_ac_data_get_index (data2, 0, i, &label2, &mpi2);
assert_err (err);
- fprintf (stderr, "Label1=`%s'\n", label1);
- fprintf (stderr, "Label1=`%s'\n", label2);
+ if (verbose)
+ {
+ fprintf (stderr, "Label1=`%s'\n", label1);
+ fprintf (stderr, "Label2=`%s'\n", label2);
+ }
assert (! strcmp (label1, label2));
assert (! gcry_mpi_cmp (mpi1, mpi2));
}
diff --git a/tests/pubkey.c b/tests/pubkey.c
index f71590d9..a2a1f32a 100644
--- a/tests/pubkey.c
+++ b/tests/pubkey.c
@@ -63,7 +63,6 @@ static const char sample_public_key_1[] =
" )\n"
")\n";
-#define RANDOM_DATA_NBITS 800
static int verbose;
@@ -134,15 +133,15 @@ check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey,
}
static void
-check_keys (gcry_sexp_t pkey, gcry_sexp_t skey)
+check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data)
{
gcry_sexp_t plain;
gcry_mpi_t x;
int rc;
/* Create plain text. */
- x = gcry_mpi_new (RANDOM_DATA_NBITS);
- gcry_mpi_randomize (x, RANDOM_DATA_NBITS, GCRY_WEAK_RANDOM);
+ x = gcry_mpi_new (nbits_data);
+ gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM);
rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x);
if (rc)
@@ -154,10 +153,11 @@ check_keys (gcry_sexp_t pkey, gcry_sexp_t skey)
gcry_mpi_release (x);
/* Create plain text. */
- x = gcry_mpi_new (RANDOM_DATA_NBITS);
- gcry_mpi_randomize (x, RANDOM_DATA_NBITS, GCRY_WEAK_RANDOM);
+ x = gcry_mpi_new (nbits_data);
+ gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM);
- rc = gcry_sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %m))", x);
+ rc = gcry_sexp_build (&plain, NULL,
+ "(data (flags raw no-blinding) (value %m))", x);
if (rc)
die ("converting data for encryption failed: %s\n",
gcry_strerror (rc));
@@ -212,20 +212,70 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
*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;
+ int rc;
+
+ rc = gcry_sexp_new
+ (&key_spec,
+ (fixed_x
+ ? "(genkey (elg (nbits 4:1024)(xvalue my.not-so-secret.key)))"
+ : "(genkey (elg (nbits 3:512)))"),
+ 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));
+
+ 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)
{
gcry_sexp_t pkey, skey;
- /* Check sample keys. */
+ if (verbose)
+ fprintf (stderr, "Checking sample key.\n");
get_keys_sample (&pkey, &skey);
- check_keys (pkey, skey);
+ check_keys (pkey, skey, 800);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
- /* Check newly generated keys. */
+ if (verbose)
+ fprintf (stderr, "Checking generated RSA key.\n");
get_keys_new (&pkey, &skey);
- check_keys (pkey, skey);
+ check_keys (pkey, skey, 800);
+ 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 );
+ gcry_sexp_release (pkey);
+ gcry_sexp_release (skey);
+
+ if (verbose)
+ fprintf (stderr, "Checking passphrase generated Elgamal key.\n");
+ get_elg_key_new (&pkey, &skey, 1);
+ check_keys (pkey, skey, 800);
gcry_sexp_release (pkey);
gcry_sexp_release (skey);
}
@@ -234,7 +284,7 @@ int
main (int argc, char **argv)
{
int debug = 0;
- int i = 10;
+ int i;
if (argc > 1 && !strcmp (argv[1], "--verbose"))
verbose = 1;
@@ -250,7 +300,7 @@ main (int argc, char **argv)
/* No valuable keys are create, so we can speed up our RNG. */
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
- for (; i > 0; i--)
+ for (i=0; i < 2; i++)
check_run ();
return 0;
diff --git a/tests/random.c b/tests/random.c
new file mode 100644
index 00000000..502a3758
--- /dev/null
+++ b/tests/random.c
@@ -0,0 +1,255 @@
+/* random.c - part of the Libgcrypt test suite.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include "../src/gcrypt.h"
+
+static int verbose;
+
+static void
+die (const char *format, ...)
+{
+ va_list arg_ptr;
+
+ va_start (arg_ptr, format);
+ vfprintf (stderr, format, arg_ptr);
+ va_end (arg_ptr);
+ exit (1);
+}
+
+
+static void
+print_hex (const char *text, const void *buf, size_t n)
+{
+ const unsigned char *p = buf;
+
+ fputs (text, stdout);
+ for (; n; n--, p++)
+ printf ("%02X", *p);
+ putchar ('\n');
+}
+
+
+static int
+writen (int fd, const void *buf, size_t nbytes)
+{
+ size_t nleft = nbytes;
+ int nwritten;
+
+ while (nleft > 0)
+ {
+ nwritten = write (fd, buf, nleft);
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ nwritten = 0;
+ else
+ return -1;
+ }
+ nleft -= nwritten;
+ buf = (const char*)buf + nwritten;
+ }
+
+ return 0;
+}
+
+static int
+readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
+{
+ size_t nleft = buflen;
+ int nread;
+ char *p;
+
+ p = buf;
+ while ( nleft > 0 )
+ {
+ nread = read ( fd, buf, nleft );
+ if (nread < 0)
+ {
+ if (nread == EINTR)
+ nread = 0;
+ else
+ return -1;
+ }
+ else if (!nread)
+ break; /* EOF */
+ nleft -= nread;
+ buf = (char*)buf + nread;
+ }
+ if (ret_nread)
+ *ret_nread = buflen - nleft;
+ return 0;
+}
+
+
+
+/* Check that forking won't return the same random. */
+static void
+check_forking (void)
+{
+ pid_t pid;
+ int rp[2];
+ int i, status;
+ size_t nread;
+ char tmp1[16], tmp1c[16], tmp1p[16];
+
+ /* We better make sure that the RNG has been initialzied. */
+ gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
+ if (verbose)
+ print_hex ("initial random: ", tmp1, sizeof tmp1);
+
+ if (pipe (rp) == -1)
+ die ("pipe failed: %s\n", strerror (errno));
+
+ pid = fork ();
+ if (pid == (pid_t)(-1))
+ die ("fork failed: %s\n", strerror (errno));
+ if (!pid)
+ {
+ gcry_randomize (tmp1c, sizeof tmp1c, GCRY_STRONG_RANDOM);
+ if (writen (rp[1], tmp1c, sizeof tmp1c))
+ die ("write failed: %s\n", strerror (errno));
+ if (verbose)
+ {
+ print_hex (" child random: ", tmp1c, sizeof tmp1c);
+ fflush (stdout);
+ }
+ _exit (0);
+ }
+ gcry_randomize (tmp1p, sizeof tmp1p, GCRY_STRONG_RANDOM);
+ if (verbose)
+ print_hex (" parent random: ", tmp1p, sizeof tmp1p);
+
+ close (rp[1]);
+ if (readn (rp[0], tmp1c, sizeof tmp1c, &nread))
+ die ("read failed: %s\n", strerror (errno));
+ if (nread != sizeof tmp1c)
+ die ("read too short\n");
+
+ while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
+ ;
+ if (i != (pid_t)(-1)
+ && WIFEXITED (status) && !WEXITSTATUS (status))
+ ;
+ else
+ die ("child failed\n");
+
+ if (!memcmp (tmp1p, tmp1c, sizeof tmp1c))
+ die ("parent and child got the same random number\n");
+}
+
+
+
+/* Check that forking won't return the same nonce. */
+static void
+check_nonce_forking (void)
+{
+ pid_t pid;
+ int rp[2];
+ int i, status;
+ size_t nread;
+ char nonce1[10], nonce1c[10], nonce1p[10];
+
+ /* We won't get the same nonce back if we never initialized the
+ nonce subsystem, thus we get one nonce here and forget about
+ it. */
+ gcry_create_nonce (nonce1, sizeof nonce1);
+ if (verbose)
+ print_hex ("initial nonce: ", nonce1, sizeof nonce1);
+
+ if (pipe (rp) == -1)
+ die ("pipe failed: %s\n", strerror (errno));
+
+ pid = fork ();
+ if (pid == (pid_t)(-1))
+ die ("fork failed: %s\n", strerror (errno));
+ if (!pid)
+ {
+ gcry_create_nonce (nonce1c, sizeof nonce1c);
+ if (writen (rp[1], nonce1c, sizeof nonce1c))
+ die ("write failed: %s\n", strerror (errno));
+ if (verbose)
+ {
+ print_hex (" child nonce: ", nonce1c, sizeof nonce1c);
+ fflush (stdout);
+ }
+ _exit (0);
+ }
+ gcry_create_nonce (nonce1p, sizeof nonce1p);
+ if (verbose)
+ print_hex (" parent nonce: ", nonce1p, sizeof nonce1p);
+
+ close (rp[1]);
+ if (readn (rp[0], nonce1c, sizeof nonce1c, &nread))
+ die ("read failed: %s\n", strerror (errno));
+ if (nread != sizeof nonce1c)
+ die ("read too short\n");
+
+ while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
+ ;
+ if (i != (pid_t)(-1)
+ && WIFEXITED (status) && !WEXITSTATUS (status))
+ ;
+ else
+ die ("child failed\n");
+
+ if (!memcmp (nonce1p, nonce1c, sizeof nonce1c))
+ die ("parent and child got the same nonce\n");
+}
+
+
+
+
+
+
+int
+main (int argc, char **argv)
+{
+ int debug = 0;
+
+ if ((argc > 1) && (! strcmp (argv[1], "--verbose")))
+ verbose = 1;
+ else if ((argc > 1) && (! strcmp (argv[1], "--debug")))
+ verbose = debug = 1;
+
+ signal (SIGPIPE, SIG_IGN);
+
+ gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+ if (!gcry_check_version (GCRYPT_VERSION))
+ die ("version mismatch\n");
+
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+ if (debug)
+ gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+
+ check_forking ();
+ check_nonce_forking ();
+
+ return 0;
+}