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