/** @file crypt_new_rom.c
|
*
|
* @brief This file defines AES based functions.
|
*
|
* Copyright (C) 2014-2017, Marvell International Ltd.
|
*
|
* This software file (the "File") is distributed by Marvell International
|
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
* (the "License"). You may use, redistribute and/or modify this File in
|
* accordance with the terms and conditions of the License, a copy of which
|
* is available by writing to the Free Software Foundation, Inc.,
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
*
|
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
* this warranty disclaimer.
|
*/
|
|
/******************************************************
|
Change log:
|
03/07/2014: Initial version
|
******************************************************/
|
/*
|
* AES based functions
|
*
|
* - AES Key Wrap algorithm (128-bit KEK) (RFC-3394)
|
* - AES primitive algorithm
|
* - AES CCM algorithm
|
*
|
* Date: 11/01/2005
|
*/
|
#include "wltypes.h"
|
#include "crypt_new_rom.h"
|
#include "rc4_rom.h"
|
#include "rijndael.h"
|
|
#include "hostsa_ext_def.h"
|
#include "authenticator.h"
|
|
static const UINT8 MRVL_DEFAULT_IV[8] = { 0xA6, 0xA6, 0xA6, 0xA6,
|
0xA6, 0xA6, 0xA6, 0xA6
|
};
|
|
UINT8 aesResult[32];
|
|
/* MRVL_AES_MEMCMP
|
* : similiar to memcmp in std c lib
|
* @dst : dst ptr to be compared to
|
* @src : src ptr to be compared from
|
* @len : size of the comparison
|
*
|
* ASSUMPTION : dst/src has to be valid data ptrs
|
*/
|
int
|
MRVL_AES_MEMCMP(UINT8 *dst, UINT8 *src, int len)
|
{
|
int cnt = len;
|
|
while (len--) {
|
if (*dst++ == *src++) {
|
cnt--;
|
}
|
}
|
|
if (0 == cnt) {
|
return 0; /* dst == src */
|
}
|
|
return -1; /* dst != src */
|
}
|
|
/* MRVL_AES_MEMSET
|
* : similiar to memset in std c lib
|
* @dst : dst starting pointer
|
* @val : val to be set
|
* @size : size of dst buffer to be set
|
*
|
* ASSUMPTION : dst buffer must always have larger than the value of size
|
*/
|
void
|
MRVL_AES_MEMSET(UINT8 *dst, UINT8 val, int size)
|
{
|
while (size--) {
|
*dst++ = val;
|
}
|
}
|
|
/* MRVL_AES_MEMCPY
|
* : similar to memcpy in std c lib
|
* @dst : dst buffer starting ptr
|
* @src : src buffer starting ptr
|
* @size : size of copy
|
*
|
* ASSUMPTION :
|
* 1: dst buffer must be larger than src + size of copy
|
* 2: dst buffer isn't overlapping src buffer
|
*/
|
void
|
MRVL_AES_MEMCPY(UINT8 *dst, UINT8 *src, int size)
|
{
|
if (dst < src) {
|
while (size) {
|
*dst++ = *src++;
|
size--;
|
}
|
} else {
|
while (size) {
|
*(dst + size - 1) = *(src + size - 1);
|
size--;
|
}
|
}
|
}
|
|
int
|
MRVL_AesInterCheck(UINT8 *inter, UINT8 *d)
|
{
|
if (0 == MRVL_AES_MEMCMP(inter, d, 16)) {
|
return 0;
|
}
|
|
return -1;
|
}
|
|
#ifdef WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH
|
extern const u8 Te4[256];
|
extern const u32 rcon[];
|
extern const u32 Td0[256];
|
extern const u32 Td1[256];
|
extern const u32 Td2[256];
|
extern const u32 Td3[256];
|
#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
|
|
static int
|
rijndaelKeySetupEnc_2(u32 rk[ /*4*(Nr + 1) */ ], const u8 cipherKey[],
|
int keyBits)
|
{
|
int i = 0;
|
u32 temp;
|
|
rk[0] = GETU32(cipherKey);
|
rk[1] = GETU32(cipherKey + 4);
|
rk[2] = GETU32(cipherKey + 8);
|
rk[3] = GETU32(cipherKey + 12);
|
if (keyBits == 128) {
|
for (;;) {
|
temp = rk[3];
|
rk[4] = rk[0] ^
|
(Te4[(temp >> 16) & 0xff] << 24) ^
|
(Te4[(temp >> 8) & 0xff] << 16) ^
|
(Te4[(temp) & 0xff] << 8) ^
|
(Te4[(temp >> 24)]) ^ rcon[i];
|
rk[5] = rk[1] ^ rk[4];
|
rk[6] = rk[2] ^ rk[5];
|
rk[7] = rk[3] ^ rk[6];
|
if (++i == 10) {
|
return 10;
|
}
|
rk += 4;
|
}
|
}
|
|
/** Handle 24 bytes key length */
|
rk[4] = GETU32(cipherKey + 16);
|
rk[5] = GETU32(cipherKey + 20);
|
if (keyBits == 192) {
|
for (;;) {
|
temp = rk[5];
|
rk[6] = rk[0] ^
|
(Te4[(temp >> 16) & 0xff] << 24) ^
|
(Te4[(temp >> 8) & 0xff] << 16) ^
|
(Te4[(temp) & 0xff] << 8) ^
|
(Te4[(temp >> 24)]) ^ rcon[i];
|
rk[7] = rk[1] ^ rk[6];
|
rk[8] = rk[2] ^ rk[7];
|
rk[9] = rk[3] ^ rk[8];
|
if (++i == 8) {
|
return 12;
|
}
|
rk[10] = rk[4] ^ rk[9];
|
rk[11] = rk[5] ^ rk[10];
|
rk += 6;
|
}
|
}
|
|
/** Handle 32 bytes key length */
|
rk[6] = GETU32(cipherKey + 24);
|
rk[7] = GETU32(cipherKey + 28);
|
if (keyBits == 256) {
|
for (;;) {
|
temp = rk[7];
|
rk[8] = rk[0] ^
|
(Te4[(temp >> 16) & 0xff] << 24) ^
|
(Te4[(temp >> 8) & 0xff] << 16) ^
|
(Te4[(temp) & 0xff] << 8) ^
|
(Te4[(temp >> 24)]) ^ rcon[i];
|
rk[9] = rk[1] ^ rk[8];
|
rk[10] = rk[2] ^ rk[9];
|
rk[11] = rk[3] ^ rk[10];
|
if (++i == 7) {
|
return 14;
|
}
|
temp = rk[11];
|
rk[12] = rk[4] ^
|
(Te4[(temp >> 24)] << 24) ^
|
(Te4[(temp >> 16) & 0xff] << 16) ^
|
(Te4[(temp >> 8) & 0xff] << 8) ^
|
(Te4[(temp) & 0xff]);
|
rk[13] = rk[5] ^ rk[12];
|
rk[14] = rk[6] ^ rk[13];
|
rk[15] = rk[7] ^ rk[14];
|
rk += 8;
|
}
|
}
|
return 0;
|
}
|
|
static int
|
rijndaelKeySetupDec_2(u32 rk[ /*4*(Nr + 1) */ ], const u8 cipherKey[],
|
int keyBits, int have_encrypt)
|
{
|
int Nr, i, j;
|
u32 temp;
|
|
if (have_encrypt) {
|
Nr = have_encrypt;
|
} else {
|
/* expand the cipher key: */
|
Nr = rijndaelKeySetupEnc_2(rk, cipherKey, keyBits);
|
}
|
/* invert the order of the round keys: */
|
for (i = 0, j = 4 * Nr; i < j; i += 4, j -= 4) {
|
temp = rk[i];
|
rk[i] = rk[j];
|
rk[j] = temp;
|
temp = rk[i + 1];
|
rk[i + 1] = rk[j + 1];
|
rk[j + 1] = temp;
|
temp = rk[i + 2];
|
rk[i + 2] = rk[j + 2];
|
rk[j + 2] = temp;
|
temp = rk[i + 3];
|
rk[i + 3] = rk[j + 3];
|
rk[j + 3] = temp;
|
}
|
/* apply the inverse MixColumn transform to all round keys but the first and the last: */
|
for (i = 1; i < Nr; i++) {
|
rk += 4;
|
rk[0] = Td0[Te4[(rk[0] >> 24)]] ^
|
Td1[Te4[(rk[0] >> 16) & 0xff]] ^
|
Td2[Te4[(rk[0] >> 8) & 0xff]] ^
|
Td3[Te4[(rk[0]) & 0xff]];
|
rk[1] = Td0[Te4[(rk[1] >> 24)]] ^
|
Td1[Te4[(rk[1] >> 16) & 0xff]] ^
|
Td2[Te4[(rk[1] >> 8) & 0xff]] ^
|
Td3[Te4[(rk[1]) & 0xff]];
|
rk[2] = Td0[Te4[(rk[2] >> 24)]] ^
|
Td1[Te4[(rk[2] >> 16) & 0xff]] ^
|
Td2[Te4[(rk[2] >> 8) & 0xff]] ^
|
Td3[Te4[(rk[2]) & 0xff]];
|
rk[3] = Td0[Te4[(rk[3] >> 24)]] ^
|
Td1[Te4[(rk[3] >> 16) & 0xff]] ^
|
Td2[Te4[(rk[3] >> 8) & 0xff]] ^
|
Td3[Te4[(rk[3]) & 0xff]];
|
}
|
return Nr;
|
}
|
|
static void
|
rijndael_set_key_2(rijndael_ctx *ctx, u8 *key, int bits, int encrypt)
|
{
|
ctx->Nr = rijndaelKeySetupEnc_2(ctx->key, key, bits);
|
if (encrypt) {
|
ctx->decrypt = 0;
|
} else {
|
ctx->decrypt = 1;
|
rijndaelKeySetupDec_2(ctx->key, key, bits, ctx->Nr);
|
/**bt_test :: TBD */
|
}
|
}
|
#endif /** WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH */
|
|
/*
|
* AesEncrypt : aes primitive encryption
|
*
|
* @kek : key encryption key
|
* @kekLen : kek len
|
* @data : data pointer
|
*
|
* ASSUMPTION : both src and dst buffer has to be 16 bytes or 128-bit
|
*/
|
int
|
MRVL_AesEncrypt(UINT8 *kek, UINT8 kekLen, UINT8 *data, UINT8 *ret)
|
{
|
//BufferDesc_t * pDesc = NULL;
|
UINT8 buf[400] = { 0 };
|
rijndael_ctx *ctx;
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
int ptr_val;
|
|
if (MRVL_AesEncrypt_hook(kek, kekLen, data, ret, &ptr_val)) {
|
return ptr_val;
|
}
|
#endif
|
#if 0
|
/* Wait forever ensures a buffer */
|
pDesc = (BufferDesc_t *) bml_AllocBuffer(ramHook_encrPoolConfig,
|
400, BML_WAIT_FOREVER);
|
#endif
|
//ctx = (rijndael_ctx *)BML_DATA_PTR(pDesc);
|
ctx = (rijndael_ctx *)buf;
|
#ifdef WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH
|
rijndael_set_key_2(ctx, (UINT8 *)kek, kekLen * 64, 1);
|
#else
|
rijndael_set_key(ctx, (UINT8 *)kek, kekLen * 64, 1);
|
#endif /** WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH */
|
rijndael_encrypt(ctx, data, ret);
|
// bml_FreeBuffer((UINT32)pDesc);
|
|
return 0;
|
}
|
|
/****************************************************************
|
* AES_WRAP : AES_WRAP is specified by RFC 3394 section 2.2.1
|
*
|
* Inputs : plaintest, n 64-bit values {P1, P2, ..., Pn}, and
|
* Key, K (the KEK)
|
* Outputs : ciphertext, (n+1) 64-bit values {C0, ..., Cn}
|
*
|
* NOTE: this function is ported over from WPA_SUPPLICANT
|
****************************************************************
|
*
|
* @kek : key encryption key
|
* @kekLen : kek len, in unit of 64-bit, has to be 2, 3, or 4
|
* @n : length of the wrapped key in 64-bit
|
* unit; e.g.: 2 = 128-bit = 16 bytes
|
* @plain : plaintext key to be wrapped, has to be n * (64-bit)
|
* or n * 8 bytes
|
* @cipher : wrapped key, (n + 1) * 64-bit or (n+1) * 8 bytes
|
*/
|
|
/* debugging */
|
|
int
|
MRVL_AesWrap(UINT8 *kek, UINT8 kekLen, UINT32 n,
|
UINT8 *plain, UINT8 *keyIv, UINT8 *cipher)
|
{
|
UINT8 a[8];
|
UINT8 b[16];
|
int i = 0;
|
int j = 0;
|
UINT8 *r = NULL;
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
int ptr_val;
|
|
if (MRVL_AesWrap_hook(kek, kekLen, n, plain, keyIv, cipher, &ptr_val)) {
|
return ptr_val;
|
}
|
#endif
|
|
/* 0: before everything, check n value
|
*/
|
if (1 > n) {
|
return -1;
|
}
|
|
r = cipher + 8;
|
|
/* 1: initialize variables */
|
MRVL_AES_MEMSET(b, 0x0, 16);
|
if (keyIv) {
|
MRVL_AES_MEMCPY(a, keyIv, 8);
|
} else {
|
MRVL_AES_MEMCPY(a, (UINT8 *)MRVL_DEFAULT_IV, 8);
|
}
|
MRVL_AES_MEMCPY(r, plain, (8 * n));
|
|
/* 2: calculate intermediate values
|
* For j = 0 to 5
|
* For i=1 to n
|
* B = AES(K, A | R[i])
|
* A = MSB(64, B) ^ t where t = (n*j)+i
|
* R[i] = LSB(64, B)
|
*/
|
for (j = 0; j <= 5; j++) {
|
r = cipher + 8;
|
for (i = 1; i <= n; i++) {
|
MRVL_AES_MEMCPY(b, a, 8);
|
MRVL_AES_MEMCPY(b + 8, r, 8);
|
MRVL_AesEncrypt(kek, kekLen, b, b);
|
MRVL_AES_MEMCPY(a, b, 8);
|
a[7] ^= n * j + i;
|
MRVL_AES_MEMCPY(r, b + 8, 8);
|
r += 8;
|
}
|
}
|
|
MRVL_AES_MEMCPY(cipher, a, 8);
|
|
/* 3: output the results
|
* these are already in @cipher
|
*/
|
|
return 0;
|
}
|
|
/****************************************************************
|
* AES_UNWRAP : AES_UNWRAP is specified by RFC 3394 section 2.2.2
|
*
|
* Inputs : ciphertext, (n+1) 64-bit values {C0, ..., Cn}, and
|
* Key, K (the KEK)
|
*
|
* Outputs : plaintest, n 64-bit values {P1, P2, ..., Pn} + first 8 bytes
|
* for KEYIV
|
*
|
*
|
****************************************************************
|
*
|
* @kek : key encryption key
|
* @kekLen : kek len, in unit of 64-bit, has to be 2, 3, or 4
|
* @n : length of the wrapped key in 64-bit
|
* unit; e.g.: 2 = 128-bit = 16 bytes
|
* @cipher : wrapped data, (n + 1) * 64-bit or (n+1) * 8 bytes
|
* @plain : plaintext being unwrapped, has to be n * (64-bit)
|
* or n * 8 bytes + extra 8 bytes for KEYIV
|
*/
|
int
|
MRVL_AesUnWrap(UINT8 *kek, UINT8 kekLen, UINT32 n,
|
UINT8 *cipher, UINT8 *keyIv, UINT8 *plain)
|
{
|
UINT8 b[16];
|
int i = 0;
|
int j = 0;
|
UINT8 a[8];
|
UINT8 *r = NULL;
|
//BufferDesc_t * pDesc = NULL;
|
UINT8 buf[400] = { 0 };
|
|
rijndael_ctx *ctx;
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
int ptr_val;
|
|
if (MRVL_AesUnWrap_hook(kek, kekLen, n, cipher, keyIv, plain, &ptr_val)) {
|
return ptr_val;
|
}
|
#endif
|
|
/* 0: before everything, check n value
|
*/
|
if (1 > n) {
|
return -1;
|
}
|
|
/* 1: initialize variables */
|
MRVL_AES_MEMSET(a, 0x0, 8);
|
MRVL_AES_MEMSET(b, 0x0, 16);
|
MRVL_AES_MEMCPY(a, cipher, 8);
|
r = plain;
|
MRVL_AES_MEMCPY(r, cipher + 8, 8 * n);
|
#if 0
|
/* Wait forever ensures a buffer */
|
pDesc = (BufferDesc_t *) bml_AllocBuffer(ramHook_encrPoolConfig,
|
400, BML_WAIT_FOREVER);
|
#endif
|
//ctx = (rijndael_ctx *)BML_DATA_PTR(pDesc);
|
ctx = (rijndael_ctx *)buf;
|
#ifdef WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH
|
rijndael_set_key_2(ctx, (UINT8 *)kek, kekLen * 64, 0);
|
#else
|
rijndael_set_key(ctx, (UINT8 *)kek, kekLen * 64, 0);
|
#endif /** WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH */
|
|
/* 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--) {
|
MRVL_AES_MEMCPY(b, a, 8);
|
b[7] ^= n * j + i;
|
MRVL_AES_MEMCPY(b + 8, r, 8);
|
|
rijndael_decrypt(ctx, b, b);
|
|
MRVL_AES_MEMCPY(a, b, 8);
|
MRVL_AES_MEMCPY(r, b + 8, 8);
|
r -= 8;
|
}
|
}
|
|
// bml_FreeBuffer((UINT32)pDesc);
|
|
/* 3: copy decrypted KeyIV to keyIv array */
|
if (keyIv) {
|
if (MRVL_AES_MEMCMP(keyIv, a, 8)) {
|
return -1;
|
}
|
} else {
|
if (MRVL_AES_MEMCMP((UINT8 *)MRVL_DEFAULT_IV, a, 8)) {
|
return -1;
|
}
|
}
|
|
return 0;
|
}
|
|
#if 0
|
/*****
|
* AES CRYPTION HELPER FUNCTIONS
|
*
|
*/
|
int
|
MRVL_AesValidateHostRequest(UINT32 *pBitMap, UINT8 *pCmdPtr,
|
UINT8 *pCryptData, SINT8 *AESwrapEnc)
|
{
|
host_MRVL_AES_CRYPT_t *pLocal = NULL;
|
MrvlIEParamSet_t *pLocalIEParam = NULL;
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
int ptr_val;
|
|
if (MRVL_AesValidateHostRequest_hook(pBitMap,
|
pCmdPtr,
|
pCryptData,
|
AESwrapEnc, &ptr_val)) {
|
return ptr_val;
|
}
|
#endif
|
|
if (NULL == pBitMap || NULL == pCmdPtr) {
|
return -1;
|
}
|
|
pLocal = (host_MRVL_AES_CRYPT_t *) pCmdPtr;
|
pLocalIEParam = (MrvlIEParamSet_t *)&(pLocal->aesTlv);
|
if ((0 != pLocal->action) && (0x1 != pLocal->action)) {
|
*pBitMap |= MRVL_AES_NOT_EN_AND_DECRYPT;
|
}
|
|
if (0 == pLocal->action) {
|
((MRVL_ENDECRYPT_t *)pCryptData)->enDeAction = CRYPT_DECRYPT;
|
} else if (1 == pLocal->action) {
|
((MRVL_ENDECRYPT_t *)pCryptData)->enDeAction = CRYPT_ENCRYPT;
|
}
|
switch (pLocal->algorithm) {
|
case MRVL_CRYPTO_TEST_RC4:
|
if ((1 > (pLocal->keyIVLen + pLocal->keyLen)) ||
|
(256 < (pLocal->keyIVLen + pLocal->keyLen))) {
|
*pBitMap |= MRVL_AES_KEY_IV_INVALID_RC4;
|
}
|
break;
|
case MRVL_CRYPTO_TEST_AES_ECB:
|
if ((16 != pLocal->keyLen) &&
|
(24 != pLocal->keyLen) && (32 != pLocal->keyLen)) {
|
*pBitMap |= MRVL_AES_KEY_SIZE_INVALID;
|
}
|
|
if ((16 != pLocalIEParam->Length)) {
|
*pBitMap |= MRVL_AES_DATA_SIZE_INVALID;
|
}
|
break;
|
case MRVL_CRYPTO_TEST_AES_WRAP:
|
if (8 != pLocal->keyIVLen) {
|
*pBitMap |= MRVL_AES_KEY_IV_INVALID_AES_WRAP;
|
}
|
|
if ((16 != pLocal->keyLen) &&
|
(24 != pLocal->keyLen) && (32 != pLocal->keyLen)) {
|
*pBitMap |= MRVL_AES_KEY_SIZE_INVALID;
|
}
|
|
if ((1016 < pLocalIEParam->Length) ||
|
(8 > pLocalIEParam->Length)) {
|
*pBitMap |= MRVL_AES_DATA_SIZE_INVALID;
|
}
|
|
if (1 == pLocal->action) { /* Encryption */
|
*AESwrapEnc = 8;
|
} else if (0 == pLocal->action) { /* Decryption */
|
*AESwrapEnc = -8;
|
}
|
break;
|
#ifdef DIAG_AES_CCM
|
case MRVL_CRYPTO_TEST_AEC_CCM:
|
{
|
host_MRVL_AES_CCM_CRYPT_t *pLocalCCM
|
= (host_MRVL_AES_CCM_CRYPT_t *) pCmdPtr;
|
|
pLocalIEParam =
|
(MrvlIEParamSet_t *)&(pLocalCCM->aesTlv);
|
|
/* key length should be 16 */
|
if ((16 != pLocalCCM->keyLen) &&
|
(24 != pLocalCCM->keyLen) &&
|
(32 != pLocalCCM->keyLen)) {
|
*pBitMap |= MRVL_AES_KEY_SIZE_INVALID;
|
}
|
|
/* nonce length 7 ~ 13 bytes */
|
if ((pLocalCCM->nonceLen < 7) ||
|
(pLocalCCM->nonceLen > 13)) {
|
*pBitMap |= MRVL_AES_NONCE_INVALID;
|
}
|
|
/* AAD length 0 ~ 30 bytes */
|
if (pLocalCCM->aadLen > 30) {
|
*pBitMap |= MRVL_AES_AAD_INVALID;
|
}
|
|
/* payload length 0 ~ 32 bytes */
|
if (40 < pLocalIEParam->Length) {
|
*pBitMap |= MRVL_AES_DATA_SIZE_INVALID;
|
}
|
}
|
break;
|
#endif
|
#ifdef WAPI_HW_SUPPORT
|
case MRVL_CRYPTO_TEST_WAPI:
|
{
|
host_MRVL_WAPI_CRYPT_t *pLocalWAPI
|
= (host_MRVL_WAPI_CRYPT_t *) pCmdPtr;
|
|
/* key length should be 16 */
|
if (pLocalWAPI->keyLen != 32) {
|
*pBitMap |= MRVL_AES_KEY_SIZE_INVALID;
|
}
|
|
/* nonce length 16 bytes */
|
if (pLocalWAPI->nonceLen != 16) {
|
*pBitMap |= MRVL_AES_NONCE_INVALID;
|
}
|
|
/* AAD length 32 or 48 bytes */
|
if ((pLocalWAPI->aadLen != 32) &&
|
(pLocalWAPI->aadLen != 48)) {
|
*pBitMap |= MRVL_AES_AAD_INVALID;
|
}
|
}
|
break;
|
#endif
|
default:
|
*pBitMap |= MRVL_AES_ALGORITHM_INVALID;
|
break;
|
}
|
|
/* put the buffer ptr to cryptdata */
|
((MRVL_ENDECRYPT_t *)pCryptData)->pData = pCmdPtr;
|
|
return 0;
|
}
|
|
/**************
|
* WRAPPER to do AES primitive encryption
|
*/
|
void
|
MRVL_AesPrimitiveEncrypt(MRVL_ENDECRYPT_t *crypt, int *pErr)
|
{
|
UINT8 *kek = NULL;
|
UINT8 *data = NULL;
|
UINT8 kekLen = 0;
|
host_MRVL_AES_CRYPT_t *pLocal = NULL;
|
MrvlIEAesCrypt_t *pLocalIEParam = NULL;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (MRVL_AesPrimitiveEncrypt_hook(crypt, pErr)) {
|
return;
|
}
|
#endif
|
|
if ((NULL == pErr) || (NULL == crypt)) {
|
*pErr = -1;
|
return;
|
}
|
|
*pErr = 0;
|
|
if ((CRYPT_ENCRYPT != crypt->enDeAction)) {
|
*pErr = -1;
|
return;
|
}
|
|
pLocal = (host_MRVL_AES_CRYPT_t *) (crypt->pData);
|
pLocalIEParam = (MrvlIEAesCrypt_t *)&(pLocal->aesTlv);
|
|
kek = (UINT8 *)(pLocal->key);
|
kekLen = pLocal->keyLen;
|
data = (UINT8 *)(pLocalIEParam->payload);
|
|
if (-1 == MRVL_AesEncrypt(kek, kekLen / 8, data, data)) {
|
*pErr = -1;
|
return;
|
}
|
}
|
|
void
|
MRVL_AesPrimitiveDecrypt(MRVL_ENDECRYPT_t *crypt, int *pErr)
|
{
|
UINT8 *kek = NULL;
|
UINT8 *data = NULL;
|
UINT8 kekLen = 0;
|
host_MRVL_AES_CRYPT_t *pLocal = NULL;
|
MrvlIEAesCrypt_t *pLocalIEParam = NULL;
|
BufferDesc_t *pDesc;
|
rijndael_ctx *ctx;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (MRVL_AesPrimitiveDecrypt_hook(crypt, pErr)) {
|
return;
|
}
|
#endif
|
|
if ((NULL == pErr) || (NULL == crypt)) {
|
*pErr = -1;
|
return;
|
}
|
|
if ((CRYPT_DECRYPT != crypt->enDeAction)) {
|
*pErr = -1;
|
return;
|
}
|
|
pLocal = (host_MRVL_AES_CRYPT_t *) (crypt->pData);
|
pLocalIEParam = (MrvlIEAesCrypt_t *)&(pLocal->aesTlv);
|
|
kek = (UINT8 *)(pLocal->key);
|
kekLen = pLocal->keyLen;
|
data = (UINT8 *)(pLocalIEParam->payload);
|
#if 0
|
/* Wait forever ensures a buffer */
|
pDesc = (BufferDesc_t *) bml_AllocBuffer(ramHook_encrPoolConfig,
|
400, BML_WAIT_FOREVER);
|
#endif
|
ctx = (rijndael_ctx *)BML_DATA_PTR(pDesc);
|
|
#ifdef WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH
|
rijndael_set_key_2(ctx, (UINT8 *)kek, kekLen * 8, 0);
|
#else
|
rijndael_set_key(ctx, (UINT8 *)kek, kekLen * 8, 0);
|
#endif /** WAR_ROM_BUG64609_SUPPORT_24_32_BYTES_KEY_LENGTH */
|
|
rijndael_decrypt(ctx, data, data);
|
bml_FreeBuffer((UINT32)pDesc);
|
|
*pErr = 0;
|
|
}
|
|
void
|
MRVL_AesWrapEncrypt(MRVL_ENDECRYPT_t *crypt, int *pErr)
|
{
|
UINT8 *kek = NULL;
|
UINT8 *data = NULL;
|
UINT8 *keyIV = NULL;
|
UINT8 kekLen = 0;
|
UINT32 dataLen = 0;
|
host_MRVL_AES_CRYPT_t *pLocal = NULL;
|
MrvlIEAesCrypt_t *pLocalIEParam = NULL;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (MRVL_AesWrapEncrypt_hook(crypt, pErr)) {
|
return;
|
}
|
#endif
|
|
if ((NULL == pErr) || (NULL == crypt)) {
|
*pErr = -1;
|
return;
|
}
|
|
*pErr = 0;
|
|
if ((CRYPT_ENCRYPT != crypt->enDeAction)) {
|
*pErr = -1;
|
return;
|
}
|
|
pLocal = (host_MRVL_AES_CRYPT_t *) (crypt->pData);
|
pLocalIEParam = (MrvlIEAesCrypt_t *)&(pLocal->aesTlv);
|
|
kek = (UINT8 *)(pLocal->key);
|
keyIV = (UINT8 *)(pLocal->keyIV);
|
kekLen = pLocal->keyLen;
|
data = (UINT8 *)(pLocalIEParam->payload);
|
dataLen = pLocalIEParam->hdr.Length;
|
/* need to add one more 8-bytes for return length */
|
pLocalIEParam->hdr.Length = dataLen + 8;
|
|
if (-1 ==
|
MRVL_AesWrap(kek, kekLen / 8, dataLen / 8, data, keyIV,
|
aesResult)) {
|
*pErr = -2;
|
return;
|
}
|
|
MRVL_AES_MEMCPY(data, aesResult, pLocalIEParam->hdr.Length);
|
}
|
|
void
|
MRVL_AesWrapDecrypt(MRVL_ENDECRYPT_t *crypt, int *pErr)
|
{
|
UINT8 *kek = NULL;
|
UINT8 *keyIV = NULL;
|
UINT8 *data = NULL;
|
UINT8 kekLen = 0;
|
UINT32 dataLen = 0;
|
host_MRVL_AES_CRYPT_t *pLocal = NULL;
|
MrvlIEAesCrypt_t *pLocalIEParam = NULL;
|
|
#if 0 //!defined(REMOVE_PATCH_HOOKS)
|
if (MRVL_AesWrapDecrypt_hook(crypt, pErr)) {
|
return;
|
}
|
#endif
|
|
if ((NULL == pErr) || (NULL == crypt)) {
|
*pErr = -1;
|
return;
|
}
|
|
*pErr = 0;
|
|
if ((CRYPT_DECRYPT != crypt->enDeAction)) {
|
*pErr = -1;
|
return;
|
}
|
|
pLocal = (host_MRVL_AES_CRYPT_t *) (crypt->pData);
|
pLocalIEParam = (MrvlIEAesCrypt_t *)&(pLocal->aesTlv);
|
|
kek = (UINT8 *)(pLocal->key);
|
keyIV = (UINT8 *)(pLocal->keyIV);
|
kekLen = pLocal->keyLen;
|
data = (UINT8 *)(pLocalIEParam->payload);
|
dataLen = pLocalIEParam->hdr.Length;
|
|
if (-1 == MRVL_AesUnWrap(kek, kekLen / 8, dataLen / 8 - 1,
|
data, keyIV, aesResult)) {
|
*pErr = -2;
|
return;
|
}
|
|
dataLen -= 8;
|
pLocalIEParam->hdr.Length = dataLen;
|
MRVL_AES_MEMCPY(data, aesResult, dataLen);
|
|
}
|
#endif
|
#ifdef RC4
|
|
void
|
MRVL_Rc4Cryption(void *priv, MRVL_ENDECRYPT_t *crypt, int *pErr)
|
{
|
host_MRVL_AES_CRYPT_t *pLocal = NULL;
|
MrvlIEAesCrypt_t *pLocalIEParam = NULL;
|
UINT8 *key = NULL;
|
UINT8 *keyIV = NULL;
|
UINT8 *data = NULL;
|
UINT32 dataLen = 0;
|
|
if ((NULL == pErr) || (NULL == crypt)) {
|
*pErr = -1;
|
return;
|
}
|
|
*pErr = 0;
|
|
/* since RC4 encrypt/decrypt are the same */
|
if ((CRYPT_DECRYPT != crypt->enDeAction) &&
|
(CRYPT_ENCRYPT != crypt->enDeAction)) {
|
*pErr = -2;
|
return;
|
}
|
|
pLocal = (host_MRVL_AES_CRYPT_t *) (crypt->pData);
|
pLocalIEParam = (MrvlIEAesCrypt_t *)&(pLocal->aesTlv);
|
|
key = (UINT8 *)(pLocal->key);
|
data = (UINT8 *)(pLocalIEParam->payload);
|
keyIV = (UINT8 *)(pLocal->keyIV);
|
dataLen = pLocalIEParam->hdr.Length;
|
|
RC4_Encrypt(priv, key, keyIV, pLocal->keyIVLen, data, dataLen, 0);
|
|
return;
|
}
|
#endif /* RC4 */
|