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
56 srtp_debug_module_t srtp_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
srtp_aes_icm_alloc(srtp_cipher_t ** c,int key_len,int tlen)95 static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c,
96 int key_len,
97 int tlen)
98 {
99 srtp_aes_icm_ctx_t *icm;
100
101 debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d",
102 key_len);
103
104 /*
105 * The check for key_len = 30/46 does not apply. Our usage
106 * of aes functions with key_len = values other than 30
107 * has not broken anything. Don't know what would be the
108 * effect of skipping this check for srtp in general.
109 */
110 if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT &&
111 key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
112 return srtp_err_status_bad_param;
113 }
114
115 /* allocate memory a cipher of type aes_icm */
116 *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
117 if (*c == NULL) {
118 return srtp_err_status_alloc_fail;
119 }
120
121 icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
122 if (icm == NULL) {
123 srtp_crypto_free(*c);
124 *c = NULL;
125 return srtp_err_status_alloc_fail;
126 }
127
128 /* set pointers */
129 (*c)->state = icm;
130
131 switch (key_len) {
132 case SRTP_AES_ICM_256_KEY_LEN_WSALT:
133 (*c)->algorithm = SRTP_AES_ICM_256;
134 (*c)->type = &srtp_aes_icm_256;
135 break;
136 default:
137 (*c)->algorithm = SRTP_AES_ICM_128;
138 (*c)->type = &srtp_aes_icm_128;
139 break;
140 }
141
142 /* set key size */
143 icm->key_size = key_len;
144 (*c)->key_len = key_len;
145
146 return srtp_err_status_ok;
147 }
148
srtp_aes_icm_dealloc(srtp_cipher_t * c)149 static srtp_err_status_t srtp_aes_icm_dealloc(srtp_cipher_t *c)
150 {
151 srtp_aes_icm_ctx_t *ctx;
152
153 if (c == NULL) {
154 return srtp_err_status_bad_param;
155 }
156
157 ctx = (srtp_aes_icm_ctx_t *)c->state;
158 if (ctx) {
159 /* zeroize the key material */
160 octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
161 srtp_crypto_free(ctx);
162 }
163
164 /* free the cipher context */
165 srtp_crypto_free(c);
166
167 return srtp_err_status_ok;
168 }
169
170 /*
171 * aes_icm_context_init(...) initializes the aes_icm_context
172 * using the value in key[].
173 *
174 * the key is the secret key
175 *
176 * the salt is unpredictable (but not necessarily secret) data which
177 * randomizes the starting point in the keystream
178 */
179
srtp_aes_icm_context_init(void * cv,const uint8_t * key)180 static srtp_err_status_t srtp_aes_icm_context_init(void *cv, const uint8_t *key)
181 {
182 srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
183 srtp_err_status_t status;
184 int base_key_len, copy_len;
185
186 if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT ||
187 c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) {
188 base_key_len = c->key_size - SRTP_SALT_LEN;
189 } else {
190 return srtp_err_status_bad_param;
191 }
192
193 /*
194 * set counter and initial values to 'offset' value, being careful not to
195 * go past the end of the key buffer
196 */
197 v128_set_to_zero(&c->counter);
198 v128_set_to_zero(&c->offset);
199
200 copy_len = c->key_size - base_key_len;
201 /* force last two octets of the offset to be left zero (for srtp
202 * compatibility) */
203 if (copy_len > SRTP_SALT_LEN) {
204 copy_len = SRTP_SALT_LEN;
205 }
206
207 memcpy(&c->counter, key + base_key_len, copy_len);
208 memcpy(&c->offset, key + base_key_len, copy_len);
209
210 debug_print(srtp_mod_aes_icm, "key: %s",
211 srtp_octet_string_hex_string(key, base_key_len));
212 debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset));
213
214 /* expand key */
215 status =
216 srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key);
217 if (status) {
218 v128_set_to_zero(&c->counter);
219 v128_set_to_zero(&c->offset);
220 return status;
221 }
222
223 /* indicate that the keystream_buffer is empty */
224 c->bytes_in_buffer = 0;
225
226 return srtp_err_status_ok;
227 }
228
229 /*
230 * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
231 * the offset
232 */
233
srtp_aes_icm_set_iv(void * cv,uint8_t * iv,srtp_cipher_direction_t direction)234 static srtp_err_status_t srtp_aes_icm_set_iv(void *cv,
235 uint8_t *iv,
236 srtp_cipher_direction_t direction)
237 {
238 srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
239 v128_t nonce;
240
241 /* set nonce (for alignment) */
242 v128_copy_octet_string(&nonce, iv);
243
244 debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce));
245
246 v128_xor(&c->counter, &c->offset, &nonce);
247
248 debug_print(srtp_mod_aes_icm, "set_counter: %s",
249 v128_hex_string(&c->counter));
250
251 /* indicate that the keystream_buffer is empty */
252 c->bytes_in_buffer = 0;
253
254 return srtp_err_status_ok;
255 }
256
257 /*
258 * aes_icm_advance(...) refills the keystream_buffer and
259 * advances the block index of the sicm_context forward by one
260 *
261 * this is an internal, hopefully inlined function
262 */
srtp_aes_icm_advance(srtp_aes_icm_ctx_t * c)263 static void srtp_aes_icm_advance(srtp_aes_icm_ctx_t *c)
264 {
265 /* fill buffer with new keystream */
266 v128_copy(&c->keystream_buffer, &c->counter);
267 srtp_aes_encrypt(&c->keystream_buffer, &c->expanded_key);
268 c->bytes_in_buffer = sizeof(v128_t);
269
270 debug_print(srtp_mod_aes_icm, "counter: %s",
271 v128_hex_string(&c->counter));
272 debug_print(srtp_mod_aes_icm, "ciphertext: %s",
273 v128_hex_string(&c->keystream_buffer));
274
275 /* clock counter forward */
276 if (!++(c->counter.v8[15])) {
277 ++(c->counter.v8[14]);
278 }
279 }
280
281 /*
282 * icm_encrypt deals with the following cases:
283 *
284 * bytes_to_encr < bytes_in_buffer
285 * - add keystream into data
286 *
287 * bytes_to_encr > bytes_in_buffer
288 * - add keystream into data until keystream_buffer is depleted
289 * - loop over blocks, filling keystream_buffer and then
290 * adding keystream into data
291 * - fill buffer then add in remaining (< 16) bytes of keystream
292 */
293
srtp_aes_icm_encrypt(void * cv,unsigned char * buf,unsigned int * enc_len)294 static srtp_err_status_t srtp_aes_icm_encrypt(void *cv,
295 unsigned char *buf,
296 unsigned int *enc_len)
297 {
298 srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
299 unsigned int bytes_to_encr = *enc_len;
300 unsigned int i;
301 uint32_t *b;
302
303 /* check that there's enough segment left*/
304 if ((bytes_to_encr + htons(c->counter.v16[7])) > 0xffff) {
305 return srtp_err_status_terminus;
306 }
307
308 debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7]));
309 if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
310 /* deal with odd case of small bytes_to_encr */
311 for (i = (sizeof(v128_t) - c->bytes_in_buffer);
312 i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) {
313 *buf++ ^= c->keystream_buffer.v8[i];
314 }
315
316 c->bytes_in_buffer -= bytes_to_encr;
317
318 /* return now to avoid the main loop */
319 return srtp_err_status_ok;
320
321 } else {
322 /* encrypt bytes until the remaining data is 16-byte aligned */
323 for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t);
324 i++) {
325 *buf++ ^= c->keystream_buffer.v8[i];
326 }
327
328 bytes_to_encr -= c->bytes_in_buffer;
329 c->bytes_in_buffer = 0;
330 }
331
332 /* now loop over entire 16-byte blocks of keystream */
333 for (i = 0; i < (bytes_to_encr / sizeof(v128_t)); i++) {
334 /* fill buffer with new keystream */
335 srtp_aes_icm_advance(c);
336
337 /*
338 * add keystream into the data buffer (this would be a lot faster
339 * if we could assume 32-bit alignment!)
340 */
341
342 #if ALIGN_32
343 b = (uint32_t *)buf;
344 *b++ ^= c->keystream_buffer.v32[0];
345 *b++ ^= c->keystream_buffer.v32[1];
346 *b++ ^= c->keystream_buffer.v32[2];
347 *b++ ^= c->keystream_buffer.v32[3];
348 buf = (uint8_t *)b;
349 #else
350 if ((((uintptr_t)buf) & 0x03) != 0) {
351 *buf++ ^= c->keystream_buffer.v8[0];
352 *buf++ ^= c->keystream_buffer.v8[1];
353 *buf++ ^= c->keystream_buffer.v8[2];
354 *buf++ ^= c->keystream_buffer.v8[3];
355 *buf++ ^= c->keystream_buffer.v8[4];
356 *buf++ ^= c->keystream_buffer.v8[5];
357 *buf++ ^= c->keystream_buffer.v8[6];
358 *buf++ ^= c->keystream_buffer.v8[7];
359 *buf++ ^= c->keystream_buffer.v8[8];
360 *buf++ ^= c->keystream_buffer.v8[9];
361 *buf++ ^= c->keystream_buffer.v8[10];
362 *buf++ ^= c->keystream_buffer.v8[11];
363 *buf++ ^= c->keystream_buffer.v8[12];
364 *buf++ ^= c->keystream_buffer.v8[13];
365 *buf++ ^= c->keystream_buffer.v8[14];
366 *buf++ ^= c->keystream_buffer.v8[15];
367 } else {
368 b = (uint32_t *)buf;
369 *b++ ^= c->keystream_buffer.v32[0];
370 *b++ ^= c->keystream_buffer.v32[1];
371 *b++ ^= c->keystream_buffer.v32[2];
372 *b++ ^= c->keystream_buffer.v32[3];
373 buf = (uint8_t *)b;
374 }
375 #endif /* #if ALIGN_32 */
376 }
377
378 /* if there is a tail end of the data, process it */
379 if ((bytes_to_encr & 0xf) != 0) {
380 /* fill buffer with new keystream */
381 srtp_aes_icm_advance(c);
382
383 for (i = 0; i < (bytes_to_encr & 0xf); i++) {
384 *buf++ ^= c->keystream_buffer.v8[i];
385 }
386
387 /* reset the keystream buffer size to right value */
388 c->bytes_in_buffer = sizeof(v128_t) - i;
389 } else {
390 /* no tail, so just reset the keystream buffer size to zero */
391 c->bytes_in_buffer = 0;
392 }
393
394 return srtp_err_status_ok;
395 }
396
397 static const char srtp_aes_icm_128_description[] =
398 "AES-128 integer counter mode";
399 static const char srtp_aes_icm_256_description[] =
400 "AES-256 integer counter mode";
401
402 /* clang-format off */
403 static const uint8_t srtp_aes_icm_128_test_case_0_key[SRTP_AES_ICM_128_KEY_LEN_WSALT] = {
404 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
405 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
406 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
407 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
408 };
409 /* clang-format on */
410
411 /* clang-format off */
412 static uint8_t srtp_aes_icm_128_test_case_0_nonce[16] = {
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
415 };
416 /* clang-format on */
417
418 /* clang-format off */
419 static const uint8_t srtp_aes_icm_128_test_case_0_plaintext[32] = {
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 };
425 /* clang-format on */
426
427 /* clang-format off */
428 static const uint8_t srtp_aes_icm_128_test_case_0_ciphertext[32] = {
429 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
430 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
431 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
432 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
433 };
434 /* clang-format on */
435
436 static const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0 = {
437 SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */
438 srtp_aes_icm_128_test_case_0_key, /* key */
439 srtp_aes_icm_128_test_case_0_nonce, /* packet index */
440 32, /* octets in plaintext */
441 srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */
442 32, /* octets in ciphertext */
443 srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */
444 0, /* */
445 NULL, /* */
446 0, /* */
447 NULL /* pointer to next testcase */
448 };
449
450 /* clang-format off */
451 static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_WSALT] = {
452 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70,
453 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92,
454 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
455 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
456 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
457 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
458 };
459 /* clang-format on */
460
461 /* clang-format off */
462 static uint8_t srtp_aes_icm_256_test_case_0_nonce[16] = {
463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
465 };
466 /* clang-format on */
467
468 /* clang-format off */
469 static const uint8_t srtp_aes_icm_256_test_case_0_plaintext[32] = {
470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 };
475 /* clang-format on */
476
477 /* clang-format off */
478 static const uint8_t srtp_aes_icm_256_test_case_0_ciphertext[32] = {
479 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25,
480 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4,
481 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6,
482 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac
483 };
484 /* clang-format on */
485
486 static const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = {
487 SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */
488 srtp_aes_icm_256_test_case_0_key, /* key */
489 srtp_aes_icm_256_test_case_0_nonce, /* packet index */
490 32, /* octets in plaintext */
491 srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */
492 32, /* octets in ciphertext */
493 srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */
494 0, /* */
495 NULL, /* */
496 0, /* */
497 NULL, /* pointer to next testcase */
498 };
499
500 /*
501 * note: the encrypt function is identical to the decrypt function
502 */
503
504 const srtp_cipher_type_t srtp_aes_icm_128 = {
505 srtp_aes_icm_alloc, /* */
506 srtp_aes_icm_dealloc, /* */
507 srtp_aes_icm_context_init, /* */
508 0, /* set_aad */
509 srtp_aes_icm_encrypt, /* */
510 srtp_aes_icm_encrypt, /* */
511 srtp_aes_icm_set_iv, /* */
512 0, /* get_tag */
513 srtp_aes_icm_128_description, /* */
514 &srtp_aes_icm_128_test_case_0, /* */
515 SRTP_AES_ICM_128 /* */
516 };
517
518 const srtp_cipher_type_t srtp_aes_icm_256 = {
519 srtp_aes_icm_alloc, /* */
520 srtp_aes_icm_dealloc, /* */
521 srtp_aes_icm_context_init, /* */
522 0, /* set_aad */
523 srtp_aes_icm_encrypt, /* */
524 srtp_aes_icm_encrypt, /* */
525 srtp_aes_icm_set_iv, /* */
526 0, /* get_tag */
527 srtp_aes_icm_256_description, /* */
528 &srtp_aes_icm_256_test_case_0, /* */
529 SRTP_AES_ICM_256 /* */
530 };
531