mirror of
https://github.com/jedisct1/libsodium.git
synced 2024-12-24 12:36:01 -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_PCLMUL)
|
||||||
AC_SUBST(CFLAGS_RDRAND)
|
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_MSG_CHECKING([if _xgetbv() is available])
|
||||||
AC_LINK_IFELSE(
|
AC_LINK_IFELSE(
|
||||||
@ -779,11 +779,11 @@ dnl Checks for functions and headers
|
|||||||
|
|
||||||
AC_FUNC_ALLOCA
|
AC_FUNC_ALLOCA
|
||||||
AS_IF([test "x$EMSCRIPTEN" = "x"],[
|
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([mmap mlock madvise mprotect])
|
||||||
])
|
])
|
||||||
AC_CHECK_FUNCS([posix_memalign getpid getentropy memset_s explicit_bzero
|
AC_CHECK_FUNCS([posix_memalign getpid nanosleep])
|
||||||
explicit_memset nanosleep])
|
AC_CHECK_FUNCS([memset_s explicit_bzero explicit_memset])
|
||||||
|
|
||||||
AC_SUBST([LIBTOOL_EXTRA_FLAGS])
|
AC_SUBST([LIBTOOL_EXTRA_FLAGS])
|
||||||
|
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "crypto_stream_chacha20.h"
|
#include "crypto_stream_chacha20.h"
|
||||||
#include "randombytes.h"
|
#include "randombytes.h"
|
||||||
|
#ifndef RANDOMBYTES_CUSTOM_IMPLEMENTATION
|
||||||
# ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION
|
# ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION
|
||||||
# include "randombytes_default.h"
|
# include "randombytes_salsa20.h"
|
||||||
#else
|
# endif
|
||||||
# include "randombytes_sysrandom.h"
|
# include "randombytes_sysrandom.h"
|
||||||
#endif
|
#endif
|
||||||
#include "private/common.h"
|
#include "private/common.h"
|
||||||
|
@ -31,10 +31,12 @@
|
|||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
# include <sys/param.h>
|
# include <sys/param.h>
|
||||||
# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000
|
# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000
|
||||||
# include <sys/random.h>
|
|
||||||
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
|
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_RANDOM_H
|
||||||
|
# include <sys/random.h>
|
||||||
|
#endif
|
||||||
#if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__)
|
#if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__)
|
||||||
# define BLOCK_ON_DEV_RANDOM
|
# define BLOCK_ON_DEV_RANDOM
|
||||||
#endif
|
#endif
|
||||||
@ -75,6 +77,9 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
|||||||
#if defined(__OpenBSD__) || defined(__CloudABI__)
|
#if defined(__OpenBSD__) || defined(__CloudABI__)
|
||||||
# define HAVE_SAFE_ARC4RANDOM 1
|
# define HAVE_SAFE_ARC4RANDOM 1
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(__CloudABI__) || defined(__wasm__)
|
||||||
|
# define NONEXISTENT_DEV_RANDOM 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SSIZE_MAX
|
#ifndef SSIZE_MAX
|
||||||
# define SSIZE_MAX (SIZE_MAX / 2 - 1)
|
# define SSIZE_MAX (SIZE_MAX / 2 - 1)
|
||||||
@ -98,6 +103,7 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
|
|||||||
typedef struct Salsa20RandomGlobal_ {
|
typedef struct Salsa20RandomGlobal_ {
|
||||||
int initialized;
|
int initialized;
|
||||||
int random_data_source_fd;
|
int random_data_source_fd;
|
||||||
|
int getentropy_available;
|
||||||
int getrandom_available;
|
int getrandom_available;
|
||||||
int rdrand_available;
|
int rdrand_available;
|
||||||
#ifdef HAVE_GETPID
|
#ifdef HAVE_GETPID
|
||||||
@ -152,7 +158,7 @@ sodium_hrtime(void)
|
|||||||
}
|
}
|
||||||
return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec;
|
return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the entropy source
|
* Initialize the entropy source
|
||||||
@ -168,6 +174,119 @@ randombytes_salsa20_random_init(void)
|
|||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
|
|
||||||
|
# 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_;
|
||||||
|
size_t chunk_size = 256U;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (size < chunk_size) {
|
||||||
|
chunk_size = size;
|
||||||
|
assert(chunk_size > (size_t) 0U);
|
||||||
|
}
|
||||||
|
if (_randombytes_getentropy(buf, chunk_size) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size -= chunk_size;
|
||||||
|
buf += chunk_size;
|
||||||
|
} while (size > (size_t) 0U);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||||
|
|
||||||
|
static int
|
||||||
|
_randombytes_linux_getrandom(void * const buf, const size_t size)
|
||||||
|
{
|
||||||
|
int readnb;
|
||||||
|
|
||||||
|
assert(size <= 256U);
|
||||||
|
do {
|
||||||
|
readnb = getrandom(buf, size, 0);
|
||||||
|
} while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
|
||||||
|
|
||||||
|
return (readnb == (int) size) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
randombytes_linux_getrandom(void * const buf_, size_t size)
|
||||||
|
{
|
||||||
|
unsigned char *buf = (unsigned char *) buf_;
|
||||||
|
size_t chunk_size = 256U;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (size < chunk_size) {
|
||||||
|
chunk_size = size;
|
||||||
|
assert(chunk_size > (size_t) 0U);
|
||||||
|
}
|
||||||
|
if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size -= chunk_size;
|
||||||
|
buf += chunk_size;
|
||||||
|
} while (size > (size_t) 0U);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
# 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
|
static ssize_t
|
||||||
safe_read(const int fd, void * const buf_, size_t size)
|
safe_read(const int fd, void * const buf_, size_t size)
|
||||||
{
|
{
|
||||||
@ -219,83 +338,7 @@ randombytes_block_on_dev_random(void)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef HAVE_SAFE_ARC4RANDOM
|
# endif /* !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 */
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
|
|
||||||
static int
|
|
||||||
_randombytes_linux_getrandom(void * const buf, const size_t size)
|
|
||||||
{
|
|
||||||
int readnb;
|
|
||||||
|
|
||||||
assert(size <= 256U);
|
|
||||||
do {
|
|
||||||
readnb = getrandom(buf, size, 0);
|
|
||||||
} while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
|
|
||||||
|
|
||||||
return (readnb == (int) size) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
randombytes_linux_getrandom(void * const buf_, size_t size)
|
|
||||||
{
|
|
||||||
unsigned char *buf = (unsigned char *) buf_;
|
|
||||||
size_t chunk_size = 256U;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (size < chunk_size) {
|
|
||||||
chunk_size = size;
|
|
||||||
assert(chunk_size > (size_t) 0U);
|
|
||||||
}
|
|
||||||
if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
size -= chunk_size;
|
|
||||||
buf += chunk_size;
|
|
||||||
} while (size > (size_t) 0U);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
randombytes_salsa20_random_init(void)
|
randombytes_salsa20_random_init(void)
|
||||||
@ -303,12 +346,20 @@ randombytes_salsa20_random_init(void)
|
|||||||
const int errno_save = errno;
|
const int errno_save = errno;
|
||||||
|
|
||||||
global.rdrand_available = sodium_runtime_has_rdrand();
|
global.rdrand_available = sodium_runtime_has_rdrand();
|
||||||
|
global.getentropy_available = 0;
|
||||||
|
global.getrandom_available = 0;
|
||||||
|
|
||||||
# ifdef HAVE_SAFE_ARC4RANDOM
|
# ifdef HAVE_GETENTROPY
|
||||||
|
{
|
||||||
|
unsigned char fodder[16];
|
||||||
|
|
||||||
|
if (randombytes_getentropy(fodder, sizeof fodder) == 0) {
|
||||||
|
global.getentropy_available = 1;
|
||||||
errno = errno_save;
|
errno = errno_save;
|
||||||
# else
|
return;
|
||||||
|
}
|
||||||
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
|
}
|
||||||
|
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||||
{
|
{
|
||||||
unsigned char fodder[16];
|
unsigned char fodder[16];
|
||||||
|
|
||||||
@ -317,16 +368,18 @@ randombytes_salsa20_random_init(void)
|
|||||||
errno = errno_save;
|
errno = errno_save;
|
||||||
return;
|
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 =
|
if ((global.random_data_source_fd =
|
||||||
randombytes_salsa20_random_random_dev_open()) == -1) {
|
randombytes_salsa20_random_random_dev_open()) == -1) {
|
||||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||||
}
|
}
|
||||||
|
# elif !defined(HAVE_SAFE_ARC4RANDOM)
|
||||||
|
sodium_misuse();
|
||||||
|
# endif
|
||||||
|
|
||||||
errno = errno_save;
|
errno = errno_save;
|
||||||
# endif /* HAVE_SAFE_ARC4RANDOM */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
@ -352,18 +405,20 @@ randombytes_salsa20_random_stir(void)
|
|||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
# ifdef HAVE_SAFE_ARC4RANDOM
|
# ifdef HAVE_GETENTROPY
|
||||||
arc4random_buf(stream.key, sizeof stream.key);
|
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)
|
# elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
|
||||||
if (global.getrandom_available != 0) {
|
if (global.getrandom_available != 0) {
|
||||||
if (randombytes_linux_getrandom(stream.key, sizeof stream.key) != 0) {
|
if (randombytes_getrandom(stream.key, sizeof stream.key) != 0) {
|
||||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
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 */
|
|
||||||
}
|
}
|
||||||
|
# elif !defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
|
||||||
|
arc4random_buf(stream.key, sizeof stream.key);
|
||||||
# else
|
# else
|
||||||
if (global.random_data_source_fd == -1 ||
|
if (global.random_data_source_fd == -1 ||
|
||||||
safe_read(global.random_data_source_fd, stream.key,
|
safe_read(global.random_data_source_fd, stream.key,
|
||||||
@ -425,6 +480,17 @@ randombytes_salsa20_random_close(void)
|
|||||||
{
|
{
|
||||||
int ret = -1;
|
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 &&
|
if (global.random_data_source_fd != -1 &&
|
||||||
close(global.random_data_source_fd) == 0) {
|
close(global.random_data_source_fd) == 0) {
|
||||||
global.random_data_source_fd = -1;
|
global.random_data_source_fd = -1;
|
||||||
@ -434,15 +500,6 @@ randombytes_salsa20_random_close(void)
|
|||||||
# endif
|
# endif
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef HAVE_SAFE_ARC4RANDOM
|
|
||||||
ret = 0;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM
|
|
||||||
if (global.getrandom_available != 0) {
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
sodium_memzero(&stream, sizeof stream);
|
sodium_memzero(&stream, sizeof stream);
|
||||||
|
@ -105,7 +105,7 @@ randombytes_sysrandom_close(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* __OpenBSD__ */
|
#else /* HAVE_SAFE_ARC4RANDOM */
|
||||||
|
|
||||||
typedef struct SysRandom_ {
|
typedef struct SysRandom_ {
|
||||||
int random_data_source_fd;
|
int random_data_source_fd;
|
||||||
|
Loading…
Reference in New Issue
Block a user