X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Frand%2Frand_unix.c;h=e9ead3a529688fd2c49a95b6871240d24ac6d70d;hb=32cf5baeae21774db04af2ad2d74567a617c6fec;hp=c4aae38f1d998cb2798de1f4963a176c35f605f9;hpb=0c61e299b35a0789d5de7c1972b15a82dff2f122;p=oweals%2Fopenssl.git diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c index c4aae38f1d..e9ead3a529 100644 --- a/crypto/rand/rand_unix.c +++ b/crypto/rand/rand_unix.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -108,100 +108,284 @@ * Hudson (tjh@cryptsoft.com). * */ +#include +#define USE_SOCKETS +#include "e_os.h" #include "cryptlib.h" #include #include "rand_lcl.h" -#if !(defined(WINDOWS) || defined(WIN32) || defined(VMS)) +#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE)) #include #include #include +#include #include #include +#include +#if defined(OPENSSL_SYS_LINUX) /* should actually be available virtually everywhere */ +# include +#endif +#include +#ifndef FD_SETSIZE +# define FD_SETSIZE (8*sizeof(fd_set)) +#endif + +#ifdef __VOS__ +int RAND_poll(void) +{ + unsigned char buf[ENTROPY_NEEDED]; + pid_t curr_pid; + uid_t curr_uid; + static int first=1; + int i; + long rnd = 0; + struct timespec ts; + unsigned seed; + +/* The VOS random() function starts from a static seed so its + initial value is predictable. If random() returns the + initial value, reseed it with dynamic data. The VOS + real-time clock has a granularity of 1 nsec so it should be + reasonably difficult to predict its exact value. Do not + gratuitously reseed the PRNG because other code in this + process or thread may be using it. */ + + if (first) { + first = 0; + rnd = random (); + if (rnd == 1804289383) { + clock_gettime (CLOCK_REALTIME, &ts); + curr_pid = getpid(); + curr_uid = getuid(); + seed = ts.tv_sec ^ ts.tv_nsec ^ curr_pid ^ curr_uid; + srandom (seed); + } + } + + for (i = 0; i < sizeof(buf); i++) { + if (i % 4 == 0) + rnd = random(); + buf[i] = rnd; + rnd >>= 8; + } + RAND_add(buf, sizeof(buf), ENTROPY_NEEDED); + memset(buf, 0, sizeof(buf)); + + return 1; +} +#elif defined __OpenBSD__ +int RAND_poll(void) +{ + u_int32_t rnd = 0, i; + unsigned char buf[ENTROPY_NEEDED]; + for (i = 0; i < sizeof(buf); i++) { + if (i % 4 == 0) + rnd = arc4random(); + buf[i] = rnd; + rnd >>= 8; + } + RAND_add(buf, sizeof(buf), ENTROPY_NEEDED); + memset(buf, 0, sizeof(buf)); + + return 1; +} +#else /* !defined(__OpenBSD__) */ int RAND_poll(void) { unsigned long l; pid_t curr_pid = getpid(); -#ifdef DEVRANDOM +#if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) unsigned char tmpbuf[ENTROPY_NEEDED]; int n = 0; - static const char *randomfiles[] = { DEVRANDOM, NULL }; - const char **randomfile = NULL; +#endif +#ifdef DEVRANDOM + static const char *randomfiles[] = { DEVRANDOM }; + struct stat randomstats[sizeof(randomfiles)/sizeof(randomfiles[0])]; int fd; + unsigned int i; +#endif +#ifdef DEVRANDOM_EGD + static const char *egdsockets[] = { DEVRANDOM_EGD, NULL }; + const char **egdsocket = NULL; #endif #ifdef DEVRANDOM + memset(randomstats,0,sizeof(randomstats)); /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD * have this. Use /dev/urandom if you can as /dev/random may block * if it runs out of random entries. */ - for (randomfile = randomfiles; *randomfile && n < ENTROPY_NEEDED; randomfile++) + for (i = 0; (i < sizeof(randomfiles)/sizeof(randomfiles[0])) && + (n < ENTROPY_NEEDED); i++) { - if ((fd = open(*randomfile, O_RDONLY|O_NONBLOCK + if ((fd = open(randomfiles[i], O_RDONLY +#ifdef O_NONBLOCK + |O_NONBLOCK +#endif +#ifdef O_BINARY + |O_BINARY +#endif #ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do not make it our controlling tty */ |O_NOCTTY -#endif -#ifdef O_NOFOLLOW /* Fail if the file is a symbolic link */ - |O_NOFOLLOW #endif )) >= 0) { - struct timeval t = { 0, 10*1000 }; /* Spend 10ms on - each file. */ + int usec = 10*1000; /* spend 10ms on each file */ int r; - fd_set fset; + unsigned int j; + struct stat *st=&randomstats[i]; + + /* Avoid using same input... Used to be O_NOFOLLOW + * above, but it's not universally appropriate... */ + if (fstat(fd,st) != 0) { close(fd); continue; } + for (j=0;jst_ino && + randomstats[j].st_dev==st->st_dev) + break; + } + if (j 0 && (unsigned)fd >= FD_SETSIZE) + { + /* can't use select, so just try to read once anyway */ + try_read = 1; + } + else + { + FD_ZERO(&fset); + FD_SET(fd, &fset); + + if (select(fd+1,&fset,NULL,NULL,&t) >= 0) + { + usec = t.tv_usec; + if (FD_ISSET(fd, &fset)) + try_read = 1; + } + else + usec = 0; + } +#endif + + if (try_read) { - r=read(fd,(unsigned char *)tmpbuf+n, - ENTROPY_NEEDED-n); + r = read(fd,(unsigned char *)tmpbuf+n, ENTROPY_NEEDED-n); if (r > 0) n += r; +#if defined(OPENSSL_SYS_BEOS_R5) + if (r == 0) + snooze(t.tv_usec); +#endif } - - /* Some Unixen will update t, some - won't. For those who won't, give - up here, otherwise, we will do + else + r = -1; + + /* Some Unixen will update t in select(), some + won't. For those who won't, or if we + didn't use select() in the first place, + give up here, otherwise, we will do this once again for the remaining time. */ - if (t.tv_usec == 10*1000) - t.tv_usec=0; + if (usec == 10*1000) + usec = 0; } - while ((r > 0 || (errno == EINTR || errno == EAGAIN)) - && t.tv_usec != 0 && n < ENTROPY_NEEDED); + while ((r > 0 || + (errno == EINTR || errno == EAGAIN)) && usec != 0 && n < ENTROPY_NEEDED); close(fd); - RAND_add(tmpbuf,sizeof tmpbuf,n); - memset(tmpbuf,0,n); } } +#endif /* defined(DEVRANDOM) */ + +#ifdef DEVRANDOM_EGD + /* Use an EGD socket to read entropy from an EGD or PRNGD entropy + * collecting daemon. */ + + for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED; egdsocket++) + { + int r; + + r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf+n, + ENTROPY_NEEDED-n); + if (r > 0) + n += r; + } +#endif /* defined(DEVRANDOM_EGD) */ + +#if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) + if (n > 0) + { + RAND_add(tmpbuf,sizeof tmpbuf,(double)n); + OPENSSL_cleanse(tmpbuf,n); + } #endif /* put in some default random data, we need more than just this */ l=curr_pid; - RAND_add(&l,sizeof(l),0); + RAND_add(&l,sizeof(l),0.0); l=getuid(); - RAND_add(&l,sizeof(l),0); + RAND_add(&l,sizeof(l),0.0); l=time(NULL); - RAND_add(&l,sizeof(l),0); + RAND_add(&l,sizeof(l),0.0); -#ifdef DEVRANDOM - return 1; +#if defined(OPENSSL_SYS_BEOS) + { + system_info sysInfo; + get_system_info(&sysInfo); + RAND_add(&sysInfo,sizeof(sysInfo),0); + } #endif + +#if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) + return 1; +#else return 0; +#endif } +#endif /* defined(__OpenBSD__) */ +#endif /* !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE)) */ + + +#if defined(OPENSSL_SYS_VXWORKS) +int RAND_poll(void) + { + return 0; + } #endif