18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 29ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt * AES key unwrap (RFC3394) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "aes.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "aes_wrap.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 179ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (RFC3394) 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kek: Key encryption key (KEK) 199ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt * @kek_len: Length of KEK in octets 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * bytes 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @plain: Plaintext key, n * 64 bits 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 269ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtint aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, 279ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt u8 *plain) 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 299ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt u8 a[8], *r, b[AES_BLOCK_SIZE]; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, j; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 329ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt unsigned int t; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) Initialize variables. */ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(a, cipher, 8); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = plain; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(r, cipher + 8, 8 * n); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 399ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt ctx = aes_decrypt_init(kek, kek_len); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) Compute intermediate values. 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For j = 5 to 0 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For i = n to 1 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * A = MSB(64, B) 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R[i] = LSB(64, B) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = 5; j >= 0; j--) { 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = plain + (n - 1) * 8; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = n; i >= 1; i--) { 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(b, a, 8); 549ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt t = n * j + i; 559ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt b[7] ^= t; 569ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt b[6] ^= t >> 8; 579ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt b[5] ^= t >> 16; 589ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt b[4] ^= t >> 24; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(b + 8, r, 8); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_decrypt(ctx, b, b); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(a, b, 8); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(r, b + 8, 8); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r -= 8; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aes_decrypt_deinit(ctx); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Output results. 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * These are already in @plain due to the location of temporary 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * variables. Just verify that the IV matches with the expected value. 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 8; i++) { 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a[i] != 0xa6) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 81