Skip to content

Commit b63be2c

Browse files
committed
Merge #10377: Use rdrand as entropy source on supported platforms
cb24c85 Use rdrand as entropy source on supported platforms (Pieter Wuille) Tree-SHA512: c42eaa01a14e6bc097c70b6bf8540d61854c2f76cb32be69c2a3c411a126f7b4bf4a4486e4493c4cc367cc689319abde0d4adb799d29a54fd3e81767ce0766fc
2 parents 1ad3d4e + cb24c85 commit b63be2c

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

src/init.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ bool AppInitSanityChecks()
11701170
// ********************************************************* Step 4: sanity checks
11711171

11721172
// Initialize elliptic curve code
1173+
RandomInit();
11731174
ECC_Start();
11741175
globalVerifyHandle.reset(new ECCVerifyHandle());
11751176

src/random.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,64 @@ static inline int64_t GetPerformanceCounter()
6565
#endif
6666
}
6767

68+
69+
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
70+
static std::atomic<bool> hwrand_initialized{false};
71+
static bool rdrand_supported = false;
72+
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
73+
static void RDRandInit()
74+
{
75+
//! When calling cpuid function #1, ecx register will have this set if RDRAND is available.
76+
// Avoid clobbering ebx, as that is used for PIC on x86.
77+
uint32_t eax, tmp, ecx, edx;
78+
__asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1));
79+
if (ecx & CPUID_F1_ECX_RDRAND) {
80+
LogPrintf("Using RdRand as entropy source\n");
81+
rdrand_supported = true;
82+
}
83+
hwrand_initialized.store(true);
84+
}
85+
#else
86+
static void RDRandInit() {}
87+
#endif
88+
89+
static bool GetHWRand(unsigned char* ent32) {
90+
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
91+
assert(hwrand_initialized.load(std::memory_order_relaxed));
92+
if (rdrand_supported) {
93+
uint8_t ok;
94+
// Not all assemblers support the rdrand instruction, write it in hex.
95+
#ifdef __i386__
96+
for (int iter = 0; iter < 4; ++iter) {
97+
uint32_t r1, r2;
98+
__asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax
99+
".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx
100+
"setc %2" :
101+
"=a"(r1), "=d"(r2), "=q"(ok) :: "cc");
102+
if (!ok) return false;
103+
WriteLE32(ent32 + 8 * iter, r1);
104+
WriteLE32(ent32 + 8 * iter + 4, r2);
105+
}
106+
#else
107+
uint64_t r1, r2, r3, r4;
108+
__asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax
109+
"0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx
110+
"0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx
111+
"0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx
112+
"setc %4" :
113+
"=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc");
114+
if (!ok) return false;
115+
WriteLE64(ent32, r1);
116+
WriteLE64(ent32 + 8, r2);
117+
WriteLE64(ent32 + 16, r3);
118+
WriteLE64(ent32 + 24, r4);
119+
#endif
120+
return true;
121+
}
122+
#endif
123+
return false;
124+
}
125+
68126
void RandAddSeed()
69127
{
70128
// Seed with CPU performance counter
@@ -255,6 +313,11 @@ void GetStrongRandBytes(unsigned char* out, int num)
255313
GetOSRand(buf);
256314
hasher.Write(buf, 32);
257315

316+
// Third source: HW RNG, if available.
317+
if (GetHWRand(buf)) {
318+
hasher.Write(buf, 32);
319+
}
320+
258321
// Combine with and update state
259322
{
260323
std::unique_lock<std::mutex> lock(cs_rng_state);
@@ -381,3 +444,8 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
381444
uint256 seed;
382445
rng.SetKey(seed.begin(), 32);
383446
}
447+
448+
void RandomInit()
449+
{
450+
RDRandInit();
451+
}

src/random.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,7 @@ void GetOSRand(unsigned char *ent32);
140140
*/
141141
bool Random_SanityCheck();
142142

143+
/** Initialize the RNG. */
144+
void RandomInit();
145+
143146
#endif // BITCOIN_RANDOM_H

src/test/test_bitcoin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ extern void noui_connect();
3333

3434
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
3535
{
36+
RandomInit();
3637
ECC_Start();
3738
SetupEnvironment();
3839
SetupNetworking();

0 commit comments

Comments
 (0)