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
;