2
* AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
3
* One-Key CBC MAC (OMAC1) hash with AES-128
4
* AES-128 CTR mode encryption
5
* AES-128 EAX mode encryption/decryption
7
* Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
13
* Alternatively, this software may be distributed under the terms of BSD
16
* See README and COPYING for more details.
27
#include <openssl/aes.h>
29
#else /* EAP_TLS_FUNCS */
36
typedef struct aes_key_st AES_KEY;
38
#define AES_set_encrypt_key(userKey, bits, key) \
39
rijndaelKeySetupEnc((key)->rk, (userKey))
40
#define AES_set_decrypt_key(userKey, bits, key) \
41
rijndaelKeySetupDec((key)->rk, (userKey))
42
#define AES_encrypt(in, out, key) \
43
rijndaelEncrypt((key)->rk, in, out)
44
#define AES_decrypt(in, out, key) \
45
rijndaelDecrypt((key)->rk, in, out)
47
#endif /* EAP_TLS_FUNCS */
51
* @kek: key encryption key (KEK)
52
* @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
53
* @plain: plaintext key to be wrapped, n * 64 bit
54
* @cipher: wrapped key, (n + 1) * 64 bit
56
void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher)
65
/* 1) Initialize variables. */
67
memcpy(r, plain, 8 * n);
69
AES_set_encrypt_key(kek, 128, &key);
71
/* 2) Calculate intermediate values.
74
* B = AES(K, A | R[i])
75
* A = MSB(64, B) ^ t where t = (n*j)+i
78
for (j = 0; j <= 5; j++) {
80
for (i = 1; i <= n; i++) {
83
AES_encrypt(b, b, &key);
91
/* 3) Output the results.
93
* These are already in @cipher due to the location of temporary
100
* @kek: key encryption key (KEK)
101
* @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
102
* @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit
103
* @plain: plaintext key, n * 64 bit
105
int aes_unwrap(u8 *kek, int n, u8 *cipher, u8 *plain)
111
/* 1) Initialize variables. */
112
memcpy(a, cipher, 8);
114
memcpy(r, cipher + 8, 8 * n);
116
AES_set_decrypt_key(kek, 128, &key);
118
/* 2) Compute intermediate values.
121
* B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
125
for (j = 5; j >= 0; j--) {
126
r = plain + (n - 1) * 8;
127
for (i = n; i >= 1; i--) {
132
AES_decrypt(b, b, &key);
139
/* 3) Output results.
141
* These are already in @plain due to the location of temporary
142
* variables. Just verify that the IV matches with the expected value.
144
for (i = 0; i < 8; i++) {
153
#define BLOCK_SIZE 16
155
static void gf_mulx(u8 *pad)
159
carry = pad[0] & 0x80;
160
for (i = 0; i < BLOCK_SIZE - 1; i++)
161
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
162
pad[BLOCK_SIZE - 1] <<= 1;
164
pad[BLOCK_SIZE - 1] ^= 0x87;
168
void omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
171
u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
172
const u8 *pos = data;
174
size_t left = data_len;
176
AES_set_encrypt_key(key, 128, &akey);
177
memset(cbc, 0, BLOCK_SIZE);
179
while (left >= BLOCK_SIZE) {
180
for (i = 0; i < BLOCK_SIZE; i++)
182
if (left > BLOCK_SIZE)
183
AES_encrypt(cbc, cbc, &akey);
187
memset(pad, 0, BLOCK_SIZE);
188
AES_encrypt(pad, pad, &akey);
191
if (left || data_len == 0) {
192
for (i = 0; i < left; i++)
198
for (i = 0; i < BLOCK_SIZE; i++)
200
AES_encrypt(pad, mac, &akey);
204
void aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
207
AES_set_encrypt_key(key, 128, &akey);
208
AES_encrypt(in, out, &akey);
212
void aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
213
u8 *data, size_t data_len)
216
size_t len, left = data_len;
219
u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE];
221
AES_set_encrypt_key(key, 128, &akey);
222
memcpy(counter, nonce, BLOCK_SIZE);
225
AES_encrypt(counter, buf, &akey);
227
len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE;
228
for (i = 0; i < len; i++)
233
for (i = BLOCK_SIZE - 1; i >= 0; i--) {
242
int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
243
const u8 *hdr, size_t hdr_len,
244
u8 *data, size_t data_len, u8 *tag)
248
u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
251
if (nonce_len > data_len)
255
if (hdr_len > buf_len)
259
buf = malloc(buf_len);
266
memcpy(buf + 16, nonce, nonce_len);
267
omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
270
memcpy(buf + 16, hdr, hdr_len);
271
omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
273
aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
275
memcpy(buf + 16, data, data_len);
276
omac1_aes_128(key, buf, 16 + data_len, data_mac);
280
for (i = 0; i < BLOCK_SIZE; i++)
281
tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
287
int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
288
const u8 *hdr, size_t hdr_len,
289
u8 *data, size_t data_len, const u8 *tag)
293
u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
296
if (nonce_len > data_len)
300
if (hdr_len > buf_len)
304
buf = malloc(buf_len);
311
memcpy(buf + 16, nonce, nonce_len);
312
omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac);
315
memcpy(buf + 16, hdr, hdr_len);
316
omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac);
319
memcpy(buf + 16, data, data_len);
320
omac1_aes_128(key, buf, 16 + data_len, data_mac);
324
for (i = 0; i < BLOCK_SIZE; i++) {
325
if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
329
aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
335
void aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
343
AES_set_encrypt_key(key, 128, &akey);
344
memcpy(cbc, iv, BLOCK_SIZE);
346
blocks = data_len / BLOCK_SIZE;
347
for (i = 0; i < blocks; i++) {
348
for (j = 0; j < BLOCK_SIZE; j++)
350
AES_encrypt(cbc, cbc, &akey);
351
memcpy(pos, cbc, BLOCK_SIZE);
357
void aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
361
u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE];
365
AES_set_decrypt_key(key, 128, &akey);
366
memcpy(cbc, iv, BLOCK_SIZE);
368
blocks = data_len / BLOCK_SIZE;
369
for (i = 0; i < blocks; i++) {
370
memcpy(tmp, pos, BLOCK_SIZE);
371
AES_decrypt(pos, pos, &akey);
372
for (j = 0; j < BLOCK_SIZE; j++)
374
memcpy(cbc, tmp, BLOCK_SIZE);
383
#define rdtscll(val) \
384
__asm__ __volatile__("rdtsc" : "=A" (val))
386
static void test_aes_perf(void)
388
const int num_iters = 10;
390
unsigned int start, end;
392
u8 key[16], pt[16], ct[16];
394
printf("keySetupEnc:");
395
for (i = 0; i < num_iters; i++) {
397
AES_set_encrypt_key(key, 128, &akey);
399
printf(" %d", end - start);
404
for (i = 0; i < num_iters; i++) {
406
AES_encrypt(pt, ct, &akey);
408
printf(" %d", end - start);
412
#endif /* __i386__ */
415
static int test_eax(void)
417
u8 msg[] = { 0xF7, 0xFB };
418
u8 key[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B,
419
0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 };
420
u8 nonce[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84,
421
0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD };
422
u8 hdr[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA };
423
u8 cipher[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D,
424
0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79,
426
u8 data[sizeof(msg)], tag[BLOCK_SIZE];
428
memcpy(data, msg, sizeof(msg));
429
if (aes_128_eax_encrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
430
data, sizeof(data), tag)) {
431
printf("AES-128 EAX mode encryption failed\n");
434
if (memcmp(data, cipher, sizeof(data)) != 0) {
435
printf("AES-128 EAX mode encryption returned invalid cipher "
439
if (memcmp(tag, cipher + sizeof(data), BLOCK_SIZE) != 0) {
440
printf("AES-128 EAX mode encryption returned invalid tag\n");
444
if (aes_128_eax_decrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
445
data, sizeof(data), tag)) {
446
printf("AES-128 EAX mode decryption failed\n");
449
if (memcmp(data, msg, sizeof(data)) != 0) {
450
printf("AES-128 EAX mode decryption returned invalid plain "
459
static int test_cbc(void)
461
struct cbc_test_vector {
469
{ 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
470
0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
471
{ 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
472
0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
474
{ 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
475
0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
479
{ 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
480
0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
481
{ 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
482
0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
483
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
484
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
485
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
486
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
487
{ 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
488
0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
489
0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
490
0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
497
for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) {
498
struct cbc_test_vector *tv = &vectors[i];
499
buf = malloc(tv->len);
504
memcpy(buf, tv->plain, tv->len);
505
aes_128_cbc_encrypt(tv->key, tv->iv, buf, tv->len);
506
if (memcmp(buf, tv->cipher, tv->len) != 0) {
507
printf("AES-CBC encrypt %d failed\n", i);
510
memcpy(buf, tv->cipher, tv->len);
511
aes_128_cbc_decrypt(tv->key, tv->iv, buf, tv->len);
512
if (memcmp(buf, tv->plain, tv->len) != 0) {
513
printf("AES-CBC decrypt %d failed\n", i);
523
/* OMAC1 AES-128 test vectors from
524
* http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf
527
struct omac1_test_vector {
534
static struct omac1_test_vector test_vectors[] =
537
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
538
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
541
{ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
542
0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }
545
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
546
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
547
{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
548
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
550
{ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
551
0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }
554
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
555
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
556
{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
557
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
558
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
559
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
560
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 },
562
{ 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
563
0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 }
566
{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
567
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
568
{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
569
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
570
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
571
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
572
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
573
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
574
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
575
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
577
{ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
578
0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe }
583
int main(int argc, char *argv[])
586
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
587
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
590
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
591
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
594
0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
595
0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
596
0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
600
struct omac1_test_vector *tv;
602
aes_wrap(kek, 2, plain, result);
603
if (memcmp(result, crypt, 24) != 0) {
604
printf("AES-WRAP-128-128 failed\n");
607
if (aes_unwrap(kek, 2, crypt, result)) {
608
printf("AES-UNWRAP-128-128 reported failure\n");
611
if (memcmp(result, plain, 16) != 0) {
613
printf("AES-UNWRAP-128-128 failed\n");
615
for (i = 0; i < 16; i++)
616
printf(" %02x", result[i]);
622
#endif /* __i386__ */
624
for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) {
625
tv = &test_vectors[i];
626
omac1_aes_128(tv->k, tv->msg, tv->msg_len, result);
627
if (memcmp(result, tv->tag, 16) != 0) {
628
printf("OMAC1-AES-128 test vector %d failed\n", i);
642
#endif /* TEST_MAIN */