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