aboutsummaryrefslogtreecommitdiffstats
path: root/src/rng
diff options
context:
space:
mode:
Diffstat (limited to 'src/rng')
-rw-r--r--src/rng/randpool/modinfo.txt10
-rw-r--r--src/rng/randpool/randpool.cpp223
-rw-r--r--src/rng/randpool/randpool.h47
-rw-r--r--src/rng/x931_rng/modinfo.txt14
-rw-r--r--src/rng/x931_rng/x931_rng.cpp142
-rw-r--r--src/rng/x931_rng/x931_rng.h42
6 files changed, 478 insertions, 0 deletions
diff --git a/src/rng/randpool/modinfo.txt b/src/rng/randpool/modinfo.txt
new file mode 100644
index 000000000..1b2f79b56
--- /dev/null
+++ b/src/rng/randpool/modinfo.txt
@@ -0,0 +1,10 @@
+realname "Randpool RNG"
+
+define RANDPOOL
+
+load_on auto
+
+<add>
+randpool.cpp
+randpool.h
+</add>
diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp
new file mode 100644
index 000000000..69ef3b9e7
--- /dev/null
+++ b/src/rng/randpool/randpool.cpp
@@ -0,0 +1,223 @@
+/*************************************************
+* Randpool Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/randpool.h>
+#include <botan/lookup.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())
+ {
+ reseed();
+
+ 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 j = 0; j != counter.size(); ++j)
+ if(++counter[j])
+ 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 j = 0; j != mac_val.size(); ++j)
+ buffer[j % buffer.size()] ^= mac_val[j];
+ 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 j = 1; j != POOL_BLOCKS; ++j)
+ {
+ const byte* previous_block = pool + BLOCK_SIZE*(j-1);
+ byte* this_block = pool + BLOCK_SIZE*j;
+ xor_buf(this_block, previous_block, BLOCK_SIZE);
+ cipher->encrypt(this_block);
+ }
+
+ update_buffer();
+ }
+
+/*************************************************
+* Reseed the internal state *
+*************************************************/
+void Randpool::reseed()
+ {
+ SecureVector<byte> buffer(1024);
+ u32bit gathered_entropy = 0;
+
+ for(u32bit j = 0; j != entropy_sources.size(); ++j)
+ {
+ u32bit got = entropy_sources[j]->slow_poll(buffer, buffer.size());
+
+ mac->update(buffer, got);
+
+ gathered_entropy += entropy_estimate(buffer, got);
+ if(gathered_entropy > 512)
+ break;
+ }
+
+ SecureVector<byte> mac_val = mac->final();
+ xor_buf(pool, mac_val, mac_val.size());
+ mix_pool();
+
+ entropy += gathered_entropy;
+ }
+
+/*************************************************
+* 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();
+
+ entropy += entropy_estimate(input, length);
+ }
+
+/*************************************************
+* Add another entropy source to the list *
+*************************************************/
+void Randpool::add_entropy_source(EntropySource* src)
+ {
+ entropy_sources.push_back(src);
+ }
+
+/*************************************************
+* Check if the the pool is seeded *
+*************************************************/
+bool Randpool::is_seeded() const
+ {
+ return (entropy >= 384);
+ }
+
+/*************************************************
+* Clear memory of sensitive data *
+*************************************************/
+void Randpool::clear() throw()
+ {
+ cipher->clear();
+ mac->clear();
+ pool.clear();
+ buffer.clear();
+ counter.clear();
+ entropy = 0;
+ }
+
+/*************************************************
+* Return the name of this type *
+*************************************************/
+std::string Randpool::name() const
+ {
+ return "Randpool(" + cipher->name() + "," + mac->name() + ")";
+ }
+
+/*************************************************
+* Randpool Constructor *
+*************************************************/
+Randpool::Randpool(const std::string& cipher_name,
+ const std::string& mac_name) :
+ ITERATIONS_BEFORE_RESEED(128), POOL_BLOCKS(32)
+ {
+ cipher = get_block_cipher(cipher_name);
+ mac = get_mac(mac_name);
+
+ 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))
+ {
+ delete cipher;
+ delete mac;
+ throw Internal_Error("Randpool: Invalid algorithm combination " +
+ cipher_name + "/" + mac_name);
+ }
+
+ buffer.create(BLOCK_SIZE);
+ pool.create(POOL_BLOCKS * BLOCK_SIZE);
+ counter.create(12);
+ entropy = 0;
+ }
+
+/*************************************************
+* Randpool Destructor *
+*************************************************/
+Randpool::~Randpool()
+ {
+ delete cipher;
+ delete mac;
+
+ std::for_each(entropy_sources.begin(), entropy_sources.end(),
+ del_fun<EntropySource>());
+
+ entropy = 0;
+ }
+
+}
diff --git a/src/rng/randpool/randpool.h b/src/rng/randpool/randpool.h
new file mode 100644
index 000000000..b68dec765
--- /dev/null
+++ b/src/rng/randpool/randpool.h
@@ -0,0 +1,47 @@
+/*************************************************
+* Randpool Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_RANDPOOL_H__
+#define BOTAN_RANDPOOL_H__
+
+#include <botan/rng.h>
+#include <botan/base.h>
+#include <vector>
+
+namespace Botan {
+
+/*************************************************
+* Randpool *
+*************************************************/
+class BOTAN_DLL Randpool : public RandomNumberGenerator
+ {
+ public:
+ void randomize(byte[], u32bit);
+ bool is_seeded() const;
+ void clear() throw();
+ std::string name() const;
+
+ void reseed();
+ void add_entropy_source(EntropySource*);
+ void add_entropy(const byte[], u32bit);
+
+ Randpool(const std::string&, const std::string&);
+ ~Randpool();
+ private:
+ void update_buffer();
+ void mix_pool();
+
+ const u32bit ITERATIONS_BEFORE_RESEED, POOL_BLOCKS;
+ BlockCipher* cipher;
+ MessageAuthenticationCode* mac;
+
+ std::vector<EntropySource*> entropy_sources;
+ SecureVector<byte> pool, buffer, counter;
+ u32bit entropy;
+ };
+
+}
+
+#endif
diff --git a/src/rng/x931_rng/modinfo.txt b/src/rng/x931_rng/modinfo.txt
new file mode 100644
index 000000000..79e436822
--- /dev/null
+++ b/src/rng/x931_rng/modinfo.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>
+randpool
+</requires>
diff --git a/src/rng/x931_rng/x931_rng.cpp b/src/rng/x931_rng/x931_rng.cpp
new file mode 100644
index 000000000..f4b0f71a9
--- /dev/null
+++ b/src/rng/x931_rng/x931_rng.cpp
@@ -0,0 +1,142 @@
+/*************************************************
+* ANSI X9.31 RNG Source File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#include <botan/x931_rng.h>
+#include <botan/lookup.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())
+ reseed();
+
+ 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;
+ }
+
+/*************************************************
+* Reseed the internal state *
+*************************************************/
+void ANSI_X931_RNG::reseed()
+ {
+ prng->reseed();
+
+ 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();
+ }
+
+/*************************************************
+* 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);
+ }
+
+/*************************************************
+* 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(const std::string& cipher_name,
+ RandomNumberGenerator* prng_ptr)
+ {
+ if(!prng_ptr)
+ throw Invalid_Argument("ANSI_X931_RNG constructor: NULL prng");
+
+ prng = prng_ptr;
+ cipher = get_block_cipher(cipher_name);
+
+ R.create(cipher->BLOCK_SIZE);
+ position = 0;
+ }
+
+/*************************************************
+* ANSI X931 RNG Destructor *
+*************************************************/
+ANSI_X931_RNG::~ANSI_X931_RNG()
+ {
+ delete cipher;
+ delete prng;
+ }
+
+}
diff --git a/src/rng/x931_rng/x931_rng.h b/src/rng/x931_rng/x931_rng.h
new file mode 100644
index 000000000..7914b605d
--- /dev/null
+++ b/src/rng/x931_rng/x931_rng.h
@@ -0,0 +1,42 @@
+/*************************************************
+* ANSI X9.31 RNG Header File *
+* (C) 1999-2008 Jack Lloyd *
+*************************************************/
+
+#ifndef BOTAN_ANSI_X931_RNG_H__
+#define BOTAN_ANSI_X931_RNG_H__
+
+#include <botan/rng.h>
+#include <botan/base.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();
+ void add_entropy_source(EntropySource*);
+ void add_entropy(const byte[], u32bit);
+
+ ANSI_X931_RNG(const std::string&, RandomNumberGenerator*);
+ ~ANSI_X931_RNG();
+ private:
+ void update_buffer();
+
+ BlockCipher* cipher;
+ RandomNumberGenerator* prng;
+ SecureVector<byte> V, R;
+ u32bit position;
+ };
+
+}
+
+#endif