diff options
Diffstat (limited to 'lib/rng/x931_rng')
-rw-r--r-- | lib/rng/x931_rng/info.txt | 5 | ||||
-rw-r--r-- | lib/rng/x931_rng/x931_rng.cpp | 146 | ||||
-rw-r--r-- | lib/rng/x931_rng/x931_rng.h | 50 |
3 files changed, 201 insertions, 0 deletions
diff --git a/lib/rng/x931_rng/info.txt b/lib/rng/x931_rng/info.txt new file mode 100644 index 000000000..beab0dbfd --- /dev/null +++ b/lib/rng/x931_rng/info.txt @@ -0,0 +1,5 @@ +define X931_RNG 20131128 + +<requires> +block +</requires> diff --git a/lib/rng/x931_rng/x931_rng.cpp b/lib/rng/x931_rng/x931_rng.cpp new file mode 100644 index 000000000..b36f87106 --- /dev/null +++ b/lib/rng/x931_rng/x931_rng.cpp @@ -0,0 +1,146 @@ +/* +* ANSI X9.31 RNG +* (C) 1999-2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/x931_rng.h> +#include <botan/internal/xor_buf.h> +#include <algorithm> + +namespace Botan { + +/* +* Generate a buffer of random bytes +*/ +void ANSI_X931_RNG::randomize(byte out[], size_t length) + { + if(!is_seeded()) + throw PRNG_Unseeded(name()); + + while(length) + { + if(position == R.size()) + update_buffer(); + + const size_t copied = std::min<size_t>(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() + { + const size_t BLOCK_SIZE = cipher->block_size(); + + secure_vector<byte> DT = prng->random_vec(BLOCK_SIZE); + cipher->encrypt(DT); + + xor_buf(&R[0], &V[0], &DT[0], BLOCK_SIZE); + cipher->encrypt(R); + + xor_buf(&V[0], &R[0], &DT[0], BLOCK_SIZE); + cipher->encrypt(V); + + position = 0; + } + +/* +* Reset V and the cipher key with new values +*/ +void ANSI_X931_RNG::rekey() + { + const size_t BLOCK_SIZE = cipher->block_size(); + + if(prng->is_seeded()) + { + cipher->set_key(prng->random_vec(cipher->maximum_keylength())); + + if(V.size() != BLOCK_SIZE) + V.resize(BLOCK_SIZE); + prng->randomize(&V[0], V.size()); + + update_buffer(); + } + } + +/* +* Reseed the internal state +*/ +void ANSI_X931_RNG::reseed(size_t poll_bits) + { + prng->reseed(poll_bits); + rekey(); + } + +/* +* Add some entropy to the underlying PRNG +*/ +void ANSI_X931_RNG::add_entropy(const byte input[], size_t length) + { + prng->add_entropy(input, length); + rekey(); + } + +/* +* Check if the the PRNG is seeded +*/ +bool ANSI_X931_RNG::is_seeded() const + { + return (V.size() > 0); + } + +/* +* Clear memory of sensitive data +*/ +void ANSI_X931_RNG::clear() + { + cipher->clear(); + prng->clear(); + zeroise(R); + V.clear(); + + 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(BlockCipher* cipher_in, + RandomNumberGenerator* prng_in) + { + if(!prng_in || !cipher_in) + throw Invalid_Argument("ANSI_X931_RNG constructor: NULL arguments"); + + cipher = cipher_in; + prng = prng_in; + + R.resize(cipher->block_size()); + position = 0; + } + +/* +* ANSI X931 RNG Destructor +*/ +ANSI_X931_RNG::~ANSI_X931_RNG() + { + delete cipher; + delete prng; + } + +} diff --git a/lib/rng/x931_rng/x931_rng.h b/lib/rng/x931_rng/x931_rng.h new file mode 100644 index 000000000..8052cedc3 --- /dev/null +++ b/lib/rng/x931_rng/x931_rng.h @@ -0,0 +1,50 @@ +/* +* ANSI X9.31 RNG +* (C) 1999-2009 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ANSI_X931_RNG_H__ +#define BOTAN_ANSI_X931_RNG_H__ + +#include <botan/rng.h> +#include <botan/block_cipher.h> + +namespace Botan { + +/** +* ANSI X9.31 RNG +*/ +class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator + { + public: + void randomize(byte[], size_t); + bool is_seeded() const; + void clear(); + std::string name() const; + + void reseed(size_t poll_bits); + void add_entropy(const byte[], size_t); + + /** + * @param cipher the block cipher to use in this PRNG + * @param rng the underlying PRNG for generating inputs + * (eg, an HMAC_RNG) + */ + ANSI_X931_RNG(BlockCipher* cipher, + RandomNumberGenerator* rng); + ~ANSI_X931_RNG(); + private: + void rekey(); + void update_buffer(); + + BlockCipher* cipher; + RandomNumberGenerator* prng; + secure_vector<byte> V, R; + size_t position; + }; + +} + +#endif |