18 #include "randombytes.h"
19 #include "randombytes_sysrandom.h"
24 # include <Wincrypt.h>
27 typedef struct SysRandom_
{
29 HCRYPTPROV hcrypt_prov
;
31 int random_data_source_fd
;
35 static SysRandom stream
= {
36 _SODIUM_C99(.random_data_source_fd
=) -1,
37 _SODIUM_C99(.initialized
=) 0
42 safe_read(const int fd
, void * const buf_
, size_t count
)
44 unsigned char *buf
= (unsigned char *) buf_
;
48 while ((readnb
= read(fd
, buf
, count
)) < (ssize_t
) 0 &&
50 if (readnb
< (ssize_t
) 0) {
53 if (readnb
== (ssize_t
) 0) {
56 count
-= (size_t) readnb
;
58 } while (count
> (ssize_t
) 0);
60 return (ssize_t
) (buf
- (unsigned char *) buf_
);
66 randombytes_sysrandom_random_dev_open(void)
68 static const char * const devices
[] = {
69 # ifndef USE_BLOCKING_RANDOM
70 "/dev/arandom", "/dev/urandom",
74 const char * const *device
= devices
;
77 if (access(*device
, F_OK
| R_OK
) == 0) {
78 return open(*device
, O_RDONLY
);
81 } while (*device
!= NULL
);
87 randombytes_sysrandom_init(void)
89 if ((stream
.random_data_source_fd
=
90 randombytes_sysrandom_random_dev_open()) == -1) {
98 randombytes_sysrandom_init(void)
100 if (! CryptAcquireContext(&stream
.hcrypt_prov
, NULL
, NULL
,
101 PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
)) {
108 randombytes_sysrandom_stir(void)
110 if (stream
.initialized
== 0) {
111 randombytes_sysrandom_init();
112 stream
.initialized
= 1;
117 randombytes_sysrandom_stir_if_needed(void)
119 if (stream
.initialized
== 0) {
120 randombytes_sysrandom_stir();
125 randombytes_sysrandom_close(void)
130 if (stream
.random_data_source_fd
!= -1 &&
131 close(stream
.random_data_source_fd
) == 0) {
132 stream
.random_data_source_fd
= -1;
133 stream
.initialized
= 0;
137 if (stream
.initialized
!= 0 &&
138 CryptReleaseContext(stream
.hcrypt_prov
, 0)) {
139 stream
.initialized
= 0;
147 randombytes_sysrandom(void)
151 randombytes_sysrandom_buf(&r
, sizeof r
);
157 randombytes_sysrandom_buf(void * const buf
, const size_t size
)
159 randombytes_sysrandom_stir_if_needed();
160 #ifdef ULONG_LONG_MAX
161 assert(size
<= ULONG_LONG_MAX
);
164 if (safe_read(stream
.random_data_source_fd
, buf
, size
) != (ssize_t
) size
) {
168 if (! CryptGenRandom(stream
.hcrypt_prov
, size
, buf
)) {
175 * randombytes_sysrandom_uniform() derives from OpenBSD's arc4random_uniform()
176 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
180 randombytes_sysrandom_uniform(const uint32_t upper_bound
)
185 if (upper_bound
< 2) {
188 min
= (uint32_t) (-upper_bound
% upper_bound
);
190 r
= randombytes_sysrandom();
195 return r
% upper_bound
;
199 randombytes_sysrandom_implementation_name(void)
204 struct randombytes_implementation randombytes_sysrandom_implementation
= {
205 _SODIUM_C99(.implementation_name
=) randombytes_sysrandom_implementation_name
,
206 _SODIUM_C99(.random
=) randombytes_sysrandom
,
207 _SODIUM_C99(.stir
=) randombytes_sysrandom_stir
,
208 _SODIUM_C99(.uniform
=) randombytes_sysrandom_uniform
,
209 _SODIUM_C99(.buf
=) randombytes_sysrandom_buf
,
210 _SODIUM_C99(.close
=) randombytes_sysrandom_close