Merge #10377: Use rdrand as entropy source on supported platforms
cb24c85
Use rdrand as entropy source on supported platforms (Pieter Wuille)
Tree-SHA512: c42eaa01a14e6bc097c70b6bf8540d61854c2f76cb32be69c2a3c411a126f7b4bf4a4486e4493c4cc367cc689319abde0d4adb799d29a54fd3e81767ce0766fc
This commit is contained in:
commit
b63be2c685
4 changed files with 73 additions and 0 deletions
|
@ -1170,6 +1170,7 @@ bool AppInitSanityChecks()
|
||||||
// ********************************************************* Step 4: sanity checks
|
// ********************************************************* Step 4: sanity checks
|
||||||
|
|
||||||
// Initialize elliptic curve code
|
// Initialize elliptic curve code
|
||||||
|
RandomInit();
|
||||||
ECC_Start();
|
ECC_Start();
|
||||||
globalVerifyHandle.reset(new ECCVerifyHandle());
|
globalVerifyHandle.reset(new ECCVerifyHandle());
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,64 @@ static inline int64_t GetPerformanceCounter()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
|
||||||
|
static std::atomic<bool> hwrand_initialized{false};
|
||||||
|
static bool rdrand_supported = false;
|
||||||
|
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000;
|
||||||
|
static void RDRandInit()
|
||||||
|
{
|
||||||
|
//! When calling cpuid function #1, ecx register will have this set if RDRAND is available.
|
||||||
|
// Avoid clobbering ebx, as that is used for PIC on x86.
|
||||||
|
uint32_t eax, tmp, ecx, edx;
|
||||||
|
__asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1));
|
||||||
|
if (ecx & CPUID_F1_ECX_RDRAND) {
|
||||||
|
LogPrintf("Using RdRand as entropy source\n");
|
||||||
|
rdrand_supported = true;
|
||||||
|
}
|
||||||
|
hwrand_initialized.store(true);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void RDRandInit() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool GetHWRand(unsigned char* ent32) {
|
||||||
|
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
|
||||||
|
assert(hwrand_initialized.load(std::memory_order_relaxed));
|
||||||
|
if (rdrand_supported) {
|
||||||
|
uint8_t ok;
|
||||||
|
// Not all assemblers support the rdrand instruction, write it in hex.
|
||||||
|
#ifdef __i386__
|
||||||
|
for (int iter = 0; iter < 4; ++iter) {
|
||||||
|
uint32_t r1, r2;
|
||||||
|
__asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax
|
||||||
|
".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx
|
||||||
|
"setc %2" :
|
||||||
|
"=a"(r1), "=d"(r2), "=q"(ok) :: "cc");
|
||||||
|
if (!ok) return false;
|
||||||
|
WriteLE32(ent32 + 8 * iter, r1);
|
||||||
|
WriteLE32(ent32 + 8 * iter + 4, r2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint64_t r1, r2, r3, r4;
|
||||||
|
__asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax
|
||||||
|
"0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx
|
||||||
|
"0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx
|
||||||
|
"0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx
|
||||||
|
"setc %4" :
|
||||||
|
"=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc");
|
||||||
|
if (!ok) return false;
|
||||||
|
WriteLE64(ent32, r1);
|
||||||
|
WriteLE64(ent32 + 8, r2);
|
||||||
|
WriteLE64(ent32 + 16, r3);
|
||||||
|
WriteLE64(ent32 + 24, r4);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void RandAddSeed()
|
void RandAddSeed()
|
||||||
{
|
{
|
||||||
// Seed with CPU performance counter
|
// Seed with CPU performance counter
|
||||||
|
@ -255,6 +313,11 @@ void GetStrongRandBytes(unsigned char* out, int num)
|
||||||
GetOSRand(buf);
|
GetOSRand(buf);
|
||||||
hasher.Write(buf, 32);
|
hasher.Write(buf, 32);
|
||||||
|
|
||||||
|
// Third source: HW RNG, if available.
|
||||||
|
if (GetHWRand(buf)) {
|
||||||
|
hasher.Write(buf, 32);
|
||||||
|
}
|
||||||
|
|
||||||
// Combine with and update state
|
// Combine with and update state
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(cs_rng_state);
|
std::unique_lock<std::mutex> lock(cs_rng_state);
|
||||||
|
@ -381,3 +444,8 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
|
||||||
uint256 seed;
|
uint256 seed;
|
||||||
rng.SetKey(seed.begin(), 32);
|
rng.SetKey(seed.begin(), 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RandomInit()
|
||||||
|
{
|
||||||
|
RDRandInit();
|
||||||
|
}
|
||||||
|
|
|
@ -140,4 +140,7 @@ void GetOSRand(unsigned char *ent32);
|
||||||
*/
|
*/
|
||||||
bool Random_SanityCheck();
|
bool Random_SanityCheck();
|
||||||
|
|
||||||
|
/** Initialize the RNG. */
|
||||||
|
void RandomInit();
|
||||||
|
|
||||||
#endif // BITCOIN_RANDOM_H
|
#endif // BITCOIN_RANDOM_H
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern void noui_connect();
|
||||||
|
|
||||||
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
||||||
{
|
{
|
||||||
|
RandomInit();
|
||||||
ECC_Start();
|
ECC_Start();
|
||||||
SetupEnvironment();
|
SetupEnvironment();
|
||||||
SetupNetworking();
|
SetupNetworking();
|
||||||
|
|
Loading…
Reference in a new issue