diff options
author | lloyd <[email protected]> | 2008-06-27 18:30:07 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-06-27 18:30:07 +0000 |
commit | e2a465b75d8baeac912e3f4d428ebc5e03fd76f1 (patch) | |
tree | 7490308782cbac8b0ec9ca0cc23d73ec8a0a7b68 | |
parent | d84a769cc563aebeae3893f952cba1659562e430 (diff) |
New structure for entropy sources + RNGs. The entropy sources are owned by
Randpool, it will query them as needed (or if asked to do so). New function
make_rng() that creates an RNG (X9.31 backed by a Randpool) and seeds it.
Remove the entropy source related code from the Modules/Builtin_Modules
classes.
-rw-r--r-- | checks/dolook2.cpp | 25 | ||||
-rw-r--r-- | checks/rng.cpp | 12 | ||||
-rw-r--r-- | doc/log.txt | 2 | ||||
-rw-r--r-- | include/modules.h | 4 | ||||
-rw-r--r-- | include/randpool.h | 9 | ||||
-rw-r--r-- | include/rng.h | 10 | ||||
-rw-r--r-- | include/x931_rng.h | 5 | ||||
-rw-r--r-- | src/modules.cpp | 98 | ||||
-rw-r--r-- | src/randpool.cpp | 99 | ||||
-rw-r--r-- | src/rng.cpp | 109 | ||||
-rw-r--r-- | src/x931_rng.cpp | 27 |
11 files changed, 202 insertions, 198 deletions
diff --git a/checks/dolook2.cpp b/checks/dolook2.cpp index f52d1fc09..a47efaff9 100644 --- a/checks/dolook2.cpp +++ b/checks/dolook2.cpp @@ -113,28 +113,31 @@ Filter* lookup_rng(const std::string& algname, RandomNumberGenerator* prng = 0; if(algname == "X9.31-RNG(TripleDES)") - prng = new ANSI_X931_RNG("TripleDES", new Fixed_Output_RNG); + prng = new ANSI_X931_RNG("TripleDES", new Fixed_Output_RNG(decode_hex(key))); else if(algname == "X9.31-RNG(AES-128)") - prng = new ANSI_X931_RNG("AES-128", new Fixed_Output_RNG); + prng = new ANSI_X931_RNG("AES-128", new Fixed_Output_RNG(decode_hex(key))); else if(algname == "X9.31-RNG(AES-192)") - prng = new ANSI_X931_RNG("AES-192", new Fixed_Output_RNG); + prng = new ANSI_X931_RNG("AES-192", new Fixed_Output_RNG(decode_hex(key))); else if(algname == "X9.31-RNG(AES-256)") - prng = new ANSI_X931_RNG("AES-256", new Fixed_Output_RNG); + prng = new ANSI_X931_RNG("AES-256", new Fixed_Output_RNG(decode_hex(key))); // these are used for benchmarking: AES-256/SHA-256 matches library // defaults, so benchmark reflects real-world performance (maybe) else if(algname == "Randpool") - prng = new Randpool("AES-256", "HMAC(SHA-256)"); + { + Randpool* randpool = new Randpool("AES-256", "HMAC(SHA-256)"); + randpool->add_entropy((const byte*)key.c_str(), key.length()); + prng = randpool; + } else if(algname == "X9.31-RNG") - prng = new ANSI_X931_RNG("AES-256", - new Randpool("AES-256", "HMAC(SHA-256)")); + { + Randpool* randpool = new Randpool("AES-256", "HMAC(SHA-256)"); + randpool->add_entropy((const byte*)key.c_str(), key.length()); + prng = new ANSI_X931_RNG("AES-256", randpool); + } if(prng) - { - SecureVector<byte> seed = decode_hex(key); - prng->add_entropy(seed.begin(), seed.size()); return new RNG_Filter(prng); - } return 0; } diff --git a/checks/rng.cpp b/checks/rng.cpp index 03c4d9990..05cd4da8e 100644 --- a/checks/rng.cpp +++ b/checks/rng.cpp @@ -1,9 +1,5 @@ #include "common.h" -#include <botan/x931_rng.h> -#include <botan/randpool.h> -#include <botan/es_dev.h> -#include <botan/parsing.h> using namespace Botan; @@ -12,13 +8,7 @@ RandomNumberGenerator& global_rng() static RandomNumberGenerator* rng = 0; if(!rng) - { - rng = new ANSI_X931_RNG("AES-256", new Randpool("AES-256", "HMAC(SHA-256)")); - - Device_EntropySource dev(split_on("/dev/random:/dev/srandom:/dev/urandom", ':')); - - rng->add_entropy(dev); - } + rng = make_rng(); return *rng; } diff --git a/doc/log.txt b/doc/log.txt index e48877393..1c7a4b4ef 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,6 +1,6 @@ * 1.7.7, 2008-07-?? - - Remove many uses of the global PRNG object + - Remove the global PRNG object - Add a test suite for the ANSI X9.31 PRNG - Much cleaner and (mostly) thread-safe reimplementation of es_ftw - Remove both default arguments to ANSI_X931_RNG's constructor diff --git a/include/modules.h b/include/modules.h index fb021405a..48a07c437 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1,6 +1,6 @@ /************************************************* * Module Factory Header File * -* (C) 1999-2007 Jack Lloyd * +* (C) 1999-2008 Jack Lloyd * *************************************************/ #ifndef BOTAN_MODULE_FACTORIES_H__ @@ -23,7 +23,6 @@ class BOTAN_DLL Modules virtual std::string default_allocator() const = 0; virtual std::vector<class Allocator*> allocators() const = 0; - virtual std::vector<class EntropySource*> entropy_sources() const = 0; virtual std::vector<class Engine*> engines() const = 0; virtual ~Modules() {} @@ -40,7 +39,6 @@ class BOTAN_DLL Builtin_Modules : public Modules std::string default_allocator() const; std::vector<class Allocator*> allocators() const; - std::vector<class EntropySource*> entropy_sources() const; std::vector<class Engine*> engines() const; Builtin_Modules(const InitializerOptions&); diff --git a/include/randpool.h b/include/randpool.h index e73ba7f3e..b68dec765 100644 --- a/include/randpool.h +++ b/include/randpool.h @@ -1,6 +1,6 @@ /************************************************* * Randpool Header File * -* (C) 1999-2007 Jack Lloyd * +* (C) 1999-2008 Jack Lloyd * *************************************************/ #ifndef BOTAN_RANDPOOL_H__ @@ -8,6 +8,7 @@ #include <botan/rng.h> #include <botan/base.h> +#include <vector> namespace Botan { @@ -22,10 +23,13 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator 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 add_randomness(const byte[], u32bit); void update_buffer(); void mix_pool(); @@ -33,6 +37,7 @@ class BOTAN_DLL Randpool : public RandomNumberGenerator BlockCipher* cipher; MessageAuthenticationCode* mac; + std::vector<EntropySource*> entropy_sources; SecureVector<byte> pool, buffer, counter; u32bit entropy; }; diff --git a/include/rng.h b/include/rng.h index 3a3b66251..fc75237cc 100644 --- a/include/rng.h +++ b/include/rng.h @@ -33,14 +33,16 @@ class BOTAN_DLL RandomNumberGenerator byte next_byte(); - void add_entropy(const byte[], u32bit); - u32bit add_entropy(EntropySource&, bool = true); + virtual void reseed() {}; virtual ~RandomNumberGenerator() {} - private: - virtual void add_randomness(const byte[], u32bit) = 0; }; +/************************************************* +* Create and seed an RNG * +*************************************************/ +RandomNumberGenerator* make_rng(); + } #endif diff --git a/include/x931_rng.h b/include/x931_rng.h index 0076bb3f7..2ba39361d 100644 --- a/include/x931_rng.h +++ b/include/x931_rng.h @@ -1,6 +1,6 @@ /************************************************* * ANSI X9.31 RNG Header File * -* (C) 1999-2007 Jack Lloyd * +* (C) 1999-2008 Jack Lloyd * *************************************************/ #ifndef BOTAN_ANSI_X931_RNG_H__ @@ -22,10 +22,11 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator void clear() throw(); std::string name() const; + void reseed(); + ANSI_X931_RNG(const std::string&, RandomNumberGenerator*); ~ANSI_X931_RNG(); private: - void add_randomness(const byte[], u32bit); void update_buffer(); BlockCipher* cipher; diff --git a/src/modules.cpp b/src/modules.cpp index 089281e61..a5016aa8c 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -1,6 +1,6 @@ /************************************************* * Module Factory Source File * -* (C) 1999-2007 Jack Lloyd * +* (C) 1999-2008 Jack Lloyd * *************************************************/ #include <botan/modules.h> @@ -21,16 +21,6 @@ #include <botan/mmap_mem.h> #endif -#if defined(BOTAN_EXT_TIMER_HARDWARE) - #include <botan/tm_hard.h> -#elif defined(BOTAN_EXT_TIMER_POSIX) - #include <botan/tm_posix.h> -#elif defined(BOTAN_EXT_TIMER_UNIX) - #include <botan/tm_unix.h> -#elif defined(BOTAN_EXT_TIMER_WIN32) - #include <botan/tm_win32.h> -#endif - #if defined(BOTAN_EXT_ENGINE_GNU_MP) #include <botan/eng_gmp.h> #endif @@ -39,34 +29,6 @@ #include <botan/eng_ossl.h> #endif -#if defined(BOTAN_EXT_ENTROPY_SRC_DEVICE) - #include <botan/es_dev.h> -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_EGD) - #include <botan/es_egd.h> -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_UNIX) - #include <botan/es_unix.h> -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_BEOS) - #include <botan/es_beos.h> -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_CAPI) - #include <botan/es_capi.h> -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_WIN32) - #include <botan/es_win32.h> -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_FTW) - #include <botan/es_ftw.h> -#endif - namespace Botan { /************************************************* @@ -120,64 +82,6 @@ std::string Builtin_Modules::default_allocator() const } /************************************************* -* Register any usable entropy sources * -*************************************************/ -std::vector<EntropySource*> Builtin_Modules::entropy_sources() const - { - std::vector<EntropySource*> sources; - -#if defined(BOTAN_EXT_TIMER_HARDWARE) - sources.push_back(new Hardware_Timer); -#elif defined(BOTAN_EXT_TIMER_POSIX) - sources.push_back(new POSIX_Timer); -#elif defined(BOTAN_EXT_TIMER_UNIX) - sources.push_back(new Unix_Timer); -#elif defined(BOTAN_EXT_TIMER_WIN32) - sources.push_back(new Win32_Timer); -#else - sources.push_back(new Timer); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_EGD) - sources.push_back( - new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':')) - ); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_DEVICE) - sources.push_back( - new Device_EntropySource( - split_on("/dev/random:/dev/srandom:/dev/urandom", ':') - ) - ); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_CAPI) - sources.push_back(new Win32_CAPI_EntropySource); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_WIN32) - sources.push_back(new Win32_EntropySource); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_UNIX) - sources.push_back( - new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':')) - ); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_BEOS) - sources.push_back(new BeOS_EntropySource); -#endif - -#if defined(BOTAN_EXT_ENTROPY_SRC_FTW) - sources.push_back(new FTW_EntropySource("/proc")); -#endif - - return sources; - } - -/************************************************* * Find any usable engines * *************************************************/ std::vector<Engine*> Builtin_Modules::engines() const 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; } diff --git a/src/rng.cpp b/src/rng.cpp index 59d4e576d..5b1bf6915 100644 --- a/src/rng.cpp +++ b/src/rng.cpp @@ -4,8 +4,48 @@ *************************************************/ #include <botan/rng.h> -#include <botan/secmem.h> +#include <botan/randpool.h> +#include <botan/x931_rng.h> #include <botan/util.h> +#include <botan/parsing.h> + +#if defined(BOTAN_EXT_TIMER_HARDWARE) + #include <botan/tm_hard.h> +#elif defined(BOTAN_EXT_TIMER_POSIX) + #include <botan/tm_posix.h> +#elif defined(BOTAN_EXT_TIMER_UNIX) + #include <botan/tm_unix.h> +#elif defined(BOTAN_EXT_TIMER_WIN32) + #include <botan/tm_win32.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_DEVICE) + #include <botan/es_dev.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_EGD) + #include <botan/es_egd.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_UNIX) + #include <botan/es_unix.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_BEOS) + #include <botan/es_beos.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_CAPI) + #include <botan/es_capi.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_WIN32) + #include <botan/es_win32.h> +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_FTW) + #include <botan/es_ftw.h> +#endif namespace Botan { @@ -28,30 +68,61 @@ byte RandomNumberGenerator::next_byte() } /************************************************* -* Add entropy to internal state * +* Create and seed a new RNG object * *************************************************/ -void RandomNumberGenerator::add_entropy(const byte random[], u32bit length) +RandomNumberGenerator* make_rng() { - this->add_randomness(random, length); - } + Randpool* randpool = new Randpool("AES-256", "HMAC(SHA-256)"); -/************************************************* -* Add entropy to internal state * -*************************************************/ -u32bit RandomNumberGenerator::add_entropy(EntropySource& source, - bool slow_poll) - { - SecureVector<byte> buffer(1024); - u32bit bytes_gathered = 0; +#if defined(BOTAN_EXT_TIMER_HARDWARE) + randpool->add_entropy_source(new Hardware_Timer); +#elif defined(BOTAN_EXT_TIMER_POSIX) + randpool->add_entropy_source(new POSIX_Timer); +#elif defined(BOTAN_EXT_TIMER_UNIX) + randpool->add_entropy_source(new Unix_Timer); +#elif defined(BOTAN_EXT_TIMER_WIN32) + randpool->add_entropy_source(new Win32_Timer); +#else + randpool->add_entropy_source(new Timer); +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_DEVICE) + randpool->add_entropy_source( + new Device_EntropySource( + split_on("/dev/random:/dev/srandom:/dev/urandom", ':') + ) + ); +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_EGD) + randpool->add_entropy_source( + new EGD_EntropySource(split_on("/var/run/egd-pool:/dev/egd-pool", ':')) + ); +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_CAPI) + randpool->add_entropy_source(new Win32_CAPI_EntropySource); +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_WIN32) + randpool->add_entropy_source(new Win32_EntropySource); +#endif + +#if defined(BOTAN_EXT_ENTROPY_SRC_UNIX) + randpool->add_entropy_source( + new Unix_EntropySource(split_on("/bin:/sbin:/usr/bin:/usr/sbin", ':')) + ); +#endif - if(slow_poll) - bytes_gathered = source.slow_poll(buffer, buffer.size()); - else - bytes_gathered = source.fast_poll(buffer, buffer.size()); +#if defined(BOTAN_EXT_ENTROPY_SRC_BEOS) + randpool->add_entropy_source(new BeOS_EntropySource); +#endif - this->add_entropy(buffer, bytes_gathered); +#if defined(BOTAN_EXT_ENTROPY_SRC_FTW) + randpool->add_entropy_source(new FTW_EntropySource("/proc")); +#endif - return entropy_estimate(buffer, bytes_gathered); + return new ANSI_X931_RNG("AES-256", randpool); } } diff --git a/src/x931_rng.cpp b/src/x931_rng.cpp index d9ac69296..24b5059f1 100644 --- a/src/x931_rng.cpp +++ b/src/x931_rng.cpp @@ -1,6 +1,6 @@ /************************************************* * ANSI X9.31 RNG Source File * -* (C) 1999-2007 Jack Lloyd * +* (C) 1999-2008 Jack Lloyd * *************************************************/ #include <botan/x931_rng.h> @@ -16,7 +16,7 @@ namespace Botan { void ANSI_X931_RNG::randomize(byte out[], u32bit length) { if(!is_seeded()) - throw PRNG_Unseeded(name()); + reseed(); while(length) { @@ -52,24 +52,19 @@ void ANSI_X931_RNG::update_buffer() } /************************************************* -* Add entropy to internal state * +* Reseed the internal state * *************************************************/ -void ANSI_X931_RNG::add_randomness(const byte data[], u32bit length) +void ANSI_X931_RNG::reseed() { - prng->add_entropy(data, length); + SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH); + prng->randomize(key, key.size()); + cipher->set_key(key, key.size()); - 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()); + if(V.size() != cipher->BLOCK_SIZE) + V.create(cipher->BLOCK_SIZE); + prng->randomize(V, V.size()); - update_buffer(); - } + update_buffer(); } /************************************************* |