Fix seeding from random device w/o getrandom syscall

Use select to wait for /dev/random in readable state,
but do not actually read anything from /dev/random,
use /dev/urandom first.

Use linux define __NR_getrandom instead of the
glibc define SYS_getrandom, in case the kernel headers
are more current than the glibc headers.

Fixes #8215

Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from https://github.com/openssl/openssl/pull/8251)
This commit is contained in:
Bernd Edlinger 2019-02-15 00:03:50 +01:00
parent ed86f884ba
commit 38023b87f0
2 changed files with 29 additions and 9 deletions

View File

@ -19,7 +19,7 @@
#include <stdio.h>
#include "internal/dso.h"
#if defined(__linux)
# include <sys/syscall.h>
# include <asm/unistd.h>
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
@ -324,8 +324,8 @@ static ssize_t syscall_random(void *buf, size_t buflen)
# endif
/* Linux supports this since version 3.17 */
# if defined(__linux) && defined(SYS_getrandom)
return syscall(SYS_getrandom, buf, buflen, 0);
# if defined(__linux) && defined(__NR_getrandom)
return syscall(__NR_getrandom, buf, buflen, 0);
# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
return sysctl_random(buf, buflen);
# else
@ -510,6 +510,29 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
{
size_t i;
#ifdef DEVRANDOM_WAIT
static int wait_done = 0;
/*
* On some implementations reading from /dev/urandom is possible
* before it is initialized. Therefore we wait for /dev/random
* to be readable to make sure /dev/urandom is initialized.
*/
if (!wait_done && bytes_needed > 0) {
int f = open(DEVRANDOM_WAIT, O_RDONLY);
if (f >= 0) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(f, &fds);
while (select(f+1, &fds, NULL, NULL, NULL) < 0
&& errno == EINTR);
close(f);
}
wait_done = 1;
}
#endif
for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
ssize_t bytes = 0;

9
e_os.h
View File

@ -27,11 +27,8 @@
* set this to a comma-separated list of 'random' device files to try out. By
* default, we will try to read at least one of these files
*/
# if defined(__s390__)
# define DEVRANDOM "/dev/prandom","/dev/urandom","/dev/hwrng","/dev/random"
# else
# define DEVRANDOM "/dev/urandom","/dev/random","/dev/srandom"
# endif
# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
# define DEVRANDOM_WAIT "/dev/random"
# endif
# if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD)
/*
@ -39,7 +36,7 @@
* sockets will be tried in the order listed in case accessing the device
* files listed in DEVRANDOM did not return enough randomness.
*/
# define DEVRANDOM_EGD "/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy"
# define DEVRANDOM_EGD "/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", "/etc/entropy"
# endif
# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)