monotone

monotone Mtn Source Tree

Root/botan/eax.cpp

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

Archive Download this file

Branches

Tags

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