|
|
|
@@ -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
|
|
|
|
|
};
|