提交 14879629 编写于 作者: K Kurt Roeckx

Add support for getrandom() or equivalent system calls and use them by default

Reviewed-by: NDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
GH: #5910
上级 0e0f8116
...@@ -224,7 +224,8 @@ ...@@ -224,7 +224,8 @@
os: Use a trusted operating system entropy source. os: Use a trusted operating system entropy source.
This is the default method if such an entropy This is the default method if such an entropy
source exists. source exists.
getrandom: Use the L<getrandom(2)> system call if available. getrandom: Use the L<getrandom(2)> or equivalent system
call.
devrandom: Use the the first device from the DEVRANDOM list devrandom: Use the the first device from the DEVRANDOM list
which can be opened to read random bytes. The which can be opened to read random bytes. The
DEVRANDOM preprocessor constant expands to DEVRANDOM preprocessor constant expands to
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* https://www.openssl.org/source/license.html * https://www.openssl.org/source/license.html
*/ */
#define _GNU_SOURCE
#include "e_os.h" #include "e_os.h"
#include <stdio.h> #include <stdio.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
...@@ -14,6 +15,17 @@ ...@@ -14,6 +15,17 @@
#include "rand_lcl.h" #include "rand_lcl.h"
#include "internal/rand_int.h" #include "internal/rand_int.h"
#include <stdio.h> #include <stdio.h>
#if defined(__linux)
# include <sys/syscall.h>
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
# include <sys/sysctl.h>
# include <sys/param.h>
#endif
#if defined(__OpenBSD__)
# include <sys/param.h>
#endif
#ifdef OPENSSL_SYS_UNIX #ifdef OPENSSL_SYS_UNIX
# include <sys/types.h> # include <sys/types.h>
# include <unistd.h> # include <unistd.h>
...@@ -59,6 +71,8 @@ static uint64_t get_timer_bits(void); ...@@ -59,6 +71,8 @@ static uint64_t get_timer_bits(void);
# endif # endif
#endif #endif
int syscall_random(void *buf, size_t buflen);
#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \ #if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
!defined(OPENSSL_RAND_SEED_NONE) !defined(OPENSSL_RAND_SEED_NONE)
# error "UEFI and VXWorks only support seeding NONE" # error "UEFI and VXWorks only support seeding NONE"
...@@ -149,26 +163,93 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool) ...@@ -149,26 +163,93 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
# error "Seeding uses urandom but DEVRANDOM is not configured" # error "Seeding uses urandom but DEVRANDOM is not configured"
# endif # endif
# if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 25)
# define OPENSSL_HAVE_GETRANDOM
# endif
# endif
# if (defined(__FreeBSD__) && __FreeBSD_version >= 1200061)
# define OPENSSL_HAVE_GETRANDOM
# endif
# if defined(OPENSSL_HAVE_GETRANDOM)
# include <sys/random.h>
# endif
# if defined(OPENSSL_RAND_SEED_OS) # if defined(OPENSSL_RAND_SEED_OS)
# if !defined(DEVRANDOM) # if !defined(DEVRANDOM)
# error "OS seeding requires DEVRANDOM to be configured" # error "OS seeding requires DEVRANDOM to be configured"
# endif # endif
# define OPENSSL_RAND_SEED_GETRANDOM
# define OPENSSL_RAND_SEED_DEVRANDOM # define OPENSSL_RAND_SEED_DEVRANDOM
# if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 25)
# define OPENSSL_RAND_SEED_GETRANDOM
# endif
# endif
# endif
# ifdef OPENSSL_RAND_SEED_GETRANDOM
# include <sys/random.h>
# endif # endif
# if defined(OPENSSL_RAND_SEED_LIBRANDOM) # if defined(OPENSSL_RAND_SEED_LIBRANDOM)
# error "librandom not (yet) supported" # error "librandom not (yet) supported"
# endif # endif
# if defined(__FreeBSD__) && defined(KERN_ARND)
/*
* sysctl_random(): Use sysctl() to read a random number from the kernel
* Returns the size on success, 0 on failure.
*/
static size_t sysctl_random(char *buf, size_t buflen)
{
int mib[2];
size_t done = 0;
size_t len;
/*
* Old implementations returned longs, newer versions support variable
* sizes up to 256 byte. The code below would not work properly when
* the sysctl returns long and we want to request something not a multiple
* of longs, which should never be the case.
*/
ossl_assert(buflen % sizeof(long) == 0);
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
do {
len = buflen;
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return done;
done += len;
buf += len;
buflen -= len;
} while (buflen > 0);
return done;
}
# endif
/*
* syscall_random(): Try to get random data using a system call
* returns the number of bytes returned in buf, or <= 0 on error.
*/
int syscall_random(void *buf, size_t buflen)
{
# if defined(OPENSSL_HAVE_GETRANDOM)
return (int)getrandom(buf, buflen, 0);
# endif
# if defined(__linux) && defined(SYS_getrandom)
return (int)syscall(SYS_getrandom, buf, buflen, 0);
# endif
# if defined(__FreeBSD__) && defined(KERN_ARND)
return (int)sysctl_random(buf, buflen);
# endif
/* Supported since OpenBSD 5.6 */
# if defined(__OpenBSD__) && OpenBSD >= 201411
return getentropy(buf, buflen);
# endif
return -1;
}
/* /*
* Try the various seeding methods in turn, exit when successful. * Try the various seeding methods in turn, exit when successful.
* *
...@@ -201,7 +282,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool) ...@@ -201,7 +282,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
if (buffer != NULL) { if (buffer != NULL) {
size_t bytes = 0; size_t bytes = 0;
if (getrandom(buffer, bytes_needed, 0) == (int)bytes_needed) if (syscall_random(buffer, bytes_needed) == (int)bytes_needed)
bytes = bytes_needed; bytes = bytes_needed;
rand_pool_add_end(pool, bytes, 8 * bytes); rand_pool_add_end(pool, bytes, 8 * bytes);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册