1214501Srpaulo/* 2214501Srpaulo * AES key unwrap (128-bit KEK, RFC3394) 3214501Srpaulo * 4214501Srpaulo * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 5214501Srpaulo * 6252726Srpaulo * This software may be distributed under the terms of the BSD license. 7252726Srpaulo * See README for more details. 8214501Srpaulo */ 9214501Srpaulo 10214501Srpaulo#include "includes.h" 11214501Srpaulo 12214501Srpaulo#include "common.h" 13214501Srpaulo#include "aes.h" 14214501Srpaulo#include "aes_wrap.h" 15214501Srpaulo 16214501Srpaulo/** 17214501Srpaulo * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) 18214501Srpaulo * @kek: Key encryption key (KEK) 19214501Srpaulo * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 20214501Srpaulo * bytes 21214501Srpaulo * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits 22214501Srpaulo * @plain: Plaintext key, n * 64 bits 23214501Srpaulo * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) 24214501Srpaulo */ 25214501Srpauloint aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) 26214501Srpaulo{ 27214501Srpaulo u8 a[8], *r, b[16]; 28214501Srpaulo int i, j; 29214501Srpaulo void *ctx; 30214501Srpaulo 31214501Srpaulo /* 1) Initialize variables. */ 32214501Srpaulo os_memcpy(a, cipher, 8); 33214501Srpaulo r = plain; 34214501Srpaulo os_memcpy(r, cipher + 8, 8 * n); 35214501Srpaulo 36214501Srpaulo ctx = aes_decrypt_init(kek, 16); 37214501Srpaulo if (ctx == NULL) 38214501Srpaulo return -1; 39214501Srpaulo 40214501Srpaulo /* 2) Compute intermediate values. 41214501Srpaulo * For j = 5 to 0 42214501Srpaulo * For i = n to 1 43214501Srpaulo * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i 44214501Srpaulo * A = MSB(64, B) 45214501Srpaulo * R[i] = LSB(64, B) 46214501Srpaulo */ 47214501Srpaulo for (j = 5; j >= 0; j--) { 48214501Srpaulo r = plain + (n - 1) * 8; 49214501Srpaulo for (i = n; i >= 1; i--) { 50214501Srpaulo os_memcpy(b, a, 8); 51214501Srpaulo b[7] ^= n * j + i; 52214501Srpaulo 53214501Srpaulo os_memcpy(b + 8, r, 8); 54214501Srpaulo aes_decrypt(ctx, b, b); 55214501Srpaulo os_memcpy(a, b, 8); 56214501Srpaulo os_memcpy(r, b + 8, 8); 57214501Srpaulo r -= 8; 58214501Srpaulo } 59214501Srpaulo } 60214501Srpaulo aes_decrypt_deinit(ctx); 61214501Srpaulo 62214501Srpaulo /* 3) Output results. 63214501Srpaulo * 64214501Srpaulo * These are already in @plain due to the location of temporary 65214501Srpaulo * variables. Just verify that the IV matches with the expected value. 66214501Srpaulo */ 67214501Srpaulo for (i = 0; i < 8; i++) { 68214501Srpaulo if (a[i] != 0xa6) 69214501Srpaulo return -1; 70214501Srpaulo } 71214501Srpaulo 72214501Srpaulo return 0; 73214501Srpaulo} 74