Skip to content

Commit 723a2f9

Browse files
committed
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.
1 parent 6f2b2df commit 723a2f9

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

src/qt/winshutdownmonitor.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,6 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM
2222

2323
MSG *pMsg = static_cast<MSG *>(pMessage);
2424

25-
// Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions)
26-
if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
27-
// Warn only once as this is performance-critical
28-
static bool warned = false;
29-
if (!warned) {
30-
LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
31-
warned = true;
32-
}
33-
}
34-
3525
switch(pMsg->message)
3626
{
3727
case WM_QUERYENDSESSION:

src/util.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,36 @@ class CInit
8585
ppmutexOpenSSL[i] = new CCriticalSection();
8686
CRYPTO_set_locking_callback(locking_callback);
8787

88-
#ifdef WIN32
89-
// Seed OpenSSL PRNG with current contents of the screen
90-
RAND_screen();
91-
#endif
88+
// Check whether OpenSSL random number generator is properly seeded. If not, attempt to seed using RAND_poll().
89+
// Note that in versions of OpenSSL in the depends in Gridcoin (currently 1.1.1+), and modern Unix distros (using
90+
// openSSL 1.1+ or modern Windows operating systems with the equivalent of /dev/urandom, the random number
91+
// generator is automatically seeded on init, and periodically reseeded from trusted OS random sources. It is
92+
// not necessary to manually reseed the RNG. Here we implement a check via RAND_status() to ensure the RNG
93+
// is properly seeded. If not, we try 10 times (probably excessive) to seed the RNG via openSSL's entropy sources,
94+
// breaking as soon as the return from RAND_poll() becomes 1 (successfully seeded). A 100 ms sleep is inserted
95+
// between each try to ensure we give time for a short term unavailability of the OS entropy source to recover.
96+
// If this falls through, we abort the application as we cannot have a non-functioning RNG.
97+
bool seed_successful = RAND_status();
98+
if (!seed_successful) {
99+
for (unsigned int i = 0; i < 10; ++i)
100+
{
101+
seed_successful = RAND_poll();
102+
103+
if (seed_successful) break;
104+
105+
MilliSleep(100);
106+
}
92107

93-
// Seed OpenSSL PRNG with performance counter
94-
RandAddSeed();
108+
if (!seed_successful) {
109+
tfm::format(std::cerr, "ERROR: %s: Unable to initialize the random number generator. Cannot continue. "
110+
"Please check your operating system to ensure the random number source is "
111+
"available. (This is /dev/urandom on Linux.)",
112+
__func__);
113+
std::abort();
114+
}
115+
}
95116
}
117+
96118
~CInit()
97119
{
98120
// Securely erase the memory used by the PRNG
@@ -118,13 +140,15 @@ void RandAddSeedPerfmon()
118140
{
119141
RandAddSeed();
120142

143+
// Only need for OpenSSL < 1.1 and Win32, since 1.1 and greater seed properly from Windows, and on Linux seeds properly
144+
// in all cases.
145+
#if OPENSSL_VERSION_NUMBER < 0x10100000L && defined(WIN32)
121146
// This can take up to 2 seconds, so only do it every 10 minutes
122147
static int64_t nLastPerfmon;
123148
if ( GetAdjustedTime() < nLastPerfmon + 10 * 60)
124149
return;
125150
nLastPerfmon = GetAdjustedTime();
126151

127-
#ifdef WIN32
128152
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
129153
// Seed with the entire set of perfmon data
130154
unsigned char pdata[250000];

0 commit comments

Comments
 (0)