Auto merge of #1706 - paragonie:master, r=bitcartel

Use libsodium's CSPRNG instead of OpenSSL's

Closes #1632.
This commit is contained in:
zkbot 2017-02-05 18:26:11 +00:00
commit 499e34fc64
9 changed files with 6 additions and 95 deletions

View File

@ -15,8 +15,8 @@ zcash_GenerateParams_LDADD = \
zcash_CreateJoinSplit_SOURCES = zcash/CreateJoinSplit.cpp zcash_CreateJoinSplit_SOURCES = zcash/CreateJoinSplit.cpp
zcash_CreateJoinSplit_LDADD = \ zcash_CreateJoinSplit_LDADD = \
$(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_COMMON) \
$(LIBZCASH) \
$(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_CRYPTO) \
$(LIBZCASH) \
$(BOOST_LIBS) \ $(BOOST_LIBS) \
$(LIBZCASH_LIBS) $(LIBZCASH_LIBS)

View File

@ -1363,8 +1363,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (fFirstRun) if (fFirstRun)
{ {
// Create new keyUser and set as default key // Create new keyUser and set as default key
RandAddSeedPerfmon();
CPubKey newDefaultKey; CPubKey newDefaultKey;
if (pwalletMain->GetKeyFromPool(newDefaultKey)) { if (pwalletMain->GetKeyFromPool(newDefaultKey)) {
pwalletMain->SetDefaultKey(newDefaultKey); pwalletMain->SetDefaultKey(newDefaultKey);
@ -1481,8 +1479,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("nBestHeight = %d\n", chainActive.Height()); LogPrintf("nBestHeight = %d\n", chainActive.Height());

View File

@ -21,7 +21,6 @@ bool CKey::Check(const unsigned char *vch) {
} }
void CKey::MakeNewKey(bool fCompressedIn) { void CKey::MakeNewKey(bool fCompressedIn) {
RandAddSeedPerfmon();
do { do {
GetRandBytes(vch, sizeof(vch)); GetRandBytes(vch, sizeof(vch));
} while (!Check(vch)); } while (!Check(vch));

View File

@ -4303,7 +4303,6 @@ void static ProcessGetData(CNode* pfrom)
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
{ {
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
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)
{ {

View File

@ -12,8 +12,6 @@
#include <QDebug> #include <QDebug>
#include <openssl/rand.h>
// If we don't want a message to be processed by Qt, return true and set result to // If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false. // the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
@ -22,16 +20,6 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM
MSG *pMsg = static_cast<MSG *>(pMessage); MSG *pMsg = static_cast<MSG *>(pMessage);
// Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions)
if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
// Warn only once as this is performance-critical
static bool warned = false;
if (!warned) {
LogPrint("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
warned = true;
}
}
switch(pMsg->message) switch(pMsg->message)
{ {
case WM_QUERYENDSESSION: case WM_QUERYENDSESSION:

View File

@ -19,8 +19,7 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#include <openssl/err.h> #include "sodium.h"
#include <openssl/rand.h>
static inline int64_t GetPerformanceCounter() static inline int64_t GetPerformanceCounter()
{ {
@ -35,60 +34,9 @@ static inline int64_t GetPerformanceCounter()
return nCounter; return nCounter;
} }
void RandAddSeed() void GetRandBytes(unsigned char* buf, size_t num)
{ {
// Seed with CPU performance counter randombytes_buf(buf, num);
int64_t nCounter = GetPerformanceCounter();
RAND_add(&nCounter, sizeof(nCounter), 1.5);
memory_cleanse((void*)&nCounter, sizeof(nCounter));
}
void RandAddSeedPerfmon()
{
RandAddSeed();
#ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
// This can take up to 2 seconds, so only do it every 10 minutes
static int64_t nLastPerfmon;
if (GetTime() < nLastPerfmon + 10 * 60)
return;
nLastPerfmon = GetTime();
std::vector<unsigned char> vData(250000, 0);
long ret = 0;
unsigned long nSize = 0;
const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
while (true) {
nSize = vData.size();
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
break;
vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
}
RegCloseKey(HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS) {
RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
memory_cleanse(begin_ptr(vData), nSize);
LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
} else {
static bool warned = false; // Warn only once
if (!warned) {
LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
warned = true;
}
}
#endif
}
void GetRandBytes(unsigned char* buf, int num)
{
if (RAND_bytes(buf, num) != 1) {
LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
assert(false);
}
} }
uint64_t GetRand(uint64_t nMax) uint64_t GetRand(uint64_t nMax)

View File

@ -12,15 +12,9 @@
#include <stdint.h> #include <stdint.h>
/** /**
* Seed OpenSSL PRNG with additional entropy data * Functions to gather random data via the libsodium CSPRNG
*/ */
void RandAddSeed(); void GetRandBytes(unsigned char* buf, size_t num);
void RandAddSeedPerfmon();
/**
* Functions to gather random data via the OpenSSL PRNG
*/
void GetRandBytes(unsigned char* buf, int num);
uint64_t GetRand(uint64_t nMax); uint64_t GetRand(uint64_t nMax);
int GetRandInt(int nMax); int GetRandInt(int nMax);
uint256 GetRandHash(); uint256 GetRandHash();

View File

@ -82,7 +82,6 @@
#include <boost/program_options/parsers.hpp> #include <boost/program_options/parsers.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/conf.h> #include <openssl/conf.h>
// Work around clang compilation problem in Boost 1.46: // Work around clang compilation problem in Boost 1.46:
@ -142,19 +141,9 @@ public:
// or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be
// that the config appears to have been loaded and there are no modules/engines available. // that the config appears to have been loaded and there are no modules/engines available.
OPENSSL_no_config(); OPENSSL_no_config();
#ifdef WIN32
// Seed OpenSSL PRNG with current contents of the screen
RAND_screen();
#endif
// Seed OpenSSL PRNG with performance counter
RandAddSeed();
} }
~CInit() ~CInit()
{ {
// Securely erase the memory used by the PRNG
RAND_cleanup();
// Shutdown OpenSSL library multithreading support // Shutdown OpenSSL library multithreading support
CRYPTO_set_locking_callback(NULL); CRYPTO_set_locking_callback(NULL);
for (int i = 0; i < CRYPTO_num_locks(); i++) for (int i = 0; i < CRYPTO_num_locks(); i++)

View File

@ -814,13 +814,11 @@ 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); GetRandBytes(&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); GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);