diff options
author | lloyd <[email protected]> | 2013-11-08 21:09:36 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2013-11-08 21:09:36 +0000 |
commit | 9fab3b28e9b728dbe71bc5b0afc9a8c408de1d0e (patch) | |
tree | 95129c533c2a27840defdc956b4e2bb5f3c2e81d /src/libstate | |
parent | 51bdb06ac838b426cacdb4dd8a2efecbf67820ac (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.cpp | 110 | ||||
-rw-r--r-- | src/libstate/info.txt | 26 | ||||
-rw-r--r-- | src/libstate/libstate.cpp | 3 | ||||
-rw-r--r-- | src/libstate/libstate.h | 9 |
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; |