monotone

monotone Mtn Source Tree

Root/botan/randpool.cpp

1/*************************************************
2* Randpool Source File *
3* (C) 1999-2007 The Botan Project *
4*************************************************/
5
6#include <botan/randpool.h>
7#include <botan/lookup.h>
8#include <botan/loadstor.h>
9#include <botan/bit_ops.h>
10#include <botan/util.h>
11#include <algorithm>
12
13namespace Botan {
14
15namespace {
16
17/*************************************************
18* PRF based on a MAC *
19*************************************************/
20enum RANDPOOL_PRF_TAG {
21 USER_INPUT = 0,
22 CIPHER_KEY = 1,
23 MAC_KEY = 2,
24 GEN_OUTPUT = 3
25};
26
27SecureVector<byte> randpool_prf(MessageAuthenticationCode* mac,
28 RANDPOOL_PRF_TAG tag,
29 const byte in[], u32bit length)
30 {
31 mac->update(static_cast<byte>(tag));
32 mac->update(in, length);
33 return mac->final();
34 }
35
36}
37
38/*************************************************
39* Generate a buffer of random bytes *
40*************************************************/
41void Randpool::randomize(byte out[], u32bit length) throw(PRNG_Unseeded)
42 {
43 if(!is_seeded())
44 throw PRNG_Unseeded(name());
45
46 update_buffer();
47 while(length)
48 {
49 const u32bit copied = std::min(length, buffer.size());
50 copy_mem(out, buffer.begin(), copied);
51 out += copied;
52 length -= copied;
53 update_buffer();
54 }
55 }
56
57/*************************************************
58* Refill the output buffer *
59*************************************************/
60void Randpool::update_buffer()
61 {
62 const u64bit timestamp = system_clock();
63
64 for(u32bit j = 0; j != counter.size(); ++j)
65 if(++counter[j])
66 break;
67 store_be(timestamp, counter + 4);
68
69 SecureVector<byte> mac_val = randpool_prf(mac, GEN_OUTPUT,
70 counter, counter.size());
71
72 for(u32bit j = 0; j != mac_val.size(); ++j)
73 buffer[j % buffer.size()] ^= mac_val[j];
74 cipher->encrypt(buffer);
75
76 if(counter[0] % ITERATIONS_BEFORE_RESEED == 0)
77 {
78 mix_pool();
79 update_buffer();
80 }
81 }
82
83/*************************************************
84* Mix the entropy pool *
85*************************************************/
86void Randpool::mix_pool()
87 {
88 const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
89
90 mac->set_key(randpool_prf(mac, MAC_KEY, pool, pool.size()));
91 cipher->set_key(randpool_prf(mac, CIPHER_KEY, pool, pool.size()));
92
93 xor_buf(pool, buffer, BLOCK_SIZE);
94 cipher->encrypt(pool);
95 for(u32bit j = 1; j != POOL_BLOCKS; ++j)
96 {
97 const byte* previous_block = pool + BLOCK_SIZE*(j-1);
98 byte* this_block = pool + BLOCK_SIZE*j;
99 xor_buf(this_block, previous_block, BLOCK_SIZE);
100 cipher->encrypt(this_block);
101 }
102 }
103
104/*************************************************
105* Add entropy to the internal state *
106*************************************************/
107void Randpool::add_randomness(const byte data[], u32bit length)
108 {
109 u32bit this_entropy = entropy_estimate(data, length);
110 entropy += std::min(this_entropy, 8*mac->OUTPUT_LENGTH);
111 entropy = std::min(entropy, 8 * pool.size());
112
113 SecureVector<byte> mac_val = randpool_prf(mac, USER_INPUT, data, length);
114 xor_buf(pool, mac_val, mac_val.size());
115 mix_pool();
116 }
117
118/*************************************************
119* Check if the the pool is seeded *
120*************************************************/
121bool Randpool::is_seeded() const
122 {
123 return (entropy >= 256);
124 }
125
126/*************************************************
127* Clear memory of sensitive data *
128*************************************************/
129void Randpool::clear() throw()
130 {
131 cipher->clear();
132 mac->clear();
133 pool.clear();
134 buffer.clear();
135 counter.clear();
136 entropy = 0;
137 }
138
139/*************************************************
140* Return the name of this type *
141*************************************************/
142std::string Randpool::name() const
143 {
144 return "Randpool(" + cipher->name() + "," + mac->name() + ")";
145 }
146
147/*************************************************
148* Randpool Constructor *
149*************************************************/
150Randpool::Randpool() : ITERATIONS_BEFORE_RESEED(8), POOL_BLOCKS(32)
151 {
152 const std::string CIPHER_NAME = "AES-256";
153 const std::string MAC_NAME = "HMAC(SHA-256)";
154
155 cipher = get_block_cipher(CIPHER_NAME);
156 mac = get_mac(MAC_NAME);
157
158 const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
159 const u32bit OUTPUT_LENGTH = mac->OUTPUT_LENGTH;
160
161 if(OUTPUT_LENGTH < BLOCK_SIZE ||
162 !cipher->valid_keylength(OUTPUT_LENGTH) ||
163 !mac->valid_keylength(OUTPUT_LENGTH))
164 {
165 delete cipher;
166 delete mac;
167 throw Internal_Error("Randpool: Invalid algorithm combination " +
168 CIPHER_NAME + "/" + MAC_NAME);
169 }
170
171 buffer.create(BLOCK_SIZE);
172 pool.create(POOL_BLOCKS * BLOCK_SIZE);
173 counter.create(12);
174 entropy = 0;
175
176 mix_pool();
177 }
178
179/*************************************************
180* Randpool Destructor *
181*************************************************/
182Randpool::~Randpool()
183 {
184 delete cipher;
185 delete mac;
186 entropy = 0;
187 }
188
189}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status