mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-08-31 18:41:08 +02:00
Gather additional entropy from the environment
This based on code by Gregory Maxwell.
This commit is contained in:
@@ -3,8 +3,13 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include <config/bitcoin-config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <randomenv.h>
|
#include <randomenv.h>
|
||||||
|
|
||||||
|
#include <clientversion.h>
|
||||||
#include <crypto/sha512.h>
|
#include <crypto/sha512.h>
|
||||||
#include <support/cleanse.h>
|
#include <support/cleanse.h>
|
||||||
#include <util/time.h> // for GetTime()
|
#include <util/time.h> // for GetTime()
|
||||||
@@ -14,14 +19,21 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <climits>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
#include <sys/types.h> // must go before a number of other headers
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef __MACH__
|
#ifdef __MACH__
|
||||||
@@ -29,6 +41,12 @@
|
|||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if HAVE_DECL_GETIFADDRS
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Necessary on some platforms
|
||||||
|
extern char** environ;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -85,6 +103,53 @@ CSHA512& operator<<(CSHA512& hasher, const T& data) {
|
|||||||
return hasher;
|
return hasher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
void AddSockaddr(CSHA512& hasher, const struct sockaddr *addr)
|
||||||
|
{
|
||||||
|
if (addr == nullptr) return;
|
||||||
|
switch (addr->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in));
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
hasher.Write((const unsigned char*)addr, sizeof(sockaddr_in6));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
hasher.Write((const unsigned char*)&addr->sa_family, sizeof(addr->sa_family));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddFile(CSHA512& hasher, const char *path)
|
||||||
|
{
|
||||||
|
struct stat sb = {};
|
||||||
|
int f = open(path, O_RDONLY);
|
||||||
|
size_t total = 0;
|
||||||
|
if (f != -1) {
|
||||||
|
unsigned char fbuf[4096];
|
||||||
|
int n;
|
||||||
|
hasher.Write((const unsigned char*)&f, sizeof(f));
|
||||||
|
if (fstat(f, &sb) == 0) hasher << sb;
|
||||||
|
do {
|
||||||
|
n = read(f, fbuf, sizeof(fbuf));
|
||||||
|
if (n > 0) hasher.Write(fbuf, n);
|
||||||
|
total += n;
|
||||||
|
/* not bothering with EINTR handling. */
|
||||||
|
} while (n == sizeof(fbuf) && total < 1048576); // Read only the first 1 Mbyte
|
||||||
|
close(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddPath(CSHA512& hasher, const char *path)
|
||||||
|
{
|
||||||
|
struct stat sb = {};
|
||||||
|
if (stat(path, &sb) == 0) {
|
||||||
|
hasher.Write((const unsigned char*)path, strlen(path) + 1);
|
||||||
|
hasher << sb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void RandAddDynamicEnv(CSHA512& hasher)
|
void RandAddDynamicEnv(CSHA512& hasher)
|
||||||
@@ -99,18 +164,18 @@ void RandAddDynamicEnv(CSHA512& hasher)
|
|||||||
#else
|
#else
|
||||||
# ifndef __MACH__
|
# ifndef __MACH__
|
||||||
// On non-MacOS systems, use various clock_gettime() calls.
|
// On non-MacOS systems, use various clock_gettime() calls.
|
||||||
struct timespec ts;
|
struct timespec ts = {};
|
||||||
# ifdef CLOCK_MONOTONIC
|
# ifdef CLOCK_MONOTONIC
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
hasher << ts.tv_sec << ts.tv_nsec;
|
hasher << ts;
|
||||||
# endif
|
# endif
|
||||||
# ifdef CLOCK_REALTIME
|
# ifdef CLOCK_REALTIME
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
hasher << ts.tv_sec << ts.tv_nsec;
|
hasher << ts;
|
||||||
# endif
|
# endif
|
||||||
# ifdef CLOCK_BOOTTIME
|
# ifdef CLOCK_BOOTTIME
|
||||||
clock_gettime(CLOCK_BOOTTIME, &ts);
|
clock_gettime(CLOCK_BOOTTIME, &ts);
|
||||||
hasher << ts.tv_sec << ts.tv_nsec;
|
hasher << ts;
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
// On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
|
// On MacOS use mach_absolute_time (number of CPU ticks since boot) as a replacement for CLOCK_MONOTONIC,
|
||||||
@@ -118,29 +183,138 @@ void RandAddDynamicEnv(CSHA512& hasher)
|
|||||||
hasher << mach_absolute_time();
|
hasher << mach_absolute_time();
|
||||||
// From https://gist.github.com/jbenet/1087739
|
// From https://gist.github.com/jbenet/1087739
|
||||||
clock_serv_t cclock;
|
clock_serv_t cclock;
|
||||||
mach_timespec_t mts;
|
mach_timespec_t mts = {};
|
||||||
if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time(cclock, &mts) == KERN_SUCCESS) {
|
if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock) == KERN_SUCCESS && clock_get_time(cclock, &mts) == KERN_SUCCESS) {
|
||||||
hasher << mts.tv_sec << mts.tv_nsec;
|
hasher << mts;
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
// gettimeofday is available on all UNIX systems, but only has microsecond precision.
|
// gettimeofday is available on all UNIX systems, but only has microsecond precision.
|
||||||
struct timeval tv;
|
struct timeval tv = {};
|
||||||
gettimeofday(&tv, nullptr);
|
gettimeofday(&tv, nullptr);
|
||||||
hasher << tv.tv_sec << tv.tv_usec;
|
hasher << tv;
|
||||||
#endif
|
#endif
|
||||||
// Probably redundant, but also use all the clocks C++11 provides:
|
// Probably redundant, but also use all the clocks C++11 provides:
|
||||||
hasher << std::chrono::system_clock::now().time_since_epoch().count();
|
hasher << std::chrono::system_clock::now().time_since_epoch().count();
|
||||||
hasher << std::chrono::steady_clock::now().time_since_epoch().count();
|
hasher << std::chrono::steady_clock::now().time_since_epoch().count();
|
||||||
hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
// Current resource usage.
|
||||||
|
struct rusage usage = {};
|
||||||
|
if (getrusage(RUSAGE_SELF, &usage) == 0) hasher << usage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
AddFile(hasher, "/proc/diskstats");
|
||||||
|
AddFile(hasher, "/proc/vmstat");
|
||||||
|
AddFile(hasher, "/proc/schedstat");
|
||||||
|
AddFile(hasher, "/proc/zoneinfo");
|
||||||
|
AddFile(hasher, "/proc/meminfo");
|
||||||
|
AddFile(hasher, "/proc/softirqs");
|
||||||
|
AddFile(hasher, "/proc/stat");
|
||||||
|
AddFile(hasher, "/proc/self/schedstat");
|
||||||
|
AddFile(hasher, "/proc/self/status");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Stack and heap location
|
||||||
|
void* addr = malloc(4097);
|
||||||
|
hasher << &addr << addr;
|
||||||
|
free(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandAddStaticEnv(CSHA512& hasher)
|
void RandAddStaticEnv(CSHA512& hasher)
|
||||||
{
|
{
|
||||||
|
// Some compile-time static properties
|
||||||
|
hasher << (CHAR_MIN < 0) << sizeof(void*) << sizeof(long) << sizeof(int);
|
||||||
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||||
|
hasher << __GNUC__ << __GNUC_MINOR__ << __GNUC_PATCHLEVEL__;
|
||||||
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
hasher << _MSC_VER;
|
||||||
|
#endif
|
||||||
|
hasher << __cplusplus;
|
||||||
|
#ifdef _XOPEN_VERSION
|
||||||
|
hasher << _XOPEN_VERSION;
|
||||||
|
#endif
|
||||||
|
#ifdef __VERSION__
|
||||||
|
const char* COMPILER_VERSION = __VERSION__;
|
||||||
|
hasher.Write((const unsigned char*)COMPILER_VERSION, strlen(COMPILER_VERSION) + 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Bitcoin client version
|
||||||
|
hasher << CLIENT_VERSION;
|
||||||
|
|
||||||
|
// Memory locations
|
||||||
|
hasher << &hasher << &RandAddStaticEnv << &malloc << &errno << &environ;
|
||||||
|
|
||||||
|
// Hostname
|
||||||
|
char hname[256];
|
||||||
|
if (gethostname(hname, 256) == 0) {
|
||||||
|
hasher.Write((const unsigned char*)hname, strnlen(hname, 256));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_DECL_GETIFADDRS
|
||||||
|
// Network interfaces
|
||||||
|
struct ifaddrs *ifad = NULL;
|
||||||
|
getifaddrs(&ifad);
|
||||||
|
struct ifaddrs *ifit = ifad;
|
||||||
|
while (ifit != NULL) {
|
||||||
|
hasher.Write((const unsigned char*)&ifit, sizeof(ifit));
|
||||||
|
hasher.Write((const unsigned char*)ifit->ifa_name, strlen(ifit->ifa_name) + 1);
|
||||||
|
hasher.Write((const unsigned char*)&ifit->ifa_flags, sizeof(ifit->ifa_flags));
|
||||||
|
AddSockaddr(hasher, ifit->ifa_addr);
|
||||||
|
AddSockaddr(hasher, ifit->ifa_netmask);
|
||||||
|
AddSockaddr(hasher, ifit->ifa_dstaddr);
|
||||||
|
ifit = ifit->ifa_next;
|
||||||
|
}
|
||||||
|
freeifaddrs(ifad);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
// UNIX kernel information
|
||||||
|
struct utsname name;
|
||||||
|
if (uname(&name) != -1) {
|
||||||
|
hasher.Write((const unsigned char*)&name.sysname, strlen(name.sysname) + 1);
|
||||||
|
hasher.Write((const unsigned char*)&name.nodename, strlen(name.nodename) + 1);
|
||||||
|
hasher.Write((const unsigned char*)&name.release, strlen(name.release) + 1);
|
||||||
|
hasher.Write((const unsigned char*)&name.version, strlen(name.version) + 1);
|
||||||
|
hasher.Write((const unsigned char*)&name.machine, strlen(name.machine) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Path and filesystem provided data */
|
||||||
|
AddPath(hasher, "/");
|
||||||
|
AddPath(hasher, ".");
|
||||||
|
AddPath(hasher, "/tmp");
|
||||||
|
AddPath(hasher, "/home");
|
||||||
|
AddPath(hasher, "/proc");
|
||||||
|
#ifdef __linux__
|
||||||
|
AddFile(hasher, "/proc/cmdline");
|
||||||
|
AddFile(hasher, "/proc/cpuinfo");
|
||||||
|
AddFile(hasher, "/proc/version");
|
||||||
|
#endif
|
||||||
|
AddFile(hasher, "/etc/passwd");
|
||||||
|
AddFile(hasher, "/etc/group");
|
||||||
|
AddFile(hasher, "/etc/hosts");
|
||||||
|
AddFile(hasher, "/etc/resolv.conf");
|
||||||
|
AddFile(hasher, "/etc/timezone");
|
||||||
|
AddFile(hasher, "/etc/localtime");
|
||||||
|
|
||||||
|
/* TODO: sysctl's for OSX to fetch information not available from /proc */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Env variables
|
||||||
|
if (environ) {
|
||||||
|
for (size_t i = 0; environ[i]; ++i) {
|
||||||
|
hasher.Write((const unsigned char*)environ[i], strlen(environ[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process, thread, user, session, group, ... ids.
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
hasher << GetCurrentProcessId() << GetCurrentThreadId();
|
hasher << GetCurrentProcessId() << GetCurrentThreadId();
|
||||||
#else
|
#else
|
||||||
hasher << getpid();
|
hasher << getpid() << getppid() << getsid(0) << getpgid(0) << getuid() << geteuid() << getgid() << getegid();
|
||||||
#endif
|
#endif
|
||||||
hasher << std::this_thread::get_id();
|
hasher << std::this_thread::get_id();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user