34 #ifdef HAVE_SYS_GETRANDOM
35 #include <sys/syscall.h>
36 #include <linux/random.h>
38 #if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX))
41 #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
42 #include <sys/random.h>
44 #ifdef HAVE_SYSCTL_ARND
46 #include <sys/sysctl.h>
49 [[noreturn]]
static void RandFailure()
51 LogPrintf(
"Failed to read randomness, aborting\n");
55 static inline int64_t GetPerformanceCounter() noexcept
59 #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
61 #elif !defined(_MSC_VER) && defined(__i386__)
63 __asm__
volatile (
"rdtsc" :
"=A"(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));
68 return (r2 << 32) | r1;
71 return std::chrono::high_resolution_clock::now().time_since_epoch().count();
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;
81 static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND,
"Unexpected value for bit_RDRND");
84 static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED,
"Unexpected value for bit_RDSEED");
87 static void InitHardwareRand()
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;
94 GetCPUID(7, 0, eax, ebx, ecx, edx);
95 if (ebx & CPUID_F7_EBX_RDSEED) {
96 g_rdseed_supported =
true;
100 static void ReportHardwareRand()
104 if (g_rdseed_supported) {
105 LogPrintf(
"Using RdSeed as additional entropy source\n");
107 if (g_rdrand_supported) {
108 LogPrintf(
"Using RdRand as an additional entropy source\n");
116 static uint64_t GetRdRand() noexcept
122 for (
int i = 0; i < 10; ++i) {
123 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
126 for (
int i = 0; i < 10; ++i) {
127 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r2),
"=q"(ok) ::
"cc");
130 return (((uint64_t)r2) << 32) | r1;
131 #elif defined(__x86_64__) || defined(__amd64__)
134 for (
int i = 0; i < 10; ++i) {
135 __asm__
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
140 #error "RdRand is only supported on x86 and x86_64"
148 static uint64_t GetRdSeed() noexcept
156 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
158 __asm__
volatile (
"pause");
161 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r2),
"=q"(ok) ::
"cc");
163 __asm__
volatile (
"pause");
165 return (((uint64_t)r2) << 32) | r1;
166 #elif defined(__x86_64__) || defined(__amd64__)
170 __asm__
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
172 __asm__
volatile (
"pause");
176 #error "RdSeed is only supported on x86 and x86_64"
186 static void InitHardwareRand() {}
187 static void ReportHardwareRand() {}
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));
202 static void SeedHardwareSlow(
CSHA512& hasher) noexcept {
203 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
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));
215 if (g_rdrand_supported) {
216 for (
int i = 0; i < 4; ++i) {
218 for (
int j = 0; j < 1024; ++j) out ^= GetRdRand();
219 hasher.
Write((
const unsigned char*)&out,
sizeof(out));
227 static void Strengthen(
const unsigned char (&seed)[32],
int microseconds,
CSHA512& hasher) noexcept
230 inner_hasher.
Write(seed,
sizeof(seed));
236 for (
int i = 0; i < 1000; ++i) {
238 inner_hasher.
Reset();
242 int64_t perf = GetPerformanceCounter();
243 hasher.
Write((
const unsigned char*)&perf,
sizeof(perf));
250 inner_hasher.
Reset();
260 int f = open(
"/dev/urandom", O_RDONLY);
266 ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
267 if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
272 }
while (have < NUM_OS_RANDOM_BYTES);
281 HCRYPTPROV hProvider;
282 int ret = CryptAcquireContextW(&hProvider,
nullptr,
nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
286 ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
290 CryptReleaseContext(hProvider, 0);
291 #elif defined(HAVE_SYS_GETRANDOM)
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) {
309 #elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
316 if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
319 #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
321 if (&getentropy !=
nullptr) {
322 if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
328 #elif defined(HAVE_SYSCTL_ARND)
332 static const int name[2] = {CTL_KERN, KERN_ARND};
335 size_t len = NUM_OS_RANDOM_BYTES - have;
340 }
while (have < NUM_OS_RANDOM_BYTES);
361 unsigned char m_state[32]
GUARDED_BY(m_mutex) = {0};
363 bool m_strongly_seeded
GUARDED_BY(m_mutex) =
false;
365 Mutex m_events_mutex;
378 void AddEvent(uint32_t event_info) noexcept
380 LOCK(m_events_mutex);
382 m_events_hasher.Write((
const unsigned char *)&event_info,
sizeof(event_info));
385 uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
386 m_events_hasher.Write((
const unsigned char*)&perfcounter,
sizeof(perfcounter));
392 void SeedEvents(
CSHA512& hasher) noexcept
396 LOCK(m_events_mutex);
398 unsigned char events_hash[32];
399 m_events_hasher.Finalize(events_hash);
400 hasher.
Write(events_hash, 32);
403 m_events_hasher.
Reset();
404 m_events_hasher.
Write(events_hash, 32);
411 bool MixExtract(
unsigned char* out,
size_t num,
CSHA512&& hasher,
bool strong_seed) noexcept
414 unsigned char buf[64];
415 static_assert(
sizeof(buf) ==
CSHA512::OUTPUT_SIZE,
"Buffer needs to have hasher's output size");
419 ret = (m_strongly_seeded |= strong_seed);
421 hasher.
Write(m_state, 32);
423 hasher.
Write((
const unsigned char*)&m_counter,
sizeof(m_counter));
428 memcpy(m_state, buf + 32, 32);
432 assert(out !=
nullptr);
442 RNGState& GetRNGState() noexcept
446 static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
456 static void SeedTimestamp(
CSHA512& hasher) noexcept
458 int64_t perfcounter = GetPerformanceCounter();
459 hasher.
Write((
const unsigned char*)&perfcounter,
sizeof(perfcounter));
462 static void SeedFast(
CSHA512& hasher) noexcept
467 const unsigned char* ptr =
buffer;
468 hasher.
Write((
const unsigned char*)&ptr,
sizeof(ptr));
471 SeedHardwareFast(hasher);
474 SeedTimestamp(hasher);
477 static void SeedSlow(
CSHA512& hasher, RNGState& rng) noexcept
489 rng.SeedEvents(hasher);
495 SeedTimestamp(hasher);
499 static void SeedStrengthen(
CSHA512& hasher, RNGState& rng,
int microseconds) noexcept
502 unsigned char strengthen_seed[32];
503 rng.MixExtract(strengthen_seed,
sizeof(strengthen_seed),
CSHA512(hasher),
false);
505 Strengthen(strengthen_seed, microseconds, hasher);
508 static void SeedPeriodic(
CSHA512& hasher, RNGState& rng) noexcept
514 SeedTimestamp(hasher);
517 rng.SeedEvents(hasher);
523 SeedStrengthen(hasher, rng, 10000);
526 static void SeedStartup(
CSHA512& hasher, RNGState& rng) noexcept
529 SeedHardwareSlow(hasher);
532 SeedSlow(hasher, rng);
541 SeedStrengthen(hasher, rng, 100000);
550 static void ProcRand(
unsigned char* out,
int num,
RNGLevel level) noexcept
553 RNGState& rng = GetRNGState();
563 SeedSlow(hasher, rng);
566 SeedPeriodic(hasher, rng);
571 if (!rng.MixExtract(out, num, std::move(hasher),
false)) {
574 SeedStartup(startup_hasher, rng);
575 rng.MixExtract(out, num, std::move(startup_hasher),
true);
582 void RandAddEvent(
const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
609 const uint64_t v = 100000000;
611 return r <= v * rate;
635 std::vector<unsigned char> ret(len);
644 rng.SetKey(seed.begin(), 32);
649 uint64_t start = GetPerformanceCounter();
655 static const ssize_t MAX_TRIES = 1024;
656 uint8_t data[NUM_OS_RANDOM_BYTES];
657 bool overwritten[NUM_OS_RANDOM_BYTES] = {};
662 memset(data, 0, NUM_OS_RANDOM_BYTES);
664 for (
int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
665 overwritten[x] |= (data[x] != 0);
669 for (
int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
670 if (overwritten[x]) {
671 num_overwritten += 1;
676 }
while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
677 if (num_overwritten != NUM_OS_RANDOM_BYTES)
return false;
680 std::this_thread::sleep_for(std::chrono::milliseconds(1));
681 uint64_t
stop = GetPerformanceCounter();
682 if (
stop == start)
return false;
686 to_add.
Write((
const unsigned char*)&start,
sizeof(start));
688 GetRNGState().MixExtract(
nullptr, 0, std::move(to_add),
false);
695 if (!fDeterministic) {
699 rng.SetKey(seed.
begin(), 32);
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;
721 ReportHardwareRand();
A hasher class for SHA-256.
A hasher class for SHA-512.
static constexpr size_t OUTPUT_SIZE
void Finalize(unsigned char hash[OUTPUT_SIZE])
CSHA512 & Write(const unsigned char *data, size_t len)
void Keystream(unsigned char *c, size_t bytes)
outputs the keystream of size <bytes> into
void SetKey(const unsigned char *key, size_t keylen)
set key with flexible keylength; 256bit recommended */
unsigned char bytebuf[64]
FastRandomContext(bool fDeterministic=false) noexcept
uint256 rand256() noexcept
generate a random uint256.
std::vector< unsigned char > randbytes(size_t len)
Generate random bytes.
FastRandomContext & operator=(const FastRandomContext &)=delete
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
void memory_cleanse(void *ptr, size_t len)
std::vector< uint8_t > buffer
void * memcpy(void *a, const void *b, size_t c)
void GetDevURandom(unsigned char *ent32)
Fallback: get 32 bytes of system entropy from /dev/urandom.
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
bool g_mock_deterministic_tests
Flag to make GetRand in random.h return the same number.
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
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...
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
uint256 GetRandHash() noexcept
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
bool GetRandBool(double rate) noexcept
uint64_t GetRand(uint64_t nMax) noexcept
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
@ 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.
int GetRandInt(int nMax) noexcept
void RandAddStaticEnv(CSHA512 &hasher)
Gather non-cryptographic environment data that does not change over time.
void RandAddDynamicEnv(CSHA512 &hasher)
Gather non-cryptographic environment data that changes over time.
UniValue stop(const JSONRPCRequest &jsonRequest)
int64_t GetTimeMicros()
Returns the system time (not mockable)