aboutsummaryrefslogtreecommitdiffstats
path: root/cipher/rndlinux.c
diff options
context:
space:
mode:
Diffstat (limited to 'cipher/rndlinux.c')
-rw-r--r--cipher/rndlinux.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/cipher/rndlinux.c b/cipher/rndlinux.c
index b9376e8fe..66bb34e62 100644
--- a/cipher/rndlinux.c
+++ b/cipher/rndlinux.c
@@ -45,7 +45,8 @@
#endif
static int open_device( const char *name, int minor );
-static int gather_random( byte *buffer, size_t *r_length, int level );
+static int gather_random( void (*add)(const void*, size_t, int), int requester,
+ size_t length, int level );
#ifdef IS_MODULE
static void tty_printf(const char *fmt, ... )
@@ -81,15 +82,15 @@ open_device( const char *name, int minor )
static int
-gather_random( byte *buffer, size_t *r_length, int level )
+gather_random( void (*add)(const void*, size_t, int), int requester,
+ size_t length, int level )
{
static int fd_urandom = -1;
static int fd_random = -1;
int fd;
int n;
int warn=0;
- size_t length = *r_length;
- /* note: we will always return the requested length */
+ byte buffer[768];
if( level >= 2 ) {
if( fd_random == -1 )
@@ -101,7 +102,8 @@ gather_random( byte *buffer, size_t *r_length, int level )
fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 );
fd = fd_urandom;
}
- do {
+
+ while( length ) {
fd_set rfds;
struct timeval tv;
int rc;
@@ -125,20 +127,21 @@ gather_random( byte *buffer, size_t *r_length, int level )
}
do {
- n = read(fd, buffer, length );
- if( n >= 0 && n > length ) {
+ int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
+ n = read(fd, buffer, nbytes );
+ if( n >= 0 && n > nbytes ) {
g10_log_error("bogus read from random device (n=%d)\n", n );
- n = length;
+ n = nbytes;
}
} while( n == -1 && errno == EINTR );
if( n == -1 )
g10_log_fatal("read error on random device: %s\n", strerror(errno));
- assert( n <= length );
- buffer += n;
+ (*add)( buffer, n, requester );
length -= n;
- } while( length );
+ }
+ memset(buffer, 0, sizeof(buffer) );
- return 100; /* always 100% useful at the requested level */
+ return 0; /* success */
}