LCOV - code coverage report
Current view: top level - src - random.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 290 324 89.5 %
Date: 2021-06-29 14:35:33 Functions: 37 39 94.9 %
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: 52 80 65.0 %

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

Generated by: LCOV version 1.14