This commit is contained in:
Escanor Liones 2021-11-01 15:31:38 -07:00 committed by GitHub
commit c4daf148da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 154 additions and 4 deletions

View file

@ -171,12 +171,19 @@ AC_ARG_WITH([system-univalue],
[system_univalue=$withval],
[system_univalue=no]
)
AC_ARG_ENABLE([zmq],
[AS_HELP_STRING([--disable-zmq],
[disable ZMQ notifications])],
[use_zmq=$enableval],
[use_zmq=yes])
AC_ARG_ENABLE([rdseed],
[AS_HELP_STRING([--disable-rdseed],
[disable rdseed entropy (default is yes where available)])],
[use_rdseed=$enableval],
[use_rdseed=yes])
AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], [])
AC_ARG_ENABLE(man,
@ -861,6 +868,23 @@ else
fi
fi
dnl Use rdseed to gather entropy
if test "x$use_rdseed" = "xyes"; then
dnl Only enable rdseed on the compiler when targeting x86
case $host in
*x86*)
CXXFLAGS="$CXXFLAGS -mrdseed"
;;
*i686*)
CXXFLAGS="$CXXFLAGS -mrdseed"
;;
*)
use_rdseed="no"
esac
fi
save_CXXFLAGS="${CXXFLAGS}"
CXXFLAGS="${CXXFLAGS} ${CRYPTO_CFLAGS} ${SSL_CFLAGS}"
AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT

58
src/lowlevel.h Normal file
View file

@ -0,0 +1,58 @@
// Copyright (c) 2021 The Dogecoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//Here be dragons, wizards, witches and master of the dark arts.
//Careful thou who wonders 'round these parts without magic spells,
//mana potions and doggy treats...especially magical doggy treats.
//Only define this header on x86
#if ( defined(i386) || defined(__i386) || defined(__i386__) || \
defined( __386) || defined(_X86_) || defined( _M_I86) || \
defined(__i386__) || defined(__X86__) || defined(__x86_64) )
#ifndef LOWLEVEL_H
#define LOWLEVEL_H
#define LOWLEVEL_USE_RDSEED (1)
#if ( defined(_WIN32) || defined(WIN32) || \
defined(__WIN32__) || defined(__NT__) )
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#include <cpuid.h>
#ifndef bit_RDSEED
#define bit_RDSEED (1 << 18)
#endif
/* To address compatibility issues with MacOS, given the lacking implementation
* of intrinsics we here implement rdseed in byte code so that we may use it
* anywhere the ISA extension permits it.
*
* See: https://software.intel.com/content/www/us/en/develop/articles/the-drng-library-and-manual.html
* You will find this function definition at:
* libdrng-1.0.tar.gz: https://software.intel.com/file/469237/download
*/
#if defined(__APPLE__)
# define _rdseed16_step(x) ({ unsigned char err; asm volatile(".byte 0x66; .byte 0x0f; .byte 0xc7; .byte 0xf8; setc %1":"=a"(*x), "=qm"(err)); err; })
# define _rdseed32_step(x) ({ unsigned char err; asm volatile(".byte 0x0f; .byte 0xc7; .byte 0xf8; setc %1":"=a"(*x), "=qm"(err)); err; })
#endif
/* \union Useful for buffers that will need to be hashed
* where data gather comes from different int types.
*/
union block_512bits {
char byte[64];
unsigned char ubyte[64];
uint16_t word[32];
uint32_t dword[16];
uint64_t qword[8];
unsigned long long int ulli[8];
};
#endif /*LOWLEVEL_H*/
#endif /*Detect x86*/

View file

@ -23,6 +23,7 @@
#include <openssl/err.h>
#include <openssl/rand.h>
#include <lowlevel.h>
static void RandFailure()
{
@ -129,20 +130,87 @@ void GetRandBytes(unsigned char* buf, int num)
}
}
/* /fn int getRDSEED( uint64_t *buff, int num)
* /brief Use Intel's SP 800-90B & C compliant Hardware implemented
* instruction to add entropy to the pool use to create keys.
*
* For details, see: https://software.intel.com/content/www/us/en/develop/blogs/the-difference-between-rdrand-and-rdseed.html
*
* /param buff Buffer to fill with random bits.
* /param num Number of 64-bit words to write to buffer.
* /return Returns 1 if the hardware returned a valid stream of random numbers, 0 otherwise.
*
*/
int getRDSEED( uint64_t *buff, uint32_t num){
//Initialize state to 0, or failed.
uint32_t cumulativeStatus = 0;
#ifdef LOWELEVEL_USE_RDSEEED
//Check to see if the processor running this code has
//this Instruction. Most Intel/AMD CPUs after 2015
//should have this instruction.
uint32_t level, eax, ebx, ecx, edx;
//Level where the RDSEED feature is described
level = 1;
//Extract feature vector
__get_cpuid(level, &eax, &ebx, &ecx, &edx);
//Check if RDSEED exists on this processor
if( (ecx & bit_RDSEED) == bit_RDSEED ) {
//Re-initialize value to 1, or success
cumulativeStatus = 1;
for( uint32_t kk = 0; kk < num; kk++){
//Get RBG data
uint32_t rng_high, rng_low;
int32_t status1 = _rdseed32_step( &rng_low );
int32_t status2 = _rdseed32_step( &rng_high );
//Place values into a 64-bit register
uint64_t temp = rng_high;
temp <<= 32;
temp += rng_low;
//Store into buffer
buff[kk] = temp;
//Update status value.
//cumulativeStatus will be 1 iff all iterations are 1.
cumulativeStatus &= status1 & status2;
}
}
#endif /*LOWLEVEL_USE_RDSEED*/
return cumulativeStatus;
}
void GetStrongRandBytes(unsigned char* out, int num)
{
assert(num <= 32);
assert(num <= 64);
CSHA512 hasher;
unsigned char buf[64];
// First source: OpenSSL's RNG
RandAddSeedPerfmon();
GetRandBytes(buf, 32);
hasher.Write(buf, 32);
GetRandBytes(buf, 64);
hasher.Write(buf, 64);
// Second source: OS RNG
GetOSRand(buf);
hasher.Write(buf, 32);
hasher.Write(buf, 64);
//Third Source: Intel's NIST SP 800-90B & C compliant RBG
//if available, use it.
#ifdef LOWLEVEL_H
block_512bits buf2;
if ( getRDSEED(buf2.qword, 8) == 1 )
hasher.Write(buf2.ubyte, 64);
#endif
// Produce output
hasher.Finalize(buf);