Skip to content

Commit 6513a9f

Browse files
committed
Merge pull request #4400
4eedf4f make RandAddSeed() use OPENSSL_cleanse() (Philip Kaufmann) 6354935 move rand functions from util to new random.h/.cpp (Philip Kaufmann) 001a53d add GetRandBytes() as wrapper for RAND_bytes() (Philip Kaufmann)
2 parents d4bed1a + 4eedf4f commit 6513a9f

21 files changed

+233
-198
lines changed

src/Makefile.am

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ BITCOIN_CORE_H = \
9191
noui.h \
9292
pow.h \
9393
protocol.h \
94+
random.h \
9495
rpcclient.h \
9596
rpcprotocol.h \
9697
rpcserver.h \
@@ -197,14 +198,15 @@ libbitcoin_common_a_SOURCES = \
197198
# backward-compatibility objects and their sanity checks are linked.
198199
libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES)
199200
libbitcoin_util_a_SOURCES = \
201+
compat/glibc_sanity.cpp \
202+
compat/glibcxx_sanity.cpp \
200203
chainparamsbase.cpp \
204+
random.cpp \
201205
rpcprotocol.cpp \
202206
sync.cpp \
203207
uint256.cpp \
204208
util.cpp \
205209
version.cpp \
206-
compat/glibc_sanity.cpp \
207-
compat/glibcxx_sanity.cpp \
208210
$(BITCOIN_CORE_H)
209211

210212
if GLIBC_BACK_COMPAT

src/addrman.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "netbase.h"
99
#include "protocol.h"
10+
#include "random.h"
1011
#include "sync.h"
1112
#include "timedata.h"
1213
#include "util.h"
@@ -16,8 +17,6 @@
1617
#include <stdint.h>
1718
#include <vector>
1819

19-
#include <openssl/rand.h>
20-
2120
/** Extended statistics about a CAddress */
2221
class CAddrInfo : public CAddress
2322
{
@@ -384,7 +383,7 @@ class CAddrMan
384383
CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>())
385384
{
386385
nKey.resize(32);
387-
RAND_bytes(&nKey[0], 32);
386+
GetRandBytes(&nKey[0], 32);
388387

389388
nIdCount = 0;
390389
nTried = 0;

src/chainparams.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "chainparams.h"
77

88
#include "assert.h"
9+
#include "random.h"
910
#include "util.h"
1011

1112
#include <boost/assign/list_of.hpp>

src/key.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// Copyright (c) 2009-2013 The Bitcoin developers
1+
// Copyright (c) 2009-2014 The Bitcoin developers
22
// Distributed under the MIT/X11 software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include "key.h"
66

77
#include "crypto/sha2.h"
8-
#include <openssl/rand.h>
8+
#include "random.h"
99

1010
#ifdef USE_SECP256K1
1111
#include <secp256k1.h>
@@ -194,7 +194,7 @@ class CECKey {
194194
if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
195195
if(fSkipCheck)
196196
return true;
197-
197+
198198
// d2i_ECPrivateKey returns true if parsing succeeds.
199199
// This doesn't necessarily mean the key is valid.
200200
if (EC_KEY_check_key(pkey))
@@ -412,7 +412,7 @@ bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
412412

413413
void CKey::MakeNewKey(bool fCompressedIn) {
414414
do {
415-
RAND_bytes(vch, sizeof(vch));
415+
GetRandBytes(vch, sizeof(vch));
416416
} while (!Check(vch));
417417
fValid = true;
418418
fCompressed = fCompressedIn;
@@ -745,5 +745,3 @@ bool ECC_InitSanityCheck() {
745745
return true;
746746
#endif
747747
}
748-
749-

src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4381,7 +4381,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
43814381
if (pingSend) {
43824382
uint64_t nonce = 0;
43834383
while (nonce == 0) {
4384-
RAND_bytes((unsigned char*)&nonce, sizeof(nonce));
4384+
GetRandBytes((unsigned char*)&nonce, sizeof(nonce));
43854385
}
43864386
pto->fPingQueued = false;
43874387
pto->nPingUsecStart = GetTimeMicros();

src/net.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ void CNode::PushVersion()
555555
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
556556
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
557557
CAddress addrMe = GetLocalAddress(&addr);
558-
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
558+
GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
559559
if (fLogIPs)
560560
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id);
561561
else
@@ -1961,7 +1961,7 @@ bool CAddrDB::Write(const CAddrMan& addr)
19611961
{
19621962
// Generate random temporary filename
19631963
unsigned short randv = 0;
1964-
RAND_bytes((unsigned char *)&randv, sizeof(randv));
1964+
GetRandBytes((unsigned char*)&randv, sizeof(randv));
19651965
std::string tmpfn = strprintf("peers.dat.%04x", randv);
19661966

19671967
// serialize addresses, checksum data up to that point, then append csum

src/net.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "mruset.h"
1414
#include "netbase.h"
1515
#include "protocol.h"
16+
#include "random.h"
1617
#include "sync.h"
1718
#include "uint256.h"
1819
#include "util.h"
@@ -26,7 +27,6 @@
2627

2728
#include <boost/foreach.hpp>
2829
#include <boost/signals2/signal.hpp>
29-
#include <openssl/rand.h>
3030

3131
class CAddrMan;
3232
class CBlockIndex;

src/random.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright (c) 2009-2010 Satoshi Nakamoto
2+
// Copyright (c) 2009-2014 The Bitcoin developers
3+
// Distributed under the MIT/X11 software license, see the accompanying
4+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
#include "random.h"
7+
8+
#ifdef WIN32
9+
#include "compat.h" // for Windows API
10+
#endif
11+
#include "util.h" // for LogPrint()
12+
13+
#ifndef WIN32
14+
#include <sys/time.h>
15+
#endif
16+
17+
#include <openssl/crypto.h>
18+
#include <openssl/err.h>
19+
#include <openssl/rand.h>
20+
21+
static inline int64_t GetPerformanceCounter()
22+
{
23+
int64_t nCounter = 0;
24+
#ifdef WIN32
25+
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
26+
#else
27+
timeval t;
28+
gettimeofday(&t, NULL);
29+
nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
30+
#endif
31+
return nCounter;
32+
}
33+
34+
void RandAddSeed()
35+
{
36+
// Seed with CPU performance counter
37+
int64_t nCounter = GetPerformanceCounter();
38+
RAND_add(&nCounter, sizeof(nCounter), 1.5);
39+
OPENSSL_cleanse((void*)&nCounter, sizeof(nCounter));
40+
}
41+
42+
void RandAddSeedPerfmon()
43+
{
44+
RandAddSeed();
45+
46+
// This can take up to 2 seconds, so only do it every 10 minutes
47+
static int64_t nLastPerfmon;
48+
if (GetTime() < nLastPerfmon + 10 * 60)
49+
return;
50+
nLastPerfmon = GetTime();
51+
52+
#ifdef WIN32
53+
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
54+
// Seed with the entire set of perfmon data
55+
std::vector <unsigned char> vData(250000,0);
56+
long ret = 0;
57+
unsigned long nSize = 0;
58+
const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
59+
while (true)
60+
{
61+
nSize = vData.size();
62+
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
63+
if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
64+
break;
65+
vData.resize(std::max((vData.size()*3)/2, nMaxSize)); // Grow size of buffer exponentially
66+
}
67+
RegCloseKey(HKEY_PERFORMANCE_DATA);
68+
if (ret == ERROR_SUCCESS)
69+
{
70+
RAND_add(begin_ptr(vData), nSize, nSize/100.0);
71+
OPENSSL_cleanse(begin_ptr(vData), nSize);
72+
LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
73+
} else {
74+
static bool warned = false; // Warn only once
75+
if (!warned)
76+
{
77+
LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
78+
warned = true;
79+
}
80+
}
81+
#endif
82+
}
83+
84+
bool GetRandBytes(unsigned char *buf, int num)
85+
{
86+
if (RAND_bytes(buf, num) != 1) {
87+
LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
88+
return false;
89+
}
90+
return true;
91+
}
92+
93+
uint64_t GetRand(uint64_t nMax)
94+
{
95+
if (nMax == 0)
96+
return 0;
97+
98+
// The range of the random source must be a multiple of the modulus
99+
// to give every possible output value an equal possibility
100+
uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
101+
uint64_t nRand = 0;
102+
do {
103+
GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
104+
} while (nRand >= nRange);
105+
return (nRand % nMax);
106+
}
107+
108+
int GetRandInt(int nMax)
109+
{
110+
return GetRand(nMax);
111+
}
112+
113+
uint256 GetRandHash()
114+
{
115+
uint256 hash;
116+
GetRandBytes((unsigned char*)&hash, sizeof(hash));
117+
return hash;
118+
}
119+
120+
uint32_t insecure_rand_Rz = 11;
121+
uint32_t insecure_rand_Rw = 11;
122+
void seed_insecure_rand(bool fDeterministic)
123+
{
124+
// The seed values have some unlikely fixed points which we avoid.
125+
if(fDeterministic)
126+
{
127+
insecure_rand_Rz = insecure_rand_Rw = 11;
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+
}

src/random.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) 2009-2010 Satoshi Nakamoto
2+
// Copyright (c) 2009-2014 The Bitcoin developers
3+
// Distributed under the MIT/X11 software license, see the accompanying
4+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
#ifndef BITCOIN_RANDOM_H
7+
#define BITCOIN_RANDOM_H
8+
9+
#include "uint256.h"
10+
11+
#include <stdint.h>
12+
13+
/**
14+
* Seed OpenSSL PRNG with additional entropy data
15+
*/
16+
void RandAddSeed();
17+
void RandAddSeedPerfmon();
18+
19+
/**
20+
* Functions to gather random data via the OpenSSL PRNG
21+
*/
22+
bool GetRandBytes(unsigned char *buf, int num);
23+
uint64_t GetRand(uint64_t nMax);
24+
int GetRandInt(int nMax);
25+
uint256 GetRandHash();
26+
27+
/**
28+
* Seed insecure_rand using the random pool.
29+
* @param Deterministic Use a determinstic seed
30+
*/
31+
void seed_insecure_rand(bool fDeterministic = false);
32+
33+
/**
34+
* MWC RNG of George Marsaglia
35+
* This is intended to be fast. It has a period of 2^59.3, though the
36+
* least significant 16 bits only have a period of about 2^30.1.
37+
*
38+
* @return random value
39+
*/
40+
extern uint32_t insecure_rand_Rz;
41+
extern uint32_t insecure_rand_Rw;
42+
static inline uint32_t insecure_rand(void)
43+
{
44+
insecure_rand_Rz = 36969 * (insecure_rand_Rz & 65535) + (insecure_rand_Rz >> 16);
45+
insecure_rand_Rw = 18000 * (insecure_rand_Rw & 65535) + (insecure_rand_Rw >> 16);
46+
return (insecure_rand_Rw << 16) + insecure_rand_Rz;
47+
}
48+
49+
#endif // BITCOIN_RANDOM_H

src/rpcserver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ void StartRPCThreads()
532532
(mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
533533
{
534534
unsigned char rand_pwd[32];
535-
RAND_bytes(rand_pwd, 32);
535+
GetRandBytes(rand_pwd, 32);
536536
string strWhatAmI = "To use bitcoind";
537537
if (mapArgs.count("-server"))
538538
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");

0 commit comments

Comments
 (0)