LCOV - code coverage report
Current view: top level - src - random.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 289 328 88.1 %
Date: 2022-04-21 14:51:19 Functions: 38 40 95.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 49 80 61.2 %

           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 : }

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a