6#include <bitcoin-build-config.h>
36#if defined(HAVE_GETRANDOM) || (defined(HAVE_GETENTROPY_RAND) && defined(__APPLE__))
37#include <sys/random.h>
40#ifdef HAVE_SYSCTL_ARND
41#include <sys/sysctl.h>
56 LogError(
"Failed to read randomness, aborting\n");
64#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
66#elif !defined(_MSC_VER) && defined(__i386__)
68 __asm__ volatile (
"rdtsc" :
"=A"(r));
70#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
73 return (
r2 << 32) |
r1;
76 return std::chrono::high_resolution_clock::now().time_since_epoch().count();
110 LogInfo(
"Using RdSeed as an additional entropy source");
113 LogInfo(
"Using RdRand as an additional entropy source");
130 for (
int i = 0; i < 10; ++i) {
131 __asm__ volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(
r1),
"=q"(
ok) ::
"cc");
134 for (
int i = 0; i < 10; ++i) {
135 __asm__ volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(
r2),
"=q"(
ok) ::
"cc");
139#elif defined(__x86_64__) || defined(__amd64__)
142 for (
int i = 0; i < 10; ++i) {
143 __asm__ volatile (
".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(
r1),
"=q"(
ok) ::
"cc");
148#error "RdRand is only supported on x86 and x86_64"
164 __asm__ volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(
r1),
"=q"(
ok) ::
"cc");
169 __asm__ volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(
r2),
"=q"(
ok) ::
"cc");
174#elif defined(__x86_64__) || defined(__amd64__)
178 __asm__ volatile (
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(
r1),
"=q"(
ok) ::
"cc");
184#error "RdSeed is only supported on x86 and x86_64"
200#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
203 hasher.Write((
const unsigned char*)&out,
sizeof(out));
211#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
215 for (
int i = 0; i < 4; ++i) {
217 hasher.Write((
const unsigned char*)&out,
sizeof(out));
224 for (
int i = 0; i < 4; ++i) {
227 hasher.Write((
const unsigned char*)&out,
sizeof(out));
241 unsigned char buffer[64];
242 const auto stop{SteadyClock::now() +
dur};
244 for (
int i = 0; i < 1000; ++i) {
252 }
while (SteadyClock::now() <
stop);
256 hasher.Write(buffer,
sizeof(buffer));
298#elif defined(HAVE_GETRANDOM)
307#elif defined(__OpenBSD__)
315#elif defined(HAVE_GETENTROPY_RAND) && defined(__APPLE__)
319#elif defined(HAVE_SYSCTL_ARND)
350 unsigned char m_state[32]
GUARDED_BY(m_mutex) = {0};
358 Mutex m_events_mutex;
371 LOCK(m_events_mutex);
387 LOCK(m_events_mutex);
415 unsigned char buf[64];
416 static_assert(
sizeof(buf) ==
CSHA512::OUTPUT_SIZE,
"Buffer needs to have hasher's output size");
422 hasher.Write(m_state, 32);
424 hasher.Write((
const unsigned char*)&m_counter,
sizeof(m_counter));
429 memcpy(m_state, buf + 32, 32);
454 static std::vector<RNGState, secure_allocator<RNGState>>
g_rng(1);
471 unsigned char buffer[32];
474 const unsigned char* ptr = buffer;
475 hasher.Write((
const unsigned char*)&ptr,
sizeof(ptr));
486 unsigned char buffer[32];
493 hasher.Write(buffer,
sizeof(buffer));
577 case RNGLevel::PERIODIC:
604 ProcRand(bytes.data(), bytes.size(), RNGLevel::FAST,
false);
609 ProcRand(bytes.data(), bytes.size(), RNGLevel::SLOW,
true);
614 ProcRand(
nullptr, 0, RNGLevel::PERIODIC,
false);
628 if (requires_seed) RandomSeed();
629 rng.Keystream(output);
637 requires_seed =
false;
674 std::this_thread::sleep_for(std::chrono::milliseconds(1));
676 if (
stop == start)
return false;
680 to_add.
Write((
const unsigned char*)&start,
sizeof(start));
687static constexpr std::array<std::byte, ChaCha20::KEYLEN>
ZERO_KEY{};
699 ProcRand(
nullptr, 0, RNGLevel::FAST,
true);
715 return -std::log1p((
uniform >> 11) * -0x1.0p-53);
A hasher class for SHA-256.
A hasher class for SHA-512.
static constexpr size_t OUTPUT_SIZE
CSHA512 & Write(const unsigned char *data, size_t len)
void SetKey(std::span< const std::byte > key) noexcept
Set 32-byte key, and seek to nonce 0 and block position 0.
FastRandomContext(bool fDeterministic=false) noexcept
Construct a FastRandomContext with GetRandHash()-based entropy (or zero key if fDeterministic).
void RandomSeed() noexcept
void fillrand(std::span< std::byte > output) noexcept
Fill a byte span with random bytes.
void Reseed(const uint256 &seed) noexcept
Reseed with explicit seed (only for testing).
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
#define LogDebug(category,...)
std::atomic< bool > g_used_g_prng
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
void GetStrongRandBytes(std::span< unsigned char > bytes) 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.
static constexpr std::array< std::byte, ChaCha20::KEYLEN > ZERO_KEY
void MakeRandDeterministicDANGEROUS(const uint256 &seed) noexcept
Internal function to set g_determinstic_rng.
void RandomInit()
Overall design of the RNG and entropy sources.
void GetRandBytes(std::span< unsigned char > bytes) noexcept
Generate random data via the internal PRNG.
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
double MakeExponentiallyDistributed(uint64_t uniform) noexcept
Given a uniformly random uint64_t, return an exponentially distributed double with mean 1.
uint256 GetRandHash() noexcept
Generate a random uint256.
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.
auto MakeByteSpan(const V &v) noexcept
#define EXCLUSIVE_LOCKS_REQUIRED(...)
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.