Get 32 bytes of system entropy. */
| 273 | |
| 274 | /** Get 32 bytes of system entropy. */ |
| 275 | void GetOSRand(unsigned char *ent32) |
| 276 | { |
| 277 | #if defined(WIN32) |
| 278 | HCRYPTPROV hProvider; |
| 279 | int ret = CryptAcquireContextW(&hProvider, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); |
| 280 | if (!ret) { |
| 281 | RandFailure(); |
| 282 | } |
| 283 | ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32); |
| 284 | if (!ret) { |
| 285 | RandFailure(); |
| 286 | } |
| 287 | CryptReleaseContext(hProvider, 0); |
| 288 | #elif defined(HAVE_SYS_GETRANDOM) |
| 289 | /* Linux. From the getrandom(2) man page: |
| 290 | * "If the urandom source has been initialized, reads of up to 256 bytes |
| 291 | * will always return as many bytes as requested and will not be |
| 292 | * interrupted by signals." |
| 293 | */ |
| 294 | int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0); |
| 295 | if (rv != NUM_OS_RANDOM_BYTES) { |
| 296 | if (rv < 0 && errno == ENOSYS) { |
| 297 | /* Fallback for kernel <3.17: the return value will be -1 and errno |
| 298 | * ENOSYS if the syscall is not available, in that case fall back |
| 299 | * to /dev/urandom. |
| 300 | */ |
| 301 | GetDevURandom(ent32); |
| 302 | } else { |
| 303 | RandFailure(); |
| 304 | } |
| 305 | } |
| 306 | #elif defined(__OpenBSD__) |
| 307 | /* OpenBSD. From the arc4random(3) man page: |
| 308 | "Use of these functions is encouraged for almost all random number |
| 309 | consumption because the other interfaces are deficient in either |
| 310 | quality, portability, standardization, or availability." |
| 311 | The function call is always successful. |
| 312 | */ |
| 313 | arc4random_buf(ent32, NUM_OS_RANDOM_BYTES); |
| 314 | // Silence a compiler warning about unused function. |
| 315 | (void)GetDevURandom; |
| 316 | #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) |
| 317 | /* getentropy() is available on macOS 10.12 and later. |
| 318 | */ |
| 319 | if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { |
| 320 | RandFailure(); |
| 321 | } |
| 322 | // Silence a compiler warning about unused function. |
| 323 | (void)GetDevURandom; |
| 324 | #elif defined(HAVE_SYSCTL_ARND) |
| 325 | /* FreeBSD, NetBSD and similar. It is possible for the call to return less |
| 326 | * bytes than requested, so need to read in a loop. |
| 327 | */ |
| 328 | static int name[2] = {CTL_KERN, KERN_ARND}; |
| 329 | int have = 0; |
| 330 | do { |
| 331 | size_t len = NUM_OS_RANDOM_BYTES - have; |
| 332 | if (sysctl(name, std::size(name), ent32 + have, &len, nullptr, 0) != 0) { |
no test coverage detected