/* * Entropy Source Polling * (C) 2008-2010,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #if defined(BOTAN_HAS_SYSTEM_RNG) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DARWIN_SECRANDOM) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY) #include #endif namespace Botan { #if defined(BOTAN_HAS_SYSTEM_RNG) namespace { class System_RNG_EntropySource : public Entropy_Source { public: size_t poll(RandomNumberGenerator& rng) override { const size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS; rng.reseed_from_rng(system_rng(), poll_bits); return poll_bits; } std::string name() const override { return system_rng().name(); } }; } #endif std::unique_ptr Entropy_Source::create(const std::string& name) { #if defined(BOTAN_HAS_SYSTEM_RNG) if(name == "system_rng" || name == "win32_cryptoapi") { return std::unique_ptr(new System_RNG_EntropySource); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) if(name == "rdrand") { return std::unique_ptr(new Intel_Rdrand); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED) if(name == "rdseed") { return std::unique_ptr(new Intel_Rdseed); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DARWIN_SECRANDOM) if(name == "darwin_secrandom") { return std::unique_ptr(new Darwin_SecRandom); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY) if(name == "getentropy") { return std::unique_ptr(new Getentropy); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) if(name == "dev_random") { return std::unique_ptr(new Device_EntropySource(BOTAN_SYSTEM_RNG_POLL_DEVICES)); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER) if(name == "proc_walk") { const std::string root_dir = BOTAN_ENTROPY_PROC_FS_PATH; if(!root_dir.empty()) return std::unique_ptr(new ProcWalking_EntropySource(root_dir)); } #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) if(name == "system_stats") { return std::unique_ptr(new Win32_EntropySource); } #endif return std::unique_ptr(); } void Entropy_Sources::add_source(std::unique_ptr src) { if(src.get()) { m_srcs.push_back(src.release()); } } std::vector Entropy_Sources::enabled_sources() const { std::vector sources; for(size_t i = 0; i != m_srcs.size(); ++i) { sources.push_back(m_srcs[i]->name()); } return sources; } size_t Entropy_Sources::poll(RandomNumberGenerator& rng, size_t poll_bits, std::chrono::milliseconds timeout) { typedef std::chrono::system_clock clock; auto deadline = clock::now() + timeout; size_t bits_collected = 0; for(Entropy_Source* src : m_srcs) { bits_collected += src->poll(rng); if (bits_collected >= poll_bits || clock::now() > deadline) break; } return bits_collected; } size_t Entropy_Sources::poll_just(RandomNumberGenerator& rng, const std::string& the_src) { for(size_t i = 0; i != m_srcs.size(); ++i) { if(m_srcs[i]->name() == the_src) { return m_srcs[i]->poll(rng); } } return 0; } Entropy_Sources::Entropy_Sources(const std::vector& sources) { for(auto&& src_name : sources) { add_source(Entropy_Source::create(src_name)); } } Entropy_Sources::~Entropy_Sources() { for(size_t i = 0; i != m_srcs.size(); ++i) { delete m_srcs[i]; m_srcs[i] = nullptr; } m_srcs.clear(); } Entropy_Sources& Entropy_Sources::global_sources() { static Entropy_Sources global_entropy_sources(BOTAN_ENTROPY_DEFAULT_SOURCES); return global_entropy_sources; } }