diff options
author | George Hazan <george.hazan@gmail.com> | 2024-06-21 14:29:17 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2024-06-21 14:29:17 +0300 |
commit | 46ea86584a9787c8b9dc3983cf23d9b5b93b5841 (patch) | |
tree | fbaf3793ae2170f7982f08a62c028a23cd9afedd /libs/libsodium/src/randombytes | |
parent | 82e75be329dd0f30c0281ef9c3c08488b89d109f (diff) |
fixes #4477 (libsodium: update to 1.0.20)
Diffstat (limited to 'libs/libsodium/src/randombytes')
-rw-r--r-- | libs/libsodium/src/randombytes/internal/randombytes_internal_random.c (renamed from libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c) | 1236 | ||||
-rw-r--r-- | libs/libsodium/src/randombytes/nativeclient/randombytes_nativeclient.c | 61 | ||||
-rw-r--r-- | libs/libsodium/src/randombytes/randombytes.c | 133 | ||||
-rw-r--r-- | libs/libsodium/src/randombytes/sysrandom/randombytes_sysrandom.c | 31 |
4 files changed, 756 insertions, 705 deletions
diff --git a/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c b/libs/libsodium/src/randombytes/internal/randombytes_internal_random.c index fc4c9b3709..00bb703380 100644 --- a/libs/libsodium/src/randombytes/salsa20/randombytes_salsa20_random.c +++ b/libs/libsodium/src/randombytes/internal/randombytes_internal_random.c @@ -1,569 +1,667 @@ -
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdlib.h>
-#include <string.h>
-#if !defined(_MSC_VER) && !defined(__BORLANDC__)
-# include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#ifndef _WIN32
-# include <sys/stat.h>
-# include <sys/time.h>
-#endif
-#ifdef __linux__
-# ifdef __dietlibc__
-# define _LINUX_SOURCE
-# include <sys/random.h>
-# define HAVE_LINUX_COMPATIBLE_GETRANDOM
-# else /* __dietlibc__ */
-# include <sys/syscall.h>
-# 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 <sys/param.h>
-# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000
-# include <sys/random.h>
-# 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 <poll.h>
-#endif
-#ifdef HAVE_RDRAND
-# pragma GCC target("rdrnd")
-# include <immintrin.h>
-#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 <windows.h>
-# include <sys/timeb.h>
-# 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
-};
+ +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdlib.h> +#include <string.h> +#if !defined(_MSC_VER) && !defined(__BORLANDC__) +# include <unistd.h> +#endif + +#include <sys/types.h> +#ifndef _WIN32 +# include <sys/stat.h> +# include <sys/time.h> +#endif +#ifdef __linux__ +# define _LINUX_SOURCE +#endif +#ifdef HAVE_SYS_RANDOM_H +# include <sys/random.h> +#endif +#ifdef __linux__ +# ifdef HAVE_GETRANDOM +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +# else +# include <sys/syscall.h> +# 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 <sys/param.h> +# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000 +# define HAVE_LINUX_COMPATIBLE_GETRANDOM +# endif +#endif +#ifdef HAVE_COMMONCRYPTO_COMMONRANDOM_H +# include <CommonCrypto/CommonRandom.h> +#endif +#if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__) +# define BLOCK_ON_DEV_RANDOM +#endif +#ifdef BLOCK_ON_DEV_RANDOM +# include <poll.h> +#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 <immintrin.h> +#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 <windows.h> +# include <sys/timeb.h> +# 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 <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifdef __native_client__
-# include <irt.h>
-
-# 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/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 <assert.h>
#include <errno.h>
#include <fcntl.h>
@@ -8,29 +7,35 @@ #ifndef _WIN32
# include <unistd.h>
#endif
-
#include <stdlib.h>
+
#include <sys/types.h>
#ifndef _WIN32
# include <sys/stat.h>
# include <sys/time.h>
#endif
#ifdef __linux__
-# ifdef __dietlibc__
-# define _LINUX_SOURCE
-# include <sys/random.h>
+# define _LINUX_SOURCE
+#endif
+#ifdef HAVE_SYS_RANDOM_H
+# include <sys/random.h>
+#endif
+#ifdef __linux__
+# ifdef HAVE_GETRANDOM
# define HAVE_LINUX_COMPATIBLE_GETRANDOM
-# else /* __dietlibc__ */
+# else
# include <sys/syscall.h>
# 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 <sys/param.h>
-# if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000
-# include <sys/random.h>
+# 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)
|