mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Improve wrapper around OpenSSL RAND
This commit is contained in:
@@ -39,9 +39,6 @@ class csprng_engine
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
|
||||
void
|
||||
mix(void* buffer, std::size_t count, double bitsPerByte);
|
||||
|
||||
public:
|
||||
using result_type = std::uint64_t;
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/ByteUtilities.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/crypto/csprng.h>
|
||||
#include <array>
|
||||
@@ -28,25 +27,19 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
void
|
||||
csprng_engine::mix(void* data, std::size_t size, double bitsPerByte)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
assert(size != 0);
|
||||
assert(bitsPerByte != 0);
|
||||
|
||||
std::lock_guard lock(mutex_);
|
||||
RAND_add(data, size, (size * bitsPerByte) / 8.0);
|
||||
}
|
||||
|
||||
csprng_engine::csprng_engine()
|
||||
{
|
||||
mix_entropy();
|
||||
// This is not strictly necessary
|
||||
if (RAND_poll() != 1)
|
||||
Throw<std::runtime_error>("CSPRNG: Initial polling failed");
|
||||
}
|
||||
|
||||
csprng_engine::~csprng_engine()
|
||||
{
|
||||
// This cleanup function is not needed in newer versions of OpenSSL
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
RAND_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -64,46 +57,44 @@ csprng_engine::mix_entropy(void* buffer, std::size_t count)
|
||||
e = rd();
|
||||
}
|
||||
|
||||
// Assume 2 bits per byte for the system entropy:
|
||||
mix(entropy.data(),
|
||||
entropy.size() * sizeof(std::random_device::result_type),
|
||||
2.0);
|
||||
std::lock_guard lock(mutex_);
|
||||
|
||||
// We add data to the pool, but we conservatively assume that
|
||||
// it contributes no actual entropy.
|
||||
RAND_add(
|
||||
entropy.data(),
|
||||
entropy.size() * sizeof(std::random_device::result_type),
|
||||
0);
|
||||
|
||||
// We want to be extremely conservative about estimating
|
||||
// how much entropy the buffer the user gives us contains
|
||||
// and assume only 0.5 bits of entropy per byte:
|
||||
if (buffer != nullptr && count != 0)
|
||||
mix(buffer, count, 0.5);
|
||||
RAND_add(buffer, count, 0);
|
||||
}
|
||||
|
||||
void
|
||||
csprng_engine::operator()(void* ptr, std::size_t count)
|
||||
{
|
||||
// RAND_bytes is thread-safe on OpenSSL 1.1.0 and later when compiled
|
||||
// with thread support, so we don't need to grab a mutex.
|
||||
// https://mta.openssl.org/pipermail/openssl-users/2020-November/013146.html
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || !defined(OPENSSL_THREADS)
|
||||
std::lock_guard lock(mutex_);
|
||||
#endif
|
||||
|
||||
auto const result =
|
||||
RAND_bytes(reinterpret_cast<unsigned char*>(ptr), count);
|
||||
|
||||
if (result != 1)
|
||||
Throw<std::runtime_error>("CSPRNG: Insufficient entropy");
|
||||
}
|
||||
|
||||
csprng_engine::result_type
|
||||
csprng_engine::operator()()
|
||||
{
|
||||
result_type ret;
|
||||
|
||||
std::lock_guard lock(mutex_);
|
||||
|
||||
auto const result =
|
||||
RAND_bytes(reinterpret_cast<unsigned char*>(&ret), sizeof(ret));
|
||||
|
||||
if (result == 0)
|
||||
Throw<std::runtime_error>("Insufficient entropy");
|
||||
|
||||
(*this)(&ret, sizeof(result_type));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
csprng_engine::operator()(void* ptr, std::size_t count)
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
|
||||
auto const result =
|
||||
RAND_bytes(reinterpret_cast<unsigned char*>(ptr), count);
|
||||
|
||||
if (result != 1)
|
||||
Throw<std::runtime_error>("Insufficient entropy");
|
||||
}
|
||||
|
||||
csprng_engine&
|
||||
crypto_prng()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user