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