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> 
   51static const int NUM_OS_RANDOM_BYTES = 32;
 
   54[[noreturn]] 
void RandFailure()
 
   56    LogError(
"Failed to read randomness, aborting\n");
 
   60inline int64_t GetPerformanceCounter() noexcept
 
   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__)) 
   71    uint64_t r1 = 0, r2 = 0;
 
   72    __asm__ 
volatile (
"rdtsc" : 
"=a"(r1), 
"=d"(r2)); 
 
   73    return (r2 << 32) | r1;
 
   76    return std::chrono::high_resolution_clock::now().time_since_epoch().count();
 
   81bool g_rdrand_supported = 
false;
 
   82bool g_rdseed_supported = 
false;
 
   83constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
 
   84constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;
 
   86static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, 
"Unexpected value for bit_RDRND");
 
   89static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, 
"Unexpected value for bit_RDSEED");
 
   92void InitHardwareRand()
 
   94    uint32_t eax, ebx, ecx, edx;
 
   95    GetCPUID(1, 0, eax, ebx, ecx, edx);
 
   96    if (ecx & CPUID_F1_ECX_RDRAND) {
 
   97        g_rdrand_supported = 
true;
 
   99    GetCPUID(7, 0, eax, ebx, ecx, edx);
 
  100    if (ebx & CPUID_F7_EBX_RDSEED) {
 
  101        g_rdseed_supported = 
true;
 
  105void ReportHardwareRand()
 
  109    if (g_rdseed_supported) {
 
  110        LogInfo(
"Using RdSeed as an additional entropy source");
 
  112    if (g_rdrand_supported) {
 
  113        LogInfo(
"Using RdRand as an additional entropy source");
 
  121uint64_t GetRdRand() noexcept
 
  129    uint32_t r1 = 0, r2 = 0;
 
  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"); 
 
  138    return (((uint64_t)r2) << 32) | r1;
 
  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" 
  156uint64_t GetRdSeed() noexcept
 
  164        __asm__ 
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" : 
"=a"(r1), 
"=q"(ok) :: 
"cc"); 
 
  166        __asm__ 
volatile (
"pause");
 
  169        __asm__ 
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" : 
"=a"(r2), 
"=q"(ok) :: 
"cc"); 
 
  171        __asm__ 
volatile (
"pause");
 
  173    return (((uint64_t)r2) << 32) | r1;
 
  174#elif defined(__x86_64__) || defined(__amd64__) 
  178        __asm__ 
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" : 
"=a"(r1), 
"=q"(ok) :: 
"cc"); 
 
  180        __asm__ 
volatile (
"pause");
 
  184#error "RdSeed is only supported on x86 and x86_64" 
  194void InitHardwareRand() {}
 
  195void ReportHardwareRand() {}
 
  199void SeedHardwareFast(
CSHA512& hasher) 
noexcept {
 
  200#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) 
  201    if (g_rdrand_supported) {
 
  202        uint64_t 
out = GetRdRand();
 
  203        hasher.Write((
const unsigned char*)&
out, 
sizeof(
out));
 
  210void SeedHardwareSlow(
CSHA512& hasher) 
noexcept {
 
  211#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) 
  214    if (g_rdseed_supported) {
 
  215        for (
int i = 0; i < 4; ++i) {
 
  216            uint64_t 
out = GetRdSeed();
 
  217            hasher.Write((
const unsigned char*)&
out, 
sizeof(
out));
 
  223    if (g_rdrand_supported) {
 
  224        for (
int i = 0; i < 4; ++i) {
 
  226            for (
int j = 0; j < 1024; ++j) 
out ^= GetRdRand();
 
  227            hasher.Write((
const unsigned char*)&
out, 
sizeof(
out));
 
  235void Strengthen(
const unsigned char (&seed)[32], SteadyClock::duration dur, 
CSHA512& hasher) 
noexcept 
  238    inner_hasher.
Write(seed, 
sizeof(seed));
 
  241    unsigned char buffer[64];
 
  242    const auto stop{SteadyClock::now() + dur};
 
  244        for (
int i = 0; i < 1000; ++i) {
 
  246            inner_hasher.
Reset();
 
  247            inner_hasher.
Write(buffer, 
sizeof(buffer));
 
  250        int64_t perf = GetPerformanceCounter();
 
  251        hasher.Write((
const unsigned char*)&perf, 
sizeof(perf));
 
  252    } 
while (SteadyClock::now() < 
stop);
 
  256    hasher.Write(buffer, 
sizeof(buffer));
 
  258    inner_hasher.
Reset();
 
  266[[maybe_unused]] 
void GetDevURandom(
unsigned char *ent32)
 
  268    int f = open(
"/dev/urandom", O_RDONLY);
 
  274        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
 
  275        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
 
  280    } 
while (have < NUM_OS_RANDOM_BYTES);
 
  286void GetOSRand(
unsigned char *ent32)
 
  289    constexpr uint32_t STATUS_SUCCESS{0x00000000};
 
  290    NTSTATUS status = BCryptGenRandom(NULL,
 
  293                                      BCRYPT_USE_SYSTEM_PREFERRED_RNG);
 
  295    if (status != STATUS_SUCCESS) {
 
  298#elif defined(HAVE_GETRANDOM) 
  304    if (getrandom(ent32, NUM_OS_RANDOM_BYTES, 0) != NUM_OS_RANDOM_BYTES) {
 
  307#elif defined(__OpenBSD__) 
  314    arc4random_buf(ent32, NUM_OS_RANDOM_BYTES);
 
  315#elif defined(HAVE_GETENTROPY_RAND) && defined(__APPLE__) 
  316    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
 
  319#elif defined(HAVE_SYSCTL_ARND) 
  323    static int name[2] = {CTL_KERN, KERN_ARND};
 
  326        size_t len = NUM_OS_RANDOM_BYTES - have;
 
  327        if (sysctl(
name, std::size(
name), ent32 + have, &len, 
nullptr, 0) != 0) {
 
  331    } 
while (have < NUM_OS_RANDOM_BYTES);
 
  336    GetDevURandom(ent32);
 
  350    unsigned char m_state[32] 
GUARDED_BY(m_mutex) = {0};
 
  352    bool m_strongly_seeded 
GUARDED_BY(m_mutex) = 
false;
 
  356    std::optional<ChaCha20> m_deterministic_prng 
GUARDED_BY(m_mutex);
 
  358    Mutex m_events_mutex;
 
  367    ~RNGState() = 
default;
 
  371        LOCK(m_events_mutex);
 
  373        m_events_hasher.Write((
const unsigned char *)&event_info, 
sizeof(event_info));
 
  376        uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
 
  377        m_events_hasher.Write((
const unsigned char*)&perfcounter, 
sizeof(perfcounter));
 
  387        LOCK(m_events_mutex);
 
  389        unsigned char events_hash[32];
 
  390        m_events_hasher.Finalize(events_hash);
 
  391        hasher.Write(events_hash, 32);
 
  394        m_events_hasher.Reset();
 
  395        m_events_hasher.Write(events_hash, 32);
 
  415        unsigned char buf[64];
 
  416        static_assert(
sizeof(buf) == 
CSHA512::OUTPUT_SIZE, 
"Buffer needs to have hasher's output size");
 
  420            ret = (m_strongly_seeded |= strong_seed);
 
  422            hasher.Write(m_state, 32);
 
  424            hasher.Write((
const unsigned char*)&m_counter, 
sizeof(m_counter));
 
  427            hasher.Finalize(buf);
 
  429            memcpy(m_state, buf + 32, 32);
 
  431            if (!always_use_real_rng && m_deterministic_prng.has_value()) [[unlikely]] {
 
  433                m_deterministic_prng->Keystream(std::as_writable_bytes(std::span{buf, num}));
 
  441            memcpy(
out, buf, num);
 
  450RNGState& GetRNGState() noexcept
 
  454    static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
 
  463void SeedTimestamp(
CSHA512& hasher) 
noexcept 
  465    int64_t perfcounter = GetPerformanceCounter();
 
  466    hasher.Write((
const unsigned char*)&perfcounter, 
sizeof(perfcounter));
 
  469void SeedFast(
CSHA512& hasher) 
noexcept 
  471    unsigned char buffer[32];
 
  474    const unsigned char* ptr = buffer;
 
  475    hasher.Write((
const unsigned char*)&ptr, 
sizeof(ptr));
 
  478    SeedHardwareFast(hasher);
 
  481    SeedTimestamp(hasher);
 
  484void SeedSlow(
CSHA512& hasher, RNGState& rng) 
noexcept 
  486    unsigned char buffer[32];
 
  493    hasher.Write(buffer, 
sizeof(buffer));
 
  496    rng.SeedEvents(hasher);
 
  502    SeedTimestamp(hasher);
 
  506void SeedStrengthen(
CSHA512& hasher, RNGState& rng, SteadyClock::duration dur) 
noexcept 
  510    unsigned char strengthen_seed[32];
 
  511    rng.MixExtract(strengthen_seed, 
sizeof(strengthen_seed), 
CSHA512(hasher), 
false, 
true);
 
  513    Strengthen(strengthen_seed, dur, hasher);
 
  516void SeedPeriodic(
CSHA512& hasher, RNGState& rng) 
noexcept 
  522    SeedTimestamp(hasher);
 
  525    rng.SeedEvents(hasher);
 
  528    auto old_size = hasher.Size();
 
  530    LogDebug(
BCLog::RAND, 
"Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);
 
  533    SeedStrengthen(hasher, rng, 10ms);
 
  536void SeedStartup(
CSHA512& hasher, RNGState& rng) 
noexcept 
  539    SeedHardwareSlow(hasher);
 
  542    SeedSlow(hasher, rng);
 
  545    auto old_size = hasher.Size();
 
  550    LogDebug(
BCLog::RAND, 
"Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
 
  553    SeedStrengthen(hasher, rng, 100ms);
 
  562void ProcRand(
unsigned char* 
out, 
int num, RNGLevel level, 
bool always_use_real_rng) 
noexcept 
  565    RNGState& rng = GetRNGState();
 
  575        SeedSlow(hasher, rng);
 
  577    case RNGLevel::PERIODIC:
 
  578        SeedPeriodic(hasher, rng);
 
  583    if (!rng.MixExtract(
out, num, std::move(hasher), 
false, always_use_real_rng)) {
 
  586        SeedStartup(startup_hasher, rng);
 
  587        rng.MixExtract(
out, num, std::move(startup_hasher), 
true, always_use_real_rng);
 
  597    GetRNGState().MakeDeterministic(seed);
 
  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);
 
  617void RandAddEvent(
const uint32_t event_info) 
noexcept { GetRNGState().AddEvent(event_info); }
 
  628    if (requires_seed) RandomSeed();
 
  629    rng.Keystream(output);
 
  637    requires_seed = 
false;
 
  643    uint64_t start = GetPerformanceCounter();
 
  649    static constexpr int MAX_TRIES{1024};
 
  650    uint8_t 
data[NUM_OS_RANDOM_BYTES];
 
  651    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; 
 
  656        memset(
data, 0, NUM_OS_RANDOM_BYTES);
 
  658        for (
int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
 
  659            overwritten[x] |= (
data[x] != 0);
 
  663        for (
int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
 
  664            if (overwritten[x]) {
 
  665                num_overwritten += 1;
 
  670    } 
while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
 
  671    if (num_overwritten != NUM_OS_RANDOM_BYTES) 
return false; 
 
  674    std::this_thread::sleep_for(std::chrono::milliseconds(1));
 
  675    uint64_t 
stop = GetPerformanceCounter();
 
  676    if (
stop == start) 
return false;
 
  680    to_add.
Write((
const unsigned char*)&start, 
sizeof(start));
 
  682    GetRNGState().MixExtract(
nullptr, 0, std::move(to_add), 
false, 
true);
 
  687static constexpr std::array<std::byte, ChaCha20::KEYLEN> 
ZERO_KEY{};
 
  699    ProcRand(
nullptr, 0, RNGLevel::FAST, 
true);
 
  701    ReportHardwareRand();
 
  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
 
void Finalize(unsigned char hash[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(...)