LCOV - code coverage report
Current view: top level - src - random.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 251 278 90.3 %
Date: 2020-09-26 01:30:44 Functions: 41 43 95.3 %

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

Generated by: LCOV version 1.15