1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
8 #include "support/cleanse.h"
10 #include "compat.h" // for Windows API
12 #include "serialize.h" // for begin_ptr(vec)
13 #include "util.h" // for LogPrint()
14 #include "utilstrencodings.h" // for GetTime()
22 #include <openssl/err.h>
23 #include <openssl/rand.h>
25 static inline int64_t GetPerformanceCounter()
29 QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
32 gettimeofday(&t, NULL);
33 nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
40 // Seed with CPU performance counter
41 int64_t nCounter = GetPerformanceCounter();
42 RAND_add(&nCounter, sizeof(nCounter), 1.5);
43 memory_cleanse((void*)&nCounter, sizeof(nCounter));
46 void RandAddSeedPerfmon()
51 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
52 // Seed with the entire set of perfmon data
54 // This can take up to 2 seconds, so only do it every 10 minutes
55 static int64_t nLastPerfmon;
56 if (GetTime() < nLastPerfmon + 10 * 60)
58 nLastPerfmon = GetTime();
60 std::vector<unsigned char> vData(250000, 0);
62 unsigned long nSize = 0;
63 const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
66 ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
67 if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
69 vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
71 RegCloseKey(HKEY_PERFORMANCE_DATA);
72 if (ret == ERROR_SUCCESS) {
73 RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
74 memory_cleanse(begin_ptr(vData), nSize);
75 LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
77 static bool warned = false; // Warn only once
79 LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
86 void GetRandBytes(unsigned char* buf, int num)
88 if (RAND_bytes(buf, num) != 1) {
89 LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
94 uint64_t GetRand(uint64_t nMax)
99 // The range of the random source must be a multiple of the modulus
100 // to give every possible output value an equal possibility
101 uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
104 GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
105 } while (nRand >= nRange);
106 return (nRand % nMax);
109 int GetRandInt(int nMax)
111 return GetRand(nMax);
114 uint256 GetRandHash()
117 GetRandBytes((unsigned char*)&hash, sizeof(hash));
121 uint32_t insecure_rand_Rz = 11;
122 uint32_t insecure_rand_Rw = 11;
123 void seed_insecure_rand(bool fDeterministic)
125 // The seed values have some unlikely fixed points which we avoid.
126 if (fDeterministic) {
127 insecure_rand_Rz = insecure_rand_Rw = 11;
131 GetRandBytes((unsigned char*)&tmp, 4);
132 } while (tmp == 0 || tmp == 0x9068ffffU);
133 insecure_rand_Rz = tmp;
135 GetRandBytes((unsigned char*)&tmp, 4);
136 } while (tmp == 0 || tmp == 0x464fffffU);
137 insecure_rand_Rw = tmp;
141 int GenIdentity(int n)