2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #define BR_ENABLE_INTRINSICS 1
29 #include <sys/types.h>
38 #pragma comment(lib, "advapi32")
45 seeder_rdrand(const br_prng_class
**ctx
)
47 unsigned char tmp
[32];
50 for (u
= 0; u
< sizeof tmp
; u
+= sizeof(uint32_t)) {
55 * We use the 32-bit intrinsic so that code is compatible
56 * with both 32-bit and 64-bit architectures.
58 * Intel recommends trying at least 10 times in case of
61 for (j
= 0; j
< 10; j
++) {
62 if (_rdrand32_step(&x
)) {
68 br_enc32le(tmp
+ u
, x
);
70 (*ctx
)->update(ctx
, tmp
, sizeof tmp
);
76 rdrand_supported(void)
79 * The RDRND support is bit 30 of ECX, as returned by CPUID.
81 return br_cpuid(0, 0, 0x40000000, 0);
88 seeder_urandom(const br_prng_class
**ctx
)
92 f
= open("/dev/urandom", O_RDONLY
);
94 unsigned char tmp
[32];
97 for (u
= 0; u
< sizeof tmp
;) {
100 len
= read(f
, tmp
+ u
, (sizeof tmp
) - u
);
102 if (errno
== EINTR
) {
110 if (u
== sizeof tmp
) {
111 (*ctx
)->update(ctx
, tmp
, sizeof tmp
);
119 #if BR_USE_WIN32_RAND
121 seeder_win32(const br_prng_class
**ctx
)
125 if (CryptAcquireContext(&hp
, 0, 0, PROV_RSA_FULL
,
126 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
131 r
= CryptGenRandom(hp
, sizeof buf
, buf
);
132 CryptReleaseContext(hp
, 0);
134 (*ctx
)->update(ctx
, buf
, sizeof buf
);
142 /* see bearssl_rand.h.h */
144 br_prng_seeder_system(const char **name
)
147 if (rdrand_supported()) {
151 return &seeder_rdrand
;
158 return &seeder_urandom
;
159 #elif BR_USE_WIN32_RAND
163 return &seeder_win32
;