From 27a3d9f9aa1ca6137ffd13a23775709c6f1ef567 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Tue, 27 Jun 2006 06:31:34 +0000 Subject: [PATCH] Use poll() when possible to gather Unix randomness entropy --- CHANGES | 5 ++++ crypto/rand/rand_unix.c | 59 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 8e7cf614ff..92f912bbe3 100644 --- a/CHANGES +++ b/CHANGES @@ -1289,6 +1289,11 @@ Changes between 0.9.7j and 0.9.7k [xx XXX xxxx] + *) Change the Unix randomness entropy gathering to use poll() when + possible instead of select(), since the latter has some + undesirable limitations. + [Darryl Miles via Richard Levitte] + *) Disable rogue ciphersuites: - SSLv2 0x08 0x00 0x80 ("RC4-64-MD5") diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c index c4838b6b2e..bf0bfa76de 100644 --- a/crypto/rand/rand_unix.c +++ b/crypto/rand/rand_unix.c @@ -126,6 +126,54 @@ #include #include +#if defined(OPENSSL_SYS_LINUX) + /* lets use poll() */ +# include +# define IOWAIT_VARS struct pollfd pset; struct timeval t +# define IOWAIT_INIT(f, t) do { \ + pset.fd = (f); \ + pset.events = POLLIN; \ + pset.revents = 0; \ + (t)->tv_sec = 0; \ + (t)->tv_usec = 10*1000; \ + /* Spend 10ms on each file. */ \ + } while(0) +# define IOWAIT_FUNC(f, t) poll(&pset, 1, ((t)->tv_sec * 1000) + ((t)->tv_usec / 1000)) +# define IOWAIT_CHECK(f) ((pset.revents & POLLIN) != 0) +#else + /* lets use select() */ + + /* For each platform we could do with making a guess at + * how many FDs we support. With glibc/Linux its possible + * to use FD_SETSIZE directly, but this may not be very + * portable. Another options was to use _POSIX_OPEN_MAX + * but that value is a tad dull on modern hardware. So + * I ended up trying sizeof(fd_set)*8 which should be + * closer to the real value. + * If this causes a problem on your platform because we + * can not guess correctly then set it to zero. + */ +# if defined(FD_SETSIZE) +# define IOWAIT_FD_SETSIZE (FD_SETSIZE) +# else + /* fallback method */ +# define IOWAIT_FD_SETSIZE (sizeof(fd_set) * 8) +# endif +# define IOWAIT_VARS fd_set fset; struct timeval t +# define IOWAIT_INIT(f, t) do { \ + FD_ZERO(&fset); \ + if(IOWAIT_FD_SETSIZE > 0 \ + && (f) >= IOWAIT_FD_SETSIZE) \ + { break; } \ + FD_SET((f), &fset); \ + (t)->tv_sec = 0; \ + (t)->tv_usec = 10*1000; \ + /* Spend 10ms on each file. */ \ + } while(0) +# define IOWAIT_FUNC(f, t) select((f)+1,&fset,NULL,NULL,(t)) +# define IOWAIT_CHECK(f) FD_ISSET((f), &fset) +#endif + #ifdef __OpenBSD__ int RAND_poll(void) { @@ -185,11 +233,9 @@ int RAND_poll(void) #endif )) >= 0) { - struct timeval t = { 0, 10*1000 }; /* Spend 10ms on - each file. */ int r; unsigned int j; - fd_set fset; + IOWAIT_VARS; struct stat *st=&randomstats[i]; /* Avoid using same input... Used to be O_NOFOLLOW @@ -215,13 +261,12 @@ int RAND_poll(void) else if (r == 0) snooze(t.tv_usec); #else - FD_ZERO(&fset); - FD_SET(fd, &fset); + IOWAIT_INIT(fd, &t); r = -1; - if (select(fd+1,&fset,NULL,NULL,&t) < 0) + if (IOWAIT_FUNC(fd, &t) < 0) t.tv_usec=0; - else if (FD_ISSET(fd, &fset)) + else if (IOWAIT_CHECK(fd)) { r=read(fd,(unsigned char *)tmpbuf+n, ENTROPY_NEEDED-n); -- 2.34.1