diff options
Diffstat (limited to 'cipher')
-rw-r--r-- | cipher/ChangeLog | 17 | ||||
-rw-r--r-- | cipher/random.c | 165 | ||||
-rw-r--r-- | cipher/random.h | 2 | ||||
-rw-r--r-- | cipher/rndegd.c | 9 | ||||
-rw-r--r-- | cipher/rndlinux.c | 6 | ||||
-rw-r--r-- | cipher/rndunix.c | 7 | ||||
-rw-r--r-- | cipher/rndw32.c | 3 |
7 files changed, 207 insertions, 2 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 6804a7b19..f1e73c537 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,20 @@ +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 diff --git a/cipher/random.c b/cipher/random.c index 465e7b8be..6c55de670 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -36,6 +36,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <fcntl.h> #ifdef HAVE_GETHRTIME #include <sys/times.h> #endif @@ -91,6 +92,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,6 +268,131 @@ 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; + + fd = open( seed_file_name, O_RDONLY ); + 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) || S_ISLNK(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 ) + 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++; + + fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); + 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 ) { @@ -275,6 +404,27 @@ read_pool( byte *buffer, size_t length, int level ) 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 ) { size_t needed; @@ -338,6 +488,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 ) @@ -423,6 +579,15 @@ fast_random_poll() } #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/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..9f60b3cf8 100644 --- a/cipher/rndunix.c +++ b/cipher/rndunix.c @@ -716,6 +716,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 +729,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 index b8a1aaf24..8bef6348f 100644 --- a/cipher/rndw32.c +++ b/cipher/rndw32.c @@ -164,6 +164,9 @@ gather_random( void (*add)(const void*, size_t, int), int requester, unsigned int result; unsigned int nbytes; + if( !level ) + return 0; + if( !slow_seeder ) load_and_init_winseed(); |