aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstate/global_rng.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-03-19 15:59:45 +0000
committerlloyd <[email protected]>2010-03-19 15:59:45 +0000
commit1418ba24b73b8d9e4af67950fee38a02e7f1ac75 (patch)
treefeeb7add6cc5cd172579cb1326bfe3fcd6f4830e /src/libstate/global_rng.cpp
parent87cb43641ca7000b6d97dcb4d8a5e716a07fcf76 (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.cpp196
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);
+ }
+
+}