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
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  int i;
168
169  /* set counter and initial values to 'offset' value */
170  /* FIX!!! this assumes the salt is at key + 16, and thus that the */
171  /* FIX!!! cipher key length is 16! */
172  for (i = 0; i < 14; i++) {
173    c->counter.v8[i] = key[16 + i];
174    c->offset.v8[i] = key[16 + i];
175  }
176
177  /* force last two octets of the offset to zero (for srtp compatibility) */
178  c->offset.v8[14] = c->offset.v8[15] = 0;
179  c->counter.v8[14] = c->counter.v8[15] = 0;
180
181  /* set tmp_key (for alignment) */
182  v128_copy_octet_string(&tmp_key, key);
183
184  debug_print(mod_aes_icm,
185	      "key:  %s", v128_hex_string(&tmp_key));
186  debug_print(mod_aes_icm,
187	      "offset: %s", v128_hex_string(&c->offset));
188
189  /* expand key */
190  aes_expand_encryption_key(&tmp_key, c->expanded_key);
191
192  /* indicate that the keystream_buffer is empty */
193  c->bytes_in_buffer = 0;
194
195  return err_status_ok;
196}
197
198/*
199 * aes_icm_set_octet(c, i) sets the counter of the context which it is
200 * passed so that the next octet of keystream that will be generated
201 * is the ith octet
202 */
203
204err_status_t
205aes_icm_set_octet(aes_icm_ctx_t *c,
206		  uint64_t octet_num) {
207
208#ifdef NO_64BIT_MATH
209  int tail_num       = low32(octet_num) & 0x0f;
210  /* 64-bit right-shift 4 */
211  uint64_t block_num = make64(high32(octet_num) >> 4,
212							  ((high32(octet_num) & 0x0f)<<(32-4)) |
213							   (low32(octet_num) >> 4));
214#else
215  int tail_num       = (int)(octet_num % 16);
216  uint64_t block_num = octet_num / 16;
217#endif
218
219
220  /* set counter value */
221  /* FIX - There's no way this is correct */
222  c->counter.v64[0] = c->offset.v64[0];
223#ifdef NO_64BIT_MATH
224  c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
225							 low32(c->offset.v64[0])  ^ low32(block_num));
226#else
227  c->counter.v64[0] = c->offset.v64[0] ^ block_num;
228#endif
229
230  debug_print(mod_aes_icm,
231	      "set_octet: %s", v128_hex_string(&c->counter));
232
233  /* fill keystream buffer, if needed */
234  if (tail_num) {
235    v128_copy(&c->keystream_buffer, &c->counter);
236    aes_encrypt(&c->keystream_buffer, c->expanded_key);
237    c->bytes_in_buffer = sizeof(v128_t);
238
239    debug_print(mod_aes_icm, "counter:    %s",
240	      v128_hex_string(&c->counter));
241    debug_print(mod_aes_icm, "ciphertext: %s",
242	      v128_hex_string(&c->keystream_buffer));
243
244    /*  indicate number of bytes in keystream_buffer  */
245    c->bytes_in_buffer = sizeof(v128_t) - tail_num;
246
247  } else {
248
249    /* indicate that keystream_buffer is empty */
250    c->bytes_in_buffer = 0;
251  }
252
253  return err_status_ok;
254}
255
256/*
257 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
258 * the offset
259 */
260
261err_status_t
262aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
263  v128_t *nonce = (v128_t *) iv;
264
265  debug_print(mod_aes_icm,
266	      "setting iv: %s", v128_hex_string(nonce));
267
268  v128_xor(&c->counter, &c->offset, nonce);
269
270  debug_print(mod_aes_icm,
271	      "set_counter: %s", v128_hex_string(&c->counter));
272
273  /* indicate that the keystream_buffer is empty */
274  c->bytes_in_buffer = 0;
275
276  return err_status_ok;
277}
278
279
280
281/*
282 * aes_icm_advance(...) refills the keystream_buffer and
283 * advances the block index of the sicm_context forward by one
284 *
285 * this is an internal, hopefully inlined function
286 */
287
288static inline void
289aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
290  /* fill buffer with new keystream */
291  v128_copy(&c->keystream_buffer, &c->counter);
292  aes_encrypt(&c->keystream_buffer, c->expanded_key);
293  c->bytes_in_buffer = sizeof(v128_t);
294
295  debug_print(mod_aes_icm, "counter:    %s",
296	      v128_hex_string(&c->counter));
297  debug_print(mod_aes_icm, "ciphertext: %s",
298	      v128_hex_string(&c->keystream_buffer));
299
300  /* clock counter forward */
301
302  if (forIsmacryp) {
303    uint32_t temp;
304    //alex's clock counter forward
305    temp = ntohl(c->counter.v32[3]);
306    c->counter.v32[3] = htonl(++temp);
307  } else {
308    if (!++(c->counter.v8[15]))
309      ++(c->counter.v8[14]);
310  }
311}
312
313inline void aes_icm_advance(aes_icm_ctx_t *c) {
314  aes_icm_advance_ismacryp(c, 0);
315}
316
317
318/*e
319 * icm_encrypt deals with the following cases:
320 *
321 * bytes_to_encr < bytes_in_buffer
322 *  - add keystream into data
323 *
324 * bytes_to_encr > bytes_in_buffer
325 *  - add keystream into data until keystream_buffer is depleted
326 *  - loop over blocks, filling keystream_buffer and then
327 *    adding keystream into data
328 *  - fill buffer then add in remaining (< 16) bytes of keystream
329 */
330
331err_status_t
332aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
333              unsigned char *buf, unsigned int *enc_len,
334              int forIsmacryp) {
335  unsigned int bytes_to_encr = *enc_len;
336  unsigned int i;
337  uint32_t *b;
338
339  /* check that there's enough segment left but not for ismacryp*/
340  if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
341    return err_status_terminus;
342
343 debug_print(mod_aes_icm, "block index: %d",
344           htons(c->counter.v16[7]));
345  if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
346
347    /* deal with odd case of small bytes_to_encr */
348    for (i = (sizeof(v128_t) - c->bytes_in_buffer);
349		 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
350	{
351      *buf++ ^= c->keystream_buffer.v8[i];
352	}
353
354    c->bytes_in_buffer -= bytes_to_encr;
355
356    /* return now to avoid the main loop */
357    return err_status_ok;
358
359  } else {
360
361    /* encrypt bytes until the remaining data is 16-byte aligned */
362    for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
363      *buf++ ^= c->keystream_buffer.v8[i];
364
365    bytes_to_encr -= c->bytes_in_buffer;
366    c->bytes_in_buffer = 0;
367
368  }
369
370  /* now loop over entire 16-byte blocks of keystream */
371  for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
372
373    /* fill buffer with new keystream */
374    aes_icm_advance_ismacryp(c, forIsmacryp);
375
376    /*
377     * add keystream into the data buffer (this would be a lot faster
378     * if we could assume 32-bit alignment!)
379     */
380
381#if ALIGN_32
382    b = (uint32_t *)buf;
383    *b++ ^= c->keystream_buffer.v32[0];
384    *b++ ^= c->keystream_buffer.v32[1];
385    *b++ ^= c->keystream_buffer.v32[2];
386    *b++ ^= c->keystream_buffer.v32[3];
387    buf = (uint8_t *)b;
388#else
389    if ((((unsigned long) buf) & 0x03) != 0) {
390      *buf++ ^= c->keystream_buffer.v8[0];
391      *buf++ ^= c->keystream_buffer.v8[1];
392      *buf++ ^= c->keystream_buffer.v8[2];
393      *buf++ ^= c->keystream_buffer.v8[3];
394      *buf++ ^= c->keystream_buffer.v8[4];
395      *buf++ ^= c->keystream_buffer.v8[5];
396      *buf++ ^= c->keystream_buffer.v8[6];
397      *buf++ ^= c->keystream_buffer.v8[7];
398      *buf++ ^= c->keystream_buffer.v8[8];
399      *buf++ ^= c->keystream_buffer.v8[9];
400      *buf++ ^= c->keystream_buffer.v8[10];
401      *buf++ ^= c->keystream_buffer.v8[11];
402      *buf++ ^= c->keystream_buffer.v8[12];
403      *buf++ ^= c->keystream_buffer.v8[13];
404      *buf++ ^= c->keystream_buffer.v8[14];
405      *buf++ ^= c->keystream_buffer.v8[15];
406    } else {
407      b = (uint32_t *)buf;
408      *b++ ^= c->keystream_buffer.v32[0];
409      *b++ ^= c->keystream_buffer.v32[1];
410      *b++ ^= c->keystream_buffer.v32[2];
411      *b++ ^= c->keystream_buffer.v32[3];
412      buf = (uint8_t *)b;
413    }
414#endif /* #if ALIGN_32 */
415
416  }
417
418  /* if there is a tail end of the data, process it */
419  if ((bytes_to_encr & 0xf) != 0) {
420
421    /* fill buffer with new keystream */
422    aes_icm_advance_ismacryp(c, forIsmacryp);
423
424    for (i=0; i < (bytes_to_encr & 0xf); i++)
425      *buf++ ^= c->keystream_buffer.v8[i];
426
427    /* reset the keystream buffer size to right value */
428    c->bytes_in_buffer = sizeof(v128_t) - i;
429  } else {
430
431    /* no tail, so just reset the keystream buffer size to zero */
432    c->bytes_in_buffer = 0;
433
434  }
435
436  return err_status_ok;
437}
438
439err_status_t
440aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
441  return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
442}
443
444err_status_t
445aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
446  unsigned int len = num_octets_to_output;
447
448  /* zeroize the buffer */
449  octet_string_set_to_zero(buffer, num_octets_to_output);
450
451  /* exor keystream into buffer */
452  return aes_icm_encrypt(c, buffer, &len);
453}
454
455
456char
457aes_icm_description[] = "aes integer counter mode";
458
459uint8_t aes_icm_test_case_0_key[30] = {
460  0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
461  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
462  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
463  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
464};
465
466uint8_t aes_icm_test_case_0_nonce[16] = {
467  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
468  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
469};
470
471uint8_t aes_icm_test_case_0_plaintext[32] =  {
472  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476};
477
478uint8_t aes_icm_test_case_0_ciphertext[32] = {
479  0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
480  0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
481  0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
482  0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
483};
484
485cipher_test_case_t aes_icm_test_case_0 = {
486  30,                                    /* octets in key            */
487  aes_icm_test_case_0_key,               /* key                      */
488  aes_icm_test_case_0_nonce,             /* packet index             */
489  32,                                    /* octets in plaintext      */
490  aes_icm_test_case_0_plaintext,         /* plaintext                */
491  32,                                    /* octets in ciphertext     */
492  aes_icm_test_case_0_ciphertext,        /* ciphertext               */
493  NULL                                   /* pointer to next testcase */
494};
495
496
497/*
498 * note: the encrypt function is identical to the decrypt function
499 */
500
501cipher_type_t aes_icm = {
502  (cipher_alloc_func_t)          aes_icm_alloc,
503  (cipher_dealloc_func_t)        aes_icm_dealloc,
504  (cipher_init_func_t)           aes_icm_context_init,
505  (cipher_encrypt_func_t)        aes_icm_encrypt,
506  (cipher_decrypt_func_t)        aes_icm_encrypt,
507  (cipher_set_iv_func_t)         aes_icm_set_iv,
508  (char *)                       aes_icm_description,
509  (int)                          0,   /* instance count */
510  (cipher_test_case_t *)        &aes_icm_test_case_0,
511  (debug_module_t *)            &mod_aes_icm
512};
513