]>
Commit | Line | Data |
---|---|---|
4c9e03e0 JB |
1 | /* |
2 | * AES key unwrap (128-bit KEK, RFC3394) | |
3 | * | |
4 | * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> | |
5 | * | |
0f3d578e JM |
6 | * This software may be distributed under the terms of the BSD license. |
7 | * See README for more details. | |
4c9e03e0 JB |
8 | */ |
9 | ||
10 | #include "includes.h" | |
11 | ||
12 | #include "common.h" | |
1ba787b9 | 13 | #include "aes.h" |
8e2c104f | 14 | #include "aes_wrap.h" |
4c9e03e0 JB |
15 | |
16 | /** | |
17 | * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) | |
18 | * @kek: Key encryption key (KEK) | |
19 | * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 | |
20 | * bytes | |
21 | * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits | |
22 | * @plain: Plaintext key, n * 64 bits | |
23 | * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) | |
24 | */ | |
25 | int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) | |
26 | { | |
27 | u8 a[8], *r, b[16]; | |
28 | int i, j; | |
29 | void *ctx; | |
30 | ||
31 | /* 1) Initialize variables. */ | |
32 | os_memcpy(a, cipher, 8); | |
33 | r = plain; | |
34 | os_memcpy(r, cipher + 8, 8 * n); | |
35 | ||
36 | ctx = aes_decrypt_init(kek, 16); | |
37 | if (ctx == NULL) | |
38 | return -1; | |
39 | ||
40 | /* 2) Compute intermediate values. | |
41 | * For j = 5 to 0 | |
42 | * For i = n to 1 | |
43 | * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i | |
44 | * A = MSB(64, B) | |
45 | * R[i] = LSB(64, B) | |
46 | */ | |
47 | for (j = 5; j >= 0; j--) { | |
48 | r = plain + (n - 1) * 8; | |
49 | for (i = n; i >= 1; i--) { | |
50 | os_memcpy(b, a, 8); | |
51 | b[7] ^= n * j + i; | |
52 | ||
53 | os_memcpy(b + 8, r, 8); | |
54 | aes_decrypt(ctx, b, b); | |
55 | os_memcpy(a, b, 8); | |
56 | os_memcpy(r, b + 8, 8); | |
57 | r -= 8; | |
58 | } | |
59 | } | |
60 | aes_decrypt_deinit(ctx); | |
61 | ||
62 | /* 3) Output results. | |
63 | * | |
64 | * These are already in @plain due to the location of temporary | |
65 | * variables. Just verify that the IV matches with the expected value. | |
66 | */ | |
67 | for (i = 0; i < 8; i++) { | |
68 | if (a[i] != 0xa6) | |
69 | return -1; | |
70 | } | |
71 | ||
72 | return 0; | |
73 | } |