Get 32 bytes of system entropy. */
| 201 | |
| 202 | /** Get 32 bytes of system entropy. */ |
| 203 | void GetOSRand(unsigned char *ent32) |
| 204 | { |
| 205 | #if defined(WIN32) |
| 206 | HCRYPTPROV hProvider; |
| 207 | int ret = CryptAcquireContextW(&hProvider, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); |
| 208 | if (!ret) { |
| 209 | RandFailure(); |
| 210 | } |
| 211 | ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32); |
| 212 | if (!ret) { |
| 213 | RandFailure(); |
| 214 | } |
| 215 | CryptReleaseContext(hProvider, 0); |
| 216 | #elif defined(HAVE_SYS_GETRANDOM) |
| 217 | /* Linux. From the getrandom(2) man page: |
| 218 | * "If the urandom source has been initialized, reads of up to 256 bytes |
| 219 | * will always return as many bytes as requested and will not be |
| 220 | * interrupted by signals." |
| 221 | */ |
| 222 | int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0); |
| 223 | if (rv != NUM_OS_RANDOM_BYTES) { |
| 224 | if (rv < 0 && errno == ENOSYS) { |
| 225 | /* Fallback for kernel <3.17: the return value will be -1 and errno |
| 226 | * ENOSYS if the syscall is not available, in that case fall back |
| 227 | * to /dev/urandom. |
| 228 | */ |
| 229 | GetDevURandom(ent32); |
| 230 | } else { |
| 231 | RandFailure(); |
| 232 | } |
| 233 | } |
| 234 | #elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__) |
| 235 | /* On OpenBSD this can return up to 256 bytes of entropy, will return an |
| 236 | * error if more are requested. |
| 237 | * The call cannot return less than the requested number of bytes. |
| 238 | getentropy is explicitly limited to openbsd here, as a similar (but not |
| 239 | the same) function may exist on other platforms via glibc. |
| 240 | */ |
| 241 | if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { |
| 242 | RandFailure(); |
| 243 | } |
| 244 | #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) |
| 245 | // We need a fallback for OSX < 10.12 |
| 246 | if (&getentropy != nullptr) { |
| 247 | if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { |
| 248 | RandFailure(); |
| 249 | } |
| 250 | } else { |
| 251 | GetDevURandom(ent32); |
| 252 | } |
| 253 | #elif defined(HAVE_SYSCTL_ARND) |
| 254 | /* FreeBSD and similar. It is possible for the call to return less |
| 255 | * bytes than requested, so need to read in a loop. |
| 256 | */ |
| 257 | static const int name[2] = {CTL_KERN, KERN_ARND}; |
| 258 | int have = 0; |
| 259 | do { |
| 260 | size_t len = NUM_OS_RANDOM_BYTES - have; |
no test coverage detected