15 #include "crypto_core_salsa20.h"
16 #include "crypto_auth_hmacsha512256.h"
17 #include "crypto_stream_salsa20.h"
18 #include "randombytes.h"
19 #include "randombytes_salsa20_random.h"
24 # include <Wincrypt.h>
25 # include <sys/timeb.h>
28 #define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES
29 #define SHA512_BLOCK_SIZE 128U
30 #define SHA512_MIN_PAD_SIZE (1U + 16U)
31 #define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
33 typedef struct Salsa20Random_
{
34 unsigned char key
[crypto_stream_salsa20_KEYBYTES
];
35 unsigned char rnd32
[SALSA20_RANDOM_BLOCK_SIZE
];
40 HCRYPTPROV hcrypt_prov
;
42 int random_data_source_fd
;
46 static Salsa20Random stream
= {
47 _SODIUM_C99(.random_data_source_fd
=) -1,
48 _SODIUM_C99(.rnd32_outleft
=) (size_t) 0U,
49 _SODIUM_C99(.initialized
=) 0
56 uint64_t ts
= (uint64_t) 0U;
63 tv
.tv_sec
= (long) tb
.time
;
64 tv
.tv_usec
= ((int) tb
.millitm
) * 1000;
67 ret
= gettimeofday(&tv
, NULL
);
71 ts
= (uint64_t) tv
.tv_sec
* 1000000U + (uint64_t) tv
.tv_usec
;
78 safe_read(const int fd
, void * const buf_
, size_t count
)
80 unsigned char *buf
= (unsigned char *) buf_
;
84 while ((readnb
= read(fd
, buf
, count
)) < (ssize_t
) 0 &&
86 if (readnb
< (ssize_t
) 0) {
89 if (readnb
== (ssize_t
) 0) {
92 count
-= (size_t) readnb
;
94 } while (count
> (ssize_t
) 0);
96 return (ssize_t
) (buf
- (unsigned char *) buf_
);
102 randombytes_salsa20_random_random_dev_open(void)
104 static const char * const devices
[] = {
105 # ifndef USE_BLOCKING_RANDOM
106 "/dev/arandom", "/dev/urandom",
110 const char * const *device
= devices
;
113 if (access(*device
, F_OK
| R_OK
) == 0) {
114 return open(*device
, O_RDONLY
);
117 } while (*device
!= NULL
);
123 randombytes_salsa20_random_init(void)
125 stream
.nonce
= sodium_hrtime();
126 assert(stream
.nonce
!= (uint64_t) 0U);
128 if ((stream
.random_data_source_fd
=
129 randombytes_salsa20_random_random_dev_open()) == -1) {
137 randombytes_salsa20_random_init(void)
139 stream
.nonce
= sodium_hrtime();
140 assert(stream
.nonce
!= (uint64_t) 0U);
142 if (! CryptAcquireContext(&stream
.hcrypt_prov
, NULL
, NULL
,
143 PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
)) {
150 randombytes_salsa20_random_stir(void)
152 const unsigned char s
[crypto_auth_hmacsha512256_KEYBYTES
] = {
153 'T', 'h', 'i', 's', 'I', 's', 'J', 'u', 's', 't', 'A', 'T',
154 'h', 'i', 'r', 't', 'y', 'T', 'w', 'o', 'B', 'y', 't', 'e',
155 's', 'S', 'e', 'e', 'd', '.', '.', '.'
157 unsigned char m0
[crypto_auth_hmacsha512256_BYTES
+
158 2U * SHA512_BLOCK_SIZE
- SHA512_MIN_PAD_SIZE
];
159 unsigned char *k0
= m0
+ crypto_auth_hmacsha512256_BYTES
;
161 size_t sizeof_k0
= sizeof m0
- crypto_auth_hmacsha512256_BYTES
;
163 memset(stream
.rnd32
, 0, sizeof stream
.rnd32
);
164 stream
.rnd32_outleft
= (size_t) 0U;
165 if (stream
.initialized
== 0) {
166 randombytes_salsa20_random_init();
167 stream
.initialized
= 1;
170 if (safe_read(stream
.random_data_source_fd
, m0
,
171 sizeof m0
) != (ssize_t
) sizeof m0
) {
175 if (! CryptGenRandom(stream
.hcrypt_prov
, sizeof m0
, m0
)) {
179 COMPILER_ASSERT(sizeof stream
.key
== crypto_auth_hmacsha512256_BYTES
);
180 crypto_auth_hmacsha512256(stream
.key
, k0
, sizeof_k0
, s
);
181 COMPILER_ASSERT(sizeof stream
.key
<= sizeof m0
);
182 for (i
= (size_t) 0U; i
< sizeof stream
.key
; i
++) {
183 stream
.key
[i
] ^= m0
[i
];
185 sodium_memzero(m0
, sizeof m0
);
189 randombytes_salsa20_random_stir_if_needed(void)
191 const pid_t pid
= getpid();
193 if (stream
.initialized
== 0 || stream
.pid
!= pid
) {
195 randombytes_salsa20_random_stir();
200 randombytes_salsa20_random_getword(void)
205 COMPILER_ASSERT(sizeof stream
.rnd32
>= sizeof val
);
206 COMPILER_ASSERT(sizeof stream
.rnd32
% sizeof val
== (size_t) 0U);
207 if (stream
.rnd32_outleft
<= (size_t) 0U) {
208 randombytes_salsa20_random_stir_if_needed();
209 COMPILER_ASSERT(sizeof stream
.nonce
== crypto_stream_salsa20_NONCEBYTES
);
210 ret
= crypto_stream_salsa20((unsigned char *) stream
.rnd32
,
211 (unsigned long long) sizeof stream
.rnd32
,
212 (unsigned char *) &stream
.nonce
,
216 stream
.rnd32_outleft
= sizeof stream
.rnd32
;
218 stream
.rnd32_outleft
-= sizeof val
;
219 memcpy(&val
, &stream
.rnd32
[stream
.rnd32_outleft
], sizeof val
);
225 randombytes_salsa20_random_close(void)
230 if (stream
.random_data_source_fd
!= -1 &&
231 close(stream
.random_data_source_fd
) == 0) {
232 stream
.random_data_source_fd
= -1;
233 stream
.initialized
= 0;
237 if (stream
.initialized
!= 0 &&
238 CryptReleaseContext(stream
.hcrypt_prov
, 0)) {
239 stream
.initialized
= 0;
247 randombytes_salsa20_random(void)
249 return randombytes_salsa20_random_getword();
253 randombytes_salsa20_random_buf(void * const buf
, const size_t size
)
257 randombytes_salsa20_random_stir_if_needed();
258 COMPILER_ASSERT(sizeof stream
.nonce
== crypto_stream_salsa20_NONCEBYTES
);
259 #ifdef ULONG_LONG_MAX
260 assert(size
<= ULONG_LONG_MAX
);
262 ret
= crypto_stream_salsa20((unsigned char *) buf
, (unsigned long long) size
,
263 (unsigned char *) &stream
.nonce
,
270 * randombytes_salsa20_random_uniform() derives from OpenBSD's arc4random_uniform()
271 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
275 randombytes_salsa20_random_uniform(const uint32_t upper_bound
)
280 if (upper_bound
< 2) {
283 min
= (uint32_t) (-upper_bound
% upper_bound
);
285 r
= randombytes_salsa20_random();
290 return r
% upper_bound
;
294 randombytes_salsa20_implementation_name(void)
299 struct randombytes_implementation randombytes_salsa20_implementation
= {
300 _SODIUM_C99(.implementation_name
=) randombytes_salsa20_implementation_name
,
301 _SODIUM_C99(.random
=) randombytes_salsa20_random
,
302 _SODIUM_C99(.stir
=) randombytes_salsa20_random_stir
,
303 _SODIUM_C99(.uniform
=) randombytes_salsa20_random_uniform
,
304 _SODIUM_C99(.buf
=) randombytes_salsa20_random_buf
,
305 _SODIUM_C99(.close
=) randombytes_salsa20_random_close