aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstate
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-11-08 21:09:36 +0000
committerlloyd <[email protected]>2013-11-08 21:09:36 +0000
commit9fab3b28e9b728dbe71bc5b0afc9a8c408de1d0e (patch)
tree95129c533c2a27840defdc956b4e2bb5f3c2e81d /src/libstate
parent51bdb06ac838b426cacdb4dd8a2efecbf67820ac (diff)
Previously, AutoRNG was just a reference to the global rng, which can
cause a huge amount of lock contention in heavily multithreaded code. Now each AutoRNG is its own uniquely seeded HMAC_RNG. The set of entropy sources is shared rather than being per-RNG (so there is only one open fd to /dev/random, etc). So reseeding is still a global lock, but sharing the resources (open file descriptors, etc) across RNGs seems worth the contention. Remove Randpool, which was only used if HMAC_RNG was disabled at build.
Diffstat (limited to 'src/libstate')
-rw-r--r--src/libstate/global_rng.cpp110
-rw-r--r--src/libstate/info.txt26
-rw-r--r--src/libstate/libstate.cpp3
-rw-r--r--src/libstate/libstate.h9
4 files changed, 53 insertions, 95 deletions
diff --git a/src/libstate/global_rng.cpp b/src/libstate/global_rng.cpp
index e460199c5..38b8ec559 100644
--- a/src/libstate/global_rng.cpp
+++ b/src/libstate/global_rng.cpp
@@ -7,18 +7,6 @@
#include <botan/libstate.h>
-#if defined(BOTAN_HAS_RANDPOOL)
- #include <botan/randpool.h>
-#endif
-
-#if defined(BOTAN_HAS_HMAC_RNG)
- #include <botan/hmac_rng.h>
-#endif
-
-#if defined(BOTAN_HAS_X931_RNG)
- #include <botan/x931_rng.h>
-#endif
-
#if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER)
#include <botan/internal/hres_timer.h>
#endif
@@ -57,58 +45,58 @@
namespace Botan {
-namespace {
-
-/**
-* Add any known entropy sources to this RNG
-*/
-void add_entropy_sources(RandomNumberGenerator* rng)
+std::vector<std::unique_ptr<EntropySource>> Library_State::entropy_sources()
{
+ std::vector<std::unique_ptr<EntropySource>> sources;
+
#if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER)
- rng->add_entropy_source(new High_Resolution_Timestamp);
+ sources.push_back(std::unique_ptr<EntropySource>(new High_Resolution_Timestamp));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
- rng->add_entropy_source(new Intel_Rdrand);
+ sources.push_back(std::unique_ptr<EntropySource>(new Intel_Rdrand));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
- rng->add_entropy_source(
- new Device_EntropySource(
- split_on("/dev/random:/dev/srandom:/dev/urandom", ':')
- )
- );
+ sources.push_back(std::unique_ptr<EntropySource>(new Device_EntropySource(
+ { "/dev/random", "/dev/srandom", "/dev/urandom" }
+ )));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
- rng->add_entropy_source(new Win32_CAPI_EntropySource);
+ sources.push_back(std::unique_ptr<EntropySource>(new Win32_CAPI_EntropySource));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
- rng->add_entropy_source(new FTW_EntropySource("/proc"));
+ sources.push_back(std::unique_ptr<EntropySource>(new FTW_EntropySource("/proc")));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
- rng->add_entropy_source(new Win32_EntropySource);
+ sources.push_back(std::unique_ptr<EntropySource>(new Win32_EntropySource));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
- rng->add_entropy_source(new BeOS_EntropySource);
+ sources.push_back(std::unique_ptr<EntropySource>(new BeOS_EntropySource));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
- rng->add_entropy_source(
- new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':'))
- );
+ sources.push_back(std::unique_ptr<EntropySource>(
+ new Unix_EntropySource(
+ { "/bin", "/sbin", "/usr/bin", "/usr/sbin" }
+ )));
#endif
#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
- rng->add_entropy_source(
- new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':'))
- );
+ sources.push_back(std::unique_ptr<EntropySource>(
+ new EGD_EntropySource({ "/var/run/egd-pool" "/dev/egd-pool" })
+ ));
#endif
+
+ return sources;
}
+namespace {
+
class Serialized_PRNG : public RandomNumberGenerator
{
public:
@@ -142,12 +130,6 @@ class Serialized_PRNG : public RandomNumberGenerator
rng->reseed(poll_bits);
}
- void add_entropy_source(EntropySource* es)
- {
- std::lock_guard<std::mutex> lock(mutex);
- rng->add_entropy_source(es);
- }
-
void add_entropy(const byte in[], size_t len)
{
std::lock_guard<std::mutex> lock(mutex);
@@ -157,47 +139,41 @@ class Serialized_PRNG : public RandomNumberGenerator
// We do not own the mutex; Library_State does
Serialized_PRNG(RandomNumberGenerator* r, std::mutex& m) :
mutex(m), rng(r) {}
-
- ~Serialized_PRNG() { delete rng; }
private:
std::mutex& mutex;
- RandomNumberGenerator* rng;
+ std::unique_ptr<RandomNumberGenerator> rng;
};
}
-RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af,
- std::mutex& mutex)
+void Library_State::poll_available_sources(class Entropy_Accumulator& accum)
{
- RandomNumberGenerator* rng = nullptr;
+ std::lock_guard<std::mutex> lock(m_entropy_src_mutex);
-#if defined(BOTAN_HAS_HMAC_RNG)
+ const size_t poll_bits = accum.desired_remaining_bits();
- rng = new HMAC_RNG(af.make_mac("HMAC(SHA-512)"),
- af.make_mac("HMAC(SHA-256)"));
+ if(!m_sources.empty())
+ {
+ size_t poll_attempt = 0;
-#elif defined(BOTAN_HAS_RANDPOOL)
-
- rng = new Randpool(af.make_block_cipher("AES-256"),
- af.make_mac("HMAC(SHA-256)"));
+ while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
+ {
+ const size_t src_idx = poll_attempt % m_sources.size();
+ m_sources[src_idx]->poll(accum);
+ ++poll_attempt;
+ }
+ }
+ }
-#endif
+RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af,
+ std::mutex& mutex)
+ {
+ auto rng = RandomNumberGenerator::make_rng(af);
if(!rng)
throw Internal_Error("No usable RNG found enabled in build");
- /* If X9.31 is available, use it to wrap the other RNG as a failsafe */
-#if defined(BOTAN_HAS_X931_RNG)
-
- rng = new ANSI_X931_RNG(af.make_block_cipher("AES-256"), rng);
-
-#endif
-
- add_entropy_sources(rng);
-
- rng->reseed(256);
-
- return new Serialized_PRNG(rng, mutex);
+ return new Serialized_PRNG(rng.release(), mutex);
}
}
diff --git a/src/libstate/info.txt b/src/libstate/info.txt
index b0704cd96..49a6d38ee 100644
--- a/src/libstate/info.txt
+++ b/src/libstate/info.txt
@@ -1,29 +1,6 @@
load_on always
-define LIBSTATE_MODULE
-
-<header:public>
-botan.h
-global_state.h
-init.h
-libstate.h
-lookup.h
-scan_name.h
-</header:public>
-
-<source>
-get_enc.cpp
-global_rng.cpp
-global_state.cpp
-init.cpp
-libstate.cpp
-lookup.cpp
-policy.cpp
-scan_name.cpp
-</source>
-
<requires>
-aes
algo_factory
alloc
bigint
@@ -33,7 +10,6 @@ engine
filters
hash
hmac
-hmac_rng
kdf
mac
mode_pad
@@ -41,7 +17,5 @@ pbkdf
pk_pad
pubkey
rng
-sha2_32
-sha2_64
stream
</requires>
diff --git a/src/libstate/libstate.cpp b/src/libstate/libstate.cpp
index 78ff9135c..6a0a28a45 100644
--- a/src/libstate/libstate.cpp
+++ b/src/libstate/libstate.cpp
@@ -157,6 +157,8 @@ void Library_State::initialize()
algorithm_factory().add_engine(new Core_Engine);
+ m_sources = entropy_sources();
+
#if defined(BOTAN_HAS_SELFTESTS)
confirm_startup_self_tests(algorithm_factory());
#endif
@@ -168,7 +170,6 @@ void Library_State::initialize()
Library_State::Library_State()
{
m_algorithm_factory = nullptr;
-
global_rng_ptr = nullptr;
}
diff --git a/src/libstate/libstate.h b/src/libstate/libstate.h
index 4d0a2b3e7..13333367c 100644
--- a/src/libstate/libstate.h
+++ b/src/libstate/libstate.h
@@ -11,11 +11,11 @@
#include <botan/global_state.h>
#include <botan/algo_factory.h>
#include <botan/rng.h>
-
#include <mutex>
#include <string>
#include <vector>
#include <map>
+#include <memory>
namespace Botan {
@@ -43,6 +43,8 @@ class BOTAN_DLL Library_State
*/
RandomNumberGenerator& global_rng();
+ void poll_available_sources(class Entropy_Accumulator& accum);
+
/**
* Set the default allocator
* @param name the name of the allocator to use as the default
@@ -100,11 +102,16 @@ class BOTAN_DLL Library_State
static RandomNumberGenerator* make_global_rng(Algorithm_Factory& af,
std::mutex& mutex);
+ static std::vector<std::unique_ptr<EntropySource>> entropy_sources();
+
void load_default_config();
std::mutex global_rng_lock;
RandomNumberGenerator* global_rng_ptr;
+ std::mutex m_entropy_src_mutex;
+ std::vector<std::unique_ptr<EntropySource>> m_sources;
+
std::mutex config_lock;
std::map<std::string, std::string> config;