summaryrefslogtreecommitdiffstats
path: root/botan/src/rng
diff options
context:
space:
mode:
Diffstat (limited to 'botan/src/rng')
-rw-r--r--botan/src/rng/auto_rng/auto_rng.cpp158
-rw-r--r--botan/src/rng/auto_rng/auto_rng.h44
-rw-r--r--botan/src/rng/auto_rng/info.txt16
-rw-r--r--botan/src/rng/hmac_rng/hmac_rng.cpp223
-rw-r--r--botan/src/rng/hmac_rng/hmac_rng.h59
-rw-r--r--botan/src/rng/hmac_rng/info.txt14
-rw-r--r--botan/src/rng/info.txt12
-rw-r--r--botan/src/rng/randpool/info.txt15
-rw-r--r--botan/src/rng/randpool/randpool.cpp214
-rw-r--r--botan/src/rng/randpool/randpool.h53
-rw-r--r--botan/src/rng/rng.cpp38
-rw-r--r--botan/src/rng/rng.h103
-rw-r--r--botan/src/rng/x931_rng/info.txt14
-rw-r--r--botan/src/rng/x931_rng/x931_rng.cpp154
-rw-r--r--botan/src/rng/x931_rng/x931_rng.h45
15 files changed, 1162 insertions, 0 deletions
diff --git a/botan/src/rng/auto_rng/auto_rng.cpp b/botan/src/rng/auto_rng/auto_rng.cpp
new file mode 100644
index 0000000..8405170
--- /dev/null
+++ b/botan/src/rng/auto_rng/auto_rng.cpp
@@ -0,0 +1,158 @@
+/*
+* Auto Seeded RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/auto_rng.h>
+#include <botan/parsing.h>
+#include <botan/timer.h>
+#include <botan/hmac.h>
+#include <botan/sha2_32.h>
+#include <botan/sha2_64.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_AES)
+ #include <botan/aes.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_HARDWARE)
+ #include <botan/tm_hard.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_POSIX)
+ #include <botan/tm_posix.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_UNIX)
+ #include <botan/tm_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_TIMER_WIN32)
+ #include <botan/tm_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ #include <botan/es_dev.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_EGD)
+ #include <botan/es_egd.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_UNIX)
+ #include <botan/es_unix.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_BEOS)
+ #include <botan/es_beos.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_CAPI)
+ #include <botan/es_capi.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ #include <botan/es_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_FTW)
+ #include <botan/es_ftw.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+/**
+* Add any known entropy sources to this RNG
+*/
+void add_entropy_sources(RandomNumberGenerator* rng)
+ {
+
+ // Add a high resolution timer, if available
+#if defined(BOTAN_HAS_TIMER_HARDWARE)
+ rng->add_entropy_source(new Hardware_Timer);
+#elif defined(BOTAN_HAS_TIMER_POSIX)
+ rng->add_entropy_source(new POSIX_Timer);
+#elif defined(BOTAN_HAS_TIMER_UNIX)
+ rng->add_entropy_source(new Unix_Timer);
+#elif defined(BOTAN_HAS_TIMER_WIN32)
+ rng->add_entropy_source(new Win32_Timer);
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEVICE)
+ 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
+ }
+
+}
+
+AutoSeeded_RNG::AutoSeeded_RNG(u32bit poll_bits)
+ {
+ rng = 0;
+
+#if defined(BOTAN_HAS_HMAC_RNG)
+ rng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256));
+#elif defined(BOTAN_HAS_RANDPOOL) && defined(BOTAN_HAS_AES)
+ rng = new Randpool(new AES_256, new HMAC(new SHA_256));
+#endif
+
+ if(!rng)
+ throw Algorithm_Not_Found("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(new AES_256, rng);
+#endif
+
+ add_entropy_sources(rng);
+
+ rng->reseed(poll_bits);
+ }
+
+}
diff --git a/botan/src/rng/auto_rng/auto_rng.h b/botan/src/rng/auto_rng/auto_rng.h
new file mode 100644
index 0000000..f18f8e5
--- /dev/null
+++ b/botan/src/rng/auto_rng/auto_rng.h
@@ -0,0 +1,44 @@
+/*
+* Auto Seeded RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_AUTO_SEEDING_RNG_H__
+#define BOTAN_AUTO_SEEDING_RNG_H__
+
+#include <botan/rng.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* RNG that attempts to seed itself
+*/
+class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte out[], u32bit len)
+ { rng->randomize(out, len); }
+ bool is_seeded() const
+ { return rng->is_seeded(); }
+ void clear() throw() { rng->clear(); }
+ std::string name() const
+ { return "AutoSeeded(" + rng->name() + ")"; }
+
+ void reseed(u32bit poll_bits = 256) { rng->reseed(poll_bits); }
+ void add_entropy_source(EntropySource* es)
+ { rng->add_entropy_source(es); }
+ void add_entropy(const byte in[], u32bit len)
+ { rng->add_entropy(in, len); }
+
+ AutoSeeded_RNG(u32bit poll_bits = 256);
+ ~AutoSeeded_RNG() { delete rng; }
+ private:
+ RandomNumberGenerator* rng;
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/auto_rng/info.txt b/botan/src/rng/auto_rng/info.txt
new file mode 100644
index 0000000..7d5d5dd
--- /dev/null
+++ b/botan/src/rng/auto_rng/info.txt
@@ -0,0 +1,16 @@
+realname "Auto-seeded Random Number Generator"
+
+define AUTO_SEEDING_RNG
+
+load_on auto
+
+<add>
+auto_rng.h
+auto_rng.cpp
+</add>
+
+<requires>
+hmac
+sha2
+timer
+</requires>
diff --git a/botan/src/rng/hmac_rng/hmac_rng.cpp b/botan/src/rng/hmac_rng/hmac_rng.cpp
new file mode 100644
index 0000000..113489d
--- /dev/null
+++ b/botan/src/rng/hmac_rng/hmac_rng.cpp
@@ -0,0 +1,223 @@
+/*
+* HMAC_RNG
+* (C) 2008-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hmac_rng.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+#include <botan/util.h>
+#include <botan/stl_util.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+void hmac_prf(MessageAuthenticationCode* prf,
+ MemoryRegion<byte>& K,
+ u32bit& counter,
+ const std::string& label)
+ {
+ prf->update(K, K.size());
+ prf->update(label);
+ for(u32bit i = 0; i != 4; ++i)
+ prf->update(get_byte(i, counter));
+ prf->final(K);
+
+ ++counter;
+ }
+
+}
+
+/**
+* Generate a buffer of random bytes
+*/
+void HMAC_RNG::randomize(byte out[], u32bit length)
+ {
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
+
+ /*
+ HMAC KDF as described in E-t-E, using a CTXinfo of "rng"
+ */
+ while(length)
+ {
+ hmac_prf(prf, K, counter, "rng");
+
+ const u32bit copied = std::min(K.size(), length);
+
+ copy_mem(out, K.begin(), copied);
+ out += copied;
+ length -= copied;
+ }
+ }
+
+/**
+* Reseed the internal state, also accepting user input to include
+*/
+void HMAC_RNG::reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit input_length)
+ {
+ /**
+ Using the terminology of E-t-E, XTR is the MAC function (normally
+ HMAC) seeded with XTS (below) and we form SKM, the key material, by
+ fast polling each source, and then slow polling as many as we think
+ we need (in the following loop), and feeding all of the poll
+ results, along with any optional user input, along with, finally,
+ feedback of the current PRK value, into the extractor function.
+ */
+
+ Entropy_Accumulator_BufferedComputation accum(*extractor, poll_bits);
+
+ if(!entropy_sources.empty())
+ {
+ u32bit poll_attempt = 0;
+
+ while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
+ {
+ entropy_sources[poll_attempt % entropy_sources.size()]->poll(accum);
+ ++poll_attempt;
+ }
+ }
+
+ // And now add the user-provided input, if any
+ if(input_length)
+ accum.add(input, input_length, 1);
+
+ /*
+ It is necessary to feed forward poll data. Otherwise, a good poll
+ (collecting a large amount of conditional entropy) followed by a
+ bad one (collecting little) would be unsafe. Do this by generating
+ new PRF outputs using the previous key and feeding them into the
+ extractor function.
+
+ Cycle the RNG once (CTXinfo="rng"), then generate a new PRF output
+ using the CTXinfo "reseed". Provide these values as input to the
+ extractor function.
+ */
+ hmac_prf(prf, K, counter, "rng");
+ extractor->update(K); // K is the CTXinfo=rng PRF output
+
+ hmac_prf(prf, K, counter, "reseed");
+ extractor->update(K); // K is the CTXinfo=reseed PRF output
+
+ /* Now derive the new PRK using everything that has been fed into
+ the extractor, and set the PRF key to that */
+ prf->set_key(extractor->final());
+
+ // Now generate a new PRF output to use as the XTS extractor salt
+ hmac_prf(prf, K, counter, "xts");
+ extractor->set_key(K, K.size());
+
+ // Reset state
+ K.clear();
+ counter = 0;
+
+ if(input_length || accum.bits_collected() >= poll_bits)
+ seeded = true;
+ }
+
+/**
+* Reseed the internal state
+*/
+void HMAC_RNG::reseed(u32bit poll_bits)
+ {
+ reseed_with_input(poll_bits, 0, 0);
+ }
+
+/**
+* Add user-supplied entropy by reseeding and including this
+* input among the poll data
+*/
+void HMAC_RNG::add_entropy(const byte input[], u32bit length)
+ {
+ reseed_with_input(0, input, length);
+ }
+
+/**
+* Add another entropy source to the list
+*/
+void HMAC_RNG::add_entropy_source(EntropySource* src)
+ {
+ entropy_sources.push_back(src);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void HMAC_RNG::clear() throw()
+ {
+ extractor->clear();
+ prf->clear();
+ K.clear();
+ counter = 0;
+ seeded = false;
+ }
+
+/**
+* Return the name of this type
+*/
+std::string HMAC_RNG::name() const
+ {
+ return "HMAC_RNG(" + extractor->name() + "," + prf->name() + ")";
+ }
+
+/**
+* HMAC_RNG Constructor
+*/
+HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac,
+ MessageAuthenticationCode* prf_mac) :
+ extractor(extractor_mac), prf(prf_mac)
+ {
+ // First PRF inputs are all zero, as specified in section 2
+ K.create(prf->OUTPUT_LENGTH);
+ counter = 0;
+ seeded = false;
+
+ /*
+ Normally we want to feedback PRF output into the input to the
+ extractor function to ensure a single bad poll does not damage the
+ RNG, but obviously that is meaningless to do on the first poll.
+
+ We will want to use the PRF before we set the first key (in
+ reseed_with_input), and it is a pain to keep track if it is set or
+ not. Since the first time it doesn't matter anyway, just set it to
+ a constant: randomize() will not produce output unless is_seeded()
+ returns true, and that will only be the case if the estimated
+ entropy counter is high enough. That variable is only set when a
+ reseeding is performed.
+ */
+ std::string prf_key = "Botan HMAC_RNG PRF";
+ prf->set_key(reinterpret_cast<const byte*>(prf_key.c_str()),
+ prf_key.length());
+
+ /*
+ This will be used as the first XTS value when extracting input.
+ XTS values after this one are generated using the PRF.
+
+ If I understand the E-t-E paper correctly (specifically Section 4),
+ using this fixed extractor key is safe to do.
+ */
+ std::string xts = "Botan HMAC_RNG XTS";
+ extractor->set_key(reinterpret_cast<const byte*>(xts.c_str()),
+ xts.length());
+ }
+
+/**
+* HMAC_RNG Destructor
+*/
+HMAC_RNG::~HMAC_RNG()
+ {
+ delete extractor;
+ delete prf;
+
+ std::for_each(entropy_sources.begin(), entropy_sources.end(),
+ del_fun<EntropySource>());
+
+ counter = 0;
+ }
+
+}
diff --git a/botan/src/rng/hmac_rng/hmac_rng.h b/botan/src/rng/hmac_rng/hmac_rng.h
new file mode 100644
index 0000000..318e2a9
--- /dev/null
+++ b/botan/src/rng/hmac_rng/hmac_rng.h
@@ -0,0 +1,59 @@
+/*
+* HMAC RNG
+* (C) 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HMAC_RNG_H__
+#define BOTAN_HMAC_RNG_H__
+
+#include <botan/mac.h>
+#include <botan/rng.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+HMAC_RNG - based on the design described in "On Extract-then-Expand
+Key Derivation Functions and an HMAC-based KDF" by Hugo Krawczyk
+(henceforce, 'E-t-E')
+
+However it actually can be parameterized with any two MAC functions,
+not restricted to HMAC (this variation is also described in Krawczyk's
+paper), for instance one could use HMAC(SHA-512) as the extractor
+and CMAC(AES-256) as the PRF.
+*/
+class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte buf[], u32bit len);
+ bool is_seeded() const { return seeded; }
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit poll_bits);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte[], u32bit);
+
+ HMAC_RNG(MessageAuthenticationCode* extractor,
+ MessageAuthenticationCode* prf);
+
+ ~HMAC_RNG();
+ private:
+ void reseed_with_input(u32bit poll_bits,
+ const byte input[], u32bit length);
+
+ MessageAuthenticationCode* extractor;
+ MessageAuthenticationCode* prf;
+
+ std::vector<EntropySource*> entropy_sources;
+ bool seeded;
+
+ SecureVector<byte> K, io_buffer;
+ u32bit counter, source_index;
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/hmac_rng/info.txt b/botan/src/rng/hmac_rng/info.txt
new file mode 100644
index 0000000..2c7f13e
--- /dev/null
+++ b/botan/src/rng/hmac_rng/info.txt
@@ -0,0 +1,14 @@
+realname "HMAC RNG"
+
+define HMAC_RNG
+
+load_on auto
+
+<add>
+hmac_rng.cpp
+hmac_rng.h
+</add>
+
+<requires>
+mac
+</requires>
diff --git a/botan/src/rng/info.txt b/botan/src/rng/info.txt
new file mode 100644
index 0000000..44a4166
--- /dev/null
+++ b/botan/src/rng/info.txt
@@ -0,0 +1,12 @@
+realname "Random Number Generators"
+
+load_on auto
+
+<add>
+rng.cpp
+rng.h
+</add>
+
+<requires>
+entropy
+</requires>
diff --git a/botan/src/rng/randpool/info.txt b/botan/src/rng/randpool/info.txt
new file mode 100644
index 0000000..cc7f615
--- /dev/null
+++ b/botan/src/rng/randpool/info.txt
@@ -0,0 +1,15 @@
+realname "Randpool RNG"
+
+define RANDPOOL
+
+load_on auto
+
+<add>
+randpool.cpp
+randpool.h
+</add>
+
+<requires>
+block
+mac
+</requires>
diff --git a/botan/src/rng/randpool/randpool.cpp b/botan/src/rng/randpool/randpool.cpp
new file mode 100644
index 0000000..4d7b92d
--- /dev/null
+++ b/botan/src/rng/randpool/randpool.cpp
@@ -0,0 +1,214 @@
+/*
+* Randpool
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/randpool.h>
+#include <botan/loadstor.h>
+#include <botan/xor_buf.h>
+#include <botan/util.h>
+#include <botan/stl_util.h>
+#include <algorithm>
+
+namespace Botan {
+
+namespace {
+
+/**
+* PRF based on a MAC
+*/
+enum RANDPOOL_PRF_TAG {
+ CIPHER_KEY = 0,
+ MAC_KEY = 1,
+ GEN_OUTPUT = 2
+};
+
+}
+
+/**
+* Generate a buffer of random bytes
+*/
+void Randpool::randomize(byte out[], u32bit length)
+ {
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
+
+ update_buffer();
+ while(length)
+ {
+ const u32bit copied = std::min(length, buffer.size());
+ copy_mem(out, buffer.begin(), copied);
+ out += copied;
+ length -= copied;
+ update_buffer();
+ }
+ }
+
+/**
+* Refill the output buffer
+*/
+void Randpool::update_buffer()
+ {
+ const u64bit timestamp = system_time();
+
+ for(u32bit i = 0; i != counter.size(); ++i)
+ if(++counter[i])
+ break;
+ store_be(timestamp, counter + 4);
+
+ mac->update(static_cast<byte>(GEN_OUTPUT));
+ mac->update(counter, counter.size());
+ SecureVector<byte> mac_val = mac->final();
+
+ for(u32bit i = 0; i != mac_val.size(); ++i)
+ buffer[i % buffer.size()] ^= mac_val[i];
+ cipher->encrypt(buffer);
+
+ if(counter[0] % ITERATIONS_BEFORE_RESEED == 0)
+ mix_pool();
+ }
+
+/**
+* Mix the entropy pool
+*/
+void Randpool::mix_pool()
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+
+ mac->update(static_cast<byte>(MAC_KEY));
+ mac->update(pool, pool.size());
+ mac->set_key(mac->final());
+
+ mac->update(static_cast<byte>(CIPHER_KEY));
+ mac->update(pool, pool.size());
+ cipher->set_key(mac->final());
+
+ xor_buf(pool, buffer, BLOCK_SIZE);
+ cipher->encrypt(pool);
+ for(u32bit i = 1; i != POOL_BLOCKS; ++i)
+ {
+ const byte* previous_block = pool + BLOCK_SIZE*(i-1);
+ byte* this_block = pool + BLOCK_SIZE*i;
+ xor_buf(this_block, previous_block, BLOCK_SIZE);
+ cipher->encrypt(this_block);
+ }
+
+ update_buffer();
+ }
+
+/**
+* Reseed the internal state
+*/
+void Randpool::reseed(u32bit poll_bits)
+ {
+ Entropy_Accumulator_BufferedComputation accum(*mac, poll_bits);
+
+ if(!entropy_sources.empty())
+ {
+ u32bit poll_attempt = 0;
+
+ while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
+ {
+ entropy_sources[poll_attempt % entropy_sources.size()]->poll(accum);
+ ++poll_attempt;
+ }
+ }
+
+ SecureVector<byte> mac_val = mac->final();
+
+ xor_buf(pool, mac_val, mac_val.size());
+ mix_pool();
+
+ if(accum.bits_collected() >= poll_bits)
+ seeded = true;
+ }
+
+/**
+* Add user-supplied entropy
+*/
+void Randpool::add_entropy(const byte input[], u32bit length)
+ {
+ SecureVector<byte> mac_val = mac->process(input, length);
+ xor_buf(pool, mac_val, mac_val.size());
+ mix_pool();
+
+ if(length)
+ seeded = true;
+ }
+
+/**
+* Add another entropy source to the list
+*/
+void Randpool::add_entropy_source(EntropySource* src)
+ {
+ entropy_sources.push_back(src);
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void Randpool::clear() throw()
+ {
+ cipher->clear();
+ mac->clear();
+ pool.clear();
+ buffer.clear();
+ counter.clear();
+ seeded = false;
+ }
+
+/**
+* Return the name of this type
+*/
+std::string Randpool::name() const
+ {
+ return "Randpool(" + cipher->name() + "," + mac->name() + ")";
+ }
+
+/**
+* Randpool Constructor
+*/
+Randpool::Randpool(BlockCipher* cipher_in,
+ MessageAuthenticationCode* mac_in,
+ u32bit pool_blocks,
+ u32bit iter_before_reseed) :
+ ITERATIONS_BEFORE_RESEED(iter_before_reseed),
+ POOL_BLOCKS(pool_blocks),
+ cipher(cipher_in),
+ mac(mac_in)
+ {
+ const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
+ const u32bit OUTPUT_LENGTH = mac->OUTPUT_LENGTH;
+
+ if(OUTPUT_LENGTH < BLOCK_SIZE ||
+ !cipher->valid_keylength(OUTPUT_LENGTH) ||
+ !mac->valid_keylength(OUTPUT_LENGTH))
+ {
+ std::string ciphername = cipher->name(), macname = mac->name();
+ delete cipher;
+ delete mac;
+ throw Internal_Error("Randpool: Invalid algorithm combination " +
+ ciphername + "/" + macname);
+ }
+
+ buffer.create(BLOCK_SIZE);
+ pool.create(POOL_BLOCKS * BLOCK_SIZE);
+ counter.create(12);
+ seeded = false;
+ }
+
+/**
+* Randpool Destructor
+*/
+Randpool::~Randpool()
+ {
+ delete cipher;
+ delete mac;
+
+ std::for_each(entropy_sources.begin(), entropy_sources.end(),
+ del_fun<EntropySource>());
+ }
+
+}
diff --git a/botan/src/rng/randpool/randpool.h b/botan/src/rng/randpool/randpool.h
new file mode 100644
index 0000000..b6a3add
--- /dev/null
+++ b/botan/src/rng/randpool/randpool.h
@@ -0,0 +1,53 @@
+/*
+* Randpool
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RANDPOOL_H__
+#define BOTAN_RANDPOOL_H__
+
+#include <botan/rng.h>
+#include <botan/block_cipher.h>
+#include <botan/mac.h>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Randpool
+*/
+class BOTAN_DLL Randpool : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const { return seeded; }
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit bits_to_collect);
+ void add_entropy_source(EntropySource* es);
+ void add_entropy(const byte input[], u32bit length);
+
+ Randpool(BlockCipher* cipher, MessageAuthenticationCode* mac,
+ u32bit pool_blocks = 32,
+ u32bit iterations_before_reseed = 128);
+
+ ~Randpool();
+ private:
+ void update_buffer();
+ void mix_pool();
+
+ u32bit ITERATIONS_BEFORE_RESEED, POOL_BLOCKS;
+ BlockCipher* cipher;
+ MessageAuthenticationCode* mac;
+
+ std::vector<EntropySource*> entropy_sources;
+ SecureVector<byte> pool, buffer, counter;
+ bool seeded;
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/rng.cpp b/botan/src/rng/rng.cpp
new file mode 100644
index 0000000..aa9b73f
--- /dev/null
+++ b/botan/src/rng/rng.cpp
@@ -0,0 +1,38 @@
+/*
+* Random Number Generator Base
+* (C) 1999-2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ #include <botan/auto_rng.h>
+#endif
+
+namespace Botan {
+
+/*
+* Get a single random byte
+*/
+byte RandomNumberGenerator::next_byte()
+ {
+ byte out;
+ this->randomize(&out, 1);
+ return out;
+ }
+
+/*
+* Create and seed a new RNG object
+*/
+RandomNumberGenerator* RandomNumberGenerator::make_rng()
+ {
+#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
+ return new AutoSeeded_RNG;
+#endif
+
+ throw Algorithm_Not_Found("RandomNumberGenerator::make_rng - no RNG found");
+ }
+
+}
diff --git a/botan/src/rng/rng.h b/botan/src/rng/rng.h
new file mode 100644
index 0000000..41904db
--- /dev/null
+++ b/botan/src/rng/rng.h
@@ -0,0 +1,103 @@
+/*
+* RandomNumberGenerator
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__
+#define BOTAN_RANDOM_NUMBER_GENERATOR_H__
+
+#include <botan/entropy_src.h>
+#include <botan/exceptn.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* This class represents a random number (RNG) generator object.
+*/
+class BOTAN_DLL RandomNumberGenerator
+ {
+ public:
+ /**
+ * Create a seeded and active RNG object for general application use
+ */
+ static RandomNumberGenerator* make_rng();
+
+ /**
+ * Randomize a byte array.
+ * @param output the byte array to hold the random output.
+ * @param length the length of the byte array output.
+ */
+ virtual void randomize(byte output[], u32bit length) = 0;
+
+ /**
+ * Return a random byte
+ * @return random byte
+ */
+ byte next_byte();
+
+ /**
+ * Check whether this RNG is seeded.
+ * @return true if this RNG was already seeded, false otherwise.
+ */
+ virtual bool is_seeded() const { return true; }
+
+ /**
+ * Clear all internally held values of this RNG.
+ */
+ virtual void clear() throw() = 0;
+
+ /**
+ * Return the name of this object
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Seed this RNG using the entropy sources it contains.
+ * @param bits_to_collect is the number of bits of entropy to
+ attempt to gather from the entropy sources
+ */
+ virtual void reseed(u32bit bits_to_collect) = 0;
+
+ /**
+ * Add this entropy source to the RNG object
+ * @param source the entropy source which will be retained and used by RNG
+ */
+ virtual void add_entropy_source(EntropySource* source) = 0;
+
+ /**
+ * Add entropy to this RNG.
+ * @param in a byte array containg the entropy to be added
+ * @param length the length of the byte array in
+ */
+ virtual void add_entropy(const byte in[], u32bit length) = 0;
+
+ RandomNumberGenerator() {}
+ virtual ~RandomNumberGenerator() {}
+ private:
+ RandomNumberGenerator(const RandomNumberGenerator&) {}
+ RandomNumberGenerator& operator=(const RandomNumberGenerator&)
+ { return (*this); }
+ };
+
+/*
+* Null Random Number Generator
+*/
+class BOTAN_DLL Null_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit) { throw PRNG_Unseeded("Null_RNG"); }
+ void clear() throw() {}
+ std::string name() const { return "Null_RNG"; }
+
+ void reseed(u32bit) {}
+ bool is_seeded() const { return false; }
+ void add_entropy(const byte[], u32bit) {}
+ void add_entropy_source(EntropySource* es) { delete es; }
+ };
+
+}
+
+#endif
diff --git a/botan/src/rng/x931_rng/info.txt b/botan/src/rng/x931_rng/info.txt
new file mode 100644
index 0000000..633eb02
--- /dev/null
+++ b/botan/src/rng/x931_rng/info.txt
@@ -0,0 +1,14 @@
+realname "ANSI X9.31 PRNG"
+
+define X931_RNG
+
+load_on auto
+
+<add>
+x931_rng.cpp
+x931_rng.h
+</add>
+
+<requires>
+block
+</requires>
diff --git a/botan/src/rng/x931_rng/x931_rng.cpp b/botan/src/rng/x931_rng/x931_rng.cpp
new file mode 100644
index 0000000..e239bce
--- /dev/null
+++ b/botan/src/rng/x931_rng/x931_rng.cpp
@@ -0,0 +1,154 @@
+/*
+* ANSI X9.31 RNG
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/x931_rng.h>
+#include <botan/xor_buf.h>
+#include <algorithm>
+
+namespace Botan {
+
+/**
+* Generate a buffer of random bytes
+*/
+void ANSI_X931_RNG::randomize(byte out[], u32bit length)
+ {
+ if(!is_seeded())
+ throw PRNG_Unseeded(name());
+
+ while(length)
+ {
+ if(position == R.size())
+ update_buffer();
+
+ const u32bit copied = std::min(length, R.size() - position);
+
+ copy_mem(out, R + position, copied);
+ out += copied;
+ length -= copied;
+ position += copied;
+ }
+ }
+
+/**
+* Refill the internal state
+*/
+void ANSI_X931_RNG::update_buffer()
+ {
+ SecureVector<byte> DT(cipher->BLOCK_SIZE);
+
+ prng->randomize(DT, DT.size());
+ cipher->encrypt(DT);
+
+ xor_buf(R, V, DT, cipher->BLOCK_SIZE);
+ cipher->encrypt(R);
+
+ xor_buf(V, R, DT, cipher->BLOCK_SIZE);
+ cipher->encrypt(V);
+
+ position = 0;
+ }
+
+/**
+* Reset V and the cipher key with new values
+*/
+void ANSI_X931_RNG::rekey()
+ {
+ if(prng->is_seeded())
+ {
+ SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH);
+ prng->randomize(key, key.size());
+ cipher->set_key(key, key.size());
+
+ if(V.size() != cipher->BLOCK_SIZE)
+ V.create(cipher->BLOCK_SIZE);
+ prng->randomize(V, V.size());
+
+ update_buffer();
+ }
+ }
+
+/**
+* Reseed the internal state
+*/
+void ANSI_X931_RNG::reseed(u32bit poll_bits)
+ {
+ prng->reseed(poll_bits);
+ rekey();
+ }
+
+/**
+* Add a entropy source to the underlying PRNG
+*/
+void ANSI_X931_RNG::add_entropy_source(EntropySource* src)
+ {
+ prng->add_entropy_source(src);
+ }
+
+/**
+* Add some entropy to the underlying PRNG
+*/
+void ANSI_X931_RNG::add_entropy(const byte input[], u32bit length)
+ {
+ prng->add_entropy(input, length);
+ rekey();
+ }
+
+/**
+* Check if the the PRNG is seeded
+*/
+bool ANSI_X931_RNG::is_seeded() const
+ {
+ return V.has_items();
+ }
+
+/**
+* Clear memory of sensitive data
+*/
+void ANSI_X931_RNG::clear() throw()
+ {
+ cipher->clear();
+ prng->clear();
+ R.clear();
+ V.destroy();
+
+ position = 0;
+ }
+
+/**
+* Return the name of this type
+*/
+std::string ANSI_X931_RNG::name() const
+ {
+ return "X9.31(" + cipher->name() + ")";
+ }
+
+/**
+* ANSI X931 RNG Constructor
+*/
+ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in,
+ RandomNumberGenerator* prng_in)
+ {
+ if(!prng_in || !cipher_in)
+ throw Invalid_Argument("ANSI_X931_RNG constructor: NULL arguments");
+
+ cipher = cipher_in;
+ prng = prng_in;
+
+ R.create(cipher->BLOCK_SIZE);
+ position = 0;
+ }
+
+/**
+* ANSI X931 RNG Destructor
+*/
+ANSI_X931_RNG::~ANSI_X931_RNG()
+ {
+ delete cipher;
+ delete prng;
+ }
+
+}
diff --git a/botan/src/rng/x931_rng/x931_rng.h b/botan/src/rng/x931_rng/x931_rng.h
new file mode 100644
index 0000000..44e9b44
--- /dev/null
+++ b/botan/src/rng/x931_rng/x931_rng.h
@@ -0,0 +1,45 @@
+/*
+* ANSI X9.31 RNG
+* (C) 1999-2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ANSI_X931_RNG_H__
+#define BOTAN_ANSI_X931_RNG_H__
+
+#include <botan/rng.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+/**
+* ANSI X9.31 RNG
+*/
+class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const;
+ void clear() throw();
+ std::string name() const;
+
+ void reseed(u32bit poll_bits);
+ void add_entropy_source(EntropySource*);
+ void add_entropy(const byte[], u32bit);
+
+ ANSI_X931_RNG(BlockCipher*, RandomNumberGenerator*);
+ ~ANSI_X931_RNG();
+ private:
+ void rekey();
+ void update_buffer();
+
+ BlockCipher* cipher;
+ RandomNumberGenerator* prng;
+ SecureVector<byte> V, R;
+ u32bit position;
+ };
+
+}
+
+#endif