Home | History | Annotate | Download | only in cipher
      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
     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 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 
    132 err_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 
    136 err_status_t
    137 aes_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 
    164 err_status_t
    165 aes_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 
    204 err_status_t
    205 aes_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 
    261 err_status_t
    262 aes_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 
    288 static inline void
    289 aes_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 
    313 inline 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 
    331 err_status_t
    332 aes_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 
    439 err_status_t
    440 aes_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 
    444 err_status_t
    445 aes_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 
    456 char
    457 aes_icm_description[] = "aes integer counter mode";
    458 
    459 uint8_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 
    466 uint8_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 
    471 uint8_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 
    478 uint8_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 
    485 cipher_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 
    501 cipher_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