Skip to content

Commit 60bd389

Browse files
sipaxanimo
authored andcommitted
Use rdrand as entropy source on supported platforms
Includes squashed commits: 5155d11 a9e82f6 674848f Cherry-picked from: cb24c85
1 parent 23bc7a0 commit 60bd389

File tree

5 files changed

+76
-0
lines changed

5 files changed

+76
-0
lines changed

src/bench/bench_bitcoin.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
#include "bench.h" // for BenchRunner
66
#include "key.h" // for ECC_Start, ECC_Stop
77
#include "util.h" // for SetupEnvironment, fPrintToDebugLog
8+
#include "random.h"
89

910
int
1011
main(int argc, char** argv)
1112
{
13+
RandomInit();
1214
ECC_Start();
1315
SetupEnvironment();
1416
fPrintToDebugLog = false; // don't want to write to debug.log file

src/init.cpp

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

11901190
// Initialize elliptic curve code
1191+
RandomInit();
11911192
ECC_Start();
11921193
globalVerifyHandle.reset(new ECCVerifyHandle());
11931194

src/random.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
#include <sys/sysctl.h>
3838
#endif
3939

40+
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
41+
#include <cpuid.h>
42+
#endif
43+
4044
#include <openssl/err.h>
4145
#include <openssl/rand.h>
4246

@@ -66,6 +70,61 @@ static inline int64_t GetPerformanceCounter()
6670
#endif
6771
}
6872

73+
74+
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
75+
static std::atomic<bool> hwrand_initialized{false};
76+
static bool rdrand_supported = false;
77+
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
78+
static void RDRandInit()
79+
{
80+
uint32_t eax, ebx, ecx, edx;
81+
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) {
82+
LogPrintf("Using RdRand as an additional entropy source\n");
83+
rdrand_supported = true;
84+
}
85+
hwrand_initialized.store(true);
86+
}
87+
#else
88+
static void RDRandInit() {}
89+
#endif
90+
91+
static bool GetHWRand(unsigned char* ent32) {
92+
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
93+
assert(hwrand_initialized.load(std::memory_order_relaxed));
94+
if (rdrand_supported) {
95+
uint8_t ok;
96+
// Not all assemblers support the rdrand instruction, write it in hex.
97+
#ifdef __i386__
98+
for (int iter = 0; iter < 4; ++iter) {
99+
uint32_t r1, r2;
100+
__asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax
101+
".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx
102+
"setc %2" :
103+
"=a"(r1), "=d"(r2), "=q"(ok) :: "cc");
104+
if (!ok) return false;
105+
WriteLE32(ent32 + 8 * iter, r1);
106+
WriteLE32(ent32 + 8 * iter + 4, r2);
107+
}
108+
#else
109+
uint64_t r1, r2, r3, r4;
110+
__asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax
111+
"0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx
112+
"0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx
113+
"0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx
114+
"setc %4" :
115+
"=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc");
116+
if (!ok) return false;
117+
WriteLE64(ent32, r1);
118+
WriteLE64(ent32 + 8, r2);
119+
WriteLE64(ent32 + 16, r3);
120+
WriteLE64(ent32 + 24, r4);
121+
#endif
122+
return true;
123+
}
124+
#endif
125+
return false;
126+
}
127+
69128
void RandAddSeed()
70129
{
71130
// Seed with CPU performance counter
@@ -228,6 +287,11 @@ void GetStrongRandBytes(unsigned char* out, int num)
228287
GetOSRand(buf);
229288
hasher.Write(buf, 32);
230289

290+
// Third source: HW RNG, if available.
291+
if (GetHWRand(buf)) {
292+
hasher.Write(buf, 32);
293+
}
294+
231295
// Produce output
232296
hasher.Finalize(buf);
233297
memcpy(out, buf, num);
@@ -345,3 +409,8 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
345409
uint256 seed;
346410
rng.SetKey(seed.begin(), 32);
347411
}
412+
413+
void RandomInit()
414+
{
415+
RDRandInit();
416+
}

src/random.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,7 @@ void GetOSRand(unsigned char *ent32);
133133
*/
134134
bool Random_SanityCheck();
135135

136+
/** Initialize the RNG. */
137+
void RandomInit();
138+
136139
#endif // BITCOIN_RANDOM_H

src/test/test_bitcoin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static const int COINBASE_MATURITY = 60*4; // 4 hours of blocks
4343

4444
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
4545
{
46+
RandomInit();
4647
ECC_Start();
4748
SetupEnvironment();
4849
SetupNetworking();

0 commit comments

Comments
 (0)