|
|
|
@@ -26,10 +26,8 @@
|
|
|
|
|
|
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
|
|
|
|
|
|
|
|
#ifndef NO_AES
|
|
|
|
|
#if !defined(NO_AES) && defined(WOLFSSL_TI_CRYPT)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(WOLFSSL_TI_CRYPT)
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
@@ -37,6 +35,13 @@
|
|
|
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
|
|
|
#include <wolfssl/wolfcrypt/port/ti/ti-ccm.h>
|
|
|
|
|
|
|
|
|
|
#ifdef NO_INLINE
|
|
|
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
|
|
|
#else
|
|
|
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
|
|
|
#include <wolfcrypt/src/misc.c>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "inc/hw_aes.h"
|
|
|
|
|
#include "inc/hw_memmap.h"
|
|
|
|
|
#include "inc/hw_ints.h"
|
|
|
|
@@ -45,6 +50,13 @@
|
|
|
|
|
#include "driverlib/rom_map.h"
|
|
|
|
|
#include "driverlib/rom.h"
|
|
|
|
|
|
|
|
|
|
#define AES_CFG_MODE_CTR_NOCTR (AES_CFG_MODE_CTR + 100)
|
|
|
|
|
#define IS_ALIGN16(p) (((unsigned int)(p) & 0xf) == 0)
|
|
|
|
|
#define ROUNDUP_16(n) ((n+15) & 0xfffffff0)
|
|
|
|
|
#ifndef TI_BUFFSIZE
|
|
|
|
|
#define TI_BUFFSIZE 1024
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int AesSetIV(Aes* aes, const byte* iv)
|
|
|
|
|
{
|
|
|
|
|
if (aes == NULL)
|
|
|
|
@@ -58,43 +70,87 @@ static int AesSetIV(Aes* aes, const byte* iv)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv,
|
|
|
|
|
int dir)
|
|
|
|
|
int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, int dir)
|
|
|
|
|
{
|
|
|
|
|
if(!wolfSSL_TI_CCMInit())return 1 ;
|
|
|
|
|
if ((aes == NULL) || (key == NULL) || (iv == NULL))
|
|
|
|
|
if (!wolfSSL_TI_CCMInit())
|
|
|
|
|
return 1;
|
|
|
|
|
if ((aes == NULL) || (key == NULL))
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
if (!((dir == AES_ENCRYPTION) || (dir == AES_DECRYPTION)))
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
|
|
|
|
|
switch (len) {
|
|
|
|
|
case 16: aes->keylen = AES_CFG_KEY_SIZE_128BIT ; break ;
|
|
|
|
|
case 24: aes->keylen = AES_CFG_KEY_SIZE_192BIT ; break ;
|
|
|
|
|
case 32: aes->keylen = AES_CFG_KEY_SIZE_256BIT ; break ;
|
|
|
|
|
default: return BAD_FUNC_ARG;
|
|
|
|
|
#ifdef WOLFSSL_AES_128
|
|
|
|
|
case 16:
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WOLFSSL_AES_192
|
|
|
|
|
case 24:
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WOLFSSL_AES_256
|
|
|
|
|
case 32:
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
default:
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
aes->keylen = len;
|
|
|
|
|
aes->rounds = len / 4 + 6;
|
|
|
|
|
|
|
|
|
|
XMEMCPY(aes->key, key, len);
|
|
|
|
|
#ifdef WOLFSSL_AES_COUNTER
|
|
|
|
|
aes->left = 0;
|
|
|
|
|
#endif /* WOLFSSL_AES_COUNTER */
|
|
|
|
|
#endif
|
|
|
|
|
return AesSetIV(aes, iv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define AES_CFG_MODE_CTR_NOCTR AES_CFG_MODE_CTR+100
|
|
|
|
|
#define IS_ALIGN16(p) (((unsigned int)(p)&0xf) == 0)
|
|
|
|
|
|
|
|
|
|
static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode)
|
|
|
|
|
int wc_AesGetKeySize(Aes* aes, word32* keySize)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (aes == NULL || keySize == NULL) {
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (aes->rounds) {
|
|
|
|
|
#ifdef WOLFSSL_AES_128
|
|
|
|
|
case 10:
|
|
|
|
|
*keySize = 16;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WOLFSSL_AES_192
|
|
|
|
|
case 12:
|
|
|
|
|
*keySize = 24;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WOLFSSL_AES_256
|
|
|
|
|
case 14:
|
|
|
|
|
*keySize = 32;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
default:
|
|
|
|
|
*keySize = 0;
|
|
|
|
|
ret = BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
word32 dir, word32 mode)
|
|
|
|
|
{
|
|
|
|
|
/* Processed aligned chunk to HW AES */
|
|
|
|
|
wolfSSL_TI_lockCCM();
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen | dir |
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen-8 | dir |
|
|
|
|
|
(mode == AES_CFG_MODE_CTR_NOCTR ? AES_CFG_MODE_CTR : mode)));
|
|
|
|
|
ROM_AESIVSet(AES_BASE, (uint32_t *)aes->reg);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, (uint32_t *)aes->key, aes->keylen);
|
|
|
|
|
if((dir == AES_CFG_DIR_DECRYPT)&& (mode == AES_CFG_MODE_CBC))
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, (uint32_t *)aes->key, aes->keylen-8);
|
|
|
|
|
if (dir == AES_CFG_DIR_DECRYPT && mode == AES_CFG_MODE_CBC) {
|
|
|
|
|
/* if input and output same will overwrite input iv */
|
|
|
|
|
XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
|
|
|
|
|
}
|
|
|
|
|
ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz);
|
|
|
|
|
wolfSSL_TI_unlockCCM();
|
|
|
|
|
|
|
|
|
@@ -117,14 +173,14 @@ static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 di
|
|
|
|
|
} while ((int)sz > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0 ;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode)
|
|
|
|
|
static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
word32 dir, word32 mode)
|
|
|
|
|
{
|
|
|
|
|
const byte *in_p; byte *out_p;
|
|
|
|
|
word32 size;
|
|
|
|
|
#define TI_BUFFSIZE 1024
|
|
|
|
|
byte buff[TI_BUFFSIZE];
|
|
|
|
|
|
|
|
|
|
if ((aes == NULL) || (in == NULL) || (out == NULL))
|
|
|
|
@@ -155,18 +211,18 @@ static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, word32 di
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
{
|
|
|
|
|
return AesProcess(aes, out, in, sz, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
{
|
|
|
|
|
return AesProcess(aes, out, in, sz, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef WOLFSSL_AES_COUNTER
|
|
|
|
|
WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
{
|
|
|
|
|
char out_block[AES_BLOCK_SIZE];
|
|
|
|
|
int odd;
|
|
|
|
@@ -195,7 +251,7 @@ WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
out+= odd;
|
|
|
|
|
sz -= odd;
|
|
|
|
|
}
|
|
|
|
|
odd = sz % AES_BLOCK_SIZE ; /* if there is tail flagment */
|
|
|
|
|
odd = sz % AES_BLOCK_SIZE; /* if there is tail fragment */
|
|
|
|
|
if (sz / AES_BLOCK_SIZE) {
|
|
|
|
|
even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE;
|
|
|
|
|
ret = AesProcess(aes, out, in, even, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CTR);
|
|
|
|
@@ -218,28 +274,41 @@ WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#endif /* WOLFSSL_AES_COUNTER */
|
|
|
|
|
|
|
|
|
|
/* AES-DIRECT */
|
|
|
|
|
#if defined(WOLFSSL_AES_DIRECT)
|
|
|
|
|
WOLFSSL_API int wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
|
|
|
|
|
int wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
|
|
|
|
|
{
|
|
|
|
|
return AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_ENCRYPT, AES_CFG_MODE_CBC) ;
|
|
|
|
|
return AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_ENCRYPT,
|
|
|
|
|
AES_CFG_MODE_CBC);
|
|
|
|
|
}
|
|
|
|
|
WOLFSSL_API int wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
|
|
|
|
|
int wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
|
|
|
|
|
{
|
|
|
|
|
return AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_DECRYPT, AES_CFG_MODE_CBC) ;
|
|
|
|
|
return AesProcess(aes, out, in, AES_BLOCK_SIZE, AES_CFG_DIR_DECRYPT,
|
|
|
|
|
AES_CFG_MODE_CBC);
|
|
|
|
|
}
|
|
|
|
|
WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
|
|
|
|
|
const byte* iv, int dir)
|
|
|
|
|
int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, const byte* iv,
|
|
|
|
|
int dir)
|
|
|
|
|
{
|
|
|
|
|
return(wc_AesSetKey(aes, key, len, iv, dir)) ;
|
|
|
|
|
return wc_AesSetKey(aes, key, len, iv, dir);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#endif /* WOLFSSL_AES_DIRECT */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
|
|
|
|
|
|
|
|
|
|
#ifndef NO_RNG
|
|
|
|
|
static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = (int)ctrSz - 1; i >= 0; i--) {
|
|
|
|
|
if (++ctr[i])
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int AesAuthSetKey(Aes* aes, const byte* key, word32 keySz)
|
|
|
|
|
{
|
|
|
|
|
byte nonce[AES_BLOCK_SIZE];
|
|
|
|
@@ -257,12 +326,11 @@ static int AesAuthSetKey(Aes* aes, const byte* key, word32 keySz)
|
|
|
|
|
static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
const byte* nonce, word32 nonceSz,
|
|
|
|
|
const byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz, word32 *M, word32 *L)
|
|
|
|
|
word32 *M, word32 *L)
|
|
|
|
|
{
|
|
|
|
|
(void) authInSz ;
|
|
|
|
|
if((aes == NULL)||(nonce == NULL)||(authTag== NULL)||(authIn == NULL))
|
|
|
|
|
if (aes == NULL || nonce == NULL || authTag == NULL)
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
if((inSz != 0) && ((out == NULL)||(in == NULL)))
|
|
|
|
|
if (inSz != 0 && (out == NULL || in == NULL))
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
|
|
|
|
|
switch (authTagSz) {
|
|
|
|
@@ -307,8 +375,9 @@ static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int mode) {
|
|
|
|
|
|
|
|
|
|
static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L,
|
|
|
|
|
int mode)
|
|
|
|
|
{
|
|
|
|
|
if (mode == AES_CFG_MODE_CCM) {
|
|
|
|
|
XMEMSET(aes->reg, 0, 16);
|
|
|
|
|
switch (L) {
|
|
|
|
@@ -330,91 +399,156 @@ static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int
|
|
|
|
|
aes->reg[0] = 0x0; break;
|
|
|
|
|
}
|
|
|
|
|
XMEMCPY(((byte*)aes->reg)+1, nonce, len);
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else { /* GCM */
|
|
|
|
|
if (len == GCM_NONCE_MID_SZ) {
|
|
|
|
|
byte *b = (byte*)aes->reg;
|
|
|
|
|
XMEMSET(aes->reg, 0, AES_BLOCK_SIZE);
|
|
|
|
|
if (nonce != NULL)
|
|
|
|
|
XMEMCPY(aes->reg, nonce, len);
|
|
|
|
|
b[AES_BLOCK_SIZE-4] = 0;
|
|
|
|
|
b[AES_BLOCK_SIZE-3] = 0;
|
|
|
|
|
b[AES_BLOCK_SIZE-2] = 0;
|
|
|
|
|
b[AES_BLOCK_SIZE-1] = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
word32 zeros[AES_BLOCK_SIZE/sizeof(word32)];
|
|
|
|
|
word32 subkey[AES_BLOCK_SIZE/sizeof(word32)];
|
|
|
|
|
word32 nonce_padded[AES_BLOCK_SIZE/sizeof(word32)];
|
|
|
|
|
word32 i;
|
|
|
|
|
|
|
|
|
|
XMEMSET(zeros, 0, sizeof(zeros)); /* init to zero */
|
|
|
|
|
|
|
|
|
|
wolfSSL_TI_lockCCM();
|
|
|
|
|
/* Perform a basic GHASH operation with the hashsubkey and IV */
|
|
|
|
|
/* get subkey */
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen-8) | AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_ECB);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, (aes->keylen-8));
|
|
|
|
|
ROM_AESDataProcess(AES_BASE, zeros, subkey, sizeof zeros);
|
|
|
|
|
|
|
|
|
|
/* GHASH */
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, AES_CFG_KEY_SIZE_128BIT | AES_CFG_MODE_GCM_HLY0ZERO);
|
|
|
|
|
ROM_AESKey2Set(AES_BASE, subkey, AES_CFG_KEY_SIZE_128BIT);
|
|
|
|
|
|
|
|
|
|
ROM_AESLengthSet(AES_BASE, len);
|
|
|
|
|
ROM_AESAuthLengthSet(AES_BASE, 0);
|
|
|
|
|
|
|
|
|
|
/* copy nonce */
|
|
|
|
|
for (i = 0; i < len; i += AES_BLOCK_SIZE) {
|
|
|
|
|
word32 nonceSz = len - i;
|
|
|
|
|
if (nonceSz > AES_BLOCK_SIZE)
|
|
|
|
|
nonceSz = AES_BLOCK_SIZE;
|
|
|
|
|
XMEMSET(nonce_padded, 0, sizeof(nonce_padded));
|
|
|
|
|
XMEMCPY(nonce_padded, (word32*)(nonce + i), nonceSz);
|
|
|
|
|
ROM_AESDataWrite(AES_BASE, nonce_padded);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define RoundUp16(n) ((n+15)&0xfffffff0)
|
|
|
|
|
#define FREE_ALL \
|
|
|
|
|
if(in_save) XFREE(in_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\
|
|
|
|
|
if(out_save) XFREE(out_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\
|
|
|
|
|
if(authIn_save)XFREE(authIn_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);\
|
|
|
|
|
if(nonce_save) XFREE(nonce_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
ROM_AESTagRead(AES_BASE, aes->reg);
|
|
|
|
|
wolfSSL_TI_unlockCCM();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
const byte* nonce, word32 nonceSz,
|
|
|
|
|
byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz, int mode)
|
|
|
|
|
{
|
|
|
|
|
word32 M, L ;
|
|
|
|
|
byte *in_a, *in_save ;
|
|
|
|
|
byte *out_a, *out_save ;
|
|
|
|
|
byte *authIn_a, *authIn_save ;
|
|
|
|
|
byte *nonce_a, *nonce_save ;
|
|
|
|
|
word32 tmpTag[4] ;
|
|
|
|
|
int ret;
|
|
|
|
|
word32 M, L;
|
|
|
|
|
byte *in_a, *in_save = NULL;
|
|
|
|
|
byte *out_a, *out_save = NULL;
|
|
|
|
|
byte *authIn_a, *authIn_save = NULL;
|
|
|
|
|
word32 tmpTag[AES_BLOCK_SIZE/sizeof(word32)];
|
|
|
|
|
|
|
|
|
|
if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L)
|
|
|
|
|
== BAD_FUNC_ARG)return BAD_FUNC_ARG ;
|
|
|
|
|
ret = AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag,
|
|
|
|
|
authTagSz, &M, &L);
|
|
|
|
|
if (ret == BAD_FUNC_ARG) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 16 byte padding */
|
|
|
|
|
in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ;
|
|
|
|
|
if((inSz%16)==0){
|
|
|
|
|
AesAuthSetIv(aes, nonce, nonceSz, L, mode);
|
|
|
|
|
|
|
|
|
|
if (inSz == 0 && authInSz == 0) {
|
|
|
|
|
/* This is a special case that cannot use the GCM mode because the
|
|
|
|
|
* data and AAD lengths are both zero. The work around is to perform
|
|
|
|
|
* an ECB encryption on IV. */
|
|
|
|
|
wolfSSL_TI_lockCCM();
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen-8) | AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_ECB);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, (aes->keylen-8));
|
|
|
|
|
ROM_AESDataProcess(AES_BASE, aes->reg, tmpTag, AES_BLOCK_SIZE);
|
|
|
|
|
wolfSSL_TI_unlockCCM();
|
|
|
|
|
XMEMCPY(authTag, tmpTag, authTagSz);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make sure all pointers are 16 byte aligned */
|
|
|
|
|
if (IS_ALIGN16(inSz)) {
|
|
|
|
|
in_save = NULL; in_a = (byte*)in;
|
|
|
|
|
out_save = NULL; out_a = out;
|
|
|
|
|
} else {
|
|
|
|
|
if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E ; }
|
|
|
|
|
in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
in_save = XMALLOC(ROUNDUP_16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (in_save == NULL) { ret = MEMORY_E; goto exit; }
|
|
|
|
|
in_a = in_save;
|
|
|
|
|
XMEMSET(in_a, 0, ROUNDUP_16(inSz));
|
|
|
|
|
XMEMCPY(in_a, in, inSz);
|
|
|
|
|
|
|
|
|
|
if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E ; }
|
|
|
|
|
out_save = XMALLOC(ROUNDUP_16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (out_save == NULL) { ret = MEMORY_E; goto exit; }
|
|
|
|
|
out_a = out_save;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((authInSz%16)==0){
|
|
|
|
|
if (IS_ALIGN16(authInSz)) {
|
|
|
|
|
authIn_save = NULL; authIn_a = (byte*)authIn;
|
|
|
|
|
} else {
|
|
|
|
|
if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E ; }
|
|
|
|
|
authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
authIn_save = XMALLOC(ROUNDUP_16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (authIn_save == NULL) { ret = MEMORY_E; goto exit; }
|
|
|
|
|
|
|
|
|
|
authIn_a = authIn_save;
|
|
|
|
|
XMEMSET(authIn_a, 0, ROUNDUP_16(authInSz));
|
|
|
|
|
XMEMCPY(authIn_a, authIn, authInSz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((nonceSz%16)==0){
|
|
|
|
|
nonce_save = NULL ; nonce_a = (byte *)nonce ;
|
|
|
|
|
} else {
|
|
|
|
|
if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E; }
|
|
|
|
|
nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do aes-ccm */
|
|
|
|
|
AesAuthSetIv(aes, nonce, nonceSz, L, mode) ;
|
|
|
|
|
/* Do AES-CCM/GCM Cipher with Auth */
|
|
|
|
|
wolfSSL_TI_lockCCM();
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_ENCRYPT |
|
|
|
|
|
ROM_AESConfigSet(AES_BASE,
|
|
|
|
|
(aes->keylen-8 |
|
|
|
|
|
AES_CFG_DIR_ENCRYPT |
|
|
|
|
|
AES_CFG_CTR_WIDTH_128 |
|
|
|
|
|
mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ;
|
|
|
|
|
mode |
|
|
|
|
|
((mode == AES_CFG_MODE_CCM) ? (L | M) : 0 ))
|
|
|
|
|
);
|
|
|
|
|
ROM_AESIVSet(AES_BASE, aes->reg);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen);
|
|
|
|
|
ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz,
|
|
|
|
|
(unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen-8);
|
|
|
|
|
|
|
|
|
|
ret = ROM_AESDataProcessAuth(AES_BASE,
|
|
|
|
|
(unsigned int*)in_a, (unsigned int*)out_a, inSz,
|
|
|
|
|
(unsigned int*)authIn_a, authInSz,
|
|
|
|
|
(unsigned int*)tmpTag);
|
|
|
|
|
wolfSSL_TI_unlockCCM();
|
|
|
|
|
|
|
|
|
|
if (ret == false) {
|
|
|
|
|
XMEMSET(out, 0, inSz);
|
|
|
|
|
XMEMSET(authTag, 0, authTagSz);
|
|
|
|
|
} else {
|
|
|
|
|
ret = AES_GCM_AUTH_E;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
XMEMCPY(out, out_a, inSz);
|
|
|
|
|
XMEMCPY(authTag, tmpTag, authTagSz);
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FREE_ALL;
|
|
|
|
|
return 0 ;
|
|
|
|
|
exit:
|
|
|
|
|
if (in_save) XFREE(in_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (out_save) XFREE(out_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (authIn_save)XFREE(authIn_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
@@ -422,78 +556,110 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
const byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz, int mode)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
word32 M, L;
|
|
|
|
|
byte *in_a, *in_save ;
|
|
|
|
|
byte *out_a, *out_save ;
|
|
|
|
|
byte *authIn_a, *authIn_save ;
|
|
|
|
|
byte *nonce_a, *nonce_save ;
|
|
|
|
|
word32 tmpTag[4] ;
|
|
|
|
|
bool ret ;
|
|
|
|
|
byte *in_a, *in_save = NULL;
|
|
|
|
|
byte *out_a, *out_save = NULL;
|
|
|
|
|
byte *authIn_a, *authIn_save = NULL;
|
|
|
|
|
word32 tmpTag[AES_BLOCK_SIZE/sizeof(word32)];
|
|
|
|
|
|
|
|
|
|
if(AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz, &M, &L)
|
|
|
|
|
== BAD_FUNC_ARG)return BAD_FUNC_ARG ;
|
|
|
|
|
ret = AesAuthArgCheck(aes, out, in, inSz, nonce, nonceSz, authTag,
|
|
|
|
|
authTagSz, &M, &L);
|
|
|
|
|
if (ret == BAD_FUNC_ARG) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 16 byte padding */
|
|
|
|
|
in_save = NULL ; out_save = NULL ; authIn_save = NULL ; nonce_save = NULL ;
|
|
|
|
|
if((inSz%16)==0){
|
|
|
|
|
AesAuthSetIv(aes, nonce, nonceSz, L, mode);
|
|
|
|
|
|
|
|
|
|
if (inSz == 0 && authInSz == 0) {
|
|
|
|
|
/* This is a special case that cannot use the GCM mode because the
|
|
|
|
|
* data and AAD lengths are both zero. The work around is to perform
|
|
|
|
|
* an ECB encryption on IV. */
|
|
|
|
|
wolfSSL_TI_lockCCM();
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen-8) | AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_ECB);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, (aes->keylen-8));
|
|
|
|
|
ROM_AESDataProcess(AES_BASE, aes->reg, tmpTag, AES_BLOCK_SIZE);
|
|
|
|
|
wolfSSL_TI_unlockCCM();
|
|
|
|
|
|
|
|
|
|
if (XMEMCMP(authTag, tmpTag, authTagSz) != 0) {
|
|
|
|
|
ret = AES_GCM_AUTH_E;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make sure all pointers are 16 byte aligned */
|
|
|
|
|
if (IS_ALIGN16(inSz)) {
|
|
|
|
|
in_save = NULL; in_a = (byte*)in;
|
|
|
|
|
out_save = NULL; out_a = out;
|
|
|
|
|
} else {
|
|
|
|
|
if((in_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E;}
|
|
|
|
|
in_a = in_save ; XMEMSET(in_a, 0, RoundUp16(inSz)) ; XMEMCPY(in_a, in, inSz) ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
in_save = XMALLOC(ROUNDUP_16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (in_save == NULL) { ret = MEMORY_E; goto exit; }
|
|
|
|
|
in_a = in_save;
|
|
|
|
|
XMEMSET(in_a, 0, ROUNDUP_16(inSz));
|
|
|
|
|
XMEMCPY(in_a, in, inSz);
|
|
|
|
|
|
|
|
|
|
if((out_save = XMALLOC(RoundUp16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E;}
|
|
|
|
|
out_save = XMALLOC(ROUNDUP_16(inSz), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (out_save == NULL) { ret = MEMORY_E; goto exit; }
|
|
|
|
|
out_a = out_save;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((authInSz%16)==0){
|
|
|
|
|
if (IS_ALIGN16(authInSz)) {
|
|
|
|
|
authIn_save = NULL; authIn_a = (byte*)authIn;
|
|
|
|
|
} else {
|
|
|
|
|
if((authIn_save = XMALLOC(RoundUp16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E; }
|
|
|
|
|
authIn_a = authIn_save ; XMEMSET(authIn_a, 0, RoundUp16(authInSz)) ; XMEMCPY(authIn_a, authIn, authInSz) ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
authIn_save = XMALLOC(ROUNDUP_16(authInSz), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (authIn_save == NULL) { ret = MEMORY_E; goto exit; }
|
|
|
|
|
|
|
|
|
|
authIn_a = authIn_save;
|
|
|
|
|
XMEMSET(authIn_a, 0, ROUNDUP_16(authInSz));
|
|
|
|
|
XMEMCPY(authIn_a, authIn, authInSz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((nonceSz%16)==0){
|
|
|
|
|
nonce_save = NULL ; nonce_a = (byte *)nonce ;
|
|
|
|
|
} else {
|
|
|
|
|
if((nonce_save = XMALLOC(RoundUp16(nonceSz), NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL){
|
|
|
|
|
FREE_ALL; return MEMORY_E; }
|
|
|
|
|
nonce_a = nonce_save ; XMEMSET(nonce_a, 0, RoundUp16(nonceSz)) ; XMEMCPY(nonce_a, nonce, nonceSz) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do aes-ccm */
|
|
|
|
|
AesAuthSetIv(aes, nonce, nonceSz, L, mode) ;
|
|
|
|
|
/* Do AES-CCM/GCM Cipher with Auth */
|
|
|
|
|
wolfSSL_TI_lockCCM();
|
|
|
|
|
ROM_AESReset(AES_BASE);
|
|
|
|
|
ROM_AESConfigSet(AES_BASE, (aes->keylen | AES_CFG_DIR_DECRYPT |
|
|
|
|
|
ROM_AESConfigSet(AES_BASE,
|
|
|
|
|
(aes->keylen-8 |
|
|
|
|
|
AES_CFG_DIR_DECRYPT |
|
|
|
|
|
AES_CFG_CTR_WIDTH_128 |
|
|
|
|
|
mode | ((mode== AES_CFG_MODE_CCM) ? (L | M) : 0 ))) ;
|
|
|
|
|
mode |
|
|
|
|
|
((mode == AES_CFG_MODE_CCM) ? (L | M) : 0 ))
|
|
|
|
|
);
|
|
|
|
|
ROM_AESIVSet(AES_BASE, aes->reg);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen);
|
|
|
|
|
ret = ROM_AESDataProcessAuth(AES_BASE, (unsigned int*)in_a, (unsigned int *)out_a, inSz,
|
|
|
|
|
(unsigned int*)authIn_a, authInSz, (unsigned int *)tmpTag);
|
|
|
|
|
ROM_AESKey1Set(AES_BASE, aes->key, aes->keylen-8);
|
|
|
|
|
ret = ROM_AESDataProcessAuth(AES_BASE,
|
|
|
|
|
(unsigned int*)in_a, (unsigned int*)out_a, inSz,
|
|
|
|
|
(unsigned int*)authIn_a, authInSz,
|
|
|
|
|
(unsigned int*)tmpTag);
|
|
|
|
|
wolfSSL_TI_unlockCCM();
|
|
|
|
|
|
|
|
|
|
if ((ret == false) || (XMEMCMP(authTag, tmpTag, authTagSz) != 0)) {
|
|
|
|
|
XMEMSET(out, 0, inSz);
|
|
|
|
|
ret = false ;
|
|
|
|
|
} else {
|
|
|
|
|
ret = AES_GCM_AUTH_E;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
XMEMCPY(out, out_a, inSz);
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FREE_ALL ;
|
|
|
|
|
return ret==true ? 0 : 1 ;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
exit:
|
|
|
|
|
if (in_save) XFREE(in_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (out_save) XFREE(out_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
if (authIn_save)XFREE(authIn_save, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_AESGCM || HAVE_AESCCM */
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_AESGCM
|
|
|
|
|
WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
|
|
|
|
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
|
|
|
|
|
{
|
|
|
|
|
return AesAuthSetKey(aes, key, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
const byte* iv, word32 ivSz,
|
|
|
|
|
byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz)
|
|
|
|
@@ -504,7 +670,9 @@ WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz
|
|
|
|
|
return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz,
|
|
|
|
|
authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC);
|
|
|
|
|
}
|
|
|
|
|
WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
|
|
|
|
|
int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
const byte* iv, word32 ivSz,
|
|
|
|
|
const byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz)
|
|
|
|
@@ -512,13 +680,14 @@ WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz
|
|
|
|
|
return AesAuthDecrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz,
|
|
|
|
|
authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
|
|
|
|
|
int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len)
|
|
|
|
|
{
|
|
|
|
|
return AesAuthSetKey(&gmac->aes, key, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
|
|
|
|
|
int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
|
|
|
|
|
const byte* authIn, word32 authInSz,
|
|
|
|
|
byte* authTag, word32 authTagSz)
|
|
|
|
|
{
|
|
|
|
@@ -526,15 +695,188 @@ WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz,
|
|
|
|
|
authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NO_RNG
|
|
|
|
|
static WARN_UNUSED_RESULT WC_INLINE int CheckAesGcmIvSize(int ivSz) {
|
|
|
|
|
return (ivSz == GCM_NONCE_MIN_SZ ||
|
|
|
|
|
ivSz == GCM_NONCE_MID_SZ ||
|
|
|
|
|
ivSz == GCM_NONCE_MAX_SZ);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wc_AesGcmSetIV(Aes* aes, word32 ivSz,
|
|
|
|
|
const byte* ivFixed, word32 ivFixedSz,
|
|
|
|
|
WC_RNG* rng)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (aes == NULL || rng == NULL || !CheckAesGcmIvSize((int)ivSz) ||
|
|
|
|
|
(ivFixed == NULL && ivFixedSz != 0) ||
|
|
|
|
|
(ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ)) {
|
|
|
|
|
|
|
|
|
|
ret = BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
byte* iv = (byte*)aes->reg;
|
|
|
|
|
|
|
|
|
|
if (ivFixedSz)
|
|
|
|
|
XMEMCPY(iv, ivFixed, ivFixedSz);
|
|
|
|
|
|
|
|
|
|
ret = wc_RNG_GenerateBlock(rng, iv + ivFixedSz, ivSz - ivFixedSz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
/* If the IV is 96, allow for a 2^64 invocation counter.
|
|
|
|
|
* For any other size for the nonce, limit the invocation
|
|
|
|
|
* counter to 32-bits. (SP 800-38D 8.3) */
|
|
|
|
|
aes->invokeCtr[0] = 0;
|
|
|
|
|
aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF;
|
|
|
|
|
#ifdef WOLFSSL_AESGCM_STREAM
|
|
|
|
|
aes->ctrSet = 1;
|
|
|
|
|
#endif
|
|
|
|
|
aes->nonceSz = ivSz;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
byte* ivOut, word32 ivOutSz,
|
|
|
|
|
byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
|
|
|
|
|
ivOut == NULL || ivOutSz != aes->nonceSz ||
|
|
|
|
|
(authIn == NULL && authInSz != 0)) {
|
|
|
|
|
|
|
|
|
|
ret = BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
aes->invokeCtr[0]++;
|
|
|
|
|
if (aes->invokeCtr[0] == 0) {
|
|
|
|
|
aes->invokeCtr[1]++;
|
|
|
|
|
if (aes->invokeCtr[1] == 0)
|
|
|
|
|
ret = AES_GCM_OVERFLOW_E;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
XMEMCPY(ivOut, aes->reg, ivOutSz);
|
|
|
|
|
ret = wc_AesGcmEncrypt(aes, out, in, sz,
|
|
|
|
|
(byte*)aes->reg, ivOutSz,
|
|
|
|
|
authTag, authTagSz,
|
|
|
|
|
authIn, authInSz);
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
IncCtr((byte*)aes->reg, ivOutSz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz,
|
|
|
|
|
const byte* authIn, word32 authInSz,
|
|
|
|
|
byte* authTag, word32 authTagSz, WC_RNG* rng)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
|
|
Aes *aes = NULL;
|
|
|
|
|
#else
|
|
|
|
|
Aes aes[1];
|
|
|
|
|
#endif
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
|
|
|
|
|
authTag == NULL || authTagSz == 0 || rng == NULL) {
|
|
|
|
|
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
|
|
if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
|
|
|
|
|
DYNAMIC_TYPE_AES)) == NULL)
|
|
|
|
|
return MEMORY_E;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
ret = wc_AesGcmSetKey(aes, key, keySz);
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
ret = wc_AesGcmSetIV(aes, ivSz, NULL, 0, rng);
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
ret = wc_AesGcmEncrypt_ex(aes, NULL, NULL, 0, iv, ivSz,
|
|
|
|
|
authTag, authTagSz, authIn, authInSz);
|
|
|
|
|
wc_AesFree(aes);
|
|
|
|
|
}
|
|
|
|
|
ForceZero(aes, sizeof *aes);
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
|
|
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wc_GmacVerify(const byte* key, word32 keySz,
|
|
|
|
|
const byte* iv, word32 ivSz,
|
|
|
|
|
const byte* authIn, word32 authInSz,
|
|
|
|
|
const byte* authTag, word32 authTagSz)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
#ifdef HAVE_AES_DECRYPT
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
|
|
Aes *aes = NULL;
|
|
|
|
|
#else
|
|
|
|
|
Aes aes[1];
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
|
|
|
|
|
authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) {
|
|
|
|
|
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
|
|
if ((aes = (Aes *)XMALLOC(sizeof *aes, NULL,
|
|
|
|
|
DYNAMIC_TYPE_AES)) == NULL)
|
|
|
|
|
return MEMORY_E;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ret = wc_AesInit(aes, NULL, INVALID_DEVID);
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
ret = wc_AesGcmSetKey(aes, key, keySz);
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
ret = wc_AesGcmDecrypt(aes, NULL, NULL, 0, iv, ivSz,
|
|
|
|
|
authTag, authTagSz, authIn, authInSz);
|
|
|
|
|
wc_AesFree(aes);
|
|
|
|
|
}
|
|
|
|
|
ForceZero(aes, sizeof *aes);
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
|
|
XFREE(aes, NULL, DYNAMIC_TYPE_AES);
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
(void)key;
|
|
|
|
|
(void)keySz;
|
|
|
|
|
(void)iv;
|
|
|
|
|
(void)ivSz;
|
|
|
|
|
(void)authIn;
|
|
|
|
|
(void)authInSz;
|
|
|
|
|
(void)authTag;
|
|
|
|
|
(void)authTagSz;
|
|
|
|
|
ret = NOT_COMPILED_IN;
|
|
|
|
|
#endif
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
#endif /* !NO_RNG */
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_AESGCM */
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_AESCCM
|
|
|
|
|
WOLFSSL_API int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
|
|
|
|
|
int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz)
|
|
|
|
|
{
|
|
|
|
|
return AesAuthSetKey(aes, key, keySz);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
const byte* nonce, word32 nonceSz,
|
|
|
|
|
byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz)
|
|
|
|
@@ -543,7 +885,7 @@ WOLFSSL_API int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inS
|
|
|
|
|
authIn, authInSz, AES_CFG_MODE_CCM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz,
|
|
|
|
|
const byte* nonce, word32 nonceSz,
|
|
|
|
|
const byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz)
|
|
|
|
@@ -551,9 +893,76 @@ WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inS
|
|
|
|
|
return AesAuthDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz,
|
|
|
|
|
authIn, authInSz, AES_CFG_MODE_CCM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* abstract functions that call lower level AESCCM functions */
|
|
|
|
|
#ifndef WC_NO_RNG
|
|
|
|
|
|
|
|
|
|
int wc_AesCcmSetNonce(Aes* aes, const byte* nonce, word32 nonceSz)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (aes == NULL || nonce == NULL ||
|
|
|
|
|
nonceSz < CCM_NONCE_MIN_SZ || nonceSz > CCM_NONCE_MAX_SZ) {
|
|
|
|
|
|
|
|
|
|
ret = BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
XMEMCPY(aes->reg, nonce, nonceSz);
|
|
|
|
|
aes->nonceSz = nonceSz;
|
|
|
|
|
|
|
|
|
|
/* Invocation counter should be 2^61 */
|
|
|
|
|
aes->invokeCtr[0] = 0;
|
|
|
|
|
aes->invokeCtr[1] = 0xE0000000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz,
|
|
|
|
|
byte* ivOut, word32 ivOutSz,
|
|
|
|
|
byte* authTag, word32 authTagSz,
|
|
|
|
|
const byte* authIn, word32 authInSz)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
if (aes == NULL || out == NULL ||
|
|
|
|
|
(in == NULL && sz != 0) ||
|
|
|
|
|
ivOut == NULL ||
|
|
|
|
|
(authIn == NULL && authInSz != 0) ||
|
|
|
|
|
(ivOutSz != aes->nonceSz)) {
|
|
|
|
|
|
|
|
|
|
ret = BAD_FUNC_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
aes->invokeCtr[0]++;
|
|
|
|
|
if (aes->invokeCtr[0] == 0) {
|
|
|
|
|
aes->invokeCtr[1]++;
|
|
|
|
|
if (aes->invokeCtr[1] == 0)
|
|
|
|
|
ret = AES_CCM_OVERFLOW_E;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
ret = wc_AesCcmEncrypt(aes, out, in, sz,
|
|
|
|
|
(byte*)aes->reg, aes->nonceSz,
|
|
|
|
|
authTag, authTagSz,
|
|
|
|
|
authIn, authInSz);
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
XMEMCPY(ivOut, aes->reg, aes->nonceSz);
|
|
|
|
|
IncCtr((byte*)aes->reg, aes->nonceSz);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
#endif /* !WC_NO_RNG */
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_AESCCM */
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId)
|
|
|
|
|
int wc_AesInit(Aes* aes, void* heap, int devId)
|
|
|
|
|
{
|
|
|
|
|
if (aes == NULL)
|
|
|
|
|
return BAD_FUNC_ARG;
|
|
|
|
@@ -564,14 +973,9 @@ WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WOLFSSL_API void wc_AesFree(Aes* aes)
|
|
|
|
|
void wc_AesFree(Aes* aes)
|
|
|
|
|
{
|
|
|
|
|
(void)aes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* WOLFSSL_TI_CRYPT */
|
|
|
|
|
|
|
|
|
|
#endif /* NO_AES */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* !NO_AES && WOLFSSL_TI_CRYPT */
|
|
|
|
|