Skip to content

Commit

Permalink
Seed RNG with precision timestamps on receipt of net messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBlueMatt authored and Fuzzbawls committed Apr 14, 2021
1 parent 7d6ddcb commit f363ea9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "netbase.h"
#include "netmessagemaker.h"
#include "primitives/transaction.h"
#include "random.h"
#include "scheduler.h"
#include "validation.h"

Expand Down Expand Up @@ -379,6 +380,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char* pszDest, bool fCo
pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
pnode->AddRef();

// We're making a new connection, harvest entropy from the time (and our peer count)
RandAddEvent((uint32_t)id);

return pnode;
} else if (!proxyConnectionFailed) {
// If connecting to the node failed, and failure is not caused by a problem connecting to
Expand Down Expand Up @@ -1067,6 +1071,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
LOCK(cs_vNodes);
vNodes.push_back(pnode);
}

// We received a new connection, harvest entropy from the time (and our peer count)
RandAddEvent((uint32_t)id);
}

void CConnman::ThreadSocketHandler()
Expand Down
33 changes: 33 additions & 0 deletions src/random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "allocators.h"
#include "compat/cpuid.h"
#include "crypto/sha256.h"
#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
Expand Down Expand Up @@ -488,6 +489,23 @@ static void SeedFast(CSHA512& hasher) noexcept
SeedTimestamp(hasher);
}

// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
// since we want it to be fast as network peers may be able to trigger it repeatedly.
static Mutex events_mutex;
static CSHA256 events_hasher;
static void SeedEvents(CSHA512& hasher)
{
LOCK(events_mutex);

unsigned char events_hash[32];
events_hasher.Finalize(events_hash);
hasher.Write(events_hash, 32);

// Re-initialize the hasher with the finalized state to use later.
events_hasher.Reset();
events_hasher.Write(events_hash, 32);
}

static void SeedSlow(CSHA512& hasher) noexcept
{
unsigned char buffer[32];
Expand All @@ -503,6 +521,9 @@ static void SeedSlow(CSHA512& hasher) noexcept
RAND_bytes(buffer, sizeof(buffer));
hasher.Write(buffer, sizeof(buffer));

// Add the events hasher into the mix
SeedEvents(hasher);

// High-precision timestamp.
//
// Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
Expand All @@ -528,6 +549,9 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
// High-precision timestamp
SeedTimestamp(hasher);

// Add the events hasher into the mix
SeedEvents(hasher);

// Dynamic environment data (performance monitoring, ...)
RandAddDynamicEnv(hasher);

Expand Down Expand Up @@ -600,6 +624,15 @@ void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNG
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
void RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }

void RandAddEvent(const uint32_t event_info) {
LOCK(events_mutex);
events_hasher.Write((const unsigned char *)&event_info, sizeof(event_info));
// Get the low four bytes of the performance counter. This translates to roughly the
// subsecond part.
uint32_t perfcounter = (GetPerformanceCounter() & 0xffffffff);
events_hasher.Write((const unsigned char*)&perfcounter, sizeof(perfcounter));
}

bool g_mock_deterministic_tests{false};

uint64_t GetRand(uint64_t nMax) noexcept
Expand Down
8 changes: 8 additions & 0 deletions src/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
*/
void RandAddPeriodic();

/**
* Gathers entropy from the low bits of the time at which events occur. Should
* be called with a uint32_t describing the event at the time an event occurs.
*
* Thread-safe.
*/
void RandAddEvent(const uint32_t event_info);

/**
* Fast randomness source. This is seeded once with secure random data, but
* is completely deterministic and does not gather more entropy after that.
Expand Down

0 comments on commit f363ea9

Please sign in to comment.