aes_icm.c (14081B)
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-2017 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 #ifdef HAVE_CONFIG_H 47 #include <config.h> 48 #endif 49 50 #define ALIGN_32 0 51 52 #include "aes_icm.h" 53 #include "alloc.h" 54 #include "cipher_types.h" 55 #include "cipher_test_cases.h" 56 57 srtp_debug_module_t srtp_mod_aes_icm = { 58 0, /* debugging is off by default */ 59 "aes icm" /* printable module name */ 60 }; 61 62 /* 63 * integer counter mode works as follows: 64 * 65 * 16 bits 66 * <-----> 67 * +------+------+------+------+------+------+------+------+ 68 * | nonce | pakcet index | ctr |---+ 69 * +------+------+------+------+------+------+------+------+ | 70 * | 71 * +------+------+------+------+------+------+------+------+ v 72 * | salt |000000|->(+) 73 * +------+------+------+------+------+------+------+------+ | 74 * | 75 * +---------+ 76 * | encrypt | 77 * +---------+ 78 * | 79 * +------+------+------+------+------+------+------+------+ | 80 * | keystream block |<--+ 81 * +------+------+------+------+------+------+------+------+ 82 * 83 * All fields are big-endian 84 * 85 * ctr is the block counter, which increments from zero for 86 * each packet (16 bits wide) 87 * 88 * packet index is distinct for each packet (48 bits wide) 89 * 90 * nonce can be distinct across many uses of the same key, or 91 * can be a fixed value per key, or can be per-packet randomness 92 * (64 bits) 93 * 94 */ 95 96 static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c, 97 int key_len, 98 int tlen) 99 { 100 srtp_aes_icm_ctx_t *icm; 101 (void)tlen; 102 103 debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", 104 key_len); 105 106 /* 107 * The check for key_len = 30/46 does not apply. Our usage 108 * of aes functions with key_len = values other than 30 109 * has not broken anything. Don't know what would be the 110 * effect of skipping this check for srtp in general. 111 */ 112 if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && 113 key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) { 114 return srtp_err_status_bad_param; 115 } 116 117 /* allocate memory a cipher of type aes_icm */ 118 *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t)); 119 if (*c == NULL) { 120 return srtp_err_status_alloc_fail; 121 } 122 123 icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t)); 124 if (icm == NULL) { 125 srtp_crypto_free(*c); 126 *c = NULL; 127 return srtp_err_status_alloc_fail; 128 } 129 130 /* set pointers */ 131 (*c)->state = icm; 132 133 switch (key_len) { 134 case SRTP_AES_ICM_256_KEY_LEN_WSALT: 135 (*c)->algorithm = SRTP_AES_ICM_256; 136 (*c)->type = &srtp_aes_icm_256; 137 break; 138 default: 139 (*c)->algorithm = SRTP_AES_ICM_128; 140 (*c)->type = &srtp_aes_icm_128; 141 break; 142 } 143 144 /* set key size */ 145 icm->key_size = key_len; 146 (*c)->key_len = key_len; 147 148 return srtp_err_status_ok; 149 } 150 151 static srtp_err_status_t srtp_aes_icm_dealloc(srtp_cipher_t *c) 152 { 153 srtp_aes_icm_ctx_t *ctx; 154 155 if (c == NULL) { 156 return srtp_err_status_bad_param; 157 } 158 159 ctx = (srtp_aes_icm_ctx_t *)c->state; 160 if (ctx) { 161 /* zeroize the key material */ 162 octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t)); 163 srtp_crypto_free(ctx); 164 } 165 166 /* free the cipher context */ 167 srtp_crypto_free(c); 168 169 return srtp_err_status_ok; 170 } 171 172 /* 173 * aes_icm_context_init(...) initializes the aes_icm_context 174 * using the value in key[]. 175 * 176 * the key is the secret key 177 * 178 * the salt is unpredictable (but not necessarily secret) data which 179 * randomizes the starting point in the keystream 180 */ 181 182 static srtp_err_status_t srtp_aes_icm_context_init(void *cv, const uint8_t *key) 183 { 184 srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; 185 srtp_err_status_t status; 186 int base_key_len, copy_len; 187 188 if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT || 189 c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) { 190 base_key_len = c->key_size - SRTP_SALT_LEN; 191 } else { 192 return srtp_err_status_bad_param; 193 } 194 195 /* 196 * set counter and initial values to 'offset' value, being careful not to 197 * go past the end of the key buffer 198 */ 199 v128_set_to_zero(&c->counter); 200 v128_set_to_zero(&c->offset); 201 202 copy_len = c->key_size - base_key_len; 203 /* force last two octets of the offset to be left zero (for srtp 204 * compatibility) */ 205 if (copy_len > SRTP_SALT_LEN) { 206 copy_len = SRTP_SALT_LEN; 207 } 208 209 memcpy(&c->counter, key + base_key_len, copy_len); 210 memcpy(&c->offset, key + base_key_len, copy_len); 211 212 debug_print(srtp_mod_aes_icm, "key: %s", 213 srtp_octet_string_hex_string(key, base_key_len)); 214 debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); 215 216 /* expand key */ 217 status = 218 srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key); 219 if (status) { 220 v128_set_to_zero(&c->counter); 221 v128_set_to_zero(&c->offset); 222 return status; 223 } 224 225 /* indicate that the keystream_buffer is empty */ 226 c->bytes_in_buffer = 0; 227 228 return srtp_err_status_ok; 229 } 230 231 /* 232 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with 233 * the offset 234 */ 235 236 static srtp_err_status_t srtp_aes_icm_set_iv(void *cv, 237 uint8_t *iv, 238 srtp_cipher_direction_t direction) 239 { 240 srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; 241 v128_t nonce; 242 (void)direction; 243 244 /* set nonce (for alignment) */ 245 v128_copy_octet_string(&nonce, iv); 246 247 debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); 248 249 v128_xor(&c->counter, &c->offset, &nonce); 250 251 debug_print(srtp_mod_aes_icm, "set_counter: %s", 252 v128_hex_string(&c->counter)); 253 254 /* indicate that the keystream_buffer is empty */ 255 c->bytes_in_buffer = 0; 256 257 return srtp_err_status_ok; 258 } 259 260 /* 261 * aes_icm_advance(...) refills the keystream_buffer and 262 * advances the block index of the sicm_context forward by one 263 * 264 * this is an internal, hopefully inlined function 265 */ 266 static void srtp_aes_icm_advance(srtp_aes_icm_ctx_t *c) 267 { 268 /* fill buffer with new keystream */ 269 v128_copy(&c->keystream_buffer, &c->counter); 270 srtp_aes_encrypt(&c->keystream_buffer, &c->expanded_key); 271 c->bytes_in_buffer = sizeof(v128_t); 272 273 debug_print(srtp_mod_aes_icm, "counter: %s", 274 v128_hex_string(&c->counter)); 275 debug_print(srtp_mod_aes_icm, "ciphertext: %s", 276 v128_hex_string(&c->keystream_buffer)); 277 278 /* clock counter forward */ 279 if (!++(c->counter.v8[15])) { 280 ++(c->counter.v8[14]); 281 } 282 } 283 284 /* 285 * icm_encrypt deals with the following cases: 286 * 287 * bytes_to_encr < bytes_in_buffer 288 * - add keystream into data 289 * 290 * bytes_to_encr > bytes_in_buffer 291 * - add keystream into data until keystream_buffer is depleted 292 * - loop over blocks, filling keystream_buffer and then 293 * adding keystream into data 294 * - fill buffer then add in remaining (< 16) bytes of keystream 295 */ 296 297 static srtp_err_status_t srtp_aes_icm_encrypt(void *cv, 298 unsigned char *buf, 299 unsigned int *enc_len) 300 { 301 srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; 302 unsigned int bytes_to_encr = *enc_len; 303 unsigned int i; 304 uint32_t *b; 305 306 /* check that there's enough segment left*/ 307 unsigned int bytes_of_new_keystream = bytes_to_encr - c->bytes_in_buffer; 308 unsigned int blocks_of_new_keystream = (bytes_of_new_keystream + 15) >> 4; 309 if ((blocks_of_new_keystream + htons(c->counter.v16[7])) > 0xffff) { 310 return srtp_err_status_terminus; 311 } 312 313 debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7])); 314 if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) { 315 /* deal with odd case of small bytes_to_encr */ 316 for (i = (sizeof(v128_t) - c->bytes_in_buffer); 317 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) { 318 *buf++ ^= c->keystream_buffer.v8[i]; 319 } 320 321 c->bytes_in_buffer -= bytes_to_encr; 322 323 /* return now to avoid the main loop */ 324 return srtp_err_status_ok; 325 326 } else { 327 /* encrypt bytes until the remaining data is 16-byte aligned */ 328 for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); 329 i++) { 330 *buf++ ^= c->keystream_buffer.v8[i]; 331 } 332 333 bytes_to_encr -= c->bytes_in_buffer; 334 c->bytes_in_buffer = 0; 335 } 336 337 /* now loop over entire 16-byte blocks of keystream */ 338 for (i = 0; i < (bytes_to_encr / sizeof(v128_t)); i++) { 339 /* fill buffer with new keystream */ 340 srtp_aes_icm_advance(c); 341 342 /* 343 * add keystream into the data buffer (this would be a lot faster 344 * if we could assume 32-bit alignment!) 345 */ 346 347 #if ALIGN_32 348 b = (uint32_t *)buf; 349 *b++ ^= c->keystream_buffer.v32[0]; 350 *b++ ^= c->keystream_buffer.v32[1]; 351 *b++ ^= c->keystream_buffer.v32[2]; 352 *b++ ^= c->keystream_buffer.v32[3]; 353 buf = (uint8_t *)b; 354 #else 355 if ((((uintptr_t)buf) & 0x03) != 0) { 356 *buf++ ^= c->keystream_buffer.v8[0]; 357 *buf++ ^= c->keystream_buffer.v8[1]; 358 *buf++ ^= c->keystream_buffer.v8[2]; 359 *buf++ ^= c->keystream_buffer.v8[3]; 360 *buf++ ^= c->keystream_buffer.v8[4]; 361 *buf++ ^= c->keystream_buffer.v8[5]; 362 *buf++ ^= c->keystream_buffer.v8[6]; 363 *buf++ ^= c->keystream_buffer.v8[7]; 364 *buf++ ^= c->keystream_buffer.v8[8]; 365 *buf++ ^= c->keystream_buffer.v8[9]; 366 *buf++ ^= c->keystream_buffer.v8[10]; 367 *buf++ ^= c->keystream_buffer.v8[11]; 368 *buf++ ^= c->keystream_buffer.v8[12]; 369 *buf++ ^= c->keystream_buffer.v8[13]; 370 *buf++ ^= c->keystream_buffer.v8[14]; 371 *buf++ ^= c->keystream_buffer.v8[15]; 372 } else { 373 b = (uint32_t *)buf; 374 *b++ ^= c->keystream_buffer.v32[0]; 375 *b++ ^= c->keystream_buffer.v32[1]; 376 *b++ ^= c->keystream_buffer.v32[2]; 377 *b++ ^= c->keystream_buffer.v32[3]; 378 buf = (uint8_t *)b; 379 } 380 #endif /* #if ALIGN_32 */ 381 } 382 383 /* if there is a tail end of the data, process it */ 384 if ((bytes_to_encr & 0xf) != 0) { 385 /* fill buffer with new keystream */ 386 srtp_aes_icm_advance(c); 387 388 for (i = 0; i < (bytes_to_encr & 0xf); i++) { 389 *buf++ ^= c->keystream_buffer.v8[i]; 390 } 391 392 /* reset the keystream buffer size to right value */ 393 c->bytes_in_buffer = sizeof(v128_t) - i; 394 } else { 395 /* no tail, so just reset the keystream buffer size to zero */ 396 c->bytes_in_buffer = 0; 397 } 398 399 return srtp_err_status_ok; 400 } 401 402 static const char srtp_aes_icm_128_description[] = 403 "AES-128 integer counter mode"; 404 static const char srtp_aes_icm_256_description[] = 405 "AES-256 integer counter mode"; 406 407 /* 408 * note: the encrypt function is identical to the decrypt function 409 */ 410 411 const srtp_cipher_type_t srtp_aes_icm_128 = { 412 srtp_aes_icm_alloc, /* */ 413 srtp_aes_icm_dealloc, /* */ 414 srtp_aes_icm_context_init, /* */ 415 0, /* set_aad */ 416 srtp_aes_icm_encrypt, /* */ 417 srtp_aes_icm_encrypt, /* */ 418 srtp_aes_icm_set_iv, /* */ 419 0, /* get_tag */ 420 srtp_aes_icm_128_description, /* */ 421 &srtp_aes_icm_128_test_case_0, /* */ 422 SRTP_AES_ICM_128 /* */ 423 }; 424 425 const srtp_cipher_type_t srtp_aes_icm_256 = { 426 srtp_aes_icm_alloc, /* */ 427 srtp_aes_icm_dealloc, /* */ 428 srtp_aes_icm_context_init, /* */ 429 0, /* set_aad */ 430 srtp_aes_icm_encrypt, /* */ 431 srtp_aes_icm_encrypt, /* */ 432 srtp_aes_icm_set_iv, /* */ 433 0, /* get_tag */ 434 srtp_aes_icm_256_description, /* */ 435 &srtp_aes_icm_256_test_case_0, /* */ 436 SRTP_AES_ICM_256 /* */ 437 };