|
|
@ -19,8 +19,7 @@ |
|
|
|
#include <sys/time.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
#include <openssl/err.h> |
|
|
|
#include <openssl/rand.h> |
|
|
|
#include "sodium.h" |
|
|
|
|
|
|
|
static inline int64_t GetPerformanceCounter() |
|
|
|
{ |
|
|
@ -35,60 +34,9 @@ static inline int64_t GetPerformanceCounter() |
|
|
|
return nCounter; |
|
|
|
} |
|
|
|
|
|
|
|
void RandAddSeed() |
|
|
|
void GetRandBytes(unsigned char* buf, size_t num) |
|
|
|
{ |
|
|
|
// Seed with CPU performance counter
|
|
|
|
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); |
|
|
|
} |
|
|
|
randombytes_buf(buf, num); |
|
|
|
} |
|
|
|
|
|
|
|
uint64_t GetRand(uint64_t nMax) |
|
|
|