/* * Global PRNG * (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #if defined(BOTAN_HAS_RANDPOOL) #include #endif #if defined(BOTAN_HAS_HMAC_RNG) #include #endif #if defined(BOTAN_HAS_X931_RNG) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_EGD) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_UNIX) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_CAPI) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) #include #endif #if defined(BOTAN_HAS_ENTROPY_SRC_FTW) #include #endif namespace Botan { namespace { /** * Add any known entropy sources to this RNG */ void add_entropy_sources(RandomNumberGenerator* rng) { #if defined(BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) rng->add_entropy_source(new High_Resolution_Timestamp); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) rng->add_entropy_source(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", ':') ) ); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_EGD) rng->add_entropy_source( new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':')) ); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_CAPI) rng->add_entropy_source(new Win32_CAPI_EntropySource); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_FTW) rng->add_entropy_source(new FTW_EntropySource("/proc")); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) rng->add_entropy_source(new Win32_EntropySource); #endif #if defined(BOTAN_HAS_ENTROPY_SRC_BEOS) rng->add_entropy_source(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", ':')) ); #endif } class Serialized_PRNG : public RandomNumberGenerator { public: void randomize(byte out[], size_t len) { std::lock_guard lock(mutex); rng->randomize(out, len); } bool is_seeded() const { std::lock_guard lock(mutex); return rng->is_seeded(); } void clear() { std::lock_guard lock(mutex); rng->clear(); } std::string name() const { std::lock_guard lock(mutex); return rng->name(); } void reseed(size_t poll_bits) { std::lock_guard lock(mutex); rng->reseed(poll_bits); } void add_entropy_source(EntropySource* es) { std::lock_guard lock(mutex); rng->add_entropy_source(es); } void add_entropy(const byte in[], size_t len) { std::lock_guard lock(mutex); rng->add_entropy(in, len); } // 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; }; } RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af, std::mutex& mutex) { RandomNumberGenerator* rng = nullptr; #if defined(BOTAN_HAS_HMAC_RNG) rng = new HMAC_RNG(af.make_mac("HMAC(SHA-512)"), af.make_mac("HMAC(SHA-256)")); #elif defined(BOTAN_HAS_RANDPOOL) rng = new Randpool(af.make_block_cipher("AES-256"), af.make_mac("HMAC(SHA-256)")); #endif 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); } }