aes: Add aes_unwrap

This commit is contained in:
Denis Kenzior 2015-02-17 13:52:00 -06:00
parent d188028fc1
commit 6e6783fc11
2 changed files with 59 additions and 0 deletions

View File

@ -30,6 +30,8 @@
#include <string.h>
#include <sys/socket.h>
#include <ell/ell.h>
#ifndef PF_ALG
#include <linux/types.h>
@ -128,3 +130,56 @@ done:
return result;
}
/*
* Implements AES Key-Unwrap from RFC 3394
*
* The key is specified using @kek. @in contains the encrypted data and @len
* contains its length. @out will contain the decrypted data. The result
* will be (len - 8) bytes.
*
* Returns: true on success, false if an IV mismatch has occurred.
*
* NOTE: Buffers @in and @out can overlap
*/
bool aes_unwrap(const uint8_t *kek, const uint8_t *in, size_t len,
uint8_t *out)
{
uint8_t a[8], b[16];
uint8_t *r;
size_t n = (len - 8) >> 3;
int i, j;
struct l_cipher *cipher;
cipher = l_cipher_new(L_CIPHER_AES, kek, 16);
if (!cipher)
return false;
/* Set up */
memcpy(a, in, 8);
memmove(out, in + 8, n * 8);
/* Unwrap */
for (j = 5; j >= 0; j--) {
r = out + (n - 1) * 8;
for (i = n; i >= 1; i--) {
memcpy(b, a, 8);
memcpy(b + 8, r, 8);
b[7] ^= n * j + i;
l_cipher_decrypt(cipher, b, b, 16);
memcpy(a, b, 8);
memcpy(r, b + 8, 8);
r -= 8;
}
}
l_cipher_free(cipher);
/* Check IV */
for (i = 0; i < 8; i++)
if (a[i] != 0xA6)
return false;
return true;
}

View File

@ -21,6 +21,10 @@
*/
#include <stdbool.h>
#include <stdint.h>
bool cmac_aes(const void *key, size_t key_len,
const void *msg, size_t msg_len, void *tag, size_t size);
bool aes_unwrap(const uint8_t *kek, const uint8_t *in, size_t len,
uint8_t *out);