Get 32 bytes of system entropy. */
| 284 | |
| 285 | /** Get 32 bytes of system entropy. */ |
| 286 | void GetOSRand(unsigned char *ent32) |
| 287 | { |
| 288 | #if defined(WIN32) |
| 289 | constexpr uint32_t STATUS_SUCCESS{0x00000000}; |
| 290 | NTSTATUS status = BCryptGenRandom(/*hAlgorithm=*/NULL, |
| 291 | /*pbBuffer=*/ent32, |
| 292 | /*cbBuffer=*/NUM_OS_RANDOM_BYTES, |
| 293 | /*dwFlags=*/BCRYPT_USE_SYSTEM_PREFERRED_RNG); |
| 294 | |
| 295 | if (status != STATUS_SUCCESS) { |
| 296 | RandFailure(); |
| 297 | } |
| 298 | #elif defined(HAVE_GETRANDOM) |
| 299 | /* Linux. From the getrandom(2) man page: |
| 300 | * "If the urandom source has been initialized, reads of up to 256 bytes |
| 301 | * will always return as many bytes as requested and will not be |
| 302 | * interrupted by signals." |
| 303 | */ |
| 304 | if (getrandom(ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) { |
| 305 | RandFailure(); |
| 306 | } |
| 307 | #elif defined(__OpenBSD__) |
| 308 | /* OpenBSD. From the arc4random(3) man page: |
| 309 | "Use of these functions is encouraged for almost all random number |
| 310 | consumption because the other interfaces are deficient in either |
| 311 | quality, portability, standardization, or availability." |
| 312 | The function call is always successful. |
| 313 | */ |
| 314 | arc4random_buf(ent32, NUM_OS_RANDOM_BYTES); |
| 315 | #elif defined(HAVE_GETENTROPY_RAND) && defined(__APPLE__) |
| 316 | if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { |
| 317 | RandFailure(); |
| 318 | } |
| 319 | #elif defined(HAVE_SYSCTL_ARND) |
| 320 | /* FreeBSD, NetBSD and similar. It is possible for the call to return less |
| 321 | * bytes than requested, so need to read in a loop. |
| 322 | */ |
| 323 | static int name[2] = {CTL_KERN, KERN_ARND}; |
| 324 | int have = 0; |
| 325 | do { |
| 326 | size_t len = NUM_OS_RANDOM_BYTES - have; |
| 327 | if (sysctl(name, std::size(name), ent32 + have, &len, nullptr, 0) != 0) { |
| 328 | RandFailure(); |
| 329 | } |
| 330 | have += len; |
| 331 | } while (have < NUM_OS_RANDOM_BYTES); |
| 332 | #else |
| 333 | /* Fall back to /dev/urandom if there is no specific method implemented to |
| 334 | * get system entropy for this OS. |
| 335 | */ |
| 336 | GetDevURandom(ent32); |
| 337 | #endif |
| 338 | } |
| 339 | |
| 340 | class RNGState { |
| 341 | Mutex m_mutex; |
no test coverage detected