aboutsummaryrefslogtreecommitdiffstats
path: root/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'cipher')
-rw-r--r--cipher/ChangeLog17
-rw-r--r--cipher/random.c165
-rw-r--r--cipher/random.h2
-rw-r--r--cipher/rndegd.c9
-rw-r--r--cipher/rndlinux.c6
-rw-r--r--cipher/rndunix.c7
-rw-r--r--cipher/rndw32.c3
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();