mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Refactor free functions into RandomNumbers
This commit is contained in:
@@ -148,5 +148,6 @@ namespace boost {
|
||||
|
||||
#include "types/ripple_UInt256.h"
|
||||
#include "utility/ripple_HashUtilities.h" // requires UInt256
|
||||
#include "types/ripple_HashTables.h"
|
||||
|
||||
#endif
|
||||
|
||||
95
modules/ripple_basics/types/ripple_HashTables.h
Normal file
95
modules/ripple_basics/types/ripple_HashTables.h
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef RIPPLE_HASHMAPS_H
|
||||
#define RIPPLE_HASHMAPS_H
|
||||
|
||||
/** Management helper of hash functions used in hash map containers.
|
||||
|
||||
The nonce is used to prevent attackers from feeding carefully crafted
|
||||
inputs in order to cause denegerate hash map data structures. This is
|
||||
done by seeding the hashing function with a random number generated
|
||||
at program startup.
|
||||
*/
|
||||
// VFALCO: TODO derive from Uncopyable
|
||||
class HashMaps // : beast::Uncopayble
|
||||
{
|
||||
public:
|
||||
/** Retrieve the singleton.
|
||||
|
||||
@return The global instance of the singleton.
|
||||
*/
|
||||
static HashMaps const& getInstance ()
|
||||
{
|
||||
static HashMaps instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Instantiate a nonce for a type.
|
||||
|
||||
@note This may be used during program initialization
|
||||
to avoid concurrency issues. Only C++11 provides thread
|
||||
safety guarantees for function-local static objects.
|
||||
*/
|
||||
template <class T>
|
||||
void initializeNonce () const
|
||||
{
|
||||
getNonceHolder <T> ();
|
||||
}
|
||||
|
||||
/** Get the nonce for a type.
|
||||
|
||||
The nonces are generated when they are first used.
|
||||
This code is thread safe.
|
||||
*/
|
||||
template <class T>
|
||||
T getNonce () const
|
||||
{
|
||||
return getNonceHolder <T> ().getNonce ();
|
||||
}
|
||||
|
||||
private:
|
||||
HashMaps ()
|
||||
{
|
||||
}
|
||||
|
||||
~HashMaps ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates and holds a nonce for a type.
|
||||
*/
|
||||
template <class T>
|
||||
class NonceHolder
|
||||
{
|
||||
public:
|
||||
NonceHolder ()
|
||||
{
|
||||
// VFALCO: NOTE, this can be dangerous if T is an object type
|
||||
RandomNumbers::getInstance ().fill (&m_nonce);
|
||||
}
|
||||
|
||||
inline T getNonce () const
|
||||
{
|
||||
return m_nonce;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_nonce;
|
||||
};
|
||||
|
||||
/** Retrieve the nonce holder for a type.
|
||||
|
||||
@note This routine will be called concurrently.
|
||||
*/
|
||||
template <class T>
|
||||
NonceHolder <T> const& getNonceHolder ()
|
||||
{
|
||||
static NonceHolder <T> nonceHolder;
|
||||
|
||||
return nonceHolder;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -16,26 +16,72 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
void getRand(unsigned char *buf, int num)
|
||||
RandomNumbers::RandomNumbers ()
|
||||
: m_initialized (false)
|
||||
{
|
||||
}
|
||||
|
||||
RandomNumbers::~RandomNumbers ()
|
||||
{
|
||||
}
|
||||
|
||||
bool RandomNumbers::initialize ()
|
||||
{
|
||||
assert (!m_initialized);
|
||||
|
||||
bool success = platformAddEntropy ();
|
||||
|
||||
if (success)
|
||||
m_initialized = true;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void RandomNumbers::fillBytes (void* destinationBuffer, int numberOfBytes)
|
||||
{
|
||||
// VFALCO: NOTE this assert is here to remind us that the code is not yet
|
||||
// thread safe.
|
||||
assert (m_initialized);
|
||||
|
||||
// VFALCO: NOTE When a spinlock is available in beast, use it here.
|
||||
if (! m_initialized)
|
||||
{
|
||||
if (! initialize ())
|
||||
{
|
||||
char const* message = "Unable to add system entropy";
|
||||
std::cerr << message << std::endl;
|
||||
throw std::runtime_error (message);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PURIFY
|
||||
memset(buf, 0, num);
|
||||
memset (destinationBuffer, 0, numberOfBytes);
|
||||
#endif
|
||||
if (RAND_bytes(buf, num) != 1)
|
||||
|
||||
if (RAND_bytes (reinterpret_cast <unsigned char*> (destinationBuffer), numberOfBytes) != 1)
|
||||
{
|
||||
assert(false);
|
||||
throw std::runtime_error("Entropy pool not seeded");
|
||||
|
||||
throw std::runtime_error ("Entropy pool not seeded");
|
||||
}
|
||||
}
|
||||
|
||||
RandomNumbers& RandomNumbers::getInstance ()
|
||||
{
|
||||
static RandomNumbers instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO: TODO replace WIN32 macro with VFLIB_WIN32
|
||||
// VFALCO: TODO replace WIN32 macro
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
bool AddSystemEntropy()
|
||||
{ // Get entropy from the Windows crypto provider
|
||||
// Get entropy from the Windows crypto provider
|
||||
bool RandomNumbers::platformAddEntropy ()
|
||||
{
|
||||
char name[512], rand[128];
|
||||
DWORD count = 500;
|
||||
HCRYPTPROV cryptoHandle;
|
||||
@@ -73,12 +119,7 @@ bool AddSystemEntropy()
|
||||
|
||||
#else
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
bool AddSystemEntropy()
|
||||
bool RandomNumbers::platformAddEntropy ()
|
||||
{
|
||||
char rand[128];
|
||||
std::ifstream reader;
|
||||
@@ -117,7 +158,7 @@ bool AddSystemEntropy()
|
||||
// - The user (asking the user to fix the system clock if the first two disagree)
|
||||
//
|
||||
|
||||
void RandAddSeedPerfmon()
|
||||
void RandomNumbers::platformAddPerformanceMonitorEntropy ()
|
||||
{
|
||||
// VFALCO: This is how we simulate local functions
|
||||
struct
|
||||
|
||||
@@ -19,33 +19,58 @@
|
||||
#ifndef RIPPLE_RANDOMNUMBERS_H
|
||||
#define RIPPLE_RANDOMNUMBERS_H
|
||||
|
||||
extern bool AddSystemEntropy ();
|
||||
|
||||
// Cryptographically secure random number source
|
||||
|
||||
// VFALCO: TODO Clean this up, rename stuff
|
||||
// Seriously...wtf...rename "num" to bytes, or make it work
|
||||
// using a template so the destination can be a vector of objects.
|
||||
//
|
||||
// VFALCO: Should accept void* not unsigned char*
|
||||
//
|
||||
extern void getRand (unsigned char *buf, int num);
|
||||
|
||||
inline static void getRand (char *buf, int num)
|
||||
/** Cryptographically secure random number source.
|
||||
*/
|
||||
class RandomNumbers
|
||||
{
|
||||
return getRand (reinterpret_cast<unsigned char *>(buf), num);
|
||||
}
|
||||
public:
|
||||
static RandomNumbers& getInstance ();
|
||||
|
||||
// VFALCO: TODO Clean this
|
||||
// "num" is really bytes this should just be called getRandomBytes()
|
||||
// This function is unnecessary!
|
||||
//
|
||||
inline static void getRand (void *buf, int num)
|
||||
{
|
||||
return getRand (reinterpret_cast<unsigned char *>(buf), num);
|
||||
}
|
||||
/** Initialize the generator.
|
||||
|
||||
// Lifted from BitcoinUtil.h
|
||||
extern void RandAddSeedPerfmon();
|
||||
If the generator is not manually initialized, it will be
|
||||
automatically initialized on first use. If automatic initialization
|
||||
fails, an exception is thrown.
|
||||
|
||||
@return `true` if enough entropy could be retrieved.
|
||||
*/
|
||||
bool initialize ();
|
||||
|
||||
/** Generate secure random numbers.
|
||||
|
||||
The generated data is suitable for cryptography.
|
||||
|
||||
@invariant The destination buffer must be large enough or undefined behavior
|
||||
results.
|
||||
@param destinationBuffer The place to store the bytes.
|
||||
@param numberOfBytes The number of bytes to generate.
|
||||
*/
|
||||
void fillBytes (void* destinationBuffer, int numberOfBytes);
|
||||
|
||||
/** Generate secure random numbers.
|
||||
|
||||
The generated data is suitable for cryptography.
|
||||
|
||||
Fills the memory for the object with random numbers. This is a type-safe
|
||||
alternative to the function above.
|
||||
*/
|
||||
template <class T>
|
||||
void fill (T* object)
|
||||
{
|
||||
fillBytes (object, sizeof (T));
|
||||
}
|
||||
|
||||
private:
|
||||
RandomNumbers ();
|
||||
|
||||
~RandomNumbers ();
|
||||
|
||||
bool platformAddEntropy ();
|
||||
|
||||
void platformAddPerformanceMonitorEntropy ();
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -105,7 +105,7 @@ std::vector<unsigned char> CKey::encryptECIES(CKey& otherKey, const std::vector<
|
||||
{
|
||||
|
||||
ECIES_ENC_IV_TYPE iv;
|
||||
getRand(static_cast<unsigned char *>(iv.begin()), ECIES_ENC_BLK_SIZE);
|
||||
RandomNumbers::getInstance ().fillBytes (iv.begin (), ECIES_ENC_BLK_SIZE);
|
||||
|
||||
ECIES_ENC_KEY_TYPE secret;
|
||||
ECIES_HMAC_KEY_TYPE hmacKey;
|
||||
@@ -268,7 +268,7 @@ bool checkECIES(void)
|
||||
std::vector<unsigned char> message(4096);
|
||||
int msglen = i%3000;
|
||||
|
||||
getRand(static_cast<unsigned char *>(&message.front()), msglen);
|
||||
RandomNumbers::getInstance ().fillBytes (&message.front(), msglen);
|
||||
message.resize(msglen);
|
||||
|
||||
// encrypt message with sender's private key and recipient's public key
|
||||
|
||||
@@ -803,7 +803,7 @@ void RippleAddress::setSeedRandom()
|
||||
// XXX Maybe we should call MakeNewKey
|
||||
uint128 key;
|
||||
|
||||
getRand(key.begin(), key.size());
|
||||
RandomNumbers::getInstance ().fillBytes (key.begin(), key.size());
|
||||
|
||||
RippleAddress::setSeed(key);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "crypto/ripple_CBigNum.h"
|
||||
#include "crypto/ripple_Base58.h" // VFALCO: TODO, Can be moved to .cpp if we clean up setAlphabet stuff
|
||||
#include "crypto/ripple_Base58Data.h"
|
||||
// #include "src/cpp/ripple/ProofOfWork.h"
|
||||
|
||||
#include "protocol/ripple_FieldNames.h"
|
||||
#include "protocol/ripple_RippleAddress.h"
|
||||
|
||||
@@ -1270,6 +1270,7 @@
|
||||
<ClInclude Include="modules\ripple_basics\containers\ripple_SecureAllocator.h" />
|
||||
<ClInclude Include="modules\ripple_basics\containers\ripple_TaggedCache.h" />
|
||||
<ClInclude Include="modules\ripple_basics\ripple_basics.h" />
|
||||
<ClInclude Include="modules\ripple_basics\types\ripple_HashTables.h" />
|
||||
<ClInclude Include="modules\ripple_basics\types\ripple_UInt256.h" />
|
||||
<ClInclude Include="modules\ripple_basics\utility\ripple_ByteOrder.h" />
|
||||
<ClInclude Include="modules\ripple_basics\utility\ripple_DiffieHellmanUtil.h" />
|
||||
|
||||
@@ -118,9 +118,6 @@
|
||||
<Filter Include="1. Modules\ripple_main\_unfactored\types">
|
||||
<UniqueIdentifier>{1b463564-35d9-43d1-b3a0-21b344a3a1c7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="1. Modules\ripple_main\_unfactored\http">
|
||||
<UniqueIdentifier>{29cd2103-d553-4d82-9e6a-224e3b1cb667}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="1. Modules\ripple_main\_unfactored\main">
|
||||
<UniqueIdentifier>{1ccfc5ad-5cd7-4a8e-b305-08f663c2397c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -1508,6 +1505,9 @@
|
||||
<ClInclude Include="modules\ripple_data\protocol\ripple_RippleSystem.h">
|
||||
<Filter>1. Modules\ripple_data\protocol</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="modules\ripple_basics\types\ripple_HashTables.h">
|
||||
<Filter>1. Modules\ripple_basics\types</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="SConstruct" />
|
||||
|
||||
@@ -68,8 +68,8 @@ Application::Application ()
|
||||
, mSweepTimer (mAuxService)
|
||||
, mShutdown (false)
|
||||
{
|
||||
getRand (mNonce256.begin(), mNonce256.size());
|
||||
getRand (reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
|
||||
RandomNumbers::getInstance ().fillBytes (mNonce256.begin(), mNonce256.size());
|
||||
RandomNumbers::getInstance ().fill (&mNonceST);
|
||||
}
|
||||
|
||||
extern const char *RpcDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[],
|
||||
|
||||
@@ -1782,7 +1782,7 @@ bool NetworkOPs::subServer(InfoSub::ref isrListener, Json::Value& jvResult)
|
||||
if (theConfig.TESTNET)
|
||||
jvResult["testnet"] = theConfig.TESTNET;
|
||||
|
||||
getRand(uRandom.begin(), uRandom.size());
|
||||
RandomNumbers::getInstance ().fillBytes (uRandom.begin(), uRandom.size());
|
||||
jvResult["random"] = uRandom.ToString();
|
||||
jvResult["server_status"] = strOperatingMode();
|
||||
jvResult["load_base"] = theApp->getFeeTrack().getLoadBase();
|
||||
|
||||
@@ -103,7 +103,7 @@ uint256 ProofOfWork::solve(int maxIterations) const
|
||||
throw std::runtime_error("invalid proof of work target/iteration");
|
||||
|
||||
uint256 nonce;
|
||||
getRand(nonce.begin(), nonce.size());
|
||||
RandomNumbers::getInstance ().fill (&nonce);
|
||||
|
||||
std::vector<uint256> buf2;
|
||||
buf2.resize(mIterations);
|
||||
@@ -162,7 +162,7 @@ bool ProofOfWork::validateToken(const std::string& strToken)
|
||||
ProofOfWorkGenerator::ProofOfWorkGenerator() : mValidTime(180)
|
||||
{
|
||||
setDifficulty(1);
|
||||
getRand(mSecret.begin(), mSecret.size());
|
||||
RandomNumbers::getInstance ().fillBytes (mSecret.begin(), mSecret.size());
|
||||
}
|
||||
|
||||
ProofOfWork ProofOfWorkGenerator::getProof()
|
||||
@@ -173,7 +173,7 @@ ProofOfWork ProofOfWorkGenerator::getProof()
|
||||
int now = static_cast<int>(time(NULL) / 4);
|
||||
|
||||
uint256 challenge;
|
||||
getRand(challenge.begin(), challenge.size());
|
||||
RandomNumbers::getInstance ().fillBytes (challenge.begin(), challenge.size());
|
||||
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
|
||||
@@ -1276,7 +1276,7 @@ Json::Value RPCHandler::doRandom(Json::Value jvRequest, int& cost, ScopedLock& M
|
||||
|
||||
try
|
||||
{
|
||||
getRand(uRandom.begin(), uRandom.size());
|
||||
RandomNumbers::getInstance ().fillBytes (uRandom.begin(), uRandom.size());
|
||||
|
||||
Json::Value jvResult;
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ void SNTPClient::resolveComplete(const boost::system::error_code& error, boost::
|
||||
}
|
||||
query.mReceivedReply = false;
|
||||
query.mLocalTimeSent = now;
|
||||
getRand(reinterpret_cast<unsigned char *>(&query.mQueryNonce), sizeof(query.mQueryNonce));
|
||||
RandomNumbers::getInstance ().fill (&query.mQueryNonce);
|
||||
reinterpret_cast<uint32*>(SNTPQueryData)[NTP_OFF_XMITTS_INT] = static_cast<uint32>(time(NULL)) + NTP_UNIX_OFFSET;
|
||||
reinterpret_cast<uint32*>(SNTPQueryData)[NTP_OFF_XMITTS_FRAC] = query.mQueryNonce;
|
||||
mSocket.async_send_to(boost::asio::buffer(SNTPQueryData, 48), *sel,
|
||||
|
||||
@@ -160,7 +160,7 @@ int main(int argc, char* argv[])
|
||||
// Prepare to run
|
||||
//
|
||||
|
||||
if (!AddSystemEntropy())
|
||||
if (! RandomNumbers::getInstance ().initialize ())
|
||||
{
|
||||
std::cerr << "Unable to add system entropy" << std::endl;
|
||||
iResult = 2;
|
||||
|
||||
@@ -4,6 +4,11 @@ int DatabaseCon::sCount = 0;
|
||||
DatabaseCon::DatabaseCon(const std::string& strName, const char *initStrings[], int initCount)
|
||||
{
|
||||
++sCount;
|
||||
|
||||
// VFALCO: TODO, remove this dependency on the config by making it the caller's
|
||||
// responsibility to pass in the path. Add a member function to Application
|
||||
// or Config to compute this path.
|
||||
//
|
||||
boost::filesystem::path pPath = (theConfig.RUN_STANDALONE && (theConfig.START_UP != Config::LOAD))
|
||||
? "" // Use temporary files.
|
||||
: (theConfig.DATA_DIR / strName); // Use regular db files.
|
||||
|
||||
Reference in New Issue
Block a user