diff options
author | Werner Koch <[email protected]> | 1998-11-25 11:52:41 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 1998-11-25 11:52:41 +0000 |
commit | 2e494682b63e9f7abc2a34711618f4ebd21e2744 (patch) | |
tree | e8afb0e10b4657a3d841ff9cb02a752698c19f97 /cipher/random.c | |
parent | Ready for version 0.4.4 (diff) | |
download | gnupg-2e494682b63e9f7abc2a34711618f4ebd21e2744.tar.gz gnupg-2e494682b63e9f7abc2a34711618f4ebd21e2744.zip |
Restructured the RNG source and add support for loadable
random modules.
Diffstat (limited to '')
-rw-r--r-- | cipher/random.c | 143 |
1 files changed, 136 insertions, 7 deletions
diff --git a/cipher/random.c b/cipher/random.c index e22f3d70c..e173a5279 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -36,7 +36,9 @@ #include "rmd.h" #include "ttyio.h" #include "i18n.h" +#include "random.h" #include "rand-internal.h" +#include "dynload.h" #if SIZEOF_UNSIGNED_LONG == 8 @@ -47,6 +49,20 @@ #error weird size for an unsigned long #endif +#define BLOCKLEN 64 /* hash this amount of bytes */ +#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ +/* poolblocks is the number of digests which make up the pool + * and poolsize must be a multiple of the digest length + * to make the AND operations faster, the size should also be + * a multiple of ulong + */ +#define POOLBLOCKS 30 +#define POOLSIZE (POOLBLOCKS*DIGESTLEN) +#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) + #error Please make sure that poolsize is a multiple of ulong +#endif +#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) + static int is_initialized; #define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) @@ -60,9 +76,16 @@ static int just_mixed; static int secure_alloc; static int quick_test; +static int faked_rng; static void read_pool( byte *buffer, size_t length, int level ); +static void add_randomness( const void *buffer, size_t length, int source ); +static void random_poll(void); +static void read_random_source( byte *buffer, size_t length, int level ); +#ifndef HAVE_DEV_RANDOM +static int gather_faked( byte *buffer, size_t *r_length, int level ); +#endif static void @@ -76,6 +99,20 @@ initialize() keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) : m_alloc_clear(POOLSIZE+BLOCKLEN); is_initialized = 1; + + #if USE_RNDLINUX + rndlinux_constructor(); + #elif USE_RNDUNIX + rndunix_constructor(); + #elif USE_RNDW32 + rndw32_constructor(); + #elif USE_RNDOS2 + rndos2_constructor(); + #elif USE_RNDATARI + rndatari_constructor(); + #elif USE_RNDMVS + rndmvs_constructor(); + #endif } void @@ -88,13 +125,13 @@ secure_random_alloc() int quick_random_gen( int onoff ) { - int last = quick_test; + int last; + + read_random_source( NULL, 0, 0 ); /* load module */ + last = quick_test; if( onoff != -1 ) quick_test = onoff; - #ifdef USE_RAND_DUMMY - last = 1; /* insecure RNG */ - #endif - return last; + return faked_rng? 1 : last; } @@ -250,9 +287,9 @@ 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 randomeness source. + * source may be used to specify the randomness source. */ -void +static void add_randomness( const void *buffer, size_t length, int source ) { if( !is_initialized ) @@ -271,3 +308,95 @@ add_randomness( const void *buffer, size_t length, int source ) +static void +random_poll() +{ + char buf[POOLSIZE/5]; + read_random_source( buf, POOLSIZE/5, 1 ); + add_randomness( buf, POOLSIZE/5, 2); + memset( buf, 0, POOLSIZE/5); +} + + +void +fast_random_poll() +{ + static void (*fnc)( void (*)(const void*, size_t, int)) = NULL; + static int initialized = 0; + + if( !initialized ) { + if( !is_initialized ) + initialize(); + initialized = 1; + fnc = dynload_getfnc_fast_random_poll(); + if( !fnc ) + log_info("Ooops: No fast random poll function\n"); + } + if( fnc ) + (*fnc)( add_randomness ); +} + + + +static void +read_random_source( byte *buffer, size_t length, int level ) +{ + static int (*fnc)(byte*, size_t*, int) = NULL; + int nbytes; + int goodness; + + if( !fnc ) { + if( !is_initialized ) + initialize(); + fnc = dynload_getfnc_gather_random(); + if( !fnc ) { + faked_rng = 1; + #ifndef HAVE_DEV_RANDOM + fnc = gather_faked; + #else + BUG(); + #endif + } + } + while( length ) { + nbytes = length; + goodness = (*fnc)( buffer, &nbytes, level ); + buffer +=nbytes; + length -= nbytes; + /* FIXME: how can we handle the goodness */ + } +} + + +#ifndef HAVE_DEV_RANDOM +static int +gather_faked( byte *buffer, size_t *r_length, int level ) +{ + static int initialized=0; + size_t length = *r_length; + + if( !initialized ) { + log_info(_("WARNING: using insecure random number generator!!\n")); + tty_printf(_("The random number generator is only a kludge to let\n" + "it compile - it is in no way a strong RNG!\n\n" + "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); + initialized=1; + #ifdef HAVE_RAND + srand(make_timestamp()*getpid()); + #else + srandom(make_timestamp()*getpid()); + #endif + } + + #ifdef HAVE_RAND + while( length-- ) + *buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); + #else + while( length-- ) + *buffer++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); + #endif + return 100; /* We really fake it ;-) */ +} + +#endif /* ! HAVE_DEV_RANDOM */ + |