1 /*
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
53 debug_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
92 err_status_t
aes_icm_alloc_ismacryp(cipher_t ** c,int key_len,int forIsmacryp)93 aes_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/38/46 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 > 16 && key_len < 30) &&
110 key_len != 30 && key_len != 38 && key_len != 46)
111 return err_status_bad_param;
112
113 /* allocate memory a cipher of type aes_icm */
114 tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
115 pointer = (uint8_t*)crypto_alloc(tmp);
116 if (pointer == NULL)
117 return err_status_alloc_fail;
118
119 /* set pointers */
120 *c = (cipher_t *)pointer;
121 (*c)->type = &aes_icm;
122 (*c)->state = pointer + sizeof(cipher_t);
123
124 /* increment ref_count */
125 aes_icm.ref_count++;
126
127 /* set key size */
128 (*c)->key_len = key_len;
129
130 return err_status_ok;
131 }
132
aes_icm_alloc(cipher_t ** c,int key_len,int forIsmacryp)133 err_status_t aes_icm_alloc(cipher_t **c, int key_len, int forIsmacryp) {
134 return aes_icm_alloc_ismacryp(c, key_len, 0);
135 }
136
137 err_status_t
aes_icm_dealloc(cipher_t * c)138 aes_icm_dealloc(cipher_t *c) {
139 extern cipher_type_t aes_icm;
140
141 /* zeroize entire state*/
142 octet_string_set_to_zero((uint8_t *)c,
143 sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
144
145 /* free memory */
146 crypto_free(c);
147
148 /* decrement ref_count */
149 aes_icm.ref_count--;
150
151 return err_status_ok;
152 }
153
154
155 /*
156 * aes_icm_context_init(...) initializes the aes_icm_context
157 * using the value in key[].
158 *
159 * the key is the secret key
160 *
161 * the salt is unpredictable (but not necessarily secret) data which
162 * randomizes the starting point in the keystream
163 */
164
165 err_status_t
aes_icm_context_init(aes_icm_ctx_t * c,const uint8_t * key,int key_len)166 aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) {
167 err_status_t status;
168 int base_key_len, copy_len;
169
170 if (key_len > 16 && key_len < 30) /* Ismacryp */
171 base_key_len = 16;
172 else if (key_len == 30 || key_len == 38 || key_len == 46)
173 base_key_len = key_len - 14;
174 else
175 return err_status_bad_param;
176
177 /*
178 * set counter and initial values to 'offset' value, being careful not to
179 * go past the end of the key buffer.
180 */
181 v128_set_to_zero(&c->counter);
182 v128_set_to_zero(&c->offset);
183
184 /* force last two octets of the offset to be left zero
185 * (for srtp compatibility) */
186 copy_len = key_len - base_key_len;
187
188 memcpy(&c->counter, key + base_key_len, copy_len);
189 memcpy(&c->offset, key + base_key_len, copy_len);
190
191 debug_print(mod_aes_icm,
192 "key: %s", octet_string_hex_string(key, base_key_len));
193 debug_print(mod_aes_icm,
194 "offset: %s", v128_hex_string(&c->offset));
195
196 /* expand key */
197 status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
198 if (status) {
199 v128_set_to_zero(&c->counter);
200 v128_set_to_zero(&c->offset);
201 return status;
202 }
203
204 /* indicate that the keystream_buffer is empty */
205 c->bytes_in_buffer = 0;
206
207 return err_status_ok;
208 }
209
210 /*
211 * aes_icm_set_octet(c, i) sets the counter of the context which it is
212 * passed so that the next octet of keystream that will be generated
213 * is the ith octet
214 */
215
216 err_status_t
aes_icm_set_octet(aes_icm_ctx_t * c,uint64_t octet_num)217 aes_icm_set_octet(aes_icm_ctx_t *c,
218 uint64_t octet_num) {
219
220 #ifdef NO_64BIT_MATH
221 int tail_num = low32(octet_num) & 0x0f;
222 /* 64-bit right-shift 4 */
223 uint64_t block_num = make64(high32(octet_num) >> 4,
224 ((high32(octet_num) & 0x0f)<<(32-4)) |
225 (low32(octet_num) >> 4));
226 #else
227 int tail_num = (int)(octet_num % 16);
228 uint64_t block_num = octet_num / 16;
229 #endif
230
231
232 /* set counter value */
233 /* FIX - There's no way this is correct */
234 c->counter.v64[0] = c->offset.v64[0];
235 #ifdef NO_64BIT_MATH
236 c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
237 low32(c->offset.v64[0]) ^ low32(block_num));
238 #else
239 c->counter.v64[0] = c->offset.v64[0] ^ block_num;
240 #endif
241
242 debug_print(mod_aes_icm,
243 "set_octet: %s", v128_hex_string(&c->counter));
244
245 /* fill keystream buffer, if needed */
246 if (tail_num) {
247 v128_copy(&c->keystream_buffer, &c->counter);
248 aes_encrypt(&c->keystream_buffer, &c->expanded_key);
249 c->bytes_in_buffer = sizeof(v128_t);
250
251 debug_print(mod_aes_icm, "counter: %s",
252 v128_hex_string(&c->counter));
253 debug_print(mod_aes_icm, "ciphertext: %s",
254 v128_hex_string(&c->keystream_buffer));
255
256 /* indicate number of bytes in keystream_buffer */
257 c->bytes_in_buffer = sizeof(v128_t) - tail_num;
258
259 } else {
260
261 /* indicate that keystream_buffer is empty */
262 c->bytes_in_buffer = 0;
263 }
264
265 return err_status_ok;
266 }
267
268 /*
269 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
270 * the offset
271 */
272
273 err_status_t
aes_icm_set_iv(aes_icm_ctx_t * c,void * iv)274 aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
275 v128_t *nonce = (v128_t *) iv;
276
277 debug_print(mod_aes_icm,
278 "setting iv: %s", v128_hex_string(nonce));
279
280 v128_xor(&c->counter, &c->offset, nonce);
281
282 debug_print(mod_aes_icm,
283 "set_counter: %s", v128_hex_string(&c->counter));
284
285 /* indicate that the keystream_buffer is empty */
286 c->bytes_in_buffer = 0;
287
288 return err_status_ok;
289 }
290
291
292
293 /*
294 * aes_icm_advance(...) refills the keystream_buffer and
295 * advances the block index of the sicm_context forward by one
296 *
297 * this is an internal, hopefully inlined function
298 */
299
300 static INLINE void
aes_icm_advance_ismacryp(aes_icm_ctx_t * c,uint8_t forIsmacryp)301 aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
302 /* fill buffer with new keystream */
303 v128_copy(&c->keystream_buffer, &c->counter);
304 aes_encrypt(&c->keystream_buffer, &c->expanded_key);
305 c->bytes_in_buffer = sizeof(v128_t);
306
307 debug_print(mod_aes_icm, "counter: %s",
308 v128_hex_string(&c->counter));
309 debug_print(mod_aes_icm, "ciphertext: %s",
310 v128_hex_string(&c->keystream_buffer));
311
312 /* clock counter forward */
313
314 if (forIsmacryp) {
315 uint32_t temp;
316 //alex's clock counter forward
317 temp = ntohl(c->counter.v32[3]);
318 c->counter.v32[3] = htonl(++temp);
319 } else {
320 if (!++(c->counter.v8[15]))
321 ++(c->counter.v8[14]);
322 }
323 }
324
aes_icm_advance(aes_icm_ctx_t * c)325 static INLINE void aes_icm_advance(aes_icm_ctx_t *c) {
326 aes_icm_advance_ismacryp(c, 0);
327 }
328
329
330 /*e
331 * icm_encrypt deals with the following cases:
332 *
333 * bytes_to_encr < bytes_in_buffer
334 * - add keystream into data
335 *
336 * bytes_to_encr > bytes_in_buffer
337 * - add keystream into data until keystream_buffer is depleted
338 * - loop over blocks, filling keystream_buffer and then
339 * adding keystream into data
340 * - fill buffer then add in remaining (< 16) bytes of keystream
341 */
342
343 err_status_t
aes_icm_encrypt_ismacryp(aes_icm_ctx_t * c,unsigned char * buf,unsigned int * enc_len,int forIsmacryp)344 aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
345 unsigned char *buf, unsigned int *enc_len,
346 int forIsmacryp) {
347 unsigned int bytes_to_encr = *enc_len;
348 unsigned int i;
349 uint32_t *b;
350
351 /* check that there's enough segment left but not for ismacryp*/
352 if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
353 return err_status_terminus;
354
355 debug_print(mod_aes_icm, "block index: %d",
356 htons(c->counter.v16[7]));
357 if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
358
359 /* deal with odd case of small bytes_to_encr */
360 for (i = (sizeof(v128_t) - c->bytes_in_buffer);
361 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
362 {
363 *buf++ ^= c->keystream_buffer.v8[i];
364 }
365
366 c->bytes_in_buffer -= bytes_to_encr;
367
368 /* return now to avoid the main loop */
369 return err_status_ok;
370
371 } else {
372
373 /* encrypt bytes until the remaining data is 16-byte aligned */
374 for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
375 *buf++ ^= c->keystream_buffer.v8[i];
376
377 bytes_to_encr -= c->bytes_in_buffer;
378 c->bytes_in_buffer = 0;
379
380 }
381
382 /* now loop over entire 16-byte blocks of keystream */
383 for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
384
385 /* fill buffer with new keystream */
386 aes_icm_advance_ismacryp(c, forIsmacryp);
387
388 /*
389 * add keystream into the data buffer (this would be a lot faster
390 * if we could assume 32-bit alignment!)
391 */
392
393 #if ALIGN_32
394 b = (uint32_t *)buf;
395 *b++ ^= c->keystream_buffer.v32[0];
396 *b++ ^= c->keystream_buffer.v32[1];
397 *b++ ^= c->keystream_buffer.v32[2];
398 *b++ ^= c->keystream_buffer.v32[3];
399 buf = (uint8_t *)b;
400 #else
401 if ((((unsigned long) buf) & 0x03) != 0) {
402 *buf++ ^= c->keystream_buffer.v8[0];
403 *buf++ ^= c->keystream_buffer.v8[1];
404 *buf++ ^= c->keystream_buffer.v8[2];
405 *buf++ ^= c->keystream_buffer.v8[3];
406 *buf++ ^= c->keystream_buffer.v8[4];
407 *buf++ ^= c->keystream_buffer.v8[5];
408 *buf++ ^= c->keystream_buffer.v8[6];
409 *buf++ ^= c->keystream_buffer.v8[7];
410 *buf++ ^= c->keystream_buffer.v8[8];
411 *buf++ ^= c->keystream_buffer.v8[9];
412 *buf++ ^= c->keystream_buffer.v8[10];
413 *buf++ ^= c->keystream_buffer.v8[11];
414 *buf++ ^= c->keystream_buffer.v8[12];
415 *buf++ ^= c->keystream_buffer.v8[13];
416 *buf++ ^= c->keystream_buffer.v8[14];
417 *buf++ ^= c->keystream_buffer.v8[15];
418 } else {
419 b = (uint32_t *)buf;
420 *b++ ^= c->keystream_buffer.v32[0];
421 *b++ ^= c->keystream_buffer.v32[1];
422 *b++ ^= c->keystream_buffer.v32[2];
423 *b++ ^= c->keystream_buffer.v32[3];
424 buf = (uint8_t *)b;
425 }
426 #endif /* #if ALIGN_32 */
427
428 }
429
430 /* if there is a tail end of the data, process it */
431 if ((bytes_to_encr & 0xf) != 0) {
432
433 /* fill buffer with new keystream */
434 aes_icm_advance_ismacryp(c, forIsmacryp);
435
436 for (i=0; i < (bytes_to_encr & 0xf); i++)
437 *buf++ ^= c->keystream_buffer.v8[i];
438
439 /* reset the keystream buffer size to right value */
440 c->bytes_in_buffer = sizeof(v128_t) - i;
441 } else {
442
443 /* no tail, so just reset the keystream buffer size to zero */
444 c->bytes_in_buffer = 0;
445
446 }
447
448 return err_status_ok;
449 }
450
451 err_status_t
aes_icm_encrypt(aes_icm_ctx_t * c,unsigned char * buf,unsigned int * enc_len)452 aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
453 return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
454 }
455
456 err_status_t
aes_icm_output(aes_icm_ctx_t * c,uint8_t * buffer,int num_octets_to_output)457 aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
458 unsigned int len = num_octets_to_output;
459
460 /* zeroize the buffer */
461 octet_string_set_to_zero(buffer, num_octets_to_output);
462
463 /* exor keystream into buffer */
464 return aes_icm_encrypt(c, buffer, &len);
465 }
466
467
468 char
469 aes_icm_description[] = "aes integer counter mode";
470
471 uint8_t aes_icm_test_case_0_key[30] = {
472 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
473 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
474 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
475 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
476 };
477
478 uint8_t aes_icm_test_case_0_nonce[16] = {
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
481 };
482
483 uint8_t aes_icm_test_case_0_plaintext[32] = {
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 };
489
490 uint8_t aes_icm_test_case_0_ciphertext[32] = {
491 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
492 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
493 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
494 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
495 };
496
497 cipher_test_case_t aes_icm_test_case_0 = {
498 30, /* octets in key */
499 aes_icm_test_case_0_key, /* key */
500 aes_icm_test_case_0_nonce, /* packet index */
501 32, /* octets in plaintext */
502 aes_icm_test_case_0_plaintext, /* plaintext */
503 32, /* octets in ciphertext */
504 aes_icm_test_case_0_ciphertext, /* ciphertext */
505 NULL /* pointer to next testcase */
506 };
507
508 uint8_t aes_icm_test_case_1_key[46] = {
509 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
510 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
511 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
512 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
513 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
514 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
515 };
516
517 uint8_t aes_icm_test_case_1_nonce[16] = {
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
520 };
521
522 uint8_t aes_icm_test_case_1_plaintext[32] = {
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 };
528
529 uint8_t aes_icm_test_case_1_ciphertext[32] = {
530 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
531 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
532 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
533 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
534 };
535
536 cipher_test_case_t aes_icm_test_case_1 = {
537 46, /* octets in key */
538 aes_icm_test_case_1_key, /* key */
539 aes_icm_test_case_1_nonce, /* packet index */
540 32, /* octets in plaintext */
541 aes_icm_test_case_1_plaintext, /* plaintext */
542 32, /* octets in ciphertext */
543 aes_icm_test_case_1_ciphertext, /* ciphertext */
544 &aes_icm_test_case_0 /* pointer to next testcase */
545 };
546
547
548
549 /*
550 * note: the encrypt function is identical to the decrypt function
551 */
552
553 cipher_type_t aes_icm = {
554 (cipher_alloc_func_t) aes_icm_alloc,
555 (cipher_dealloc_func_t) aes_icm_dealloc,
556 (cipher_init_func_t) aes_icm_context_init,
557 (cipher_encrypt_func_t) aes_icm_encrypt,
558 (cipher_decrypt_func_t) aes_icm_encrypt,
559 (cipher_set_iv_func_t) aes_icm_set_iv,
560 (char *) aes_icm_description,
561 (int) 0, /* instance count */
562 (cipher_test_case_t *) &aes_icm_test_case_1,
563 (debug_module_t *) &mod_aes_icm,
564 (cipher_type_id_t) AES_ICM
565 };
566
567