xrpld
Loading...
Searching...
No Matches
libxrpl/crypto/csprng.cpp
1#include <xrpl/crypto/csprng.h>
2
3#include <xrpl/basics/contract.h>
4
5#include <openssl/opensslv.h>
6#include <openssl/rand.h>
7
8#include <array>
9#include <cstddef>
10#include <mutex>
11#include <random>
12#include <stdexcept>
13
14namespace xrpl {
15
17{
18 // This is not strictly necessary
19 if (RAND_poll() != 1)
20 Throw<std::runtime_error>("CSPRNG: Initial polling failed");
21}
22
24{
25 // This cleanup function is not needed in newer versions of OpenSSL
26#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
27 RAND_cleanup();
28#endif
29}
30
31void
33{
35
36 {
37 // On every platform we support, std::random_device
38 // is non-deterministic and should provide some good
39 // quality entropy.
41
42 for (auto& e : entropy)
43 e = rd();
44 }
45
46 std::scoped_lock const lock(mutex_);
47
48 // We add data to the pool, but we conservatively assume that
49 // it contributes no actual entropy.
50 RAND_add(entropy.data(), entropy.size() * sizeof(std::random_device::result_type), 0);
51
52 if (buffer != nullptr && count != 0)
53 RAND_add(buffer, count, 0);
54}
55
56void
58{
59 // RAND_bytes is thread-safe on OpenSSL 1.1.0 and later when compiled
60 // with thread support, so we don't need to grab a mutex.
61 // https://mta.openssl.org/pipermail/openssl-users/2020-November/013146.html
62#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || !defined(OPENSSL_THREADS)
64#endif
65
66 auto const result = RAND_bytes(reinterpret_cast<unsigned char*>(ptr), count);
67
68 if (result != 1)
69 Throw<std::runtime_error>("CSPRNG: Insufficient entropy");
70}
71
74{
75 result_type ret = 0;
76 (*this)(&ret, sizeof(result_type));
77 return ret;
78}
79
82{
83 static CsprngEngine kEngine;
84 return kEngine;
85}
86
87} // namespace xrpl
A cryptographically secure random number engine.
Definition csprng.h:16
std::mutex mutex_
Definition csprng.h:18
result_type operator()()
Generate a random integer.
std::uint64_t result_type
Definition csprng.h:21
void mixEntropy(void *buffer=nullptr, std::size_t count=0)
Mix entropy into the pool.
T data(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
CsprngEngine & cryptoPrng()
The default cryptographically secure PRNG.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T size(T... args)