From 6df1dc542cdac14e35e5d563bd0c4fa45614ec63 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Thu, 15 Jul 2021 19:09:18 -0400 Subject: [PATCH] Remove deprecated random number generator functions This commit changes CInit to check for proper RNG seeding and use RAND_poll() if necessary. It removes RandAddSeed() RandAddSeedPerfmon() and also the use of RAND_screen. --- src/init.cpp | 4 --- src/main.cpp | 2 -- src/qt/winshutdownmonitor.cpp | 10 ------ src/util.cpp | 60 +++++++++++------------------------ src/util.h | 3 -- src/wallet/wallet.cpp | 3 -- 6 files changed, 19 insertions(+), 63 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bbd24026bf..40d489a56b 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -1245,8 +1245,6 @@ bool AppInit2(ThreadHandlerPtr threads) if (fFirstRun) { // Create new keyUser and set as default key - RandAddSeedPerfmon(); - CPubKey newDefaultKey; if (pwalletMain->GetKeyFromPool(newDefaultKey, false)) { pwalletMain->SetDefaultKey(newDefaultKey); @@ -1358,8 +1356,6 @@ bool AppInit2(ThreadHandlerPtr threads) if (!CheckDiskSpace()) return false; - RandAddSeedPerfmon(); - if (!GRC::Initialize(threads, pindexBest)) { return false; } diff --git a/src/main.cpp b/src/main.cpp index 579b984676..bfd15d4ef4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2950,8 +2950,6 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv) bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { - RandAddSeedPerfmon(); - LogPrint(BCLog::LogFlags::NOISY, "received: %s from %s (%" PRIszu " bytes)", strCommand, pfrom->addrName, vRecv.size()); if (strCommand == "aries") diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index aa8453208f..d242cfd603 100755 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -22,16 +22,6 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM MSG *pMsg = static_cast(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) { - LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__); - warned = true; - } - } - switch(pMsg->message) { case WM_QUERYENDSESSION: diff --git a/src/util.cpp b/src/util.cpp index ec2dc434f9..e5939c8052 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -85,14 +85,27 @@ class CInit ppmutexOpenSSL[i] = new CCriticalSection(); CRYPTO_set_locking_callback(locking_callback); -#ifdef WIN32 - // Seed OpenSSL PRNG with current contents of the screen - RAND_screen(); -#endif + // Check whether OpenSSL random number generator is properly seeded. If not, attempt to seed using RAND_poll(). + // Note that in versions of OpenSSL in the depends in Gridcoin (currently 1.1.1+), and modern Unix distros (using + // openSSL 1.1.1+ or modern Windows operating systems with the equivalent of /dev/urandom, the random number + // generator is automatically seeded on init, and periodically reseeded from trusted OS random sources. It is + // not necessary to manually reseed the RNG. Here we implement a check via RAND_status() to ensure the RNG + // is properly seeded. If not, we try 10 times (probably excessive) to seed the RNG via openSSL's entropy sources, + // breaking as soon as the return from RAND_poll() becomes 1 (successfully seeded). If this falls through, we abort + // the application as we cannot have a non-functioning RNG. + bool seed_successful = RAND_status(); + if (!seed_successful) { + for (unsigned int i = 0; i < 10; ++i) + { + seed_successful = RAND_poll(); - // Seed OpenSSL PRNG with performance counter - RandAddSeed(); + if (seed_successful) break; + } + + if (!seed_successful) std::abort(); + } } + ~CInit() { // Securely erase the memory used by the PRNG @@ -106,41 +119,6 @@ class CInit } instance_of_cinit; -void RandAddSeed() -{ - // Seed with CPU performance counter - int64_t nCounter = GetPerformanceCounter(); - RAND_add(&nCounter, sizeof(nCounter), 1.5); - memset(&nCounter, 0, sizeof(nCounter)); -} - -void RandAddSeedPerfmon() -{ - RandAddSeed(); - - // This can take up to 2 seconds, so only do it every 10 minutes - static int64_t nLastPerfmon; - if ( GetAdjustedTime() < nLastPerfmon + 10 * 60) - return; - nLastPerfmon = GetAdjustedTime(); - -#ifdef WIN32 - // Don't need this on Linux, OpenSSL automatically uses /dev/urandom - // Seed with the entire set of perfmon data - unsigned char pdata[250000]; - memset(pdata, 0, sizeof(pdata)); - unsigned long nSize = sizeof(pdata); - long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, pdata, &nSize); - RegCloseKey(HKEY_PERFORMANCE_DATA); - if (ret == ERROR_SUCCESS) - { - RAND_add(pdata, nSize, nSize/100.0); - memset(pdata, 0, nSize); - LogPrint(BCLog::LogFlags::NOISY, "rand", "RandAddSeed() %lu bytes", nSize); - } -#endif -} - uint64_t GetRand(uint64_t nMax) { if (nMax == 0) diff --git a/src/util.h b/src/util.h index b2154f4207..5fc01345ba 100644 --- a/src/util.h +++ b/src/util.h @@ -89,9 +89,6 @@ extern bool fLogTimestamps; extern bool fReopenDebugLog; extern bool fDevbuildCripple; -void RandAddSeed(); -void RandAddSeedPerfmon(); - void LogException(std::exception* pex, const char* pszThread); void PrintException(std::exception* pex, const char* pszThread); void PrintExceptionContinue(std::exception* pex, const char* pszThread); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5a3762fe4f..22482ae148 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -88,7 +88,6 @@ CPubKey CWallet::GenerateNewKey() AssertLockHeld(cs_wallet); // mapKeyMetadata bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets - RandAddSeedPerfmon(); CKey key; key.MakeNewKey(fCompressed); @@ -307,14 +306,12 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return false; CKeyingMaterial vMasterKey; - RandAddSeedPerfmon(); vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); CMasterKey kMasterKey(nDerivationMethodIndex); - RandAddSeedPerfmon(); kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);