Skip to content

Commit

Permalink
Use rdrand as entropy source on supported platforms
Browse files Browse the repository at this point in the history
Includes squashed commits:
5155d11
a9e82f6
674848f

Cherry-picked from: cb24c85
  • Loading branch information
sipa authored and xanimo committed Jun 18, 2024
1 parent 23bc7a0 commit 60bd389
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/bench/bench_bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
#include "bench.h" // for BenchRunner
#include "key.h" // for ECC_Start, ECC_Stop
#include "util.h" // for SetupEnvironment, fPrintToDebugLog
#include "random.h"

int
main(int argc, char** argv)
{
RandomInit();
ECC_Start();
SetupEnvironment();
fPrintToDebugLog = false; // don't want to write to debug.log file
Expand Down
1 change: 1 addition & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,7 @@ bool AppInitSanityChecks()
// ********************************************************* Step 4: sanity checks

// Initialize elliptic curve code
RandomInit();
ECC_Start();
globalVerifyHandle.reset(new ECCVerifyHandle());

Expand Down
69 changes: 69 additions & 0 deletions src/random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#include <sys/sysctl.h>
#endif

#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
#include <cpuid.h>
#endif

#include <openssl/err.h>
#include <openssl/rand.h>

Expand Down Expand Up @@ -66,6 +70,61 @@ static inline int64_t GetPerformanceCounter()
#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()
{
uint32_t eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & CPUID_F1_ECX_RDRAND)) {
LogPrintf("Using RdRand as an additional 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()
{
// Seed with CPU performance counter
Expand Down Expand Up @@ -228,6 +287,11 @@ void GetStrongRandBytes(unsigned char* out, int num)
GetOSRand(buf);
hasher.Write(buf, 32);

// Third source: HW RNG, if available.
if (GetHWRand(buf)) {
hasher.Write(buf, 32);
}

// Produce output
hasher.Finalize(buf);
memcpy(out, buf, num);
Expand Down Expand Up @@ -345,3 +409,8 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete
uint256 seed;
rng.SetKey(seed.begin(), 32);
}

void RandomInit()
{
RDRandInit();
}
3 changes: 3 additions & 0 deletions src/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,7 @@ void GetOSRand(unsigned char *ent32);
*/
bool Random_SanityCheck();

/** Initialize the RNG. */
void RandomInit();

#endif // BITCOIN_RANDOM_H
1 change: 1 addition & 0 deletions src/test/test_bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static const int COINBASE_MATURITY = 60*4; // 4 hours of blocks

BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
{
RandomInit();
ECC_Start();
SetupEnvironment();
SetupNetworking();
Expand Down

0 comments on commit 60bd389

Please sign in to comment.