summaryrefslogtreecommitdiffstats
path: root/crypto/rand/rand_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/rand/rand_unix.c')
-rw-r--r--crypto/rand/rand_unix.c292
1 files changed, 94 insertions, 198 deletions
diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c
index bfdd3e6efa..2cfd20dd50 100644
--- a/crypto/rand/rand_unix.c
+++ b/crypto/rand/rand_unix.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -9,32 +9,32 @@
#include <stdio.h>
-#define USE_SOCKETS
#include "e_os.h"
#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include "rand_lcl.h"
+#include <stdio.h>
#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI))
-# include <sys/types.h>
-# include <sys/time.h>
-# include <sys/times.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <unistd.h>
-# include <time.h>
-# if defined(OPENSSL_SYS_LINUX) /* should actually be available virtually
- * everywhere */
-# include <poll.h>
-# endif
-# include <limits.h>
-# ifndef FD_SETSIZE
-# define FD_SETSIZE (8*sizeof(fd_set))
+# if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
+ !defined(OPENSSL_RAND_SEED_NONE)
+# error "UEFI and VXWorks only support seeding NONE"
# endif
# if defined(OPENSSL_SYS_VOS)
+# ifndef OPENSSL_RAND_SEED_OS
+# error "Unsupported seeding method configured; must be os"
+# endif
+
+# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
+# error "Unsupported HP-PA and IA32 at the same time."
+# endif
+# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
+# error "Must have one of HP-PA or IA32"
+# endif
+
/*
* The following algorithm repeatedly samples the real-time clock (RTC) to
* generate a sequence of unpredictable data. The algorithm relies upon the
@@ -51,7 +51,6 @@
* As a precaution, we generate 4 times the minimum required amount of seed
* data.
*/
-
int RAND_poll(void)
{
short int code;
@@ -61,35 +60,24 @@ int RAND_poll(void)
int i, k;
struct timespec ts;
unsigned char v;
-
# ifdef OPENSSL_SYS_VOS_HPPA
long duration;
extern void s$sleep(long *_duration, short int *_code);
# else
-# ifdef OPENSSL_SYS_VOS_IA32
long long duration;
extern void s$sleep2(long long *_duration, short int *_code);
-# else
-# error "Unsupported Platform."
-# endif /* OPENSSL_SYS_VOS_IA32 */
-# endif /* OPENSSL_SYS_VOS_HPPA */
+# endif
/*
* Seed with the gid, pid, and uid, to ensure *some* variation between
* different processes.
*/
-
curr_gid = getgid();
- RAND_add(&curr_gid, sizeof curr_gid, 1);
- curr_gid = 0;
-
+ RAND_add(&curr_gid, sizeof curr_gid, 0);
curr_pid = getpid();
- RAND_add(&curr_pid, sizeof curr_pid, 1);
- curr_pid = 0;
-
+ RAND_add(&curr_pid, sizeof curr_pid, 0);
curr_uid = getuid();
- RAND_add(&curr_uid, sizeof curr_uid, 1);
- curr_uid = 0;
+ RAND_add(&curr_uid, sizeof curr_uid, 0);
for (i = 0; i < (RANDOMNESS_NEEDED * 4); i++) {
/*
@@ -104,203 +92,111 @@ int RAND_poll(void)
duration = 1;
s$sleep(&duration, &code);
# else
-# ifdef OPENSSL_SYS_VOS_IA32
/* sleep for 1/65536 of a second (15 us). */
duration = 1;
s$sleep2(&duration, &code);
-# endif /* OPENSSL_SYS_VOS_IA32 */
-# endif /* OPENSSL_SYS_VOS_HPPA */
+# endif
- /* get wall clock time. */
+ /* Get wall clock time, take 8 bits. */
clock_gettime(CLOCK_REALTIME, &ts);
-
- /* take 8 bits */
- v = (unsigned char)(ts.tv_nsec % 256);
+ v = (unsigned char)(ts.tv_nsec & 0xFF);
RAND_add(&v, sizeof v, 1);
- v = 0;
}
return 1;
}
+
# else
-int RAND_poll(void)
-{
- unsigned long l;
- pid_t curr_pid = getpid();
-# if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD))
- unsigned char tmpbuf[RANDOMNESS_NEEDED];
- int n = 0;
-# endif
-# ifdef DEVRANDOM
- static const char *randomfiles[] = { DEVRANDOM };
- struct stat randomstats[OSSL_NELEM(randomfiles)];
- int fd;
- unsigned int i;
-# endif
-# if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
- static const char *egdsockets[] = { DEVRANDOM_EGD, NULL };
- const char **egdsocket = NULL;
+
+# if defined(OPENSSL_RAND_SEED_EGD) && \
+ (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
+# error "Seeding uses EGD but EGD is turned off or no device given"
# endif
-# ifdef DEVRANDOM
- memset(randomstats, 0, sizeof(randomstats));
- /*
- * Use a randomness 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.
- */
+# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
+# error "Seeding uses urandom but DEVRANDOM is not configured"
+# endif
- for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < RANDOMNESS_NEEDED); i++) {
- 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
+# if defined(OPENSSL_RAND_SEED_OS)
+# if defined(DEVRANDOM)
+# define OPENSSL_RAND_SEED_DEVRANDOM
+# else
+# error "OS seeding requires DEVRANDOM to be configured"
# endif
- )) >= 0) {
- int usec = 10 * 1000; /* spend 10ms on each file */
- int r;
- 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; j < i; j++) {
- if (randomstats[j].st_ino == st->st_ino &&
- randomstats[j].st_dev == st->st_dev)
- break;
- }
- if (j < i) {
- close(fd);
- continue;
- }
-
- do {
- int try_read = 0;
-
-# if 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;
+# endif
-# else
- /* use select() */
- fd_set fset;
- struct timeval t;
+# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
+# error "librandom not (yet) supported"
+# endif
- t.tv_sec = 0;
- t.tv_usec = usec;
+int RAND_poll(void)
+{
+# ifdef OPENSSL_RAND_SEED_NONE
+ return 0;
+# else
+ int ok = 0;
+ char temp[RANDOMNESS_NEEDED];
+# define TEMPSIZE (int)sizeof(temp)
- if (FD_SETSIZE > 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);
+# ifdef OPENSSL_RAND_SEED_RDTSC
+ rand_rdtsc();
+# endif
- if (select(fd + 1, &fset, NULL, NULL, &t) >= 0) {
- usec = t.tv_usec;
- if (FD_ISSET(fd, &fset))
- try_read = 1;
- } else
- usec = 0;
- }
+# ifdef OPENSSL_RAND_SEED_RDCPU
+ if (rand_rdcpu())
+ ok++;
# endif
- if (try_read) {
- r = read(fd, (unsigned char *)tmpbuf + n,
- RANDOMNESS_NEEDED - n);
- if (r > 0)
- n += r;
- } else
- r = -1;
+# ifdef OPENSSL_RAND_SEED_EGD
+ {
+ static const char *paths[] = { DEVRANDOM_EGD, NULL };
+ int i;
- /*
- * 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 (usec == 10 * 1000)
- usec = 0;
+ for (i = 0; paths[i] != NULL; i++) {
+ if (RAND_query_egd_bytes(paths[i], temp, TEMPSIZE) == TEMPSIZE) {
+ RAND_add(temp, TEMPSIZE, TEMPSIZE);
+ ok++;
+ break;
}
- while ((r > 0 ||
- (errno == EINTR || errno == EAGAIN)) && usec != 0
- && n < RANDOMNESS_NEEDED);
-
- close(fd);
}
}
-# endif /* defined(DEVRANDOM) */
-
-# if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
- /*
- * Use an EGD socket to read randomness from the daemon.
- */
-
- for (egdsocket = egdsockets; *egdsocket && n < RANDOMNESS_NEEDED;
- egdsocket++) {
- int r;
+# endif
- r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n,
- RANDOMNESS_NEEDED - n);
- if (r > 0)
- n += r;
- }
-# endif /* defined(DEVRANDOM_EGD) */
+# ifdef OPENSSL_RAND_SEED_DEVRANDOM
+ {
+ static const char *paths[] = { DEVRANDOM, NULL };
+ FILE *fp;
+ int i;
-# if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
- if (n > 0) {
- RAND_add(tmpbuf, sizeof tmpbuf, (double)n);
- OPENSSL_cleanse(tmpbuf, n);
+ for (i = 0; paths[i] != NULL; i++) {
+ if ((fp = fopen(paths[i], "rb")) == NULL)
+ continue;
+ setbuf(fp, NULL);
+ if (fread(temp, 1, TEMPSIZE, fp) == TEMPSIZE) {
+ RAND_add(temp, TEMPSIZE, TEMPSIZE);
+ ok++;
+ fclose(fp);
+ break;
+ }
+ }
}
-# endif
+# endif
- /* put in some default random data, we need more than just this */
- l = curr_pid;
- RAND_add(&l, sizeof(l), 0.0);
- l = getuid();
- RAND_add(&l, sizeof(l), 0.0);
+# ifdef OPENSSL_RAND_SEED_GETRANDOM
+ {
+ int i = getrandom(temp, TEMPSIZE, 0);
- l = time(NULL);
- RAND_add(&l, sizeof(l), 0.0);
+ if (i >= 0) {
+ RAND_add(temp, i, i);
+ if (i == TEMPSIZE)
+ ok++;
+ }
+ }
+# endif
-# if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
- return 1;
-# else
- return 0;
+ OPENSSL_cleanse(temp, TEMPSIZE);
+ return ok > 0 ? 1 : 0;
# endif
}
+# endif
-# endif /* defined(__OpenBSD__) */
-#endif /* !(defined(OPENSSL_SYS_WINDOWS) ||
- * defined(OPENSSL_SYS_WIN32) ||
- * defined(OPENSSL_SYS_VMS) ||
- * defined(OPENSSL_SYS_VXWORKS) */
-
-#if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
-int RAND_poll(void)
-{
- return 0;
-}
#endif