6 #if defined(HAVE_CONFIG_H)
38 #if defined(HAVE_GETRANDOM) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX))
39 #include <sys/random.h>
42 #ifdef HAVE_SYSCTL_ARND
43 #include <sys/sysctl.h>
45 #if defined(HAVE_STRONG_GETAUXVAL) && defined(__aarch64__)
51 LogPrintf(
"Failed to read randomness, aborting\n");
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");
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;
104 if (g_rdseed_supported) {
105 LogPrintf(
"Using RdSeed as an 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
124 uint32_t r1 = 0, r2 = 0;
125 for (
int i = 0; i < 10; ++i) {
126 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
129 for (
int i = 0; i < 10; ++i) {
130 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r2),
"=q"(ok) ::
"cc");
133 return (((uint64_t)r2) << 32) | r1;
134 #elif defined(__x86_64__) || defined(__amd64__)
137 for (
int i = 0; i < 10; ++i) {
138 __asm__
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
143 #error "RdRand is only supported on x86 and x86_64"
151 static uint64_t GetRdSeed() noexcept
159 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
161 __asm__
volatile (
"pause");
164 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r2),
"=q"(ok) ::
"cc");
166 __asm__
volatile (
"pause");
168 return (((uint64_t)r2) << 32) | r1;
169 #elif defined(__x86_64__) || defined(__amd64__)
173 __asm__
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
175 __asm__
volatile (
"pause");
179 #error "RdSeed is only supported on x86 and x86_64"
183 #elif defined(__aarch64__) && defined(HWCAP2_RNG)
185 static bool g_rndr_supported =
false;
189 if (getauxval(AT_HWCAP2) & HWCAP2_RNG) {
190 g_rndr_supported =
true;
198 if (g_rndr_supported) {
199 LogPrintf(
"Using RNDR and RNDRRS as additional entropy sources\n");
207 static uint64_t GetRNDR() noexcept
213 __asm__
volatile(
"mrs %0, s3_3_c2_c4_0; cset %w1, ne;"
214 :
"=r"(r1),
"=r"(ok)::
"cc");
216 __asm__
volatile(
"yield");
225 static uint64_t GetRNDRRS() noexcept
231 __asm__
volatile(
"mrs %0, s3_3_c2_c4_1; cset %w1, ne;"
232 :
"=r"(r1),
"=r"(ok)::
"cc");
234 __asm__
volatile(
"yield");
251 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
252 if (g_rdrand_supported) {
253 uint64_t
out = GetRdRand();
254 hasher.Write((
const unsigned char*)&
out,
sizeof(
out));
257 #elif defined(__aarch64__) && defined(HWCAP2_RNG)
258 if (g_rndr_supported) {
259 uint64_t
out = GetRNDR();
260 hasher.Write((
const unsigned char*)&
out,
sizeof(
out));
268 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
271 if (g_rdseed_supported) {
272 for (
int i = 0; i < 4; ++i) {
273 uint64_t
out = GetRdSeed();
274 hasher.Write((
const unsigned char*)&
out,
sizeof(
out));
280 if (g_rdrand_supported) {
281 for (
int i = 0; i < 4; ++i) {
283 for (
int j = 0; j < 1024; ++j)
out ^= GetRdRand();
284 hasher.Write((
const unsigned char*)&
out,
sizeof(
out));
288 #elif defined(__aarch64__) && defined(HWCAP2_RNG)
289 if (g_rndr_supported) {
290 for (
int i = 0; i < 4; ++i) {
291 uint64_t
out = GetRNDRRS();
292 hasher.Write((
const unsigned char*)&
out,
sizeof(
out));
300 static void Strengthen(
const unsigned char (&seed)[32], SteadyClock::duration dur,
CSHA512& hasher) noexcept
303 inner_hasher.
Write(seed,
sizeof(seed));
306 unsigned char buffer[64];
307 const auto stop{SteadyClock::now() + dur};
309 for (
int i = 0; i < 1000; ++i) {
311 inner_hasher.
Reset();
312 inner_hasher.
Write(buffer,
sizeof(buffer));
316 hasher.Write((
const unsigned char*)&perf,
sizeof(perf));
317 }
while (SteadyClock::now() <
stop);
321 hasher.Write(buffer,
sizeof(buffer));
323 inner_hasher.
Reset();
333 int f = open(
"/dev/urandom", O_RDONLY);
354 HCRYPTPROV hProvider;
355 int ret = CryptAcquireContextW(&hProvider,
nullptr,
nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
363 CryptReleaseContext(hProvider, 0);
364 #elif defined(HAVE_GETRANDOM)
373 #elif defined(__OpenBSD__)
381 #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
385 #elif defined(HAVE_SYSCTL_ARND)
389 static int name[2] = {CTL_KERN, KERN_ARND};
393 if (sysctl(
name, std::size(
name), ent32 + have, &len,
nullptr, 0) != 0) {
418 unsigned char m_state[32]
GUARDED_BY(m_mutex) = {0};
420 bool m_strongly_seeded
GUARDED_BY(m_mutex) =
false;
422 Mutex m_events_mutex;
431 ~RNGState() =
default;
435 LOCK(m_events_mutex);
437 m_events_hasher.Write((
const unsigned char *)&event_info,
sizeof(event_info));
441 m_events_hasher.Write((
const unsigned char*)&perfcounter,
sizeof(perfcounter));
451 LOCK(m_events_mutex);
453 unsigned char events_hash[32];
454 m_events_hasher.Finalize(events_hash);
455 hasher.Write(events_hash, 32);
458 m_events_hasher.Reset();
459 m_events_hasher.Write(events_hash, 32);
469 unsigned char buf[64];
470 static_assert(
sizeof(buf) ==
CSHA512::OUTPUT_SIZE,
"Buffer needs to have hasher's output size");
474 ret = (m_strongly_seeded |= strong_seed);
476 hasher.Write(m_state, 32);
478 hasher.Write((
const unsigned char*)&m_counter,
sizeof(m_counter));
481 hasher.Finalize(buf);
483 memcpy(m_state, buf + 32, 32);
488 memcpy(
out, buf, num);
497 RNGState& GetRNGState() noexcept
501 static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
514 hasher.Write((
const unsigned char*)&perfcounter,
sizeof(perfcounter));
519 unsigned char buffer[32];
522 const unsigned char* ptr = buffer;
523 hasher.Write((
const unsigned char*)&ptr,
sizeof(ptr));
534 unsigned char buffer[32];
541 hasher.Write(buffer,
sizeof(buffer));
544 rng.SeedEvents(hasher);
557 unsigned char strengthen_seed[32];
558 rng.MixExtract(strengthen_seed,
sizeof(strengthen_seed),
CSHA512(hasher),
false);
572 rng.SeedEvents(hasher);
575 auto old_size = hasher.Size();
577 LogPrint(
BCLog::RAND,
"Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);
592 auto old_size = hasher.Size();
597 LogPrint(
BCLog::RAND,
"Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
612 RNGState& rng = GetRNGState();
630 if (!rng.MixExtract(
out, num, std::move(hasher),
false)) {
634 rng.MixExtract(
out, num, std::move(startup_hasher),
true);
641 void RandAddEvent(
const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
672 template <
typename B>
675 std::vector<B>
ret(len);
698 static constexpr
int MAX_TRIES{1024};
708 overwritten[x] |= (data[x] != 0);
713 if (overwritten[x]) {
714 num_overwritten += 1;
723 std::this_thread::sleep_for(std::chrono::milliseconds(1));
725 if (
stop == start)
return false;
729 to_add.
Write((
const unsigned char*)&start,
sizeof(start));
731 GetRNGState().MixExtract(
nullptr, 0, std::move(to_add),
false);
736 static constexpr std::array<std::byte, ChaCha20::KEYLEN>
ZERO_KEY{};
749 bitbuf = from.bitbuf;
750 bitbuf_size = from.bitbuf_size;
751 from.requires_seed =
true;
752 from.bitbuf_size = 0;
764 std::chrono::microseconds
GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
766 double unscaled = -std::log1p(
GetRand(uint64_t{1} << 48) * -0.0000000000000035527136788 );
767 return now + std::chrono::duration_cast<std::chrono::microseconds>(unscaled * average_interval + 0.5us);
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(Span< std::byte > out) noexcept
outputs the keystream to out.
void SetKey(Span< const std::byte > key) noexcept
Set 32-byte key, and seek to nonce 0 and block position 0.
void fillrand(Span< std::byte > output)
Fill a byte Span with random bytes.
FastRandomContext(bool fDeterministic=false) noexcept
uint256 rand256() noexcept
generate a random uint256.
FastRandomContext & operator=(const FastRandomContext &)=delete
std::vector< B > randbytes(size_t len)
Generate random bytes.
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()
static void SeedStrengthen(CSHA512 &hasher, RNGState &rng, SteadyClock::duration dur) noexcept
Extract entropy from rng, strengthen it, and feed it into hasher.
void GetRandBytes(Span< unsigned char > bytes) noexcept
Overall design of the RNG and entropy sources.
static void SeedStartup(CSHA512 &hasher, RNGState &rng) noexcept
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
static void GetDevURandom(unsigned char *ent32)
Fallback: get 32 bytes of system entropy from /dev/urandom.
bool g_mock_deterministic_tests
Flag to make GetRand in random.h return the same number.
static void SeedFast(CSHA512 &hasher) noexcept
static void InitHardwareRand()
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 GetStrongRandBytes(Span< unsigned char > bytes) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
static void SeedTimestamp(CSHA512 &hasher) noexcept
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
static constexpr std::array< std::byte, ChaCha20::KEYLEN > ZERO_KEY
uint256 GetRandHash() noexcept
static void ProcRand(unsigned char *out, int num, RNGLevel level) noexcept
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
static void SeedPeriodic(CSHA512 &hasher, RNGState &rng) 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()
static void Strengthen(const unsigned char(&seed)[32], SteadyClock::duration dur, CSHA512 &hasher) noexcept
Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher.
@ 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.
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
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.
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
#define EXCLUSIVE_LOCKS_REQUIRED(...)