Botan: src/rng/randpool/randpool.cpp Source File

Botan 1.10.17

randpool.cpp
Go to the documentation of this file.
1 /*
2 * Randpool
3 * (C) 1999-2009 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/randpool.h>
9 #include <botan/get_byte.h>
10 #include <botan/internal/xor_buf.h>
11 #include <botan/internal/stl_util.h>
12 #include <algorithm>
13
14 namespace Botan {
15
16 namespace {
17
18 /*
19 * PRF based on a MAC
20 */
21 enum RANDPOOL_PRF_TAG {
22 CIPHER_KEY = 0,
23 MAC_KEY = 1,
24 GEN_OUTPUT = 2
25 };
26
27 }
28
29 /*
30 * Generate a buffer of random bytes
31 */
32 void Randpool::randomize(byte out[], size_t length)
33 {
34 if(!is_seeded())
35 throw PRNG_Unseeded(name());
36
37 update_buffer();
38 while(length)
39 {
40 const size_t copied = std::min<size_t>(length, buffer.size());
41 copy_mem(out, &buffer[0], copied);
42 out += copied;
43 length -= copied;
44 update_buffer();
45 }
46 }
47
48 /*
49 * Refill the output buffer
50 */
51 void Randpool::update_buffer()
52 {
53 for(size_t i = 0; i != counter.size(); ++i)
54 if(++counter[i])
55 break;
56
57 mac->update(static_cast<byte>(GEN_OUTPUT));
58 mac->update(counter);
59 SecureVector<byte> mac_val = mac->final();
60
61 for(size_t i = 0; i != mac_val.size(); ++i)
62 buffer[i % buffer.size()] ^= mac_val[i];
63 cipher->encrypt(buffer);
64
65 if(counter[0] % ITERATIONS_BEFORE_RESEED == 0)
66 mix_pool();
67 }
68
69 /*
70 * Mix the entropy pool
71 */
72 void Randpool::mix_pool()
73 {
74 const size_t BLOCK_SIZE = cipher->block_size();
75
76 mac->update(static_cast<byte>(MAC_KEY));
77 mac->update(pool);
78 mac->set_key(mac->final());
79
80 mac->update(static_cast<byte>(CIPHER_KEY));
81 mac->update(pool);
82 cipher->set_key(mac->final());
83
84 xor_buf(pool, buffer, BLOCK_SIZE);
85 cipher->encrypt(pool);
86 for(size_t i = 1; i != POOL_BLOCKS; ++i)
87 {
88 const byte* previous_block = &pool[BLOCK_SIZE*(i-1)];
89 byte* this_block = &pool[BLOCK_SIZE*i];
90 xor_buf(this_block, previous_block, BLOCK_SIZE);
91 cipher->encrypt(this_block);
92 }
93
94 update_buffer();
95 }
96
97 /*
98 * Reseed the internal state
99 */
100 void Randpool::reseed(size_t poll_bits)
101 {
102 Entropy_Accumulator_BufferedComputation accum(*mac, poll_bits);
103
104 if(!entropy_sources.empty())
105 {
106 size_t poll_attempt = 0;
107
108 while(!accum.polling_goal_achieved() && poll_attempt < poll_bits)
109 {
110 entropy_sources[poll_attempt % entropy_sources.size()]->poll(accum);
111 ++poll_attempt;
112 }
113 }
114
115 SecureVector<byte> mac_val = mac->final();
116
117 xor_buf(pool, mac_val, mac_val.size());
118 mix_pool();
119
120 if(accum.bits_collected() >= poll_bits)
121 seeded = true;
122 }
123
124 /*
125 * Add user-supplied entropy
126 */
127 void Randpool::add_entropy(const byte input[], size_t length)
128 {
129 SecureVector<byte> mac_val = mac->process(input, length);
130 xor_buf(pool, mac_val, mac_val.size());
131 mix_pool();
132
133 if(length)
134 seeded = true;
135 }
136
137 /*
138 * Add another entropy source to the list
139 */
140 void Randpool::add_entropy_source(EntropySource* src)
141 {
142 entropy_sources.push_back(src);
143 }
144
145 /*
146 * Clear memory of sensitive data
147 */
148 void Randpool::clear()
149 {
150 cipher->clear();
151 mac->clear();
152 zeroise(pool);
153 zeroise(buffer);
154 zeroise(counter);
155 seeded = false;
156 }
157
158 /*
159 * Return the name of this type
160 */
161 std::string Randpool::name() const
162 {
163 return "Randpool(" + cipher->name() + "," + mac->name() + ")";
164 }
165
166 /*
167 * Randpool Constructor
168 */
169 Randpool::Randpool(BlockCipher* cipher_in,
170 MessageAuthenticationCode* mac_in,
171 size_t pool_blocks,
172 size_t iter_before_reseed) :
173 ITERATIONS_BEFORE_RESEED(iter_before_reseed),
174 POOL_BLOCKS(pool_blocks),
175 cipher(cipher_in),
176 mac(mac_in)
177 {
178 const size_t BLOCK_SIZE = cipher->block_size();
179 const size_t OUTPUT_LENGTH = mac->output_length();
180
181 if(OUTPUT_LENGTH < BLOCK_SIZE ||
182 !cipher->valid_keylength(OUTPUT_LENGTH) ||
183 !mac->valid_keylength(OUTPUT_LENGTH))
184 {
185 delete cipher;
186 delete mac;
187 throw Internal_Error("Randpool: Invalid algorithm combination");
188 }
189
190 buffer.resize(BLOCK_SIZE);
191 pool.resize(POOL_BLOCKS * BLOCK_SIZE);
192 counter.resize(12);
193 seeded = false;
194 }
195
196 /*
197 * Randpool Destructor
198 */
199 Randpool::~Randpool()
200 {
201 delete cipher;
202 delete mac;
203
204 std::for_each(entropy_sources.begin(), entropy_sources.end(),
205 del_fun<EntropySource>());
206 }
207
208 }
Botan::MemoryRegion::resize
void resize(size_t n)
Definition: secmem.h:217
Botan::Algorithm::clear
virtual void clear()=0
Botan::Randpool::add_entropy
void add_entropy(const byte input[], size_t length)
Definition: randpool.cpp:127
Botan::Randpool::add_entropy_source
void add_entropy_source(EntropySource *es)
Definition: randpool.cpp:140
Botan::Randpool::Randpool
Randpool(BlockCipher *cipher, MessageAuthenticationCode *mac, size_t pool_blocks=32, size_t iterations_before_reseed=128)
Definition: randpool.cpp:169
Botan::Entropy_Accumulator_BufferedComputation
Definition: entropy_src.h:98
Botan::Internal_Error
Definition: exceptn.h:45
Botan::EntropySource
Definition: entropy_src.h:122
Botan::MessageAuthenticationCode
Definition: mac.h:20
Botan::@518::RANDPOOL_PRF_TAG
RANDPOOL_PRF_TAG
Definition: randpool.cpp:21
Botan::Randpool::name
std::string name() const
Definition: randpool.cpp:161
Botan::Randpool::randomize
void randomize(byte[], size_t)
Definition: randpool.cpp:32
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::SymmetricAlgorithm::valid_keylength
bool valid_keylength(size_t length) const
Definition: sym_algo.h:51
Botan::BlockCipher::encrypt
void encrypt(const byte in[], byte out[]) const
Definition: block_cipher.h:47
Botan::SymmetricAlgorithm::set_key
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:60
Botan::MessageAuthenticationCode::name
virtual std::string name() const =0
Botan::Buffered_Computation::update
void update(const byte in[], size_t length)
Definition: buf_comp.h:33
Botan::Buffered_Computation::process
SecureVector< byte > process(const byte in[], size_t length)
Definition: buf_comp.h:101
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
Botan
Definition: algo_base.h:14
Botan::Algorithm::name
virtual std::string name() const =0
Botan::Buffered_Computation::final
void final(byte out[])
Definition: buf_comp.h:80
Botan::Entropy_Accumulator::polling_goal_achieved
bool polling_goal_achieved() const
Definition: entropy_src.h:50
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::del_fun
Definition: stl_util.h:57
Botan::Randpool::reseed
void reseed(size_t bits_to_collect)
Definition: randpool.cpp:100
Botan::Randpool::~Randpool
~Randpool()
Definition: randpool.cpp:199
Botan::SecureVector< byte >
Botan::Entropy_Accumulator::bits_collected
size_t bits_collected() const
Definition: entropy_src.h:44
Botan::xor_buf
void xor_buf(byte out[], const byte in[], size_t length)
Definition: xor_buf.h:21
Botan::Randpool::is_seeded
bool is_seeded() const
Definition: randpool.h:25
Botan::zeroise
void zeroise(MemoryRegion< T > &vec)
Definition: secmem.h:428
Botan::BlockCipher::block_size
virtual size_t block_size() const =0
Botan::Buffered_Computation::output_length
virtual size_t output_length() const =0
Botan::PRNG_Unseeded
Definition: exceptn.h:89
Botan::Randpool::clear
void clear()
Definition: randpool.cpp:148
Botan::BlockCipher
Definition: block_cipher.h:18