|
|
@ -49,11 +49,11 @@ |
|
|
|
#endif |
|
|
|
|
|
|
|
#include "core.h" |
|
|
|
#include "crypto_core_salsa20.h" |
|
|
|
#include "crypto_stream_salsa20.h" |
|
|
|
#include "crypto_core_hchacha20.h" |
|
|
|
#include "crypto_stream_chacha20.h" |
|
|
|
#include "private/common.h" |
|
|
|
#include "randombytes.h" |
|
|
|
#include "randombytes_salsa20_random.h" |
|
|
|
#include "randombytes_internal_random.h" |
|
|
|
#include "runtime.h" |
|
|
|
#include "utils.h" |
|
|
|
|
|
|
@ -72,7 +72,7 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); |
|
|
|
# endif |
|
|
|
#endif |
|
|
|
|
|
|
|
#define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES |
|
|
|
#define INTERNAL_RANDOM_BLOCK_SIZE crypto_core_hchacha20_OUTPUTBYTES |
|
|
|
|
|
|
|
#if defined(__OpenBSD__) || defined(__CloudABI__) |
|
|
|
# define HAVE_SAFE_ARC4RANDOM 1 |
|
|
@ -100,7 +100,7 @@ BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); |
|
|
|
# endif |
|
|
|
#endif |
|
|
|
|
|
|
|
typedef struct Salsa20RandomGlobal_ { |
|
|
|
typedef struct InternalRandomGlobal_ { |
|
|
|
int initialized; |
|
|
|
int random_data_source_fd; |
|
|
|
int getentropy_available; |
|
|
@ -109,22 +109,22 @@ typedef struct Salsa20RandomGlobal_ { |
|
|
|
#ifdef HAVE_GETPID |
|
|
|
pid_t pid; |
|
|
|
#endif |
|
|
|
} Salsa20RandomGlobal; |
|
|
|
} InternalRandomGlobal; |
|
|
|
|
|
|
|
typedef struct Salsa20Random_ { |
|
|
|
typedef struct InternalRandom_ { |
|
|
|
int initialized; |
|
|
|
size_t rnd32_outleft; |
|
|
|
unsigned char key[crypto_stream_salsa20_KEYBYTES]; |
|
|
|
unsigned char rnd32[16U * SALSA20_RANDOM_BLOCK_SIZE]; |
|
|
|
unsigned char key[crypto_stream_chacha20_KEYBYTES]; |
|
|
|
unsigned char rnd32[16U * INTERNAL_RANDOM_BLOCK_SIZE]; |
|
|
|
uint64_t nonce; |
|
|
|
} Salsa20Random; |
|
|
|
} InternalRandom; |
|
|
|
|
|
|
|
static Salsa20RandomGlobal global = { |
|
|
|
static InternalRandomGlobal global = { |
|
|
|
SODIUM_C99(.initialized =) 0, |
|
|
|
SODIUM_C99(.random_data_source_fd =) -1 |
|
|
|
}; |
|
|
|
|
|
|
|
static TLS Salsa20Random stream = { |
|
|
|
static TLS InternalRandom stream = { |
|
|
|
SODIUM_C99(.initialized =) 0, |
|
|
|
SODIUM_C99(.rnd32_outleft =) (size_t) 0U |
|
|
|
}; |
|
|
@ -167,7 +167,7 @@ sodium_hrtime(void) |
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
static void |
|
|
|
randombytes_salsa20_random_init(void) |
|
|
|
randombytes_internal_random_init(void) |
|
|
|
{ |
|
|
|
global.rdrand_available = sodium_runtime_has_rdrand(); |
|
|
|
} |
|
|
@ -248,7 +248,7 @@ randombytes_linux_getrandom(void * const buf_, size_t size) |
|
|
|
|
|
|
|
# ifndef NONEXISTENT_DEV_RANDOM |
|
|
|
static int |
|
|
|
randombytes_salsa20_random_random_dev_open(void) |
|
|
|
randombytes_internal_random_random_dev_open(void) |
|
|
|
{ |
|
|
|
/* LCOV_EXCL_START */ |
|
|
|
struct stat st; |
|
|
@ -341,7 +341,7 @@ randombytes_block_on_dev_random(void) |
|
|
|
# endif /* !NONEXISTENT_DEV_RANDOM */ |
|
|
|
|
|
|
|
static void |
|
|
|
randombytes_salsa20_random_init(void) |
|
|
|
randombytes_internal_random_init(void) |
|
|
|
{ |
|
|
|
const int errno_save = errno; |
|
|
|
|
|
|
@ -369,17 +369,19 @@ randombytes_salsa20_random_init(void) |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
# elif !defined(NONEXISTENT_DEV_RANDOM) |
|
|
|
# endif |
|
|
|
# if !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) { |
|
|
|
randombytes_internal_random_random_dev_open()) == -1) { |
|
|
|
sodium_misuse(); /* LCOV_EXCL_LINE */ |
|
|
|
} |
|
|
|
# elif !defined(HAVE_SAFE_ARC4RANDOM) |
|
|
|
errno = errno_save; |
|
|
|
return; |
|
|
|
# endif |
|
|
|
# ifndef HAVE_SAFE_ARC4RANDOM |
|
|
|
sodium_misuse(); |
|
|
|
# endif |
|
|
|
|
|
|
|
errno = errno_save; |
|
|
|
} |
|
|
|
|
|
|
|
#endif /* _WIN32 */ |
|
|
@ -389,14 +391,14 @@ randombytes_salsa20_random_init(void) |
|
|
|
*/ |
|
|
|
|
|
|
|
static void |
|
|
|
randombytes_salsa20_random_stir(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_salsa20_random_init(); |
|
|
|
randombytes_internal_random_init(); |
|
|
|
global.initialized = 1; |
|
|
|
} |
|
|
|
#ifdef HAVE_GETPID |
|
|
@ -417,14 +419,16 @@ randombytes_salsa20_random_stir(void) |
|
|
|
sodium_misuse(); /* LCOV_EXCL_LINE */ |
|
|
|
} |
|
|
|
} |
|
|
|
# elif !defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM) |
|
|
|
# elif defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM) |
|
|
|
arc4random_buf(stream.key, sizeof stream.key); |
|
|
|
# else |
|
|
|
# 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 */ |
|
|
@ -441,17 +445,17 @@ randombytes_salsa20_random_stir(void) |
|
|
|
*/ |
|
|
|
|
|
|
|
static void |
|
|
|
randombytes_salsa20_random_stir_if_needed(void) |
|
|
|
randombytes_internal_random_stir_if_needed(void) |
|
|
|
{ |
|
|
|
#ifdef HAVE_GETPID |
|
|
|
if (stream.initialized == 0) { |
|
|
|
randombytes_salsa20_random_stir(); |
|
|
|
randombytes_internal_random_stir(); |
|
|
|
} else if (global.pid != getpid()) { |
|
|
|
sodium_misuse(); /* LCOV_EXCL_LINE */ |
|
|
|
} |
|
|
|
#else |
|
|
|
if (stream.initialized == 0) { |
|
|
|
randombytes_salsa20_random_stir(); |
|
|
|
randombytes_internal_random_stir(); |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
@ -462,7 +466,7 @@ randombytes_salsa20_random_stir_if_needed(void) |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
static int |
|
|
|
randombytes_salsa20_random_close(void) |
|
|
|
randombytes_internal_random_close(void) |
|
|
|
{ |
|
|
|
int ret = -1; |
|
|
|
|
|
|
@ -476,7 +480,7 @@ randombytes_salsa20_random_close(void) |
|
|
|
} |
|
|
|
#else |
|
|
|
static int |
|
|
|
randombytes_salsa20_random_close(void) |
|
|
|
randombytes_internal_random_close(void) |
|
|
|
{ |
|
|
|
int ret = -1; |
|
|
|
|
|
|
@ -513,7 +517,7 @@ randombytes_salsa20_random_close(void) |
|
|
|
*/ |
|
|
|
|
|
|
|
static void |
|
|
|
randombytes_salsa20_random_xorhwrand(void) |
|
|
|
randombytes_internal_random_xorhwrand(void) |
|
|
|
{ |
|
|
|
/* LCOV_EXCL_START */ |
|
|
|
#ifdef HAVE_RDRAND |
|
|
@ -524,7 +528,7 @@ randombytes_salsa20_random_xorhwrand(void) |
|
|
|
} |
|
|
|
(void) _rdrand32_step(&r); |
|
|
|
* (uint32_t *) (void *) |
|
|
|
&stream.key[crypto_stream_salsa20_KEYBYTES - 4] ^= (uint32_t) r; |
|
|
|
&stream.key[crypto_stream_chacha20_KEYBYTES - 4] ^= (uint32_t) r; |
|
|
|
#endif |
|
|
|
/* LCOV_EXCL_STOP */ |
|
|
|
} |
|
|
@ -534,7 +538,7 @@ randombytes_salsa20_random_xorhwrand(void) |
|
|
|
*/ |
|
|
|
|
|
|
|
static inline void |
|
|
|
randombytes_salsa20_random_xorkey(const unsigned char * const mix) |
|
|
|
randombytes_internal_random_xorkey(const unsigned char * const mix) |
|
|
|
{ |
|
|
|
unsigned char *key = stream.key; |
|
|
|
size_t i; |
|
|
@ -549,29 +553,29 @@ randombytes_salsa20_random_xorkey(const unsigned char * const mix) |
|
|
|
*/ |
|
|
|
|
|
|
|
static void |
|
|
|
randombytes_salsa20_random_buf(void * const buf, const size_t size) |
|
|
|
randombytes_internal_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); |
|
|
|
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_salsa20((unsigned char *) buf, (unsigned long long) size, |
|
|
|
(unsigned char *) &stream.nonce, stream.key); |
|
|
|
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_salsa20_random_xorhwrand(); |
|
|
|
randombytes_internal_random_xorhwrand(); |
|
|
|
stream.nonce++; |
|
|
|
crypto_stream_salsa20_xor(stream.key, stream.key, sizeof stream.key, |
|
|
|
(unsigned char *) &stream.nonce, stream.key); |
|
|
|
crypto_stream_chacha20_xor(stream.key, stream.key, sizeof stream.key, |
|
|
|
(unsigned char *) &stream.nonce, stream.key); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
@ -581,7 +585,7 @@ randombytes_salsa20_random_buf(void * const buf, const size_t size) |
|
|
|
*/ |
|
|
|
|
|
|
|
static uint32_t |
|
|
|
randombytes_salsa20_random(void) |
|
|
|
randombytes_internal_random(void) |
|
|
|
{ |
|
|
|
uint32_t val; |
|
|
|
int ret; |
|
|
@ -590,16 +594,16 @@ randombytes_salsa20_random(void) |
|
|
|
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); |
|
|
|
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_salsa20_random_xorhwrand(); |
|
|
|
randombytes_salsa20_random_xorkey(&stream.rnd32[stream.rnd32_outleft]); |
|
|
|
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++; |
|
|
|
} |
|
|
@ -611,16 +615,16 @@ randombytes_salsa20_random(void) |
|
|
|
} |
|
|
|
|
|
|
|
static const char * |
|
|
|
randombytes_salsa20_implementation_name(void) |
|
|
|
randombytes_internal_implementation_name(void) |
|
|
|
{ |
|
|
|
return "salsa20"; |
|
|
|
return "internal"; |
|
|
|
} |
|
|
|
|
|
|
|
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, |
|
|
|
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_salsa20_random_buf, |
|
|
|
SODIUM_C99(.close =) randombytes_salsa20_random_close |
|
|
|
SODIUM_C99(.buf =) randombytes_internal_random_buf, |
|
|
|
SODIUM_C99(.close =) randombytes_internal_random_close |
|
|
|
}; |