00001
00002
00003
00004
00005
00006
00007
00008 #include <botan/x931_rng.h>
00009 #include <botan/internal/xor_buf.h>
00010 #include <algorithm>
00011
00012 namespace Botan {
00013
00014
00015
00016
00017 void ANSI_X931_RNG::randomize(byte out[], u32bit length)
00018 {
00019 if(!is_seeded())
00020 throw PRNG_Unseeded(name());
00021
00022 while(length)
00023 {
00024 if(position == R.size())
00025 update_buffer();
00026
00027 const u32bit copied = std::min(length, R.size() - position);
00028
00029 copy_mem(out, R + position, copied);
00030 out += copied;
00031 length -= copied;
00032 position += copied;
00033 }
00034 }
00035
00036
00037
00038
00039 void ANSI_X931_RNG::update_buffer()
00040 {
00041 SecureVector<byte> DT(cipher->BLOCK_SIZE);
00042
00043 prng->randomize(DT, DT.size());
00044 cipher->encrypt(DT);
00045
00046 xor_buf(R, V, DT, cipher->BLOCK_SIZE);
00047 cipher->encrypt(R);
00048
00049 xor_buf(V, R, DT, cipher->BLOCK_SIZE);
00050 cipher->encrypt(V);
00051
00052 position = 0;
00053 }
00054
00055
00056
00057
00058 void ANSI_X931_RNG::rekey()
00059 {
00060 if(prng->is_seeded())
00061 {
00062 SecureVector<byte> key(cipher->MAXIMUM_KEYLENGTH);
00063 prng->randomize(key, key.size());
00064 cipher->set_key(key, key.size());
00065
00066 if(V.size() != cipher->BLOCK_SIZE)
00067 V.resize(cipher->BLOCK_SIZE);
00068 prng->randomize(V, V.size());
00069
00070 update_buffer();
00071 }
00072 }
00073
00074
00075
00076
00077 void ANSI_X931_RNG::reseed(u32bit poll_bits)
00078 {
00079 prng->reseed(poll_bits);
00080 rekey();
00081 }
00082
00083
00084
00085
00086 void ANSI_X931_RNG::add_entropy_source(EntropySource* src)
00087 {
00088 prng->add_entropy_source(src);
00089 }
00090
00091
00092
00093
00094 void ANSI_X931_RNG::add_entropy(const byte input[], u32bit length)
00095 {
00096 prng->add_entropy(input, length);
00097 rekey();
00098 }
00099
00100
00101
00102
00103 bool ANSI_X931_RNG::is_seeded() const
00104 {
00105 return (V.size() > 0);
00106 }
00107
00108
00109
00110
00111 void ANSI_X931_RNG::clear()
00112 {
00113 cipher->clear();
00114 prng->clear();
00115 R.clear();
00116 V.destroy();
00117
00118 position = 0;
00119 }
00120
00121
00122
00123
00124 std::string ANSI_X931_RNG::name() const
00125 {
00126 return "X9.31(" + cipher->name() + ")";
00127 }
00128
00129
00130
00131
00132 ANSI_X931_RNG::ANSI_X931_RNG(BlockCipher* cipher_in,
00133 RandomNumberGenerator* prng_in)
00134 {
00135 if(!prng_in || !cipher_in)
00136 throw Invalid_Argument("ANSI_X931_RNG constructor: NULL arguments");
00137
00138 cipher = cipher_in;
00139 prng = prng_in;
00140
00141 R.resize(cipher->BLOCK_SIZE);
00142 position = 0;
00143 }
00144
00145
00146
00147
00148 ANSI_X931_RNG::~ANSI_X931_RNG()
00149 {
00150 delete cipher;
00151 delete prng;
00152 }
00153
00154 }