2014-06-26 14:41:53 +02:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2015-12-13 14:51:43 +01:00
// Copyright (c) 2009-2015 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2014-06-26 14:41:53 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2020-03-19 23:46:56 +01:00
# include <random.h>
2014-06-26 14:41:53 +02:00
2020-03-19 23:46:56 +01:00
# include <crypto/sha512.h>
# include <support/cleanse.h>
2014-06-26 14:41:53 +02:00
# ifdef WIN32
2020-03-19 23:46:56 +01:00
# include <compat.h> // for Windows API
2016-05-30 15:46:16 +02:00
# include <wincrypt.h>
2014-06-26 14:41:53 +02:00
# endif
2018-05-17 18:25:09 +02:00
# include <logging.h> // for LogPrint()
2017-11-08 21:28:35 +01:00
# include <sync.h> // for WAIT_LOCK
2018-05-17 18:25:09 +02:00
# include <utiltime.h> // for GetTime()
2014-06-26 14:41:53 +02:00
2016-05-30 15:46:16 +02:00
# include <stdlib.h>
2017-05-09 19:10:23 +02:00
# include <chrono>
# include <thread>
2014-09-14 12:43:56 +02:00
2014-06-26 14:41:53 +02:00
# ifndef WIN32
2018-05-17 18:25:09 +02:00
# include <fcntl.h>
2014-06-26 14:41:53 +02:00
# include <sys/time.h>
# endif
2014-09-14 12:43:56 +02:00
2017-03-01 12:40:06 +01:00
# ifdef HAVE_SYS_GETRANDOM
# include <sys/syscall.h>
# include <linux/random.h>
# endif
2017-08-07 17:13:49 +02:00
# if defined(HAVE_GETENTROPY) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX))
2017-03-01 12:40:06 +01:00
# include <unistd.h>
# endif
2017-08-07 17:13:49 +02:00
# if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
# include <sys/random.h>
# endif
2017-03-01 12:40:06 +01:00
# ifdef HAVE_SYSCTL_ARND
2018-05-24 15:04:35 +02:00
# include <utilstrencodings.h> // for ARRAYLEN
2017-03-01 12:40:06 +01:00
# include <sys/sysctl.h>
# endif
2017-05-09 19:13:45 +02:00
# include <mutex>
2017-07-16 20:49:45 +02:00
# if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
# include <cpuid.h>
# endif
2014-06-26 14:41:53 +02:00
# include <openssl/err.h>
# include <openssl/rand.h>
2017-08-22 09:36:06 +02:00
[[noreturn]] static void RandFailure ( )
2016-05-30 15:46:16 +02:00
{
LogPrintf ( " Failed to read randomness, aborting \n " ) ;
2017-08-22 09:36:06 +02:00
std : : abort ( ) ;
2016-05-30 15:46:16 +02:00
}
2014-06-26 14:41:53 +02:00
static inline int64_t GetPerformanceCounter ( )
{
2017-05-09 19:10:23 +02:00
// Read the hardware time stamp counter when available.
// See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
return __rdtsc ( ) ;
# elif !defined(_MSC_VER) && defined(__i386__)
uint64_t r = 0 ;
__asm__ volatile ( " rdtsc " : " =A " ( r ) ) ; // Constrain the r variable to the eax:edx pair.
return r ;
# elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
uint64_t r1 = 0 , r2 = 0 ;
__asm__ volatile ( " rdtsc " : " =a " ( r1 ) , " =d " ( r2 ) ) ; // Constrain r1 to rax and r2 to rdx.
return ( r2 < < 32 ) | r1 ;
2014-06-26 14:41:53 +02:00
# else
2017-05-09 19:10:23 +02:00
// Fall back to using C++11 clock (usually microsecond or nanosecond precision)
return std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) . count ( ) ;
2014-06-26 14:41:53 +02:00
# endif
}
2017-06-14 15:22:08 +02:00
# if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
static std : : atomic < bool > hwrand_initialized { false } ;
static bool rdrand_supported = false ;
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000 ;
static void RDRandInit ( )
{
2017-07-16 20:49:45 +02:00
uint32_t eax , ebx , ecx , edx ;
if ( __get_cpuid ( 1 , & eax , & ebx , & ecx , & edx ) & & ( ecx & CPUID_F1_ECX_RDRAND ) ) {
LogPrintf ( " Using RdRand as an additional entropy source \n " ) ;
2017-06-14 15:22:08 +02:00
rdrand_supported = true ;
}
hwrand_initialized . store ( true ) ;
}
# else
static void RDRandInit ( ) { }
# endif
static bool GetHWRand ( unsigned char * ent32 ) {
# if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
assert ( hwrand_initialized . load ( std : : memory_order_relaxed ) ) ;
if ( rdrand_supported ) {
uint8_t ok ;
// Not all assemblers support the rdrand instruction, write it in hex.
# ifdef __i386__
for ( int iter = 0 ; iter < 4 ; + + iter ) {
uint32_t r1 , r2 ;
__asm__ volatile ( " .byte 0x0f, 0xc7, 0xf0; " // rdrand %eax
" .byte 0x0f, 0xc7, 0xf2; " // rdrand %edx
" setc %2 " :
" =a " ( r1 ) , " =d " ( r2 ) , " =q " ( ok ) : : " cc " ) ;
if ( ! ok ) return false ;
WriteLE32 ( ent32 + 8 * iter , r1 ) ;
WriteLE32 ( ent32 + 8 * iter + 4 , r2 ) ;
}
# else
uint64_t r1 , r2 , r3 , r4 ;
__asm__ volatile ( " .byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax
" 0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx
" 0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx
" 0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx
" setc %4 " :
" =a " ( r1 ) , " =b " ( r2 ) , " =c " ( r3 ) , " =d " ( r4 ) , " =q " ( ok ) : : " cc " ) ;
if ( ! ok ) return false ;
WriteLE64 ( ent32 , r1 ) ;
WriteLE64 ( ent32 + 8 , r2 ) ;
WriteLE64 ( ent32 + 16 , r3 ) ;
WriteLE64 ( ent32 + 24 , r4 ) ;
# endif
return true ;
}
# endif
return false ;
}
2014-06-26 14:41:53 +02:00
void RandAddSeed ( )
{
// Seed with CPU performance counter
int64_t nCounter = GetPerformanceCounter ( ) ;
RAND_add ( & nCounter , sizeof ( nCounter ) , 1.5 ) ;
2015-01-21 01:23:25 +01:00
memory_cleanse ( ( void * ) & nCounter , sizeof ( nCounter ) ) ;
2014-06-26 14:41:53 +02:00
}
2016-05-30 15:46:16 +02:00
static void RandAddSeedPerfmon ( )
2014-06-26 14:41:53 +02:00
{
RandAddSeed ( ) ;
2015-02-25 03:03:53 +01:00
# ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
2014-06-26 14:41:53 +02:00
// This can take up to 2 seconds, so only do it every 10 minutes
static int64_t nLastPerfmon ;
if ( GetTime ( ) < nLastPerfmon + 10 * 60 )
return ;
nLastPerfmon = GetTime ( ) ;
2014-09-19 19:21:46 +02:00
std : : vector < unsigned char > vData ( 250000 , 0 ) ;
2014-06-26 14:41:53 +02:00
long ret = 0 ;
unsigned long nSize = 0 ;
const size_t nMaxSize = 10000000 ; // Bail out at more than 10MB of performance data
2014-09-19 19:21:46 +02:00
while ( true ) {
2014-06-26 14:41:53 +02:00
nSize = vData . size ( ) ;
2019-08-06 05:08:33 +02:00
ret = RegQueryValueExA ( HKEY_PERFORMANCE_DATA , " Global " , nullptr , nullptr , vData . data ( ) , & nSize ) ;
2014-06-26 14:41:53 +02:00
if ( ret ! = ERROR_MORE_DATA | | vData . size ( ) > = nMaxSize )
break ;
2014-09-19 19:21:46 +02:00
vData . resize ( std : : max ( ( vData . size ( ) * 3 ) / 2 , nMaxSize ) ) ; // Grow size of buffer exponentially
2014-06-26 14:41:53 +02:00
}
RegCloseKey ( HKEY_PERFORMANCE_DATA ) ;
2014-09-19 19:21:46 +02:00
if ( ret = = ERROR_SUCCESS ) {
2016-12-13 12:20:26 +01:00
RAND_add ( vData . data ( ) , nSize , nSize / 100.0 ) ;
memory_cleanse ( vData . data ( ) , nSize ) ;
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : RANDOM , " %s: %lu bytes \n " , __func__ , nSize ) ;
2014-06-26 14:41:53 +02:00
} else {
static bool warned = false ; // Warn only once
2014-09-19 19:21:46 +02:00
if ( ! warned ) {
2014-06-26 14:41:53 +02:00
LogPrintf ( " %s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i \n " , __func__ , ret ) ;
warned = true ;
}
}
# endif
}
2017-03-01 12:40:06 +01:00
# ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
* compatible way to get cryptographic randomness on UNIX - ish platforms .
*/
2018-05-04 22:42:39 +02:00
static void GetDevURandom ( unsigned char * ent32 )
2017-03-01 12:40:06 +01:00
{
int f = open ( " /dev/urandom " , O_RDONLY ) ;
if ( f = = - 1 ) {
RandFailure ( ) ;
}
int have = 0 ;
do {
ssize_t n = read ( f , ent32 + have , NUM_OS_RANDOM_BYTES - have ) ;
if ( n < = 0 | | n + have > NUM_OS_RANDOM_BYTES ) {
2017-07-17 13:10:50 +02:00
close ( f ) ;
2017-03-01 12:40:06 +01:00
RandFailure ( ) ;
}
have + = n ;
} while ( have < NUM_OS_RANDOM_BYTES ) ;
close ( f ) ;
}
# endif
2016-05-30 15:46:16 +02:00
/** Get 32 bytes of system entropy. */
2017-03-01 12:40:06 +01:00
void GetOSRand ( unsigned char * ent32 )
2016-05-30 15:46:16 +02:00
{
2017-03-01 12:40:06 +01:00
# if defined(WIN32)
2016-05-30 15:46:16 +02:00
HCRYPTPROV hProvider ;
2019-08-06 05:08:33 +02:00
int ret = CryptAcquireContextW ( & hProvider , nullptr , nullptr , PROV_RSA_FULL , CRYPT_VERIFYCONTEXT ) ;
2016-05-30 15:46:16 +02:00
if ( ! ret ) {
RandFailure ( ) ;
}
2017-03-01 12:40:06 +01:00
ret = CryptGenRandom ( hProvider , NUM_OS_RANDOM_BYTES , ent32 ) ;
2016-05-30 15:46:16 +02:00
if ( ! ret ) {
RandFailure ( ) ;
}
CryptReleaseContext ( hProvider , 0 ) ;
2017-03-01 12:40:06 +01:00
# elif defined(HAVE_SYS_GETRANDOM)
/* Linux. From the getrandom(2) man page:
* " If the urandom source has been initialized, reads of up to 256 bytes
* will always return as many bytes as requested and will not be
* interrupted by signals . "
*/
int rv = syscall ( SYS_getrandom , ent32 , NUM_OS_RANDOM_BYTES , 0 ) ;
if ( rv ! = NUM_OS_RANDOM_BYTES ) {
if ( rv < 0 & & errno = = ENOSYS ) {
/* Fallback for kernel <3.17: the return value will be -1 and errno
* ENOSYS if the syscall is not available , in that case fall back
* to / dev / urandom .
*/
GetDevURandom ( ent32 ) ;
} else {
RandFailure ( ) ;
}
}
2017-07-18 08:24:40 +02:00
# elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
2017-03-01 12:40:06 +01:00
/* On OpenBSD this can return up to 256 bytes of entropy, will return an
* error if more are requested .
* The call cannot return less than the requested number of bytes .
2017-07-18 08:24:40 +02:00
getentropy is explicitly limited to openbsd here , as a similar ( but not
the same ) function may exist on other platforms via glibc .
2017-03-01 12:40:06 +01:00
*/
if ( getentropy ( ent32 , NUM_OS_RANDOM_BYTES ) ! = 0 ) {
2016-05-30 15:46:16 +02:00
RandFailure ( ) ;
}
2017-08-07 17:13:49 +02:00
# elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)
// We need a fallback for OSX < 10.12
2019-08-06 05:08:33 +02:00
if ( & getentropy ! = nullptr ) {
2017-08-07 17:13:49 +02:00
if ( getentropy ( ent32 , NUM_OS_RANDOM_BYTES ) ! = 0 ) {
RandFailure ( ) ;
}
} else {
GetDevURandom ( ent32 ) ;
}
2017-03-01 12:40:06 +01:00
# elif defined(HAVE_SYSCTL_ARND)
/* FreeBSD and similar. It is possible for the call to return less
* bytes than requested , so need to read in a loop .
*/
static const int name [ 2 ] = { CTL_KERN , KERN_ARND } ;
2016-05-30 15:46:16 +02:00
int have = 0 ;
do {
2017-03-01 12:40:06 +01:00
size_t len = NUM_OS_RANDOM_BYTES - have ;
2019-08-06 05:08:33 +02:00
if ( sysctl ( name , ARRAYLEN ( name ) , ent32 + have , & len , nullptr , 0 ) ! = 0 ) {
2016-05-30 15:46:16 +02:00
RandFailure ( ) ;
}
2017-03-01 12:40:06 +01:00
have + = len ;
} while ( have < NUM_OS_RANDOM_BYTES ) ;
# else
/* Fall back to /dev/urandom if there is no specific method implemented to
* get system entropy for this OS .
*/
GetDevURandom ( ent32 ) ;
2016-05-30 15:46:16 +02:00
# endif
}
2014-11-07 13:42:52 +01:00
void GetRandBytes ( unsigned char * buf , int num )
2014-06-26 14:41:53 +02:00
{
if ( RAND_bytes ( buf , num ) ! = 1 ) {
2016-05-30 15:46:16 +02:00
RandFailure ( ) ;
2014-06-26 14:41:53 +02:00
}
}
2017-05-23 17:53:00 +02:00
static void AddDataToRng ( void * data , size_t len ) ;
void RandAddSeedSleep ( )
{
int64_t nPerfCounter1 = GetPerformanceCounter ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
int64_t nPerfCounter2 = GetPerformanceCounter ( ) ;
// Combine with and update state
AddDataToRng ( & nPerfCounter1 , sizeof ( nPerfCounter1 ) ) ;
AddDataToRng ( & nPerfCounter2 , sizeof ( nPerfCounter2 ) ) ;
memory_cleanse ( & nPerfCounter1 , sizeof ( nPerfCounter1 ) ) ;
memory_cleanse ( & nPerfCounter2 , sizeof ( nPerfCounter2 ) ) ;
}
2021-06-04 21:26:33 +02:00
static Mutex cs_rng_state ;
2017-05-09 19:13:45 +02:00
static unsigned char rng_state [ 32 ] = { 0 } ;
static uint64_t rng_counter = 0 ;
2017-05-23 17:53:00 +02:00
static void AddDataToRng ( void * data , size_t len ) {
CSHA512 hasher ;
hasher . Write ( ( const unsigned char * ) & len , sizeof ( len ) ) ;
hasher . Write ( ( const unsigned char * ) data , len ) ;
unsigned char buf [ 64 ] ;
{
2017-11-08 21:28:35 +01:00
WAIT_LOCK ( cs_rng_state , lock ) ;
2017-05-23 17:53:00 +02:00
hasher . Write ( rng_state , sizeof ( rng_state ) ) ;
hasher . Write ( ( const unsigned char * ) & rng_counter , sizeof ( rng_counter ) ) ;
+ + rng_counter ;
hasher . Finalize ( buf ) ;
memcpy ( rng_state , buf + 32 , 32 ) ;
}
memory_cleanse ( buf , 64 ) ;
}
2016-05-30 15:46:16 +02:00
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 ) ;
2017-06-14 15:22:08 +02:00
// Third source: HW RNG, if available.
if ( GetHWRand ( buf ) ) {
hasher . Write ( buf , 32 ) ;
}
2017-05-09 19:13:45 +02:00
// Combine with and update state
{
2017-11-08 21:28:35 +01:00
WAIT_LOCK ( cs_rng_state , lock ) ;
2017-05-09 19:13:45 +02:00
hasher . Write ( rng_state , sizeof ( rng_state ) ) ;
hasher . Write ( ( const unsigned char * ) & rng_counter , sizeof ( rng_counter ) ) ;
+ + rng_counter ;
hasher . Finalize ( buf ) ;
memcpy ( rng_state , buf + 32 , 32 ) ;
}
2016-05-30 15:46:16 +02:00
// Produce output
memcpy ( out , buf , num ) ;
memory_cleanse ( buf , 64 ) ;
}
2019-02-04 12:11:34 +01:00
bool g_mock_deterministic_tests { false } ;
2014-06-26 14:41:53 +02:00
uint64_t GetRand ( uint64_t nMax )
{
if ( nMax = = 0 )
return 0 ;
2020-04-13 22:40:38 +02:00
// This will later conflict with bitcoin#14955. Simply take the bitcoin version as resolution and pass g_mock_deterministic_tests into FastRandomContext
2019-02-04 12:11:34 +01:00
if ( g_mock_deterministic_tests ) {
return FastRandomContext ( true ) . randrange ( nMax ) ;
}
2014-06-26 14:41:53 +02:00
// The range of the random source must be a multiple of the modulus
// to give every possible output value an equal possibility
uint64_t nRange = ( std : : numeric_limits < uint64_t > : : max ( ) / nMax ) * nMax ;
uint64_t nRand = 0 ;
do {
GetRandBytes ( ( unsigned char * ) & nRand , sizeof ( nRand ) ) ;
} while ( nRand > = nRange ) ;
return ( nRand % nMax ) ;
}
2020-04-08 14:27:07 +02:00
std : : chrono : : microseconds GetRandMicros ( std : : chrono : : microseconds duration_max ) noexcept
{
return std : : chrono : : microseconds { GetRand ( duration_max . count ( ) ) } ;
}
2014-06-26 14:41:53 +02:00
int GetRandInt ( int nMax )
{
return GetRand ( nMax ) ;
}
uint256 GetRandHash ( )
{
uint256 hash ;
GetRandBytes ( ( unsigned char * ) & hash , sizeof ( hash ) ) ;
return hash ;
}
2019-01-09 07:30:19 +01:00
bool GetRandBool ( double rate )
{
if ( rate = = 0.0 ) {
return false ;
}
const uint64_t v = 100000000 ;
uint64_t r = GetRand ( v + 1 ) ;
return r < = v * rate ;
}
2017-04-24 14:02:12 +02:00
void FastRandomContext : : RandomSeed ( )
2014-06-26 14:41:53 +02:00
{
2017-04-24 14:02:12 +02:00
uint256 seed = GetRandHash ( ) ;
rng . SetKey ( seed . begin ( ) , 32 ) ;
requires_seed = false ;
}
2017-06-07 23:59:41 +02:00
uint256 FastRandomContext : : rand256 ( )
{
if ( bytebuf_size < 32 ) {
FillByteBuffer ( ) ;
}
uint256 ret ;
memcpy ( ret . begin ( ) , bytebuf + 64 - bytebuf_size , 32 ) ;
bytebuf_size - = 32 ;
return ret ;
}
std : : vector < unsigned char > FastRandomContext : : randbytes ( size_t len )
{
std : : vector < unsigned char > ret ( len ) ;
if ( len > 0 ) {
2019-05-10 09:26:02 +02:00
rng . Keystream ( & ret [ 0 ] , len ) ;
2017-06-07 23:59:41 +02:00
}
return ret ;
}
2017-04-24 14:02:12 +02:00
FastRandomContext : : FastRandomContext ( const uint256 & seed ) : requires_seed ( false ) , bytebuf_size ( 0 ) , bitbuf_size ( 0 )
{
rng . SetKey ( seed . begin ( ) , 32 ) ;
2014-06-26 14:41:53 +02:00
}
2017-03-01 12:40:06 +01:00
bool Random_SanityCheck ( )
{
2017-05-09 19:10:23 +02:00
uint64_t start = GetPerformanceCounter ( ) ;
2017-03-01 12:40:06 +01:00
/* This does not measure the quality of randomness, but it does test that
* OSRandom ( ) overwrites all 32 bytes of the output given a maximum
* number of tries .
*/
static const ssize_t MAX_TRIES = 1024 ;
uint8_t data [ NUM_OS_RANDOM_BYTES ] ;
bool overwritten [ NUM_OS_RANDOM_BYTES ] = { } ; /* Tracks which bytes have been overwritten at least once */
int num_overwritten ;
int tries = 0 ;
/* Loop until all bytes have been overwritten at least once, or max number tries reached */
do {
memset ( data , 0 , NUM_OS_RANDOM_BYTES ) ;
GetOSRand ( data ) ;
for ( int x = 0 ; x < NUM_OS_RANDOM_BYTES ; + + x ) {
overwritten [ x ] | = ( data [ x ] ! = 0 ) ;
}
num_overwritten = 0 ;
for ( int x = 0 ; x < NUM_OS_RANDOM_BYTES ; + + x ) {
if ( overwritten [ x ] ) {
num_overwritten + = 1 ;
}
}
tries + = 1 ;
} while ( num_overwritten < NUM_OS_RANDOM_BYTES & & tries < MAX_TRIES ) ;
2017-05-09 19:10:23 +02:00
if ( num_overwritten ! = NUM_OS_RANDOM_BYTES ) return false ; /* If this failed, bailed out after too many tries */
// Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
uint64_t stop = GetPerformanceCounter ( ) ;
if ( stop = = start ) return false ;
// We called GetPerformanceCounter. Use it as entropy.
RAND_add ( ( const unsigned char * ) & start , sizeof ( start ) , 1 ) ;
RAND_add ( ( const unsigned char * ) & stop , sizeof ( stop ) , 1 ) ;
return true ;
2017-03-01 12:40:06 +01:00
}
2017-04-24 14:02:12 +02:00
FastRandomContext : : FastRandomContext ( bool fDeterministic ) : requires_seed ( ! fDeterministic ) , bytebuf_size ( 0 ) , bitbuf_size ( 0 )
{
if ( ! fDeterministic ) {
return ;
}
uint256 seed ;
rng . SetKey ( seed . begin ( ) , 32 ) ;
}
2017-06-14 15:22:08 +02:00
void RandomInit ( )
{
RDRandInit ( ) ;
}