blob: b466ca9aec34a789cd60f6740be444d0739c4925 [file] [log] [blame]
Benny Prijono8a0ab282008-01-23 20:17:42 +00001/*
2 * aes_icm.c
3 *
4 * AES Integer Counter Mode
5 *
6 * David A. McGrew
7 * Cisco Systems, Inc.
8 */
9
10/*
11 *
12 * Copyright (c) 2001-2006, Cisco Systems, Inc.
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * Redistributions in binary form must reproduce the above
23 * copyright notice, this list of conditions and the following
24 * disclaimer in the documentation and/or other materials provided
25 * with the distribution.
26 *
27 * Neither the name of the Cisco Systems, Inc. nor the names of its
28 * contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
35 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
36 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
42 * OF THE POSSIBILITY OF SUCH DAMAGE.
43 *
44 */
45
46
47#define ALIGN_32 0
48
49#include "aes_icm.h"
50#include "alloc.h"
51
52
53debug_module_t mod_aes_icm = {
54 0, /* debugging is off by default */
55 "aes icm" /* printable module name */
56};
57
58/*
59 * integer counter mode works as follows:
60 *
61 * 16 bits
62 * <----->
63 * +------+------+------+------+------+------+------+------+
64 * | nonce | pakcet index | ctr |---+
65 * +------+------+------+------+------+------+------+------+ |
66 * |
67 * +------+------+------+------+------+------+------+------+ v
68 * | salt |000000|->(+)
69 * +------+------+------+------+------+------+------+------+ |
70 * |
71 * +---------+
72 * | encrypt |
73 * +---------+
74 * |
75 * +------+------+------+------+------+------+------+------+ |
76 * | keystream block |<--+
77 * +------+------+------+------+------+------+------+------+
78 *
79 * All fields are big-endian
80 *
81 * ctr is the block counter, which increments from zero for
82 * each packet (16 bits wide)
83 *
84 * packet index is distinct for each packet (48 bits wide)
85 *
86 * nonce can be distinct across many uses of the same key, or
87 * can be a fixed value per key, or can be per-packet randomness
88 * (64 bits)
89 *
90 */
91
92err_status_t
93aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) {
94 extern cipher_type_t aes_icm;
95 uint8_t *pointer;
96 int tmp;
97
98 debug_print(mod_aes_icm,
99 "allocating cipher with key length %d", key_len);
100
101 /*
102 * Ismacryp, for example, uses 16 byte key + 8 byte
103 * salt so this function is called with key_len = 24.
104 * The check for key_len = 30 does not apply. Our usage
105 * of aes functions with key_len = values other than 30
106 * has not broken anything. Don't know what would be the
107 * effect of skipping this check for srtp in general.
108 */
109 if (!forIsmacryp && key_len != 30)
110 return err_status_bad_param;
111
112 /* allocate memory a cipher of type aes_icm */
113 tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
114 pointer = (uint8_t*)crypto_alloc(tmp);
115 if (pointer == NULL)
116 return err_status_alloc_fail;
117
118 /* set pointers */
119 *c = (cipher_t *)pointer;
120 (*c)->type = &aes_icm;
121 (*c)->state = pointer + sizeof(cipher_t);
122
123 /* increment ref_count */
124 aes_icm.ref_count++;
125
126 /* set key size */
127 (*c)->key_len = key_len;
128
129 return err_status_ok;
130}
131
132err_status_t aes_icm_alloc(cipher_t **c, int key_len, int forIsmacryp) {
133 return aes_icm_alloc_ismacryp(c, key_len, 0);
134}
135
136err_status_t
137aes_icm_dealloc(cipher_t *c) {
138 extern cipher_type_t aes_icm;
139
140 /* zeroize entire state*/
141 octet_string_set_to_zero((uint8_t *)c,
142 sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
143
144 /* free memory */
145 crypto_free(c);
146
147 /* decrement ref_count */
148 aes_icm.ref_count--;
149
150 return err_status_ok;
151}
152
153
154/*
155 * aes_icm_context_init(...) initializes the aes_icm_context
156 * using the value in key[].
157 *
158 * the key is the secret key
159 *
160 * the salt is unpredictable (but not necessarily secret) data which
161 * randomizes the starting point in the keystream
162 */
163
164err_status_t
165aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key) {
166 v128_t tmp_key;
167
168 /* set counter and initial values to 'offset' value */
169 /* FIX!!! this assumes the salt is at key + 16, and thus that the */
170 /* FIX!!! cipher key length is 16! Also note this copies past the
171 end of the 'key' array by 2 bytes! */
172 v128_copy_octet_string(&c->counter, key + 16);
173 v128_copy_octet_string(&c->offset, key + 16);
174
175 /* force last two octets of the offset to zero (for srtp compatibility) */
176 c->offset.v8[14] = c->offset.v8[15] = 0;
177 c->counter.v8[14] = c->counter.v8[15] = 0;
178
179 /* set tmp_key (for alignment) */
180 v128_copy_octet_string(&tmp_key, key);
181
182 debug_print(mod_aes_icm,
183 "key: %s", v128_hex_string(&tmp_key));
184 debug_print(mod_aes_icm,
185 "offset: %s", v128_hex_string(&c->offset));
186
187 /* expand key */
188 aes_expand_encryption_key(&tmp_key, c->expanded_key);
189
190 /* indicate that the keystream_buffer is empty */
191 c->bytes_in_buffer = 0;
192
193 return err_status_ok;
194}
195
196/*
197 * aes_icm_set_octet(c, i) sets the counter of the context which it is
198 * passed so that the next octet of keystream that will be generated
199 * is the ith octet
200 */
201
202err_status_t
203aes_icm_set_octet(aes_icm_ctx_t *c,
204 uint64_t octet_num) {
205
206#ifdef NO_64BIT_MATH
207 int tail_num = low32(octet_num) & 0x0f;
208 /* 64-bit right-shift 4 */
209 uint64_t block_num = make64(high32(octet_num) >> 4,
210 ((high32(octet_num) & 0x0f)<<(32-4)) |
211 (low32(octet_num) >> 4));
212#else
213 int tail_num = octet_num % 16;
214 uint64_t block_num = octet_num / 16;
215#endif
216
217
218 /* set counter value */
219 /* FIX - There's no way this is correct */
220 c->counter.v64[0] = c->offset.v64[0];
221#ifdef NO_64BIT_MATH
222 c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
223 low32(c->offset.v64[0]) ^ low32(block_num));
224#else
225 c->counter.v64[0] = c->offset.v64[0] ^ block_num;
226#endif
227
228 debug_print(mod_aes_icm,
229 "set_octet: %s", v128_hex_string(&c->counter));
230
231 /* fill keystream buffer, if needed */
232 if (tail_num) {
233 v128_copy(&c->keystream_buffer, &c->counter);
234 aes_encrypt(&c->keystream_buffer, c->expanded_key);
235 c->bytes_in_buffer = sizeof(v128_t);
236
237 debug_print(mod_aes_icm, "counter: %s",
238 v128_hex_string(&c->counter));
239 debug_print(mod_aes_icm, "ciphertext: %s",
240 v128_hex_string(&c->keystream_buffer));
241
242 /* indicate number of bytes in keystream_buffer */
243 c->bytes_in_buffer = sizeof(v128_t) - tail_num;
244
245 } else {
246
247 /* indicate that keystream_buffer is empty */
248 c->bytes_in_buffer = 0;
249 }
250
251 return err_status_ok;
252}
253
254/*
255 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
256 * the offset
257 */
258
259err_status_t
260aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
261 v128_t *nonce = (v128_t *) iv;
262
263 debug_print(mod_aes_icm,
264 "setting iv: %s", v128_hex_string(nonce));
265
266 v128_xor(&c->counter, &c->offset, nonce);
267
268 debug_print(mod_aes_icm,
269 "set_counter: %s", v128_hex_string(&c->counter));
270
271 /* indicate that the keystream_buffer is empty */
272 c->bytes_in_buffer = 0;
273
274 return err_status_ok;
275}
276
277
278
279/*
280 * aes_icm_advance(...) refills the keystream_buffer and
281 * advances the block index of the sicm_context forward by one
282 *
283 * this is an internal, hopefully inlined function
284 */
285
286inline void
287aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
288 /* fill buffer with new keystream */
289 v128_copy(&c->keystream_buffer, &c->counter);
290 aes_encrypt(&c->keystream_buffer, c->expanded_key);
291 c->bytes_in_buffer = sizeof(v128_t);
292
293 debug_print(mod_aes_icm, "counter: %s",
294 v128_hex_string(&c->counter));
295 debug_print(mod_aes_icm, "ciphertext: %s",
296 v128_hex_string(&c->keystream_buffer));
297
298 /* clock counter forward */
299
300 if (forIsmacryp) {
301 uint32_t temp;
302 //alex's clock counter forward
303 temp = ntohl(c->counter.v32[3]);
304 c->counter.v32[3] = htonl(++temp);
305 } else {
306 if (!++(c->counter.v8[15]))
307 ++(c->counter.v8[14]);
308 }
309}
310
311inline void aes_icm_advance(aes_icm_ctx_t *c) {
312 aes_icm_advance_ismacryp(c, 0);
313}
314
315
316/*e
317 * icm_encrypt deals with the following cases:
318 *
319 * bytes_to_encr < bytes_in_buffer
320 * - add keystream into data
321 *
322 * bytes_to_encr > bytes_in_buffer
323 * - add keystream into data until keystream_buffer is depleted
324 * - loop over blocks, filling keystream_buffer and then
325 * adding keystream into data
326 * - fill buffer then add in remaining (< 16) bytes of keystream
327 */
328
329err_status_t
330aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
331 unsigned char *buf, unsigned int *enc_len,
332 int forIsmacryp) {
333 unsigned int bytes_to_encr = *enc_len;
334 unsigned int i;
335 uint32_t *b;
336
337 /* check that there's enough segment left but not for ismacryp*/
338 if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
339 return err_status_terminus;
340
341 debug_print(mod_aes_icm, "block index: %d",
342 htons(c->counter.v16[7]));
343 if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
344
345 /* deal with odd case of small bytes_to_encr */
346 for (i = (sizeof(v128_t) - c->bytes_in_buffer);
347 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
348 {
349 *buf++ ^= c->keystream_buffer.v8[i];
350 }
351
352 c->bytes_in_buffer -= bytes_to_encr;
353
354 /* return now to avoid the main loop */
355 return err_status_ok;
356
357 } else {
358
359 /* encrypt bytes until the remaining data is 16-byte aligned */
360 for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
361 *buf++ ^= c->keystream_buffer.v8[i];
362
363 bytes_to_encr -= c->bytes_in_buffer;
364 c->bytes_in_buffer = 0;
365
366 }
367
368 /* now loop over entire 16-byte blocks of keystream */
369 for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
370
371 /* fill buffer with new keystream */
372 aes_icm_advance_ismacryp(c, forIsmacryp);
373
374 /*
375 * add keystream into the data buffer (this would be a lot faster
376 * if we could assume 32-bit alignment!)
377 */
378
379#if ALIGN_32
380 b = (uint32_t *)buf;
381 *b++ ^= c->keystream_buffer.v32[0];
382 *b++ ^= c->keystream_buffer.v32[1];
383 *b++ ^= c->keystream_buffer.v32[2];
384 *b++ ^= c->keystream_buffer.v32[3];
385 buf = (uint8_t *)b;
386#else
387 if ((((unsigned long) buf) & 0x03) != 0) {
388 *buf++ ^= c->keystream_buffer.v8[0];
389 *buf++ ^= c->keystream_buffer.v8[1];
390 *buf++ ^= c->keystream_buffer.v8[2];
391 *buf++ ^= c->keystream_buffer.v8[3];
392 *buf++ ^= c->keystream_buffer.v8[4];
393 *buf++ ^= c->keystream_buffer.v8[5];
394 *buf++ ^= c->keystream_buffer.v8[6];
395 *buf++ ^= c->keystream_buffer.v8[7];
396 *buf++ ^= c->keystream_buffer.v8[8];
397 *buf++ ^= c->keystream_buffer.v8[9];
398 *buf++ ^= c->keystream_buffer.v8[10];
399 *buf++ ^= c->keystream_buffer.v8[11];
400 *buf++ ^= c->keystream_buffer.v8[12];
401 *buf++ ^= c->keystream_buffer.v8[13];
402 *buf++ ^= c->keystream_buffer.v8[14];
403 *buf++ ^= c->keystream_buffer.v8[15];
404 } else {
405 b = (uint32_t *)buf;
406 *b++ ^= c->keystream_buffer.v32[0];
407 *b++ ^= c->keystream_buffer.v32[1];
408 *b++ ^= c->keystream_buffer.v32[2];
409 *b++ ^= c->keystream_buffer.v32[3];
410 buf = (uint8_t *)b;
411 }
412#endif /* #if ALIGN_32 */
413
414 }
415
416 /* if there is a tail end of the data, process it */
417 if ((bytes_to_encr & 0xf) != 0) {
418
419 /* fill buffer with new keystream */
420 aes_icm_advance_ismacryp(c, forIsmacryp);
421
422 for (i=0; i < (bytes_to_encr & 0xf); i++)
423 *buf++ ^= c->keystream_buffer.v8[i];
424
425 /* reset the keystream buffer size to right value */
426 c->bytes_in_buffer = sizeof(v128_t) - i;
427 } else {
428
429 /* no tail, so just reset the keystream buffer size to zero */
430 c->bytes_in_buffer = 0;
431
432 }
433
434 return err_status_ok;
435}
436
437err_status_t
438aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
439 return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
440}
441
442err_status_t
443aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
444 unsigned int len = num_octets_to_output;
445
446 /* zeroize the buffer */
447 octet_string_set_to_zero(buffer, num_octets_to_output);
448
449 /* exor keystream into buffer */
450 return aes_icm_encrypt(c, buffer, &len);
451}
452
453
454char
455aes_icm_description[] = "aes integer counter mode";
456
457uint8_t aes_icm_test_case_0_key[30] = {
458 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
459 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
460 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
461 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
462};
463
464uint8_t aes_icm_test_case_0_nonce[16] = {
465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
467};
468
469uint8_t aes_icm_test_case_0_plaintext[32] = {
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474};
475
476uint8_t aes_icm_test_case_0_ciphertext[32] = {
477 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
478 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
479 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
480 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
481};
482
483cipher_test_case_t aes_icm_test_case_0 = {
484 30, /* octets in key */
485 aes_icm_test_case_0_key, /* key */
486 aes_icm_test_case_0_nonce, /* packet index */
487 32, /* octets in plaintext */
488 aes_icm_test_case_0_plaintext, /* plaintext */
489 32, /* octets in ciphertext */
490 aes_icm_test_case_0_ciphertext, /* ciphertext */
491 NULL /* pointer to next testcase */
492};
493
494
495/*
496 * note: the encrypt function is identical to the decrypt function
497 */
498
499cipher_type_t aes_icm = {
500 (cipher_alloc_func_t) aes_icm_alloc,
501 (cipher_dealloc_func_t) aes_icm_dealloc,
502 (cipher_init_func_t) aes_icm_context_init,
503 (cipher_encrypt_func_t) aes_icm_encrypt,
504 (cipher_decrypt_func_t) aes_icm_encrypt,
505 (cipher_set_iv_func_t) aes_icm_set_iv,
506 (char *) aes_icm_description,
507 (int) 0, /* instance count */
508 (cipher_test_case_t *) &aes_icm_test_case_0,
509 (debug_module_t *) &mod_aes_icm
510};
511