diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-12-06 17:43:35 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-12-06 17:43:35 +0000 |
commit | 3eecdfe454d22c8c3904b9b14d21337af4094935 (patch) | |
tree | f4c7e44f5bbe2c49b98cbdaded28a2aed693b16c /lib | |
parent | 73f269fce8cd33d237ab27ab4af3f81e0df49635 (diff) |
In srandomdev(), if we can't access /dev/arandom, use the sysctl() instead.
We don't want to use the sysctl() by default since we are reading more
than just a few bytes of entropy when setting up the state.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/stdlib/random.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c index 5ce7c90ee9c..787581fe58b 100644 --- a/lib/libc/stdlib/random.c +++ b/lib/libc/stdlib/random.c @@ -32,10 +32,11 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: random.c,v 1.9 2000/04/04 14:27:00 millert Exp $"; +static char *rcsid = "$OpenBSD: random.c,v 1.10 2002/12/06 17:43:34 millert Exp $"; #endif /* LIBC_SCCS and not lint */ -#include <sys/types.h> +#include <sys/param.h> +#include <sys/sysctl.h> #include <sys/time.h> #include <fcntl.h> #include <stdio.h> @@ -237,7 +238,7 @@ srandom(x) void srandomdev() { - int fd; + int fd, i, mib[2], n; size_t len; if (rand_type == TYPE_0) @@ -245,19 +246,35 @@ srandomdev() else len = rand_deg * sizeof(state[0]); + /* + * To get seed data, first try reading from /dev/arandom. + * If that fails, try the KERN_ARND sysctl() (one int at a time). + * As a last resort, call srandom(). + */ if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 && read(fd, (void *) state, len) == (ssize_t) len) { close(fd); } else { - struct timeval tv; - u_int junk; - - /* XXX - this could be better */ - gettimeofday(&tv, NULL); - srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk); if (fd != -1) close(fd); - return; + mib[0] = CTL_KERN; + mib[1] = KERN_ARND; + n = len / sizeof(int); + len = sizeof(int); + for (i = 0; i < n; i++) { + if (sysctl(mib, 2, (char *)((int *)state + i), &len, + NULL, 0) == -1) + break; + } + if (i != n) { + struct timeval tv; + u_int junk; + + /* XXX - this could be better */ + gettimeofday(&tv, NULL); + srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk); + return; + } } if (rand_type != TYPE_0) { |