30 #ifdef HAVE_SYS_GETRANDOM 31 #include <sys/syscall.h> 32 #include <linux/random.h> 34 #if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)) 37 #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) 38 #include <sys/random.h> 40 #ifdef HAVE_SYSCTL_ARND 42 #include <sys/sysctl.h> 47 LogPrintf(
"Failed to read randomness, aborting\n");
55 #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) 57 #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;
63 __asm__
volatile (
"rdtsc" :
"=a"(r1),
"=d"(r2));
64 return (r2 << 32) | r1;
72 static bool g_rdrand_supported =
false;
73 static bool g_rdseed_supported =
false;
74 static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
75 static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000;
77 static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND,
"Unexpected value for bit_RDRND");
80 static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED,
"Unexpected value for bit_RDSEED");
85 uint32_t eax, ebx, ecx, edx;
86 GetCPUID(1, 0, eax, ebx, ecx, edx);
87 if (ecx & CPUID_F1_ECX_RDRAND) {
88 g_rdrand_supported =
true;
90 GetCPUID(7, 0, eax, ebx, ecx, edx);
91 if (ebx & CPUID_F7_EBX_RDSEED) {
92 g_rdseed_supported =
true;
100 if (g_rdseed_supported) {
101 LogPrintf(
"Using RdSeed as additional entropy source\n");
103 if (g_rdrand_supported) {
104 LogPrintf(
"Using RdRand as an additional entropy source\n");
112 static uint64_t GetRdRand() noexcept
120 uint32_t r1 = 0, r2 = 0;
121 for (
int i = 0; i < 10; ++i) {
122 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
125 for (
int i = 0; i < 10; ++i) {
126 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r2),
"=q"(ok) ::
"cc");
129 return (((uint64_t)r2) << 32) | r1;
130 #elif defined(__x86_64__) || defined(__amd64__) 133 for (
int i = 0; i < 10; ++i) {
134 __asm__
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf0; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
139 #error "RdRand is only supported on x86 and x86_64" 147 static uint64_t GetRdSeed() noexcept
155 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
157 __asm__
volatile (
"pause");
160 __asm__
volatile (
".byte 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r2),
"=q"(ok) ::
"cc");
162 __asm__
volatile (
"pause");
164 return (((uint64_t)r2) << 32) | r1;
165 #elif defined(__x86_64__) || defined(__amd64__) 169 __asm__
volatile (
".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" :
"=a"(r1),
"=q"(ok) ::
"cc");
171 __asm__
volatile (
"pause");
175 #error "RdSeed is only supported on x86 and x86_64" 191 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) 192 if (g_rdrand_supported) {
193 uint64_t out = GetRdRand();
194 hasher.Write((
const unsigned char*)&out,
sizeof(out));
202 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) 205 if (g_rdseed_supported) {
206 for (
int i = 0; i < 4; ++i) {
207 uint64_t out = GetRdSeed();
208 hasher.Write((
const unsigned char*)&out,
sizeof(out));
214 if (g_rdrand_supported) {
215 for (
int i = 0; i < 4; ++i) {
217 for (
int j = 0; j < 1024; ++j) out ^= GetRdRand();
218 hasher.Write((
const unsigned char*)&out,
sizeof(out));
226 static void Strengthen(
const unsigned char (&seed)[32],
int microseconds,
CSHA512& hasher) noexcept
229 inner_hasher.
Write(seed,
sizeof(seed));
232 unsigned char buffer[64];
235 for (
int i = 0; i < 1000; ++i) {
237 inner_hasher.
Reset();
238 inner_hasher.
Write(buffer,
sizeof(buffer));
242 hasher.Write((
const unsigned char*)&perf,
sizeof(perf));
247 hasher.Write(buffer,
sizeof(buffer));
249 inner_hasher.
Reset();
259 int f = open(
"/dev/urandom", O_RDONLY);
280 HCRYPTPROV hProvider;
281 int ret = CryptAcquireContextW(&hProvider,
nullptr,
nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
289 CryptReleaseContext(hProvider, 0);
290 #elif defined(HAVE_SYS_GETRANDOM) 298 if (rv < 0 && errno == ENOSYS) {
308 #elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__) 320 #elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) 328 #elif defined(HAVE_SYSCTL_ARND) 332 static int name[2] = {CTL_KERN, KERN_ARND};
336 if (sysctl(name,
ARRAYLEN(name), ent32 + have, &len,
nullptr, 0) != 0) {
363 unsigned char m_state[32]
GUARDED_BY(m_mutex) = {0};
365 bool m_strongly_seeded
GUARDED_BY(m_mutex) =
false;
367 Mutex m_events_mutex;
380 void AddEvent(uint32_t event_info) noexcept
382 LOCK(m_events_mutex);
384 m_events_hasher.Write((
const unsigned char *)&event_info,
sizeof(event_info));
388 m_events_hasher.Write((
const unsigned char*)&perfcounter,
sizeof(perfcounter));
394 void SeedEvents(
CSHA512& hasher) noexcept
398 LOCK(m_events_mutex);
400 unsigned char events_hash[32];
401 m_events_hasher.Finalize(events_hash);
402 hasher.
Write(events_hash, 32);
405 m_events_hasher.
Reset();
406 m_events_hasher.
Write(events_hash, 32);
413 bool MixExtract(
unsigned char* out,
size_t num,
CSHA512&& hasher,
bool strong_seed) noexcept
416 unsigned char buf[64];
417 static_assert(
sizeof(buf) ==
CSHA512::OUTPUT_SIZE,
"Buffer needs to have hasher's output size");
421 ret = (m_strongly_seeded |= strong_seed);
423 hasher.
Write(m_state, 32);
425 hasher.
Write((
const unsigned char*)&m_counter,
sizeof(m_counter));
430 memcpy(m_state, buf + 32, 32);
444 RNGState& GetRNGState() noexcept
448 static std::vector<RNGState, secure_allocator<RNGState>> g_rng(1);
461 hasher.Write((
const unsigned char*)&perfcounter,
sizeof(perfcounter));
466 unsigned char buffer[32];
469 const unsigned char* ptr = buffer;
470 hasher.Write((
const unsigned char*)&ptr,
sizeof(ptr));
481 unsigned char buffer[32];
488 hasher.Write(buffer,
sizeof(buffer));
491 rng.SeedEvents(hasher);
504 unsigned char strengthen_seed[32];
505 rng.MixExtract(strengthen_seed,
sizeof(strengthen_seed),
CSHA512(hasher),
false);
507 Strengthen(strengthen_seed, microseconds, hasher);
519 rng.SeedEvents(hasher);
522 auto old_size = hasher.Size();
524 LogPrint(
BCLog::RAND,
"Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);
539 auto old_size = hasher.Size();
544 LogPrint(
BCLog::RAND,
"Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
559 RNGState& rng = GetRNGState();
577 if (!rng.MixExtract(out, num, std::move(hasher),
false)) {
581 rng.MixExtract(out, num, std::move(startup_hasher),
true);
588 void RandAddEvent(
const uint32_t event_info) noexcept { GetRNGState().AddEvent(event_info); }
612 rng.SetKey(seed.
begin(), 32);
613 requires_seed =
false;
618 if (bytebuf_size < 32) {
622 memcpy(ret.
begin(), bytebuf + 64 - bytebuf_size, 32);
629 if (requires_seed) RandomSeed();
630 std::vector<unsigned char> ret(len);
632 rng.Keystream(&ret[0], len);
639 rng.SetKey(seed.begin(), 32);
650 static const ssize_t MAX_TRIES = 1024;
660 overwritten[x] |= (data[x] != 0);
665 if (overwritten[x]) {
666 num_overwritten += 1;
675 std::this_thread::sleep_for(std::chrono::milliseconds(1));
677 if (stop == start)
return false;
681 to_add.
Write((
const unsigned char*)&start,
sizeof(start));
682 to_add.
Write((
const unsigned char*)&stop,
sizeof(stop));
683 GetRNGState().MixExtract(
nullptr, 0, std::move(to_add),
false);
690 if (!fDeterministic) {
694 rng.SetKey(seed.
begin(), 32);
701 std::copy(std::begin(from.bytebuf), std::end(from.bytebuf), std::begin(bytebuf));
702 bytebuf_size = from.bytebuf_size;
703 bitbuf = from.bitbuf;
704 bitbuf_size = from.bitbuf_size;
705 from.requires_seed =
true;
706 from.bytebuf_size = 0;
707 from.bitbuf_size = 0;
static const int NUM_OS_RANDOM_BYTES
void RandomInit()
Initialize global RNG state and log any CPU features that are used.
void GetOSRand(unsigned char *ent32)
Get 32 bytes of system entropy.
void RandAddEvent(const uint32_t event_info) noexcept
Gathers entropy from the low bits of the time at which events occur.
uint64_t GetRand(uint64_t nMax) noexcept
Generate a uniform random integer in the range [0..range).
const std::chrono::seconds now
#define LogPrint(category,...)
FastRandomContext & operator=(const FastRandomContext &)=delete
uint256 GetRandHash() noexcept
static void SeedHardwareSlow(CSHA512 &hasher) noexcept
Add 256 bits of entropy gathered from hardware to hasher.
#define ARRAYLEN(array)
Utilities for converting data from/to strings.
static void ProcRand(unsigned char *out, int num, RNGLevel level) noexcept
static void GetDevURandom(unsigned char *ent32)
Fallback: get 32 bytes of system entropy from /dev/urandom.
uint256 rand256() noexcept
generate a random uint256.
static void LogPrintf(const char *fmt, const Args &... args)
void RandAddPeriodic() noexcept
Gather entropy from various expensive sources, and feed them to the PRNG state.
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
FastRandomContext(bool fDeterministic=false) noexcept
static void Strengthen(const unsigned char(&seed)[32], int microseconds, CSHA512 &hasher) noexcept
Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. ...
static void SeedStrengthen(CSHA512 &hasher, RNGState &rng, int microseconds) noexcept
Extract entropy from rng, strengthen it, and feed it into hasher.
Called by RandAddPeriodic()
void Finalize(unsigned char hash[OUTPUT_SIZE])
static void SeedFast(CSHA512 &hasher) noexcept
static void RandFailure()
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
void GetStrongRandBytes(unsigned char *buf, int num) noexcept
Gather entropy from various sources, feed it into the internal PRNG, and generate random data using i...
static void SeedStartup(CSHA512 &hasher, RNGState &rng) noexcept
Automatically called by GetStrongRandBytes.
static constexpr size_t OUTPUT_SIZE
static void SeedPeriodic(CSHA512 &hasher, RNGState &rng) noexcept
int64_t GetTimeMicros()
Returns the system time (not mockable)
Automatically called by GetRandBytes.
static void ReportHardwareRand()
static void SeedSlow(CSHA512 &hasher, RNGState &rng) noexcept
void * memcpy(void *a, const void *b, size_t c)
CSHA512 & Write(const unsigned char *data, size_t len)
A hasher class for SHA-512.
bool g_mock_deterministic_tests
static void SeedHardwareFast(CSHA512 &hasher) noexcept
Add 64 bits of entropy gathered from hardware to hasher.
A hasher class for SHA-256.
void RandAddStaticEnv(CSHA512 &hasher)
Gather non-cryptographic environment data that does not change over time.
int GetRandInt(int nMax) noexcept
bool Random_SanityCheck()
Check that OS randomness is available and returning the requested number of bytes.
static void InitHardwareRand()
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
std::vector< unsigned char > randbytes(size_t len)
Generate random bytes.
static int64_t GetPerformanceCounter() noexcept
static void SeedTimestamp(CSHA512 &hasher) noexcept
void RandAddDynamicEnv(CSHA512 &hasher)
Gather non-cryptographic environment data that changes over time.