4
* AES Integer Counter Mode
12
* Copyright (c) 2001-2006, Cisco Systems, Inc.
13
* All rights reserved.
15
* Redistribution and use in source and binary forms, with or without
16
* modification, are permitted provided that the following conditions
19
* Redistributions of source code must retain the above copyright
20
* notice, this list of conditions and the following disclaimer.
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.
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.
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.
53
debug_module_t mod_aes_icm = {
54
0, /* debugging is off by default */
55
"aes icm" /* printable module name */
59
* integer counter mode works as follows:
63
* +------+------+------+------+------+------+------+------+
64
* | nonce | pakcet index | ctr |---+
65
* +------+------+------+------+------+------+------+------+ |
67
* +------+------+------+------+------+------+------+------+ v
68
* | salt |000000|->(+)
69
* +------+------+------+------+------+------+------+------+ |
75
* +------+------+------+------+------+------+------+------+ |
76
* | keystream block |<--+
77
* +------+------+------+------+------+------+------+------+
79
* All fields are big-endian
81
* ctr is the block counter, which increments from zero for
82
* each packet (16 bits wide)
84
* packet index is distinct for each packet (48 bits wide)
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
93
aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) {
94
extern cipher_type_t aes_icm;
98
debug_print(mod_aes_icm,
99
"allocating cipher with key length %d", key_len);
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 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.
109
if (!forIsmacryp && key_len != 30)
110
return err_status_bad_param;
112
/* allocate memory a cipher of type aes_icm */
113
tmp = (sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
114
pointer = (uint8_t*)crypto_alloc(tmp);
116
return err_status_alloc_fail;
119
*c = (cipher_t *)pointer;
120
(*c)->type = &aes_icm;
121
(*c)->state = pointer + sizeof(cipher_t);
123
/* increment ref_count */
127
(*c)->key_len = key_len;
129
return err_status_ok;
132
err_status_t aes_icm_alloc(cipher_t **c, int key_len, int forIsmacryp) {
133
return aes_icm_alloc_ismacryp(c, key_len, 0);
137
aes_icm_dealloc(cipher_t *c) {
138
extern cipher_type_t aes_icm;
140
/* zeroize entire state*/
141
octet_string_set_to_zero((uint8_t *)c,
142
sizeof(aes_icm_ctx_t) + sizeof(cipher_t));
147
/* decrement ref_count */
150
return err_status_ok;
155
* aes_icm_context_init(...) initializes the aes_icm_context
156
* using the value in key[].
158
* the key is the secret key
160
* the salt is unpredictable (but not necessarily secret) data which
161
* randomizes the starting point in the keystream
165
aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key) {
168
/* set counter and initial values to 'offset' value */
169
/* FIX!!! this assumes the salt is at key + 16, and thus that the */
170
/* FIX!!! cipher key length is 16! Also note this copies past the
171
end of the 'key' array by 2 bytes! */
172
v128_copy_octet_string(&c->counter, key + 16);
173
v128_copy_octet_string(&c->offset, key + 16);
175
/* force last two octets of the offset to zero (for srtp compatibility) */
176
c->offset.v8[14] = c->offset.v8[15] = 0;
177
c->counter.v8[14] = c->counter.v8[15] = 0;
179
/* set tmp_key (for alignment) */
180
v128_copy_octet_string(&tmp_key, key);
182
debug_print(mod_aes_icm,
183
"key: %s", v128_hex_string(&tmp_key));
184
debug_print(mod_aes_icm,
185
"offset: %s", v128_hex_string(&c->offset));
188
aes_expand_encryption_key(&tmp_key, c->expanded_key);
190
/* indicate that the keystream_buffer is empty */
191
c->bytes_in_buffer = 0;
193
return err_status_ok;
197
* aes_icm_set_octet(c, i) sets the counter of the context which it is
198
* passed so that the next octet of keystream that will be generated
203
aes_icm_set_octet(aes_icm_ctx_t *c,
204
uint64_t octet_num) {
207
int tail_num = low32(octet_num) & 0x0f;
208
/* 64-bit right-shift 4 */
209
uint64_t block_num = make64(high32(octet_num) >> 4,
210
((high32(octet_num) & 0x0f)<<(32-4)) |
211
(low32(octet_num) >> 4));
213
int tail_num = octet_num % 16;
214
uint64_t block_num = octet_num / 16;
218
/* set counter value */
219
/* FIX - There's no way this is correct */
220
c->counter.v64[0] = c->offset.v64[0];
222
c->counter.v64[0] = make64(high32(c->offset.v64[0]) ^ high32(block_num),
223
low32(c->offset.v64[0]) ^ low32(block_num));
225
c->counter.v64[0] = c->offset.v64[0] ^ block_num;
228
debug_print(mod_aes_icm,
229
"set_octet: %s", v128_hex_string(&c->counter));
231
/* fill keystream buffer, if needed */
233
v128_copy(&c->keystream_buffer, &c->counter);
234
aes_encrypt(&c->keystream_buffer, c->expanded_key);
235
c->bytes_in_buffer = sizeof(v128_t);
237
debug_print(mod_aes_icm, "counter: %s",
238
v128_hex_string(&c->counter));
239
debug_print(mod_aes_icm, "ciphertext: %s",
240
v128_hex_string(&c->keystream_buffer));
242
/* indicate number of bytes in keystream_buffer */
243
c->bytes_in_buffer = sizeof(v128_t) - tail_num;
247
/* indicate that keystream_buffer is empty */
248
c->bytes_in_buffer = 0;
251
return err_status_ok;
255
* aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with
260
aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) {
261
v128_t *nonce = (v128_t *) iv;
263
debug_print(mod_aes_icm,
264
"setting iv: %s", v128_hex_string(nonce));
266
v128_xor(&c->counter, &c->offset, nonce);
268
debug_print(mod_aes_icm,
269
"set_counter: %s", v128_hex_string(&c->counter));
271
/* indicate that the keystream_buffer is empty */
272
c->bytes_in_buffer = 0;
274
return err_status_ok;
280
* aes_icm_advance(...) refills the keystream_buffer and
281
* advances the block index of the sicm_context forward by one
283
* this is an internal, hopefully inlined function
287
aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) {
288
/* fill buffer with new keystream */
289
v128_copy(&c->keystream_buffer, &c->counter);
290
aes_encrypt(&c->keystream_buffer, c->expanded_key);
291
c->bytes_in_buffer = sizeof(v128_t);
293
debug_print(mod_aes_icm, "counter: %s",
294
v128_hex_string(&c->counter));
295
debug_print(mod_aes_icm, "ciphertext: %s",
296
v128_hex_string(&c->keystream_buffer));
298
/* clock counter forward */
302
//alex's clock counter forward
303
temp = ntohl(c->counter.v32[3]);
304
c->counter.v32[3] = htonl(++temp);
306
if (!++(c->counter.v8[15]))
307
++(c->counter.v8[14]);
311
inline void aes_icm_advance(aes_icm_ctx_t *c) {
312
aes_icm_advance_ismacryp(c, 0);
317
* icm_encrypt deals with the following cases:
319
* bytes_to_encr < bytes_in_buffer
320
* - add keystream into data
322
* bytes_to_encr > bytes_in_buffer
323
* - add keystream into data until keystream_buffer is depleted
324
* - loop over blocks, filling keystream_buffer and then
325
* adding keystream into data
326
* - fill buffer then add in remaining (< 16) bytes of keystream
330
aes_icm_encrypt_ismacryp(aes_icm_ctx_t *c,
331
unsigned char *buf, unsigned int *enc_len,
333
unsigned int bytes_to_encr = *enc_len;
337
/* check that there's enough segment left but not for ismacryp*/
338
if (!forIsmacryp && (bytes_to_encr + htons(c->counter.v16[7])) > 0xffff)
339
return err_status_terminus;
341
debug_print(mod_aes_icm, "block index: %d",
342
htons(c->counter.v16[7]));
343
if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) {
345
/* deal with odd case of small bytes_to_encr */
346
for (i = (sizeof(v128_t) - c->bytes_in_buffer);
347
i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++)
349
*buf++ ^= c->keystream_buffer.v8[i];
352
c->bytes_in_buffer -= bytes_to_encr;
354
/* return now to avoid the main loop */
355
return err_status_ok;
359
/* encrypt bytes until the remaining data is 16-byte aligned */
360
for (i=(sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++)
361
*buf++ ^= c->keystream_buffer.v8[i];
363
bytes_to_encr -= c->bytes_in_buffer;
364
c->bytes_in_buffer = 0;
368
/* now loop over entire 16-byte blocks of keystream */
369
for (i=0; i < (bytes_to_encr/sizeof(v128_t)); i++) {
371
/* fill buffer with new keystream */
372
aes_icm_advance_ismacryp(c, forIsmacryp);
375
* add keystream into the data buffer (this would be a lot faster
376
* if we could assume 32-bit alignment!)
381
*b++ ^= c->keystream_buffer.v32[0];
382
*b++ ^= c->keystream_buffer.v32[1];
383
*b++ ^= c->keystream_buffer.v32[2];
384
*b++ ^= c->keystream_buffer.v32[3];
387
if ((((unsigned long) buf) & 0x03) != 0) {
388
*buf++ ^= c->keystream_buffer.v8[0];
389
*buf++ ^= c->keystream_buffer.v8[1];
390
*buf++ ^= c->keystream_buffer.v8[2];
391
*buf++ ^= c->keystream_buffer.v8[3];
392
*buf++ ^= c->keystream_buffer.v8[4];
393
*buf++ ^= c->keystream_buffer.v8[5];
394
*buf++ ^= c->keystream_buffer.v8[6];
395
*buf++ ^= c->keystream_buffer.v8[7];
396
*buf++ ^= c->keystream_buffer.v8[8];
397
*buf++ ^= c->keystream_buffer.v8[9];
398
*buf++ ^= c->keystream_buffer.v8[10];
399
*buf++ ^= c->keystream_buffer.v8[11];
400
*buf++ ^= c->keystream_buffer.v8[12];
401
*buf++ ^= c->keystream_buffer.v8[13];
402
*buf++ ^= c->keystream_buffer.v8[14];
403
*buf++ ^= c->keystream_buffer.v8[15];
406
*b++ ^= c->keystream_buffer.v32[0];
407
*b++ ^= c->keystream_buffer.v32[1];
408
*b++ ^= c->keystream_buffer.v32[2];
409
*b++ ^= c->keystream_buffer.v32[3];
412
#endif /* #if ALIGN_32 */
416
/* if there is a tail end of the data, process it */
417
if ((bytes_to_encr & 0xf) != 0) {
419
/* fill buffer with new keystream */
420
aes_icm_advance_ismacryp(c, forIsmacryp);
422
for (i=0; i < (bytes_to_encr & 0xf); i++)
423
*buf++ ^= c->keystream_buffer.v8[i];
425
/* reset the keystream buffer size to right value */
426
c->bytes_in_buffer = sizeof(v128_t) - i;
429
/* no tail, so just reset the keystream buffer size to zero */
430
c->bytes_in_buffer = 0;
434
return err_status_ok;
438
aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) {
439
return aes_icm_encrypt_ismacryp(c, buf, enc_len, 0);
443
aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) {
444
unsigned int len = num_octets_to_output;
446
/* zeroize the buffer */
447
octet_string_set_to_zero(buffer, num_octets_to_output);
449
/* exor keystream into buffer */
450
return aes_icm_encrypt(c, buffer, &len);
455
aes_icm_description[] = "aes integer counter mode";
457
uint8_t aes_icm_test_case_0_key[30] = {
458
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
459
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
460
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
461
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd
464
uint8_t aes_icm_test_case_0_nonce[16] = {
465
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
469
uint8_t aes_icm_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,
476
uint8_t aes_icm_test_case_0_ciphertext[32] = {
477
0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80,
478
0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4,
479
0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7,
480
0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab
483
cipher_test_case_t aes_icm_test_case_0 = {
484
30, /* octets in key */
485
aes_icm_test_case_0_key, /* key */
486
aes_icm_test_case_0_nonce, /* packet index */
487
32, /* octets in plaintext */
488
aes_icm_test_case_0_plaintext, /* plaintext */
489
32, /* octets in ciphertext */
490
aes_icm_test_case_0_ciphertext, /* ciphertext */
491
NULL /* pointer to next testcase */
496
* note: the encrypt function is identical to the decrypt function
499
cipher_type_t aes_icm = {
500
(cipher_alloc_func_t) aes_icm_alloc,
501
(cipher_dealloc_func_t) aes_icm_dealloc,
502
(cipher_init_func_t) aes_icm_context_init,
503
(cipher_encrypt_func_t) aes_icm_encrypt,
504
(cipher_decrypt_func_t) aes_icm_encrypt,
505
(cipher_set_iv_func_t) aes_icm_set_iv,
506
(char *) aes_icm_description,
507
(int) 0, /* instance count */
508
(cipher_test_case_t *) &aes_icm_test_case_0,
509
(debug_module_t *) &mod_aes_icm