mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-26 11:13:23 -03:00
Seed RNG with precision timestamps on receipt of net messages.
This commit is contained in:
parent
33c103e2fe
commit
02d8c56a18
3 changed files with 51 additions and 0 deletions
10
src/net.cpp
10
src/net.cpp
|
@ -16,6 +16,7 @@
|
||||||
#include <crypto/sha256.h>
|
#include <crypto/sha256.h>
|
||||||
#include <netbase.h>
|
#include <netbase.h>
|
||||||
#include <net_permissions.h>
|
#include <net_permissions.h>
|
||||||
|
#include <random.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
#include <ui_interface.h>
|
#include <ui_interface.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
@ -445,6 +446,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||||
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false, block_relay_only);
|
CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false, block_relay_only);
|
||||||
pnode->AddRef();
|
pnode->AddRef();
|
||||||
|
|
||||||
|
// We're making a new connection, harvest entropy from the time (and our peer count)
|
||||||
|
RandAddEvent((uint32_t)id);
|
||||||
|
|
||||||
return pnode;
|
return pnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,6 +697,9 @@ CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageSta
|
||||||
msg.m_message_size = hdr.nMessageSize;
|
msg.m_message_size = hdr.nMessageSize;
|
||||||
msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
|
msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
|
||||||
|
|
||||||
|
// We just received a message off the wire, harvest entropy from the time (and the message checksum)
|
||||||
|
RandAddEvent(ReadLE32(hash.begin()));
|
||||||
|
|
||||||
msg.m_valid_checksum = (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) == 0);
|
msg.m_valid_checksum = (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) == 0);
|
||||||
if (!msg.m_valid_checksum) {
|
if (!msg.m_valid_checksum) {
|
||||||
LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
|
LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
|
||||||
|
@ -1017,6 +1024,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
vNodes.push_back(pnode);
|
vNodes.push_back(pnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We received a new connection, harvest entropy from the time (and our peer count)
|
||||||
|
RandAddEvent((uint32_t)id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConnman::DisconnectNodes()
|
void CConnman::DisconnectNodes()
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
|
|
||||||
#include <compat/cpuid.h>
|
#include <compat/cpuid.h>
|
||||||
|
#include <crypto/sha256.h>
|
||||||
#include <crypto/sha512.h>
|
#include <crypto/sha512.h>
|
||||||
#include <support/cleanse.h>
|
#include <support/cleanse.h>
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -449,6 +450,23 @@ static void SeedFast(CSHA512& hasher) noexcept
|
||||||
SeedTimestamp(hasher);
|
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
|
static void SeedSlow(CSHA512& hasher) noexcept
|
||||||
{
|
{
|
||||||
unsigned char buffer[32];
|
unsigned char buffer[32];
|
||||||
|
@ -460,6 +478,9 @@ static void SeedSlow(CSHA512& hasher) noexcept
|
||||||
GetOSRand(buffer);
|
GetOSRand(buffer);
|
||||||
hasher.Write(buffer, sizeof(buffer));
|
hasher.Write(buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
// Add the events hasher into the mix
|
||||||
|
SeedEvents(hasher);
|
||||||
|
|
||||||
// High-precision timestamp.
|
// High-precision timestamp.
|
||||||
//
|
//
|
||||||
// Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
|
// Note that we also commit to a timestamp in the Fast seeder, so we indirectly commit to a
|
||||||
|
@ -485,6 +506,9 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng)
|
||||||
// High-precision timestamp
|
// High-precision timestamp
|
||||||
SeedTimestamp(hasher);
|
SeedTimestamp(hasher);
|
||||||
|
|
||||||
|
// Add the events hasher into the mix
|
||||||
|
SeedEvents(hasher);
|
||||||
|
|
||||||
// Dynamic environment data (performance monitoring, ...)
|
// Dynamic environment data (performance monitoring, ...)
|
||||||
auto old_size = hasher.Size();
|
auto old_size = hasher.Size();
|
||||||
RandAddDynamicEnv(hasher);
|
RandAddDynamicEnv(hasher);
|
||||||
|
@ -553,6 +577,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 GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
|
||||||
void RandAddPeriodic() { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
|
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};
|
bool g_mock_deterministic_tests{false};
|
||||||
|
|
||||||
uint64_t GetRand(uint64_t nMax) noexcept
|
uint64_t GetRand(uint64_t nMax) noexcept
|
||||||
|
|
|
@ -89,6 +89,14 @@ void GetStrongRandBytes(unsigned char* buf, int num) noexcept;
|
||||||
*/
|
*/
|
||||||
void RandAddPeriodic();
|
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
|
* Fast randomness source. This is seeded once with secure random data, but
|
||||||
* is completely deterministic and does not gather more entropy after that.
|
* is completely deterministic and does not gather more entropy after that.
|
||||||
|
|
Loading…
Add table
Reference in a new issue