33#ifdef HAVE_SYS_GETRANDOM
34#include <linux/random.h>
35#include <sys/syscall.h>
37#if defined(HAVE_GETENTROPY) || \
38 (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
45#include <sys/sysctl.h>
49 LogPrintf(
"Failed to read randomness, aborting\n");
56#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
58#elif !defined(_MSC_VER) && defined(__i386__)
61 __asm__
volatile(
"rdtsc" :
"=A"(r));
63#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
64 uint64_t r1 = 0, r2 = 0;
66 __asm__
volatile(
"rdtsc" :
"=a"(r1),
"=d"(r2));
67 return (r2 << 32) | r1;
71 return std::chrono::high_resolution_clock::now().time_since_epoch().count();
76static bool g_rdrand_supported =
false;
77static bool g_rdseed_supported =
false;
78static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
79static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;
81static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND,
82 "Unexpected value for bit_RDRND");
85static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED,
86 "Unexpected value for bit_RDSEED");
90 uint32_t eax, ebx, ecx, edx;
91 GetCPUID(1, 0, eax, ebx, ecx, edx);
92 if (ecx & CPUID_F1_ECX_RDRAND) {
93 g_rdrand_supported =
true;
95 GetCPUID(7, 0, eax, ebx, ecx, edx);
96 if (ebx & CPUID_F7_EBX_RDSEED) {
97 g_rdseed_supported =
true;
105 if (g_rdseed_supported) {
106 LogPrintf(
"Using RdSeed as additional entropy source\n");
108 if (g_rdrand_supported) {
109 LogPrintf(
"Using RdRand as an additional entropy source\n");
118static uint64_t GetRdRand() noexcept {
126 uint32_t r1 = 0, r2 = 0;
127 for (
int i = 0; i < 10; ++i) {
129 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf0; setc %1"
130 :
"=a"(r1),
"=q"(ok)::
"cc");
135 for (
int i = 0; i < 10; ++i) {
137 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf0; setc %1"
138 :
"=a"(r2),
"=q"(ok)::
"cc");
143 return (uint64_t(r2) << 32) | r1;
144#elif defined(__x86_64__) || defined(__amd64__)
147 for (
int i = 0; i < 10; ++i) {
149 __asm__
volatile(
".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1"
150 :
"=a"(r1),
"=q"(ok)::
"cc");
157#error "RdRand is only supported on x86 and x86_64"
166static uint64_t GetRdSeed() noexcept {
174 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf8; setc %1"
175 :
"=a"(r1),
"=q"(ok)::
"cc");
179 __asm__
volatile(
"pause");
183 __asm__
volatile(
".byte 0x0f, 0xc7, 0xf8; setc %1"
184 :
"=a"(r2),
"=q"(ok)::
"cc");
188 __asm__
volatile(
"pause");
190 return (uint64_t(r2) << 32) | r1;
191#elif defined(__x86_64__) || defined(__amd64__)
196 __asm__
volatile(
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1"
197 :
"=a"(r1),
"=q"(ok)::
"cc");
201 __asm__
volatile(
"pause");
205#error "RdSeed is only supported on x86 and x86_64"
225#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
226 if (g_rdrand_supported) {
227 uint64_t out = GetRdRand();
228 hasher.Write((
const uint8_t *)&out,
sizeof(out));
239#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
242 if (g_rdseed_supported) {
243 for (
int i = 0; i < 4; ++i) {
244 uint64_t out = GetRdSeed();
245 hasher.Write((
const uint8_t *)&out,
sizeof(out));
251 if (g_rdrand_supported) {
252 for (
int i = 0; i < 4; ++i) {
254 for (
int j = 0; j < 1024; ++j) {
257 hasher.Write((
const uint8_t *)&out,
sizeof(out));
268static void Strengthen(
const uint8_t (&seed)[32],
int microseconds,
271 inner_hasher.
Write(seed,
sizeof(seed));
277 for (
int i = 0; i < 1000; ++i) {
279 inner_hasher.
Reset();
280 inner_hasher.
Write(buffer,
sizeof(buffer));
284 hasher.Write((
const uint8_t *)&perf,
sizeof(perf));
289 hasher.Write(buffer,
sizeof(buffer));
291 inner_hasher.
Reset();
301 int f = open(
"/dev/urandom", O_RDONLY);
321 HCRYPTPROV hProvider;
322 int ret = CryptAcquireContextW(&hProvider,
nullptr,
nullptr, PROV_RSA_FULL,
323 CRYPT_VERIFYCONTEXT);
331 CryptReleaseContext(hProvider, 0);
332#elif defined(HAVE_SYS_GETRANDOM)
341 if (rv < 0 && errno == ENOSYS) {
351#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
364#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
373#elif defined(HAVE_SYSCTL_ARND)
378 static const int name[2] = {CTL_KERN, KERN_ARND};
382 if (sysctl(
name, std::size(
name), ent32 + have, &len,
nullptr, 0) !=
412 uint8_t m_state[32]
GUARDED_BY(m_mutex) = {0};
414 bool m_strongly_seeded
GUARDED_BY(m_mutex) =
false;
416 Mutex m_events_mutex;
424 void AddEvent(uint32_t event_info)
noexcept
426 LOCK(m_events_mutex);
428 m_events_hasher.Write((
const uint8_t *)&event_info,
sizeof(event_info));
432 m_events_hasher.Write((
const uint8_t *)&perfcounter,
433 sizeof(perfcounter));
439 void SeedEvents(
CSHA512 &hasher)
noexcept
444 LOCK(m_events_mutex);
446 uint8_t events_hash[32];
447 m_events_hasher.Finalize(events_hash);
448 hasher.Write(events_hash, 32);
451 m_events_hasher.Reset();
452 m_events_hasher.Write(events_hash, 32);
462 bool MixExtract(uint8_t *out,
size_t num,
CSHA512 &&hasher,
463 bool strong_seed)
noexcept
468 "Buffer needs to have hasher's output size");
472 ret = (m_strongly_seeded |= strong_seed);
474 hasher.Write(m_state, 32);
476 hasher.Write((
const uint8_t *)&m_counter,
sizeof(m_counter));
479 hasher.Finalize(buf);
481 memcpy(m_state, buf + 32, 32);
487 memcpy(out, buf, num);
496RNGState &GetRNGState() noexcept {
500 static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
513 hasher.Write((
const uint8_t *)&perfcounter,
sizeof(perfcounter));
520 const uint8_t *ptr = buffer;
521 hasher.Write((
const uint8_t *)&ptr,
sizeof(ptr));
538 hasher.Write(buffer,
sizeof(buffer));
541 rng.SeedEvents(hasher);
553 int microseconds)
noexcept {
556 uint8_t strengthen_seed[32];
557 rng.MixExtract(strengthen_seed,
sizeof(strengthen_seed),
CSHA512(hasher),
560 Strengthen(strengthen_seed, microseconds, hasher);
571 rng.SeedEvents(hasher);
574 auto old_size = hasher.Size();
577 "Feeding %i bytes of dynamic environment data into RNG\n",
578 hasher.Size() - old_size);
592 auto old_size = hasher.Size();
598 hasher.Size() - old_size);
613 RNGState &rng = GetRNGState();
631 if (!rng.MixExtract(out, num, std::move(hasher),
false)) {
635 rng.MixExtract(out, num, std::move(startup_hasher),
true);
650 GetRNGState().AddEvent(event_info);
694 std::vector<uint8_t> ret(len);
702 : requires_seed(
false), bytebuf_size(0), bitbuf_size(0) {
703 rng.SetKey(seed.begin(), 32);
714 static const ssize_t MAX_TRIES = 1024;
728 overwritten[x] |= (data[x] != 0);
733 if (overwritten[x]) {
734 num_overwritten += 1;
747 std::this_thread::sleep_for(std::chrono::milliseconds(1));
755 to_add.
Write((
const uint8_t *)&start,
sizeof(start));
757 GetRNGState().MixExtract(
nullptr, 0, std::move(to_add),
false);
763 : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) {
764 if (!fDeterministic) {
768 rng.SetKey(seed.
begin(), 32);
775 std::copy(std::begin(from.bytebuf), std::end(from.bytebuf),
776 std::begin(bytebuf));
777 bytebuf_size = from.bytebuf_size;
778 bitbuf = from.bitbuf;
779 bitbuf_size = from.bitbuf_size;
780 from.requires_seed =
true;
781 from.bytebuf_size = 0;
782 from.bitbuf_size = 0;
793std::chrono::microseconds
795 std::chrono::seconds average_interval) {
796 double unscaled = -std::log1p(
GetRand(uint64_t{1} << 48) *
797 -0.0000000000000035527136788 );
798 return now + std::chrono::duration_cast<std::chrono::microseconds>(
799 unscaled * average_interval + 0.5us);
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).
A Span is an object that can refer to a contiguous sequence of objects.
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
#define LogPrint(category,...)
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en....
static void ReportHardwareRand()
void GetRandBytes(Span< uint8_t > bytes) noexcept
Overall design of the RNG and entropy sources.
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.
uint64_t GetRandInternal(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
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
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.
static void SeedHardwareSlow(CSHA512 &hasher) noexcept
Add 256 bits of entropy gathered from hardware to hasher.
static int64_t GetPerformanceCounter() noexcept
void GetStrongRandBytes(Span< uint8_t > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
static void SeedSlow(CSHA512 &hasher, RNGState &rng) noexcept
static const int NUM_OS_RANDOM_BYTES
Number of random bytes returned by GetOSRand.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
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.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetTimeMicros()
Returns the system time (not mockable)