diff options
author | Micah Anderson <micah@riseup.net> | 2014-08-11 13:49:21 -0400 |
---|---|---|
committer | Micah Anderson <micah@riseup.net> | 2014-08-11 13:49:21 -0400 |
commit | 2e59f9740a29439df7c7a56cf0ae83dec3081d31 (patch) | |
tree | d5e7c4e74c9a0f1ea999327d2e68b1dd27be00e0 /src/libsodium/randombytes |
initial import of debian version from mentors0.6.1
Diffstat (limited to 'src/libsodium/randombytes')
-rw-r--r-- | src/libsodium/randombytes/randombytes.c | 65 | ||||
-rw-r--r-- | src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c | 324 | ||||
-rw-r--r-- | src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c | 257 |
3 files changed, 646 insertions, 0 deletions
diff --git a/src/libsodium/randombytes/randombytes.c b/src/libsodium/randombytes/randombytes.c new file mode 100644 index 0000000..07e2341 --- /dev/null +++ b/src/libsodium/randombytes/randombytes.c @@ -0,0 +1,65 @@ + +#include <sys/types.h> + +#include <assert.h> +#include <limits.h> +#include <stdint.h> + +#include "randombytes.h" +#include "randombytes_sysrandom.h" + +static const randombytes_implementation *implementation = + &randombytes_sysrandom_implementation; + +int +randombytes_set_implementation(randombytes_implementation *impl) +{ + implementation = impl; + + return 0; +} + +const char * +randombytes_implementation_name(void) +{ + return implementation->implementation_name(); +} + +uint32_t +randombytes_random(void) +{ + return implementation->random(); +} + +void +randombytes_stir(void) +{ + implementation->stir(); +} + +uint32_t +randombytes_uniform(const uint32_t upper_bound) +{ + return implementation->uniform(upper_bound); +} + +void +randombytes_buf(void * const buf, const size_t size) +{ + if (size > (size_t) 0U) { + implementation->buf(buf, size); + } +} + +int +randombytes_close(void) +{ + return implementation->close(); +} + +void +randombytes(unsigned char * const buf, const unsigned long long buf_len) +{ + assert(buf_len <= SIZE_MAX); + randombytes_buf(buf, (size_t) buf_len); +} diff --git a/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c b/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c new file mode 100644 index 0000000..374ff4d --- /dev/null +++ b/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c @@ -0,0 +1,324 @@ + +#include <sys/types.h> +#ifndef _WIN32 +# include <sys/stat.h> +# include <sys/time.h> +#endif + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#ifndef _MSC_VER +# include <unistd.h> +#endif + +#include "crypto_core_salsa20.h" +#include "crypto_auth_hmacsha512256.h" +#include "crypto_stream_salsa20.h" +#include "randombytes.h" +#include "randombytes_salsa20_random.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") +#endif + +#define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES +#define SHA512_BLOCK_SIZE 128U +#define SHA512_MIN_PAD_SIZE (1U + 16U) +#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1]) + +typedef struct Salsa20Random_ { + unsigned char key[crypto_stream_salsa20_KEYBYTES]; + unsigned char rnd32[SALSA20_RANDOM_BLOCK_SIZE]; + uint64_t nonce; + size_t rnd32_outleft; +#ifndef _MSC_VER + pid_t pid; +#endif + int random_data_source_fd; + int initialized; +} Salsa20Random; + +static Salsa20Random stream = { + _SODIUM_C99(.random_data_source_fd =) -1, + _SODIUM_C99(.rnd32_outleft =) (size_t) 0U, + _SODIUM_C99(.initialized =) 0 +}; + +static uint64_t +sodium_hrtime(void) +{ + struct timeval tv; + uint64_t ts = (uint64_t) 0U; + int ret; + +#ifdef _WIN32 + struct _timeb tb; + + _ftime(&tb); + tv.tv_sec = (long) tb.time; + tv.tv_usec = ((int) tb.millitm) * 1000; + ret = 0; +#else + ret = gettimeofday(&tv, NULL); +#endif + assert(ret == 0); + if (ret == 0) { + ts = (uint64_t) tv.tv_sec * 1000000U + (uint64_t) tv.tv_usec; + } + return ts; +} + +#ifndef _WIN32 +static ssize_t +safe_read(const int fd, void * const buf_, size_t count) +{ + unsigned char *buf = (unsigned char *) buf_; + ssize_t readnb; + + assert(count > (size_t) 0U); + do { + while ((readnb = read(fd, buf, count)) < (ssize_t) 0 && + errno == EINTR); + if (readnb < (ssize_t) 0) { + return readnb; + } + if (readnb == (ssize_t) 0) { + break; + } + count -= (size_t) readnb; + buf += readnb; + } while (count > (ssize_t) 0); + + return (ssize_t) (buf - (unsigned char *) buf_); +} +#endif + +#ifndef _WIN32 +static int +randombytes_salsa20_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; + + do { + if ((fd = open(*device, O_RDONLY)) != -1) { + if (fstat(fd, &st) == 0 && S_ISCHR(st.st_mode)) { + return fd; + } + (void) close(fd); + } + device++; + } while (*device != NULL); + + return -1; +} + +static void +randombytes_salsa20_random_init(void) +{ + const int errno_save = errno; + + stream.nonce = sodium_hrtime(); + assert(stream.nonce != (uint64_t) 0U); + + if ((stream.random_data_source_fd = + randombytes_salsa20_random_random_dev_open()) == -1) { + abort(); + } + errno = errno_save; +} + +#else /* _WIN32 */ + +static void +randombytes_salsa20_random_init(void) +{ + stream.nonce = sodium_hrtime(); + assert(stream.nonce != (uint64_t) 0U); +} +#endif + +void +randombytes_salsa20_random_stir(void) +{ + const unsigned char s[crypto_auth_hmacsha512256_KEYBYTES] = { + 'T', 'h', 'i', 's', 'I', 's', 'J', 'u', 's', 't', 'A', 'T', + 'h', 'i', 'r', 't', 'y', 'T', 'w', 'o', 'B', 'y', 't', 'e', + 's', 'S', 'e', 'e', 'd', '.', '.', '.' + }; + unsigned char m0[crypto_auth_hmacsha512256_BYTES + + 2U * SHA512_BLOCK_SIZE - SHA512_MIN_PAD_SIZE]; + unsigned char *k0 = m0 + crypto_auth_hmacsha512256_BYTES; + size_t i; + size_t sizeof_k0 = sizeof m0 - crypto_auth_hmacsha512256_BYTES; + + memset(stream.rnd32, 0, sizeof stream.rnd32); + stream.rnd32_outleft = (size_t) 0U; + if (stream.initialized == 0) { + randombytes_salsa20_random_init(); + stream.initialized = 1; + } +#ifndef _WIN32 + if (safe_read(stream.random_data_source_fd, m0, + sizeof m0) != (ssize_t) sizeof m0) { + abort(); + } +#else /* _WIN32 */ + if (! RtlGenRandom((PVOID) m0, (ULONG) sizeof m0)) { + abort(); + } +#endif + COMPILER_ASSERT(sizeof stream.key == crypto_auth_hmacsha512256_BYTES); + crypto_auth_hmacsha512256(stream.key, k0, sizeof_k0, s); + COMPILER_ASSERT(sizeof stream.key <= sizeof m0); + for (i = (size_t) 0U; i < sizeof stream.key; i++) { + stream.key[i] ^= m0[i]; + } + sodium_memzero(m0, sizeof m0); +} + +static void +randombytes_salsa20_random_stir_if_needed(void) +{ +#ifdef _MSC_VER + if (stream.initialized == 0) { + randombytes_salsa20_random_stir(); + } +#else + const pid_t pid = getpid(); + + if (stream.initialized == 0 || stream.pid != pid) { + stream.pid = pid; + randombytes_salsa20_random_stir(); + } +#endif +} + +static uint32_t +randombytes_salsa20_random_getword(void) +{ + uint32_t val; + int ret; + + COMPILER_ASSERT(sizeof stream.rnd32 >= sizeof val); + COMPILER_ASSERT(sizeof stream.rnd32 % 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.nonce++; + stream.rnd32_outleft = sizeof stream.rnd32; + } + stream.rnd32_outleft -= sizeof val; + memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val); + + return val; +} + +int +randombytes_salsa20_random_close(void) +{ + int ret = -1; + +#ifndef _WIN32 + if (stream.random_data_source_fd != -1 && + close(stream.random_data_source_fd) == 0) { + stream.random_data_source_fd = -1; + stream.initialized = 0; + ret = 0; + } +#else /* _WIN32 */ + if (stream.initialized != 0) { + stream.initialized = 0; + ret = 0; + } +#endif + return ret; +} + +uint32_t +randombytes_salsa20_random(void) +{ + return randombytes_salsa20_random_getword(); +} + +void +randombytes_salsa20_random_buf(void * const buf, const size_t size) +{ + int ret; + + randombytes_salsa20_random_stir_if_needed(); + COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES); +#ifdef ULONG_LONG_MAX + /* coverity[result_independent_of_operands] */ + assert(size <= ULONG_LONG_MAX); +#endif + ret = crypto_stream_salsa20((unsigned char *) buf, (unsigned long long) size, + (unsigned char *) &stream.nonce, + stream.key); + assert(ret == 0); + stream.nonce++; +} + +/* + * randombytes_salsa20_random_uniform() derives from OpenBSD's arc4random_uniform() + * Copyright (c) 2008, Damien Miller <djm@openbsd.org> + */ + +uint32_t +randombytes_salsa20_random_uniform(const uint32_t upper_bound) +{ + uint32_t min; + uint32_t r; + + if (upper_bound < 2) { + return 0; + } + min = (uint32_t) (-upper_bound % upper_bound); + for (;;) { + r = randombytes_salsa20_random(); + if (r >= min) { + break; + } + } + return r % upper_bound; +} + +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 =) randombytes_salsa20_random_uniform, + _SODIUM_C99(.buf =) randombytes_salsa20_random_buf, + _SODIUM_C99(.close =) randombytes_salsa20_random_close +}; diff --git a/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c b/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c new file mode 100644 index 0000000..0ffcc2e --- /dev/null +++ b/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c @@ -0,0 +1,257 @@ + +#include <sys/types.h> +#ifndef _WIN32 +# include <sys/stat.h> +# include <sys/time.h> +#endif + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#ifndef _WIN32 +# include <unistd.h> +#endif + +#include "randombytes.h" +#include "randombytes_sysrandom.h" +#include "utils.h" + +#ifdef _WIN32 +# include <windows.h> +# define RtlGenRandom SystemFunction036 +# if defined(__cplusplus) +extern "C" +# endif +BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); +# pragma comment(lib, "advapi32.lib") +#endif + +#ifdef __OpenBSD__ + +uint32_t +randombytes_sysrandom(void) +{ + return arc4random(); +} + +void +randombytes_sysrandom_stir(void) +{ +} + +uint32_t +randombytes_sysrandom_uniform(const uint32_t upper_bound) +{ + return arc4random_uniform(upper_bound); +} + +void +randombytes_sysrandom_buf(void * const buf, const size_t size) +{ + return arc4random_buf(buf, size); +} + +int +randombytes_sysrandom_close(void) +{ + return 0; +} + +#else /* __OpenBSD__ */ + +typedef struct SysRandom_ { + int random_data_source_fd; + int initialized; +} SysRandom; + +static SysRandom stream = { + _SODIUM_C99(.random_data_source_fd =) -1, + _SODIUM_C99(.initialized =) 0 +}; + +#ifndef _WIN32 +static ssize_t +safe_read(const int fd, void * const buf_, size_t count) +{ + unsigned char *buf = (unsigned char *) buf_; + ssize_t readnb; + + assert(count > (size_t) 0U); + do { + while ((readnb = read(fd, buf, count)) < (ssize_t) 0 && + errno == EINTR); + if (readnb < (ssize_t) 0) { + return readnb; + } + if (readnb == (ssize_t) 0) { + break; + } + count -= (size_t) readnb; + buf += readnb; + } while (count > (ssize_t) 0); + + return (ssize_t) (buf - (unsigned char *) buf_); +} +#endif + +#ifndef _WIN32 +static int +randombytes_sysrandom_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; + + do { + if ((fd = open(*device, O_RDONLY)) != -1) { + if (fstat(fd, &st) == 0 && S_ISCHR(st.st_mode)) { + return fd; + } + (void) close(fd); + } + device++; + } while (*device != NULL); + + return -1; +} + +static void +randombytes_sysrandom_init(void) +{ + const int errno_save = errno; + + if ((stream.random_data_source_fd = + randombytes_sysrandom_random_dev_open()) == -1) { + abort(); + } + errno = errno_save; +} + +#else /* _WIN32 */ + +static void +randombytes_sysrandom_init(void) +{ +} +#endif + +void +randombytes_sysrandom_stir(void) +{ + if (stream.initialized == 0) { + randombytes_sysrandom_init(); + stream.initialized = 1; + } +} + +static void +randombytes_sysrandom_stir_if_needed(void) +{ + if (stream.initialized == 0) { + randombytes_sysrandom_stir(); + } +} + +int +randombytes_sysrandom_close(void) +{ + int ret = -1; + +#ifndef _WIN32 + if (stream.random_data_source_fd != -1 && + close(stream.random_data_source_fd) == 0) { + stream.random_data_source_fd = -1; + stream.initialized = 0; + ret = 0; + } +#else /* _WIN32 */ + if (stream.initialized != 0) { + stream.initialized = 0; + ret = 0; + } +#endif + return ret; +} + +uint32_t +randombytes_sysrandom(void) +{ + uint32_t r; + + randombytes_sysrandom_buf(&r, sizeof r); + + return r; +} + +void +randombytes_sysrandom_buf(void * const buf, const size_t size) +{ + randombytes_sysrandom_stir_if_needed(); +#ifdef ULONG_LONG_MAX + /* coverity[result_independent_of_operands] */ + assert(size <= ULONG_LONG_MAX); +#endif +#ifndef _WIN32 + if (safe_read(stream.random_data_source_fd, buf, size) != (ssize_t) size) { + abort(); + } +#else + if (size > 0xffffffff) { + abort(); + } + if (! RtlGenRandom((PVOID) buf, (ULONG) size)) { + abort(); + } +#endif +} + +/* + * randombytes_sysrandom_uniform() derives from OpenBSD's arc4random_uniform() + * Copyright (c) 2008, Damien Miller <djm@openbsd.org> + */ + +uint32_t +randombytes_sysrandom_uniform(const uint32_t upper_bound) +{ + uint32_t min; + uint32_t r; + + if (upper_bound < 2) { + return 0; + } + min = (uint32_t) (-upper_bound % upper_bound); + for (;;) { + r = randombytes_sysrandom(); + if (r >= min) { + break; + } + } + return r % upper_bound; +} + +#endif + +const char * +randombytes_sysrandom_implementation_name(void) +{ + return "sysrandom"; +} + +struct randombytes_implementation randombytes_sysrandom_implementation = { + _SODIUM_C99(.implementation_name =) randombytes_sysrandom_implementation_name, + _SODIUM_C99(.random =) randombytes_sysrandom, + _SODIUM_C99(.stir =) randombytes_sysrandom_stir, + _SODIUM_C99(.uniform =) randombytes_sysrandom_uniform, + _SODIUM_C99(.buf =) randombytes_sysrandom_buf, + _SODIUM_C99(.close =) randombytes_sysrandom_close +}; |