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