aes-unwrap.c revision 252726
1299425Smm/* 2299425Smm * AES key unwrap (128-bit KEK, RFC3394) 3299425Smm * 4299425Smm * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 5299425Smm * 6299425Smm * This software may be distributed under the terms of the BSD license. 7299425Smm * See README for more details. 8299425Smm */ 9299425Smm 10299425Smm#include "includes.h" 11299425Smm 12299425Smm#include "common.h" 13299425Smm#include "aes.h" 14299425Smm#include "aes_wrap.h" 15299425Smm 16299425Smm/** 17299425Smm * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) 18299425Smm * @kek: Key encryption key (KEK) 19299425Smm * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 20299425Smm * bytes 21299425Smm * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits 22299425Smm * @plain: Plaintext key, n * 64 bits 23299425Smm * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) 24299425Smm */ 25299425Smmint aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) 26299425Smm{ 27299425Smm u8 a[8], *r, b[16]; 28299425Smm int i, j; 29299425Smm void *ctx; 30299425Smm 31299425Smm /* 1) Initialize variables. */ 32299425Smm os_memcpy(a, cipher, 8); 33299425Smm r = plain; 34299425Smm os_memcpy(r, cipher + 8, 8 * n); 35299425Smm 36299425Smm ctx = aes_decrypt_init(kek, 16); 37299425Smm if (ctx == NULL) 38299425Smm return -1; 39299425Smm 40299425Smm /* 2) Compute intermediate values. 41299425Smm * For j = 5 to 0 42299425Smm * For i = n to 1 43299425Smm * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i 44299425Smm * A = MSB(64, B) 45299425Smm * R[i] = LSB(64, B) 46299425Smm */ 47299425Smm for (j = 5; j >= 0; j--) { 48299425Smm r = plain + (n - 1) * 8; 49299425Smm for (i = n; i >= 1; i--) { 50299425Smm os_memcpy(b, a, 8); 51299425Smm b[7] ^= n * j + i; 52299425Smm 53299425Smm os_memcpy(b + 8, r, 8); 54299425Smm aes_decrypt(ctx, b, b); 55299425Smm os_memcpy(a, b, 8); 56299425Smm os_memcpy(r, b + 8, 8); 57299425Smm r -= 8; 58299425Smm } 59299425Smm } 60299425Smm aes_decrypt_deinit(ctx); 61299425Smm 62299425Smm /* 3) Output results. 63299425Smm * 64299425Smm * These are already in @plain due to the location of temporary 65299425Smm * variables. Just verify that the IV matches with the expected value. 66299425Smm */ 67299425Smm for (i = 0; i < 8; i++) { 68299425Smm if (a[i] != 0xa6) 69299425Smm return -1; 70299425Smm } 71299425Smm 72299425Smm return 0; 73299425Smm} 74299425Smm