monotone

monotone Mtn Source Tree

Root/botan/randpool.cpp

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

Archive Download this file

Branches

Tags

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