LCOV - code coverage report
Current view: top level - src - random.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 178 255 69.8 %
Date: 2023-09-26 12:08:55 Functions: 30 41 73.2 %

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

Generated by: LCOV version 1.14