Merge #7891: Always require OS randomness when generating secret keys
628cf14 Don't use assert for catching randomness failures (Pieter Wuille) fa2637a Always require OS randomness when generating secret keys (Pieter Wuille)
This commit is contained in:
parent
cee571bda4
commit
43cbeb7fa5
@ -469,7 +469,8 @@ endif
|
|||||||
dash_cli_LDADD = \
|
dash_cli_LDADD = \
|
||||||
$(LIBBITCOIN_CLI) \
|
$(LIBBITCOIN_CLI) \
|
||||||
$(LIBUNIVALUE) \
|
$(LIBUNIVALUE) \
|
||||||
$(LIBBITCOIN_UTIL)
|
$(LIBBITCOIN_UTIL) \
|
||||||
|
$(LIBBITCOIN_CRYPTO)
|
||||||
dash_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
|
dash_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@ -1781,8 +1781,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
if (!strErrors.str().empty())
|
if (!strErrors.str().empty())
|
||||||
return InitError(strErrors.str());
|
return InitError(strErrors.str());
|
||||||
|
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
//// debug print
|
//// debug print
|
||||||
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
|
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
|
||||||
LogPrintf("chainActive.Height() = %d\n", chainActive.Height());
|
LogPrintf("chainActive.Height() = %d\n", chainActive.Height());
|
||||||
|
@ -232,8 +232,7 @@ SecureString CKeePassIntegrator::generateRandomKey(size_t nSize)
|
|||||||
SecureString sKey;
|
SecureString sKey;
|
||||||
sKey.resize(nSize);
|
sKey.resize(nSize);
|
||||||
|
|
||||||
RandAddSeedPerfmon();
|
GetStrongRandBytes((unsigned char *) &sKey[0], nSize);
|
||||||
GetRandBytes((unsigned char *) &sKey[0], nSize);
|
|
||||||
|
|
||||||
return sKey;
|
return sKey;
|
||||||
}
|
}
|
||||||
|
@ -124,9 +124,8 @@ bool CKey::Check(const unsigned char *vch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CKey::MakeNewKey(bool fCompressedIn) {
|
void CKey::MakeNewKey(bool fCompressedIn) {
|
||||||
RandAddSeedPerfmon();
|
|
||||||
do {
|
do {
|
||||||
GetRandBytes(vch, sizeof(vch));
|
GetStrongRandBytes(vch, sizeof(vch));
|
||||||
} while (!Check(vch));
|
} while (!Check(vch));
|
||||||
fValid = true;
|
fValid = true;
|
||||||
fCompressed = fCompressedIn;
|
fCompressed = fCompressedIn;
|
||||||
|
@ -1076,8 +1076,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|||||||
|
|
||||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, std::atomic<bool>& interruptMsgProc)
|
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, std::atomic<bool>& interruptMsgProc)
|
||||||
{
|
{
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
|
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
|
||||||
|
|
||||||
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
|
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
|
||||||
|
@ -5,14 +5,17 @@
|
|||||||
|
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
|
||||||
|
#include "crypto/sha512.h"
|
||||||
#include "support/cleanse.h"
|
#include "support/cleanse.h"
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include "compat.h" // for Windows API
|
#include "compat.h" // for Windows API
|
||||||
|
#include <wincrypt.h>
|
||||||
#endif
|
#endif
|
||||||
#include "serialize.h" // for begin_ptr(vec)
|
#include "serialize.h" // for begin_ptr(vec)
|
||||||
#include "util.h" // for LogPrint()
|
#include "util.h" // for LogPrint()
|
||||||
#include "utilstrencodings.h" // for GetTime()
|
#include "utilstrencodings.h" // for GetTime()
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
@ -22,6 +25,12 @@
|
|||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
|
static void RandFailure()
|
||||||
|
{
|
||||||
|
LogPrintf("Failed to read randomness, aborting\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
static inline int64_t GetPerformanceCounter()
|
static inline int64_t GetPerformanceCounter()
|
||||||
{
|
{
|
||||||
int64_t nCounter = 0;
|
int64_t nCounter = 0;
|
||||||
@ -43,7 +52,7 @@ void RandAddSeed()
|
|||||||
memory_cleanse((void*)&nCounter, sizeof(nCounter));
|
memory_cleanse((void*)&nCounter, sizeof(nCounter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandAddSeedPerfmon()
|
static void RandAddSeedPerfmon()
|
||||||
{
|
{
|
||||||
RandAddSeed();
|
RandAddSeed();
|
||||||
|
|
||||||
@ -83,14 +92,65 @@ void RandAddSeedPerfmon()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get 32 bytes of system entropy. */
|
||||||
|
static void GetOSRand(unsigned char *ent32)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
HCRYPTPROV hProvider;
|
||||||
|
int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
|
||||||
|
if (!ret) {
|
||||||
|
RandFailure();
|
||||||
|
}
|
||||||
|
ret = CryptGenRandom(hProvider, 32, ent32);
|
||||||
|
if (!ret) {
|
||||||
|
RandFailure();
|
||||||
|
}
|
||||||
|
CryptReleaseContext(hProvider, 0);
|
||||||
|
#else
|
||||||
|
int f = open("/dev/urandom", O_RDONLY);
|
||||||
|
if (f == -1) {
|
||||||
|
RandFailure();
|
||||||
|
}
|
||||||
|
int have = 0;
|
||||||
|
do {
|
||||||
|
ssize_t n = read(f, ent32 + have, 32 - have);
|
||||||
|
if (n <= 0 || n + have > 32) {
|
||||||
|
RandFailure();
|
||||||
|
}
|
||||||
|
have += n;
|
||||||
|
} while (have < 32);
|
||||||
|
close(f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GetRandBytes(unsigned char* buf, int num)
|
void GetRandBytes(unsigned char* buf, int num)
|
||||||
{
|
{
|
||||||
if (RAND_bytes(buf, num) != 1) {
|
if (RAND_bytes(buf, num) != 1) {
|
||||||
LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
|
RandFailure();
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetStrongRandBytes(unsigned char* out, int num)
|
||||||
|
{
|
||||||
|
assert(num <= 32);
|
||||||
|
CSHA512 hasher;
|
||||||
|
unsigned char buf[64];
|
||||||
|
|
||||||
|
// First source: OpenSSL's RNG
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
GetRandBytes(buf, 32);
|
||||||
|
hasher.Write(buf, 32);
|
||||||
|
|
||||||
|
// Second source: OS RNG
|
||||||
|
GetOSRand(buf);
|
||||||
|
hasher.Write(buf, 32);
|
||||||
|
|
||||||
|
// Produce output
|
||||||
|
hasher.Finalize(buf);
|
||||||
|
memcpy(out, buf, num);
|
||||||
|
memory_cleanse(buf, 64);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t GetRand(uint64_t nMax)
|
uint64_t GetRand(uint64_t nMax)
|
||||||
{
|
{
|
||||||
if (nMax == 0)
|
if (nMax == 0)
|
||||||
|
11
src/random.h
11
src/random.h
@ -10,11 +10,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/**
|
/* Seed OpenSSL PRNG with additional entropy data */
|
||||||
* Seed OpenSSL PRNG with additional entropy data
|
|
||||||
*/
|
|
||||||
void RandAddSeed();
|
void RandAddSeed();
|
||||||
void RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions to gather random data via the OpenSSL PRNG
|
* Functions to gather random data via the OpenSSL PRNG
|
||||||
@ -24,6 +21,12 @@ uint64_t GetRand(uint64_t nMax);
|
|||||||
int GetRandInt(int nMax);
|
int GetRandInt(int nMax);
|
||||||
uint256 GetRandHash();
|
uint256 GetRandHash();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to gather random data from multiple sources, failing whenever any
|
||||||
|
* of those source fail to provide a result.
|
||||||
|
*/
|
||||||
|
void GetStrongRandBytes(unsigned char* buf, int num);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seed insecure_rand using the random pool.
|
* Seed insecure_rand using the random pool.
|
||||||
* @param Deterministic Use a deterministic seed
|
* @param Deterministic Use a deterministic seed
|
||||||
|
@ -738,16 +738,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
CKeyingMaterial vMasterKey;
|
CKeyingMaterial vMasterKey;
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
|
||||||
GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
GetStrongRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
|
||||||
|
|
||||||
CMasterKey kMasterKey;
|
CMasterKey kMasterKey;
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
|
||||||
GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
GetStrongRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
|
||||||
|
|
||||||
CCrypter crypter;
|
CCrypter crypter;
|
||||||
int64_t nStartTime = GetTimeMillis();
|
int64_t nStartTime = GetTimeMillis();
|
||||||
@ -4549,8 +4547,6 @@ bool CWallet::InitLoadWallet()
|
|||||||
if (fFirstRun)
|
if (fFirstRun)
|
||||||
{
|
{
|
||||||
// Create new keyUser and set as default key
|
// Create new keyUser and set as default key
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) {
|
if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) {
|
||||||
if (GetArg("-mnemonicpassphrase", "").size() > 256) {
|
if (GetArg("-mnemonicpassphrase", "").size() > 256) {
|
||||||
return InitError(_("Mnemonic passphrase is too long, must be at most 256 characters"));
|
return InitError(_("Mnemonic passphrase is too long, must be at most 256 characters"));
|
||||||
|
Loading…
Reference in New Issue
Block a user