diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -319,6 +319,7 @@ interfaces/handler.cpp logging.cpp random.cpp + randomenv.cpp rcu.cpp rpc/protocol.cpp support/cleanse.cpp diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -197,6 +197,7 @@ psbt.h \ radix.h \ random.h \ + randomenv.h \ rcu.h \ reverse_iterator.h \ reverselock.h \ @@ -534,6 +535,7 @@ interfaces/handler.cpp \ logging.cpp \ random.cpp \ + randomenv.cpp \ rcu.cpp \ rpc/protocol.cpp \ support/cleanse.cpp \ diff --git a/src/random.cpp b/src/random.cpp --- a/src/random.cpp +++ b/src/random.cpp @@ -11,6 +11,7 @@ #endif #include #include // for LogPrintf() +#include #include #include #include // for Mutex @@ -306,48 +307,6 @@ memory_cleanse(buffer, sizeof(buffer)); } -static void RandAddSeedPerfmon(CSHA512 &hasher) { -#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 vData(250000, 0); - long ret = 0; - unsigned long nSize = 0; - // Bail out at more than 10MB of performance data - const size_t nMaxSize = 10000000; - while (true) { - nSize = vData.size(); - ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, - nullptr, vData.data(), &nSize); - if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) { - break; - } - // Grow size of buffer exponentially - vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); - } - RegCloseKey(HKEY_PERFORMANCE_DATA); - if (ret == ERROR_SUCCESS) { - hasher.Write(vData.data(), nSize); - memory_cleanse(vData.data(), nSize); - } else { - // Performance data is only a best-effort attempt at improving the - // situation when the OS randomness (and other sources) aren't - // adequate. As a result, failure to read it is isn't considered - // critical, so we don't call RandFailure(). - // TODO: Add logging when the logger is made functional before global - // constructors have been invoked. - } -#endif -} - #ifndef WIN32 /** * Fallback: get 32 bytes of system entropy from /dev/urandom. The most @@ -643,8 +602,9 @@ // before and after, this measures the delay) SeedTimestamp(hasher); - // Windows performance monitor data (once every 10 minutes) - RandAddSeedPerfmon(hasher); + // Dynamic environment data (performance monitoring, ...; once every 10 + // minutes) + RandAddDynamicEnv(hasher); // Strengthen SeedStrengthen(hasher, rng); @@ -657,8 +617,11 @@ // Everything that the 'slow' seeder includes. SeedSlow(hasher); - // Windows performance monitor data. - RandAddSeedPerfmon(hasher); + // Dynamic environment data + RandAddDynamicEnv(hasher); + + // Static environment data + RandAddStaticEnv(hasher); // Strengthen SeedStrengthen(hasher, rng); diff --git a/src/randomenv.h b/src/randomenv.h new file mode 100644 --- /dev/null +++ b/src/randomenv.h @@ -0,0 +1,17 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RANDOMENV_H +#define BITCOIN_RANDOMENV_H + +#include + +/** Gather non-cryptographic environment data that changes over time. */ +void RandAddDynamicEnv(CSHA512 &hasher); + +/** Gather non-cryptographic environment data that does not change over time. */ +void RandAddStaticEnv(CSHA512 &hasher); + +#endif // BITCOIN_RANDOMENV_H diff --git a/src/randomenv.cpp b/src/randomenv.cpp new file mode 100644 --- /dev/null +++ b/src/randomenv.cpp @@ -0,0 +1,69 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include // for GetTime() +#ifdef WIN32 +#include // for Windows API +#endif + +#include +#include + +#include + +namespace { +void RandAddSeedPerfmon(CSHA512 &hasher) { +#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 vData(250000, 0); + long ret = 0; + unsigned long nSize = 0; + // Bail out at more than 10MB of performance data + const size_t nMaxSize = 10000000; + while (true) { + nSize = vData.size(); + ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, + nullptr, vData.data(), &nSize); + if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) { + break; + } + // Grow size of buffer exponentially + vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); + } + RegCloseKey(HKEY_PERFORMANCE_DATA); + if (ret == ERROR_SUCCESS) { + hasher.Write(vData.data(), nSize); + memory_cleanse(vData.data(), nSize); + } else { + // Performance data is only a best-effort attempt at improving the + // situation when the OS randomness (and other sources) aren't + // adequate. As a result, failure to read it is isn't considered + // critical, so we don't call RandFailure(). + // TODO: Add logging when the logger is made functional before global + // constructors have been invoked. + } +#endif +} + +} // namespace + +void RandAddDynamicEnv(CSHA512 &hasher) { + RandAddSeedPerfmon(hasher); +} + +void RandAddStaticEnv(CSHA512 &hasher) {}