diff options
author | lloyd <[email protected]> | 2010-03-19 15:59:45 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-03-19 15:59:45 +0000 |
commit | 1418ba24b73b8d9e4af67950fee38a02e7f1ac75 (patch) | |
tree | feeb7add6cc5cd172579cb1326bfe3fcd6f4830e /src/libstate/global_rng.cpp | |
parent | 87cb43641ca7000b6d97dcb4d8a5e716a07fcf76 (diff) |
There are some nasty API problems that are caused by having to pass a
PRNG everywhere. The removal of the global PRNG was generated by a
desire to remove the global library state entirely. However the real
point of this was to remove the use of globally visible _mutable_
state; of the mutable state, the PRNG is probably the least important,
and the most useful to share. And it seems unlikely that thread
contention would be a major issue in the PRNG.
Add back a global PRNG to Library_State. Use lazy initialization, so
apps that don't ever use a PRNG don't need a seeding step. Then have
AutoSeeded_RNG call that global PRNG.
Offer once again
RandomNumberGenerator& Library_State::global_rng();
which returns a reference to the global PRNG.
This RNG object serializes access to itself with a mutex.
Remove the hack known as Blinding::choose_nonce, replace with using
the global PRNG to choose a blinding nonce
Diffstat (limited to 'src/libstate/global_rng.cpp')
-rw-r--r-- | src/libstate/global_rng.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/libstate/global_rng.cpp b/src/libstate/global_rng.cpp new file mode 100644 index 000000000..c18705a3a --- /dev/null +++ b/src/libstate/global_rng.cpp @@ -0,0 +1,196 @@ +/* +* Global PRNG +* (C) 2008-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/libstate.h> +#include <botan/mutex.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 + +#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) + #include <botan/internal/dev_random.h> +#endif + +#if defined(BOTAN_HAS_ENTROPY_SRC_EGD) + #include <botan/internal/es_egd.h> +#endif + +#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX) + #include <botan/internal/es_unix.h> +#endif + +#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS) + #include <botan/internal/es_beos.h> +#endif + +#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI) + #include <botan/internal/es_capi.h> +#endif + +#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32) + #include <botan/internal/es_win32.h> +#endif + +#if defined(BOTAN_HAS_ENTROPY_SRC_FTW) + #include <botan/internal/es_ftw.h> +#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_DEV_RANDOM) + rng->add_entropy_source( + new Device_EntropySource( + split_on("/dev/urandom:/dev/random:/dev/srandom", ':') + ) + ); +#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[], u32bit len) + { + Mutex_Holder lock(mutex); + rng->randomize(out, len); + } + + bool is_seeded() const + { + Mutex_Holder lock(mutex); + return rng->is_seeded(); + } + + void clear() + { + Mutex_Holder lock(mutex); + rng->clear(); + } + + std::string name() const + { + Mutex_Holder lock(mutex); + return rng->name(); + } + + void reseed(u32bit poll_bits) + { + Mutex_Holder lock(mutex); + rng->reseed(poll_bits); + } + + void add_entropy_source(EntropySource* es) + { + Mutex_Holder lock(mutex); + rng->add_entropy_source(es); + } + + void add_entropy(const byte in[], u32bit len) + { + Mutex_Holder lock(mutex); + rng->add_entropy(in, len); + } + + // We do not own the mutex; Library_State does + Serialized_PRNG(RandomNumberGenerator* r, Mutex* m) : + mutex(m), rng(r) {} + + ~Serialized_PRNG() { delete rng; } + private: + Mutex* mutex; + RandomNumberGenerator* rng; + }; + +} + +RandomNumberGenerator* Library_State::make_global_rng(Algorithm_Factory& af, + Mutex* mutex) + { + RandomNumberGenerator* rng = 0; + +#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) && defined(BOTAN_HAS_AES) + + 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) && defined(BOTAN_HAS_AES) + + 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); + } + +} |