mirror of
https://github.com/jedisct1/libsodium.git
synced 2024-12-19 10:05:05 -07:00
Use getentropy(2) if available, cleanup salsa20/randombytes by the way
This commit is contained in:
parent
9c6ee44d93
commit
0ea9a8f0e9
@ -539,7 +539,7 @@ AC_SUBST(CFLAGS_AESNI)
|
||||
AC_SUBST(CFLAGS_PCLMUL)
|
||||
AC_SUBST(CFLAGS_RDRAND)
|
||||
|
||||
AC_CHECK_HEADERS([sys/mman.h intrin.h])
|
||||
AC_CHECK_HEADERS([sys/mman.h sys/random.h intrin.h])
|
||||
|
||||
AC_MSG_CHECKING([if _xgetbv() is available])
|
||||
AC_LINK_IFELSE(
|
||||
@ -779,11 +779,11 @@ dnl Checks for functions and headers
|
||||
|
||||
AC_FUNC_ALLOCA
|
||||
AS_IF([test "x$EMSCRIPTEN" = "x"],[
|
||||
AC_CHECK_FUNCS([arc4random arc4random_buf])
|
||||
AC_CHECK_FUNCS([arc4random arc4random_buf getentropy])
|
||||
AC_CHECK_FUNCS([mmap mlock madvise mprotect])
|
||||
])
|
||||
AC_CHECK_FUNCS([posix_memalign getpid getentropy memset_s explicit_bzero
|
||||
explicit_memset nanosleep])
|
||||
AC_CHECK_FUNCS([posix_memalign getpid nanosleep])
|
||||
AC_CHECK_FUNCS([memset_s explicit_bzero explicit_memset])
|
||||
|
||||
AC_SUBST([LIBTOOL_EXTRA_FLAGS])
|
||||
|
||||
|
@ -13,9 +13,10 @@
|
||||
#include "core.h"
|
||||
#include "crypto_stream_chacha20.h"
|
||||
#include "randombytes.h"
|
||||
#ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION
|
||||
# include "randombytes_default.h"
|
||||
#else
|
||||
#ifndef RANDOMBYTES_CUSTOM_IMPLEMENTATION
|
||||
# ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION
|
||||
# include "randombytes_salsa20.h"
|
||||
# endif
|
||||
# include "randombytes_sysrandom.h"
|
||||
#endif
|
||||
#include "private/common.h"
|
||||
|
@ -31,10 +31,12 @@
|
||||
#elif defined(__FreeBSD__)
|
||||
# include <sys/param.h>
|
||||
# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000
|
||||
# include <sys/random.h>
|
||||
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
|
||||
# endif
|
||||
#endif
|
||||
#ifdef HAVE_SYS_RANDOM_H
|
||||
# include <sys/random.h>
|
||||
#endif
|
||||
#if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__)
|
||||
# define BLOCK_ON_DEV_RANDOM
|
||||
#endif
|
||||
@ -75,6 +77,9 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
||||
#if defined(__OpenBSD__) || defined(__CloudABI__)
|
||||
# define HAVE_SAFE_ARC4RANDOM 1
|
||||
#endif
|
||||
#if defined(__CloudABI__) || defined(__wasm__)
|
||||
# define NONEXISTENT_DEV_RANDOM 1
|
||||
#endif
|
||||
|
||||
#ifndef SSIZE_MAX
|
||||
# define SSIZE_MAX (SIZE_MAX / 2 - 1)
|
||||
@ -98,6 +103,7 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
||||
typedef struct Salsa20RandomGlobal_ {
|
||||
int initialized;
|
||||
int random_data_source_fd;
|
||||
int getentropy_available;
|
||||
int getrandom_available;
|
||||
int rdrand_available;
|
||||
#ifdef HAVE_GETPID
|
||||
@ -152,7 +158,7 @@ sodium_hrtime(void)
|
||||
}
|
||||
return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec;
|
||||
}
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*
|
||||
* Initialize the entropy source
|
||||
@ -168,100 +174,43 @@ randombytes_salsa20_random_init(void)
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
static ssize_t
|
||||
safe_read(const int fd, void * const buf_, size_t size)
|
||||
# ifdef HAVE_GETENTROPY
|
||||
static int
|
||||
_randombytes_getentropy(void * const buf, const size_t size)
|
||||
{
|
||||
int readnb;
|
||||
|
||||
assert(size <= 256U);
|
||||
do {
|
||||
readnb = getentropy(buf, size);
|
||||
} while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
return (readnb == (int) size) - 1;
|
||||
}
|
||||
|
||||
static int
|
||||
randombytes_getentropy(void * const buf_, size_t size)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *) buf_;
|
||||
ssize_t readnb;
|
||||
size_t chunk_size = 256U;
|
||||
|
||||
assert(size > (size_t) 0U);
|
||||
assert(size <= SSIZE_MAX);
|
||||
do {
|
||||
while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
|
||||
(errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
|
||||
if (readnb < (ssize_t) 0) {
|
||||
return readnb; /* LCOV_EXCL_LINE */
|
||||
if (size < chunk_size) {
|
||||
chunk_size = size;
|
||||
assert(chunk_size > (size_t) 0U);
|
||||
}
|
||||
if (readnb == (ssize_t) 0) {
|
||||
break; /* LCOV_EXCL_LINE */
|
||||
if (_randombytes_getentropy(buf, chunk_size) != 0) {
|
||||
return -1;
|
||||
}
|
||||
size -= (size_t) readnb;
|
||||
buf += readnb;
|
||||
} while (size > (ssize_t) 0);
|
||||
size -= chunk_size;
|
||||
buf += chunk_size;
|
||||
} while (size > (size_t) 0U);
|
||||
|
||||
return (ssize_t) (buf - (unsigned char *) buf_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# ifdef BLOCK_ON_DEV_RANDOM
|
||||
static int
|
||||
randombytes_block_on_dev_random(void)
|
||||
{
|
||||
struct pollfd pfd;
|
||||
int fd;
|
||||
int pret;
|
||||
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||
|
||||
fd = open("/dev/random", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
do {
|
||||
pret = poll(&pfd, 1, -1);
|
||||
} while (pret < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
if (pret != 1) {
|
||||
(void) close(fd);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return close(fd);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_SAFE_ARC4RANDOM
|
||||
static int
|
||||
randombytes_salsa20_random_random_dev_open(void)
|
||||
{
|
||||
/* LCOV_EXCL_START */
|
||||
struct stat st;
|
||||
static const char *devices[] = {
|
||||
# ifndef USE_BLOCKING_RANDOM
|
||||
"/dev/urandom",
|
||||
# endif
|
||||
"/dev/random", NULL
|
||||
};
|
||||
const char **device = devices;
|
||||
int fd;
|
||||
|
||||
# ifdef BLOCK_ON_DEV_RANDOM
|
||||
if (randombytes_block_on_dev_random() != 0) {
|
||||
return -1;
|
||||
}
|
||||
# endif
|
||||
do {
|
||||
fd = open(*device, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
if (fstat(fd, &st) == 0 && (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))) {
|
||||
# if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
# endif
|
||||
return fd;
|
||||
}
|
||||
(void) close(fd);
|
||||
} else if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
device++;
|
||||
} while (*device != NULL);
|
||||
|
||||
errno = EIO;
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
|
||||
static int
|
||||
_randombytes_linux_getrandom(void * const buf, const size_t size)
|
||||
{
|
||||
@ -297,18 +246,120 @@ randombytes_linux_getrandom(void * const buf_, size_t size)
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef NONEXISTENT_DEV_RANDOM
|
||||
static int
|
||||
randombytes_salsa20_random_random_dev_open(void)
|
||||
{
|
||||
/* LCOV_EXCL_START */
|
||||
struct stat st;
|
||||
static const char *devices[] = {
|
||||
# ifndef USE_BLOCKING_RANDOM
|
||||
"/dev/urandom",
|
||||
# endif
|
||||
"/dev/random", NULL
|
||||
};
|
||||
const char **device = devices;
|
||||
int fd;
|
||||
|
||||
# ifdef BLOCK_ON_DEV_RANDOM
|
||||
if (randombytes_block_on_dev_random() != 0) {
|
||||
return -1;
|
||||
}
|
||||
# endif
|
||||
do {
|
||||
fd = open(*device, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
if (fstat(fd, &st) == 0 && (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))) {
|
||||
# if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
# endif
|
||||
return fd;
|
||||
}
|
||||
(void) close(fd);
|
||||
} else if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
device++;
|
||||
} while (*device != NULL);
|
||||
|
||||
errno = EIO;
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
safe_read(const int fd, void * const buf_, size_t size)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *) buf_;
|
||||
ssize_t readnb;
|
||||
|
||||
assert(size > (size_t) 0U);
|
||||
assert(size <= SSIZE_MAX);
|
||||
do {
|
||||
while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
|
||||
(errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
|
||||
if (readnb < (ssize_t) 0) {
|
||||
return readnb; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (readnb == (ssize_t) 0) {
|
||||
break; /* LCOV_EXCL_LINE */
|
||||
}
|
||||
size -= (size_t) readnb;
|
||||
buf += readnb;
|
||||
} while (size > (ssize_t) 0);
|
||||
|
||||
return (ssize_t) (buf - (unsigned char *) buf_);
|
||||
}
|
||||
|
||||
# ifdef BLOCK_ON_DEV_RANDOM
|
||||
static int
|
||||
randombytes_block_on_dev_random(void)
|
||||
{
|
||||
struct pollfd pfd;
|
||||
int fd;
|
||||
int pret;
|
||||
|
||||
fd = open("/dev/random", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
do {
|
||||
pret = poll(&pfd, 1, -1);
|
||||
} while (pret < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
if (pret != 1) {
|
||||
(void) close(fd);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return close(fd);
|
||||
}
|
||||
# endif
|
||||
|
||||
# endif /* !NONEXISTENT_DEV_RANDOM */
|
||||
|
||||
static void
|
||||
randombytes_salsa20_random_init(void)
|
||||
{
|
||||
const int errno_save = errno;
|
||||
|
||||
global.rdrand_available = sodium_runtime_has_rdrand();
|
||||
global.getentropy_available = 0;
|
||||
global.getrandom_available = 0;
|
||||
|
||||
# ifdef HAVE_SAFE_ARC4RANDOM
|
||||
errno = errno_save;
|
||||
# else
|
||||
# ifdef HAVE_GETENTROPY
|
||||
{
|
||||
unsigned char fodder[16];
|
||||
|
||||
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
|
||||
if (randombytes_getentropy(fodder, sizeof fodder) == 0) {
|
||||
global.getentropy_available = 1;
|
||||
errno = errno_save;
|
||||
return;
|
||||
}
|
||||
}
|
||||
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||
{
|
||||
unsigned char fodder[16];
|
||||
|
||||
@ -317,16 +368,18 @@ randombytes_salsa20_random_init(void)
|
||||
errno = errno_save;
|
||||
return;
|
||||
}
|
||||
global.getrandom_available = 0;
|
||||
}
|
||||
# endif /* HAVE_LINUX_COMPATIBLE_GETRANDOM */
|
||||
|
||||
# elif !defined(NONEXISTENT_DEV_RANDOM)
|
||||
assert((global.getentropy_available | global.getrandom_available) == 0);
|
||||
if ((global.random_data_source_fd =
|
||||
randombytes_salsa20_random_random_dev_open()) == -1) {
|
||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
# elif !defined(HAVE_SAFE_ARC4RANDOM)
|
||||
sodium_misuse();
|
||||
# endif
|
||||
|
||||
errno = errno_save;
|
||||
# endif /* HAVE_SAFE_ARC4RANDOM */
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
@ -352,18 +405,20 @@ randombytes_salsa20_random_stir(void)
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
# ifdef HAVE_SAFE_ARC4RANDOM
|
||||
arc4random_buf(stream.key, sizeof stream.key);
|
||||
# ifdef HAVE_GETENTROPY
|
||||
if (global.getentropy_available != 0) {
|
||||
if (randombytes_getentropy(stream.key, sizeof stream.key) != 0) {
|
||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
}
|
||||
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||
if (global.getrandom_available != 0) {
|
||||
if (randombytes_linux_getrandom(stream.key, sizeof stream.key) != 0) {
|
||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
} else if (global.random_data_source_fd == -1 ||
|
||||
safe_read(global.random_data_source_fd, stream.key,
|
||||
sizeof stream.key) != (ssize_t) sizeof stream.key) {
|
||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
if (global.getrandom_available != 0) {
|
||||
if (randombytes_getrandom(stream.key, sizeof stream.key) != 0) {
|
||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
}
|
||||
# elif !defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
|
||||
arc4random_buf(stream.key, sizeof stream.key);
|
||||
# else
|
||||
if (global.random_data_source_fd == -1 ||
|
||||
safe_read(global.random_data_source_fd, stream.key,
|
||||
@ -425,6 +480,17 @@ randombytes_salsa20_random_close(void)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
# ifdef HAVE_GETENTROPY
|
||||
if (global.getentropy_available != 0) {
|
||||
ret = 0;
|
||||
}
|
||||
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||
if (global.getrandom_available != 0) {
|
||||
ret = 0;
|
||||
}
|
||||
# elif !defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
|
||||
ret = 0;
|
||||
# else
|
||||
if (global.random_data_source_fd != -1 &&
|
||||
close(global.random_data_source_fd) == 0) {
|
||||
global.random_data_source_fd = -1;
|
||||
@ -434,15 +500,6 @@ randombytes_salsa20_random_close(void)
|
||||
# endif
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
# ifdef HAVE_SAFE_ARC4RANDOM
|
||||
ret = 0;
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
|
||||
if (global.getrandom_available != 0) {
|
||||
ret = 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
sodium_memzero(&stream, sizeof stream);
|
||||
|
@ -105,7 +105,7 @@ randombytes_sysrandom_close(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __OpenBSD__ */
|
||||
#else /* HAVE_SAFE_ARC4RANDOM */
|
||||
|
||||
typedef struct SysRandom_ {
|
||||
int random_data_source_fd;
|
||||
|
Loading…
Reference in New Issue
Block a user