netwerk/srtp/src/crypto/cipher/aes_icm.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * aes_icm.c
     3  *
     4  * AES Integer Counter Mode
     5  *
     6  * David A. McGrew
     7  * Cisco Systems, Inc.
     8  */
    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  */
    47 #define ALIGN_32 0
    49 #include "aes_icm.h"
    50 #include "alloc.h"
    53 debug_module_t mod_aes_icm = {
    54   0,                 /* debugging is off by default */
    55   "aes icm"          /* printable module name       */
    56 };
    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  */
    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;
    98   debug_print(mod_aes_icm, 
    99             "allocating cipher with key length %d", key_len);
   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;
   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;
   119   /* set pointers */
   120   *c = (cipher_t *)pointer;
   121   (*c)->type = &aes_icm;
   122   (*c)->state = pointer + sizeof(cipher_t);
   124   /* increment ref_count */
   125   aes_icm.ref_count++;
   127   /* set key size        */
   128   (*c)->key_len = key_len;
   130   return err_status_ok;  
   131 }
   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 }
   137 err_status_t
   138 aes_icm_dealloc(cipher_t *c) {
   139   extern cipher_type_t aes_icm;
   141   /* zeroize entire state*/
   142   octet_string_set_to_zero((uint8_t *)c, 
   143 			   sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
   145   /* free memory */
   146   crypto_free(c);
   148   /* decrement ref_count */
   149   aes_icm.ref_count--;
   151   return err_status_ok;  
   152 }
   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  */
   165 err_status_t
   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;
   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;
   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);
   184   copy_len = key_len - base_key_len;
   185   /* force last two octets of the offset to be left zero (for srtp compatibility) */
   186   if (copy_len > 14)
   187     copy_len = 14;
   189   memcpy(&c->counter, key + base_key_len, copy_len);
   190   memcpy(&c->offset, key + base_key_len, copy_len);
   192   debug_print(mod_aes_icm, 
   193 	      "key:  %s", octet_string_hex_string(key, base_key_len)); 
   194   debug_print(mod_aes_icm, 
   195 	      "offset: %s", v128_hex_string(&c->offset)); 
   197   /* expand key */
   198   status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
   199   if (status) {
   200     v128_set_to_zero(&c->counter);
   201     v128_set_to_zero(&c->offset);
   202     return status;
   203   }
   205   /* indicate that the keystream_buffer is empty */
   206   c->bytes_in_buffer = 0;
   208   return err_status_ok;
   209 }
   211 /*
   212  * aes_icm_set_octet(c, i) sets the counter of the context which it is
   213  * passed so that the next octet of keystream that will be generated
   214  * is the ith octet
   215  */
   217 err_status_t
   218 aes_icm_set_octet(aes_icm_ctx_t *c,
   219 		  uint64_t octet_num) {
   221 #ifdef NO_64BIT_MATH
   222   int tail_num       = low32(octet_num) & 0x0f;
   223   /* 64-bit right-shift 4 */
   224   uint64_t block_num = make64(high32(octet_num) >> 4,
   225 							  ((high32(octet_num) & 0x0f)<<(32-4)) |
   226 							   (low32(octet_num) >> 4));
   227 #else
   228   int tail_num       = (int)(octet_num % 16);
   229   uint64_t block_num = octet_num / 16;
   230 #endif
   233   /* set counter value */
   234   /* FIX - There's no way this is correct */
   235   c->counter.v64[0] = c->offset.v64[0];
   236 #ifdef NO_64BIT_MATH
   237   c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
   238 							 low32(c->offset.v64[0])  ^ low32(block_num));
   239 #else
   240   c->counter.v64[0] = c->offset.v64[0] ^ block_num;
   241 #endif
   243   debug_print(mod_aes_icm, 
   244 	      "set_octet: %s", v128_hex_string(&c->counter)); 
   246   /* fill keystream buffer, if needed */
   247   if (tail_num) {
   248     v128_copy(&c->keystream_buffer, &c->counter);
   249     aes_encrypt(&c->keystream_buffer, &c->expanded_key);
   250     c->bytes_in_buffer = sizeof(v128_t);
   252     debug_print(mod_aes_icm, "counter:    %s", 
   253 	      v128_hex_string(&c->counter));
   254     debug_print(mod_aes_icm, "ciphertext: %s", 
   255 	      v128_hex_string(&c->keystream_buffer));    
   257     /*  indicate number of bytes in keystream_buffer  */
   258     c->bytes_in_buffer = sizeof(v128_t) - tail_num;
   260   } else {
   262     /* indicate that keystream_buffer is empty */
   263     c->bytes_in_buffer = 0;
   264   }
   266   return err_status_ok;
   267 }
   269 /*
   270  * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
   271  * the offset
   272  */
   274 err_status_t
   275 aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
   276   v128_t *nonce = (v128_t *) iv;
   278   debug_print(mod_aes_icm, 
   279 	      "setting iv: %s", v128_hex_string(nonce)); 
   281   v128_xor(&c->counter, &c->offset, nonce);
   283   debug_print(mod_aes_icm, 
   284 	      "set_counter: %s", v128_hex_string(&c->counter)); 
   286   /* indicate that the keystream_buffer is empty */
   287   c->bytes_in_buffer = 0;
   289   return err_status_ok;
   290 }
   294 /*
   295  * aes_icm_advance(...) refills the keystream_buffer and
   296  * advances the block index of the sicm_context forward by one
   297  *
   298  * this is an internal, hopefully inlined function
   299  */
   301 static inline void
   302 aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
   303   /* fill buffer with new keystream */
   304   v128_copy(&c->keystream_buffer, &c->counter);
   305   aes_encrypt(&c->keystream_buffer, &c->expanded_key);
   306   c->bytes_in_buffer = sizeof(v128_t);
   308   debug_print(mod_aes_icm, "counter:    %s", 
   309 	      v128_hex_string(&c->counter));
   310   debug_print(mod_aes_icm, "ciphertext: %s", 
   311 	      v128_hex_string(&c->keystream_buffer));    
   313   /* clock counter forward */
   315   if (forIsmacryp) {
   316     uint32_t temp;    
   317     //alex's clock counter forward
   318     temp = ntohl(c->counter.v32[3]);
   319     c->counter.v32[3] = htonl(++temp);
   320   } else {
   321     if (!++(c->counter.v8[15])) 
   322       ++(c->counter.v8[14]);
   323   }
   324 }
   326 static inline void aes_icm_advance(aes_icm_ctx_t *c) {
   327   aes_icm_advance_ismacryp(c, 0);
   328 }
   331 /*e
   332  * icm_encrypt deals with the following cases:
   333  *
   334  * bytes_to_encr < bytes_in_buffer
   335  *  - add keystream into data
   336  *
   337  * bytes_to_encr > bytes_in_buffer
   338  *  - add keystream into data until keystream_buffer is depleted
   339  *  - loop over blocks, filling keystream_buffer and then
   340  *    adding keystream into data
   341  *  - fill buffer then add in remaining (< 16) bytes of keystream 
   342  */
   344 err_status_t
   345 aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
   346               unsigned char *buf, unsigned int *enc_len, 
   347               int forIsmacryp) {
   348   unsigned int bytes_to_encr = *enc_len;
   349   unsigned int i;
   350   uint32_t *b;
   352   /* check that there's enough segment left but not for ismacryp*/
   353   if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
   354     return err_status_terminus;
   356  debug_print(mod_aes_icm, "block index: %d", 
   357            htons(c->counter.v16[7]));
   358   if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
   360     /* deal with odd case of small bytes_to_encr */
   361     for (i = (sizeof(v128_t) - c->bytes_in_buffer);
   362 		 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) 
   363 	{
   364       *buf++ ^= c->keystream_buffer.v8[i];
   365 	}
   367     c->bytes_in_buffer -= bytes_to_encr;
   369     /* return now to avoid the main loop */
   370     return err_status_ok;
   372   } else {
   374     /* encrypt bytes until the remaining data is 16-byte aligned */    
   375     for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++) 
   376       *buf++ ^= c->keystream_buffer.v8[i];
   378     bytes_to_encr -= c->bytes_in_buffer;
   379     c->bytes_in_buffer = 0;
   381   }
   383   /* now loop over entire 16-byte blocks of keystream */
   384   for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
   386     /* fill buffer with new keystream */
   387     aes_icm_advance_ismacryp(c, forIsmacryp);
   389     /*
   390      * add keystream into the data buffer (this would be a lot faster
   391      * if we could assume 32-bit alignment!)
   392      */
   394 #if ALIGN_32
   395     b = (uint32_t *)buf;
   396     *b++ ^= c->keystream_buffer.v32[0];
   397     *b++ ^= c->keystream_buffer.v32[1];
   398     *b++ ^= c->keystream_buffer.v32[2];
   399     *b++ ^= c->keystream_buffer.v32[3];
   400     buf = (uint8_t *)b;
   401 #else    
   402     if ((((unsigned long) buf) & 0x03) != 0) {
   403       *buf++ ^= c->keystream_buffer.v8[0];
   404       *buf++ ^= c->keystream_buffer.v8[1];
   405       *buf++ ^= c->keystream_buffer.v8[2];
   406       *buf++ ^= c->keystream_buffer.v8[3];
   407       *buf++ ^= c->keystream_buffer.v8[4];
   408       *buf++ ^= c->keystream_buffer.v8[5];
   409       *buf++ ^= c->keystream_buffer.v8[6];
   410       *buf++ ^= c->keystream_buffer.v8[7];
   411       *buf++ ^= c->keystream_buffer.v8[8];
   412       *buf++ ^= c->keystream_buffer.v8[9];
   413       *buf++ ^= c->keystream_buffer.v8[10];
   414       *buf++ ^= c->keystream_buffer.v8[11];
   415       *buf++ ^= c->keystream_buffer.v8[12];
   416       *buf++ ^= c->keystream_buffer.v8[13];
   417       *buf++ ^= c->keystream_buffer.v8[14];
   418       *buf++ ^= c->keystream_buffer.v8[15];
   419     } else {
   420       b = (uint32_t *)buf;
   421       *b++ ^= c->keystream_buffer.v32[0];
   422       *b++ ^= c->keystream_buffer.v32[1];
   423       *b++ ^= c->keystream_buffer.v32[2];
   424       *b++ ^= c->keystream_buffer.v32[3];
   425       buf = (uint8_t *)b;
   426     }
   427 #endif /* #if ALIGN_32 */
   429   }
   431   /* if there is a tail end of the data, process it */
   432   if ((bytes_to_encr & 0xf) != 0) {
   434     /* fill buffer with new keystream */
   435     aes_icm_advance_ismacryp(c, forIsmacryp);
   437     for (i=0; i < (bytes_to_encr & 0xf); i++)
   438       *buf++ ^= c->keystream_buffer.v8[i];
   440     /* reset the keystream buffer size to right value */
   441     c->bytes_in_buffer = sizeof(v128_t) - i;  
   442   } else {
   444     /* no tail, so just reset the keystream buffer size to zero */
   445     c->bytes_in_buffer = 0;
   447   }
   449   return err_status_ok;
   450 }
   452 err_status_t
   453 aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
   454   return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
   455 }
   457 err_status_t
   458 aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
   459   unsigned int len = num_octets_to_output;
   461   /* zeroize the buffer */
   462   octet_string_set_to_zero(buffer, num_octets_to_output);
   464   /* exor keystream into buffer */
   465   return aes_icm_encrypt(c, buffer, &len);
   466 }
   469 char 
   470 aes_icm_description[] = "aes integer counter mode";
   472 uint8_t aes_icm_test_case_0_key[30] = {
   473   0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
   474   0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
   475   0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
   476   0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
   477 };
   479 uint8_t aes_icm_test_case_0_nonce[16] = {
   480   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   481   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   482 };
   484 uint8_t aes_icm_test_case_0_plaintext[32] =  {
   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   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   489 };
   491 uint8_t aes_icm_test_case_0_ciphertext[32] = {
   492   0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
   493   0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
   494   0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
   495   0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
   496 };
   498 cipher_test_case_t aes_icm_test_case_0 = {
   499   30,                                    /* octets in key            */
   500   aes_icm_test_case_0_key,               /* key                      */
   501   aes_icm_test_case_0_nonce,             /* packet index             */
   502   32,                                    /* octets in plaintext      */
   503   aes_icm_test_case_0_plaintext,         /* plaintext                */
   504   32,                                    /* octets in ciphertext     */
   505   aes_icm_test_case_0_ciphertext,        /* ciphertext               */
   506   NULL                                   /* pointer to next testcase */
   507 };
   509 uint8_t aes_icm_test_case_1_key[46] = {
   510   0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
   511   0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
   512   0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
   513   0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
   514   0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
   515   0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
   516 };
   518 uint8_t aes_icm_test_case_1_nonce[16] = {
   519   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   520   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   521 };
   523 uint8_t aes_icm_test_case_1_plaintext[32] =  {
   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   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   528 };
   530 uint8_t aes_icm_test_case_1_ciphertext[32] = {
   531   0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
   532   0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
   533   0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
   534   0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
   535 };
   537 cipher_test_case_t aes_icm_test_case_1 = {
   538   46,                                    /* octets in key            */
   539   aes_icm_test_case_1_key,               /* key                      */
   540   aes_icm_test_case_1_nonce,             /* packet index             */
   541   32,                                    /* octets in plaintext      */
   542   aes_icm_test_case_1_plaintext,         /* plaintext                */
   543   32,                                    /* octets in ciphertext     */
   544   aes_icm_test_case_1_ciphertext,        /* ciphertext               */
   545   &aes_icm_test_case_0                   /* pointer to next testcase */
   546 };
   550 /*
   551  * note: the encrypt function is identical to the decrypt function
   552  */
   554 cipher_type_t aes_icm = {
   555   (cipher_alloc_func_t)          aes_icm_alloc,
   556   (cipher_dealloc_func_t)        aes_icm_dealloc,  
   557   (cipher_init_func_t)           aes_icm_context_init,
   558   (cipher_encrypt_func_t)        aes_icm_encrypt,
   559   (cipher_decrypt_func_t)        aes_icm_encrypt,
   560   (cipher_set_iv_func_t)         aes_icm_set_iv,
   561   (char *)                       aes_icm_description,
   562   (int)                          0,   /* instance count */
   563   (cipher_test_case_t *)        &aes_icm_test_case_1,
   564   (debug_module_t *)            &mod_aes_icm,
   565   (cipher_type_id_t)             AES_ICM
   566 };

mercurial