19 #include "crypto_core_salsa20.h"
20 #include "crypto_auth_hmacsha512256.h"
21 #include "crypto_stream_salsa20.h"
22 #include "randombytes.h"
23 #include "randombytes_salsa20_random.h"
28 # include <sys/timeb.h>
29 # define RtlGenRandom SystemFunction036
30 # if defined(__cplusplus)
33 BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
34 # pragma comment(lib, "advapi32.lib")
37 #define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES
38 #define SHA512_BLOCK_SIZE 128U
39 #define SHA512_MIN_PAD_SIZE (1U + 16U)
40 #define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
42 typedef struct Salsa20Random_ {
43 unsigned char key[crypto_stream_salsa20_KEYBYTES];
44 unsigned char rnd32[16U * SALSA20_RANDOM_BLOCK_SIZE];
50 int random_data_source_fd;
54 static Salsa20Random stream = {
55 SODIUM_C99(.random_data_source_fd =) -1,
56 SODIUM_C99(.rnd32_outleft =) (size_t) 0U,
57 SODIUM_C99(.initialized =) 0
64 uint64_t ts = (uint64_t) 0U;
70 # pragma warning(push)
71 # pragma warning(disable: 4996)
74 tv.tv_sec = (long) tb.time;
75 tv.tv_usec = ((int) tb.millitm) * 1000;
78 ret = gettimeofday(&tv, NULL);
82 ts = (uint64_t) tv.tv_sec * 1000000U + (uint64_t) tv.tv_usec;
89 safe_read(const int fd, void * const buf_, size_t count)
91 unsigned char *buf = (unsigned char *) buf_;
94 assert(count > (size_t) 0U);
96 while ((readnb = read(fd, buf, count)) < (ssize_t) 0 &&
97 (errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
98 if (readnb < (ssize_t) 0) {
99 return readnb; /* LCOV_EXCL_LINE */
101 if (readnb == (ssize_t) 0) {
102 break; /* LCOV_EXCL_LINE */
104 count -= (size_t) readnb;
106 } while (count > (ssize_t) 0);
108 return (ssize_t) (buf - (unsigned char *) buf_);
114 randombytes_salsa20_random_random_dev_open(void)
116 /* LCOV_EXCL_START */
118 static const char *devices[] = {
119 # ifndef USE_BLOCKING_RANDOM
124 const char ** device = devices;
128 fd = open(*device, O_RDONLY);
130 if (fstat(fd, &st) == 0 && S_ISCHR(st.st_mode)) {
131 # if defined(F_SETFD) && defined(FD_CLOEXEC)
132 (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
137 } else if (errno == EINTR) {
141 } while (*device != NULL);
149 randombytes_salsa20_random_init(void)
151 const int errno_save = errno;
153 stream.nonce = sodium_hrtime();
154 assert(stream.nonce != (uint64_t) 0U);
156 if ((stream.random_data_source_fd =
157 randombytes_salsa20_random_random_dev_open()) == -1) {
158 abort(); /* LCOV_EXCL_LINE */
166 randombytes_salsa20_random_init(void)
168 stream.nonce = sodium_hrtime();
169 assert(stream.nonce != (uint64_t) 0U);
174 randombytes_salsa20_random_stir(void)
176 const unsigned char s[crypto_auth_hmacsha512256_KEYBYTES] = {
177 'T', 'h', 'i', 's', 'I', 's', 'J', 'u', 's', 't', 'A', 'T',
178 'h', 'i', 'r', 't', 'y', 'T', 'w', 'o', 'B', 'y', 't', 'e',
179 's', 'S', 'e', 'e', 'd', '.', '.', '.'
181 unsigned char m0[crypto_auth_hmacsha512256_BYTES +
182 2U * SHA512_BLOCK_SIZE - SHA512_MIN_PAD_SIZE];
183 unsigned char *k0 = m0 + crypto_auth_hmacsha512256_BYTES;
185 size_t sizeof_k0 = sizeof m0 - crypto_auth_hmacsha512256_BYTES;
187 memset(stream.rnd32, 0, sizeof stream.rnd32);
188 stream.rnd32_outleft = (size_t) 0U;
189 if (stream.initialized == 0) {
190 randombytes_salsa20_random_init();
191 stream.initialized = 1;
194 if (safe_read(stream.random_data_source_fd, m0,
195 sizeof m0) != (ssize_t) sizeof m0) {
196 abort(); /* LCOV_EXCL_LINE */
199 if (! RtlGenRandom((PVOID) m0, (ULONG) sizeof m0)) {
200 abort(); /* LCOV_EXCL_LINE */
203 COMPILER_ASSERT(sizeof stream.key == crypto_auth_hmacsha512256_BYTES);
204 crypto_auth_hmacsha512256(stream.key, k0, sizeof_k0, s);
205 COMPILER_ASSERT(sizeof stream.key <= sizeof m0);
206 for (i = (size_t) 0U; i < sizeof stream.key; i++) {
207 stream.key[i] ^= m0[i];
209 sodium_memzero(m0, sizeof m0);
213 randombytes_salsa20_random_stir_if_needed(void)
216 if (stream.initialized == 0) {
217 randombytes_salsa20_random_stir();
220 const pid_t pid = getpid();
222 if (stream.initialized == 0 || stream.pid != pid) {
224 randombytes_salsa20_random_stir();
230 randombytes_salsa20_random_rekey(const unsigned char * const mix)
232 unsigned char *key = stream.key;
235 for (i = (size_t) 0U; i < sizeof stream.key; i++) {
241 randombytes_salsa20_random_getword(void)
246 COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val));
247 COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key))
248 % sizeof val == (size_t) 0U);
249 if (stream.rnd32_outleft <= (size_t) 0U) {
250 randombytes_salsa20_random_stir_if_needed();
251 COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES);
252 ret = crypto_stream_salsa20((unsigned char *) stream.rnd32,
253 (unsigned long long) sizeof stream.rnd32,
254 (unsigned char *) &stream.nonce,
257 stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key);
258 randombytes_salsa20_random_rekey(&stream.rnd32[stream.rnd32_outleft]);
261 stream.rnd32_outleft -= sizeof val;
262 memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val);
263 memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val);
269 randombytes_salsa20_random_close(void)
274 if (stream.random_data_source_fd != -1 &&
275 close(stream.random_data_source_fd) == 0) {
276 stream.random_data_source_fd = -1;
277 stream.initialized = 0;
281 if (stream.initialized != 0) {
282 stream.initialized = 0;
290 randombytes_salsa20_random(void)
292 return randombytes_salsa20_random_getword();
296 randombytes_salsa20_random_buf(void * const buf, const size_t size)
300 randombytes_salsa20_random_stir_if_needed();
301 COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES);
302 #ifdef ULONG_LONG_MAX
303 /* coverity[result_independent_of_operands] */
304 assert(size <= ULONG_LONG_MAX);
306 ret = crypto_stream_salsa20((unsigned char *) buf, (unsigned long long) size,
307 (unsigned char *) &stream.nonce, stream.key);
310 crypto_stream_salsa20_xor(stream.key, stream.key, sizeof stream.key,
311 (unsigned char *) &stream.nonce, stream.key);
315 * randombytes_salsa20_random_uniform() derives from OpenBSD's arc4random_uniform()
320 randombytes_salsa20_random_uniform(const uint32_t upper_bound)
325 if (upper_bound < 2) {
328 min = (uint32_t) (-upper_bound % upper_bound);
330 r = randombytes_salsa20_random();
334 } /* LCOV_EXCL_LINE */
335 return r % upper_bound;
339 randombytes_salsa20_implementation_name(void)
344 struct randombytes_implementation randombytes_salsa20_implementation = {
345 SODIUM_C99(.implementation_name =) randombytes_salsa20_implementation_name,
346 SODIUM_C99(.random =) randombytes_salsa20_random,
347 SODIUM_C99(.stir =) randombytes_salsa20_random_stir,
348 SODIUM_C99(.uniform =) randombytes_salsa20_random_uniform,
349 SODIUM_C99(.buf =) randombytes_salsa20_random_buf,
350 SODIUM_C99(.close =) randombytes_salsa20_random_close