1ba787b954
The BLOCK_SIZE define can be made more specific by using AES_ prefix and by moving it to aes.h. After this, most aes-*.c do not really need to include anything from the internal aes_i.h header file. In other words, aes_i.h can now be used only for the code that uses the internal AES block operation implementation and none of the code that can use AES implementation from an external library do not need to include this header file.
78 lines
1.8 KiB
C
78 lines
1.8 KiB
C
/*
|
|
* AES key unwrap (128-bit KEK, RFC3394)
|
|
*
|
|
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* Alternatively, this software may be distributed under the terms of BSD
|
|
* license.
|
|
*
|
|
* See README and COPYING for more details.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
#include "common.h"
|
|
#include "aes.h"
|
|
|
|
/**
|
|
* aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
|
|
* @kek: Key encryption key (KEK)
|
|
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
|
|
* bytes
|
|
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
|
|
* @plain: Plaintext key, n * 64 bits
|
|
* Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
|
|
*/
|
|
int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
|
|
{
|
|
u8 a[8], *r, b[16];
|
|
int i, j;
|
|
void *ctx;
|
|
|
|
/* 1) Initialize variables. */
|
|
os_memcpy(a, cipher, 8);
|
|
r = plain;
|
|
os_memcpy(r, cipher + 8, 8 * n);
|
|
|
|
ctx = aes_decrypt_init(kek, 16);
|
|
if (ctx == NULL)
|
|
return -1;
|
|
|
|
/* 2) Compute intermediate values.
|
|
* For j = 5 to 0
|
|
* For i = n to 1
|
|
* B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
|
|
* A = MSB(64, B)
|
|
* R[i] = LSB(64, B)
|
|
*/
|
|
for (j = 5; j >= 0; j--) {
|
|
r = plain + (n - 1) * 8;
|
|
for (i = n; i >= 1; i--) {
|
|
os_memcpy(b, a, 8);
|
|
b[7] ^= n * j + i;
|
|
|
|
os_memcpy(b + 8, r, 8);
|
|
aes_decrypt(ctx, b, b);
|
|
os_memcpy(a, b, 8);
|
|
os_memcpy(r, b + 8, 8);
|
|
r -= 8;
|
|
}
|
|
}
|
|
aes_decrypt_deinit(ctx);
|
|
|
|
/* 3) Output results.
|
|
*
|
|
* These are already in @plain due to the location of temporary
|
|
* variables. Just verify that the IV matches with the expected value.
|
|
*/
|
|
for (i = 0; i < 8; i++) {
|
|
if (a[i] != 0xa6)
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|