From 001a53d7427dcbcceef3c6754d9cca19df6dafa1 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 14:27:32 +0200 Subject: [PATCH 1/3] add GetRandBytes() as wrapper for RAND_bytes() - add a small wrapper in util around RAND_bytes() and replace with GetRandBytes() in the code to log errors from calling RAND_bytes() - remove OpenSSL header rand.h where no longer needed --- src/addrman.h | 4 +--- src/key.cpp | 10 ++++------ src/main.cpp | 2 +- src/net.cpp | 4 ++-- src/rpcserver.cpp | 2 +- src/util.cpp | 29 ++++++++++++++++------------- src/util.h | 1 + src/wallet.cpp | 9 +++++---- 8 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/addrman.h b/src/addrman.h index c4c296560..c012e3dee 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -16,8 +16,6 @@ #include #include -#include - /** Extended statistics about a CAddress */ class CAddrInfo : public CAddress { @@ -384,7 +382,7 @@ public: CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set()) { nKey.resize(32); - RAND_bytes(&nKey[0], 32); + GetRandBytes(&nKey[0], 32); nIdCount = 0; nTried = 0; diff --git a/src/key.cpp b/src/key.cpp index 3c4fa77e7..a253f8666 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -1,11 +1,11 @@ -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "key.h" #include "crypto/sha2.h" -#include +#include "random.h" #ifdef USE_SECP256K1 #include @@ -194,7 +194,7 @@ public: if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) { if(fSkipCheck) return true; - + // d2i_ECPrivateKey returns true if parsing succeeds. // This doesn't necessarily mean the key is valid. if (EC_KEY_check_key(pkey)) @@ -412,7 +412,7 @@ bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) { void CKey::MakeNewKey(bool fCompressedIn) { do { - RAND_bytes(vch, sizeof(vch)); + GetRandBytes(vch, sizeof(vch)); } while (!Check(vch)); fValid = true; fCompressed = fCompressedIn; @@ -745,5 +745,3 @@ bool ECC_InitSanityCheck() { return true; #endif } - - diff --git a/src/main.cpp b/src/main.cpp index a9c080ffa..8225d73d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4370,7 +4370,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) if (pingSend) { uint64_t nonce = 0; while (nonce == 0) { - RAND_bytes((unsigned char*)&nonce, sizeof(nonce)); + GetRandBytes((unsigned char*)&nonce, sizeof(nonce)); } pto->fPingQueued = false; pto->nPingUsecStart = GetTimeMicros(); diff --git a/src/net.cpp b/src/net.cpp index 6a660dc9b..0e663aea8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -546,7 +546,7 @@ void CNode::PushVersion() int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime()); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); CAddress addrMe = GetLocalAddress(&addr); - RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); + GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); if (fLogIPs) LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); else @@ -1931,7 +1931,7 @@ bool CAddrDB::Write(const CAddrMan& addr) { // Generate random temporary filename unsigned short randv = 0; - RAND_bytes((unsigned char *)&randv, sizeof(randv)); + GetRandBytes((unsigned char*)&randv, sizeof(randv)); std::string tmpfn = strprintf("peers.dat.%04x", randv); // serialize addresses, checksum data up to that point, then append csum diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 18fa07510..e0c96d88f 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -531,7 +531,7 @@ void StartRPCThreads() (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword()) { unsigned char rand_pwd[32]; - RAND_bytes(rand_pwd, 32); + GetRandBytes(rand_pwd, 32); string strWhatAmI = "To use bitcoind"; if (mapArgs.count("-server")) strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); diff --git a/src/util.cpp b/src/util.cpp index 91ac8833d..8f2a1bd73 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include // Work around clang compilation problem in Boost 1.46: @@ -141,12 +142,14 @@ public: } instance_of_cinit; - - - - - - +bool GetRandBytes(unsigned char *buf, int num) +{ + if (RAND_bytes(buf, num) == 0) { + LogPrint("rand", "%s : OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + return true; +} void RandAddSeed() { @@ -207,9 +210,9 @@ uint64_t GetRand(uint64_t nMax) // to give every possible output value an equal possibility uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; uint64_t nRand = 0; - do - RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); - while (nRand >= nRange); + do { + GetRandBytes((unsigned char*)&nRand, sizeof(nRand)); + } while (nRand >= nRange); return (nRand % nMax); } @@ -221,7 +224,7 @@ int GetRandInt(int nMax) uint256 GetRandHash() { uint256 hash; - RAND_bytes((unsigned char*)&hash, sizeof(hash)); + GetRandBytes((unsigned char*)&hash, sizeof(hash)); return hash; } @@ -1196,18 +1199,18 @@ uint32_t insecure_rand_Rz = 11; uint32_t insecure_rand_Rw = 11; void seed_insecure_rand(bool fDeterministic) { - //The seed values have some unlikely fixed points which we avoid. + // The seed values have some unlikely fixed points which we avoid. if(fDeterministic) { insecure_rand_Rz = insecure_rand_Rw = 11; } else { uint32_t tmp; do { - RAND_bytes((unsigned char*)&tmp, 4); + GetRandBytes((unsigned char*)&tmp, 4); } while(tmp == 0 || tmp == 0x9068ffffU); insecure_rand_Rz = tmp; do { - RAND_bytes((unsigned char*)&tmp, 4); + GetRandBytes((unsigned char*)&tmp, 4); } while(tmp == 0 || tmp == 0x464fffffU); insecure_rand_Rw = tmp; } diff --git a/src/util.h b/src/util.h index 60db71bfd..d0108ee77 100644 --- a/src/util.h +++ b/src/util.h @@ -103,6 +103,7 @@ extern bool fLogTimestamps; extern bool fLogIPs; extern volatile bool fReopenDebugLog; +bool GetRandBytes(unsigned char *buf, int num); void RandAddSeed(); void RandAddSeedPerfmon(); void SetupEnvironment(); diff --git a/src/wallet.cpp b/src/wallet.cpp index a54494f93..d61f01d09 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -12,7 +12,6 @@ #include "timedata.h" #include -#include using namespace std; @@ -384,13 +383,15 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) RandAddSeedPerfmon(); vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE); - RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE); + if (!GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE)) + return false; CMasterKey kMasterKey; - RandAddSeedPerfmon(); + kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE); - RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE); + if (!GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE)) + return false; CCrypter crypter; int64_t nStartTime = GetTimeMillis(); From 6354935c485d116e1965567561c197ab3fbc0e11 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Thu, 26 Jun 2014 14:41:53 +0200 Subject: [PATCH 2/3] move rand functions from util to new random.h/.cpp --- src/Makefile.am | 6 +- src/addrman.h | 1 + src/chainparams.cpp | 1 + src/net.h | 2 +- src/random.cpp | 140 +++++++++++++++++++++++++++++++++++ src/random.h | 49 ++++++++++++ src/script.cpp | 8 +- src/test/canonical_tests.cpp | 8 +- src/test/crypto_tests.cpp | 1 + src/test/mruset_tests.cpp | 1 + src/test/sighash_tests.cpp | 16 ++-- src/test/skiplist_tests.cpp | 7 +- src/test/test_bitcoin.cpp | 4 +- src/test/util_tests.cpp | 1 + src/util.cpp | 109 +-------------------------- src/util.h | 51 ------------- 16 files changed, 220 insertions(+), 185 deletions(-) create mode 100644 src/random.cpp create mode 100644 src/random.h diff --git a/src/Makefile.am b/src/Makefile.am index 9b0b97b7a..90e0a43be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,6 +91,7 @@ BITCOIN_CORE_H = \ noui.h \ pow.h \ protocol.h \ + random.h \ rpcclient.h \ rpcprotocol.h \ rpcserver.h \ @@ -197,14 +198,15 @@ libbitcoin_common_a_SOURCES = \ # backward-compatibility objects and their sanity checks are linked. libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_util_a_SOURCES = \ + compat/glibc_sanity.cpp \ + compat/glibcxx_sanity.cpp \ chainparamsbase.cpp \ + random.cpp \ rpcprotocol.cpp \ sync.cpp \ uint256.cpp \ util.cpp \ version.cpp \ - compat/glibc_sanity.cpp \ - compat/glibcxx_sanity.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT diff --git a/src/addrman.h b/src/addrman.h index c012e3dee..a0dc134c4 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -7,6 +7,7 @@ #include "netbase.h" #include "protocol.h" +#include "random.h" #include "sync.h" #include "timedata.h" #include "util.h" diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 63067a153..50977dc06 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -6,6 +6,7 @@ #include "chainparams.h" #include "assert.h" +#include "random.h" #include "util.h" #include diff --git a/src/net.h b/src/net.h index c2a041645..21a2919f4 100644 --- a/src/net.h +++ b/src/net.h @@ -13,6 +13,7 @@ #include "mruset.h" #include "netbase.h" #include "protocol.h" +#include "random.h" #include "sync.h" #include "uint256.h" #include "util.h" @@ -26,7 +27,6 @@ #include #include -#include class CAddrMan; class CBlockIndex; diff --git a/src/random.cpp b/src/random.cpp new file mode 100644 index 000000000..4c7f150f7 --- /dev/null +++ b/src/random.cpp @@ -0,0 +1,140 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "random.h" + +#ifdef WIN32 +#include "compat.h" // for Windows API +#endif +#include "util.h" // for LogPrint() + +#ifndef WIN32 +#include +#endif +#include // for memset() + +#include +#include +#include + +static inline int64_t GetPerformanceCounter() +{ + int64_t nCounter = 0; +#ifdef WIN32 + QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); +#else + timeval t; + gettimeofday(&t, NULL); + nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec); +#endif + return nCounter; +} + +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 (GetTime() < nLastPerfmon + 10 * 60) + return; + nLastPerfmon = GetTime(); + +#ifdef WIN32 + // Don't need this on Linux, OpenSSL automatically uses /dev/urandom + // Seed with the entire set of perfmon data + std::vector 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); + OPENSSL_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 +} + +bool 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)); + return false; + } + return true; +} + +uint64_t GetRand(uint64_t nMax) +{ + if (nMax == 0) + return 0; + + // The range of the random source must be a multiple of the modulus + // to give every possible output value an equal possibility + uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; + uint64_t nRand = 0; + do { + GetRandBytes((unsigned char*)&nRand, sizeof(nRand)); + } while (nRand >= nRange); + return (nRand % nMax); +} + +int GetRandInt(int nMax) +{ + return GetRand(nMax); +} + +uint256 GetRandHash() +{ + uint256 hash; + GetRandBytes((unsigned char*)&hash, sizeof(hash)); + return hash; +} + +uint32_t insecure_rand_Rz = 11; +uint32_t insecure_rand_Rw = 11; +void seed_insecure_rand(bool fDeterministic) +{ + // The seed values have some unlikely fixed points which we avoid. + if(fDeterministic) + { + insecure_rand_Rz = insecure_rand_Rw = 11; + } else { + uint32_t tmp; + do { + GetRandBytes((unsigned char*)&tmp, 4); + } while(tmp == 0 || tmp == 0x9068ffffU); + insecure_rand_Rz = tmp; + do { + GetRandBytes((unsigned char*)&tmp, 4); + } while(tmp == 0 || tmp == 0x464fffffU); + insecure_rand_Rw = tmp; + } +} diff --git a/src/random.h b/src/random.h new file mode 100644 index 000000000..a599b0847 --- /dev/null +++ b/src/random.h @@ -0,0 +1,49 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RANDOM_H +#define BITCOIN_RANDOM_H + +#include "uint256.h" + +#include + +/** + * Seed OpenSSL PRNG with additional entropy data + */ +void RandAddSeed(); +void RandAddSeedPerfmon(); + +/** + * Functions to gather random data via the OpenSSL PRNG + */ +bool GetRandBytes(unsigned char *buf, int num); +uint64_t GetRand(uint64_t nMax); +int GetRandInt(int nMax); +uint256 GetRandHash(); + +/** + * Seed insecure_rand using the random pool. + * @param Deterministic Use a determinstic seed + */ +void seed_insecure_rand(bool fDeterministic = false); + +/** + * MWC RNG of George Marsaglia + * This is intended to be fast. It has a period of 2^59.3, though the + * least significant 16 bits only have a period of about 2^30.1. + * + * @return random value + */ +extern uint32_t insecure_rand_Rz; +extern uint32_t insecure_rand_Rw; +static inline uint32_t insecure_rand(void) +{ + insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16); + insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16); + return (insecure_rand_Rw << 16) + insecure_rand_Rz; +} + +#endif // BITCOIN_RANDOM_H diff --git a/src/script.cpp b/src/script.cpp index 238a25e72..39ae001db 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -5,13 +5,14 @@ #include "script.h" +#include "crypto/ripemd160.h" +#include "crypto/sha1.h" +#include "crypto/sha2.h" #include "core.h" #include "hash.h" #include "key.h" #include "keystore.h" -#include "crypto/sha1.h" -#include "crypto/sha2.h" -#include "crypto/ripemd160.h" +#include "random.h" #include "sync.h" #include "uint256.h" #include "util.h" @@ -1097,7 +1098,6 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig // Valid signature cache, to avoid doing expensive ECDSA signature checking // twice for every transaction (once when accepted into memory pool, and // again when accepted into the block chain) - class CSignatureCache { private: diff --git a/src/test/canonical_tests.cpp b/src/test/canonical_tests.cpp index 23dd74296..a9798623e 100644 --- a/src/test/canonical_tests.cpp +++ b/src/test/canonical_tests.cpp @@ -6,12 +6,11 @@ // Unit tests for canonical signatures // - - -#include "script.h" -#include "util.h" #include "data/sig_noncanonical.json.h" #include "data/sig_canonical.json.h" +#include "random.h" +#include "script.h" +#include "util.h" #include #include @@ -21,7 +20,6 @@ using namespace std; using namespace json_spirit; - // In script_tests.cpp extern Array read_json(const std::string& jsondata); diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 7bd98fa38..a17278b80 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -5,6 +5,7 @@ #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" +#include "random.h" #include "util.h" #include diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index 60f11c147..547cd1090 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -4,6 +4,7 @@ #include "mruset.h" +#include "random.h" #include "util.h" #include diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 423ae4a78..b99797fcc 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -2,15 +2,16 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include -#include - +#include "data/sighash.json.h" #include "main.h" -#include "util.h" +#include "random.h" #include "serialize.h" +#include "util.h" #include "version.h" -#include "data/sighash.json.h" +#include + +#include #include "json/json_spirit_reader_template.h" #include "json/json_spirit_utils.h" #include "json/json_spirit_writer_template.h" @@ -118,7 +119,7 @@ BOOST_AUTO_TEST_SUITE(sighash_tests) BOOST_AUTO_TEST_CASE(sighash_test) { seed_insecure_rand(false); - + #if defined(PRINT_SIGHASH_JSON) std::cout << "[\n"; std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n"; @@ -205,10 +206,9 @@ BOOST_AUTO_TEST_CASE(sighash_from_data) BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest); continue; } - + sh = SignatureHash(scriptCode, tx, nIn, nHashType); BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest); } } BOOST_AUTO_TEST_SUITE_END() - diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 11762c6ea..a123f1d19 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -2,11 +2,13 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include -#include #include "main.h" +#include "random.h" #include "util.h" +#include + +#include #define SKIPLIST_LENGTH 300000 @@ -98,4 +100,3 @@ BOOST_AUTO_TEST_CASE(getlocator_test) } BOOST_AUTO_TEST_SUITE_END() - diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index bcd2f75f5..443b5853b 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -4,9 +4,8 @@ #define BOOST_TEST_MODULE Bitcoin Test Suite - - #include "main.h" +#include "random.h" #include "txdb.h" #include "ui_interface.h" #include "util.h" @@ -89,4 +88,3 @@ bool ShutdownRequested() { return false; } - diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 0b071361d..068b9f29c 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -4,6 +4,7 @@ #include "util.h" +#include "random.h" #include "sync.h" #include diff --git a/src/util.cpp b/src/util.cpp index 8f2a1bd73..ce31619ec 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6,6 +6,7 @@ #include "util.h" #include "chainparamsbase.h" +#include "random.h" #include "sync.h" #include "uint256.h" #include "version.h" @@ -69,7 +70,6 @@ #include #include #include -#include #include // Work around clang compilation problem in Boost 1.46: @@ -142,92 +142,6 @@ public: } instance_of_cinit; -bool GetRandBytes(unsigned char *buf, int num) -{ - if (RAND_bytes(buf, num) == 0) { - LogPrint("rand", "%s : OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL)); - return false; - } - return true; -} - -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 (GetTime() < nLastPerfmon + 10 * 60) - return; - nLastPerfmon = GetTime(); - -#ifdef WIN32 - // Don't need this on Linux, OpenSSL automatically uses /dev/urandom - // Seed with the entire set of perfmon data - std::vector 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); - OPENSSL_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 -} - -uint64_t GetRand(uint64_t nMax) -{ - if (nMax == 0) - return 0; - - // The range of the random source must be a multiple of the modulus - // to give every possible output value an equal possibility - uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; - uint64_t nRand = 0; - do { - GetRandBytes((unsigned char*)&nRand, sizeof(nRand)); - } while (nRand >= nRange); - return (nRand % nMax); -} - -int GetRandInt(int nMax) -{ - return GetRand(nMax); -} - -uint256 GetRandHash() -{ - uint256 hash; - GetRandBytes((unsigned char*)&hash, sizeof(hash)); - return hash; -} - // LogPrintf() has been broken a couple of times now // by well-meaning people adding mutexes in the most straightforward way. // It breaks because it may be called by global destructors during shutdown. @@ -1195,27 +1109,6 @@ void SetMockTime(int64_t nMockTimeIn) nMockTime = nMockTimeIn; } -uint32_t insecure_rand_Rz = 11; -uint32_t insecure_rand_Rw = 11; -void seed_insecure_rand(bool fDeterministic) -{ - // The seed values have some unlikely fixed points which we avoid. - if(fDeterministic) - { - insecure_rand_Rz = insecure_rand_Rw = 11; - } else { - uint32_t tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while(tmp == 0 || tmp == 0x9068ffffU); - insecure_rand_Rz = tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while(tmp == 0 || tmp == 0x464fffffU); - insecure_rand_Rw = tmp; - } -} - string FormatVersion(int nVersion) { if (nVersion%100 == 0) diff --git a/src/util.h b/src/util.h index d0108ee77..db2005337 100644 --- a/src/util.h +++ b/src/util.h @@ -90,8 +90,6 @@ inline void MilliSleep(int64_t n) #endif } - - extern std::map mapArgs; extern std::map > mapMultiArgs; extern bool fDebug; @@ -103,9 +101,6 @@ extern bool fLogTimestamps; extern bool fLogIPs; extern volatile bool fReopenDebugLog; -bool GetRandBytes(unsigned char *buf, int num); -void RandAddSeed(); -void RandAddSeedPerfmon(); void SetupEnvironment(); /* Return true if log accepts specified category */ @@ -188,23 +183,12 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif boost::filesystem::path GetTempPath(); void ShrinkDebugFile(); -int GetRandInt(int nMax); -uint64_t GetRand(uint64_t nMax); -uint256 GetRandHash(); int64_t GetTime(); void SetMockTime(int64_t nMockTimeIn); std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); void runCommand(std::string strCommand); - - - - - - - - inline std::string i64tostr(int64_t n) { return strprintf("%d", n); @@ -290,19 +274,6 @@ inline std::string HexStr(const T& vch, bool fSpaces=false) */ std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0); -inline int64_t GetPerformanceCounter() -{ - int64_t nCounter = 0; -#ifdef WIN32 - QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); -#else - timeval t; - gettimeofday(&t, NULL); - nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec; -#endif - return nCounter; -} - inline int64_t GetTimeMillis() { return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) - @@ -371,28 +342,6 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue); */ bool SoftSetBoolArg(const std::string& strArg, bool fValue); -/** - * MWC RNG of George Marsaglia - * This is intended to be fast. It has a period of 2^59.3, though the - * least significant 16 bits only have a period of about 2^30.1. - * - * @return random value - */ -extern uint32_t insecure_rand_Rz; -extern uint32_t insecure_rand_Rw; -static inline uint32_t insecure_rand(void) -{ - insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16); - insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16); - return (insecure_rand_Rw << 16) + insecure_rand_Rz; -} - -/** - * Seed insecure_rand using the random pool. - * @param Deterministic Use a determinstic seed - */ -void seed_insecure_rand(bool fDeterministic=false); - /** * Timing-attack-resistant comparison. * Takes time proportional to length From 4eedf4ffeea6a3734f245f785a8d82d69634dccd Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 9 Jul 2014 09:43:55 +0200 Subject: [PATCH 3/3] make RandAddSeed() use OPENSSL_cleanse() - removes the cstring include and is also used in RandAddSeedPerfmon() --- src/random.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 4c7f150f7..0d20d205a 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -13,7 +13,6 @@ #ifndef WIN32 #include #endif -#include // for memset() #include #include @@ -37,7 +36,7 @@ void RandAddSeed() // Seed with CPU performance counter int64_t nCounter = GetPerformanceCounter(); RAND_add(&nCounter, sizeof(nCounter), 1.5); - memset(&nCounter, 0, sizeof(nCounter)); + OPENSSL_cleanse((void*)&nCounter, sizeof(nCounter)); } void RandAddSeedPerfmon()