From 46ea86584a9787c8b9dc3983cf23d9b5b93b5841 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 21 Jun 2024 14:29:17 +0300 Subject: fixes #4477 (libsodium: update to 1.0.20) --- .../internal/randombytes_internal_random.c | 667 +++++++++++++++++++++ .../nativeclient/randombytes_nativeclient.c | 61 -- libs/libsodium/src/randombytes/randombytes.c | 133 ++-- .../salsa20/randombytes_salsa20_random.c | 569 ------------------ .../randombytes/sysrandom/randombytes_sysrandom.c | 31 +- 5 files changed, 756 insertions(+), 705 deletions(-) create mode 100644 libs/libsodium/src/randombytes/internal/randombytes_internal_random.c delete mode 100644 libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c delete mode 100644 libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c (limited to 'libs/libsodium/src/randombytes') diff --git a/libs/libsodium/src/randombytes/internal/randombytes_internal_random.c b/libs/libsodium/src/randombytes/internal/randombytes_internal_random.c new file mode 100644 index 0000000000..00bb703380 --- /dev/null +++ b/libs/libsodium/src/randombytes/internal/randombytes_internal_random.c @@ -0,0 +1,667 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(_MSC_VER) && !defined(__BORLANDC__) +# include +#endif + +#include +#ifndef _WIN32 +# include +# include +#endif +#ifdef __linux__ +# define _LINUX_SOURCE +#endif +#ifdef HAVE_SYS_RANDOM_H +# include +#endif +#ifdef __linux__ +# ifdef HAVE_GETRANDOM +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +# else +# include +# if defined(SYS_getrandom) && defined(__NR_getrandom) +# define getrandom(B, S, F) syscall(SYS_getrandom, (B), (int) (S), (F)) +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +# endif +# endif +#elif defined(__midipix__) +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +#elif defined(__FreeBSD__) +# include +# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000 +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +# endif +#endif +#ifdef HAVE_COMMONCRYPTO_COMMONRANDOM_H +# include +#endif +#if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__) +# define BLOCK_ON_DEV_RANDOM +#endif +#ifdef BLOCK_ON_DEV_RANDOM +# include +#endif +#ifdef HAVE_RDRAND +# ifdef __clang__ +# pragma clang attribute push(__attribute__((target("rdrnd"))), apply_to = function) +# elif defined(__GNUC__) +# pragma GCC target("rdrnd") +# endif +# include +#endif + +#include "core.h" +#include "crypto_core_hchacha20.h" +#include "crypto_stream_chacha20.h" +#include "private/common.h" +#include "randombytes.h" +#include "randombytes_internal_random.h" +#include "runtime.h" +#include "utils.h" + +#ifdef _WIN32 +# include +# include +# define RtlGenRandom SystemFunction036 +# if defined(__cplusplus) +extern "C" +# endif +BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); +# pragma comment(lib, "advapi32.lib") +# ifdef __BORLANDC__ +# define _ftime ftime +# define _timeb timeb +# endif +#endif + +#define INTERNAL_RANDOM_BLOCK_SIZE crypto_core_hchacha20_OUTPUTBYTES + +#if defined(__OpenBSD__) || defined(__CloudABI__) || defined(__wasi__) +# 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) +#endif +#ifndef S_ISNAM +# ifdef __COMPCERT__ +# define S_ISNAM(X) 1 +# else +# define S_ISNAM(X) 0 +# endif +#endif + +#if !defined(TLS) && !defined(__STDC_NO_THREADS__) && \ + defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +# define TLS _Thread_local +#endif +#ifndef TLS +# ifdef _WIN32 +# define TLS __declspec(thread) +# else +# define TLS +# endif +#endif + +typedef struct InternalRandomGlobal_ { + int initialized; + int random_data_source_fd; + int getentropy_available; + int getrandom_available; + int rdrand_available; +#ifdef HAVE_GETPID + pid_t pid; +#endif +} InternalRandomGlobal; + +typedef struct InternalRandom_ { + int initialized; + size_t rnd32_outleft; + unsigned char key[crypto_stream_chacha20_KEYBYTES]; + unsigned char rnd32[16U * INTERNAL_RANDOM_BLOCK_SIZE]; + uint64_t nonce; +} InternalRandom; + +static InternalRandomGlobal global = { + SODIUM_C99(.initialized =) 0, + SODIUM_C99(.random_data_source_fd =) -1 +}; + +static TLS InternalRandom stream = { + SODIUM_C99(.initialized =) 0, + SODIUM_C99(.rnd32_outleft =) (size_t) 0U +}; + + +/* + * Get a high-resolution timestamp, as a uint64_t value + */ + +#ifdef _WIN32 +static uint64_t +sodium_hrtime(void) +{ + struct _timeb tb; +# pragma warning(push) +# pragma warning(disable: 4996) + _ftime(&tb); +# pragma warning(pop) + return ((uint64_t) tb.time) * 1000000U + ((uint64_t) tb.millitm) * 1000U; +} + +#else /* _WIN32 */ + +static uint64_t +sodium_hrtime(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, NULL) != 0) { + sodium_misuse(); /* LCOV_EXCL_LINE */ + } + return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec; +} +#endif /* _WIN32 */ + +/* + * Initialize the entropy source + */ + +#ifdef _WIN32 + +static void +randombytes_internal_random_init(void) +{ + global.rdrand_available = sodium_runtime_has_rdrand(); +} + +#else /* _WIN32 */ + +# ifdef HAVE_COMMONCRYPTO_COMMONRANDOM_H +static int +randombytes_getentropy(void * const buf, const size_t size) +{ + if (CCRandomGenerateBytes(buf, size) != kCCSuccess) { + return -1; + } + return 0; +} + +# elif defined(HAVE_GETENTROPY) + +static int +_randombytes_getentropy(void * const buf, const size_t size) +{ + assert(size <= 256U); + /* LCOV_EXCL_START */ + if (&getentropy == NULL) { + errno = ENOSYS; + return -1; + } + /* LCOV_EXCL_END */ + if (getentropy(buf, size) != 0) { + return -1; /* LCOV_EXCL_LINE */ + } + return 0; +} + +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; /* LCOV_EXCL_LINE */ + } + 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 + +# 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 + +/* LCOV_EXCL_START */ +static int +randombytes_internal_random_random_dev_open(void) +{ + 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_); +} + +# endif /* !NONEXISTENT_DEV_RANDOM */ + +static void +randombytes_internal_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_GETENTROPY + { + unsigned char fodder[16]; + + 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]; + + if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) { + global.getrandom_available = 1; + errno = errno_save; + return; + } + } +# endif +/* LCOV_EXCL_START */ +# if !defined(NONEXISTENT_DEV_RANDOM) + assert((global.getentropy_available | global.getrandom_available) == 0); + if ((global.random_data_source_fd = + randombytes_internal_random_random_dev_open()) == -1) { + sodium_misuse(); /* LCOV_EXCL_LINE */ + } + errno = errno_save; + return; +# endif +/* LCOV_EXCL_STOP */ +# ifndef HAVE_SAFE_ARC4RANDOM + sodium_misuse(); +# endif +} + +#endif /* _WIN32 */ + +/* + * (Re)seed the generator using the entropy source + */ + +static void +randombytes_internal_random_stir(void) +{ + stream.nonce = sodium_hrtime(); + assert(stream.nonce != (uint64_t) 0U); + memset(stream.rnd32, 0, sizeof stream.rnd32); + stream.rnd32_outleft = (size_t) 0U; + if (global.initialized == 0) { + randombytes_internal_random_init(); + global.initialized = 1; + } +#ifdef HAVE_GETPID + global.pid = getpid(); +#endif + +#ifndef _WIN32 + +# 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 */ + } + } +# elif defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM) + arc4random_buf(stream.key, sizeof stream.key); +# elif !defined(NONEXISTENT_DEV_RANDOM) + 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 */ + } +# else + sodium_misuse(); +# endif + +#else /* _WIN32 */ + if (! RtlGenRandom((PVOID) stream.key, (ULONG) sizeof stream.key)) { + sodium_misuse(); /* LCOV_EXCL_LINE */ + } +#endif + + stream.initialized = 1; +} + +/* + * Reseed the generator if it hasn't been initialized yet + */ + +static void +randombytes_internal_random_stir_if_needed(void) +{ +#ifdef HAVE_GETPID + if (stream.initialized == 0) { + randombytes_internal_random_stir(); + } else if (global.pid != getpid()) { + sodium_misuse(); /* LCOV_EXCL_LINE */ + } +#else + if (stream.initialized == 0) { + randombytes_internal_random_stir(); + } +#endif +} + +/* + * Close the stream, free global resources + */ + +#ifdef _WIN32 +static int +randombytes_internal_random_close(void) +{ + int ret = -1; + + if (global.initialized != 0) { + global.initialized = 0; + ret = 0; + } + sodium_memzero(&stream, sizeof stream); + + return ret; +} +#else +static int +randombytes_internal_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; + global.initialized = 0; +# ifdef HAVE_GETPID + global.pid = (pid_t) 0; +# endif + ret = 0; + } +# endif + + sodium_memzero(&stream, sizeof stream); + + return ret; +} +#endif + +/* + * RDRAND is only used to mitigate prediction if a key is compromised + */ + +static void +randombytes_internal_random_xorhwrand(void) +{ +/* LCOV_EXCL_START */ +#ifdef HAVE_RDRAND + unsigned int r; + + if (global.rdrand_available == 0) { + return; + } + (void) _rdrand32_step(&r); + * (uint32_t *) (void *) + &stream.key[crypto_stream_chacha20_KEYBYTES - 4] ^= (uint32_t) r; +#endif +/* LCOV_EXCL_STOP */ +} + +/* + * XOR the key with another same-length secret + */ + +static inline void +randombytes_internal_random_xorkey(const unsigned char * const mix) +{ + unsigned char *key = stream.key; + size_t i; + + for (i = (size_t) 0U; i < sizeof stream.key; i++) { + key[i] ^= mix[i]; + } +} + +/* + * Put `size` random bytes into `buf` and overwrite the key + */ + +static void +randombytes_internal_random_buf(void * const buf, const size_t size) +{ + size_t i; + int ret; + + randombytes_internal_random_stir_if_needed(); + COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_chacha20_NONCEBYTES); +#if defined(ULLONG_MAX) && defined(SIZE_MAX) +# if SIZE_MAX > ULLONG_MAX + /* coverity[result_independent_of_operands] */ + assert(size <= ULLONG_MAX); +# endif +#endif + ret = crypto_stream_chacha20((unsigned char *) buf, (unsigned long long) size, + (unsigned char *) &stream.nonce, stream.key); + assert(ret == 0); + for (i = 0U; i < sizeof size; i++) { + stream.key[i] ^= ((const unsigned char *) (const void *) &size)[i]; + } + randombytes_internal_random_xorhwrand(); + stream.nonce++; + crypto_stream_chacha20_xor(stream.key, stream.key, sizeof stream.key, + (unsigned char *) &stream.nonce, stream.key); +} + +/* + * Pop a 32-bit value from the random pool + * + * Overwrite the key after the pool gets refilled. + */ + +static uint32_t +randombytes_internal_random(void) +{ + uint32_t val; + int ret; + + COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val)); + COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key)) + % sizeof val == (size_t) 0U); + if (stream.rnd32_outleft <= (size_t) 0U) { + randombytes_internal_random_stir_if_needed(); + COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_chacha20_NONCEBYTES); + ret = crypto_stream_chacha20((unsigned char *) stream.rnd32, + (unsigned long long) sizeof stream.rnd32, + (unsigned char *) &stream.nonce, + stream.key); + assert(ret == 0); + stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key); + randombytes_internal_random_xorhwrand(); + randombytes_internal_random_xorkey(&stream.rnd32[stream.rnd32_outleft]); + memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof stream.key); + stream.nonce++; + } + stream.rnd32_outleft -= sizeof val; + memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val); + memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val); + + return val; +} + +static const char * +randombytes_internal_implementation_name(void) +{ + return "internal"; +} + +struct randombytes_implementation randombytes_internal_implementation = { + SODIUM_C99(.implementation_name =) randombytes_internal_implementation_name, + SODIUM_C99(.random =) randombytes_internal_random, + SODIUM_C99(.stir =) randombytes_internal_random_stir, + SODIUM_C99(.uniform =) NULL, + SODIUM_C99(.buf =) randombytes_internal_random_buf, + SODIUM_C99(.close =) randombytes_internal_random_close +}; + +#ifdef HAVE_RDRAND +# ifdef __clang__ +# pragma clang attribute pop +# endif +#endif diff --git a/libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c b/libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c deleted file mode 100644 index 93eec1f601..0000000000 --- a/libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c +++ /dev/null @@ -1,61 +0,0 @@ - -#include -#include -#include - -#ifdef __native_client__ -# include - -# include "core.h" -# include "utils.h" -# include "randombytes.h" -# include "randombytes_nativeclient.h" - -static void -randombytes_nativeclient_buf(void * const buf, const size_t size) -{ - unsigned char *buf_ = (unsigned char *) buf; - struct nacl_irt_random rand_intf; - size_t readnb = (size_t) 0U; - size_t toread = size; - - if (nacl_interface_query(NACL_IRT_RANDOM_v0_1, &rand_intf, - sizeof rand_intf) != sizeof rand_intf) { - sodium_misuse(); - } - while (toread > (size_t) 0U) { - if (rand_intf.get_random_bytes(buf_, size, &readnb) != 0 || - readnb > size) { - sodium_misuse(); - } - toread -= readnb; - buf_ += readnb; - } -} - -static uint32_t -randombytes_nativeclient_random(void) -{ - uint32_t r; - - randombytes_nativeclient_buf(&r, sizeof r); - - return r; -} - -static const char * -randombytes_nativeclient_implementation_name(void) -{ - return "nativeclient"; -} - -struct randombytes_implementation randombytes_nativeclient_implementation = { - SODIUM_C99(.implementation_name =) randombytes_nativeclient_implementation_name, - SODIUM_C99(.random =) randombytes_nativeclient_random, - SODIUM_C99(.stir =) NULL, - SODIUM_C99(.uniform =) NULL, - SODIUM_C99(.buf =) randombytes_nativeclient_buf, - SODIUM_C99(.close =) NULL -}; - -#endif diff --git a/libs/libsodium/src/randombytes/randombytes.c b/libs/libsodium/src/randombytes/randombytes.c index 34d9ebb1cd..9e5664a30a 100644 --- a/libs/libsodium/src/randombytes/randombytes.c +++ b/libs/libsodium/src/randombytes/randombytes.c @@ -13,14 +13,11 @@ #include "core.h" #include "crypto_stream_chacha20.h" #include "randombytes.h" -#ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION -# include "randombytes_default.h" -#else -# ifdef __native_client__ -# include "randombytes_nativeclient.h" -# else -# include "randombytes_sysrandom.h" +#ifndef RANDOMBYTES_CUSTOM_IMPLEMENTATION +# ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION +# include "randombytes_internal.h" # endif +# include "randombytes_sysrandom.h" #endif #include "private/common.h" @@ -33,64 +30,28 @@ static const randombytes_implementation *implementation; # ifdef __EMSCRIPTEN__ # define RANDOMBYTES_DEFAULT_IMPLEMENTATION NULL # else -# ifdef __native_client__ -# define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_nativeclient_implementation; -# else -# define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_sysrandom_implementation; -# endif +# define RANDOMBYTES_DEFAULT_IMPLEMENTATION &randombytes_sysrandom_implementation # endif #endif -static void -randombytes_init_if_needed(void) -{ - if (implementation == NULL) { - implementation = RANDOMBYTES_DEFAULT_IMPLEMENTATION; - randombytes_stir(); - } -} - -int -randombytes_set_implementation(randombytes_implementation *impl) -{ - implementation = impl; - - return 0; -} - -const char * -randombytes_implementation_name(void) +#ifdef __EMSCRIPTEN__ +static const char * +javascript_implementation_name(void) { -#ifndef __EMSCRIPTEN__ - randombytes_init_if_needed(); - return implementation->implementation_name(); -#else return "js"; -#endif } -uint32_t -randombytes_random(void) +static uint32_t +javascript_random(void) { -#ifndef __EMSCRIPTEN__ - randombytes_init_if_needed(); - return implementation->random(); -#else return EM_ASM_INT_V({ return Module.getRandomValue(); }); -#endif } -void -randombytes_stir(void) +static void +javascript_stir(void) { -#ifndef __EMSCRIPTEN__ - randombytes_init_if_needed(); - if (implementation->stir != NULL) { - implementation->stir(); - } -#else EM_ASM({ if (Module.getRandomValue === undefined) { try { @@ -118,7 +79,66 @@ randombytes_stir(void) } } }); +} + +static void +javascript_buf(void * const buf, const size_t size) +{ + unsigned char *p = (unsigned char *) buf; + size_t i; + + for (i = (size_t) 0U; i < size; i++) { + p[i] = (unsigned char) randombytes_random(); + } +} #endif + +static void +randombytes_init_if_needed(void) +{ + if (implementation == NULL) { +#ifdef __EMSCRIPTEN__ + static randombytes_implementation javascript_implementation; + javascript_implementation.implementation_name = javascript_implementation_name; + javascript_implementation.random = javascript_random; + javascript_implementation.stir = javascript_stir; + javascript_implementation.buf = javascript_buf; + implementation = &javascript_implementation; +#else + implementation = RANDOMBYTES_DEFAULT_IMPLEMENTATION; +#endif + randombytes_stir(); + } +} + +int +randombytes_set_implementation(const randombytes_implementation *impl) +{ + implementation = impl; + return 0; +} + +const char * +randombytes_implementation_name(void) +{ + randombytes_init_if_needed(); + return implementation->implementation_name(); +} + +uint32_t +randombytes_random(void) +{ + randombytes_init_if_needed(); + return implementation->random(); +} + +void +randombytes_stir(void) +{ + randombytes_init_if_needed(); + if (implementation->stir != NULL) { + implementation->stir(); + } } uint32_t @@ -127,12 +147,10 @@ randombytes_uniform(const uint32_t upper_bound) uint32_t min; uint32_t r; -#ifndef __EMSCRIPTEN__ randombytes_init_if_needed(); if (implementation->uniform != NULL) { return implementation->uniform(upper_bound); } -#endif if (upper_bound < 2) { return 0; } @@ -149,19 +167,10 @@ randombytes_uniform(const uint32_t upper_bound) void randombytes_buf(void * const buf, const size_t size) { -#ifndef __EMSCRIPTEN__ randombytes_init_if_needed(); if (size > (size_t) 0U) { implementation->buf(buf, size); } -#else - unsigned char *p = (unsigned char *) buf; - size_t i; - - for (i = (size_t) 0U; i < size; i++) { - p[i] = (unsigned char) randombytes_random(); - } -#endif } void diff --git a/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c b/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c deleted file mode 100644 index fc4c9b3709..0000000000 --- a/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c +++ /dev/null @@ -1,569 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(_MSC_VER) && !defined(__BORLANDC__) -# include -#endif - -#include -#ifndef _WIN32 -# include -# include -#endif -#ifdef __linux__ -# ifdef __dietlibc__ -# define _LINUX_SOURCE -# include -# define HAVE_LINUX_COMPATIBLE_GETRANDOM -# else /* __dietlibc__ */ -# include -# if defined(SYS_getrandom) && defined(__NR_getrandom) -# define getrandom(B, S, F) syscall(SYS_getrandom, (B), (int) (S), (F)) -# define HAVE_LINUX_COMPATIBLE_GETRANDOM -# endif -# endif /* __dietlibc__ */ -#elif defined(__FreeBSD__) -# include -# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000 -# include -# define HAVE_LINUX_COMPATIBLE_GETRANDOM -# endif -#endif -#if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__) -# define BLOCK_ON_DEV_RANDOM -#endif -#ifdef BLOCK_ON_DEV_RANDOM -# include -#endif -#ifdef HAVE_RDRAND -# pragma GCC target("rdrnd") -# include -#endif - -#include "core.h" -#include "crypto_core_salsa20.h" -#include "crypto_stream_salsa20.h" -#include "private/common.h" -#include "randombytes.h" -#include "randombytes_salsa20_random.h" -#include "runtime.h" -#include "utils.h" - -#ifdef _WIN32 -# include -# include -# define RtlGenRandom SystemFunction036 -# if defined(__cplusplus) -extern "C" -# endif -BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); -# pragma comment(lib, "advapi32.lib") -# ifdef __BORLANDC__ -# define _ftime ftime -# define _timeb timeb -# endif -#endif - -#define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES - -#if defined(__OpenBSD__) || defined(__CloudABI__) -# define HAVE_SAFE_ARC4RANDOM 1 -#endif - -#ifndef SSIZE_MAX -# define SSIZE_MAX (SIZE_MAX / 2 - 1) -#endif -#ifndef S_ISNAM -# ifdef __COMPCERT__ -# define S_ISNAM(X) 1 -# else -# define S_ISNAM(X) 0 -# endif -#endif - -#ifndef TLS -# ifdef _WIN32 -# define TLS __declspec(thread) -# else -# define TLS -# endif -#endif - -typedef struct Salsa20RandomGlobal_ { - int initialized; - int random_data_source_fd; - int getrandom_available; - int rdrand_available; -#ifdef HAVE_GETPID - pid_t pid; -#endif -} Salsa20RandomGlobal; - -typedef struct Salsa20Random_ { - int initialized; - size_t rnd32_outleft; - unsigned char key[crypto_stream_salsa20_KEYBYTES]; - unsigned char rnd32[16U * SALSA20_RANDOM_BLOCK_SIZE]; - uint64_t nonce; -} Salsa20Random; - -static Salsa20RandomGlobal global = { - SODIUM_C99(.initialized =) 0, - SODIUM_C99(.random_data_source_fd =) -1 -}; - -static TLS Salsa20Random stream = { - SODIUM_C99(.initialized =) 0, - SODIUM_C99(.rnd32_outleft =) (size_t) 0U -}; - - -/* - * Get a high-resolution timestamp, as a uint64_t value - */ - -#ifdef _WIN32 -static uint64_t -sodium_hrtime(void) -{ - struct _timeb tb; -# pragma warning(push) -# pragma warning(disable: 4996) - _ftime(&tb); -# pragma warning(pop) - return ((uint64_t) tb.time) * 1000000U + ((uint64_t) tb.millitm) * 1000U; -} - -#else /* _WIN32 */ - -static uint64_t -sodium_hrtime(void) -{ - struct timeval tv; - - if (gettimeofday(&tv, NULL) != 0) { - sodium_misuse(); /* LCOV_EXCL_LINE */ - } - return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec; -} -#endif - -/* - * Initialize the entropy source - */ - -#ifdef _WIN32 - -static void -randombytes_salsa20_random_init(void) -{ - global.rdrand_available = sodium_runtime_has_rdrand(); -} - -#else /* _WIN32 */ - -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 - -# 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) -{ - 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 -randombytes_salsa20_random_init(void) -{ - const int errno_save = errno; - - global.rdrand_available = sodium_runtime_has_rdrand(); - -# ifdef HAVE_SAFE_ARC4RANDOM - errno = errno_save; -# else - -# ifdef HAVE_LINUX_COMPATIBLE_GETRANDOM - { - unsigned char fodder[16]; - - if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) { - global.getrandom_available = 1; - errno = errno_save; - return; - } - global.getrandom_available = 0; - } -# endif /* HAVE_LINUX_COMPATIBLE_GETRANDOM */ - - if ((global.random_data_source_fd = - randombytes_salsa20_random_random_dev_open()) == -1) { - sodium_misuse(); /* LCOV_EXCL_LINE */ - } - errno = errno_save; -# endif /* HAVE_SAFE_ARC4RANDOM */ -} - -#endif /* _WIN32 */ - -/* - * (Re)seed the generator using the entropy source - */ - -static void -randombytes_salsa20_random_stir(void) -{ - stream.nonce = sodium_hrtime(); - assert(stream.nonce != (uint64_t) 0U); - memset(stream.rnd32, 0, sizeof stream.rnd32); - stream.rnd32_outleft = (size_t) 0U; - if (global.initialized == 0) { - randombytes_salsa20_random_init(); - global.initialized = 1; - } -#ifdef HAVE_GETPID - global.pid = getpid(); -#endif - -#ifndef _WIN32 - -# ifdef HAVE_SAFE_ARC4RANDOM - arc4random_buf(stream.key, sizeof stream.key); -# 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 */ - } -# 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 */ - } -# endif - -#else /* _WIN32 */ - if (! RtlGenRandom((PVOID) stream.key, (ULONG) sizeof stream.key)) { - sodium_misuse(); /* LCOV_EXCL_LINE */ - } -#endif - - stream.initialized = 1; -} - -/* - * Reseed the generator if it hasn't been initialized yet - */ - -static void -randombytes_salsa20_random_stir_if_needed(void) -{ -#ifdef HAVE_GETPID - if (stream.initialized == 0) { - randombytes_salsa20_random_stir(); - } else if (global.pid != getpid()) { - sodium_misuse(); /* LCOV_EXCL_LINE */ - } -#else - if (stream.initialized == 0) { - randombytes_salsa20_random_stir(); - } -#endif -} - -/* - * Close the stream, free global resources - */ - -#ifdef _WIN32 -static int -randombytes_salsa20_random_close(void) -{ - int ret = -1; - - if (global.initialized != 0) { - global.initialized = 0; - ret = 0; - } - sodium_memzero(&stream, sizeof stream); - - return ret; -} -#else -static int -randombytes_salsa20_random_close(void) -{ - int ret = -1; - - if (global.random_data_source_fd != -1 && - close(global.random_data_source_fd) == 0) { - global.random_data_source_fd = -1; - global.initialized = 0; -# ifdef HAVE_GETPID - global.pid = (pid_t) 0; -# 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); - - return ret; -} -#endif - -/* - * RDRAND is only used to mitigate prediction if a key is compromised - */ - -static void -randombytes_salsa20_random_xorhwrand(void) -{ -/* LCOV_EXCL_START */ -#ifdef HAVE_RDRAND - unsigned int r; - - if (global.rdrand_available == 0) { - return; - } - (void) _rdrand32_step(&r); - * (uint32_t *) (void *) - &stream.key[crypto_stream_salsa20_KEYBYTES - 4] ^= (uint32_t) r; -#endif -/* LCOV_EXCL_STOP */ -} - -/* - * XOR the key with another same-length secret - */ - -static inline void -randombytes_salsa20_random_xorkey(const unsigned char * const mix) -{ - unsigned char *key = stream.key; - size_t i; - - for (i = (size_t) 0U; i < sizeof stream.key; i++) { - key[i] ^= mix[i]; - } -} - -/* - * Put `size` random bytes into `buf` and overwrite the key - */ - -static void -randombytes_salsa20_random_buf(void * const buf, const size_t size) -{ - size_t i; - int ret; - - randombytes_salsa20_random_stir_if_needed(); - COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES); -#if defined(ULLONG_MAX) && defined(SIZE_MAX) -# if SIZE_MAX > ULLONG_MAX - /* coverity[result_independent_of_operands] */ - assert(size <= ULLONG_MAX); -# endif -#endif - ret = crypto_stream_salsa20((unsigned char *) buf, (unsigned long long) size, - (unsigned char *) &stream.nonce, stream.key); - assert(ret == 0); - for (i = 0U; i < sizeof size; i++) { - stream.key[i] ^= ((const unsigned char *) (const void *) &size)[i]; - } - randombytes_salsa20_random_xorhwrand(); - stream.nonce++; - crypto_stream_salsa20_xor(stream.key, stream.key, sizeof stream.key, - (unsigned char *) &stream.nonce, stream.key); -} - -/* - * Pop a 32-bit value from the random pool - * - * Overwrite the key after the pool gets refilled. - */ - -static uint32_t -randombytes_salsa20_random(void) -{ - uint32_t val; - int ret; - - COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val)); - COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key)) - % sizeof val == (size_t) 0U); - if (stream.rnd32_outleft <= (size_t) 0U) { - randombytes_salsa20_random_stir_if_needed(); - COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES); - ret = crypto_stream_salsa20((unsigned char *) stream.rnd32, - (unsigned long long) sizeof stream.rnd32, - (unsigned char *) &stream.nonce, - stream.key); - assert(ret == 0); - stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key); - randombytes_salsa20_random_xorhwrand(); - randombytes_salsa20_random_xorkey(&stream.rnd32[stream.rnd32_outleft]); - memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof stream.key); - stream.nonce++; - } - stream.rnd32_outleft -= sizeof val; - memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val); - memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val); - - return val; -} - -static const char * -randombytes_salsa20_implementation_name(void) -{ - return "salsa20"; -} - -struct randombytes_implementation randombytes_salsa20_implementation = { - SODIUM_C99(.implementation_name =) randombytes_salsa20_implementation_name, - SODIUM_C99(.random =) randombytes_salsa20_random, - SODIUM_C99(.stir =) randombytes_salsa20_random_stir, - SODIUM_C99(.uniform =) NULL, - SODIUM_C99(.buf =) randombytes_salsa20_random_buf, - SODIUM_C99(.close =) randombytes_salsa20_random_close -}; diff --git a/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c b/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c index d1439bf7fc..75fbca9dab 100644 --- a/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c +++ b/libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c @@ -1,4 +1,3 @@ - #include #include #include @@ -8,29 +7,35 @@ #ifndef _WIN32 # include #endif - #include + #include #ifndef _WIN32 # include # include #endif #ifdef __linux__ -# ifdef __dietlibc__ -# define _LINUX_SOURCE -# include +# define _LINUX_SOURCE +#endif +#ifdef HAVE_SYS_RANDOM_H +# include +#endif +#ifdef __linux__ +# ifdef HAVE_GETRANDOM # define HAVE_LINUX_COMPATIBLE_GETRANDOM -# else /* __dietlibc__ */ +# else # include # if defined(SYS_getrandom) && defined(__NR_getrandom) # define getrandom(B, S, F) syscall(SYS_getrandom, (B), (int) (S), (F)) # define HAVE_LINUX_COMPATIBLE_GETRANDOM # endif -# endif /* __dietlibc */ -#elif defined(__FreeBSD__) +# endif +#elif defined(__midipix__) +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +#elif defined(__FreeBSD__) || defined(__DragonFly__) # include -# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000 -# include +# if (defined(__FreeBSD_version) && __FreeBSD_version >= 1200000) || \ + (defined(__DragonFly_version) && __DragonFly_version >= 500700) # define HAVE_LINUX_COMPATIBLE_GETRANDOM # endif #endif @@ -72,7 +77,7 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); # pragma comment(lib, "advapi32.lib") #endif -#if defined(__OpenBSD__) || defined(__CloudABI__) +#if defined(__OpenBSD__) || defined(__CloudABI__) || defined(__wasi__) # define HAVE_SAFE_ARC4RANDOM 1 #endif @@ -105,7 +110,7 @@ randombytes_sysrandom_close(void) return 0; } -#else /* __OpenBSD__ */ +#else /* HAVE_SAFE_ARC4RANDOM */ typedef struct SysRandom_ { int random_data_source_fd; @@ -375,7 +380,7 @@ randombytes_sysrandom(void) return r; } -#endif /* __OpenBSD__ */ +#endif /* HAVE_SAFE_ARC4RANDOM */ static const char * randombytes_sysrandom_implementation_name(void) -- cgit v1.2.3