diff options
Diffstat (limited to 'src/rng')
-rw-r--r-- | src/rng/randpool/modinfo.txt | 10 | ||||
-rw-r--r-- | src/rng/randpool/randpool.cpp | 223 | ||||
-rw-r--r-- | src/rng/randpool/randpool.h | 47 | ||||
-rw-r--r-- | src/rng/x931_rng/modinfo.txt | 14 | ||||
-rw-r--r-- | src/rng/x931_rng/x931_rng.cpp | 142 | ||||
-rw-r--r-- | src/rng/x931_rng/x931_rng.h | 42 |
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 |