Changeset View
Changeset View
Standalone View
Standalone View
src/random.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <random.h> | #include <random.h> | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
#include <compat.h> // for Windows API | #include <compat.h> // for Windows API | ||||
#include <wincrypt.h> | #include <wincrypt.h> | ||||
#endif | #endif | ||||
#include <compat/cpuid.h> | |||||
#include <crypto/sha512.h> | #include <crypto/sha512.h> | ||||
#include <logging.h> // for LogPrintf() | #include <logging.h> // for LogPrintf() | ||||
#include <randomenv.h> | #include <randomenv.h> | ||||
#include <support/allocators/secure.h> | #include <support/allocators/secure.h> | ||||
#include <support/cleanse.h> | #include <support/cleanse.h> | ||||
#include <sync.h> // for Mutex | #include <sync.h> // for Mutex | ||||
#include <util/time.h> // for GetTime() | #include <util/time.h> // for GetTime() | ||||
Show All 23 Lines | |||||
#if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) | #if defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) | ||||
#include <sys/random.h> | #include <sys/random.h> | ||||
#endif | #endif | ||||
#ifdef HAVE_SYSCTL_ARND | #ifdef HAVE_SYSCTL_ARND | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <util/strencodings.h> // for ARRAYLEN | #include <util/strencodings.h> // for ARRAYLEN | ||||
#endif | #endif | ||||
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) | |||||
#include <cpuid.h> | |||||
#endif | |||||
[[noreturn]] static void RandFailure() { | [[noreturn]] static void RandFailure() { | ||||
LogPrintf("Failed to read randomness, aborting\n"); | LogPrintf("Failed to read randomness, aborting\n"); | ||||
std::abort(); | std::abort(); | ||||
} | } | ||||
static inline int64_t GetPerformanceCounter() noexcept { | static inline int64_t GetPerformanceCounter() noexcept { | ||||
// Read the hardware time stamp counter when available. | // Read the hardware time stamp counter when available. | ||||
// See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information. | // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information. | ||||
Show All 11 Lines | #elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__)) | ||||
return (r2 << 32) | r1; | return (r2 << 32) | r1; | ||||
#else | #else | ||||
// Fall back to using C++11 clock (usually microsecond or nanosecond | // Fall back to using C++11 clock (usually microsecond or nanosecond | ||||
// precision) | // precision) | ||||
return std::chrono::high_resolution_clock::now().time_since_epoch().count(); | return std::chrono::high_resolution_clock::now().time_since_epoch().count(); | ||||
#endif | #endif | ||||
} | } | ||||
#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) | #ifdef HAVE_GETCPUID | ||||
static bool g_rdrand_supported = false; | static bool g_rdrand_supported = false; | ||||
static bool g_rdseed_supported = false; | static bool g_rdseed_supported = false; | ||||
static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; | static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; | ||||
static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000; | static constexpr uint32_t CPUID_F7_EBX_RDSEED = 0x00040000; | ||||
#ifdef bit_RDRND | #ifdef bit_RDRND | ||||
static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, | static_assert(CPUID_F1_ECX_RDRAND == bit_RDRND, | ||||
"Unexpected value for bit_RDRND"); | "Unexpected value for bit_RDRND"); | ||||
#endif | #endif | ||||
#ifdef bit_RDSEED | #ifdef bit_RDSEED | ||||
static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, | static_assert(CPUID_F7_EBX_RDSEED == bit_RDSEED, | ||||
"Unexpected value for bit_RDSEED"); | "Unexpected value for bit_RDSEED"); | ||||
#endif | #endif | ||||
static void inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t &a, | |||||
uint32_t &b, uint32_t &c, uint32_t &d) { | |||||
// We can't use __get_cpuid as it doesn't support subleafs. | |||||
#ifdef __GNUC__ | |||||
__cpuid_count(leaf, subleaf, a, b, c, d); | |||||
#else | |||||
__asm__("cpuid" | |||||
: "=a"(a), "=b"(b), "=c"(c), "=d"(d) | |||||
: "0"(leaf), "2"(subleaf)); | |||||
#endif | |||||
} | |||||
static void InitHardwareRand() { | static void InitHardwareRand() { | ||||
uint32_t eax, ebx, ecx, edx; | uint32_t eax, ebx, ecx, edx; | ||||
GetCPUID(1, 0, eax, ebx, ecx, edx); | GetCPUID(1, 0, eax, ebx, ecx, edx); | ||||
if (ecx & CPUID_F1_ECX_RDRAND) { | if (ecx & CPUID_F1_ECX_RDRAND) { | ||||
g_rdrand_supported = true; | g_rdrand_supported = true; | ||||
} | } | ||||
GetCPUID(7, 0, eax, ebx, ecx, edx); | GetCPUID(7, 0, eax, ebx, ecx, edx); | ||||
▲ Show 20 Lines • Show All 704 Lines • Show Last 20 Lines |