Skip to content

Commit fa2637a

Browse files
committed
Always require OS randomness when generating secret keys
1 parent a80de15 commit fa2637a

File tree

7 files changed

+59
-17
lines changed

7 files changed

+59
-17
lines changed

src/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,8 @@ endif
374374
bitcoin_cli_LDADD = \
375375
$(LIBBITCOIN_CLI) \
376376
$(LIBUNIVALUE) \
377-
$(LIBBITCOIN_UTIL)
377+
$(LIBBITCOIN_UTIL) \
378+
$(LIBBITCOIN_CRYPTO)
378379

379380
bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
380381
#

src/init.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,8 +1401,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
14011401
if (!strErrors.str().empty())
14021402
return InitError(strErrors.str());
14031403

1404-
RandAddSeedPerfmon();
1405-
14061404
//// debug print
14071405
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
14081406
LogPrintf("nBestHeight = %d\n", chainActive.Height());

src/key.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,8 @@ bool CKey::Check(const unsigned char *vch) {
124124
}
125125

126126
void CKey::MakeNewKey(bool fCompressedIn) {
127-
RandAddSeedPerfmon();
128127
do {
129-
GetRandBytes(vch, sizeof(vch));
128+
GetStrongRandBytes(vch, sizeof(vch));
130129
} while (!Check(vch));
131130
fValid = true;
132131
fCompressed = fCompressedIn;

src/main.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4547,7 +4547,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
45474547

45484548
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
45494549
{
4550-
RandAddSeedPerfmon();
45514550
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
45524551
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
45534552
{

src/random.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
#include "random.h"
77

8+
#include "crypto/sha512.h"
89
#include "support/cleanse.h"
910
#ifdef WIN32
1011
#include "compat.h" // for Windows API
12+
#include <wincrypt.h>
1113
#endif
1214
#include "serialize.h" // for begin_ptr(vec)
1315
#include "util.h" // for LogPrint()
@@ -43,7 +45,7 @@ void RandAddSeed()
4345
memory_cleanse((void*)&nCounter, sizeof(nCounter));
4446
}
4547

46-
void RandAddSeedPerfmon()
48+
static void RandAddSeedPerfmon()
4749
{
4850
RandAddSeed();
4951

@@ -83,6 +85,29 @@ void RandAddSeedPerfmon()
8385
#endif
8486
}
8587

88+
/** Get 32 bytes of system entropy. */
89+
static void GetOSRand(unsigned char *ent32)
90+
{
91+
#ifdef WIN32
92+
HCRYPTPROV hProvider;
93+
int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
94+
assert(ret);
95+
ret = CryptGenRandom(hProvider, 32, ent32);
96+
assert(ret);
97+
CryptReleaseContext(hProvider, 0);
98+
#else
99+
int f = open("/dev/urandom", O_RDONLY);
100+
assert(f != -1);
101+
int have = 0;
102+
do {
103+
ssize_t n = read(f, ent32 + have, 32 - have);
104+
assert(n > 0 && n <= 32 - have);
105+
have += n;
106+
} while (have < 32);
107+
close(f);
108+
#endif
109+
}
110+
86111
void GetRandBytes(unsigned char* buf, int num)
87112
{
88113
if (RAND_bytes(buf, num) != 1) {
@@ -91,6 +116,27 @@ void GetRandBytes(unsigned char* buf, int num)
91116
}
92117
}
93118

119+
void GetStrongRandBytes(unsigned char* out, int num)
120+
{
121+
assert(num <= 32);
122+
CSHA512 hasher;
123+
unsigned char buf[64];
124+
125+
// First source: OpenSSL's RNG
126+
RandAddSeedPerfmon();
127+
GetRandBytes(buf, 32);
128+
hasher.Write(buf, 32);
129+
130+
// Second source: OS RNG
131+
GetOSRand(buf);
132+
hasher.Write(buf, 32);
133+
134+
// Produce output
135+
hasher.Finalize(buf);
136+
memcpy(out, buf, num);
137+
memory_cleanse(buf, 64);
138+
}
139+
94140
uint64_t GetRand(uint64_t nMax)
95141
{
96142
if (nMax == 0)

src/random.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010

1111
#include <stdint.h>
1212

13-
/**
14-
* Seed OpenSSL PRNG with additional entropy data
15-
*/
13+
/* Seed OpenSSL PRNG with additional entropy data */
1614
void RandAddSeed();
17-
void RandAddSeedPerfmon();
1815

1916
/**
2017
* Functions to gather random data via the OpenSSL PRNG
@@ -24,6 +21,12 @@ uint64_t GetRand(uint64_t nMax);
2421
int GetRandInt(int nMax);
2522
uint256 GetRandHash();
2623

24+
/**
25+
* Function to gather random data from multiple sources, failing whenever any
26+
* of those source fail to provide a result.
27+
*/
28+
void GetStrongRandBytes(unsigned char* buf, int num);
29+
2730
/**
2831
* Seed insecure_rand using the random pool.
2932
* @param Deterministic Use a deterministic seed

src/wallet/wallet.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -509,16 +509,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
509509
return false;
510510

511511
CKeyingMaterial vMasterKey;
512-
RandAddSeedPerfmon();
513512

514513
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
515-
GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
514+
GetStrongRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
516515

517516
CMasterKey kMasterKey;
518-
RandAddSeedPerfmon();
519517

520518
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
521-
GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
519+
GetStrongRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
522520

523521
CCrypter crypter;
524522
int64_t nStartTime = GetTimeMillis();
@@ -3147,8 +3145,6 @@ bool CWallet::InitLoadWallet()
31473145
if (fFirstRun)
31483146
{
31493147
// Create new keyUser and set as default key
3150-
RandAddSeedPerfmon();
3151-
31523148
CPubKey newDefaultKey;
31533149
if (walletInstance->GetKeyFromPool(newDefaultKey)) {
31543150
walletInstance->SetDefaultKey(newDefaultKey);

0 commit comments

Comments
 (0)