X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Frand%2Frand_unix.c;h=e9ead3a529688fd2c49a95b6871240d24ac6d70d;hb=7cc684f4f7fbcdc5cf4683eaf025d4f915acbf3c;hp=bf0bfa76deaf17ef1bb7f80e6a9fa08a4f7f34c8;hpb=27a3d9f9aa1ca6137ffd13a23775709c6f1ef567;p=oweals%2Fopenssl.git diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c index bf0bfa76de..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 @@ -116,7 +116,7 @@ #include #include "rand_lcl.h" -#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)) +#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 @@ -125,56 +125,58 @@ #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 -#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() */ +#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; - /* 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 +/* 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)); -#ifdef __OpenBSD__ + return 1; +} +#elif defined __OpenBSD__ int RAND_poll(void) { u_int32_t rnd = 0, i; @@ -191,7 +193,7 @@ int RAND_poll(void) return 1; } -#else +#else /* !defined(__OpenBSD__) */ int RAND_poll(void) { unsigned long l; @@ -233,9 +235,9 @@ int RAND_poll(void) #endif )) >= 0) { + int usec = 10*1000; /* spend 10ms on each file */ int r; unsigned int j; - IOWAIT_VARS; struct stat *st=&randomstats[i]; /* Avoid using same input... Used to be O_NOFOLLOW @@ -251,44 +253,84 @@ int RAND_poll(void) do { + int try_read = 0; + #if defined(OPENSSL_SYS_BEOS_R5) - /* select() is broken in BeOS R5, so we simply - * try to read something and snooze if we couldn't: */ - r=read(fd,(unsigned char *)tmpbuf+n, - ENTROPY_NEEDED-n); - if (r > 0) - n += r; - else if (r == 0) - snooze(t.tv_usec); + /* select() is broken in BeOS R5, so we simply + * try to read something and snooze if we couldn't */ + try_read = 1; + +#elif defined(OPENSSL_SYS_LINUX) + /* use poll() */ + struct pollfd pset; + + pset.fd = fd; + pset.events = POLLIN; + pset.revents = 0; + + if (poll(&pset, 1, usec / 1000) < 0) + usec = 0; + else + try_read = (pset.revents & POLLIN) != 0; + #else - IOWAIT_INIT(fd, &t); - r = -1; + /* use select() */ + fd_set fset; + struct timeval t; + + t.tv_sec = 0; + t.tv_usec = usec; - if (IOWAIT_FUNC(fd, &t) < 0) - t.tv_usec=0; - else if (IOWAIT_CHECK(fd)) + if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE) { - r=read(fd,(unsigned char *)tmpbuf+n, - ENTROPY_NEEDED-n); + /* 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); 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); } } -#endif +#endif /* defined(DEVRANDOM) */ #ifdef DEVRANDOM_EGD /* Use an EGD socket to read entropy from an EGD or PRNGD entropy @@ -303,7 +345,7 @@ int RAND_poll(void) if (r > 0) n += r; } -#endif +#endif /* defined(DEVRANDOM_EGD) */ #if defined(DEVRANDOM) || defined(DEVRANDOM_EGD) if (n > 0) @@ -337,12 +379,13 @@ int RAND_poll(void) #endif } -#endif -#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; -} + { + return 0; + } #endif