--- openbsd_arc4random.c 2011-11-13 18:47:17.000000000 -0500 +++ arc4random.c 2011-11-13 19:15:16.000000000 -0500 @@ -29,6 +29,10 @@ * RC4 is a registered trademark of RSA Laboratories. */ +#include +__FBSDID("$FreeBSD: head/lib/libc/gen/arc4random.c 182886 2008-09-09 09:46:36Z ache $"); + +#include "namespace.h" #include #include #include @@ -36,8 +40,10 @@ #include #include #include -#include -#include "thread_private.h" +#include + +#include "libc_private.h" +#include "un-namespace.h" #ifdef __GNUC__ #define inline __inline @@ -51,12 +57,28 @@ u_int8_t s[256]; }; +static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; + +#define RANDOMDEV "/dev/random" +#define _ARC4_LOCK() \ + do { \ + if (__isthreaded) \ + _pthread_mutex_lock(&arc4random_mtx); \ + } while (0) + +#define _ARC4_UNLOCK() \ + do { \ + if (__isthreaded) \ + _pthread_mutex_unlock(&arc4random_mtx); \ + } while (0) + static int rs_initialized; static struct arc4_stream rs; static pid_t arc4_stir_pid; static int arc4_count; static inline u_int8_t arc4_getbyte(void); +static void arc4_stir(void); static inline void arc4_init(void) @@ -89,28 +111,41 @@ static void arc4_stir(void) { - int i, mib[2]; - size_t len; - u_char rnd[128]; + int done, fd, i; + struct { + struct timeval tv; + pid_t pid; + u_char rnd[128]; + } rdat; if (!rs_initialized) { arc4_init(); rs_initialized = 1; } + fd = _open(RANDOMDEV, O_RDONLY, 0); + done = 0; + if (fd >= 0) { + if (_read(fd, &rdat.rnd, sizeof(rdat.rnd)) == sizeof(rdat.rnd)) + done = 1; + (void)_close(fd); + } + if (!done) { + /* + * XXX This is a highly effective way to provide a false + * sense of security. + */ + (void)gettimeofday(&rdat.tv, NULL); + rdat.pid = getpid(); + /* We'll just take whatever was on the stack too... */ + } - mib[0] = CTL_KERN; - mib[1] = KERN_ARND; - - len = sizeof(rnd); - sysctl(mib, 2, rnd, &len, NULL, 0); - - arc4_addrandom(rnd, sizeof(rnd)); + arc4_addrandom((u_char *)&rdat, sizeof(rdat)); /* * Discard early keystream, as per recommendations in: - * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + * "(Not So) Random Shuffles of RC4" by Ilya Mironov. */ - for (i = 0; i < 256; i++) + for (i = 0; i < 1024; i++) (void)arc4_getbyte(); arc4_count = 1600000; }