Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #include <random.h>
# 7 : :
# 8 : : #include <compat/cpuid.h>
# 9 : : #include <crypto/sha256.h>
# 10 : : #include <crypto/sha512.h>
# 11 : : #include <support/cleanse.h>
# 12 : : #ifdef WIN32
# 13 : : #include <compat.h> // for Windows API
# 14 : : #include <wincrypt.h>
# 15 : : #endif
# 16 : : #include <logging.h>
# 17 : : #include <randomenv.h>
# 18 : : #include <support/allocators/secure.h>
# 19 : : #include <sync.h> // for Mutex
# 20 : : #include <util/time.h> // for GetTimeMicros()
# 21 : :
# 22 : : #include <cmath>
# 23 : : #include <stdlib.h>
# 24 : : #include <thread>
# 25 : :
# 26 : : #ifndef WIN32
# 27 : : #include <fcntl.h>
# 28 : : #include <sys/time.h>
# 29 : : #endif
# 30 : :
# 31 : : #ifdef HAVE_SYS_GETRANDOM
# 32 : : #include <sys/syscall.h>
# 33 : : #include <linux/random.h>
# 34 : : #endif
# 35 : : #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
# 36 : : #include <unistd.h>
# 37 : : #include <sys/random.h>
# 38 : : #endif
# 39 : : #ifdef HAVE_SYSCTL_ARND
# 40 : : #include <sys/sysctl.h>
# 41 : : #endif
# 42 : :
# 43 : : [[noreturn]] static void RandFailure()
# 44 : 0 : {
# 45 : 0 : LogPrintf("Failed to read randomness, aborting\n");
# 46 : 0 : std::abort();
# 47 : 0 : }
# 48 : :
# 49 : : static inline int64_t GetPerformanceCounter() noexcept
# 50 : 1658213 : {
# 51 : : // Read the hardware time stamp counter when available.
# 52 : : // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
# 53 : : #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
# 54 : : return __rdtsc();
# 55 : : #elif !defined(_MSC_VER) && defined(__i386__)
# 56 : : uint64_t r = 0;
# 57 : : __asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair.
# 58 : : return r;
# 59 : : #elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
# 60 : 1658213 : uint64_t r1 = 0, r2 = 0;
# 61 : 1658213 : __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.
# 62 : 1658213 : return (r2 << 32) | r1;
# 63 : : #else
# 64 : : // Fall back to using C++11 clock (usually microsecond or nanosecond precision)
# 65 : : return std::chrono::high_resolution_clock::now().time_since_epoch().count();
# 66 : : #endif
# 67 : 1658213 : }
# 68 : :
# 69 : : #ifdef HAVE_GETCPUID
# 70 : : static bool g_rdrand_supported = false;
# 71 : : static bool g_rdseed_supported = false;
# 72 : : static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
# 73 : : static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;
# 74 : : #ifdef bit_RDRND
# 75 : : static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, "Unexpected value for bit_RDRND");
# 76 : : #endif
# 77 : : #ifdef bit_RDSEED
# 78 : : static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, "Unexpected value for bit_RDSEED");
# 79 : : #endif
# 80 : :
# 81 : : static void InitHardwareRand()
# 82 : 893 : {
# 83 : 893 : uint32_t eax, ebx, ecx, edx;
# 84 : 893 : GetCPUID(1, 0, eax, ebx, ecx, edx);
# 85 [ + - ]: 893 : if (ecx & CPUID_F1_ECX_RDRAND) {
# 86 : 893 : g_rdrand_supported = true;
# 87 : 893 : }
# 88 : 893 : GetCPUID(7, 0, eax, ebx, ecx, edx);
# 89 [ + - ]: 893 : if (ebx & CPUID_F7_EBX_RDSEED) {
# 90 : 893 : g_rdseed_supported = true;
# 91 : 893 : }
# 92 : 893 : }
# 93 : :
# 94 : : static void ReportHardwareRand()
# 95 : 860 : {
# 96 : : // This must be done in a separate function, as InitHardwareRand() may be indirectly called
# 97 : : // from global constructors, before logging is initialized.
# 98 [ + - ]: 860 : if (g_rdseed_supported) {
# 99 : 860 : LogPrintf("Using RdSeed as additional entropy source\n");
# 100 : 860 : }
# 101 [ + - ]: 860 : if (g_rdrand_supported) {
# 102 : 860 : LogPrintf("Using RdRand as an additional entropy source\n");
# 103 : 860 : }
# 104 : 860 : }
# 105 : :
# 106 : : /** Read 64 bits of entropy using rdrand.
# 107 : : *
# 108 : : * Must only be called when RdRand is supported.
# 109 : : */
# 110 : : static uint64_t GetRdRand() noexcept
# 111 : 1509079 : {
# 112 : : // RdRand may very rarely fail. Invoke it up to 10 times in a loop to reduce this risk.
# 113 : : #ifdef __i386__
# 114 : : uint8_t ok;
# 115 : : // Initialize to 0 to silence a compiler warning that r1 or r2 may be used
# 116 : : // uninitialized. Even if rdrand fails (!ok) it will set the output to 0,
# 117 : : // but there is no way that the compiler could know that.
# 118 : : uint32_t r1 = 0, r2 = 0;
# 119 : : for (int i = 0; i < 10; ++i) {
# 120 : : __asm__ volatile (".byte 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %eax
# 121 : : if (ok) break;
# 122 : : }
# 123 : : for (int i = 0; i < 10; ++i) {
# 124 : : __asm__ volatile (".byte 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdrand %eax
# 125 : : if (ok) break;
# 126 : : }
# 127 : : return (((uint64_t)r2) << 32) | r1;
# 128 : : #elif defined(__x86_64__) || defined(__amd64__)
# 129 : 1509079 : uint8_t ok;
# 130 : 1509079 : uint64_t r1 = 0; // See above why we initialize to 0.
# 131 [ + - ]: 1509079 : for (int i = 0; i < 10; ++i) {
# 132 : 1509079 : __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %rax
# 133 [ + - ]: 1509079 : if (ok) break;
# 134 : 1509079 : }
# 135 : 1509079 : return r1;
# 136 : : #else
# 137 : : #error "RdRand is only supported on x86 and x86_64"
# 138 : : #endif
# 139 : 1509079 : }
# 140 : :
# 141 : : /** Read 64 bits of entropy using rdseed.
# 142 : : *
# 143 : : * Must only be called when RdSeed is supported.
# 144 : : */
# 145 : : static uint64_t GetRdSeed() noexcept
# 146 : 3572 : {
# 147 : : // RdSeed may fail when the HW RNG is overloaded. Loop indefinitely until enough entropy is gathered,
# 148 : : // but pause after every failure.
# 149 : : #ifdef __i386__
# 150 : : uint8_t ok;
# 151 : : uint32_t r1, r2;
# 152 : : do {
# 153 : : __asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %eax
# 154 : : if (ok) break;
# 155 : : __asm__ volatile ("pause");
# 156 : : } while(true);
# 157 : : do {
# 158 : : __asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdseed %eax
# 159 : : if (ok) break;
# 160 : : __asm__ volatile ("pause");
# 161 : : } while(true);
# 162 : : return (((uint64_t)r2) << 32) | r1;
# 163 : : #elif defined(__x86_64__) || defined(__amd64__)
# 164 : 3572 : uint8_t ok;
# 165 : 3572 : uint64_t r1;
# 166 : 3572 : do {
# 167 : 3572 : __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %rax
# 168 [ + - ]: 3572 : if (ok) break;
# 169 : 0 : __asm__ volatile ("pause");
# 170 : 0 : } while(true);
# 171 : 0 : return r1;
# 172 : : #else
# 173 : : #error "RdSeed is only supported on x86 and x86_64"
# 174 : : #endif
# 175 : 3572 : }
# 176 : :
# 177 : : #else
# 178 : : /* Access to other hardware random number generators could be added here later,
# 179 : : * assuming it is sufficiently fast (in the order of a few hundred CPU cycles).
# 180 : : * Slower sources should probably be invoked separately, and/or only from
# 181 : : * RandAddPeriodic (which is called once a minute).
# 182 : : */
# 183 : : static void InitHardwareRand() {}
# 184 : : static void ReportHardwareRand() {}
# 185 : : #endif
# 186 : :
# 187 : : /** Add 64 bits of entropy gathered from hardware to hasher. Do nothing if not supported. */
# 188 : 1509079 : static void SeedHardwareFast(CSHA512& hasher) noexcept {
# 189 : 1509079 : #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
# 190 [ + - ]: 1509079 : if (g_rdrand_supported) {
# 191 : 1509079 : uint64_t out = GetRdRand();
# 192 : 1509079 : hasher.Write((const unsigned char*)&out, sizeof(out));
# 193 : 1509079 : return;
# 194 : 1509079 : }
# 195 : 1509079 : #endif
# 196 : 1509079 : }
# 197 : :
# 198 : : /** Add 256 bits of entropy gathered from hardware to hasher. Do nothing if not supported. */
# 199 : 893 : static void SeedHardwareSlow(CSHA512& hasher) noexcept {
# 200 : 893 : #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
# 201 : : // When we want 256 bits of entropy, prefer RdSeed over RdRand, as it's
# 202 : : // guaranteed to produce independent randomness on every call.
# 203 [ + - ]: 893 : if (g_rdseed_supported) {
# 204 [ + + ]: 4465 : for (int i = 0; i < 4; ++i) {
# 205 : 3572 : uint64_t out = GetRdSeed();
# 206 : 3572 : hasher.Write((const unsigned char*)&out, sizeof(out));
# 207 : 3572 : }
# 208 : 893 : return;
# 209 : 893 : }
# 210 : : // When falling back to RdRand, XOR the result of 1024 results.
# 211 : : // This guarantees a reseeding occurs between each.
# 212 [ # # ]: 0 : if (g_rdrand_supported) {
# 213 [ # # ]: 0 : for (int i = 0; i < 4; ++i) {
# 214 : 0 : uint64_t out = 0;
# 215 [ # # ]: 0 : for (int j = 0; j < 1024; ++j) out ^= GetRdRand();
# 216 : 0 : hasher.Write((const unsigned char*)&out, sizeof(out));
# 217 : 0 : }
# 218 : 0 : return;
# 219 : 0 : }
# 220 : 0 : #endif
# 221 : 0 : }
# 222 : :
# 223 : : /** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */
# 224 : : static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
# 225 : 987 : {
# 226 : 987 : CSHA512 inner_hasher;
# 227 : 987 : inner_hasher.Write(seed, sizeof(seed));
# 228 : :
# 229 : : // Hash loop
# 230 : 987 : unsigned char buffer[64];
# 231 : 987 : int64_t stop = GetTimeMicros() + microseconds;
# 232 : 32265 : do {
# 233 [ + + ]: 32297265 : for (int i = 0; i < 1000; ++i) {
# 234 : 32265000 : inner_hasher.Finalize(buffer);
# 235 : 32265000 : inner_hasher.Reset();
# 236 : 32265000 : inner_hasher.Write(buffer, sizeof(buffer));
# 237 : 32265000 : }
# 238 : : // Benchmark operation and feed it into outer hasher.
# 239 : 32265 : int64_t perf = GetPerformanceCounter();
# 240 : 32265 : hasher.Write((const unsigned char*)&perf, sizeof(perf));
# 241 [ + + ]: 32265 : } while (GetTimeMicros() < stop);
# 242 : :
# 243 : : // Produce output from inner state and feed it to outer hasher.
# 244 : 987 : inner_hasher.Finalize(buffer);
# 245 : 987 : hasher.Write(buffer, sizeof(buffer));
# 246 : : // Try to clean up.
# 247 : 987 : inner_hasher.Reset();
# 248 : 987 : memory_cleanse(buffer, sizeof(buffer));
# 249 : 987 : }
# 250 : :
# 251 : : #ifndef WIN32
# 252 : : /** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
# 253 : : * compatible way to get cryptographic randomness on UNIX-ish platforms.
# 254 : : */
# 255 : : static void GetDevURandom(unsigned char *ent32)
# 256 : 0 : {
# 257 : 0 : int f = open("/dev/urandom", O_RDONLY);
# 258 [ # # ]: 0 : if (f == -1) {
# 259 : 0 : RandFailure();
# 260 : 0 : }
# 261 : 0 : int have = 0;
# 262 : 0 : do {
# 263 : 0 : ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
# 264 [ # # ][ # # ]: 0 : if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
# 265 : 0 : close(f);
# 266 : 0 : RandFailure();
# 267 : 0 : }
# 268 : 0 : have += n;
# 269 [ # # ]: 0 : } while (have < NUM_OS_RANDOM_BYTES);
# 270 : 0 : close(f);
# 271 : 0 : }
# 272 : : #endif
# 273 : :
# 274 : : /** Get 32 bytes of system entropy. */
# 275 : : void GetOSRand(unsigned char *ent32)
# 276 : 3257 : {
# 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 : 3257 : static int name[2] = {CTL_KERN, KERN_ARND};
# 329 : 3257 : int have = 0;
# 330 : 3257 : do {
# 331 : 3257 : size_t len = NUM_OS_RANDOM_BYTES - have;
# 332 [ - + ]: 3257 : if (sysctl(name, std::size(name), ent32 + have, &len, nullptr, 0) != 0) {
# 333 : 0 : RandFailure();
# 334 : 0 : }
# 335 : 3257 : have += len;
# 336 [ - + ]: 3257 : } while (have < NUM_OS_RANDOM_BYTES);
# 337 : : // Silence a compiler warning about unused function.
# 338 : 3257 : (void)GetDevURandom;
# 339 : : #else
# 340 : : /* Fall back to /dev/urandom if there is no specific method implemented to
# 341 : : * get system entropy for this OS.
# 342 : : */
# 343 : : GetDevURandom(ent32);
# 344 : : #endif
# 345 : 3257 : }
# 346 : :
# 347 : : namespace {
# 348 : :
# 349 : : class RNGState {
# 350 : : Mutex m_mutex;
# 351 : : /* The RNG state consists of 256 bits of entropy, taken from the output of
# 352 : : * one operation's SHA512 output, and fed as input to the next one.
# 353 : : * Carrying 256 bits of entropy should be sufficient to guarantee
# 354 : : * unpredictability as long as any entropy source was ever unpredictable
# 355 : : * to an attacker. To protect against situations where an attacker might
# 356 : : * observe the RNG's state, fresh entropy is always mixed when
# 357 : : * GetStrongRandBytes is called.
# 358 : : */
# 359 : : unsigned char m_state[32] GUARDED_BY(m_mutex) = {0};
# 360 : : uint64_t m_counter GUARDED_BY(m_mutex) = 0;
# 361 : : bool m_strongly_seeded GUARDED_BY(m_mutex) = false;
# 362 : :
# 363 : : Mutex m_events_mutex;
# 364 : : CSHA256 m_events_hasher GUARDED_BY(m_events_mutex);
# 365 : :
# 366 : : public:
# 367 : : RNGState() noexcept
# 368 : 893 : {
# 369 : 893 : InitHardwareRand();
# 370 : 893 : }
# 371 : :
# 372 : : ~RNGState()
# 373 : 65 : {
# 374 : 65 : }
# 375 : :
# 376 : : void AddEvent(uint32_t event_info) noexcept
# 377 : 112817 : {
# 378 : 112817 : LOCK(m_events_mutex);
# 379 : :
# 380 : 112817 : m_events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info));
# 381 : : // Get the low four bytes of the performance counter. This translates to roughly the
# 382 : : // subsecond part.
# 383 : 112817 : uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
# 384 : 112817 : m_events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
# 385 : 112817 : }
# 386 : :
# 387 : : /**
# 388 : : * Feed (the hash of) all events added through AddEvent() to hasher.
# 389 : : */
# 390 : : void SeedEvents(CSHA512& hasher) noexcept
# 391 : 2459 : {
# 392 : : // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
# 393 : : // since we want it to be fast as network peers may be able to trigger it repeatedly.
# 394 : 2459 : LOCK(m_events_mutex);
# 395 : :
# 396 : 2459 : unsigned char events_hash[32];
# 397 : 2459 : m_events_hasher.Finalize(events_hash);
# 398 : 2459 : hasher.Write(events_hash, 32);
# 399 : :
# 400 : : // Re-initialize the hasher with the finalized state to use later.
# 401 : 2459 : m_events_hasher.Reset();
# 402 : 2459 : m_events_hasher.Write(events_hash, 32);
# 403 : 2459 : }
# 404 : :
# 405 : : /** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher.
# 406 : : *
# 407 : : * If this function has never been called with strong_seed = true, false is returned.
# 408 : : */
# 409 : : bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept
# 410 : 1510863 : {
# 411 : 1510863 : assert(num <= 32);
# 412 : 0 : unsigned char buf[64];
# 413 : 1510863 : static_assert(sizeof(buf) == CSHA512::OUTPUT_SIZE, "Buffer needs to have hasher's output size");
# 414 : 1510863 : bool ret;
# 415 : 1510863 : {
# 416 : 1510863 : LOCK(m_mutex);
# 417 : 1510863 : ret = (m_strongly_seeded |= strong_seed);
# 418 : : // Write the current state of the RNG into the hasher
# 419 : 1510863 : hasher.Write(m_state, 32);
# 420 : : // Write a new counter number into the state
# 421 : 1510863 : hasher.Write((const unsigned char*)&m_counter, sizeof(m_counter));
# 422 : 1510863 : ++m_counter;
# 423 : : // Finalize the hasher
# 424 : 1510863 : hasher.Finalize(buf);
# 425 : : // Store the last 32 bytes of the hash output as new RNG state.
# 426 : 1510863 : memcpy(m_state, buf + 32, 32);
# 427 : 1510863 : }
# 428 : : // If desired, copy (up to) the first 32 bytes of the hash output as output.
# 429 [ + + ]: 1510863 : if (num) {
# 430 : 1509047 : assert(out != nullptr);
# 431 : 0 : memcpy(out, buf, num);
# 432 : 1509047 : }
# 433 : : // Best effort cleanup of internal state
# 434 : 0 : hasher.Reset();
# 435 : 1510863 : memory_cleanse(buf, 64);
# 436 : 1510863 : return ret;
# 437 : 1510863 : }
# 438 : : };
# 439 : :
# 440 : : RNGState& GetRNGState() noexcept
# 441 : 1621797 : {
# 442 : : // This C++11 idiom relies on the guarantee that static variable are initialized
# 443 : : // on first call, even when multiple parallel calls are permitted.
# 444 : 1621797 : static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
# 445 : 1621797 : return g_rng[0];
# 446 : 1621797 : }
# 447 : : }
# 448 : :
# 449 : : /* A note on the use of noexcept in the seeding functions below:
# 450 : : *
# 451 : : * None of the RNG code should ever throw any exception.
# 452 : : */
# 453 : :
# 454 : : static void SeedTimestamp(CSHA512& hasher) noexcept
# 455 : 1511538 : {
# 456 : 1511538 : int64_t perfcounter = GetPerformanceCounter();
# 457 : 1511538 : hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
# 458 : 1511538 : }
# 459 : :
# 460 : : static void SeedFast(CSHA512& hasher) noexcept
# 461 : 1509079 : {
# 462 : 1509079 : unsigned char buffer[32];
# 463 : :
# 464 : : // Stack pointer to indirectly commit to thread/callstack
# 465 : 1509079 : const unsigned char* ptr = buffer;
# 466 : 1509079 : hasher.Write((const unsigned char*)&ptr, sizeof(ptr));
# 467 : :
# 468 : : // Hardware randomness is very fast when available; use it always.
# 469 : 1509079 : SeedHardwareFast(hasher);
# 470 : :
# 471 : : // High-precision timestamp
# 472 : 1509079 : SeedTimestamp(hasher);
# 473 : 1509079 : }
# 474 : :
# 475 : : static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
# 476 : 2365 : {
# 477 : 2365 : unsigned char buffer[32];
# 478 : :
# 479 : : // Everything that the 'fast' seeder includes
# 480 : 2365 : SeedFast(hasher);
# 481 : :
# 482 : : // OS randomness
# 483 : 2365 : GetOSRand(buffer);
# 484 : 2365 : hasher.Write(buffer, sizeof(buffer));
# 485 : :
# 486 : : // Add the events hasher into the mix
# 487 : 2365 : rng.SeedEvents(hasher);
# 488 : :
# 489 : : // High-precision timestamp.
# 490 : : //
# 491 : : // Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
# 492 : : // benchmark of all the entropy gathering sources in this function).
# 493 : 2365 : SeedTimestamp(hasher);
# 494 : 2365 : }
# 495 : :
# 496 : : /** Extract entropy from rng, strengthen it, and feed it into hasher. */
# 497 : : static void SeedStrengthen(CSHA512& hasher, RNGState& rng, int microseconds) noexcept
# 498 : 987 : {
# 499 : : // Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
# 500 : 987 : unsigned char strengthen_seed[32];
# 501 : 987 : rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
# 502 : : // Strengthen the seed, and feed it into hasher.
# 503 : 987 : Strengthen(strengthen_seed, microseconds, hasher);
# 504 : 987 : }
# 505 : :
# 506 : : static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
# 507 : 94 : {
# 508 : : // Everything that the 'fast' seeder includes
# 509 : 94 : SeedFast(hasher);
# 510 : :
# 511 : : // High-precision timestamp
# 512 : 94 : SeedTimestamp(hasher);
# 513 : :
# 514 : : // Add the events hasher into the mix
# 515 : 94 : rng.SeedEvents(hasher);
# 516 : :
# 517 : : // Dynamic environment data (performance monitoring, ...)
# 518 : 94 : auto old_size = hasher.Size();
# 519 : 94 : RandAddDynamicEnv(hasher);
# 520 [ + - ]: 94 : LogPrint(BCLog::RAND, "Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);
# 521 : :
# 522 : : // Strengthen for 10 ms
# 523 : 94 : SeedStrengthen(hasher, rng, 10000);
# 524 : 94 : }
# 525 : :
# 526 : : static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
# 527 : 893 : {
# 528 : : // Gather 256 bits of hardware randomness, if available
# 529 : 893 : SeedHardwareSlow(hasher);
# 530 : :
# 531 : : // Everything that the 'slow' seeder includes.
# 532 : 893 : SeedSlow(hasher, rng);
# 533 : :
# 534 : : // Dynamic environment data (performance monitoring, ...)
# 535 : 893 : auto old_size = hasher.Size();
# 536 : 893 : RandAddDynamicEnv(hasher);
# 537 : :
# 538 : : // Static environment data
# 539 : 893 : RandAddStaticEnv(hasher);
# 540 [ - + ]: 893 : LogPrint(BCLog::RAND, "Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
# 541 : :
# 542 : : // Strengthen for 100 ms
# 543 : 893 : SeedStrengthen(hasher, rng, 100000);
# 544 : 893 : }
# 545 : :
# 546 : : enum class RNGLevel {
# 547 : : FAST, //!< Automatically called by GetRandBytes
# 548 : : SLOW, //!< Automatically called by GetStrongRandBytes
# 549 : : PERIODIC, //!< Called by RandAddPeriodic()
# 550 : : };
# 551 : :
# 552 : : static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
# 553 : 1508186 : {
# 554 : : // Make sure the RNG is initialized first (as all Seed* function possibly need hwrand to be available).
# 555 : 1508186 : RNGState& rng = GetRNGState();
# 556 : :
# 557 : 1508186 : assert(num <= 32);
# 558 : :
# 559 : 0 : CSHA512 hasher;
# 560 [ - + ]: 1508186 : switch (level) {
# 561 [ + + ]: 1506620 : case RNGLevel::FAST:
# 562 : 1506620 : SeedFast(hasher);
# 563 : 1506620 : break;
# 564 [ + + ]: 1472 : case RNGLevel::SLOW:
# 565 : 1472 : SeedSlow(hasher, rng);
# 566 : 1472 : break;
# 567 [ + + ]: 94 : case RNGLevel::PERIODIC:
# 568 : 94 : SeedPeriodic(hasher, rng);
# 569 : 94 : break;
# 570 : 1508186 : }
# 571 : :
# 572 : : // Combine with and update state
# 573 [ + + ]: 1508186 : if (!rng.MixExtract(out, num, std::move(hasher), false)) {
# 574 : : // On the first invocation, also seed with SeedStartup().
# 575 : 893 : CSHA512 startup_hasher;
# 576 : 893 : SeedStartup(startup_hasher, rng);
# 577 : 893 : rng.MixExtract(out, num, std::move(startup_hasher), true);
# 578 : 893 : }
# 579 : 1508186 : }
# 580 : :
# 581 : 1505760 : void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
# 582 : 1472 : void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
# 583 : 94 : void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
# 584 : 112817 : void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
# 585 : :
# 586 : : bool g_mock_deterministic_tests{false};
# 587 : :
# 588 : : uint64_t GetRand(uint64_t nMax) noexcept
# 589 : 1460741 : {
# 590 : 1460741 : return FastRandomContext(g_mock_deterministic_tests).randrange(nMax);
# 591 : 1460741 : }
# 592 : :
# 593 : : int GetRandInt(int nMax) noexcept
# 594 : 40 : {
# 595 : 40 : return GetRand(nMax);
# 596 : 40 : }
# 597 : :
# 598 : : uint256 GetRandHash() noexcept
# 599 : 1458747 : {
# 600 : 1458747 : uint256 hash;
# 601 : 1458747 : GetRandBytes((unsigned char*)&hash, sizeof(hash));
# 602 : 1458747 : return hash;
# 603 : 1458747 : }
# 604 : :
# 605 : : void FastRandomContext::RandomSeed()
# 606 : 1456076 : {
# 607 : 1456076 : uint256 seed = GetRandHash();
# 608 : 1456076 : rng.SetKey(seed.begin(), 32);
# 609 : 1456076 : requires_seed = false;
# 610 : 1456076 : }
# 611 : :
# 612 : : uint256 FastRandomContext::rand256() noexcept
# 613 : 1570954 : {
# 614 [ + + ]: 1570954 : if (bytebuf_size < 32) {
# 615 : 846451 : FillByteBuffer();
# 616 : 846451 : }
# 617 : 1570954 : uint256 ret;
# 618 : 1570954 : memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32);
# 619 : 1570954 : bytebuf_size -= 32;
# 620 : 1570954 : return ret;
# 621 : 1570954 : }
# 622 : :
# 623 : : std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
# 624 : 3625 : {
# 625 [ + + ]: 3625 : if (requires_seed) RandomSeed();
# 626 : 3625 : std::vector<unsigned char> ret(len);
# 627 [ + + ]: 3625 : if (len > 0) {
# 628 : 3603 : rng.Keystream(ret.data(), len);
# 629 : 3603 : }
# 630 : 3625 : return ret;
# 631 : 3625 : }
# 632 : :
# 633 : : FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
# 634 : 1095 : {
# 635 : 1095 : rng.SetKey(seed.begin(), 32);
# 636 : 1095 : }
# 637 : :
# 638 : : bool Random_SanityCheck()
# 639 : 797 : {
# 640 : 797 : uint64_t start = GetPerformanceCounter();
# 641 : :
# 642 : : /* This does not measure the quality of randomness, but it does test that
# 643 : : * GetOSRand() overwrites all 32 bytes of the output given a maximum
# 644 : : * number of tries.
# 645 : : */
# 646 : 797 : static const ssize_t MAX_TRIES = 1024;
# 647 : 797 : uint8_t data[NUM_OS_RANDOM_BYTES];
# 648 : 797 : bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
# 649 : 797 : int num_overwritten;
# 650 : 797 : int tries = 0;
# 651 : : /* Loop until all bytes have been overwritten at least once, or max number tries reached */
# 652 : 892 : do {
# 653 : 892 : memset(data, 0, NUM_OS_RANDOM_BYTES);
# 654 : 892 : GetOSRand(data);
# 655 [ + + ]: 29436 : for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
# 656 : 28544 : overwritten[x] |= (data[x] != 0);
# 657 : 28544 : }
# 658 : :
# 659 : 892 : num_overwritten = 0;
# 660 [ + + ]: 29436 : for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
# 661 [ + + ]: 28544 : if (overwritten[x]) {
# 662 : 28444 : num_overwritten += 1;
# 663 : 28444 : }
# 664 : 28544 : }
# 665 : :
# 666 : 892 : tries += 1;
# 667 [ + + ][ + - ]: 892 : } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
# 668 [ - + ]: 797 : if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */
# 669 : :
# 670 : : // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.
# 671 : 797 : std::this_thread::sleep_for(std::chrono::milliseconds(1));
# 672 : 797 : uint64_t stop = GetPerformanceCounter();
# 673 [ - + ]: 797 : if (stop == start) return false;
# 674 : :
# 675 : : // We called GetPerformanceCounter. Use it as entropy.
# 676 : 797 : CSHA512 to_add;
# 677 : 797 : to_add.Write((const unsigned char*)&start, sizeof(start));
# 678 : 797 : to_add.Write((const unsigned char*)&stop, sizeof(stop));
# 679 : 797 : GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false);
# 680 : :
# 681 : 797 : return true;
# 682 : 797 : }
# 683 : :
# 684 : : FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
# 685 : 1692432 : {
# 686 [ + + ]: 1692432 : if (!fDeterministic) {
# 687 : 1691506 : return;
# 688 : 1691506 : }
# 689 : 926 : uint256 seed;
# 690 : 926 : rng.SetKey(seed.begin(), 32);
# 691 : 926 : }
# 692 : :
# 693 : : FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexcept
# 694 : 1121 : {
# 695 : 1121 : requires_seed = from.requires_seed;
# 696 : 1121 : rng = from.rng;
# 697 : 1121 : std::copy(std::begin(from.bytebuf), std::end(from.bytebuf), std::begin(bytebuf));
# 698 : 1121 : bytebuf_size = from.bytebuf_size;
# 699 : 1121 : bitbuf = from.bitbuf;
# 700 : 1121 : bitbuf_size = from.bitbuf_size;
# 701 : 1121 : from.requires_seed = true;
# 702 : 1121 : from.bytebuf_size = 0;
# 703 : 1121 : from.bitbuf_size = 0;
# 704 : 1121 : return *this;
# 705 : 1121 : }
# 706 : :
# 707 : : void RandomInit()
# 708 : 860 : {
# 709 : : // Invoke RNG code to trigger initialization (if not already performed)
# 710 : 860 : ProcRand(nullptr, 0, RNGLevel::FAST);
# 711 : :
# 712 : 860 : ReportHardwareRand();
# 713 : 860 : }
# 714 : :
# 715 : : std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
# 716 : 9307 : {
# 717 : 9307 : double unscaled = -std::log1p(GetRand(uint64_t{1} << 48) * -0.0000000000000035527136788 /* -1/2^48 */);
# 718 : 9307 : return now + std::chrono::duration_cast<std::chrono::microseconds>(unscaled * average_interval + 0.5us);
# 719 : 9307 : }
|