4 * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
5 * - One-Key CBC MAC (OMAC1) hash with AES-128
6 * - AES-128 CTR mode encryption
7 * - AES-128 EAX mode encryption/decryption
10 * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
16 * Alternatively, this software may be distributed under the terms of BSD
19 * See README and COPYING for more details.
31 #endif /* EAP_TLS_FUNCS */
35 * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
36 * @kek: Key encryption key (KEK)
37 * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
38 * @plain: Plaintext key to be wrapped, n * 64 bit
39 * @cipher: Wrapped key, (n + 1) * 64 bit
40 * Returns: 0 on success, -1 on failure
42 int aes_wrap(const u8
*kek
, int n
, const u8
*plain
, u8
*cipher
)
51 /* 1) Initialize variables. */
53 memcpy(r
, plain
, 8 * n
);
55 ctx
= aes_encrypt_init(kek
, 16);
59 /* 2) Calculate intermediate values.
62 * B = AES(K, A | R[i])
63 * A = MSB(64, B) ^ t where t = (n*j)+i
66 for (j
= 0; j
<= 5; j
++) {
68 for (i
= 1; i
<= n
; i
++) {
71 aes_encrypt(ctx
, b
, b
);
78 aes_encrypt_deinit(ctx
);
80 /* 3) Output the results.
82 * These are already in @cipher due to the location of temporary
91 * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
92 * @kek: Key encryption key (KEK)
93 * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
94 * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bit
95 * @plain: Plaintext key, n * 64 bit
96 * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
98 int aes_unwrap(const u8
*kek
, int n
, const u8
*cipher
, u8
*plain
)
104 /* 1) Initialize variables. */
105 memcpy(a
, cipher
, 8);
107 memcpy(r
, cipher
+ 8, 8 * n
);
109 ctx
= aes_decrypt_init(kek
, 16);
113 /* 2) Compute intermediate values.
116 * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
120 for (j
= 5; j
>= 0; j
--) {
121 r
= plain
+ (n
- 1) * 8;
122 for (i
= n
; i
>= 1; i
--) {
127 aes_decrypt(ctx
, b
, b
);
133 aes_decrypt_deinit(ctx
);
135 /* 3) Output results.
137 * These are already in @plain due to the location of temporary
138 * variables. Just verify that the IV matches with the expected value.
140 for (i
= 0; i
< 8; i
++) {
149 #define BLOCK_SIZE 16
151 static void gf_mulx(u8
*pad
)
155 carry
= pad
[0] & 0x80;
156 for (i
= 0; i
< BLOCK_SIZE
- 1; i
++)
157 pad
[i
] = (pad
[i
] << 1) | (pad
[i
+ 1] >> 7);
158 pad
[BLOCK_SIZE
- 1] <<= 1;
160 pad
[BLOCK_SIZE
- 1] ^= 0x87;
165 * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128
166 * @key: Key for the hash operation
167 * @data: Data buffer for which a MAC is determined
168 * @data: Length of data buffer in bytes
169 * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
170 * Returns: 0 on success, -1 on failure
172 int omac1_aes_128(const u8
*key
, const u8
*data
, size_t data_len
, u8
*mac
)
175 u8 cbc
[BLOCK_SIZE
], pad
[BLOCK_SIZE
];
176 const u8
*pos
= data
;
178 size_t left
= data_len
;
180 ctx
= aes_encrypt_init(key
, 16);
183 memset(cbc
, 0, BLOCK_SIZE
);
185 while (left
>= BLOCK_SIZE
) {
186 for (i
= 0; i
< BLOCK_SIZE
; i
++)
188 if (left
> BLOCK_SIZE
)
189 aes_encrypt(ctx
, cbc
, cbc
);
193 memset(pad
, 0, BLOCK_SIZE
);
194 aes_encrypt(ctx
, pad
, pad
);
197 if (left
|| data_len
== 0) {
198 for (i
= 0; i
< left
; i
++)
204 for (i
= 0; i
< BLOCK_SIZE
; i
++)
206 aes_encrypt(ctx
, pad
, mac
);
207 aes_encrypt_deinit(ctx
);
213 * aes_128_encrypt_block - Perform one AES 128-bit block operation
215 * @in: Input data (16 bytes)
216 * @out: Output of the AES block operation (16 bytes)
217 * Returns: 0 on success, -1 on failure
219 int aes_128_encrypt_block(const u8
*key
, const u8
*in
, u8
*out
)
222 ctx
= aes_encrypt_init(key
, 16);
225 aes_encrypt(ctx
, in
, out
);
226 aes_encrypt_deinit(ctx
);
232 * aes_128_ctr_encrypt - AES-128 CTR mode encryption
233 * @key: Key for encryption (16 bytes)
234 * @nonce: Nonce for counter mode (16 bytes)
235 * @data: Data to encrypt in-place
236 * @data_len: Length of data in bytes
237 * Returns: 0 on success, -1 on failure
239 int aes_128_ctr_encrypt(const u8
*key
, const u8
*nonce
,
240 u8
*data
, size_t data_len
)
243 size_t len
, left
= data_len
;
246 u8 counter
[BLOCK_SIZE
], buf
[BLOCK_SIZE
];
248 ctx
= aes_encrypt_init(key
, 16);
251 memcpy(counter
, nonce
, BLOCK_SIZE
);
254 aes_encrypt(ctx
, counter
, buf
);
256 len
= (left
< BLOCK_SIZE
) ? left
: BLOCK_SIZE
;
257 for (i
= 0; i
< len
; i
++)
262 for (i
= BLOCK_SIZE
- 1; i
>= 0; i
--) {
268 aes_encrypt_deinit(ctx
);
274 * aes_128_eax_encrypt - AES-128 EAX mode encryption
275 * @key: Key for encryption (16 bytes)
276 * @nonce: Nonce for counter mode
277 * @nonce_len: Nonce length in bytes
278 * @hdr: Header data to be authenticity protected
279 * @hdr_len: Length of the header data bytes
280 * @data: Data to encrypt in-place
281 * @data_len: Length of data in bytes
282 * @tag: 16-byte tag value
283 * Returns: 0 on success, -1 on failure
285 int aes_128_eax_encrypt(const u8
*key
, const u8
*nonce
, size_t nonce_len
,
286 const u8
*hdr
, size_t hdr_len
,
287 u8
*data
, size_t data_len
, u8
*tag
)
291 u8 nonce_mac
[BLOCK_SIZE
], hdr_mac
[BLOCK_SIZE
], data_mac
[BLOCK_SIZE
];
294 if (nonce_len
> data_len
)
298 if (hdr_len
> buf_len
)
302 buf
= malloc(buf_len
);
309 memcpy(buf
+ 16, nonce
, nonce_len
);
310 omac1_aes_128(key
, buf
, 16 + nonce_len
, nonce_mac
);
313 memcpy(buf
+ 16, hdr
, hdr_len
);
314 omac1_aes_128(key
, buf
, 16 + hdr_len
, hdr_mac
);
316 aes_128_ctr_encrypt(key
, nonce_mac
, data
, data_len
);
318 memcpy(buf
+ 16, data
, data_len
);
319 omac1_aes_128(key
, buf
, 16 + data_len
, data_mac
);
323 for (i
= 0; i
< BLOCK_SIZE
; i
++)
324 tag
[i
] = nonce_mac
[i
] ^ data_mac
[i
] ^ hdr_mac
[i
];
331 * aes_128_eax_decrypt - AES-128 EAX mode decryption
332 * @key: Key for decryption (16 bytes)
333 * @nonce: Nonce for counter mode
334 * @nonce_len: Nonce length in bytes
335 * @hdr: Header data to be authenticity protected
336 * @hdr_len: Length of the header data bytes
337 * @data: Data to encrypt in-place
338 * @data_len: Length of data in bytes
339 * @tag: 16-byte tag value
340 * Returns: 0 on success, -1 on failure, -2 if tag does not match
342 int aes_128_eax_decrypt(const u8
*key
, const u8
*nonce
, size_t nonce_len
,
343 const u8
*hdr
, size_t hdr_len
,
344 u8
*data
, size_t data_len
, const u8
*tag
)
348 u8 nonce_mac
[BLOCK_SIZE
], hdr_mac
[BLOCK_SIZE
], data_mac
[BLOCK_SIZE
];
351 if (nonce_len
> data_len
)
355 if (hdr_len
> buf_len
)
359 buf
= malloc(buf_len
);
366 memcpy(buf
+ 16, nonce
, nonce_len
);
367 omac1_aes_128(key
, buf
, 16 + nonce_len
, nonce_mac
);
370 memcpy(buf
+ 16, hdr
, hdr_len
);
371 omac1_aes_128(key
, buf
, 16 + hdr_len
, hdr_mac
);
374 memcpy(buf
+ 16, data
, data_len
);
375 omac1_aes_128(key
, buf
, 16 + data_len
, data_mac
);
379 for (i
= 0; i
< BLOCK_SIZE
; i
++) {
380 if (tag
[i
] != (nonce_mac
[i
] ^ data_mac
[i
] ^ hdr_mac
[i
]))
384 aes_128_ctr_encrypt(key
, nonce_mac
, data
, data_len
);
391 * aes_128_cbc_encrypt - AES-128 CBC encryption
392 * @key: Encryption key
393 * @iv: Encryption IV for CBC mode (16 bytes)
394 * @data: Data to encrypt in-place
395 * @data_len: Length of data in bytes (must be divisible by 16)
396 * Returns: 0 on success, -1 on failure
398 int aes_128_cbc_encrypt(const u8
*key
, const u8
*iv
, u8
*data
, size_t data_len
)
405 ctx
= aes_encrypt_init(key
, 16);
408 memcpy(cbc
, iv
, BLOCK_SIZE
);
410 blocks
= data_len
/ BLOCK_SIZE
;
411 for (i
= 0; i
< blocks
; i
++) {
412 for (j
= 0; j
< BLOCK_SIZE
; j
++)
414 aes_encrypt(ctx
, cbc
, cbc
);
415 memcpy(pos
, cbc
, BLOCK_SIZE
);
418 aes_encrypt_deinit(ctx
);
424 * aes_128_cbc_decrypt - AES-128 CBC decryption
425 * @key: Decryption key
426 * @iv: Decryption IV for CBC mode (16 bytes)
427 * @data: Data to decrypt in-place
428 * @data_len: Length of data in bytes (must be divisible by 16)
429 * Returns: 0 on success, -1 on failure
431 int aes_128_cbc_decrypt(const u8
*key
, const u8
*iv
, u8
*data
, size_t data_len
)
434 u8 cbc
[BLOCK_SIZE
], tmp
[BLOCK_SIZE
];
438 ctx
= aes_decrypt_init(key
, 16);
441 memcpy(cbc
, iv
, BLOCK_SIZE
);
443 blocks
= data_len
/ BLOCK_SIZE
;
444 for (i
= 0; i
< blocks
; i
++) {
445 memcpy(tmp
, pos
, BLOCK_SIZE
);
446 aes_decrypt(ctx
, pos
, pos
);
447 for (j
= 0; j
< BLOCK_SIZE
; j
++)
449 memcpy(cbc
, tmp
, BLOCK_SIZE
);
452 aes_decrypt_deinit(ctx
);
460 #define rdtscll(val) \
461 __asm__ __volatile__("rdtsc" : "=A" (val))
463 static void test_aes_perf(void)
465 const int num_iters
= 10;
467 unsigned int start
, end
;
468 u8 key
[16], pt
[16], ct
[16];
471 printf("keySetupEnc:");
472 for (i
= 0; i
< num_iters
; i
++) {
474 ctx
= aes_encrypt_init(key
, 16);
476 aes_encrypt_deinit(ctx
);
477 printf(" %d", end
- start
);
482 ctx
= aes_encrypt_init(key
, 16);
483 for (i
= 0; i
< num_iters
; i
++) {
485 aes_encrypt(ctx
, pt
, ct
);
487 printf(" %d", end
- start
);
489 aes_encrypt_deinit(ctx
);
492 #endif /* __i386__ */
495 static int test_eax(void)
497 u8 msg
[] = { 0xF7, 0xFB };
498 u8 key
[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B,
499 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 };
500 u8 nonce
[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84,
501 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD };
502 u8 hdr
[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA };
503 u8 cipher
[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D,
504 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79,
506 u8 data
[sizeof(msg
)], tag
[BLOCK_SIZE
];
508 memcpy(data
, msg
, sizeof(msg
));
509 if (aes_128_eax_encrypt(key
, nonce
, sizeof(nonce
), hdr
, sizeof(hdr
),
510 data
, sizeof(data
), tag
)) {
511 printf("AES-128 EAX mode encryption failed\n");
514 if (memcmp(data
, cipher
, sizeof(data
)) != 0) {
515 printf("AES-128 EAX mode encryption returned invalid cipher "
519 if (memcmp(tag
, cipher
+ sizeof(data
), BLOCK_SIZE
) != 0) {
520 printf("AES-128 EAX mode encryption returned invalid tag\n");
524 if (aes_128_eax_decrypt(key
, nonce
, sizeof(nonce
), hdr
, sizeof(hdr
),
525 data
, sizeof(data
), tag
)) {
526 printf("AES-128 EAX mode decryption failed\n");
529 if (memcmp(data
, msg
, sizeof(data
)) != 0) {
530 printf("AES-128 EAX mode decryption returned invalid plain "
539 static int test_cbc(void)
541 struct cbc_test_vector
{
549 { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
550 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
551 { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
552 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
554 { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
555 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
559 { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
560 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
561 { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
562 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
563 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
564 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
565 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
566 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
567 { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
568 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
569 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
570 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
577 for (i
= 0; i
< sizeof(vectors
) / sizeof(vectors
[0]); i
++) {
578 struct cbc_test_vector
*tv
= &vectors
[i
];
579 buf
= malloc(tv
->len
);
584 memcpy(buf
, tv
->plain
, tv
->len
);
585 aes_128_cbc_encrypt(tv
->key
, tv
->iv
, buf
, tv
->len
);
586 if (memcmp(buf
, tv
->cipher
, tv
->len
) != 0) {
587 printf("AES-CBC encrypt %d failed\n", i
);
590 memcpy(buf
, tv
->cipher
, tv
->len
);
591 aes_128_cbc_decrypt(tv
->key
, tv
->iv
, buf
, tv
->len
);
592 if (memcmp(buf
, tv
->plain
, tv
->len
) != 0) {
593 printf("AES-CBC decrypt %d failed\n", i
);
603 /* OMAC1 AES-128 test vectors from
604 * http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf
607 struct omac1_test_vector
{
614 static struct omac1_test_vector test_vectors
[] =
617 { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
618 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
621 { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
622 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }
625 { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
626 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
627 { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
628 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
630 { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
631 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }
634 { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
635 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
636 { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
637 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
638 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
639 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
640 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 },
642 { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
643 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 }
646 { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
647 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
648 { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
649 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
650 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
651 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
652 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
653 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
654 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
655 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
657 { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
658 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe }
663 int main(int argc
, char *argv
[])
666 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
667 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
670 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
671 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
674 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
675 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
676 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
680 struct omac1_test_vector
*tv
;
682 if (aes_wrap(kek
, 2, plain
, result
)) {
683 printf("AES-WRAP-128-128 reported failure\n");
686 if (memcmp(result
, crypt
, 24) != 0) {
687 printf("AES-WRAP-128-128 failed\n");
690 if (aes_unwrap(kek
, 2, crypt
, result
)) {
691 printf("AES-UNWRAP-128-128 reported failure\n");
694 if (memcmp(result
, plain
, 16) != 0) {
696 printf("AES-UNWRAP-128-128 failed\n");
698 for (i
= 0; i
< 16; i
++)
699 printf(" %02x", result
[i
]);
705 #endif /* __i386__ */
707 for (i
= 0; i
< sizeof(test_vectors
) / sizeof(test_vectors
[0]); i
++) {
708 tv
= &test_vectors
[i
];
709 omac1_aes_128(tv
->k
, tv
->msg
, tv
->msg_len
, result
);
710 if (memcmp(result
, tv
->tag
, 16) != 0) {
711 printf("OMAC1-AES-128 test vector %d failed\n", i
);
725 #endif /* TEST_MAIN */