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