diff options
Diffstat (limited to 'cipher')
-rw-r--r-- | cipher/ChangeLog | 134 | ||||
-rw-r--r-- | cipher/Makefile.am | 26 | ||||
-rw-r--r-- | cipher/blowfish.c | 12 | ||||
-rw-r--r-- | cipher/cast5.c | 13 | ||||
-rw-r--r-- | cipher/des.c | 218 | ||||
-rw-r--r-- | cipher/dsa.c | 18 | ||||
-rw-r--r-- | cipher/elgamal.c | 138 | ||||
-rw-r--r-- | cipher/md.c | 2 | ||||
-rw-r--r-- | cipher/md5.c | 8 | ||||
-rw-r--r-- | cipher/primegen.c | 27 | ||||
-rw-r--r-- | cipher/random.c | 199 | ||||
-rw-r--r-- | cipher/random.h | 2 | ||||
-rw-r--r-- | cipher/rmd160.c | 8 | ||||
-rw-r--r-- | cipher/rndegd.c | 9 | ||||
-rw-r--r-- | cipher/rndlinux.c | 6 | ||||
-rw-r--r-- | cipher/rndunix.c | 15 | ||||
-rw-r--r-- | cipher/rndw32.c | 958 | ||||
-rw-r--r-- | cipher/sha1.c | 8 | ||||
-rw-r--r-- | cipher/tiger.c | 8 | ||||
-rw-r--r-- | cipher/twofish.c | 28 |
20 files changed, 1630 insertions, 207 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog index a8c3d3f13..b26d3f3f1 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,5 +1,137 @@ -Wed Sep 15 16:22:17 CEST 1999 Werner Koch <[email protected]> +Sun May 28 13:55:17 CEST 2000 Werner Koch <[email protected]> + + * random.c (read_seed_file): Binary open for DOSish system + (update_random_seed_file): Ditto. + + * rndw32.c: Add some debuging code enabled by an environment variable. + +Tue May 23 09:19:00 CEST 2000 Werner Koch <[email protected]> + + * rndw32.c: Started with alternative code to replace entropy.dll + +Thu May 18 11:38:54 CEST 2000 Werner Koch <[email protected]> + + * primegen.c (register_primegen_progress): New. + * dsa.c (register_pk_dsa_progress): New. + * elgamal.c (register_pk_elg_progress): New. + +Fri Apr 14 19:37:08 CEST 2000 Werner Koch <[email protected]> + + * twofish.c (twofish_get_info): Fixed warning about cast. + +Tue Mar 28 14:26:58 CEST 2000 Werner Koch <[email protected]> + + * random.c [MINGW32]: Include process.h for getpid. + +Thu Mar 2 15:37:46 CET 2000 Werner Koch <[email protected]> + + * random.c (fast_random_poll): Add clock_gettime() as fallback for + system which support this POSIX.4 fucntion. By Sam Roberts. + + * rndunix.c: Add some more headers for QNX. By Sam Roberts. + + * random.c (read_seed_file): Removed the S_ISLNK test becuase it + is already covered by !S_ISREG and is not defined in Unixware. + Reported by Dave Dykstra. + + * sha1.c (sha1_get_info): Removed those stupid double lines. Dave + is really a good lint. + +Wed Feb 23 10:07:57 CET 2000 Werner Koch <[email protected]> + + * twofish.c (twofish_get_info): Add some const to the casts. By Martin + Kahlert. + +Mon Feb 14 14:30:20 CET 2000 Werner Koch <[email protected]> + + (update_random_seed_file): Silently ignore update request when pool + is not filled. + +Fri Feb 11 17:44:40 CET 2000 Werner Koch <[email protected]> + + * random.c (read_seed_file): New. + (set_random_seed_file): New. + (read_pool): Try to read the seeding file. + (update_random_seed_file): New. + + (read_pool): Do an initial extra seeding when level 2 quality random + is requested the first time. This requestes at least POOLSIZE/2 bytes + of entropy. Compined with the seeding file this should make normal + random bytes cheaper and increase the quality of the random bytes + used for key generation. + + * rndegd.c (gather_random): Shortcut level 0. + * rndunix.c (gather_random): Ditto. + * rndw32.c (gather_random): Ditto. +Fri Jan 14 18:32:01 CET 2000 Werner Koch <[email protected]> + + * rmd160.c (rmd160_get_info): Moved casting to the left side due to a + problem with UTS4.3. Suggested by Dave Dykstra. + * sha1.c (sha1_get_info): Ditto. + * tiger.c (tiger_get_info): Ditto. + * md5.c (md5_get_info): Ditto + * des.c (des_get_info): Ditto. + * blowfish.c (blowfish_get_info): Ditto. + * cast5.c (cast5_get_info): Ditto. + * twofish.c (twofish_get_info): Ditto. + +Thu Jan 13 19:31:58 CET 2000 Werner Koch <[email protected]> + + * elgamal.c (wiener_map): New. + (gen_k): Use a much smaller k. + (generate): Calculate the qbits using the wiener map and + choose an x at a size comparable to the one choosen in gen_k + + * random.c (read_pool): Print a more friendly error message in + cases when too much random is requested in one call. + + * Makefile.am (tiger): Replaced -O1 by -O. Suggested by Alec Habig. + +Sat Dec 4 12:30:28 CET 1999 Werner Koch <[email protected]> + + * primegen.c (generate_elg_prime): All primes are now generated with + the lowest random quality level. Becuase they are public anyway we + don't need stronger random and by this we do not drain the systems + entropy so much. + +Thu Oct 28 16:08:20 CEST 1999 Werner Koch <[email protected]> + + * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; + this is not the case for some ESIX and Unixware, although they have + getrusage(). + + * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). + +Mon Oct 11 09:24:12 CEST 1999 Werner Koch <[email protected]> + + * rndw32.c (gather_random): Handle PCP_SEEDER_TOO_SMALL. + +Sat Oct 9 20:34:41 CEST 1999 Werner Koch <[email protected]> + + * Makefile.am: Tweaked module build and removed libtool + +Fri Oct 8 20:32:01 CEST 1999 Werner Koch <[email protected]> + + * rndw32.c (load_and_init_winseed): Use the Registry to locate the DLL + +Mon Oct 4 21:23:04 CEST 1999 Werner Koch <[email protected]> + + * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for + fixing this bug. + +Sat Sep 18 12:51:51 CEST 1999 Werner Koch <[email protected]> + + + * Makefile.am: Never compile mingw32 as module + +Wed Sep 15 14:39:59 CEST 1999 Michael Roth <[email protected]> + + * des.c: Various speed improvements: One bit pre rotation + trick after initial permutation (Richard Outerbridge). + Finished test of SSLeay Tripple-DES patterns. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <[email protected]> * rndw32.c: New. diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 3d9a5cb93..f3b087eb8 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -3,17 +3,10 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -noinst_LTLIBRARIES = libcipher.la - -# The configure script greps the module names from the following lines. -# You must also add all these names to EXTRA_PROGRAMS some lines below -# and EXTRA_foo_SOURCES entries. -# Hmmm is there a more easy way to do this? (EXTRA_PROGRAMS -# might also list programs which are not modules) -# MODULES: rndunix rndlinux rndegd rndw32 -# MODULES: sha1 rmd160 md5 tiger -EXTRA_PROGRAMS = rndunix rndlinux rndegd rndw32 \ - sha1 rmd160 md5 tiger +noinst_LIBRARIES = libcipher.a + +# The configure script greps the module names from the EXTRA_PROGRAMS line +EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md5 tiger EXTRA_rndlinux_SOURCES = rndlinux.c EXTRA_rndunix_SOURCES = rndunix.c @@ -34,8 +27,8 @@ endif DYNLINK_MOD_CFLAGS = -DIS_MODULE @DYNLINK_MOD_CFLAGS@ -libcipher_la_LDFLAGS = -libcipher_la_SOURCES = cipher.c \ +#libcipher_a_LDFLAGS = +libcipher_a_SOURCES = cipher.c \ pubkey.c \ md.c \ dynload.c \ @@ -65,8 +58,8 @@ libcipher_la_SOURCES = cipher.c \ BUILT_SOURCES = construct.c -libcipher_la_DEPENDENCIES = @STATIC_CIPHER_OBJS@ -libcipher_la_LIBADD = @STATIC_CIPHER_OBJS@ +libcipher_a_DEPENDENCIES = @STATIC_CIPHER_OBJS@ +libcipher_a_LIBADD = @STATIC_CIPHER_OBJS@ # If I remember it correct, automake 1.4 has a feature to set @@ -74,7 +67,7 @@ libcipher_la_LIBADD = @STATIC_CIPHER_OBJS@ tiger: $(srcdir)/tiger.c `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \ - sed -e 's/-O[2-9s]*/-O1/g' ` + sed -e 's/-O[2-9s]*/-O/g' ` tiger.o: $(srcdir)/tiger.c `echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' ` @@ -99,4 +92,3 @@ rndlinux: $(srcdir)/rndlinux.c rndegd: $(srcdir)/rndegd.c $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndegd $(srcdir)/rndegd.c - diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 5a829d413..0cb5a861f 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -43,9 +43,6 @@ #define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ -#define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f) -#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f) - #define BLOWFISH_BLOCKSIZE 8 #define BLOWFISH_ROUNDS 16 @@ -584,9 +581,12 @@ blowfish_get_info( int algo, size_t *keylen, *keylen = 128; *blocksize = BLOWFISH_BLOCKSIZE; *contextsize = sizeof(BLOWFISH_context); - *r_setkey = FNCCAST_SETKEY(bf_setkey); - *r_encrypt= FNCCAST_CRYPT(encrypt_block); - *r_decrypt= FNCCAST_CRYPT(decrypt_block); + *(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey + = bf_setkey; + *(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt + = encrypt_block; + *(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt + = decrypt_block; if( algo == CIPHER_ALGO_BLOWFISH ) return "BLOWFISH"; diff --git a/cipher/cast5.c b/cipher/cast5.c index 0e602bd2e..329f00ff7 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -46,9 +46,6 @@ #define CIPHER_ALGO_CAST5 3 -#define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f) -#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f) - #define CAST5_BLOCKSIZE 8 typedef struct { @@ -610,9 +607,13 @@ cast5_get_info( int algo, size_t *keylen, *keylen = 128; *blocksize = CAST5_BLOCKSIZE; *contextsize = sizeof(CAST5_context); - *r_setkey = FNCCAST_SETKEY(cast_setkey); - *r_encrypt= FNCCAST_CRYPT(encrypt_block); - *r_decrypt= FNCCAST_CRYPT(decrypt_block); + *(int (**)(CAST5_context*, byte*, unsigned))r_setkey + = cast_setkey; + *(void (**)(CAST5_context*, byte*, byte*))r_encrypt + = encrypt_block; + *(void (**)(CAST5_context*, byte*, byte*))r_decrypt + = decrypt_block; + if( algo == CIPHER_ALGO_CAST5 ) return "CAST5"; diff --git a/cipher/des.c b/cipher/des.c index 6e6674923..847a3473e 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -1,5 +1,5 @@ /* des.c - DES and Triple-DES encryption/decryption Algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. * * Please see below for more legal information! * @@ -147,9 +147,6 @@ working_memcmp( const char *a, const char *b, size_t n ) #endif -/* Macros used by the info function. */ -#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f)) -#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f)) /* @@ -190,105 +187,105 @@ static const char *selftest (void); /* * The s-box values are permuted according to the 'primitive function P' + * and are rotated one bit to the left. */ static u32 sbox1[64] = { - 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 + 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; static u32 sbox2[64] = { - 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 + 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; static u32 sbox3[64] = { - 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 + 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; static u32 sbox4[64] = { - 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 + 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; static u32 sbox5[64] = { - 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 + 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; static u32 sbox6[64] = { - 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 + 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; static u32 sbox7[64] = { - 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 + 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; static u32 sbox8[64] = { - 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 + 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; - /* * These two tables are part of the 'permuted choice 1' function. * In this implementation several speed improvements are done. @@ -312,10 +309,10 @@ u32 rightkey_swap[16] = /* - * Numbers of left shifts per round for encryption subkey schedule - * To calculate the decryption key scheduling we just reverse the - * ordering of the subkeys so we can omit the table for decryption - * subkey schedule. + * Numbers of left shifts per round for encryption subkeys. + * To calculate the decryption subkeys we just reverse the + * ordering of the calculated encryption subkeys. So their + * is no need for a decryption rotate tab. */ static byte encrypt_rotate_tab[16] = { @@ -373,7 +370,7 @@ static byte weak_keys[64][8] = /* - * Macro to swap bits across two words + * Macro to swap bits across two words. */ #define DO_PERMUTATION(a, temp, b, offset, mask) \ temp = ((a>>offset) ^ b) & mask; \ @@ -382,21 +379,30 @@ static byte weak_keys[64][8] = /* - * This performs the 'initial permutation' for the data to be encrypted or decrypted + * This performs the 'initial permutation' of the data to be encrypted + * or decrypted. Additionally the resulting two words are rotated one bit + * to the left. */ #define INITIAL_PERMUTATION(left, temp, right) \ DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) - + right = (right << 1) | (right >> 31); \ + temp = (left ^ right) & 0xaaaaaaaa; \ + right ^= temp; \ + left ^= temp; \ + left = (left << 1) | (left >> 31); /* - * The 'inverse initial permutation' + * The 'inverse initial permutation'. */ #define FINAL_PERMUTATION(left, temp, right) \ - DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ + left = (left << 31) | (left >> 1); \ + temp = (left ^ right) & 0xaaaaaaaa; \ + left ^= temp; \ + right ^= temp; \ + right = (right << 31) | (right >> 1); \ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ @@ -406,22 +412,23 @@ static byte weak_keys[64][8] = /* * A full DES round including 'expansion function', 'sbox substitution' * and 'primitive function P' but without swapping the left and right word. + * Please note: The data in 'from' and 'to' is already rotated one bit to + * the left, done in the initial permutation. */ #define DES_ROUND(from, to, work, subkey) \ - work = ((from<<1) | (from>>31)) ^ *subkey++; \ + work = from ^ *subkey++; \ to ^= sbox8[ work & 0x3f ]; \ to ^= sbox6[ (work>>8) & 0x3f ]; \ to ^= sbox4[ (work>>16) & 0x3f ]; \ to ^= sbox2[ (work>>24) & 0x3f ]; \ - work = ((from>>3) | (from<<29)) ^ *subkey++; \ + work = ((from << 28) | (from >> 4)) ^ *subkey++; \ to ^= sbox7[ work & 0x3f ]; \ to ^= sbox5[ (work>>8) & 0x3f ]; \ to ^= sbox3[ (work>>16) & 0x3f ]; \ to ^= sbox1[ (work>>24) & 0x3f ]; - /* - * Macros to convert 8 bytes from/to 32bit words + * Macros to convert 8 bytes from/to 32bit words. */ #define READ_64BIT_DATA(data, left, right) \ left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ @@ -433,7 +440,6 @@ static byte weak_keys[64][8] = data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ data[6] = (right >> 8) &0xff; data[7] = right &0xff; - /* * Handy macros for encryption and decryption of data */ @@ -797,9 +803,7 @@ selftest (void) /* - * Triple-DES test (Do somebody known on official test?) - * - * Note: This test doesn't use tripledes_set3keys() ! + * Self made Triple-DES test (Does somebody known an official test?) */ { int i; @@ -823,10 +827,9 @@ selftest (void) tripledes_ecb_encrypt (des3, input, input); } if (memcmp (input, result, 8)) - return "TRIPLE-DES test failed."; + return "Triple-DES test failed."; } - #if 0 /* * More Triple-DES test. These are testvectors as used by SSLeay, * thanks to Jeroen C. van Gelderen. @@ -894,13 +897,32 @@ selftest (void) { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } } }; - /* fixme: do the test */ + + byte result[8]; + int i; + static char error[80]; + tripledes_ctx des3; + + for (i=0; i<sizeof(testdata)/sizeof(*testdata); ++i) { + tripledes_set3keys (des3, testdata[i].key, testdata[i].key + 8, testdata[i].key + 16); + + tripledes_ecb_encrypt (des3, testdata[i].plain, result); + if (memcmp (testdata[i].cipher, result, 8)) { + sprintf (error, "Triple-DES SSLeay test pattern no. %d failend on encryption.", i+1); + return error; + } + + tripledes_ecb_decrypt (des3, testdata[i].cipher, result); + if (memcmp (testdata[i].plain, result, 8)) { + sprintf (error, "Triple-DES SSLeay test pattern no. %d failend on decryption.", i+1); + return error; + } + } } - #endif /* - * Check the weak key detection. We simply assume the table with - * weak keys is ok and check every key in the table if it is + * Check the weak key detection. We simply assume that the table + * with weak keys is ok and check every key in the table if it is * detected... (This test is a little bit stupid) */ { @@ -971,14 +993,16 @@ des_get_info( int algo, size_t *keylen, } } - if( algo == CIPHER_ALGO_3DES ) { *keylen = 192; *blocksize = 8; *contextsize = sizeof(struct _tripledes_ctx); - *r_setkey = FNCCAST_SETKEY(do_tripledes_setkey); - *r_encrypt= FNCCAST_CRYPT(do_tripledes_encrypt); - *r_decrypt= FNCCAST_CRYPT(do_tripledes_decrypt); + *(int (**)(struct _tripledes_ctx*, byte*, unsigned))r_setkey + = do_tripledes_setkey; + *(void (**)(struct _tripledes_ctx*, byte*, byte*))r_encrypt + = do_tripledes_encrypt; + *(void (**)(struct _tripledes_ctx*, byte*, byte*))r_decrypt + = do_tripledes_decrypt; return "3DES"; } return NULL; diff --git a/cipher/dsa.c b/cipher/dsa.c index 5828b9508..d7c4f6892 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -52,13 +52,29 @@ static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ); static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey); static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey); + +static void (*progress_cb) ( void *, int ); +static void *progress_cb_data; + +void +register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data ) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + + static void progress( int c ) { - fputc( c, stderr ); + if ( progress_cb ) + progress_cb ( progress_cb_data, c ); + else + fputc( c, stderr ); } + /**************** * Generate a random secret exponent k less than q */ diff --git a/cipher/elgamal.c b/cipher/elgamal.c index bbf9c2782..74e159684 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -1,5 +1,5 @@ /* elgamal.c - ElGamal Public Key encryption - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000 Free Software Foundation, Inc. * * For a description of the algorithm, see: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. @@ -56,13 +56,67 @@ static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey); static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey); +static void (*progress_cb) ( void *, int ); +static void *progress_cb_data; + +void +register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data ) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + + static void progress( int c ) { - fputc( c, stderr ); + if ( progress_cb ) + progress_cb ( progress_cb_data, c ); + else + fputc( c, stderr ); } +/**************** + * Michael Wiener's table about subgroup sizes to match field sizes + * (floating around somewhere - Fixme: need a reference) + */ +static unsigned int +wiener_map( unsigned int n ) +{ + static struct { unsigned int p_n, q_n; } t[] = + { /* p q attack cost */ + { 512, 119 }, /* 9 x 10^17 */ + { 768, 145 }, /* 6 x 10^21 */ + { 1024, 165 }, /* 7 x 10^24 */ + { 1280, 183 }, /* 3 x 10^27 */ + { 1536, 198 }, /* 7 x 10^29 */ + { 1792, 212 }, /* 9 x 10^31 */ + { 2048, 225 }, /* 8 x 10^33 */ + { 2304, 237 }, /* 5 x 10^35 */ + { 2560, 249 }, /* 3 x 10^37 */ + { 2816, 259 }, /* 1 x 10^39 */ + { 3072, 269 }, /* 3 x 10^40 */ + { 3328, 279 }, /* 8 x 10^41 */ + { 3584, 288 }, /* 2 x 10^43 */ + { 3840, 296 }, /* 4 x 10^44 */ + { 4096, 305 }, /* 7 x 10^45 */ + { 4352, 313 }, /* 1 x 10^47 */ + { 4608, 320 }, /* 2 x 10^48 */ + { 4864, 328 }, /* 2 x 10^49 */ + { 5120, 335 }, /* 3 x 10^50 */ + { 0, 0 } + }; + int i; + + for(i=0; t[i].p_n; i++ ) { + if( n <= t[i].p_n ) + return t[i].q_n; + } + /* not in table - use some arbitrary high number ;-) */ + return n / 8 + 200; +} + static void test_keys( ELG_secret_key *sk, unsigned nbits ) { @@ -108,38 +162,45 @@ gen_k( MPI p ) MPI k = mpi_alloc_secure( 0 ); MPI temp = mpi_alloc( mpi_get_nlimbs(p) ); MPI p_1 = mpi_copy(p); - unsigned int nbits = mpi_get_nbits(p); - unsigned int nbytes = (nbits+7)/8; + unsigned int orig_nbits = mpi_get_nbits(p); + unsigned int nbits; + unsigned int nbytes; char *rndbuf = NULL; + /* IMO using a k much lesser than p is sufficient and it greatly + * improves the encryption performance. We use Wiener's table + * and add a large safety margin. + */ + nbits = wiener_map( orig_nbits ) * 3 / 2; + if( nbits >= orig_nbits ) + BUG(); + + nbytes = (nbits+7)/8; if( DBG_CIPHER ) - log_debug("choosing a random k "); + log_debug("choosing a random k of %u bits", nbits); mpi_sub_ui( p_1, p, 1); for(;;) { - if( DBG_CIPHER ) - progress('.'); if( !rndbuf || nbits < 32 ) { m_free(rndbuf); rndbuf = get_random_bits( nbits, 1, 1 ); } else { /* change only some of the higher bits */ - /* we could imporove this by directly requesting more memory + /* we could impprove this by directly requesting more memory * at the first call to get_random_bits() and use this the here - * maybe it is easier to do this directly in random.c */ + * maybe it is easier to do this directly in random.c + * Anyway, it is highly inlikely that we will ever reach this code + */ char *pp = get_random_bits( 32, 1, 1 ); memcpy( rndbuf,pp, 4 ); m_free(pp); + log_debug("gen_k: tsss, never expected to reach this\n"); } mpi_set_buffer( k, rndbuf, nbytes, 0 ); for(;;) { - /* make sure that the number is of the exact lenght */ - if( mpi_test_bit( k, nbits-1 ) ) - mpi_set_highbit( k, nbits-1 ); - else { - mpi_set_highbit( k, nbits-1 ); - mpi_clear_bit( k, nbits-1 ); - } + /* Hmm, actually we don't need this step here + * because we use k much smaller than p - we do it anyway + * just in case the keep on adding a one to k ;) */ if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */ if( DBG_CIPHER ) progress('+'); @@ -153,6 +214,8 @@ gen_k( MPI p ) if( mpi_gcd( temp, k, p_1 ) ) goto found; /* okay, k is relatively prime to (p-1) */ mpi_add_ui( k, k, 1 ); + if( DBG_CIPHER ) + progress('.'); } } found: @@ -171,7 +234,7 @@ gen_k( MPI p ) * and an array with n-1 factors of (p-1) */ static void -generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) +generate( ELG_secret_key *sk, unsigned int nbits, MPI **ret_factors ) { MPI p; /* the prime */ MPI p_min1; @@ -179,19 +242,15 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) MPI x; /* the secret exponent */ MPI y; MPI temp; - unsigned qbits; + unsigned int qbits; + unsigned int xbits; byte *rndbuf; p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - if( nbits < 512 ) - qbits = 120; - else if( nbits <= 1024 ) - qbits = 160; - else if( nbits <= 2048 ) - qbits = 200; - else - qbits = 240; + qbits = wiener_map( nbits ); + if( qbits & 1 ) /* better have a even one */ + qbits++; g = mpi_alloc(1); p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); mpi_sub_ui(p_min1, p, 1); @@ -202,18 +261,26 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) * This must be a very good random number because this is the * secret part. The prime is public and may be shared anyway, * so a random generator level of 1 is used for the prime. + * + * I don't see a reason to have a x of about the same size + * as the p. It should be sufficient to have one about the size + * of q or the later used k plus a large safety margin. Decryption + * will be much faster with such an x. */ - x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB ); + xbits = qbits * 3 / 2; + if( xbits >= nbits ) + BUG(); + x = mpi_alloc_secure( xbits/BITS_PER_MPI_LIMB ); if( DBG_CIPHER ) - log_debug("choosing a random x "); + log_debug("choosing a random x of size %u", xbits ); rndbuf = NULL; do { if( DBG_CIPHER ) progress('.'); if( rndbuf ) { /* change only some of the higher bits */ - if( nbits < 16 ) {/* should never happen ... */ + if( xbits < 16 ) {/* should never happen ... */ m_free(rndbuf); - rndbuf = get_random_bits( nbits, 2, 1 ); + rndbuf = get_random_bits( xbits, 2, 1 ); } else { char *r = get_random_bits( 16, 2, 1 ); @@ -222,9 +289,9 @@ generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) } } else - rndbuf = get_random_bits( nbits, 2, 1 ); - mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 ); - mpi_clear_highbit( x, nbits+1 ); + rndbuf = get_random_bits( xbits, 2, 1 ); + mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); + mpi_clear_highbit( x, xbits+1 ); } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); m_free(rndbuf); @@ -311,7 +378,6 @@ decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); /* output = b/(a^x) mod p */ - mpi_powm( t1, a, skey->x, skey->p ); mpi_invm( t1, t1, skey->p ); mpi_mulm( output, b, t1, skey->p ); @@ -351,8 +417,10 @@ sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) mpi_powm( a, skey->g, k, skey->p ); mpi_mul(t, skey->x, a ); mpi_subm(t, input, t, p_1 ); - while( mpi_is_neg(t) ) + while( mpi_is_neg(t) ) { + BUG(); /* That is nonsense code - left over from a very early test?*/ mpi_add(t, t, p_1); + } mpi_invm(inv, k, p_1 ); mpi_mulm(b, t, inv, p_1 ); diff --git a/cipher/md.c b/cipher/md.c index be921e4b0..9313fc068 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -291,7 +291,7 @@ md_reset( MD_HANDLE a ) { struct md_digest_list_s *r; - a->bufcount = 0; + a->bufcount = a->finalized = 0; for( r=a->list; r; r = r->next ) { memset( r->context.c, 0, r->contextsize ); (*r->init)( &r->context.c ); diff --git a/cipher/md5.c b/cipher/md5.c index bb930d042..eb09d261c 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -344,10 +344,10 @@ md5_get_info( int algo, size_t *contextsize, *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 16; - *r_init = (void (*)(void *))md5_init; - *r_write = (void (*)(void *, byte*, size_t))md5_write; - *r_final = (void (*)(void *))md5_final; - *r_read = (byte *(*)(void *))md5_read; + *(void (**)(MD5_CONTEXT *))r_init = md5_init; + *(void (**)(MD5_CONTEXT *, byte*, size_t))r_write = md5_write; + *(void (**)(MD5_CONTEXT *))r_final = md5_final; + *(byte *(**)(MD5_CONTEXT *))r_read = md5_read; return "MD5"; } diff --git a/cipher/primegen.c b/cipher/primegen.c index 9bf108531..b6c569de7 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -38,11 +38,24 @@ static int check_prime( MPI prime, MPI val_2 ); static int is_prime( MPI n, int steps, int *count ); static void m_out_of_n( char *array, int m, int n ); +static void (*progress_cb) ( void *, int ); +static void *progress_cb_data; + +void +register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + static void progress( int c ) { - fputc( c, stderr ); + if ( progress_cb ) + progress_cb ( progress_cb_data, c ); + else + fputc( c, stderr ); } @@ -117,8 +130,8 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits, log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n ); prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); - q = gen_prime( qbits, 0, 1 ); - q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL; + q = gen_prime( qbits, 0, 0 ); + q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL; /* allocate an array to hold the factors + 2 for later usage */ factors = m_alloc_clear( (n+2) * sizeof *factors ); @@ -145,7 +158,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits, perms = m_alloc_clear( m ); for(i=0; i < n; i++ ) { perms[i] = 1; - pool[i] = gen_prime( fbits, 0, 1 ); + pool[i] = gen_prime( fbits, 0, 0 ); factors[i] = pool[i]; } } @@ -154,7 +167,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits, for(i=j=0; i < m && j < n ; i++ ) if( perms[i] ) { if( !pool[i] ) - pool[i] = gen_prime( fbits, 0, 1 ); + pool[i] = gen_prime( fbits, 0, 0 ); factors[j++] = pool[i]; } if( i == n ) { @@ -177,7 +190,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits, count1 = 0; qbits++; progress('>'); - q = gen_prime( qbits, 0, 1 ); + q = gen_prime( qbits, 0, 0 ); goto next_try; } } @@ -188,7 +201,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits, count2 = 0; qbits--; progress('<'); - q = gen_prime( qbits, 0, 1 ); + q = gen_prime( qbits, 0, 0 ); goto next_try; } } diff --git a/cipher/random.c b/cipher/random.c index 8ade26c11..be23ddd3e 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -36,15 +36,22 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <fcntl.h> #ifdef HAVE_GETHRTIME #include <sys/times.h> #endif #ifdef HAVE_GETTIMEOFDAY #include <sys/times.h> #endif +#ifdef HAVE_CLOCK_GETTIME + #include <time.h> +#endif #ifdef HAVE_GETRUSAGE #include <sys/resource.h> #endif +#ifdef __MINGW32__ + #include <process.h> +#endif #include "util.h" #include "rmd.h" #include "ttyio.h" @@ -91,6 +98,9 @@ static size_t pool_writepos; static int pool_filled; static int pool_balance; static int just_mixed; +static int did_initial_extra_seeding; +static char *seed_file_name; +static int allow_seed_file_update; static int secure_alloc; static int quick_test; @@ -264,14 +274,171 @@ mix_pool(byte *pool) } +void +set_random_seed_file( const char *name ) +{ + if( seed_file_name ) + BUG(); + seed_file_name = m_strdup( name ); +} + +/**************** + * Read in a seed form the random_seed file + * and return true if this was successful + */ +static int +read_seed_file() +{ + int fd; + struct stat sb; + unsigned char buffer[POOLSIZE]; + int n; + + if( !seed_file_name ) + return 0; + + #ifdef HAVE_DOSISH_SYSTEM + fd = open( seed_file_name, O_RDONLY | O_BINARY ); + #else + fd = open( seed_file_name, O_RDONLY ); + #endif + if( fd == -1 && errno == ENOENT) { + allow_seed_file_update = 1; + return 0; + } + + if( fd == -1 ) { + log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); + return 0; + } + if( fstat( fd, &sb ) ) { + log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); + close(fd); + return 0; + } + if( !S_ISREG(sb.st_mode) ) { + log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); + close(fd); + return 0; + } + if( !sb.st_size ) { + log_info(_("note: random_seed file is empty\n") ); + close(fd); + allow_seed_file_update = 1; + return 0; + } + if( sb.st_size != POOLSIZE ) { + log_info(_("warning: invalid size of random_seed file - not used\n") ); + close(fd); + return 0; + } + do { + n = read( fd, buffer, POOLSIZE ); + } while( n == -1 && errno == EINTR ); + if( n != POOLSIZE ) { + log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); + close(fd); + return 0; + } + + close(fd); + + add_randomness( buffer, POOLSIZE, 0 ); + /* add some minor entropy to the pool now (this will also force a mixing) */ + { pid_t x = getpid(); + add_randomness( &x, sizeof(x), 0 ); + } + { time_t x = time(NULL); + add_randomness( &x, sizeof(x), 0 ); + } + { clock_t x = clock(); + add_randomness( &x, sizeof(x), 0 ); + } + /* And read a few bytes from our entropy source. By using + * a level of 0 this will not block and might not return anything + * with some entropy drivers, however the rndlinux driver will use + * /dev/urandom and return some stuff - Do not read to much as we + * want to be friendly to the scare system entropy resource. */ + read_random_source( 0, 16, 0 ); + + allow_seed_file_update = 1; + return 1; +} + +void +update_random_seed_file() +{ + ulong *sp, *dp; + int fd, i; + + if( !seed_file_name || !is_initialized || !pool_filled ) + return; + if( !allow_seed_file_update ) { + log_info(_("note: random_seed file not updated\n")); + return; + } + + + /* copy the entropy pool to a scratch pool and mix both of them */ + for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; + i < POOLWORDS; i++, dp++, sp++ ) { + *dp = *sp + ADD_VALUE; + } + mix_pool(rndpool); rndstats.mixrnd++; + mix_pool(keypool); rndstats.mixkey++; + + #ifdef HAVE_DOSISH_SYSTEM + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, + S_IRUSR|S_IWUSR ); + #else + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); + #endif + if( fd == -1 ) { + log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); + return; + } + do { + i = write( fd, keypool, POOLSIZE ); + } while( i == -1 && errno == EINTR ); + if( i != POOLSIZE ) { + log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); + } + if( close(fd) ) + log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); +} + + static void read_pool( byte *buffer, size_t length, int level ) { int i; ulong *sp, *dp; - if( length >= POOLSIZE ) - BUG(); /* not allowed */ + if( length >= POOLSIZE ) { + log_fatal(_("too many random bits requested; the limit is %d\n"), + POOLSIZE*8-1 ); + } + + if( !pool_filled ) { + if( read_seed_file() ) + pool_filled = 1; + } + + /* For level 2 quality (key generation) we alwas make + * sure that the pool has been seeded enough initially */ + if( level == 2 && !did_initial_extra_seeding ) { + size_t needed; + + pool_balance = 0; + needed = length - pool_balance; + if( needed < POOLSIZE/2 ) + needed = POOLSIZE/2; + else if( needed > POOLSIZE ) + BUG(); + read_random_source( 3, needed, 2 ); + pool_balance += needed; + did_initial_extra_seeding=1; + } /* for level 2 make sure that there is enough random in the pool */ if( level == 2 && pool_balance < length ) { @@ -336,6 +503,12 @@ read_pool( byte *buffer, size_t length, int level ) /**************** * Add LENGTH bytes of randomness from buffer to the pool. * source may be used to specify the randomness source. + * Source is: + * 0 - used ony for initialization + * 1 - fast random poll function + * 2 - normal poll function + * 3 - used when level 2 random quality has been requested + * to do an extra pool seed. */ static void add_randomness( const void *buffer, size_t length, int source ) @@ -399,6 +572,13 @@ fast_random_poll() add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); } + #elif HAVE_CLOCK_GETTIME + { struct timespec tv; + if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) + BUG(); + add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); + add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); + } #else /* use times */ #ifndef HAVE_DOSISH_SYSTEM { struct tms buf; @@ -408,13 +588,28 @@ fast_random_poll() #endif #endif #ifdef HAVE_GETRUSAGE + #ifndef RUSAGE_SELF + #ifdef __GCC__ + #warning There is no RUSAGE_SELF on this system + #endif + #else { struct rusage buf; if( getrusage( RUSAGE_SELF, &buf ) ) BUG(); add_randomness( &buf, sizeof buf, 1 ); memset( &buf, 0, sizeof buf ); } + #endif #endif + /* time and clock are availabe on all systems - so + * we better do it just in case one of the above functions + * didn't work */ + { time_t x = time(NULL); + add_randomness( &x, sizeof(x), 1 ); + } + { clock_t x = clock(); + add_randomness( &x, sizeof(x), 1 ); + } } diff --git a/cipher/random.h b/cipher/random.h index 649325c58..cf80bd98d 100644 --- a/cipher/random.h +++ b/cipher/random.h @@ -25,6 +25,8 @@ /*-- random.c --*/ void random_dump_stats(void); void secure_random_alloc(void); +void set_random_seed_file(const char *); +void update_random_seed_file(void); int quick_random_gen( int onoff ); int random_is_faked(void); void randomize_buffer( byte *buffer, size_t length, int level ); diff --git a/cipher/rmd160.c b/cipher/rmd160.c index ecd65b35d..fba910d7e 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -562,10 +562,10 @@ rmd160_get_info( int algo, size_t *contextsize, *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 20; - *r_init = (void (*)(void *))rmd160_init; - *r_write = (void (*)(void *, byte*, size_t))rmd160_write; - *r_final = (void (*)(void *))rmd160_final; - *r_read = (byte *(*)(void *))rmd160_read; + *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; + *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; + *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; + *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; return "RIPEMD160"; } diff --git a/cipher/rndegd.c b/cipher/rndegd.c index 7f2598f60..97395b959 100644 --- a/cipher/rndegd.c +++ b/cipher/rndegd.c @@ -83,9 +83,13 @@ do_read( int fd, void *buf, size_t nbytes ) -/* Note: we always use the highest level. +/**************** + * Note: we always use the highest level. * TO boost the performance we may want to add some * additional code for level 1 + * + * Using a level of 0 should never block and better add nothing + * to the pool. So this is just a dummy for EGD. */ static int gather_random( void (*add)(const void*, size_t, int), int requester, @@ -99,7 +103,8 @@ gather_random( void (*add)(const void*, size_t, int), int requester, if( !length ) return 0; - + if( !level ) + return 0; restart: if( do_restart ) { diff --git a/cipher/rndlinux.c b/cipher/rndlinux.c index 78fee1567..6f80a8def 100644 --- a/cipher/rndlinux.c +++ b/cipher/rndlinux.c @@ -89,6 +89,10 @@ open_device( const char *name, int minor ) } +/**************** + * Note: Using a level of 0 should never block and better add nothing + * to the pool. This is easy to accomplish with /dev/urandom. + */ static int gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) @@ -106,6 +110,8 @@ gather_random( void (*add)(const void*, size_t, int), int requester, fd = fd_random; } else { + /* this will also be used for elve 0 but by using /dev/urandom + * we can be sure that oit will never block. */ if( fd_urandom == -1 ) fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 ); fd = fd_urandom; diff --git a/cipher/rndunix.c b/cipher/rndunix.c index 46f80eab2..59a924e00 100644 --- a/cipher/rndunix.c +++ b/cipher/rndunix.c @@ -75,9 +75,9 @@ #ifndef __QNX__ #include <sys/resource.h> #endif /* __QNX__ */ -#ifdef _AIX +#if defined( _AIX ) || defined( __QNX__ ) #include <sys/select.h> -#endif /* _AIX */ +#endif /* _AIX || __QNX__ */ #ifndef __QNX__ #include <sys/shm.h> #include <sys/signal.h> @@ -89,6 +89,10 @@ #endif /* __hpux 9.x, after that it's in unistd.h */ #include <sys/wait.h> /* #include <kitchensink.h> */ +#ifdef __QNX__ +#include <signal.h> +#include <process.h> +#endif /* __QNX__ */ #include <errno.h> #include "types.h" /* for byte and u32 typedefs */ @@ -716,6 +720,10 @@ read_a_msg( int fd, GATHER_MSG *msg ) } +/**************** + * Using a level of 0 should never block and better add nothing + * to the pool. So this is just a dummy for this gatherer. + */ static int gather_random( void (*add)(const void*, size_t, int), int requester, size_t length, int level ) @@ -725,6 +733,9 @@ gather_random( void (*add)(const void*, size_t, int), int requester, GATHER_MSG msg; size_t n; + if( !level ) + return 0; + if( !gatherer_pid ) { /* make sure we are not setuid */ if( getuid() != geteuid() ) diff --git a/cipher/rndw32.c b/cipher/rndw32.c new file mode 100644 index 000000000..755d399fc --- /dev/null +++ b/cipher/rndw32.c @@ -0,0 +1,958 @@ +/* rndw32.c - W32 entropy gatherer + * Copyright (C) 1999, 2000 Free Software Foundation, Inc. + * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999 + * + * This file is part of GnuPG. + * + * GnuPG 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. + * + * GnuPG 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 + * + ************************************************************************* + * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann. + * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this + * copyright notice: + * + * This module is part of the cryptlib continuously seeded pseudorandom + * number generator. For usage conditions, see lib_rand.c + * + * [Here is the notice from lib_rand.c, which is now called dev_sys.c] + * + * This module and the misc/rnd*.c modules represent the cryptlib + * continuously seeded pseudorandom number generator (CSPRNG) as described in + * my 1998 Usenix Security Symposium paper "The generation of random numbers + * for cryptographic purposes". + * + * The CSPRNG code is copyright Peter Gutmann (and various others) 1996, + * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG + * modules and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and this permission notice in its entirety. + * + * 2. Redistributions in binary form must reproduce the copyright notice in + * the documentation and/or other materials provided with the distribution. + * + * 3. A copy of any bugfixes or enhancements made must be provided to the + * author, <[email protected]> to allow them to be added to the + * baseline version of the code. + * + * ALTERNATIVELY, the code may be distributed under the terms of the GNU + * General Public License, version 2 or any later version published by the + * Free Software Foundation, in which case the provisions of the GNU GPL are + * required INSTEAD OF the above restrictions. + * + * Although not required under the terms of the GPL, it would still be nice if + * you could make any changes available to the author to allow a consistent + * code base to be maintained + ************************************************************************* + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <windows.h> + + +#include "types.h" +#include "util.h" +#include "dynload.h" + +/* We do not use the netropy DLL anymore because a standalone program is + * easier to maintain and */ +/*#define USE_ENTROPY_DLL*/ + + + +#ifdef IS_MODULE + #define _(a) (a) +#else + #include "i18n.h" +#endif + + +static int debug_me; + +#ifdef USE_ENTROPY_DLL + +#define WIN32_SLOW_SEEDER 0 +#define WIN32_FAST_SEEDER 1 + +#define PCP_SUCCESS 0 +#define PCP_NULL_POINTER 1 +#define PCP_SEEDER_FAILED 2 +#define PCP_SEEDER_NO_MEM 3 +#define PCP_SEEDER_TOO_SMALL 4 +#define PCP_DLL_LOAD_FAILED 5 +#define PCP_UNKNOWN_PLATFORM 6 +#define PCP_ERROR_VERSION 7 +#define PCP_DLL_FUNC 8 +#define PCP_UNKNOWN_SEEDER_TYPE 9 + + +/**************** + * We sometimes get a SEEDER_TOO_SMALL error, in which case we increment + * the internal buffer by SEEDER_INC_CHUNK until we reach MAX_SEEDER_SIZE + * MAX_SEEDER_SIZE is used as an arbitrary limit to protect against + * bugs in Winseed. + */ +#define MAX_SEEDER_SIZE 500000 +#define SEEDER_INC_CHUNK 50000 + + +typedef void *WIN32_SEEDER; + +static WIN32_SEEDER (WINAPI *create_instance)( byte type, unsigned int *reason); +static void (WINAPI *delete_instance)( WIN32_SEEDER that ); +static unsigned int (WINAPI *get_internal_seed_size)( WIN32_SEEDER that ); +static void (WINAPI *set_internal_seed_size)( WIN32_SEEDER that, + unsigned int new_size); +static unsigned int (WINAPI *get_expected_seed_size)( WIN32_SEEDER that); +static unsigned int (WINAPI *get_seed)( WIN32_SEEDER that, byte *buffer, + unsigned int *desired_length); + +static WIN32_SEEDER slow_seeder, fast_seeder; +static byte *entropy_buffer; +static size_t entropy_buffer_size; + +/**************** + * Load and initialize the winseed DLL + * NOTE: winseed is not part of the GnuPG distribution. It should be available + * at the GNU crypto FTP server site. + * We do not load the DLL on demand to have a better control over the + * location of the library. + */ +static void +load_and_init_winseed( void ) +{ + HANDLE hInstance; + void *addr; + unsigned int reason = 0; + unsigned int n1, n2; + const char *dllname; + + dllname = read_w32_registry_string( "HKEY_LOCAL_MACHINE", + "Software\\GNU\\GnuPG", + "EntropyDLL" ); + if( !dllname ) + dllname = "c:/gnupg/entropy.dll"; + + hInstance = LoadLibrary( dllname ); + if( !hInstance ) + goto failure; + if( !(addr = GetProcAddress( hInstance, "WS_create_instance" )) ) + goto failure; + create_instance = addr; + if( !(addr = GetProcAddress( hInstance, "WS_delete_instance" )) ) + goto failure; + delete_instance = addr; + if( !(addr = GetProcAddress( hInstance, "WS_get_internal_seed_size" )) ) + goto failure; + get_internal_seed_size = addr; + if( !(addr = GetProcAddress( hInstance, "WS_set_internal_seed_size" )) ) + goto failure; + set_internal_seed_size = addr; + if( !(addr = GetProcAddress( hInstance, "WS_get_expected_seed_size" )) ) + goto failure; + get_expected_seed_size = addr; + if( !(addr = GetProcAddress( hInstance, "WS_get_seed" )) ) + goto failure; + get_seed = addr; + + /* we have all the functions - init the system */ + slow_seeder = create_instance( WIN32_SLOW_SEEDER, &reason); + if( !slow_seeder ) { + g10_log_fatal("error creating winseed slow seeder: rc=%u\n", reason ); + goto failure; + } + fast_seeder = create_instance( WIN32_FAST_SEEDER, &reason); + if( !fast_seeder ) { + g10_log_fatal("error creating winseed fast seeder: rc=%u\n", reason ); + goto failure; + } + n1 = get_internal_seed_size( slow_seeder ); + /*g10_log_info("slow buffer size=%u\n", n1);*/ + n2 = get_internal_seed_size( fast_seeder ); + /*g10_log_info("fast buffer size=%u\n", n2);*/ + + entropy_buffer_size = n1 > n2? n1: n2; + entropy_buffer = m_alloc( entropy_buffer_size ); + /*g10_log_info("using a buffer of size=%u\n", entropy_buffer_size );*/ + + return; + + failure: + g10_log_fatal("error loading winseed DLL `%s'\n", dllname ); +} + + + + + +/* Note: we always use the highest level. + * TO boost the performance we may want to add some + * additional code for level 1 + */ +static int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + unsigned int result; + unsigned int nbytes; + + if( !level ) + return 0; + + if( !slow_seeder ) + load_and_init_winseed(); + + /* Our estimation on how much entropy we should use is very vague. + * Winseed delivers some amount of entropy on each slow poll and + * we add it to our random pool. Depending on the required quality + * level we adjust the requested length so that for higher quality + * we make sure to add more entropy to our pool. However, as we don't + * like to waste any entropy collected by winseed, we always add + * at least everything we got from winseed. + */ + if( level > 1 ) + length *= 100; + else if( level > 0 ) + length *= 10; + + for(;;) { + nbytes = entropy_buffer_size; + result = get_seed( slow_seeder, entropy_buffer, &nbytes); + if( result == PCP_SEEDER_TOO_SMALL ) { + unsigned int n1 = get_internal_seed_size( slow_seeder ); + + if( n1 > MAX_SEEDER_SIZE ) { + g10_log_fatal("rndw32: internal seeder problem (size=%u)\n", + n1); + return -1; /* actually never reached */ + } + n1 += SEEDER_INC_CHUNK; + set_internal_seed_size( slow_seeder, n1 ); + if( n1 > entropy_buffer_size ) { + entropy_buffer_size = n1; + entropy_buffer = m_realloc( entropy_buffer, + entropy_buffer_size ); + } + continue; + } + + + if( result ) { + g10_log_fatal("rndw32: get_seed(slow) failed: rc=%u\n", result); + return -1; /* actually never reached */ + } + /*g10_log_info("rndw32: slow poll level %d, need %u, got %u\n", + level, (unsigned int)length, (unsigned int)nbytes );*/ + (*add)( entropy_buffer, nbytes, requester ); + if( length <= nbytes ) + return 0; /* okay */ + length -= nbytes; + } +} + +static int +gather_random_fast( void (*add)(const void*, size_t, int), int requester ) +{ + unsigned int result; + unsigned int nbytes; + + if( !fast_seeder ) + load_and_init_winseed(); + + /* winseed delivers a constant ammount of entropy for a fast + * poll. We can simply use this and add it to the pool; no need + * a loop like it is used in the slow poll */ + nbytes = entropy_buffer_size; + result = get_seed( fast_seeder, entropy_buffer, &nbytes); + if( result ) { + g10_log_fatal("rndw32: get_seed(fast) failed: rc=%u\n", result); + return -1; /* actually never reached */ + } + /*g10_log_info("rndw32: fast poll got %u\n", (unsigned int)nbytes );*/ + (*add)( entropy_buffer, nbytes, requester ); + return 0; +} + +#else /* !USE_ENTROPY_DLL */ +/* This is the new code which does not require the entropy.dll */ + +/* + * Definitions which are missing from the current GNU Windows32Api + */ + +#define TH32CS_SNAPHEAPLIST 1 +#define TH32CS_SNAPPROCESS 2 +#define TH32CS_SNAPTHREAD 4 +#define TH32CS_SNAPMODULE 8 +#define TH32CS_SNAPALL (1|2|4|8) +#define TH32CS_INHERIT 0x80000000 + +#define IOCTL_DISK_PERFORMANCE 0x00070020 +#define VER_PLATFORM_WIN32_WINDOWS 1 + + +typedef struct { + DWORD dwSize; + DWORD th32ProcessID; + DWORD th32HeapID; + DWORD dwFlags; +} HEAPLIST32; + +typedef struct { + DWORD dwSize; + HANDLE hHandle; + DWORD dwAddress; + DWORD dwBlockSize; + DWORD dwFlags; + DWORD dwLockCount; + DWORD dwResvd; + DWORD th32ProcessID; + DWORD th32HeapID; +} HEAPENTRY32; + +typedef struct { + DWORD dwSize; + DWORD cntUsage; + DWORD th32ProcessID; + DWORD th32DefaultHeapID; + DWORD th32ModuleID; + DWORD cntThreads; + DWORD th32ParentProcessID; + LONG pcPriClassBase; + DWORD dwFlags; + char szExeFile[260]; +} PROCESSENTRY32; + +typedef struct { + DWORD dwSize; + DWORD cntUsage; + DWORD th32ThreadID; + DWORD th32OwnerProcessID; + LONG tpBasePri; + LONG tpDeltaPri; + DWORD dwFlags; +} THREADENTRY32; + +typedef struct { + DWORD dwSize; + DWORD th32ModuleID; + DWORD th32ProcessID; + DWORD GlblcntUsage; + DWORD ProccntUsage; + BYTE *modBaseAddr; + DWORD modBaseSize; + HMODULE hModule; + char szModule[256]; + char szExePath[260]; +} MODULEENTRY32; + + + +/* Type definitions for function pointers to call Toolhelp32 functions + * used with the windows95 gatherer */ +typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, MODULEENTRY32 *lpme); +typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, THREADENTRY32 *lpte); +typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, PROCESSENTRY32 *lppe); +typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, HEAPLIST32 *lphl); +typedef BOOL (WINAPI * HEAPFIRST) (HEAPENTRY32 *lphe, DWORD th32ProcessID, + DWORD th32HeapID); +typedef BOOL (WINAPI * HEAPNEXT) (HEAPENTRY32 *lphe); +typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID); + +/* Type definitions for function pointers to call NetAPI32 functions */ +typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, + DWORD dwLevel, DWORD dwOptions, + LPBYTE * lpBuffer); +typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); +typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); + + +/* When we query the performance counters, we allocate an initial buffer and + * then reallocate it as required until RegQueryValueEx() stops returning + * ERROR_MORE_DATA. The following values define the initial buffer size and + * step size by which the buffer is increased + */ +#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */ +#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */ + + +static void +slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester ) +{ + static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; + static MODULEWALK pModule32First = NULL; + static MODULEWALK pModule32Next = NULL; + static PROCESSWALK pProcess32First = NULL; + static PROCESSWALK pProcess32Next = NULL; + static THREADWALK pThread32First = NULL; + static THREADWALK pThread32Next = NULL; + static HEAPLISTWALK pHeap32ListFirst = NULL; + static HEAPLISTWALK pHeap32ListNext = NULL; + static HEAPFIRST pHeap32First = NULL; + static HEAPNEXT pHeap32Next = NULL; + HANDLE hSnapshot; + + + /* initialize the Toolhelp32 function pointers */ + if ( !pCreateToolhelp32Snapshot ) { + HANDLE hKernel; + + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_95: init toolkit\n" ); + + /* Obtain the module handle of the kernel to retrieve the addresses + * of the Toolhelp32 functions */ + if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) { + g10_log_fatal ( "rndw32: can't get module handle\n" ); + } + + /* Now get pointers to the functions */ + pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel, + "CreateToolhelp32Snapshot"); + pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First"); + pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next"); + pProcess32First = (PROCESSWALK) GetProcAddress (hKernel, + "Process32First"); + pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel, + "Process32Next"); + pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First"); + pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next"); + pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel, + "Heap32ListFirst"); + pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel, + "Heap32ListNext"); + pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First"); + pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next"); + + if ( !pCreateToolhelp32Snapshot + || !pModule32First || !pModule32Next + || !pProcess32First || !pProcess32Next + || !pThread32First || !pThread32Next + || !pHeap32ListFirst || !pHeap32ListNext + || !pHeap32First || !pHeap32Next ) { + g10_log_fatal ( "rndw32: failed to get a toolhep function\n" ); + } + } + + /* Take a snapshot of everything we can get to which is currently + * in the system */ + if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) { + g10_log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" ); + } + + /* Walk through the local heap */ + { HEAPLIST32 hl32; + hl32.dwSize = sizeof (HEAPLIST32); + if (pHeap32ListFirst (hSnapshot, &hl32)) { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_95: walk heap\n" ); + do { + HEAPENTRY32 he32; + + /* First add the information from the basic Heaplist32 struct */ + (*add) ( &hl32, sizeof (hl32), requester ); + + /* Now walk through the heap blocks getting information + * on each of them */ + he32.dwSize = sizeof (HEAPENTRY32); + if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){ + do { + (*add) ( &he32, sizeof (he32), requester ); + } while (pHeap32Next (&he32)); + } + } while (pHeap32ListNext (hSnapshot, &hl32)); + } + } + + + /* Walk through all processes */ + { PROCESSENTRY32 pe32; + pe32.dwSize = sizeof (PROCESSENTRY32); + if (pProcess32First (hSnapshot, &pe32)) { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_95: walk processes\n" ); + do { + (*add) ( &pe32, sizeof (pe32), requester ); + } while (pProcess32Next (hSnapshot, &pe32)); + } + } + + /* Walk through all threads */ + { THREADENTRY32 te32; + te32.dwSize = sizeof (THREADENTRY32); + if (pThread32First (hSnapshot, &te32)) { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_95: walk threads\n" ); + do { + (*add) ( &te32, sizeof (te32), requester ); + } while (pThread32Next (hSnapshot, &te32)); + } + } + + /* Walk through all modules associated with the process */ + { MODULEENTRY32 me32; + me32.dwSize = sizeof (MODULEENTRY32); + if (pModule32First (hSnapshot, &me32)) { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_95: walk modules\n" ); + do { + (*add) ( &me32, sizeof (me32), requester ); + } while (pModule32Next (hSnapshot, &me32)); + } + } + + CloseHandle (hSnapshot); +} + + + +static void +slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester ) +{ + static int is_initialized = 0; + static NETSTATISTICSGET pNetStatisticsGet = NULL; + static NETAPIBUFFERSIZE pNetApiBufferSize = NULL; + static NETAPIBUFFERFREE pNetApiBufferFree = NULL; + static int is_workstation = 1; + + static int cbPerfData = PERFORMANCE_BUFFER_SIZE; + PERF_DATA_BLOCK *pPerfData; + HANDLE hDevice, hNetAPI32 = NULL; + DWORD dwSize, status; + int nDrive; + + if ( !is_initialized ) { + HKEY hKey; + + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" ); + /* Find out whether this is an NT server or workstation if necessary */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + BYTE szValue[32]; + dwSize = sizeof (szValue); + + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: check product options\n" ); + status = RegQueryValueEx (hKey, "ProductType", 0, NULL, + szValue, &dwSize); + if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) { + /* Note: There are (at least) three cases for ProductType: + * WinNT = NT Workstation, ServerNT = NT Server, LanmanNT = + * NT Server acting as a Domain Controller */ + is_workstation = 0; + if ( debug_me ) + log_debug ("rndw32: this is a NT server\n"); + } + RegCloseKey (hKey); + } + + /* Initialize the NetAPI32 function pointers if necessary */ + if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" ); + pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, + "NetStatisticsGet"); + pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, + "NetApiBufferSize"); + pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, + "NetApiBufferFree"); + + if ( !pNetStatisticsGet + || !pNetApiBufferSize || !pNetApiBufferFree ) { + FreeLibrary (hNetAPI32); + hNetAPI32 = NULL; + g10_log_debug ("rndw32: No NETAPI found\n" ); + } + } + + is_initialized = 1; + } + + /* Get network statistics. Note: Both NT Workstation and NT Server by + * default will be running both the workstation and server services. The + * heuristic below is probably useful though on the assumption that the + * majority of the network traffic will be via the appropriate service. + * In any case the network statistics return almost no randomness */ + { LPBYTE lpBuffer; + if (hNetAPI32 && !pNetStatisticsGet (NULL, + is_workstation ? L"LanmanWorkstation" : + L"LanmanServer", 0, 0, &lpBuffer) ) { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: get netstats\n" ); + pNetApiBufferSize (lpBuffer, &dwSize); + (*add) ( lpBuffer, dwSize,requester ); + pNetApiBufferFree (lpBuffer); + } + } + + /* Get disk I/O statistics for all the hard drives */ + for (nDrive = 0;; nDrive++) { + DISK_PERFORMANCE diskPerformance; + char szDevice[50]; + + /* Check whether we can access this device */ + sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); + hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + break; + + /* Note: This only works if you have turned on the disk performance + * counters with 'diskperf -y'. These counters are off by default */ + if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, + &diskPerformance, sizeof (DISK_PERFORMANCE), + &dwSize, NULL)) + { + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n", + nDrive ); + (*add) ( &diskPerformance, dwSize, requester ); + } + else { + log_info ("NOTE: you should run 'diskperf -y' " + "to enable the disk statistics\n"); + } + CloseHandle (hDevice); + } + + #if 0 /* we don't need this in GnuPG */ + /* Wait for any async keyset driver binding to complete. You may be + * wondering what this call is doing here... the reason it's necessary is + * because RegQueryValueEx() will hang indefinitely if the async driver + * bind is in progress. The problem occurs in the dynamic loading and + * linking of driver DLL's, which work as follows: + * + * hDriver = LoadLibrary( DRIVERNAME ); + * pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 ); + * pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 ); + * + * If RegQueryValueEx() is called while the GetProcAddress()'s are in + * progress, it will hang indefinitely. This is probably due to some + * synchronisation problem in the NT kernel where the GetProcAddress() + * calls affect something like a module reference count or function + * reference count while RegQueryValueEx() is trying to take a snapshot + * of the statistics, which include the reference counts. Because of + * this, we have to wait until any async driver bind has completed + * before we can call RegQueryValueEx() */ + waitSemaphore (SEMAPHORE_DRIVERBIND); + #endif + + /* Get information from the system performance counters. This can take + * a few seconds to do. In some environments the call to + * RegQueryValueEx() can produce an access violation at some random time + * in the future, adding a short delay after the following code block + * makes the problem go away. This problem is extremely difficult to + * reproduce, I haven't been able to get it to occur despite running it + * on a number of machines. The best explanation for the problem is that + * on the machine where it did occur, it was caused by an external driver + * or other program which adds its own values under the + * HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external + * modules to map in the data, if there's a synchronisation problem the + * external module would write its data at an inappropriate moment, + * causing the access violation. A low-level memory checker indicated + * that ExpandEnvironmentStrings() in KERNEL32.DLL, called an + * interminable number of calls down inside RegQueryValueEx(), was + * overwriting memory (it wrote twice the allocated size of a buffer to a + * buffer allocated by the NT kernel). This may be what's causing the + * problem, but since it's in the kernel there isn't much which can be + * done. + * + * In addition to these problems the code in RegQueryValueEx() which + * estimates the amount of memory required to return the performance + * counter information isn't very accurate, since it always returns a + * worst-case estimate which is usually nowhere near the actual amount + * required. For example it may report that 128K of memory is required, + * but only return 64K of data */ + { pPerfData = m_alloc (cbPerfData); + for (;;) { + dwSize = cbPerfData; + if ( debug_me ) + log_debug ("rndw32#slow_gatherer_nt: get perf data\n" ); + status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL, + NULL, (LPBYTE) pPerfData, &dwSize); + if (status == ERROR_SUCCESS) { + if (!memcmp (pPerfData->Signature, L"PERF", 8)) { + (*add) ( pPerfData, dwSize, requester ); + } + else + g10_log_debug ( "rndw32: no PERF signature\n"); + break; + } + else if (status == ERROR_MORE_DATA) { + cbPerfData += PERFORMANCE_BUFFER_STEP; + pPerfData = m_realloc (pPerfData, cbPerfData); + } + else { + g10_log_debug ( "rndw32: get performance data problem\n"); + break; + } + } + m_free (pPerfData); + } + /* Although this isn't documented in the Win32 API docs, it's necessary + to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's + implicitly opened on the first call to RegQueryValueEx()). If this + isn't done then any system components which provide performance data + can't be removed or changed while the handle remains active */ + RegCloseKey (HKEY_PERFORMANCE_DATA); +} + + +static int +gather_random( void (*add)(const void*, size_t, int), int requester, + size_t length, int level ) +{ + static int is_initialized; + static int is_windows95; + + + if( !level ) + return 0; + /* We don't differentiate between level 1 and 2 here because + * there is no nternal entropy pool as a scary resource. It may + * all work slower, but because our entropy source will never + * block but deliver some not easy to measure entropy, we assume level 2 + */ + + + if ( !is_initialized ) { + OSVERSIONINFO osvi = { sizeof( osvi ) }; + DWORD platform; + + GetVersionEx( &osvi ); + platform = osvi.dwPlatformId; + is_windows95 = platform == VER_PLATFORM_WIN32_WINDOWS; + + if ( platform == VER_PLATFORM_WIN32s ) { + g10_log_fatal("can't run on a W32s platform\n" ); + } + is_initialized = 1; + if ( debug_me ) + log_debug ("rndw32#gather_random: platform=%d\n", (int)platform ); + } + + + if ( debug_me ) + log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n", + requester, (unsigned int)length, level ); + + if (is_windows95 ) { + slow_gatherer_windows95( add, requester ); + } + else { + slow_gatherer_windowsNT( add, requester ); + } + + return 0; +} + + + +static int +gather_random_fast( void (*add)(const void*, size_t, int), int requester ) +{ + static int addedFixedItems = 0; + + if ( debug_me ) + log_debug ("rndw32#gather_random_fast: req=%d\n", requester ); + + /* Get various basic pieces of system information: Handle of active + * window, handle of window with mouse capture, handle of clipboard owner + * handle of start of clpboard viewer list, pseudohandle of current + * process, current process ID, pseudohandle of current thread, current + * thread ID, handle of desktop window, handle of window with keyboard + * focus, whether system queue has any events, cursor position for last + * message, 1 ms time for last message, handle of window with clipboard + * open, handle of process heap, handle of procs window station, types of + * events in input queue, and milliseconds since Windows was started */ + { byte buffer[20*sizeof(ulong)], *bufptr; + bufptr = buffer; + #define ADD(f) do { ulong along = (ulong)(f); \ + memcpy (bufptr, &along, sizeof (along) ); \ + bufptr += sizeof (along); } while (0) + ADD ( GetActiveWindow ()); + ADD ( GetCapture ()); + ADD ( GetClipboardOwner ()); + ADD ( GetClipboardViewer ()); + ADD ( GetCurrentProcess ()); + ADD ( GetCurrentProcessId ()); + ADD ( GetCurrentThread ()); + ADD ( GetCurrentThreadId ()); + ADD ( GetDesktopWindow ()); + ADD ( GetFocus ()); + ADD ( GetInputState ()); + ADD ( GetMessagePos ()); + ADD ( GetMessageTime ()); + ADD ( GetOpenClipboardWindow ()); + ADD ( GetProcessHeap ()); + ADD ( GetProcessWindowStation ()); + ADD ( GetQueueStatus (QS_ALLEVENTS)); + ADD ( GetTickCount ()); + + assert ( bufptr-buffer < sizeof (buffer) ); + (*add) ( buffer, bufptr-buffer, requester ); + #undef ADD + } + + /* Get multiword system information: Current caret position, current + * mouse cursor position */ + { POINT point; + GetCaretPos (&point); + (*add) ( &point, sizeof (point), requester ); + GetCursorPos (&point); + (*add) ( &point, sizeof (point), requester ); + } + + /* Get percent of memory in use, bytes of physical memory, bytes of free + * physical memory, bytes in paging file, free bytes in paging file, user + * bytes of address space, and free user bytes */ + { MEMORYSTATUS memoryStatus; + memoryStatus.dwLength = sizeof (MEMORYSTATUS); + GlobalMemoryStatus (&memoryStatus); + (*add) ( &memoryStatus, sizeof (memoryStatus), requester ); + } + + /* Get thread and process creation time, exit time, time in kernel mode, + and time in user mode in 100ns intervals */ + { HANDLE handle; + FILETIME creationTime, exitTime, kernelTime, userTime; + DWORD minimumWorkingSetSize, maximumWorkingSetSize; + + handle = GetCurrentThread (); + GetThreadTimes (handle, &creationTime, &exitTime, + &kernelTime, &userTime); + (*add) ( &creationTime, sizeof (creationTime), requester ); + (*add) ( &exitTime, sizeof (exitTime), requester ); + (*add) ( &kernelTime, sizeof (kernelTime), requester ); + (*add) ( &userTime, sizeof (userTime), requester ); + + handle = GetCurrentProcess (); + GetProcessTimes (handle, &creationTime, &exitTime, + &kernelTime, &userTime); + (*add) ( &creationTime, sizeof (creationTime), requester ); + (*add) ( &exitTime, sizeof (exitTime), requester ); + (*add) ( &kernelTime, sizeof (kernelTime), requester ); + (*add) ( &userTime, sizeof (userTime), requester ); + + /* Get the minimum and maximum working set size for the current process */ + GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, + &maximumWorkingSetSize); + (*add) ( &minimumWorkingSetSize, + sizeof (&minimumWorkingSetSize), requester ); + (*add) ( &maximumWorkingSetSize, + sizeof (&maximumWorkingSetSize), requester ); + } + + + /* The following are fixed for the lifetime of the process so we only + * add them once */ + if (!addedFixedItems) { + STARTUPINFO startupInfo; + + /* Get name of desktop, console window title, new window position and + * size, window flags, and handles for stdin, stdout, and stderr */ + startupInfo.cb = sizeof (STARTUPINFO); + GetStartupInfo (&startupInfo); + (*add) ( &startupInfo, sizeof (STARTUPINFO), requester ); + addedFixedItems = 1; + } + + /* The performance of QPC varies depending on the architecture it's + * running on and on the OS. Under NT it reads the CPU's 64-bit timestamp + * counter (at least on a Pentium and newer '486's, it hasn't been tested + * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC + * timer. There are vague mumblings in the docs that it may fail if the + * appropriate hardware isn't available (possibly '386's or MIPS machines + * running NT), but who's going to run NT on a '386? */ + { LARGE_INTEGER performanceCount; + if (QueryPerformanceCounter (&performanceCount)) { + if ( debug_me ) + log_debug ("rndw32#gather_random_fast: perf data\n"); + (*add) (&performanceCount, sizeof (&performanceCount), requester); + } + else { /* Millisecond accuracy at best... */ + DWORD aword = GetTickCount (); + (*add) (&aword, sizeof (aword), requester ); + } + } + + return 0; +} + + + + + +#endif /* !USE_ENTROPY_DLL */ + + +#ifndef IS_MODULE +static +#endif +const char * const gnupgext_version = "RNDW32 ($Revision$)"; + +static struct { + int class; + int version; + void *func; +} func_table[] = { + { 40, 1, gather_random }, + { 41, 1, gather_random_fast }, +}; + + +#ifndef IS_MODULE +static +#endif +void * +gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) +{ + void *ret; + int i = *sequence; + + debug_me = !!getenv("DEBUG_RNDW32"); + + do { + if ( i >= DIM(func_table) || i < 0 ) { + return NULL; + } + *class = func_table[i].class; + *vers = func_table[i].version; + ret = func_table[i].func; + i++; + } while ( what && what != *class ); + + *sequence = i; + return ret; +} + +#ifndef IS_MODULE +void +rndw32_constructor(void) +{ + register_internal_cipher_extension( gnupgext_version, + gnupgext_enum_func ); +} +#endif + diff --git a/cipher/sha1.c b/cipher/sha1.c index 40ad62f1f..2c2a10a7b 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -337,10 +337,10 @@ sha1_get_info( int algo, size_t *contextsize, *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 20; - *r_init = (void (*)(void *))sha1_init; - *r_write = (void (*)(void *, byte*, size_t))sha1_write; - *r_final = (void (*)(void *))sha1_final; - *r_read = (byte *(*)(void *))sha1_read; + *(void (**)(SHA1_CONTEXT *))r_init = sha1_init; + *(void (**)(SHA1_CONTEXT *, byte*, size_t))r_write = sha1_write; + *(void (**)(SHA1_CONTEXT *))r_final = sha1_final; + *(byte *(**)(SHA1_CONTEXT *))r_read = sha1_read; return "SHA1"; } diff --git a/cipher/tiger.c b/cipher/tiger.c index 0765f0bbd..e4a7c4daa 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -899,10 +899,10 @@ tiger_get_info( int algo, size_t *contextsize, *r_asnoid = asn; *r_asnlen = DIM(asn); *r_mdlen = 24; - *r_init = (void (*)(void *))tiger_init; - *r_write = (void (*)(void *, byte*, size_t))tiger_write; - *r_final = (void (*)(void *))tiger_final; - *r_read = (byte *(*)(void *))tiger_read; + *(void (**)(TIGER_CONTEXT *))r_init = tiger_init; + *(void (**)(TIGER_CONTEXT *, byte*, size_t))r_write = tiger_write; + *(void (**)(TIGER_CONTEXT *))r_final = tiger_final; + *(byte *(**)(TIGER_CONTEXT *))r_read = tiger_read; return "TIGER"; } diff --git a/cipher/twofish.c b/cipher/twofish.c index 182f18c49..12982e123 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -35,10 +35,6 @@ /* Prototype for the self-test function. */ static const char *selftest(void); -/* Macros used by the info function. */ -#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f)) -#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f)) - /* Structure for an expanded Twofish key. s contains the key-dependent * S-boxes composed with the MDS matrix; w contains the eight "whitening" * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note @@ -991,16 +987,20 @@ twofish_get_info (int algo, size_t *keylen, *keylen = algo==10? 256 : 128; *blocksize = 16; *contextsize = sizeof (TWOFISH_context); - *r_setkey = FNCCAST_SETKEY (twofish_setkey); - *r_encrypt= FNCCAST_CRYPT (twofish_encrypt); - *r_decrypt= FNCCAST_CRYPT (twofish_decrypt); - - if( algo == 10 ) - return "TWOFISH"; - if (algo == 102) /* This algorithm number is assigned for - * experiments, so we can use it */ - return "TWOFISH128"; - return NULL; + + *(int (**)(TWOFISH_context*, const byte*, const unsigned))r_setkey + = twofish_setkey; + *(void (**)(const TWOFISH_context*, byte*, const byte*))r_encrypt + = twofish_encrypt; + *(void (**)(const TWOFISH_context*, byte*, const byte*))r_decrypt + = twofish_decrypt; + + if( algo == 10 ) + return "TWOFISH"; + if (algo == 102) /* This algorithm number is assigned for + * experiments, so we can use it */ + return "TWOFISH128"; + return NULL; } |