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