Always require OS randomness when generating secret keys

This commit is contained in:
Pieter Wuille
2016-04-16 12:25:12 +02:00
parent a80de15113
commit fa2637a3be
7 changed files with 59 additions and 17 deletions

View File

@@ -5,9 +5,11 @@
#include "random.h"
#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "serialize.h" // for begin_ptr(vec)
#include "util.h" // for LogPrint()
@@ -43,7 +45,7 @@ void RandAddSeed()
memory_cleanse((void*)&nCounter, sizeof(nCounter));
}
void RandAddSeedPerfmon()
static void RandAddSeedPerfmon()
{
RandAddSeed();
@@ -83,6 +85,29 @@ void RandAddSeedPerfmon()
#endif
}
/** Get 32 bytes of system entropy. */
static void GetOSRand(unsigned char *ent32)
{
#ifdef WIN32
HCRYPTPROV hProvider;
int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
assert(ret);
ret = CryptGenRandom(hProvider, 32, ent32);
assert(ret);
CryptReleaseContext(hProvider, 0);
#else
int f = open("/dev/urandom", O_RDONLY);
assert(f != -1);
int have = 0;
do {
ssize_t n = read(f, ent32 + have, 32 - have);
assert(n > 0 && n <= 32 - have);
have += n;
} while (have < 32);
close(f);
#endif
}
void GetRandBytes(unsigned char* buf, int num)
{
if (RAND_bytes(buf, num) != 1) {
@@ -91,6 +116,27 @@ void GetRandBytes(unsigned char* buf, int num)
}
}
void GetStrongRandBytes(unsigned char* out, int num)
{
assert(num <= 32);
CSHA512 hasher;
unsigned char buf[64];
// First source: OpenSSL's RNG
RandAddSeedPerfmon();
GetRandBytes(buf, 32);
hasher.Write(buf, 32);
// Second source: OS RNG
GetOSRand(buf);
hasher.Write(buf, 32);
// Produce output
hasher.Finalize(buf);
memcpy(out, buf, num);
memory_cleanse(buf, 64);
}
uint64_t GetRand(uint64_t nMax)
{
if (nMax == 0)