monotone

monotone Mtn Source Tree

Root/botan/eax.cpp

1/*************************************************
2* EAX Mode Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/eax.h>
7#include <botan/lookup.h>
8#include <botan/bit_ops.h>
9#include <botan/parsing.h>
10#include <algorithm>
11
12namespace Botan {
13
14namespace {
15
16/*************************************************
17* EAX MAC-based PRF *
18*************************************************/
19SecureVector<byte> eax_prf(byte tag, u32bit BLOCK_SIZE,
20 MessageAuthenticationCode* mac,
21 const byte in[], u32bit length)
22 {
23 for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j)
24 mac->update(0);
25 mac->update(tag);
26 mac->update(in, length);
27 return mac->final();
28 }
29
30}
31
32/*************************************************
33* EAX_Base Constructor *
34*************************************************/
35EAX_Base::EAX_Base(const std::string& cipher_name,
36 u32bit tag_size) :
37 TAG_SIZE(tag_size ? tag_size / 8 : block_size_of(cipher_name)),
38 BLOCK_SIZE(block_size_of(cipher_name))
39 {
40 const std::string mac_name = "CMAC(" + cipher_name + ")";
41
42 cipher = get_block_cipher(cipher_name);
43 mac = get_mac(mac_name);
44
45 if(tag_size % 8 != 0 || TAG_SIZE == 0 || TAG_SIZE > mac->OUTPUT_LENGTH)
46 throw Invalid_Argument(name() + ": Bad tag size " + to_string(tag_size));
47
48 state.create(BLOCK_SIZE);
49 buffer.create(BLOCK_SIZE);
50 position = 0;
51 }
52
53/*************************************************
54* Check if a keylength is valid for EAX *
55*************************************************/
56bool EAX_Base::valid_keylength(u32bit n) const
57 {
58 if(!cipher->valid_keylength(n))
59 return false;
60 if(!mac->valid_keylength(n))
61 return false;
62 return true;
63 }
64
65/*************************************************
66* Set the EAX key *
67*************************************************/
68void EAX_Base::set_key(const SymmetricKey& key)
69 {
70 cipher->set_key(key);
71 mac->set_key(key);
72 header_mac = eax_prf(1, BLOCK_SIZE, mac, 0, 0);
73 }
74
75/*************************************************
76* Do setup at the start of each message *
77*************************************************/
78void EAX_Base::start_msg()
79 {
80 for(u32bit j = 0; j != BLOCK_SIZE - 1; ++j)
81 mac->update(0);
82 mac->update(2);
83 }
84
85/*************************************************
86* Set the EAX nonce *
87*************************************************/
88void EAX_Base::set_iv(const InitializationVector& iv)
89 {
90 nonce_mac = eax_prf(0, BLOCK_SIZE, mac, iv.begin(), iv.length());
91 state = nonce_mac;
92 cipher->encrypt(state, buffer);
93 }
94
95/*************************************************
96* Set the EAX header *
97*************************************************/
98void EAX_Base::set_header(const byte header[], u32bit length)
99 {
100 header_mac = eax_prf(1, BLOCK_SIZE, mac, header, length);
101 }
102
103/*************************************************
104* Return the name of this cipher mode *
105*************************************************/
106std::string EAX_Base::name() const
107 {
108 return (cipher->name() + "/EAX");
109 }
110
111/*************************************************
112* Increment the counter and update the buffer *
113*************************************************/
114void EAX_Base::increment_counter()
115 {
116 for(s32bit j = BLOCK_SIZE - 1; j >= 0; --j)
117 if(++state[j])
118 break;
119 cipher->encrypt(state, buffer);
120 position = 0;
121 }
122
123/*************************************************
124* EAX_Encryption Constructor *
125*************************************************/
126EAX_Encryption::EAX_Encryption(const std::string& cipher_name,
127 u32bit tag_size) :
128 EAX_Base(cipher_name, tag_size)
129 {
130 }
131
132/*************************************************
133* EAX_Encryption Constructor *
134*************************************************/
135EAX_Encryption::EAX_Encryption(const std::string& cipher_name,
136 const SymmetricKey& key,
137 const InitializationVector& iv,
138 u32bit tag_size) :
139 EAX_Base(cipher_name, tag_size)
140 {
141 set_key(key);
142 set_iv(iv);
143 }
144
145/*************************************************
146* Encrypt in EAX mode *
147*************************************************/
148void EAX_Encryption::write(const byte input[], u32bit length)
149 {
150 u32bit copied = std::min(BLOCK_SIZE - position, length);
151 xor_buf(buffer + position, input, copied);
152 send(buffer + position, copied);
153 mac->update(buffer + position, copied);
154 input += copied;
155 length -= copied;
156 position += copied;
157
158 if(position == BLOCK_SIZE)
159 increment_counter();
160
161 while(length >= BLOCK_SIZE)
162 {
163 xor_buf(buffer, input, BLOCK_SIZE);
164 send(buffer, BLOCK_SIZE);
165 mac->update(buffer, BLOCK_SIZE);
166
167 input += BLOCK_SIZE;
168 length -= BLOCK_SIZE;
169 increment_counter();
170 }
171
172 xor_buf(buffer + position, input, length);
173 send(buffer + position, length);
174 mac->update(buffer + position, length);
175 position += length;
176 }
177
178/*************************************************
179* Finish encrypting in EAX mode *
180*************************************************/
181void EAX_Encryption::end_msg()
182 {
183 SecureVector<byte> data_mac = mac->final();
184 xor_buf(data_mac, nonce_mac, data_mac.size());
185 xor_buf(data_mac, header_mac, data_mac.size());
186
187 send(data_mac, TAG_SIZE);
188
189 state.clear();
190 buffer.clear();
191 position = 0;
192 }
193
194/*************************************************
195* EAX_Decryption Constructor *
196*************************************************/
197EAX_Decryption::EAX_Decryption(const std::string& cipher_name,
198 u32bit tag_size) :
199 EAX_Base(cipher_name, tag_size)
200 {
201 queue.create(2*TAG_SIZE + DEFAULT_BUFFERSIZE);
202 queue_start = queue_end = 0;
203 }
204
205/*************************************************
206* EAX_Decryption Constructor *
207*************************************************/
208EAX_Decryption::EAX_Decryption(const std::string& cipher_name,
209 const SymmetricKey& key,
210 const InitializationVector& iv,
211 u32bit tag_size) :
212 EAX_Base(cipher_name, tag_size)
213 {
214 set_key(key);
215 set_iv(iv);
216 queue.create(2*TAG_SIZE + DEFAULT_BUFFERSIZE);
217 queue_start = queue_end = 0;
218 }
219
220/*************************************************
221* Decrypt in EAX mode *
222*************************************************/
223void EAX_Decryption::write(const byte input[], u32bit length)
224 {
225 while(length)
226 {
227 const u32bit copied = std::min(length, queue.size() - queue_end);
228
229 queue.copy(queue_end, input, copied);
230 input += copied;
231 length -= copied;
232 queue_end += copied;
233
234 SecureVector<byte> block_buf(cipher->BLOCK_SIZE);
235 while((queue_end - queue_start) > TAG_SIZE)
236 {
237 u32bit removed = (queue_end - queue_start) - TAG_SIZE;
238 do_write(queue + queue_start, removed);
239 queue_start += removed;
240 }
241
242 if(queue_start + TAG_SIZE == queue_end &&
243 queue_start >= queue.size() / 2)
244 {
245 SecureVector<byte> queue_data(TAG_SIZE);
246 queue_data.copy(queue + queue_start, TAG_SIZE);
247 queue.copy(queue_data, TAG_SIZE);
248 queue_start = 0;
249 queue_end = TAG_SIZE;
250 }
251 }
252 }
253
254/*************************************************
255* Decrypt in EAX mode *
256*************************************************/
257void EAX_Decryption::do_write(const byte input[], u32bit length)
258 {
259 mac->update(input, length);
260
261 u32bit copied = std::min(BLOCK_SIZE - position, length);
262 xor_buf(buffer + position, input, copied);
263 send(buffer + position, copied);
264 input += copied;
265 length -= copied;
266 position += copied;
267
268 if(position == BLOCK_SIZE)
269 increment_counter();
270
271 while(length >= BLOCK_SIZE)
272 {
273 xor_buf(buffer, input, BLOCK_SIZE);
274 send(buffer, BLOCK_SIZE);
275
276 input += BLOCK_SIZE;
277 length -= BLOCK_SIZE;
278 increment_counter();
279 }
280
281 xor_buf(buffer + position, input, length);
282 send(buffer + position, length);
283 position += length;
284 }
285
286/*************************************************
287* Finish decrypting in EAX mode *
288*************************************************/
289void EAX_Decryption::end_msg()
290 {
291 if((queue_end - queue_start) != TAG_SIZE)
292 throw Integrity_Failure(name() + ": Message authentication failure");
293
294 SecureVector<byte> data_mac = mac->final();
295
296 for(u32bit j = 0; j != TAG_SIZE; ++j)
297 if(queue[queue_start+j] != (data_mac[j] ^ nonce_mac[j] ^ header_mac[j]))
298 throw Integrity_Failure(name() + ": Message authentication failure");
299
300 state.clear();
301 buffer.clear();
302 position = 0;
303 queue_start = queue_end = 0;
304 }
305
306}

Archive Download this file

Branches

Tags

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