31 #ifdef HAVE_SYS_GETRANDOM
32 #include <linux/random.h>
33 #include <sys/syscall.h>
35 #if defined(HAVE_GETENTROPY) || \
36 (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX))
39 #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
40 #include <sys/random.h>
42 #ifdef HAVE_SYSCTL_ARND
43 #include <sys/sysctl.h>
47 LogPrintf(
"Failed to read randomness, aborting\n");
54 #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
56 #elif !defined(_MSC_VER) && defined(__i386__)
59 __asm__
volatile(
"rdtsc" :
"=A"(r));
61 #elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
62 uint64_t r1 = 0, r2 = 0;
64 __asm__
volatile(
"rdtsc" :
"=a"(r1),
"=d"(r2));
65 return (r2 << 32) | r1;
69 return std::chrono::high_resolution_clock::now().time_since_epoch().count();
74 static bool g_rdrand_supported =
false;
75 static bool g_rdseed_supported =
false;
76 static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
77 static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;
79 static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND,
80 "Unexpected value for bit_RDRND");
83 static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED,
84 "Unexpected value for bit_RDSEED");
88 uint32_t eax, ebx, ecx, edx;
89 GetCPUID(1, 0, eax, ebx, ecx, edx);
90 if (ecx & CPUID_F1_ECX_RDRAND) {
91 g_rdrand_supported =
true;
93 GetCPUID(7, 0, eax, ebx, ecx, edx);
94 if (ebx & CPUID_F7_EBX_RDSEED) {
95 g_rdseed_supported =
true;
103 if (g_rdseed_supported) {
104 LogPrintf(
"Using RdSeed as additional entropy source\n");
106 if (g_rdrand_supported) {
107 LogPrintf(
"Using RdRand as an additional entropy source\n");
116 static uint64_t GetRdRand() noexcept {
124 uint32_t r1 = 0, r2 = 0;
125 for (
int i = 0; i < 10; ++i) {
127 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf0; setc %1"
128 :
"=a"(r1),
"=q"(ok)::
"cc");
133 for (
int i = 0; i < 10; ++i) {
135 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf0; setc %1"
136 :
"=a"(r2),
"=q"(ok)::
"cc");
141 return (uint64_t(r2) << 32) | r1;
142 #elif defined(__x86_64__) || defined(__amd64__)
145 for (
int i = 0; i < 10; ++i) {
147 __asm__
volatile(
".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1"
148 :
"=a"(r1),
"=q"(ok)::
"cc");
155 #error "RdRand is only supported on x86 and x86_64"
164 static uint64_t GetRdSeed() noexcept {
172 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf8; setc %1"
173 :
"=a"(r1),
"=q"(ok)::
"cc");
177 __asm__
volatile(
"pause");
181 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf8; setc %1"
182 :
"=a"(r2),
"=q"(ok)::
"cc");
186 __asm__
volatile(
"pause");
188 return (uint64_t(r2) << 32) | r1;
189 #elif defined(__x86_64__) || defined(__amd64__)
194 __asm__
volatile(
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1"
195 :
"=a"(r1),
"=q"(ok)::
"cc");
199 __asm__
volatile(
"pause");
203 #error "RdSeed is only supported on x86 and x86_64"
223 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
224 if (g_rdrand_supported) {
225 uint64_t out = GetRdRand();
226 hasher.Write((
const uint8_t *)&out,
sizeof(out));
237 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
240 if (g_rdseed_supported) {
241 for (
int i = 0; i < 4; ++i) {
242 uint64_t out = GetRdSeed();
243 hasher.Write((
const uint8_t *)&out,
sizeof(out));
249 if (g_rdrand_supported) {
250 for (
int i = 0; i < 4; ++i) {
252 for (
int j = 0; j < 1024; ++j) {
255 hasher.Write((
const uint8_t *)&out,
sizeof(out));
266 static void Strengthen(
const uint8_t (&seed)[32],
int microseconds,
269 inner_hasher.
Write(seed,
sizeof(seed));
275 for (
int i = 0; i < 1000; ++i) {
277 inner_hasher.
Reset();
278 inner_hasher.
Write(buffer,
sizeof(buffer));
282 hasher.Write((
const uint8_t *)&perf,
sizeof(perf));
287 hasher.Write(buffer,
sizeof(buffer));
289 inner_hasher.
Reset();
299 int f = open(
"/dev/urandom", O_RDONLY);
319 HCRYPTPROV hProvider;
320 int ret = CryptAcquireContextW(&hProvider,
nullptr,
nullptr, PROV_RSA_FULL,
321 CRYPT_VERIFYCONTEXT);
329 CryptReleaseContext(hProvider, 0);
330 #elif defined(HAVE_SYS_GETRANDOM)
339 if (rv < 0 && errno == ENOSYS) {
349 #elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
362 #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
371 #elif defined(HAVE_SYSCTL_ARND)
376 static const int name[2] = {CTL_KERN, KERN_ARND};
380 if (sysctl(
name, std::size(
name), ent32 + have, &len,
nullptr, 0) !=
410 uint8_t m_state[32]
GUARDED_BY(m_mutex) = {0};
412 bool m_strongly_seeded
GUARDED_BY(m_mutex) =
false;
414 Mutex m_events_mutex;
422 void AddEvent(uint32_t event_info) noexcept {
423 LOCK(m_events_mutex);
425 m_events_hasher.Write((
const uint8_t *)&event_info,
sizeof(event_info));
429 m_events_hasher.Write((
const uint8_t *)&perfcounter,
430 sizeof(perfcounter));
436 void SeedEvents(
CSHA512 &hasher) noexcept {
440 LOCK(m_events_mutex);
442 uint8_t events_hash[32];
443 m_events_hasher.Finalize(events_hash);
444 hasher.Write(events_hash, 32);
447 m_events_hasher.Reset();
448 m_events_hasher.Write(events_hash, 32);
458 bool MixExtract(uint8_t *out,
size_t num,
CSHA512 &&hasher,
459 bool strong_seed) noexcept {
463 "Buffer needs to have hasher's output size");
467 ret = (m_strongly_seeded |= strong_seed);
469 hasher.Write(m_state, 32);
471 hasher.Write((
const uint8_t *)&m_counter,
sizeof(m_counter));
474 hasher.Finalize(buf);
476 memcpy(m_state, buf + 32, 32);
482 memcpy(out, buf, num);
491 RNGState &GetRNGState() noexcept {
495 static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
508 hasher.Write((
const uint8_t *)&perfcounter,
sizeof(perfcounter));
515 const uint8_t *ptr = buffer;
516 hasher.Write((
const uint8_t *)&ptr,
sizeof(ptr));
533 hasher.Write(buffer,
sizeof(buffer));
536 rng.SeedEvents(hasher);
548 int microseconds) noexcept {
551 uint8_t strengthen_seed[32];
552 rng.MixExtract(strengthen_seed,
sizeof(strengthen_seed),
CSHA512(hasher),
555 Strengthen(strengthen_seed, microseconds, hasher);
566 rng.SeedEvents(hasher);
569 auto old_size = hasher.Size();
572 "Feeding %i bytes of dynamic environment data into RNG\n",
573 hasher.Size() - old_size);
587 auto old_size = hasher.Size();
593 hasher.Size() - old_size);
608 RNGState &rng = GetRNGState();
626 if (!rng.MixExtract(out, num, std::move(hasher),
false)) {
630 rng.MixExtract(out, num, std::move(startup_hasher),
true);
645 GetRNGState().AddEvent(event_info);
693 std::vector<uint8_t> ret(len);
701 : requires_seed(
false), bytebuf_size(0), bitbuf_size(0) {
702 rng.SetKey(seed.begin(), 32);
713 static const ssize_t MAX_TRIES = 1024;
727 overwritten[x] |= (data[x] != 0);
732 if (overwritten[x]) {
733 num_overwritten += 1;
746 std::this_thread::sleep_for(std::chrono::milliseconds(1));
754 to_add.
Write((
const uint8_t *)&start,
sizeof(start));
756 GetRNGState().MixExtract(
nullptr, 0, std::move(to_add),
false);
762 : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) {
763 if (!fDeterministic) {
767 rng.SetKey(seed.
begin(), 32);
774 std::copy(std::begin(from.bytebuf), std::end(from.bytebuf),
775 std::begin(bytebuf));
776 bytebuf_size = from.bytebuf_size;
777 bitbuf = from.bitbuf;
778 bitbuf_size = from.bitbuf_size;
779 from.requires_seed =
true;
780 from.bytebuf_size = 0;
781 from.bitbuf_size = 0;
A hasher class for SHA-256.
A hasher class for SHA-512.
CSHA512 & Write(const uint8_t *data, size_t len)
static constexpr size_t OUTPUT_SIZE
void Finalize(uint8_t hash[OUTPUT_SIZE])
void SetKey(const uint8_t *key, size_t keylen)
set key with flexible keylength; 256bit recommended
void Keystream(uint8_t *c, size_t bytes)
outputs the keystream of size <bytes> into
uint160 rand160() noexcept
generate a random uint160.
std::vector< uint8_t > randbytes(size_t len)
Generate random bytes.
FastRandomContext(bool fDeterministic=false) noexcept
uint256 rand256() noexcept
generate a random uint256.
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)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
#define LogPrint(category,...)
static void ReportHardwareRand()
static void SeedStrengthen(CSHA512 &hasher, RNGState &rng, int microseconds) noexcept
Extract entropy from rng, strengthen it, and feed it into hasher.
static void SeedStartup(CSHA512 &hasher, RNGState &rng) noexcept
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
bool g_mock_deterministic_tests
static void SeedFast(CSHA512 &hasher) noexcept
static void GetDevURandom(uint8_t *ent32)
Fallback: get 32 bytes of system entropy from /dev/urandom.
static void InitHardwareRand()
Access to other hardware random number generators could be added here later, assuming it is sufficien...
static void SeedHardwareFast(CSHA512 &hasher) noexcept
Add 64 bits of entropy gathered from hardware to hasher.
void GetStrongRandBytes(uint8_t *buf, int num) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
void GetOSRand(uint8_t *ent32)
Get 32 bytes of system entropy.
static void SeedTimestamp(CSHA512 &hasher) noexcept
A note on the use of noexcept in the seeding functions below:
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
static void Strengthen(const uint8_t(&seed)[32], int microseconds, CSHA512 &hasher) noexcept
Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher.
uint256 GetRandHash() noexcept
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
static void SeedPeriodic(CSHA512 &hasher, RNGState &rng) noexcept
static void ProcRand(uint8_t *out, int num, RNGLevel level) noexcept
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
static void RandFailure()
@ SLOW
Automatically called by GetStrongRandBytes.
@ PERIODIC
Called by RandAddPeriodic()
@ FAST
Automatically called by GetRandBytes.
void GetRandBytes(uint8_t *buf, int num) noexcept
Overall design of the RNG and entropy sources.
int GetRandInt(int nMax) noexcept
static void SeedHardwareSlow(CSHA512 &hasher) noexcept
Add 256 bits of entropy gathered from hardware to hasher.
static int64_t GetPerformanceCounter() noexcept
static void SeedSlow(CSHA512 &hasher, RNGState &rng) noexcept
static const int NUM_OS_RANDOM_BYTES
Number of random bytes returned by GetOSRand.
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.
int64_t GetTimeMicros()
Returns the system time (not mockable)