diff options
-rw-r--r-- | doc/examples/rng_test.cpp | 2 | ||||
-rw-r--r-- | doc/examples/test_es.cpp | 23 | ||||
-rw-r--r-- | src/entropy/dev_random/es_dev.cpp | 13 | ||||
-rw-r--r-- | src/entropy/entropy_src.h | 39 | ||||
-rw-r--r-- | src/entropy/unix_procs/es_unix.cpp | 9 | ||||
-rw-r--r-- | src/rng/hmac_rng/hmac_rng.cpp | 21 | ||||
-rw-r--r-- | src/rng/hmac_rng/hmac_rng.h | 4 | ||||
-rw-r--r-- | src/rng/randpool/randpool.cpp | 24 | ||||
-rw-r--r-- | src/rng/randpool/randpool.h | 4 | ||||
-rw-r--r-- | src/rng/x931_rng/x931_rng.cpp | 82 | ||||
-rw-r--r-- | src/rng/x931_rng/x931_rng.h | 15 | ||||
-rw-r--r-- | src/utils/mem_ops.h | 16 |
12 files changed, 129 insertions, 123 deletions
diff --git a/doc/examples/rng_test.cpp b/doc/examples/rng_test.cpp index e38628d15..9ecb04e78 100644 --- a/doc/examples/rng_test.cpp +++ b/doc/examples/rng_test.cpp @@ -58,6 +58,8 @@ class Fixed_Output_RNG : public RandomNumberGenerator std::string name() const { return "Fixed_Output_RNG"; } + void reseed(u32bit) {} + void clear() throw() {} void add_entropy(const byte in[], u32bit len) diff --git a/doc/examples/test_es.cpp b/doc/examples/test_es.cpp index b7b2e9162..5d0c1ae5a 100644 --- a/doc/examples/test_es.cpp +++ b/doc/examples/test_es.cpp @@ -32,19 +32,21 @@ using namespace Botan; -class Saver_Of_Bytes : public BufferedComputation +class Saver_Of_Bytes : public Entropy_Accumulator { public: - Saver_Of_Bytes() : BufferedComputation(0), outbuf(64), written(0) {} - void add_data(const byte in[], u32bit length) + Saver_Of_Bytes(u32bit bits) : + Entropy_Accumulator(bits), outbuf(64), written(0) {} + + void add_bytes(const byte in[], u32bit length) { for(size_t i = 0; i != length; ++i) outbuf[i % outbuf.size()] ^= in[i]; written += length; - //outbuf.insert(outbuf.end(), in, in+length); } - void final_result(byte[]) { if(written < 64) outbuf.resize(written); } + + void trunc() { if(written < 64) outbuf.resize(written); } std::vector<byte> outbuf; u32bit written; @@ -56,16 +58,15 @@ void test_entropy_source(EntropySource* es) printf("Polling '%s':\n", es->name().c_str()); - Saver_Of_Bytes save; + Saver_Of_Bytes accum(128); - Entropy_Accumulator accum(save, 128); es->poll(accum); - save.final_result(0); + accum.trunc(); - printf("Got %d bytes\n", save.written); - for(size_t i = 0; i != save.outbuf.size(); ++i) - printf("%02X", save.outbuf[i]); + printf("Got %d bytes\n", accum.written); + for(size_t i = 0; i != accum.outbuf.size(); ++i) + printf("%02X", accum.outbuf[i]); printf("\n"); delete es; diff --git a/src/entropy/dev_random/es_dev.cpp b/src/entropy/dev_random/es_dev.cpp index 60e1a4df6..89f981373 100644 --- a/src/entropy/dev_random/es_dev.cpp +++ b/src/entropy/dev_random/es_dev.cpp @@ -51,12 +51,7 @@ u32bit Device_EntropySource::Device_Reader::get(byte out[], u32bit length, if(got <= 0) return 0; - const u32bit ret = static_cast<u32bit>(got); - - if(ret > length) - return 0; - - return ret; + return static_cast<u32bit>(got); } /** @@ -106,16 +101,16 @@ Device_EntropySource::~Device_EntropySource() */ void Device_EntropySource::poll(Entropy_Accumulator& accum) { - const u32bit MAX_READ_WAIT_MILLISECONDS = 50; + u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 16); - u32bit go_get = std::min<u32bit>(accum.desired_remaining_bits() / 8, 32); + u32bit read_wait_ms = go_get / 16; MemoryRegion<byte>& io_buffer = accum.get_io_buffer(go_get); for(size_t i = 0; i != devices.size(); ++i) { u32bit got = devices[i].get(io_buffer.begin(), io_buffer.size(), - MAX_READ_WAIT_MILLISECONDS); + read_wait_ms); if(got) { diff --git a/src/entropy/entropy_src.h b/src/entropy/entropy_src.h index 96ffcad0b..eb3a841b4 100644 --- a/src/entropy/entropy_src.h +++ b/src/entropy/entropy_src.h @@ -18,8 +18,10 @@ namespace Botan { class Entropy_Accumulator { public: - Entropy_Accumulator(BufferedComputation& sink, u32bit goal) : - entropy_sink(sink), entropy_goal(goal), collected_bits(0) {} + Entropy_Accumulator(u32bit goal) : + entropy_goal(goal), collected_bits(0) {} + + virtual ~Entropy_Accumulator() {} /** @return cached I/O buffer for repeated polls @@ -27,20 +29,23 @@ class Entropy_Accumulator MemoryRegion<byte>& get_io_buffer(u32bit size) { io_buffer.create(size); return io_buffer; } - u32bit bits_collected() const { return collected_bits; } + u32bit bits_collected() const + { return static_cast<u32bit>(collected_bits); } bool polling_goal_achieved() const { return (collected_bits >= entropy_goal); } u32bit desired_remaining_bits() const { - return (collected_bits >= entropy_goal) ? 0 : (entropy_goal - collected_bits); + if(collected_bits >= entropy_goal) + return 0; + return (entropy_goal - collected_bits); } void add(const void* bytes, u32bit length, double entropy_bits_per_byte) { - entropy_sink.update(reinterpret_cast<const byte*>(bytes), length); - collected_bits += std::min<u32bit>(8, entropy_bits_per_byte) * length; + add_bytes(reinterpret_cast<const byte*>(bytes), length); + collected_bits += entropy_bits_per_byte * length; } template<typename T> @@ -49,9 +54,27 @@ class Entropy_Accumulator add(&v, sizeof(T), entropy_bits_per_byte); } private: - BufferedComputation& entropy_sink; + virtual void add_bytes(const byte bytes[], u32bit length) = 0; + SecureVector<byte> io_buffer; - u32bit entropy_goal, collected_bits; + u32bit entropy_goal; + double collected_bits; + }; + +class Entropy_Accumulator_BufferedComputation : public Entropy_Accumulator + { + public: + Entropy_Accumulator_BufferedComputation(BufferedComputation& sink, + u32bit goal) : + Entropy_Accumulator(goal), entropy_sink(sink) {} + + private: + virtual void add_bytes(const byte bytes[], u32bit length) + { + entropy_sink.update(bytes, length); + } + + BufferedComputation& entropy_sink; }; /** diff --git a/src/entropy/unix_procs/es_unix.cpp b/src/entropy/unix_procs/es_unix.cpp index 3ac8cd8d3..c8cf6daec 100644 --- a/src/entropy/unix_procs/es_unix.cpp +++ b/src/entropy/unix_procs/es_unix.cpp @@ -66,7 +66,7 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum) struct stat statbuf; clear_mem(&statbuf, 1); ::stat(stat_targets[j], &statbuf); - accum.add(&statbuf, sizeof(statbuf), .05); + accum.add(&statbuf, sizeof(statbuf), .005); } accum.add(::getpid(), 0); @@ -79,13 +79,10 @@ void Unix_EntropySource::poll(Entropy_Accumulator& accum) struct ::rusage usage; ::getrusage(RUSAGE_SELF, &usage); - accum.add(usage, .05); + accum.add(usage, .005); ::getrusage(RUSAGE_CHILDREN, &usage); - accum.add(usage, .05); - - if(accum.desired_remaining_bits() < 128) - return; + accum.add(usage, .005); const u32bit MINIMAL_WORKING = 16; diff --git a/src/rng/hmac_rng/hmac_rng.cpp b/src/rng/hmac_rng/hmac_rng.cpp index ffdfdc60d..458118e11 100644 --- a/src/rng/hmac_rng/hmac_rng.cpp +++ b/src/rng/hmac_rng/hmac_rng.cpp @@ -69,7 +69,7 @@ void HMAC_RNG::reseed_with_input(u32bit poll_bits, feedback of the current PRK value, into the extractor function. */ - Entropy_Accumulator accum(*extractor, poll_bits); + Entropy_Accumulator_BufferedComputation accum(*extractor, poll_bits); for(u32bit i = 0; i < entropy_sources.size(); ++i) { @@ -112,9 +112,8 @@ void HMAC_RNG::reseed_with_input(u32bit poll_bits, K.clear(); counter = 0; - // Upper bound entropy estimate at the extractor output size - entropy = std::min<u32bit>(entropy + accum.bits_collected(), - 8 * extractor->OUTPUT_LENGTH); + if(input_length || accum.bits_collected() >= poll_bits) + seeded = true; } /** @@ -142,14 +141,6 @@ void HMAC_RNG::add_entropy_source(EntropySource* src) entropy_sources.push_back(src); } -/** -* Check if the the pool is seeded -*/ -bool HMAC_RNG::is_seeded() const - { - return (entropy >= 8 * prf->OUTPUT_LENGTH); - } - /* * Clear memory of sensitive data */ @@ -158,8 +149,8 @@ void HMAC_RNG::clear() throw() extractor->clear(); prf->clear(); K.clear(); - entropy = 0; counter = 0; + seeded = false; } /** @@ -177,11 +168,10 @@ HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor_mac, MessageAuthenticationCode* prf_mac) : extractor(extractor_mac), prf(prf_mac) { - entropy = 0; - // 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 @@ -223,7 +213,6 @@ HMAC_RNG::~HMAC_RNG() std::for_each(entropy_sources.begin(), entropy_sources.end(), del_fun<EntropySource>()); - entropy = 0; counter = 0; } diff --git a/src/rng/hmac_rng/hmac_rng.h b/src/rng/hmac_rng/hmac_rng.h index fbfa8df19..16adddd60 100644 --- a/src/rng/hmac_rng/hmac_rng.h +++ b/src/rng/hmac_rng/hmac_rng.h @@ -26,7 +26,7 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator { public: void randomize(byte buf[], u32bit len); - bool is_seeded() const; + bool is_seeded() const { return seeded; } void clear() throw(); std::string name() const; @@ -46,7 +46,7 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator MessageAuthenticationCode* prf; std::vector<EntropySource*> entropy_sources; - u32bit entropy; + bool seeded; SecureVector<byte> K, io_buffer; u32bit counter, source_index; diff --git a/src/rng/randpool/randpool.cpp b/src/rng/randpool/randpool.cpp index 41a8ca23a..af36c335f 100644 --- a/src/rng/randpool/randpool.cpp +++ b/src/rng/randpool/randpool.cpp @@ -101,7 +101,7 @@ void Randpool::mix_pool() */ void Randpool::reseed(u32bit poll_bits) { - Entropy_Accumulator accum(*mac, poll_bits); + Entropy_Accumulator_BufferedComputation accum(*mac, poll_bits); for(u32bit i = 0; i != entropy_sources.size(); ++i) { @@ -116,8 +116,8 @@ void Randpool::reseed(u32bit poll_bits) xor_buf(pool, mac_val, mac_val.size()); mix_pool(); - entropy = std::min<u32bit>(entropy + accum.bits_collected(), - 8 * mac_val.size()); + if(accum.bits_collected() >= poll_bits) + seeded = true; } /** @@ -129,8 +129,8 @@ void Randpool::add_entropy(const byte input[], u32bit length) xor_buf(pool, mac_val, mac_val.size()); mix_pool(); - // Assume 1 bit conditional entropy per byte of input - entropy = std::min<u32bit>(entropy + length, 8 * mac_val.size()); + if(length) + seeded = true; } /** @@ -142,14 +142,6 @@ void Randpool::add_entropy_source(EntropySource* src) } /** -* Check if the the pool is seeded -*/ -bool Randpool::is_seeded() const - { - return (entropy >= 7 * mac->OUTPUT_LENGTH); - } - -/** * Clear memory of sensitive data */ void Randpool::clear() throw() @@ -159,7 +151,7 @@ void Randpool::clear() throw() pool.clear(); buffer.clear(); counter.clear(); - entropy = 0; + seeded = false; } /** @@ -198,7 +190,7 @@ Randpool::Randpool(BlockCipher* cipher_in, buffer.create(BLOCK_SIZE); pool.create(POOL_BLOCKS * BLOCK_SIZE); counter.create(12); - entropy = 0; + seeded = false; } /** @@ -211,8 +203,6 @@ Randpool::~Randpool() 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 index 46683934e..f44527609 100644 --- a/src/rng/randpool/randpool.h +++ b/src/rng/randpool/randpool.h @@ -20,7 +20,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator { public: void randomize(byte[], u32bit); - bool is_seeded() const; + bool is_seeded() const { return seeded; } void clear() throw(); std::string name() const; @@ -43,7 +43,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator std::vector<EntropySource*> entropy_sources; SecureVector<byte> pool, buffer, counter; - u32bit entropy; + bool seeded; }; } diff --git a/src/rng/x931_rng/x931_rng.cpp b/src/rng/x931_rng/x931_rng.cpp index 4b33f4c5e..e77f04ae4 100644 --- a/src/rng/x931_rng/x931_rng.cpp +++ b/src/rng/x931_rng/x931_rng.cpp @@ -1,7 +1,7 @@ -/************************************************* -* ANSI X9.31 RNG Source File * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ +/* +* ANSI X9.31 RNG Source File +* (C) 1999-2009 Jack Lloyd +*/ #include <botan/x931_rng.h> #include <botan/xor_buf.h> @@ -9,9 +9,9 @@ namespace Botan { -/************************************************* -* Generate a buffer of random bytes * -*************************************************/ +/** +* Generate a buffer of random bytes +*/ void ANSI_X931_RNG::randomize(byte out[], u32bit length) { if(!is_seeded()) @@ -31,9 +31,9 @@ void ANSI_X931_RNG::randomize(byte out[], u32bit length) } } -/************************************************* -* Refill the internal state * -*************************************************/ +/** +* Refill the internal state +*/ void ANSI_X931_RNG::update_buffer() { SecureVector<byte> DT(cipher->BLOCK_SIZE); @@ -50,13 +50,11 @@ void ANSI_X931_RNG::update_buffer() position = 0; } -/************************************************* -* Reseed the internal state * -*************************************************/ -void ANSI_X931_RNG::reseed(u32bit poll_bits) +/** +* Reset V and the cipher key with new values +*/ +void ANSI_X931_RNG::rekey() { - prng->reseed(poll_bits); - if(prng->is_seeded()) { SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH); @@ -71,33 +69,43 @@ void ANSI_X931_RNG::reseed(u32bit poll_bits) } } -/************************************************* -* Add a entropy source to the underlying PRNG * -*************************************************/ +/** +* 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 * -*************************************************/ +/** +* 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 * -*************************************************/ +/** +* Check if the the PRNG is seeded +*/ bool ANSI_X931_RNG::is_seeded() const { return V.has_items(); } -/************************************************* -* Clear memory of sensitive data * -*************************************************/ +/** +* Clear memory of sensitive data +*/ void ANSI_X931_RNG::clear() throw() { cipher->clear(); @@ -108,17 +116,17 @@ void ANSI_X931_RNG::clear() throw() position = 0; } -/************************************************* -* Return the name of this type * -*************************************************/ +/** +* 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 Constructor +*/ ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in, RandomNumberGenerator* prng_in) { @@ -132,9 +140,9 @@ ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in, position = 0; } -/************************************************* -* ANSI X931 RNG Destructor * -*************************************************/ +/** +* ANSI X931 RNG Destructor +*/ ANSI_X931_RNG::~ANSI_X931_RNG() { delete cipher; diff --git a/src/rng/x931_rng/x931_rng.h b/src/rng/x931_rng/x931_rng.h index 2c68b9cb4..b1cef8df3 100644 --- a/src/rng/x931_rng/x931_rng.h +++ b/src/rng/x931_rng/x931_rng.h @@ -1,7 +1,7 @@ -/************************************************* -* ANSI X9.31 RNG Header File * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ +/* +* ANSI X9.31 RNG Header File +* (C) 1999-2009 Jack Lloyd +*/ #ifndef BOTAN_ANSI_X931_RNG_H__ #define BOTAN_ANSI_X931_RNG_H__ @@ -11,9 +11,9 @@ namespace Botan { -/************************************************* -* ANSI X9.31 RNG * -*************************************************/ +/** +* ANSI X9.31 RNG +*/ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator { public: @@ -29,6 +29,7 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator ANSI_X931_RNG(BlockCipher*, RandomNumberGenerator*); ~ANSI_X931_RNG(); private: + void rekey(); void update_buffer(); BlockCipher* cipher; diff --git a/src/utils/mem_ops.h b/src/utils/mem_ops.h index 810356bce..e72269e6a 100644 --- a/src/utils/mem_ops.h +++ b/src/utils/mem_ops.h @@ -1,7 +1,7 @@ -/************************************************* -* Memory Operations Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/* +* Memory Operations Header File +* (C) 1999-2009 Jack Lloyd +*/ #ifndef BOTAN_MEMORY_OPS_H__ #define BOTAN_MEMORY_OPS_H__ @@ -11,14 +11,14 @@ namespace Botan { -/************************************************* -* Memory Manipulation Functions * -*************************************************/ +/* +* Memory Manipulation Functions +*/ template<typename T> inline void copy_mem(T* out, const T* in, u32bit n) { std::memmove(out, in, sizeof(T)*n); } template<typename T> inline void clear_mem(T* ptr, u32bit n) - { std::memset(ptr, 0, sizeof(T)*n); } + { if(n) std::memset(ptr, 0, sizeof(T)*n); } template<typename T> inline void set_mem(T* ptr, u32bit n, byte val) { std::memset(ptr, val, sizeof(T)*n); } |