mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Improve pool seeding during startup:
* When starting up, we no longer rely just on the standard system RNG to generate entropy: we attempt to squeeze some from the execution state, and to recover any entropy that we had previously stored. * When shutting down, if sufficient entropy has been accumulated attempt to store it for future use.
This commit is contained in:
committed by
Tom Ritchford
parent
382a16ff07
commit
84e618b3f2
@@ -62,6 +62,7 @@
|
|||||||
#include <ripple/validators/make_Manager.h>
|
#include <ripple/validators/make_Manager.h>
|
||||||
#include <ripple/unity/git_id.h>
|
#include <ripple/unity/git_id.h>
|
||||||
#include <ripple/websocket/MakeServer.h>
|
#include <ripple/websocket/MakeServer.h>
|
||||||
|
#include <ripple/crypto/RandomNumbers.h>
|
||||||
#include <beast/asio/io_latency_probe.h>
|
#include <beast/asio/io_latency_probe.h>
|
||||||
#include <beast/module/core/text/LexicalCast.h>
|
#include <beast/module/core/text/LexicalCast.h>
|
||||||
#include <beast/module/core/thread/DeadlineTimer.h>
|
#include <beast/module/core/thread/DeadlineTimer.h>
|
||||||
@@ -286,6 +287,7 @@ public:
|
|||||||
std::unique_ptr <Validations> mValidations;
|
std::unique_ptr <Validations> mValidations;
|
||||||
std::unique_ptr <LoadManager> m_loadManager;
|
std::unique_ptr <LoadManager> m_loadManager;
|
||||||
beast::DeadlineTimer m_sweepTimer;
|
beast::DeadlineTimer m_sweepTimer;
|
||||||
|
beast::DeadlineTimer m_entropyTimer;
|
||||||
|
|
||||||
std::unique_ptr <DatabaseCon> mRpcDB;
|
std::unique_ptr <DatabaseCon> mRpcDB;
|
||||||
std::unique_ptr <DatabaseCon> mTxnDB;
|
std::unique_ptr <DatabaseCon> mTxnDB;
|
||||||
@@ -408,6 +410,8 @@ public:
|
|||||||
|
|
||||||
, m_sweepTimer (this)
|
, m_sweepTimer (this)
|
||||||
|
|
||||||
|
, m_entropyTimer (this)
|
||||||
|
|
||||||
, m_signals(get_io_service(), SIGINT)
|
, m_signals(get_io_service(), SIGINT)
|
||||||
|
|
||||||
, m_resolver (ResolverAsio::New (get_io_service(), m_logs.journal("Resolver")))
|
, m_resolver (ResolverAsio::New (get_io_service(), m_logs.journal("Resolver")))
|
||||||
@@ -857,6 +861,7 @@ public:
|
|||||||
m_journal.info << "Application starting. Build is " << gitCommitID();
|
m_journal.info << "Application starting. Build is " << gitCommitID();
|
||||||
|
|
||||||
m_sweepTimer.setExpiration (10);
|
m_sweepTimer.setExpiration (10);
|
||||||
|
m_entropyTimer.setRecurringExpiration (300);
|
||||||
|
|
||||||
m_io_latency_sampler.start();
|
m_io_latency_sampler.start();
|
||||||
|
|
||||||
@@ -887,6 +892,8 @@ public:
|
|||||||
|
|
||||||
m_sweepTimer.cancel ();
|
m_sweepTimer.cancel ();
|
||||||
|
|
||||||
|
m_entropyTimer.cancel ();
|
||||||
|
|
||||||
mValidations->flush ();
|
mValidations->flush ();
|
||||||
|
|
||||||
RippleAddress::clearCache ();
|
RippleAddress::clearCache ();
|
||||||
@@ -952,6 +959,12 @@ public:
|
|||||||
|
|
||||||
void onDeadlineTimer (beast::DeadlineTimer& timer)
|
void onDeadlineTimer (beast::DeadlineTimer& timer)
|
||||||
{
|
{
|
||||||
|
if (timer == m_entropyTimer)
|
||||||
|
{
|
||||||
|
add_entropy (nullptr, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (timer == m_sweepTimer)
|
if (timer == m_sweepTimer)
|
||||||
{
|
{
|
||||||
// VFALCO TODO Move all this into doSweep
|
// VFALCO TODO Move all this into doSweep
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#if defined(BEAST_LINUX) || defined(BEAST_MAC) || defined(BEAST_BSD)
|
#if defined(BEAST_LINUX) || defined(BEAST_MAC) || defined(BEAST_BSD)
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
@@ -67,6 +68,13 @@ void setupServer ()
|
|||||||
getApp().setup ();
|
getApp().setup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::filesystem::path
|
||||||
|
getEntropyFile()
|
||||||
|
{
|
||||||
|
return boost::filesystem::path (
|
||||||
|
getConfig().legacy("database_path")) / "random.seed";
|
||||||
|
}
|
||||||
|
|
||||||
void startServer ()
|
void startServer ()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -93,7 +101,11 @@ void startServer ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getApp().run (); // Blocks till we get a stop RPC.
|
// Block until we get a stop RPC.
|
||||||
|
getApp().run ();
|
||||||
|
|
||||||
|
// Try to write out some entropy to use the next time we start.
|
||||||
|
stir_entropy (getEntropyFile ().string ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void printHelp (const po::options_description& desc)
|
void printHelp (const po::options_description& desc)
|
||||||
@@ -258,8 +270,29 @@ int run (int argc, char** argv)
|
|||||||
po::positional_options_description p;
|
po::positional_options_description p;
|
||||||
p.add ("parameters", -1);
|
p.add ("parameters", -1);
|
||||||
|
|
||||||
// Seed the RNG early
|
{
|
||||||
add_entropy ();
|
// We want to seed the RNG early. We acquire a small amount of
|
||||||
|
// questionable quality entropy from the current time and our
|
||||||
|
// environment block which will get stirred into the RNG pool
|
||||||
|
// along with high-quality entropy from the system.
|
||||||
|
struct entropy_t
|
||||||
|
{
|
||||||
|
std::uint64_t timestamp;
|
||||||
|
std::size_t tid;
|
||||||
|
std::uintptr_t ptr[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
auto entropy = std::make_unique<entropy_t> ();
|
||||||
|
|
||||||
|
entropy->timestamp = beast::Time::currentTimeMillis ();
|
||||||
|
entropy->tid = std::hash <std::thread::id>() (std::this_thread::get_id ());
|
||||||
|
entropy->ptr[0] = reinterpret_cast<std::uintptr_t>(entropy.get ());
|
||||||
|
entropy->ptr[1] = reinterpret_cast<std::uintptr_t>(&argc);
|
||||||
|
entropy->ptr[2] = reinterpret_cast<std::uintptr_t>(argv);
|
||||||
|
entropy->ptr[3] = reinterpret_cast<std::uintptr_t>(argv[0]);
|
||||||
|
|
||||||
|
add_entropy (entropy.get (), sizeof (entropy_t));
|
||||||
|
}
|
||||||
|
|
||||||
if (!iResult)
|
if (!iResult)
|
||||||
{
|
{
|
||||||
@@ -346,6 +379,9 @@ int run (int argc, char** argv)
|
|||||||
getConfig ().RUN_STANDALONE = true;
|
getConfig ().RUN_STANDALONE = true;
|
||||||
getConfig ().LEDGER_HISTORY = 0;
|
getConfig ().LEDGER_HISTORY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use any previously available entropy to stir the pool
|
||||||
|
stir_entropy (getEntropyFile ().string ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count ("start")) getConfig ().START_UP = Config::FRESH;
|
if (vm.count ("start")) getConfig ().START_UP = Config::FRESH;
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ public:
|
|||||||
/** Returns the full path and filename of the debug log file. */
|
/** Returns the full path and filename of the debug log file. */
|
||||||
boost::filesystem::path getDebugLogFile () const;
|
boost::filesystem::path getDebugLogFile () const;
|
||||||
|
|
||||||
|
/** Returns the full path and filename of the entropy seed file. */
|
||||||
|
boost::filesystem::path getEntropyFile () const;
|
||||||
|
|
||||||
// DEPRECATED
|
// DEPRECATED
|
||||||
boost::filesystem::path CONFIG_FILE; // used by UniqueNodeList
|
boost::filesystem::path CONFIG_FILE; // used by UniqueNodeList
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -20,10 +20,21 @@
|
|||||||
#ifndef RIPPLE_CRYPTO_RANDOMNUMBERS_H_INCLUDED
|
#ifndef RIPPLE_CRYPTO_RANDOMNUMBERS_H_INCLUDED
|
||||||
#define RIPPLE_CRYPTO_RANDOMNUMBERS_H_INCLUDED
|
#define RIPPLE_CRYPTO_RANDOMNUMBERS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
/** Stir the RNG using entropy from stable storage.
|
||||||
|
|
||||||
|
@param file the file from which state is loaded and into
|
||||||
|
which it is saved.
|
||||||
|
|
||||||
|
@return true if the pool has sufficient entropy; false
|
||||||
|
otherwise.
|
||||||
|
*/
|
||||||
|
bool stir_entropy (std::string file);
|
||||||
|
|
||||||
/** Adds entropy to the RNG pool.
|
/** Adds entropy to the RNG pool.
|
||||||
|
|
||||||
@param buffer An optional buffer that contains random data.
|
@param buffer An optional buffer that contains random data.
|
||||||
|
|||||||
@@ -26,6 +26,18 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
bool stir_entropy (std::string file)
|
||||||
|
{
|
||||||
|
// First, we attempt to stir any existing saved entropy
|
||||||
|
// into the pool: no use letting it go to waste.
|
||||||
|
RAND_load_file (file.c_str (), 1024);
|
||||||
|
|
||||||
|
// And now, we extract some entropy out, and save it for
|
||||||
|
// the future. If the quality of the entropy isn't great
|
||||||
|
// then we let the user know.
|
||||||
|
return RAND_write_file (file.c_str ()) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
void add_entropy (void* buffer, int count)
|
void add_entropy (void* buffer, int count)
|
||||||
{
|
{
|
||||||
assert (buffer == nullptr || count != 0);
|
assert (buffer == nullptr || count != 0);
|
||||||
@@ -35,7 +47,7 @@ void add_entropy (void* buffer, int count)
|
|||||||
if (buffer != nullptr && count != 0)
|
if (buffer != nullptr && count != 0)
|
||||||
RAND_add (buffer, count, count / 4.0);
|
RAND_add (buffer, count, count / 4.0);
|
||||||
|
|
||||||
// Try to add a bit more entropy from the system
|
// And try to add some entropy from the system
|
||||||
unsigned int rdbuf[32];
|
unsigned int rdbuf[32];
|
||||||
|
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
|
|||||||
Reference in New Issue
Block a user