diff options
author | Werner Koch <wk@gnupg.org> | 2009-07-09 11:57:28 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2009-07-09 11:57:28 +0000 |
commit | 9b28e56d71d111416623988c7fa7c66dc6ab023c (patch) | |
tree | 2e3c1bac0638c6bbfcc8664e1dec649745785399 /random | |
parent | ab9ff33b9b55db3077af87bf321937e3fd9826c8 (diff) | |
download | libgcrypt-9b28e56d71d111416623988c7fa7c66dc6ab023c.tar.gz |
[random/ChangeLog]
* rndlinux.c (_gcry_rndlinux_gather_random): Print real values for
the progess function and call it before blocking. Suggested by
Christian Grothoff.
* rndunix.c (slow_poll): Add similar, but not yet functional, code.
SCALAR(0x81980e8)
Copyright 2008, 2009 Free Software Foundation, Inc.
[tests/ChangeLog]
* benchmark.c (progress_cb): New.
(main): Add option --progress.
Diffstat (limited to 'random')
-rw-r--r-- | random/ChangeLog | 9 | ||||
-rw-r--r-- | random/rndlinux.c | 79 | ||||
-rw-r--r-- | random/rndunix.c | 41 |
3 files changed, 90 insertions, 39 deletions
diff --git a/random/ChangeLog b/random/ChangeLog index c64671c4..1c29a7ad 100644 --- a/random/ChangeLog +++ b/random/ChangeLog @@ -1,3 +1,10 @@ +2009-07-09 Werner Koch <wk@g10code.com> + + * rndlinux.c (_gcry_rndlinux_gather_random): Print real values for + the progess function and call it before blocking. Suggested by + Christian Grothoff. + * rndunix.c (slow_poll): Add similar, but not yet functional, code. + 2009-07-02 Werner Koch <wk@g10code.com> * rndhw.c (poll_padlock): Asm change from Fedora. @@ -120,7 +127,7 @@ here. * Makefile.am: New. - Copyright 2008 Free Software Foundation, Inc. + Copyright 2008, 2009 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/random/rndlinux.c b/random/rndlinux.c index 574ef6dc..6f98a9eb 100644 --- a/random/rndlinux.c +++ b/random/rndlinux.c @@ -1,5 +1,6 @@ /* rndlinux.c - raw random number for OSes with /dev/random - * Copyright (C) 1998, 2001, 2002, 2003, 2007 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001, 2002, 2003, 2007, + * 2009 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -93,9 +94,12 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, static int fd_random = -1; int fd; int n; - int warn=0; byte buffer[768]; size_t n_hw; + size_t want = length; + size_t last_so_far = 0; + int any_need_entropy = 0; + int delay; /* First read from a hardware source. However let it account only for up to 50% of the requested bytes. */ @@ -119,7 +123,11 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, fd = fd_urandom; } - /* And enter the read loop. */ + /* Enter the read loop. */ + delay = 0; /* Start with 0 seconds so that we do no block on the + first iteration and in turn call the progess function + before blocking. To give the OS a better chance to + return with something we will actually use 100ms. */ while (length) { fd_set rfds; @@ -128,40 +136,49 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, FD_ZERO(&rfds); FD_SET(fd, &rfds); - tv.tv_sec = 3; - tv.tv_usec = 0; - if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) + tv.tv_sec = delay; + tv.tv_usec = delay? 0 : 100000; + if ( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) { - if( !warn ) + if (!any_need_entropy || last_so_far != (want - length) ) { - _gcry_random_progress ("need_entropy", 'X', 0, (int)length); - warn = 1; + last_so_far = want - length; + _gcry_random_progress ("need_entropy", 'X', + (int)last_so_far, (int)want); + any_need_entropy = 1; } + delay = 3; /* Use 3 seconds henceforth. */ continue; } - else if( rc == -1 ) - { - log_error ("select() error: %s\n", strerror(errno)); - continue; - } - - do - { - int nbytes = length < sizeof(buffer)? length : sizeof(buffer); - n = read(fd, buffer, nbytes ); - if( n >= 0 && n > nbytes ) - { - log_error("bogus read from random device (n=%d)\n", n ); - n = nbytes; - } - } - while( n == -1 && errno == EINTR ); - if( n == -1 ) - log_fatal("read error on random device: %s\n", strerror(errno)); - (*add)( buffer, n, origin ); - length -= n; + else if( rc == -1 ) + { + log_error ("select() error: %s\n", strerror(errno)); + if (!delay) + delay = 1; /* Use 1 second if we encounter an error before + we have ever blocked. */ + continue; + } + + do + { + int nbytes = length < sizeof(buffer)? length : sizeof(buffer); + n = read(fd, buffer, nbytes ); + if( n >= 0 && n > nbytes ) + { + log_error("bogus read from random device (n=%d)\n", n ); + n = nbytes; + } + } + while( n == -1 && errno == EINTR ); + if ( n == -1 ) + log_fatal("read error on random device: %s\n", strerror(errno)); + (*add)( buffer, n, origin ); + length -= n; } memset(buffer, 0, sizeof(buffer) ); - + + if (any_need_entropy) + _gcry_random_progress ("need_entropy", 'X', (int)want, (int)want); + return 0; /* success */ } diff --git a/random/rndunix.c b/random/rndunix.c index 1faf9abc..9c9317d5 100644 --- a/random/rndunix.c +++ b/random/rndunix.c @@ -521,7 +521,10 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) int maxFD = 0; #endif /* OS-specific brokenness */ int bufPos, i, usefulness = 0; - + int last_so_far = 0; + int any_need_entropy = 0; + int delay; + int rc; /* Fire up each randomness source */ FD_ZERO(&fds); @@ -566,22 +569,41 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) /* Suck all the data we can get from each of the sources */ bufPos = 0; moreSources = 1; + delay = 0; /* Return immediately (well, after 100ms) the first time. */ while (moreSources && bufPos <= gather_buffer_size) { /* Wait for data to become available from any of the sources, with a * timeout of 10 seconds. This adds even more randomness since data * becomes available in a nondeterministic fashion. Kudos to HP's QA * department for managing to ship a select() which breaks its own * prototype */ - tv.tv_sec = 10; - tv.tv_usec = 0; + tv.tv_sec = delay; + tv.tv_usec = delay? 0 : 100000; #if defined( __hpux ) && ( OS_VERSION == 9 ) - if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) + rc = select(maxFD + 1, (int *)&fds, NULL, NULL, &tv); #else /* */ - if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) + rc = select(maxFD + 1, &fds, NULL, NULL, &tv); #endif /* __hpux */ - break; - + if (rc == -1) + break; /* Ooops; select failed. */ + + if (!rc) + { + /* FIXME: Because we run several tools at once it is + unlikely that we will see a block in select at all. */ + if (!any_need_entropy + || last_so_far != (gather_buffer_size - bufPos) ) + { + last_so_far = gather_buffer_size - bufPos; + _gcry_random_progress ("need_entropy", 'X', + last_so_far, + gather_buffer_size); + any_need_entropy = 1; + } + delay = 10; /* Use 10 seconds henceforth. */ + /* Note that the fd_set is setup again at the end of this loop. */ + } + /* One of the sources has data available, read it into the buffer */ for (i = 0; dataSources[i].path != NULL; i++) { if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) { @@ -661,6 +683,11 @@ slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) } } + if (any_need_entropy) + _gcry_random_progress ("need_entropy", 'X', + gather_buffer_size, + gather_buffer_size); + if( dbgfp ) { fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); fflush(dbgfp); |