diff options
Diffstat (limited to 'src/randpool.cpp')
-rw-r--r-- | src/randpool.cpp | 99 |
1 files changed, 67 insertions, 32 deletions
diff --git a/src/randpool.cpp b/src/randpool.cpp index abb75c1f0..24086c984 100644 --- a/src/randpool.cpp +++ b/src/randpool.cpp @@ -1,6 +1,6 @@ /************************************************* * Randpool Source File * -* (C) 1999-2007 Jack Lloyd * +* (C) 1999-2008 Jack Lloyd * *************************************************/ #include <botan/randpool.h> @@ -8,6 +8,7 @@ #include <botan/loadstor.h> #include <botan/bit_ops.h> #include <botan/util.h> +#include <botan/stl_util.h> #include <algorithm> namespace Botan { @@ -18,21 +19,11 @@ namespace { * PRF based on a MAC * *************************************************/ enum RANDPOOL_PRF_TAG { - USER_INPUT = 0, - CIPHER_KEY = 1, - MAC_KEY = 2, - GEN_OUTPUT = 3 + CIPHER_KEY = 0, + MAC_KEY = 1, + GEN_OUTPUT = 2 }; -SecureVector<byte> randpool_prf(MessageAuthenticationCode* mac, - RANDPOOL_PRF_TAG tag, - const byte in[], u32bit length) - { - mac->update(static_cast<byte>(tag)); - mac->update(in, length); - return mac->final(); - } - } /************************************************* @@ -41,7 +32,12 @@ SecureVector<byte> randpool_prf(MessageAuthenticationCode* mac, void Randpool::randomize(byte out[], u32bit length) { if(!is_seeded()) - throw PRNG_Unseeded(name()); + { + reseed(); + + if(!is_seeded()) + throw PRNG_Unseeded(name()); + } update_buffer(); while(length) @@ -66,18 +62,16 @@ void Randpool::update_buffer() break; store_be(timestamp, counter + 4); - SecureVector<byte> mac_val = randpool_prf(mac, GEN_OUTPUT, - counter, counter.size()); + 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(); - update_buffer(); - } } /************************************************* @@ -87,8 +81,13 @@ void Randpool::mix_pool() { const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; - mac->set_key(randpool_prf(mac, MAC_KEY, pool, pool.size())); - cipher->set_key(randpool_prf(mac, CIPHER_KEY, pool, pool.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); @@ -99,20 +98,54 @@ void Randpool::mix_pool() xor_buf(this_block, previous_block, BLOCK_SIZE); cipher->encrypt(this_block); } + + update_buffer(); } /************************************************* -* Add entropy to the internal state * +* Reseed the internal state * *************************************************/ -void Randpool::add_randomness(const byte data[], u32bit length) +void Randpool::reseed() { - u32bit this_entropy = entropy_estimate(data, length); - entropy += std::min(this_entropy, 8*mac->OUTPUT_LENGTH); - entropy = std::min(entropy, 8 * pool.size()); + 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 = randpool_prf(mac, USER_INPUT, data, length); + 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); } /************************************************* @@ -120,7 +153,7 @@ void Randpool::add_randomness(const byte data[], u32bit length) *************************************************/ bool Randpool::is_seeded() const { - return (entropy >= 256); + return (entropy >= 384); } /************************************************* @@ -149,7 +182,7 @@ std::string Randpool::name() const *************************************************/ Randpool::Randpool(const std::string& cipher_name, const std::string& mac_name) : - ITERATIONS_BEFORE_RESEED(8), POOL_BLOCKS(32) + ITERATIONS_BEFORE_RESEED(128), POOL_BLOCKS(32) { cipher = get_block_cipher(cipher_name); mac = get_mac(mac_name); @@ -171,8 +204,6 @@ Randpool::Randpool(const std::string& cipher_name, pool.create(POOL_BLOCKS * BLOCK_SIZE); counter.create(12); entropy = 0; - - mix_pool(); } /************************************************* @@ -182,6 +213,10 @@ Randpool::~Randpool() { delete cipher; delete mac; + + std::for_each(entropy_sources.begin(), entropy_sources.end(), + del_fun<EntropySource>()); + entropy = 0; } |