* Fill the given buffer with random bytes. * * This function will attempt to use a cryptographically-strong random * generator, but will fall back to a weaker random generator if none is * available. * * In the end, the buffer will always be filled with some form of random * bytes when this function returns. * * @param buf The buffer to fill with random bytes. */
| 92 | * @param buf The buffer to fill with random bytes. |
| 93 | */ |
| 94 | void RandomBytesWithFallback(std::span<uint8_t> buf) |
| 95 | { |
| 96 | #if defined(_WIN32) |
| 97 | auto res = BCryptGenRandom(nullptr, static_cast<PUCHAR>(buf.data()), static_cast<ULONG>(buf.size()), BCRYPT_USE_SYSTEM_PREFERRED_RNG); |
| 98 | if (res >= 0) return; |
| 99 | #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) |
| 100 | arc4random_buf(buf.data(), buf.size()); |
| 101 | return; |
| 102 | #elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))) |
| 103 | auto res = getrandom(buf.data(), buf.size(), 0); |
| 104 | if (res > 0 && static_cast<size_t>(res) == buf.size()) return; |
| 105 | #elif defined(__EMSCRIPTEN__) |
| 106 | auto res = EM_ASM_INT({ |
| 107 | var buf = $0; |
| 108 | var bytes = $1; |
| 109 | |
| 110 | var crypto = window.crypto; |
| 111 | if (crypto === undefined || crypto.getRandomValues === undefined) { |
| 112 | return -1; |
| 113 | } |
| 114 | |
| 115 | crypto.getRandomValues(Module.HEAPU8.subarray(buf, buf + bytes)); |
| 116 | return 1; |
| 117 | }, buf.data(), buf.size()); |
| 118 | if (res > 0) return; |
| 119 | #else |
| 120 | # warning "No cryptographically-strong random generator available; using a fallback instead" |
| 121 | #endif |
| 122 | |
| 123 | static bool warned_once = false; |
| 124 | Debug(misc, warned_once ? 1 : 0, "Cryptographically-strong random generator unavailable; using fallback"); |
| 125 | warned_once = true; |
| 126 | |
| 127 | for (uint i = 0; i < buf.size(); i++) { |
| 128 | buf[i] = static_cast<uint8_t>(InteractiveRandom()); |
| 129 | } |
| 130 | } |
no test coverage detected