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