• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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