PIVX Core  5.6.99
P2P Digital Currency
random.cpp
Go to the documentation of this file.
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"
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 [[noreturn]] static void RandFailure()
50 {
51  LogPrintf("Failed to read randomness, aborting\n");
52  std::abort();
53 }
54 
55 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  uint64_t r1 = 0, r2 = 0;
67  __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.
68  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 static void InitHardwareRand()
88 {
89  uint32_t eax, ebx, ecx, edx;
90  GetCPUID(1, 0, eax, ebx, ecx, edx);
91  if (ecx & CPUID_F1_ECX_RDRAND) {
92  g_rdrand_supported = true;
93  }
94  GetCPUID(7, 0, eax, ebx, ecx, edx);
95  if (ebx & CPUID_F7_EBX_RDSEED) {
96  g_rdseed_supported = true;
97  }
98 }
99 
100 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  if (g_rdseed_supported) {
105  LogPrintf("Using RdSeed as additional entropy source\n");
106  }
107  if (g_rdrand_supported) {
108  LogPrintf("Using RdRand as an additional entropy source\n");
109  }
110 }
111 
116 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  uint8_t ok;
133  uint64_t r1;
134  for (int i = 0; i < 10; ++i) {
135  __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdrand %rax
136  if (ok) break;
137  }
138  return r1;
139 #else
140 #error "RdRand is only supported on x86 and x86_64"
141 #endif
142 }
143 
148 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  uint8_t ok;
168  uint64_t r1;
169  do {
170  __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %rax
171  if (ok) break;
172  __asm__ volatile ("pause");
173  } while(true);
174  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 
191 static void SeedHardwareFast(CSHA512& hasher) noexcept {
192 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
193  if (g_rdrand_supported) {
194  uint64_t out = GetRdRand();
195  hasher.Write((const unsigned char*)&out, sizeof(out));
196  return;
197  }
198 #endif
199 }
200 
202 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  if (g_rdseed_supported) {
207  for (int i = 0; i < 4; ++i) {
208  uint64_t out = GetRdSeed();
209  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  if (g_rdrand_supported) {
216  for (int i = 0; i < 4; ++i) {
217  uint64_t out = 0;
218  for (int j = 0; j < 1024; ++j) out ^= GetRdRand();
219  hasher.Write((const unsigned char*)&out, sizeof(out));
220  }
221  return;
222  }
223 #endif
224 }
225 
227 static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
228 {
229  CSHA512 inner_hasher;
230  inner_hasher.Write(seed, sizeof(seed));
231 
232  // Hash loop
233  unsigned char buffer[64];
234  int64_t stop = GetTimeMicros() + microseconds;
235  do {
236  for (int i = 0; i < 1000; ++i) {
237  inner_hasher.Finalize(buffer);
238  inner_hasher.Reset();
239  inner_hasher.Write(buffer, sizeof(buffer));
240  }
241  // Benchmark operation and feed it into outer hasher.
242  int64_t perf = GetPerformanceCounter();
243  hasher.Write((const unsigned char*)&perf, sizeof(perf));
244  } while (GetTimeMicros() < stop);
245 
246  // Produce output from inner state and feed it to outer hasher.
247  inner_hasher.Finalize(buffer);
248  hasher.Write(buffer, sizeof(buffer));
249  // Try to clean up.
250  inner_hasher.Reset();
251  memory_cleanse(buffer, sizeof(buffer));
252 }
253 
254 #ifndef WIN32
258 void GetDevURandom(unsigned char *ent32)
259 {
260  int f = open("/dev/urandom", O_RDONLY);
261  if (f == -1) {
262  RandFailure();
263  }
264  int have = 0;
265  do {
266  ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
267  if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
268  close(f);
269  RandFailure();
270  }
271  have += n;
272  } while (have < NUM_OS_RANDOM_BYTES);
273  close(f);
274 }
275 #endif
276 
278 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  int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
298  if (rv != NUM_OS_RANDOM_BYTES) {
299  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  GetDevURandom(ent32);
305  } else {
306  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 }
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  RNGState() noexcept
370  {
371  InitHardwareRand();
372  }
373 
374  ~RNGState()
375  {
376  }
377 
378  void AddEvent(uint32_t event_info) noexcept
379  {
380  LOCK(m_events_mutex);
381 
382  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  uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
386  m_events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
387  }
388 
392  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  LOCK(m_events_mutex);
397 
398  unsigned char events_hash[32];
399  m_events_hasher.Finalize(events_hash);
400  hasher.Write(events_hash, 32);
401 
402  // Re-initialize the hasher with the finalized state to use later.
403  m_events_hasher.Reset();
404  m_events_hasher.Write(events_hash, 32);
405  }
406 
411  bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept
412  {
413  assert(num <= 32);
414  unsigned char buf[64];
415  static_assert(sizeof(buf) == CSHA512::OUTPUT_SIZE, "Buffer needs to have hasher's output size");
416  bool ret;
417  {
418  LOCK(m_mutex);
419  ret = (m_strongly_seeded |= strong_seed);
420  // Write the current state of the RNG into the hasher
421  hasher.Write(m_state, 32);
422  // Write a new counter number into the state
423  hasher.Write((const unsigned char*)&m_counter, sizeof(m_counter));
424  ++m_counter;
425  // Finalize the hasher
426  hasher.Finalize(buf);
427  // Store the last 32 bytes of the hash output as new RNG state.
428  memcpy(m_state, buf + 32, 32);
429  }
430  // If desired, copy (up to) the first 32 bytes of the hash output as output.
431  if (num) {
432  assert(out != nullptr);
433  memcpy(out, buf, num);
434  }
435  // Best effort cleanup of internal state
436  hasher.Reset();
437  memory_cleanse(buf, 64);
438  return ret;
439  }
440 };
441 
442 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  static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
447  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 static void SeedTimestamp(CSHA512& hasher) noexcept
457 {
458  int64_t perfcounter = GetPerformanceCounter();
459  hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
460 }
461 
462 static void SeedFast(CSHA512& hasher) noexcept
463 {
464  unsigned char buffer[32];
465 
466  // Stack pointer to indirectly commit to thread/callstack
467  const unsigned char* ptr = buffer;
468  hasher.Write((const unsigned char*)&ptr, sizeof(ptr));
469 
470  // Hardware randomness is very fast when available; use it always.
471  SeedHardwareFast(hasher);
472 
473  // High-precision timestamp
474  SeedTimestamp(hasher);
475 }
476 
477 static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
478 {
479  unsigned char buffer[32];
480 
481  // Everything that the 'fast' seeder includes
482  SeedFast(hasher);
483 
484  // OS randomness
485  GetOSRand(buffer);
486  hasher.Write(buffer, sizeof(buffer));
487 
488  // Add the events hasher into the mix
489  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  SeedTimestamp(hasher);
496 }
497 
499 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  unsigned char strengthen_seed[32];
503  rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
504  // Strengthen the seed, and feed it into hasher.
505  Strengthen(strengthen_seed, microseconds, hasher);
506 }
507 
508 static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
509 {
510  // Everything that the 'fast' seeder includes
511  SeedFast(hasher);
512 
513  // High-precision timestamp
514  SeedTimestamp(hasher);
515 
516  // Add the events hasher into the mix
517  rng.SeedEvents(hasher);
518 
519  // Dynamic environment data (performance monitoring, ...)
520  RandAddDynamicEnv(hasher);
521 
522  // Strengthen for 10 ms
523  SeedStrengthen(hasher, rng, 10000);
524 }
525 
526 static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
527 {
528  // Gather 256 bits of hardware randomness, if available
529  SeedHardwareSlow(hasher);
530 
531  // Everything that the 'slow' seeder includes.
532  SeedSlow(hasher, rng);
533 
534  // Dynamic environment data (performance monitoring, ...)
535  RandAddDynamicEnv(hasher);
536 
537  // Static environment data
538  RandAddStaticEnv(hasher);
539 
540  // Strengthen for 100 ms
541  SeedStrengthen(hasher, rng, 100000);
542 }
543 
544 enum class RNGLevel {
545  FAST,
546  SLOW,
547  PERIODIC,
548 };
549 
550 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  RNGState& rng = GetRNGState();
554 
555  assert(num <= 32);
556 
557  CSHA512 hasher;
558  switch (level) {
559  case RNGLevel::FAST:
560  SeedFast(hasher);
561  break;
562  case RNGLevel::SLOW:
563  SeedSlow(hasher, rng);
564  break;
565  case RNGLevel::PERIODIC:
566  SeedPeriodic(hasher, rng);
567  break;
568  }
569 
570  // Combine with and update state
571  if (!rng.MixExtract(out, num, std::move(hasher), false)) {
572  // On the first invocation, also seed with SeedStartup().
573  CSHA512 startup_hasher;
574  SeedStartup(startup_hasher, rng);
575  rng.MixExtract(out, num, std::move(startup_hasher), true);
576  }
577 }
578 
579 void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
580 void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
581 void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
582 void RandAddEvent(const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
583 
585 
586 uint64_t GetRand(uint64_t nMax) noexcept
587 {
589 }
590 
591 int GetRandInt(int nMax) noexcept
592 {
593  return GetRand(nMax);
594 }
595 
597 {
598  uint256 hash;
599  GetRandBytes((unsigned char*)&hash, sizeof(hash));
600  return hash;
601 }
602 
603 bool GetRandBool(double rate) noexcept
604 {
605  if (rate == 0.0) {
606  return false;
607  }
608 
609  const uint64_t v = 100000000;
610  uint64_t r = GetRand(v + 1);
611  return r <= v * rate;
612 }
613 
615 {
616  uint256 seed = GetRandHash();
617  rng.SetKey(seed.begin(), 32);
618  requires_seed = false;
619 }
620 
622 {
623  if (bytebuf_size < 32) {
624  FillByteBuffer();
625  }
626  uint256 ret;
627  memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32);
628  bytebuf_size -= 32;
629  return ret;
630 }
631 
632 std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
633 {
634  if (requires_seed) RandomSeed();
635  std::vector<unsigned char> ret(len);
636  if (len > 0) {
637  rng.Keystream(&ret[0], len);
638  }
639  return ret;
640 }
641 
642 FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
643 {
644  rng.SetKey(seed.begin(), 32);
645 }
646 
648 {
649  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  static const ssize_t MAX_TRIES = 1024;
656  uint8_t data[NUM_OS_RANDOM_BYTES];
657  bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
658  int num_overwritten;
659  int tries = 0;
660  /* Loop until all bytes have been overwritten at least once, or max number tries reached */
661  do {
662  memset(data, 0, NUM_OS_RANDOM_BYTES);
663  GetOSRand(data);
664  for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
665  overwritten[x] |= (data[x] != 0);
666  }
667 
668  num_overwritten = 0;
669  for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
670  if (overwritten[x]) {
671  num_overwritten += 1;
672  }
673  }
674 
675  tries += 1;
676  } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
677  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  std::this_thread::sleep_for(std::chrono::milliseconds(1));
681  uint64_t stop = GetPerformanceCounter();
682  if (stop == start) return false;
683 
684  // We called GetPerformanceCounter. Use it as entropy.
685  CSHA512 to_add;
686  to_add.Write((const unsigned char*)&start, sizeof(start));
687  to_add.Write((const unsigned char*)&stop, sizeof(stop));
688  GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false);
689 
690  return true;
691 }
692 
693 FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
694 {
695  if (!fDeterministic) {
696  return;
697  }
698  uint256 seed;
699  rng.SetKey(seed.begin(), 32);
700 }
701 
703 {
704  requires_seed = from.requires_seed;
705  rng = from.rng;
706  std::copy(std::begin(from.bytebuf), std::end(from.bytebuf), std::begin(bytebuf));
707  bytebuf_size = from.bytebuf_size;
708  bitbuf = from.bitbuf;
709  bitbuf_size = from.bitbuf_size;
710  from.requires_seed = true;
711  from.bytebuf_size = 0;
712  from.bitbuf_size = 0;
713  return *this;
714 }
715 
717 {
718  // Invoke RNG code to trigger initialization (if not already performed)
719  ProcRand(nullptr, 0, RNGLevel::FAST);
720 
721  ReportHardwareRand();
722 }
A hasher class for SHA-256.
Definition: sha256.h:13
A hasher class for SHA-512.
Definition: sha512.h:13
static constexpr size_t OUTPUT_SIZE
Definition: sha512.h:20
CSHA512 & Reset()
Definition: sha512.cpp:202
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha512.cpp:185
CSHA512 & Write(const unsigned char *data, size_t len)
Definition: sha512.cpp:159
void Keystream(unsigned char *c, size_t bytes)
outputs the keystream of size <bytes> into
Definition: chacha20.cpp:74
void SetKey(const unsigned char *key, size_t keylen)
set key with flexible keylength; 256bit recommended *‍/
Definition: chacha20.cpp:24
Fast randomness source.
Definition: random.h:107
unsigned char bytebuf[64]
Definition: random.h:112
FastRandomContext(bool fDeterministic=false) noexcept
Definition: random.cpp:693
uint256 rand256() noexcept
generate a random uint256.
Definition: random.cpp:621
void RandomSeed()
Definition: random.cpp:614
ChaCha20 rng
Definition: random.h:110
std::vector< unsigned char > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:632
FastRandomContext & operator=(const FastRandomContext &)=delete
bool requires_seed
Definition: random.h:109
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Definition: random.h:174
void FillByteBuffer()
Definition: random.h:120
unsigned char * begin()
Definition: uint256.h:63
256-bit opaque blob.
Definition: uint256.h:138
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:27
std::vector< uint8_t > buffer
Definition: fuzz.cpp:71
void * memcpy(void *a, const void *b, size_t c)
@ LOCK
Definition: lockunlock.h:16
void GetDevURandom(unsigned char *ent32)
Fallback: get 32 bytes of system entropy from /dev/urandom.
Definition: random.cpp:258
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
Definition: random.cpp:581
bool g_mock_deterministic_tests
Flag to make GetRand in random.h return the same number.
Definition: random.cpp:584
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:579
void GetStrongRandBytes(unsigned char *buf, int num) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
Definition: random.cpp:580
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
Definition: random.cpp:647
uint256 GetRandHash() noexcept
Definition: random.cpp:596
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
Definition: random.cpp:716
bool GetRandBool(double rate) noexcept
Definition: random.cpp:603
uint64_t GetRand(uint64_t nMax) noexcept
Definition: random.cpp:586
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
Definition: random.cpp:582
RNGLevel
Definition: random.cpp:544
@ SLOW
Automatically called by GetStrongRandBytes.
@ PERIODIC
Called by RandAddPeriodic()
@ FAST
Automatically called by GetRandBytes.
void GetOSRand(unsigned char *ent32)
Get 32 bytes of system entropy.
Definition: random.cpp:278
int GetRandInt(int nMax) noexcept
Definition: random.cpp:591
void RandAddStaticEnv(CSHA512 &hasher)
Gather non-cryptographic environment data that does not change over time.
Definition: randomenv.cpp:325
void RandAddDynamicEnv(CSHA512 &hasher)
Gather non-cryptographic environment data that changes over time.
Definition: randomenv.cpp:230
const char * name
Definition: rest.cpp:37
UniValue stop(const JSONRPCRequest &jsonRequest)
Definition: server.cpp:264
#define GUARDED_BY(x)
Definition: threadsafety.h:37
#define ARRAYLEN(array)
int64_t GetTimeMicros()
Returns the system time (not mockable)
Definition: utiltime.cpp:74