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

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

Issue 3423016: Add current version of libSRTP from CVS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: '' Created 10 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « libsrtp/crypto/cipher/aes_cbc.c ('k') | libsrtp/crypto/cipher/cipher.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
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, 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/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;
112
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;
118
119 /* set pointers */
120 *c = (cipher_t *)pointer;
121 (*c)->type = &aes_icm;
122 (*c)->state = pointer + sizeof(cipher_t);
123
124 /* increment ref_count */
125 aes_icm.ref_count++;
126
127 /* set key size */
128 (*c)->key_len = key_len;
129
130 return err_status_ok;
131 }
132
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 }
136
137 err_status_t
138 aes_icm_dealloc(cipher_t *c) {
139 extern cipher_type_t aes_icm;
140
141 /* zeroize entire state*/
142 octet_string_set_to_zero((uint8_t *)c,
143 sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
144
145 /* free memory */
146 crypto_free(c);
147
148 /* decrement ref_count */
149 aes_icm.ref_count--;
150
151 return err_status_ok;
152 }
153
154
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 */
164
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;
169
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;
176
177 /* set counter and initial values to 'offset' value */
178 /* Note this copies past the end of the 'key' array by 2 bytes! */
179 v128_copy_octet_string(&c->counter, key + base_key_len);
180 v128_copy_octet_string(&c->offset, key + base_key_len);
181
182 /* force last two octets of the offset to zero (for srtp compatibility) */
183 c->offset.v8[14] = c->offset.v8[15] = 0;
184 c->counter.v8[14] = c->counter.v8[15] = 0;
185
186 debug_print(mod_aes_icm,
187 "key: %s", octet_string_hex_string(key, base_key_len));
188 debug_print(mod_aes_icm,
189 "offset: %s", v128_hex_string(&c->offset));
190
191 /* expand key */
192 status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
193 if (status) {
194 v128_set_to_zero(&c->counter);
195 v128_set_to_zero(&c->offset);
196 return status;
197 }
198
199 /* indicate that the keystream_buffer is empty */
200 c->bytes_in_buffer = 0;
201
202 return err_status_ok;
203 }
204
205 /*
206 * aes_icm_set_octet(c, i) sets the counter of the context which it is
207 * passed so that the next octet of keystream that will be generated
208 * is the ith octet
209 */
210
211 err_status_t
212 aes_icm_set_octet(aes_icm_ctx_t *c,
213 uint64_t octet_num) {
214
215 #ifdef NO_64BIT_MATH
216 int tail_num = low32(octet_num) & 0x0f;
217 /* 64-bit right-shift 4 */
218 uint64_t block_num = make64(high32(octet_num) >> 4,
219 ((high32(octet_num) & 0x0f)<<(32-4)) |
220 (low32(octet_num) >> 4));
221 #else
222 int tail_num = (int)(octet_num % 16);
223 uint64_t block_num = octet_num / 16;
224 #endif
225
226
227 /* set counter value */
228 /* FIX - There's no way this is correct */
229 c->counter.v64[0] = c->offset.v64[0];
230 #ifdef NO_64BIT_MATH
231 c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
232 low32(c->offset.v64[0]) ^ low32(block_num));
233 #else
234 c->counter.v64[0] = c->offset.v64[0] ^ block_num;
235 #endif
236
237 debug_print(mod_aes_icm,
238 "set_octet: %s", v128_hex_string(&c->counter));
239
240 /* fill keystream buffer, if needed */
241 if (tail_num) {
242 v128_copy(&c->keystream_buffer, &c->counter);
243 aes_encrypt(&c->keystream_buffer, &c->expanded_key);
244 c->bytes_in_buffer = sizeof(v128_t);
245
246 debug_print(mod_aes_icm, "counter: %s",
247 v128_hex_string(&c->counter));
248 debug_print(mod_aes_icm, "ciphertext: %s",
249 v128_hex_string(&c->keystream_buffer));
250
251 /* indicate number of bytes in keystream_buffer */
252 c->bytes_in_buffer = sizeof(v128_t) - tail_num;
253
254 } else {
255
256 /* indicate that keystream_buffer is empty */
257 c->bytes_in_buffer = 0;
258 }
259
260 return err_status_ok;
261 }
262
263 /*
264 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
265 * the offset
266 */
267
268 err_status_t
269 aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
270 v128_t *nonce = (v128_t *) iv;
271
272 debug_print(mod_aes_icm,
273 "setting iv: %s", v128_hex_string(nonce));
274
275 v128_xor(&c->counter, &c->offset, nonce);
276
277 debug_print(mod_aes_icm,
278 "set_counter: %s", v128_hex_string(&c->counter));
279
280 /* indicate that the keystream_buffer is empty */
281 c->bytes_in_buffer = 0;
282
283 return err_status_ok;
284 }
285
286
287
288 /*
289 * aes_icm_advance(...) refills the keystream_buffer and
290 * advances the block index of the sicm_context forward by one
291 *
292 * this is an internal, hopefully inlined function
293 */
294
295 inline void
296 aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
297 /* fill buffer with new keystream */
298 v128_copy(&c->keystream_buffer, &c->counter);
299 aes_encrypt(&c->keystream_buffer, &c->expanded_key);
300 c->bytes_in_buffer = sizeof(v128_t);
301
302 debug_print(mod_aes_icm, "counter: %s",
303 v128_hex_string(&c->counter));
304 debug_print(mod_aes_icm, "ciphertext: %s",
305 v128_hex_string(&c->keystream_buffer));
306
307 /* clock counter forward */
308
309 if (forIsmacryp) {
310 uint32_t temp;
311 //alex's clock counter forward
312 temp = ntohl(c->counter.v32[3]);
313 c->counter.v32[3] = htonl(++temp);
314 } else {
315 if (!++(c->counter.v8[15]))
316 ++(c->counter.v8[14]);
317 }
318 }
319
320 inline void aes_icm_advance(aes_icm_ctx_t *c) {
321 aes_icm_advance_ismacryp(c, 0);
322 }
323
324
325 /*e
326 * icm_encrypt deals with the following cases:
327 *
328 * bytes_to_encr < bytes_in_buffer
329 * - add keystream into data
330 *
331 * bytes_to_encr > bytes_in_buffer
332 * - add keystream into data until keystream_buffer is depleted
333 * - loop over blocks, filling keystream_buffer and then
334 * adding keystream into data
335 * - fill buffer then add in remaining (< 16) bytes of keystream
336 */
337
338 err_status_t
339 aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
340 unsigned char *buf, unsigned int *enc_len,
341 int forIsmacryp) {
342 unsigned int bytes_to_encr = *enc_len;
343 unsigned int i;
344 uint32_t *b;
345
346 /* check that there's enough segment left but not for ismacryp*/
347 if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
348 return err_status_terminus;
349
350 debug_print(mod_aes_icm, "block index: %d",
351 htons(c->counter.v16[7]));
352 if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
353
354 /* deal with odd case of small bytes_to_encr */
355 for (i = (sizeof(v128_t) - c->bytes_in_buffer);
356 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
357 {
358 *buf++ ^= c->keystream_buffer.v8[i];
359 }
360
361 c->bytes_in_buffer -= bytes_to_encr;
362
363 /* return now to avoid the main loop */
364 return err_status_ok;
365
366 } else {
367
368 /* encrypt bytes until the remaining data is 16-byte aligned */
369 for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
370 *buf++ ^= c->keystream_buffer.v8[i];
371
372 bytes_to_encr -= c->bytes_in_buffer;
373 c->bytes_in_buffer = 0;
374
375 }
376
377 /* now loop over entire 16-byte blocks of keystream */
378 for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
379
380 /* fill buffer with new keystream */
381 aes_icm_advance_ismacryp(c, forIsmacryp);
382
383 /*
384 * add keystream into the data buffer (this would be a lot faster
385 * if we could assume 32-bit alignment!)
386 */
387
388 #if ALIGN_32
389 b = (uint32_t *)buf;
390 *b++ ^= c->keystream_buffer.v32[0];
391 *b++ ^= c->keystream_buffer.v32[1];
392 *b++ ^= c->keystream_buffer.v32[2];
393 *b++ ^= c->keystream_buffer.v32[3];
394 buf = (uint8_t *)b;
395 #else
396 if ((((unsigned long) buf) & 0x03) != 0) {
397 *buf++ ^= c->keystream_buffer.v8[0];
398 *buf++ ^= c->keystream_buffer.v8[1];
399 *buf++ ^= c->keystream_buffer.v8[2];
400 *buf++ ^= c->keystream_buffer.v8[3];
401 *buf++ ^= c->keystream_buffer.v8[4];
402 *buf++ ^= c->keystream_buffer.v8[5];
403 *buf++ ^= c->keystream_buffer.v8[6];
404 *buf++ ^= c->keystream_buffer.v8[7];
405 *buf++ ^= c->keystream_buffer.v8[8];
406 *buf++ ^= c->keystream_buffer.v8[9];
407 *buf++ ^= c->keystream_buffer.v8[10];
408 *buf++ ^= c->keystream_buffer.v8[11];
409 *buf++ ^= c->keystream_buffer.v8[12];
410 *buf++ ^= c->keystream_buffer.v8[13];
411 *buf++ ^= c->keystream_buffer.v8[14];
412 *buf++ ^= c->keystream_buffer.v8[15];
413 } else {
414 b = (uint32_t *)buf;
415 *b++ ^= c->keystream_buffer.v32[0];
416 *b++ ^= c->keystream_buffer.v32[1];
417 *b++ ^= c->keystream_buffer.v32[2];
418 *b++ ^= c->keystream_buffer.v32[3];
419 buf = (uint8_t *)b;
420 }
421 #endif /* #if ALIGN_32 */
422
423 }
424
425 /* if there is a tail end of the data, process it */
426 if ((bytes_to_encr & 0xf) != 0) {
427
428 /* fill buffer with new keystream */
429 aes_icm_advance_ismacryp(c, forIsmacryp);
430
431 for (i=0; i < (bytes_to_encr & 0xf); i++)
432 *buf++ ^= c->keystream_buffer.v8[i];
433
434 /* reset the keystream buffer size to right value */
435 c->bytes_in_buffer = sizeof(v128_t) - i;
436 } else {
437
438 /* no tail, so just reset the keystream buffer size to zero */
439 c->bytes_in_buffer = 0;
440
441 }
442
443 return err_status_ok;
444 }
445
446 err_status_t
447 aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
448 return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
449 }
450
451 err_status_t
452 aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
453 unsigned int len = num_octets_to_output;
454
455 /* zeroize the buffer */
456 octet_string_set_to_zero(buffer, num_octets_to_output);
457
458 /* exor keystream into buffer */
459 return aes_icm_encrypt(c, buffer, &len);
460 }
461
462
463 char
464 aes_icm_description[] = "aes integer counter mode";
465
466 uint8_t aes_icm_test_case_0_key[30] = {
467 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
468 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
469 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
470 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
471 };
472
473 uint8_t aes_icm_test_case_0_nonce[16] = {
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_plaintext[32] = {
479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 };
484
485 uint8_t aes_icm_test_case_0_ciphertext[32] = {
486 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
487 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
488 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
489 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
490 };
491
492 cipher_test_case_t aes_icm_test_case_0 = {
493 30, /* octets in key */
494 aes_icm_test_case_0_key, /* key */
495 aes_icm_test_case_0_nonce, /* packet index */
496 32, /* octets in plaintext */
497 aes_icm_test_case_0_plaintext, /* plaintext */
498 32, /* octets in ciphertext */
499 aes_icm_test_case_0_ciphertext, /* ciphertext */
500 NULL /* pointer to next testcase */
501 };
502
503 uint8_t aes_icm_test_case_1_key[46] = {
504 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
505 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
506 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
507 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
508 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
509 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
510 };
511
512 uint8_t aes_icm_test_case_1_nonce[16] = {
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
515 };
516
517 uint8_t aes_icm_test_case_1_plaintext[32] = {
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 };
523
524 uint8_t aes_icm_test_case_1_ciphertext[32] = {
525 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
526 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
527 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
528 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
529 };
530
531 cipher_test_case_t aes_icm_test_case_1 = {
532 46, /* octets in key */
533 aes_icm_test_case_1_key, /* key */
534 aes_icm_test_case_1_nonce, /* packet index */
535 32, /* octets in plaintext */
536 aes_icm_test_case_1_plaintext, /* plaintext */
537 32, /* octets in ciphertext */
538 aes_icm_test_case_1_ciphertext, /* ciphertext */
539 &aes_icm_test_case_0 /* pointer to next testcase */
540 };
541
542
543
544 /*
545 * note: the encrypt function is identical to the decrypt function
546 */
547
548 cipher_type_t aes_icm = {
549 (cipher_alloc_func_t) aes_icm_alloc,
550 (cipher_dealloc_func_t) aes_icm_dealloc,
551 (cipher_init_func_t) aes_icm_context_init,
552 (cipher_encrypt_func_t) aes_icm_encrypt,
553 (cipher_decrypt_func_t) aes_icm_encrypt,
554 (cipher_set_iv_func_t) aes_icm_set_iv,
555 (char *) aes_icm_description,
556 (int) 0, /* instance count */
557 (cipher_test_case_t *) &aes_icm_test_case_1,
558 (debug_module_t *) &mod_aes_icm,
559 (cipher_type_id_t) AES_ICM
560 };
561
OLDNEW
« no previous file with comments | « libsrtp/crypto/cipher/aes_cbc.c ('k') | libsrtp/crypto/cipher/cipher.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698