1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 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 "crypto/sha512.h"
9 #include "support/cleanse.h"
11 #include "compat.h" // for Windows API
14 #include "serialize.h" // for begin_ptr(vec)
15 #include "util.h" // for LogPrint()
16 #include "utilstrencodings.h" // for GetTime()
25 #include <openssl/err.h>
26 #include <openssl/rand.h>
28 static void RandFailure()
30 LogPrintf("Failed to read randomness, aborting\n");
34 static inline int64_t GetPerformanceCounter()
38 QueryPerformanceCounter((LARGE_INTEGER
*)&nCounter
);
41 gettimeofday(&t
, NULL
);
42 nCounter
= (int64_t)(t
.tv_sec
* 1000000 + t
.tv_usec
);
49 // Seed with CPU performance counter
50 int64_t nCounter
= GetPerformanceCounter();
51 RAND_add(&nCounter
, sizeof(nCounter
), 1.5);
52 memory_cleanse((void*)&nCounter
, sizeof(nCounter
));
55 static void RandAddSeedPerfmon()
60 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
61 // Seed with the entire set of perfmon data
63 // This can take up to 2 seconds, so only do it every 10 minutes
64 static int64_t nLastPerfmon
;
65 if (GetTime() < nLastPerfmon
+ 10 * 60)
67 nLastPerfmon
= GetTime();
69 std::vector
<unsigned char> vData(250000, 0);
71 unsigned long nSize
= 0;
72 const size_t nMaxSize
= 10000000; // Bail out at more than 10MB of performance data
75 ret
= RegQueryValueExA(HKEY_PERFORMANCE_DATA
, "Global", NULL
, NULL
, begin_ptr(vData
), &nSize
);
76 if (ret
!= ERROR_MORE_DATA
|| vData
.size() >= nMaxSize
)
78 vData
.resize(std::max((vData
.size() * 3) / 2, nMaxSize
)); // Grow size of buffer exponentially
80 RegCloseKey(HKEY_PERFORMANCE_DATA
);
81 if (ret
== ERROR_SUCCESS
) {
82 RAND_add(begin_ptr(vData
), nSize
, nSize
/ 100.0);
83 memory_cleanse(begin_ptr(vData
), nSize
);
84 LogPrint("rand", "%s: %lu bytes\n", __func__
, nSize
);
86 static bool warned
= false; // Warn only once
88 LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__
, ret
);
95 /** Get 32 bytes of system entropy. */
96 static void GetOSRand(unsigned char *ent32
)
100 int ret
= CryptAcquireContextW(&hProvider
, NULL
, NULL
, PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
);
104 ret
= CryptGenRandom(hProvider
, 32, ent32
);
108 CryptReleaseContext(hProvider
, 0);
110 int f
= open("/dev/urandom", O_RDONLY
);
116 ssize_t n
= read(f
, ent32
+ have
, 32 - have
);
117 if (n
<= 0 || n
+ have
> 32) {
126 void GetRandBytes(unsigned char* buf
, int num
)
128 if (RAND_bytes(buf
, num
) != 1) {
133 void GetStrongRandBytes(unsigned char* out
, int num
)
137 unsigned char buf
[64];
139 // First source: OpenSSL's RNG
140 RandAddSeedPerfmon();
141 GetRandBytes(buf
, 32);
142 hasher
.Write(buf
, 32);
144 // Second source: OS RNG
146 hasher
.Write(buf
, 32);
149 hasher
.Finalize(buf
);
150 memcpy(out
, buf
, num
);
151 memory_cleanse(buf
, 64);
154 uint64_t GetRand(uint64_t nMax
)
159 // The range of the random source must be a multiple of the modulus
160 // to give every possible output value an equal possibility
161 uint64_t nRange
= (std::numeric_limits
<uint64_t>::max() / nMax
) * nMax
;
164 GetRandBytes((unsigned char*)&nRand
, sizeof(nRand
));
165 } while (nRand
>= nRange
);
166 return (nRand
% nMax
);
169 int GetRandInt(int nMax
)
171 return GetRand(nMax
);
174 uint256
GetRandHash()
177 GetRandBytes((unsigned char*)&hash
, sizeof(hash
));
181 FastRandomContext::FastRandomContext(bool fDeterministic
)
183 // The seed values have some unlikely fixed points which we avoid.
184 if (fDeterministic
) {
189 GetRandBytes((unsigned char*)&tmp
, 4);
190 } while (tmp
== 0 || tmp
== 0x9068ffffU
);
193 GetRandBytes((unsigned char*)&tmp
, 4);
194 } while (tmp
== 0 || tmp
== 0x464fffffU
);