Dash Core  0.12.2.1
P2P Digital Currency
random.cpp
Go to the documentation of this file.
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.
5 
6 #include "random.h"
7 
8 #include "support/cleanse.h"
9 #ifdef WIN32
10 #include "compat.h" // for Windows API
11 #endif
12 #include "serialize.h" // for begin_ptr(vec)
13 #include "util.h" // for LogPrint()
14 #include "utilstrencodings.h" // for GetTime()
15 
16 #include <limits>
17 
18 #ifndef WIN32
19 #include <sys/time.h>
20 #endif
21 
22 #include <openssl/err.h>
23 #include <openssl/rand.h>
24 
25 static inline int64_t GetPerformanceCounter()
26 {
27  int64_t nCounter = 0;
28 #ifdef WIN32
29  QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
30 #else
31  timeval t;
32  gettimeofday(&t, NULL);
33  nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
34 #endif
35  return nCounter;
36 }
37 
39 {
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));
44 }
45 
47 {
48  RandAddSeed();
49 
50 #ifdef WIN32
51  // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
52  // Seed with the entire set of perfmon data
53 
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)
57  return;
58  nLastPerfmon = GetTime();
59 
60  std::vector<unsigned char> vData(250000, 0);
61  long ret = 0;
62  unsigned long nSize = 0;
63  const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
64  while (true) {
65  nSize = vData.size();
66  ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
67  if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
68  break;
69  vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
70  }
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);
76  } else {
77  static bool warned = false; // Warn only once
78  if (!warned) {
79  LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
80  warned = true;
81  }
82  }
83 #endif
84 }
85 
86 void GetRandBytes(unsigned char* buf, int num)
87 {
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));
90  assert(false);
91  }
92 }
93 
94 uint64_t GetRand(uint64_t nMax)
95 {
96  if (nMax == 0)
97  return 0;
98 
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;
102  uint64_t nRand = 0;
103  do {
104  GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
105  } while (nRand >= nRange);
106  return (nRand % nMax);
107 }
108 
109 int GetRandInt(int nMax)
110 {
111  return GetRand(nMax);
112 }
113 
115 {
116  uint256 hash;
117  GetRandBytes((unsigned char*)&hash, sizeof(hash));
118  return hash;
119 }
120 
121 uint32_t insecure_rand_Rz = 11;
122 uint32_t insecure_rand_Rw = 11;
123 void seed_insecure_rand(bool fDeterministic)
124 {
125  // The seed values have some unlikely fixed points which we avoid.
126  if (fDeterministic) {
128  } else {
129  uint32_t tmp;
130  do {
131  GetRandBytes((unsigned char*)&tmp, 4);
132  } while (tmp == 0 || tmp == 0x9068ffffU);
133  insecure_rand_Rz = tmp;
134  do {
135  GetRandBytes((unsigned char*)&tmp, 4);
136  } while (tmp == 0 || tmp == 0x464fffffU);
137  insecure_rand_Rw = tmp;
138  }
139 }
140 
141 InsecureRand::InsecureRand(bool _fDeterministic)
142  : nRz(11),
143  nRw(11),
144  fDeterministic(_fDeterministic)
145 {
146  // The seed values have some unlikely fixed points which we avoid.
147  if(fDeterministic) return;
148  uint32_t nTmp;
149  do {
150  GetRandBytes((unsigned char*)&nTmp, 4);
151  } while (nTmp == 0 || nTmp == 0x9068ffffU);
152  nRz = nTmp;
153  do {
154  GetRandBytes((unsigned char*)&nTmp, 4);
155  } while (nTmp == 0 || nTmp == 0x464fffffU);
156  nRw = nTmp;
157 }
uint256 GetRandHash()
Definition: random.cpp:114
int GetRandInt(int nMax)
Definition: random.cpp:109
void RandAddSeedPerfmon()
Definition: random.cpp:46
static int64_t GetPerformanceCounter()
Definition: random.cpp:25
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:10
#define LogPrintf(...)
Definition: util.h:98
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
uint32_t insecure_rand_Rw
Definition: random.cpp:122
V::value_type * begin_ptr(V &v)
Definition: serialize.h:54
void seed_insecure_rand(bool fDeterministic)
Definition: random.cpp:123
bool fDeterministic
Definition: random.h:57
uint32_t nRz
Definition: random.h:55
void GetRandBytes(unsigned char *buf, int num)
Definition: random.cpp:86
void RandAddSeed()
Definition: random.cpp:38
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:20
uint32_t nRw
Definition: random.h:56
InsecureRand(bool _fDeterministic=false)
Definition: random.cpp:141
uint32_t insecure_rand_Rz
Definition: random.cpp:121
uint64_t GetRand(uint64_t nMax)
Definition: random.cpp:94