Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: srtp/crypto/cipher/aes_icm.c

Issue 2344973002: Update libsrtp to version 2.0 (Closed)
Patch Set: Add '.' back to include_dirs Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « srtp/crypto/cipher/aes_gcm_ossl.c ('k') | srtp/crypto/cipher/aes_icm_ossl.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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,2013 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
55
56 debug_module_t mod_aes_icm = {
57 0, /* debugging is off by default */
58 "aes icm" /* printable module name */
59 };
60
61 /*
62 * integer counter mode works as follows:
63 *
64 * 16 bits
65 * <----->
66 * +------+------+------+------+------+------+------+------+
67 * | nonce | pakcet index | ctr |---+
68 * +------+------+------+------+------+------+------+------+ |
69 * |
70 * +------+------+------+------+------+------+------+------+ v
71 * | salt |000000|->(+)
72 * +------+------+------+------+------+------+------+------+ |
73 * |
74 * +---------+
75 * | encrypt |
76 * +---------+
77 * |
78 * +------+------+------+------+------+------+------+------+ |
79 * | keystream block |<--+
80 * +------+------+------+------+------+------+------+------+
81 *
82 * All fields are big-endian
83 *
84 * ctr is the block counter, which increments from zero for
85 * each packet (16 bits wide)
86 *
87 * packet index is distinct for each packet (48 bits wide)
88 *
89 * nonce can be distinct across many uses of the same key, or
90 * can be a fixed value per key, or can be per-packet randomness
91 * (64 bits)
92 *
93 */
94
95 err_status_t
96 aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) {
97 extern cipher_type_t aes_icm;
98 uint8_t *pointer;
99 int tmp;
100
101 debug_print(mod_aes_icm,
102 "allocating cipher with key length %d", key_len);
103
104 /*
105 * Ismacryp, for example, uses 16 byte key + 8 byte
106 * salt so this function is called with key_len = 24.
107 * The check for key_len = 30/38/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 (!(forIsmacryp && key_len > 16 && key_len < 30) &&
113 key_len != 30 && key_len != 38 && key_len != 46)
114 return err_status_bad_param;
115
116 /* allocate memory a cipher of type aes_icm */
117 tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
118 pointer = (uint8_t*)crypto_alloc(tmp);
119 if (pointer == NULL)
120 return err_status_alloc_fail;
121
122 /* set pointers */
123 *c = (cipher_t *)pointer;
124 switch (key_len) {
125 case 46:
126 (*c)->algorithm = AES_256_ICM;
127 break;
128 case 38:
129 (*c)->algorithm = AES_192_ICM;
130 break;
131 default:
132 (*c)->algorithm = AES_128_ICM;
133 break;
134 }
135 (*c)->type = &aes_icm;
136 (*c)->state = pointer + sizeof(cipher_t);
137
138 /* increment ref_count */
139 aes_icm.ref_count++;
140
141 /* set key size */
142 (*c)->key_len = key_len;
143
144 return err_status_ok;
145 }
146
147 err_status_t aes_icm_alloc(cipher_t **c, int key_len, int forIsmacryp) {
148 return aes_icm_alloc_ismacryp(c, key_len, 0);
149 }
150
151 err_status_t
152 aes_icm_dealloc(cipher_t *c) {
153 extern cipher_type_t aes_icm;
154
155 /* zeroize entire state*/
156 octet_string_set_to_zero((uint8_t *)c,
157 sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
158
159 /* free memory */
160 crypto_free(c);
161
162 /* decrement ref_count */
163 aes_icm.ref_count--;
164
165 return err_status_ok;
166 }
167
168
169 /*
170 * aes_icm_context_init(...) initializes the aes_icm_context
171 * using the value in key[].
172 *
173 * the key is the secret key
174 *
175 * the salt is unpredictable (but not necessarily secret) data which
176 * randomizes the starting point in the keystream
177 */
178
179 err_status_t
180 aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) {
181 err_status_t status;
182 int base_key_len, copy_len;
183
184 if (key_len > 16 && key_len < 30) /* Ismacryp */
185 base_key_len = 16;
186 else if (key_len == 30 || key_len == 38 || key_len == 46)
187 base_key_len = key_len - 14;
188 else
189 return err_status_bad_param;
190
191 /*
192 * set counter and initial values to 'offset' value, being careful not to
193 * go past the end of the key buffer
194 */
195 v128_set_to_zero(&c->counter);
196 v128_set_to_zero(&c->offset);
197
198 copy_len = key_len - base_key_len;
199 /* force last two octets of the offset to be left zero (for srtp compatibility ) */
200 if (copy_len > 14)
201 copy_len = 14;
202
203 memcpy(&c->counter, key + base_key_len, copy_len);
204 memcpy(&c->offset, key + base_key_len, copy_len);
205
206 debug_print(mod_aes_icm,
207 "key: %s", octet_string_hex_string(key, base_key_len));
208 debug_print(mod_aes_icm,
209 "offset: %s", v128_hex_string(&c->offset));
210
211 /* expand key */
212 status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
213 if (status) {
214 v128_set_to_zero(&c->counter);
215 v128_set_to_zero(&c->offset);
216 return status;
217 }
218
219 /* indicate that the keystream_buffer is empty */
220 c->bytes_in_buffer = 0;
221
222 return err_status_ok;
223 }
224
225 /*
226 * aes_icm_set_octet(c, i) sets the counter of the context which it is
227 * passed so that the next octet of keystream that will be generated
228 * is the ith octet
229 */
230
231 err_status_t
232 aes_icm_set_octet(aes_icm_ctx_t *c,
233 uint64_t octet_num) {
234
235 #ifdef NO_64BIT_MATH
236 int tail_num = low32(octet_num) & 0x0f;
237 /* 64-bit right-shift 4 */
238 uint64_t block_num = make64(high32(octet_num) >> 4,
239 ((high32(octet_num) & 0x0f)<<(32-4)) |
240 (low32(octet_num) >> 4));
241 #else
242 int tail_num = (int)(octet_num % 16);
243 uint64_t block_num = octet_num / 16;
244 #endif
245
246
247 /* set counter value */
248 /* FIX - There's no way this is correct */
249 c->counter.v64[0] = c->offset.v64[0];
250 #ifdef NO_64BIT_MATH
251 c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
252 low32(c->offset.v64[0]) ^ low32(block_num));
253 #else
254 c->counter.v64[0] = c->offset.v64[0] ^ block_num;
255 #endif
256
257 debug_print(mod_aes_icm,
258 "set_octet: %s", v128_hex_string(&c->counter));
259
260 /* fill keystream buffer, if needed */
261 if (tail_num) {
262 v128_copy(&c->keystream_buffer, &c->counter);
263 aes_encrypt(&c->keystream_buffer, &c->expanded_key);
264 c->bytes_in_buffer = sizeof(v128_t);
265
266 debug_print(mod_aes_icm, "counter: %s",
267 v128_hex_string(&c->counter));
268 debug_print(mod_aes_icm, "ciphertext: %s",
269 v128_hex_string(&c->keystream_buffer));
270
271 /* indicate number of bytes in keystream_buffer */
272 c->bytes_in_buffer = sizeof(v128_t) - tail_num;
273
274 } else {
275
276 /* indicate that keystream_buffer is empty */
277 c->bytes_in_buffer = 0;
278 }
279
280 return err_status_ok;
281 }
282
283 /*
284 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
285 * the offset
286 */
287
288 err_status_t
289 aes_icm_set_iv(aes_icm_ctx_t *c, void *iv, int direction) {
290 v128_t nonce;
291
292 /* set nonce (for alignment) */
293 v128_copy_octet_string(&nonce, iv);
294
295 debug_print(mod_aes_icm,
296 "setting iv: %s", v128_hex_string(&nonce));
297
298 v128_xor(&c->counter, &c->offset, &nonce);
299
300 debug_print(mod_aes_icm,
301 "set_counter: %s", v128_hex_string(&c->counter));
302
303 /* indicate that the keystream_buffer is empty */
304 c->bytes_in_buffer = 0;
305
306 return err_status_ok;
307 }
308
309
310
311 /*
312 * aes_icm_advance(...) refills the keystream_buffer and
313 * advances the block index of the sicm_context forward by one
314 *
315 * this is an internal, hopefully inlined function
316 */
317
318 static inline void
319 aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
320 /* fill buffer with new keystream */
321 v128_copy(&c->keystream_buffer, &c->counter);
322 aes_encrypt(&c->keystream_buffer, &c->expanded_key);
323 c->bytes_in_buffer = sizeof(v128_t);
324
325 debug_print(mod_aes_icm, "counter: %s",
326 v128_hex_string(&c->counter));
327 debug_print(mod_aes_icm, "ciphertext: %s",
328 v128_hex_string(&c->keystream_buffer));
329
330 /* clock counter forward */
331
332 if (forIsmacryp) {
333 uint32_t temp;
334 //alex's clock counter forward
335 temp = ntohl(c->counter.v32[3]);
336 ++temp;
337 c->counter.v32[3] = htonl(temp);
338 } else {
339 if (!++(c->counter.v8[15]))
340 ++(c->counter.v8[14]);
341 }
342 }
343
344 /*e
345 * icm_encrypt deals with the following cases:
346 *
347 * bytes_to_encr < bytes_in_buffer
348 * - add keystream into data
349 *
350 * bytes_to_encr > bytes_in_buffer
351 * - add keystream into data until keystream_buffer is depleted
352 * - loop over blocks, filling keystream_buffer and then
353 * adding keystream into data
354 * - fill buffer then add in remaining (< 16) bytes of keystream
355 */
356
357 err_status_t
358 aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
359 unsigned char *buf, unsigned int *enc_len,
360 int forIsmacryp) {
361 unsigned int bytes_to_encr = *enc_len;
362 unsigned int i;
363 uint32_t *b;
364
365 /* check that there's enough segment left but not for ismacryp*/
366 if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
367 return err_status_terminus;
368
369 debug_print(mod_aes_icm, "block index: %d",
370 htons(c->counter.v16[7]));
371 if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
372
373 /* deal with odd case of small bytes_to_encr */
374 for (i = (sizeof(v128_t) - c->bytes_in_buffer);
375 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
376 {
377 *buf++ ^= c->keystream_buffer.v8[i];
378 }
379
380 c->bytes_in_buffer -= bytes_to_encr;
381
382 /* return now to avoid the main loop */
383 return err_status_ok;
384
385 } else {
386
387 /* encrypt bytes until the remaining data is 16-byte aligned */
388 for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
389 *buf++ ^= c->keystream_buffer.v8[i];
390
391 bytes_to_encr -= c->bytes_in_buffer;
392 c->bytes_in_buffer = 0;
393
394 }
395
396 /* now loop over entire 16-byte blocks of keystream */
397 for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
398
399 /* fill buffer with new keystream */
400 aes_icm_advance_ismacryp(c, forIsmacryp);
401
402 /*
403 * add keystream into the data buffer (this would be a lot faster
404 * if we could assume 32-bit alignment!)
405 */
406
407 #if ALIGN_32
408 b = (uint32_t *)buf;
409 *b++ ^= c->keystream_buffer.v32[0];
410 *b++ ^= c->keystream_buffer.v32[1];
411 *b++ ^= c->keystream_buffer.v32[2];
412 *b++ ^= c->keystream_buffer.v32[3];
413 buf = (uint8_t *)b;
414 #else
415 if ((((unsigned long) buf) & 0x03) != 0) {
416 *buf++ ^= c->keystream_buffer.v8[0];
417 *buf++ ^= c->keystream_buffer.v8[1];
418 *buf++ ^= c->keystream_buffer.v8[2];
419 *buf++ ^= c->keystream_buffer.v8[3];
420 *buf++ ^= c->keystream_buffer.v8[4];
421 *buf++ ^= c->keystream_buffer.v8[5];
422 *buf++ ^= c->keystream_buffer.v8[6];
423 *buf++ ^= c->keystream_buffer.v8[7];
424 *buf++ ^= c->keystream_buffer.v8[8];
425 *buf++ ^= c->keystream_buffer.v8[9];
426 *buf++ ^= c->keystream_buffer.v8[10];
427 *buf++ ^= c->keystream_buffer.v8[11];
428 *buf++ ^= c->keystream_buffer.v8[12];
429 *buf++ ^= c->keystream_buffer.v8[13];
430 *buf++ ^= c->keystream_buffer.v8[14];
431 *buf++ ^= c->keystream_buffer.v8[15];
432 } else {
433 b = (uint32_t *)buf;
434 *b++ ^= c->keystream_buffer.v32[0];
435 *b++ ^= c->keystream_buffer.v32[1];
436 *b++ ^= c->keystream_buffer.v32[2];
437 *b++ ^= c->keystream_buffer.v32[3];
438 buf = (uint8_t *)b;
439 }
440 #endif /* #if ALIGN_32 */
441
442 }
443
444 /* if there is a tail end of the data, process it */
445 if ((bytes_to_encr & 0xf) != 0) {
446
447 /* fill buffer with new keystream */
448 aes_icm_advance_ismacryp(c, forIsmacryp);
449
450 for (i=0; i < (bytes_to_encr & 0xf); i++)
451 *buf++ ^= c->keystream_buffer.v8[i];
452
453 /* reset the keystream buffer size to right value */
454 c->bytes_in_buffer = sizeof(v128_t) - i;
455 } else {
456
457 /* no tail, so just reset the keystream buffer size to zero */
458 c->bytes_in_buffer = 0;
459
460 }
461
462 return err_status_ok;
463 }
464
465 err_status_t
466 aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
467 return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
468 }
469
470 err_status_t
471 aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, unsigned int num_octets_to_out put) {
472 unsigned int len = num_octets_to_output;
473
474 /* zeroize the buffer */
475 octet_string_set_to_zero(buffer, num_octets_to_output);
476
477 /* exor keystream into buffer */
478 return aes_icm_encrypt(c, buffer, &len);
479 }
480
481 uint16_t
482 aes_icm_bytes_encrypted(aes_icm_ctx_t *c) {
483 return htons(c->counter.v16[7]);
484 }
485
486 char
487 aes_icm_description[] = "aes integer counter mode";
488
489 uint8_t aes_icm_test_case_0_key[30] = {
490 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
491 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
492 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
493 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
494 };
495
496 uint8_t aes_icm_test_case_0_nonce[16] = {
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
499 };
500
501 uint8_t aes_icm_test_case_0_plaintext[32] = {
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506 };
507
508 uint8_t aes_icm_test_case_0_ciphertext[32] = {
509 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
510 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
511 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
512 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
513 };
514
515 cipher_test_case_t aes_icm_test_case_0 = {
516 30, /* octets in key */
517 aes_icm_test_case_0_key, /* key */
518 aes_icm_test_case_0_nonce, /* packet index */
519 32, /* octets in plaintext */
520 aes_icm_test_case_0_plaintext, /* plaintext */
521 32, /* octets in ciphertext */
522 aes_icm_test_case_0_ciphertext, /* ciphertext */
523 0,
524 NULL,
525 0,
526 NULL /* pointer to next testcase */
527 };
528
529 uint8_t aes_icm_test_case_1_key[46] = {
530 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
531 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
532 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
533 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
534 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
535 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
536 };
537
538 uint8_t aes_icm_test_case_1_nonce[16] = {
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
541 };
542
543 uint8_t aes_icm_test_case_1_plaintext[32] = {
544 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 };
549
550 uint8_t aes_icm_test_case_1_ciphertext[32] = {
551 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
552 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
553 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
554 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
555 };
556
557 cipher_test_case_t aes_icm_test_case_1 = {
558 46, /* octets in key */
559 aes_icm_test_case_1_key, /* key */
560 aes_icm_test_case_1_nonce, /* packet index */
561 32, /* octets in plaintext */
562 aes_icm_test_case_1_plaintext, /* plaintext */
563 32, /* octets in ciphertext */
564 aes_icm_test_case_1_ciphertext, /* ciphertext */
565 0,
566 NULL,
567 0,
568 &aes_icm_test_case_0 /* pointer to next testcase */
569 };
570
571
572
573 /*
574 * note: the encrypt function is identical to the decrypt function
575 */
576
577 cipher_type_t aes_icm = {
578 (cipher_alloc_func_t) aes_icm_alloc,
579 (cipher_dealloc_func_t) aes_icm_dealloc,
580 (cipher_init_func_t) aes_icm_context_init,
581 (cipher_set_aad_func_t) 0,
582 (cipher_encrypt_func_t) aes_icm_encrypt,
583 (cipher_decrypt_func_t) aes_icm_encrypt,
584 (cipher_set_iv_func_t) aes_icm_set_iv,
585 (cipher_get_tag_func_t) 0,
586 (char *) aes_icm_description,
587 (int) 0, /* instance count */
588 (cipher_test_case_t *) &aes_icm_test_case_1,
589 (debug_module_t *) &mod_aes_icm,
590 (cipher_type_id_t) AES_ICM
591 };
592
OLDNEW
« no previous file with comments | « srtp/crypto/cipher/aes_gcm_ossl.c ('k') | srtp/crypto/cipher/aes_icm_ossl.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698