1214501Srpaulo/* 2281806Srpaulo * AES Key Wrap Algorithm (RFC3394) 3214501Srpaulo * 4214501Srpaulo * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 5214501Srpaulo * 6252726Srpaulo * This software may be distributed under the terms of the BSD license. 7252726Srpaulo * See README for more details. 8214501Srpaulo */ 9214501Srpaulo 10214501Srpaulo#include "includes.h" 11214501Srpaulo 12214501Srpaulo#include "common.h" 13214501Srpaulo#include "aes.h" 14214501Srpaulo#include "aes_wrap.h" 15214501Srpaulo 16214501Srpaulo/** 17281806Srpaulo * aes_wrap - Wrap keys with AES Key Wrap Algorithm (RFC3394) 18281806Srpaulo * @kek: Key encryption key (KEK) 19281806Srpaulo * @kek_len: Length of KEK in octets 20214501Srpaulo * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 21214501Srpaulo * bytes 22214501Srpaulo * @plain: Plaintext key to be wrapped, n * 64 bits 23214501Srpaulo * @cipher: Wrapped key, (n + 1) * 64 bits 24214501Srpaulo * Returns: 0 on success, -1 on failure 25214501Srpaulo */ 26281806Srpauloint aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) 27214501Srpaulo{ 28281806Srpaulo u8 *a, *r, b[AES_BLOCK_SIZE]; 29214501Srpaulo int i, j; 30214501Srpaulo void *ctx; 31281806Srpaulo unsigned int t; 32214501Srpaulo 33214501Srpaulo a = cipher; 34214501Srpaulo r = cipher + 8; 35214501Srpaulo 36214501Srpaulo /* 1) Initialize variables. */ 37214501Srpaulo os_memset(a, 0xa6, 8); 38214501Srpaulo os_memcpy(r, plain, 8 * n); 39214501Srpaulo 40281806Srpaulo ctx = aes_encrypt_init(kek, kek_len); 41214501Srpaulo if (ctx == NULL) 42214501Srpaulo return -1; 43214501Srpaulo 44214501Srpaulo /* 2) Calculate intermediate values. 45214501Srpaulo * For j = 0 to 5 46214501Srpaulo * For i=1 to n 47214501Srpaulo * B = AES(K, A | R[i]) 48214501Srpaulo * A = MSB(64, B) ^ t where t = (n*j)+i 49214501Srpaulo * R[i] = LSB(64, B) 50214501Srpaulo */ 51214501Srpaulo for (j = 0; j <= 5; j++) { 52214501Srpaulo r = cipher + 8; 53214501Srpaulo for (i = 1; i <= n; i++) { 54214501Srpaulo os_memcpy(b, a, 8); 55214501Srpaulo os_memcpy(b + 8, r, 8); 56214501Srpaulo aes_encrypt(ctx, b, b); 57214501Srpaulo os_memcpy(a, b, 8); 58281806Srpaulo t = n * j + i; 59281806Srpaulo a[7] ^= t; 60281806Srpaulo a[6] ^= t >> 8; 61281806Srpaulo a[5] ^= t >> 16; 62281806Srpaulo a[4] ^= t >> 24; 63214501Srpaulo os_memcpy(r, b + 8, 8); 64214501Srpaulo r += 8; 65214501Srpaulo } 66214501Srpaulo } 67214501Srpaulo aes_encrypt_deinit(ctx); 68214501Srpaulo 69214501Srpaulo /* 3) Output the results. 70214501Srpaulo * 71214501Srpaulo * These are already in @cipher due to the location of temporary 72214501Srpaulo * variables. 73214501Srpaulo */ 74214501Srpaulo 75214501Srpaulo return 0; 76214501Srpaulo} 77