Merge pull request #1968 from dgarske/fixes_stm32cube_aes

Fixes for STM32 AES GCM crypto hardware acceleration
This commit is contained in:
toddouska
2018-12-12 14:52:35 -08:00
committed by GitHub
4 changed files with 184 additions and 135 deletions

View File

@ -1873,7 +1873,9 @@ static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz,
{ {
int ret = 0, i, count = 0, times, pending = 0; int ret = 0, i, count = 0, times, pending = 0;
Aes enc[BENCH_MAX_PENDING]; Aes enc[BENCH_MAX_PENDING];
#ifdef HAVE_AES_DECRYPT
Aes dec[BENCH_MAX_PENDING]; Aes dec[BENCH_MAX_PENDING];
#endif
double start; double start;
DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT);
@ -1881,14 +1883,17 @@ static void bench_aesgcm_internal(int doAsync, const byte* key, word32 keySz,
/* clear for done cleanup */ /* clear for done cleanup */
XMEMSET(enc, 0, sizeof(enc)); XMEMSET(enc, 0, sizeof(enc));
#ifdef HAVE_AES_DECRYPT
XMEMSET(dec, 0, sizeof(dec));
#endif
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (bench_additional) if (bench_additional)
#endif #endif
{ XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); } XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ);
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (bench_tag) if (bench_tag)
#endif #endif
{ XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); } XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ);
/* init keys */ /* init keys */
for (i = 0; i < BENCH_MAX_PENDING; i++) { for (i = 0; i < BENCH_MAX_PENDING; i++) {
@ -1967,10 +1972,6 @@ exit_aes_gcm:
} while (bench_stats_sym_check(start)); } while (bench_stats_sym_check(start));
exit_aes_gcm_dec: exit_aes_gcm_dec:
bench_stats_sym_finish(decLabel, doAsync, count, bench_size, start, ret); bench_stats_sym_finish(decLabel, doAsync, count, bench_size, start, ret);
for (i = 0; i < BENCH_MAX_PENDING; i++) {
wc_AesFree(&dec[i]);
}
#endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AES_DECRYPT */
(void)decLabel; (void)decLabel;
@ -1980,7 +1981,11 @@ exit:
if (ret < 0) { if (ret < 0) {
printf("bench_aesgcm failed: %d\n", ret); printf("bench_aesgcm failed: %d\n", ret);
} }
#ifdef HAVE_AES_DECRYPT
for (i = 0; i < BENCH_MAX_PENDING; i++) {
wc_AesFree(&dec[i]);
}
#endif
for (i = 0; i < BENCH_MAX_PENDING; i++) { for (i = 0; i < BENCH_MAX_PENDING; i++) {
wc_AesFree(&enc[i]); wc_AesFree(&enc[i]);
} }

View File

@ -421,7 +421,7 @@
/* enable crypto processor */ /* enable crypto processor */
CRYP_Cmd(ENABLE); CRYP_Cmd(ENABLE);
/* wait until decrypt key has been intialized */ /* wait until decrypt key has been initialized */
while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {}
/* set direction and mode */ /* set direction and mode */
@ -2407,6 +2407,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
#else /* STD_PERI_LIB */ #else /* STD_PERI_LIB */
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{ {
int ret;
word32 *iv; word32 *iv;
word32 blocks = (sz / AES_BLOCK_SIZE); word32 blocks = (sz / AES_BLOCK_SIZE);
CRYP_InitTypeDef cryptInit; CRYP_InitTypeDef cryptInit;
@ -2469,12 +2470,13 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
/* disable crypto processor */ /* disable crypto processor */
CRYP_Cmd(DISABLE); CRYP_Cmd(DISABLE);
return 0; return ret;
} }
#ifdef HAVE_AES_DECRYPT #ifdef HAVE_AES_DECRYPT
int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{ {
int ret;
word32 *iv; word32 *iv;
word32 blocks = (sz / AES_BLOCK_SIZE); word32 blocks = (sz / AES_BLOCK_SIZE);
CRYP_InitTypeDef cryptInit; CRYP_InitTypeDef cryptInit;
@ -2548,7 +2550,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
/* disable crypto processor */ /* disable crypto processor */
CRYP_Cmd(DISABLE); CRYP_Cmd(DISABLE);
return 0; return ret;
} }
#endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AES_DECRYPT */
#endif /* WOLFSSL_STM32_CUBEMX */ #endif /* WOLFSSL_STM32_CUBEMX */
@ -3036,7 +3038,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv)
hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CTR; hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CTR;
hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE;
#endif #endif
hcryp.Init.pInitVect = (byte*)aes->reg; hcryp.Init.pInitVect = (uint8_t*)aes->reg;
HAL_CRYP_Init(&hcryp); HAL_CRYP_Init(&hcryp);
#ifdef STM32_CRYPTO_AES_ONLY #ifdef STM32_CRYPTO_AES_ONLY
@ -8177,32 +8179,60 @@ static WC_INLINE int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in,
const byte* authIn, word32 authInSz) const byte* authIn, word32 authInSz)
{ {
int ret; int ret;
word32 keySize;
byte initialCounter[AES_BLOCK_SIZE];
#ifdef WOLFSSL_STM32_CUBEMX #ifdef WOLFSSL_STM32_CUBEMX
CRYP_HandleTypeDef hcryp; CRYP_HandleTypeDef hcryp;
#else #else
byte keyCopy[AES_BLOCK_SIZE * 2]; word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)];
#endif #endif
word32 keySize;
int status = 0; int status = 0;
int outPadSz, authPadSz;
word32 tag[AES_BLOCK_SIZE/sizeof(word32)];
word32 initialCounter[AES_BLOCK_SIZE/sizeof(word32)];
byte* outPadded = NULL;
byte* authInPadded = NULL; byte* authInPadded = NULL;
byte tag[AES_BLOCK_SIZE];
int authPadSz;
ret = wc_AesGetKeySize(aes, &keySize); ret = wc_AesGetKeySize(aes, &keySize);
if (ret != 0) if (ret != 0)
return ret; return ret;
XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); #ifdef WOLFSSL_STM32_CUBEMX
XMEMCPY(initialCounter, iv, ivSz); ret = wc_Stm32_Aes_Init(aes, &hcryp);
initialCounter[AES_BLOCK_SIZE - 1] = STM32_GCM_IV_START; if (ret != 0)
return ret;
#endif
/* pad authIn if it is not a block multiple */ XMEMSET(initialCounter, 0, sizeof(initialCounter));
if ((authInSz % AES_BLOCK_SIZE) != 0) { XMEMCPY(initialCounter, iv, ivSz);
authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; *((byte*)initialCounter + (AES_BLOCK_SIZE - 1)) = STM32_GCM_IV_START;
/* Need to pad the AAD and input cipher text to a full block size since
* CRYP_AES_GCM will assume these are a multiple of AES_BLOCK_SIZE.
* It is okay to pad with zeros because GCM does this before GHASH already.
* See NIST SP 800-38D */
if ((sz % AES_BLOCK_SIZE) != 0 || sz == 0) {
outPadSz = ((sz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
outPadded = (byte*)XMALLOC(outPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (outPadded == NULL) {
return MEMORY_E;
}
XMEMSET(outPadded, 0, outPadSz);
}
else {
outPadSz = sz;
outPadded = out;
}
XMEMCPY(outPadded, in, sz);
if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) {
/* Need to pad the AAD to a full block with zeros. */ /* Need to pad the AAD to a full block with zeros. */
authInPadded = XMALLOC(authPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
authInPadded = (byte*)XMALLOC(authPadSz, aes->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (authInPadded == NULL) { if (authInPadded == NULL) {
if (outPadded != out) {
XFREE(outPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
return MEMORY_E; return MEMORY_E;
} }
XMEMSET(authInPadded, 0, authPadSz); XMEMSET(authInPadded, 0, authPadSz);
@ -8214,11 +8244,7 @@ static WC_INLINE int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in,
#ifdef WOLFSSL_STM32_CUBEMX #ifdef WOLFSSL_STM32_CUBEMX
ret = wc_Stm32_Aes_Init(aes, &hcryp); hcryp.Init.pInitVect = (uint8_t*)initialCounter;
if (ret != 0)
return ret;
hcryp.Init.pInitVect = initialCounter;
hcryp.Init.Header = authInPadded; hcryp.Init.Header = authInPadded;
hcryp.Init.HeaderSize = authInSz; hcryp.Init.HeaderSize = authInSz;
@ -8238,22 +8264,25 @@ static WC_INLINE int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in,
if (status == HAL_OK) { if (status == HAL_OK) {
/* GCM payload phase */ /* GCM payload phase */
hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE; hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE;
status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in, sz, out, STM32_HAL_TIMEOUT); status = HAL_CRYPEx_AES_Auth(&hcryp, outPadded, sz, outPadded,
STM32_HAL_TIMEOUT);
if (status == HAL_OK) { if (status == HAL_OK) {
/* GCM final phase */ /* GCM final phase */
hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE; hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE;
status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT); status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, (byte*)tag,
STM32_HAL_TIMEOUT);
} }
} }
} }
#else #else
HAL_CRYP_Init(&hcryp); HAL_CRYP_Init(&hcryp);
status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in, sz, status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, outPadded, sz,
out, STM32_HAL_TIMEOUT); outPadded, STM32_HAL_TIMEOUT);
/* Compute the authTag */ /* Compute the authTag */
if (status == HAL_OK) { if (status == HAL_OK) {
status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, (byte*)tag,
STM32_HAL_TIMEOUT);
} }
#endif #endif
@ -8262,22 +8291,31 @@ static WC_INLINE int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in,
HAL_CRYP_DeInit(&hcryp); HAL_CRYP_DeInit(&hcryp);
#else /* STD_PERI_LIB */ #else /* STD_PERI_LIB */
ByteReverseWords((word32*)keyCopy, (word32*)aes->key, keySize); ByteReverseWords(keyCopy, (word32*)aes->key, keySize);
status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)initialCounter, status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)initialCounter,
(uint8_t*)keyCopy, keySize * 8, (uint8_t*)keyCopy, keySize * 8,
(uint8_t*)in, sz, (uint8_t*)outPadded, sz,
(uint8_t*)authInPadded,authInSz, (uint8_t*)authInPadded,authInSz,
(uint8_t*)out, tag); (uint8_t*)outPadded, (byte*)tag);
if (status != SUCCESS) if (status != SUCCESS)
ret = AES_GCM_AUTH_E; ret = AES_GCM_AUTH_E;
#endif /* WOLFSSL_STM32_CUBEMX */ #endif /* WOLFSSL_STM32_CUBEMX */
/* authTag may be shorter than AES_BLOCK_SZ, store separately */ if (ret == 0) {
if (ret == 0) /* return authTag */
XMEMCPY(authTag, tag, authTagSz); XMEMCPY(authTag, tag, authTagSz);
/* We only allocate extra memory if authInPadded is not a multiple of AES_BLOCK_SZ */ /* return output if allocated padded used */
if (authInPadded != NULL && authInSz != authPadSz) { if (outPadded != out) {
XMEMCPY(out, outPadded, sz);
}
}
/* Free memory if not a multiple of AES_BLOCK_SZ */
if (outPadded != out) {
XFREE(outPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
if (authInPadded != authIn) {
XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
} }
@ -8321,7 +8359,7 @@ int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
#ifdef WOLFSSL_PIC32MZ_CRYPT #ifdef WOLFSSL_PIC32MZ_CRYPT
if (blocks) { if (blocks) {
/* use intitial IV for PIC32 HW, but don't use it below */ /* use initial IV for PIC32 HW, but don't use it below */
XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE); XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE);
ret = wc_Pic32AesCrypt( ret = wc_Pic32AesCrypt(
@ -8408,21 +8446,8 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
defined(WOLFSSL_STM32F7) || \ defined(WOLFSSL_STM32F7) || \
defined(WOLFSSL_STM32L4)) defined(WOLFSSL_STM32L4))
/* additional argument checks - STM32 HW only supports 12 byte IV */ /* STM32 HW only supports 12 byte IV and 16 byte auth */
if (ivSz != GCM_NONCE_MID_SZ) { if (ivSz == GCM_NONCE_MID_SZ && authInSz == AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
/* STM32 HW AES-GCM requires / assumes inputs are a multiple of block size.
* We can avoid this by zero padding (authIn) AAD, but zero-padded plaintext
* will be encrypted and output incorrectly, causing a bad authTag.
* We will use HW accelerated AES-GCM if plain%AES_BLOCK_SZ==0.
* Otherwise, we will use accelerated AES_CTR for encrypt, and then
* perform GHASH in software.
* See NIST SP 800-38D */
/* Plain text is a multiple of block size, so use HW-Accelerated AES_GCM */
if (sz % AES_BLOCK_SIZE == 0) {
return wc_AesGcmEncrypt_STM32(aes, out, in, sz, iv, ivSz, return wc_AesGcmEncrypt_STM32(aes, out, in, sz, iv, ivSz,
authTag, authTagSz, authIn, authInSz); authTag, authTagSz, authIn, authInSz);
} }
@ -8544,43 +8569,57 @@ static WC_INLINE int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
#ifdef WOLFSSL_STM32_CUBEMX #ifdef WOLFSSL_STM32_CUBEMX
CRYP_HandleTypeDef hcryp; CRYP_HandleTypeDef hcryp;
#else #else
byte keyCopy[AES_BLOCK_SIZE * 2]; word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)];
#endif #endif
int status; word32 keySize;
int inPadSz, authPadSz; int status;
byte tag[AES_BLOCK_SIZE]; int outPadSz, authPadSz;
byte *inPadded = NULL; word32 tag[AES_BLOCK_SIZE/sizeof(word32)];
byte *authInPadded = NULL; word32 initialCounter[AES_BLOCK_SIZE/sizeof(word32)];
byte initialCounter[AES_BLOCK_SIZE]; byte* outPadded = NULL;
byte* authInPadded = NULL;
XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); ret = wc_AesGetKeySize(aes, &keySize);
if (ret != 0)
return ret;
#ifdef WOLFSSL_STM32_CUBEMX
ret = wc_Stm32_Aes_Init(aes, &hcryp);
if (ret != 0)
return ret;
#endif
XMEMSET(initialCounter, 0, sizeof(initialCounter));
XMEMCPY(initialCounter, iv, ivSz); XMEMCPY(initialCounter, iv, ivSz);
initialCounter[AES_BLOCK_SIZE - 1] = STM32_GCM_IV_START; *((byte*)initialCounter + (AES_BLOCK_SIZE - 1)) = STM32_GCM_IV_START;
/* Need to pad the AAD and input cipher text to a full block size since /* Need to pad the AAD and input cipher text to a full block size since
* CRYP_AES_GCM will assume these are a multiple of AES_BLOCK_SIZE. * CRYP_AES_GCM will assume these are a multiple of AES_BLOCK_SIZE.
* It is okay to pad with zeros because GCM does this before GHASH already. * It is okay to pad with zeros because GCM does this before GHASH already.
* See NIST SP 800-38D */ * See NIST SP 800-38D */
if ((sz % AES_BLOCK_SIZE) != 0 || sz == 0) {
if ((sz % AES_BLOCK_SIZE) > 0) { outPadSz = ((sz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
inPadSz = ((sz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; outPadded = (byte*)XMALLOC(outPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
inPadded = XMALLOC(inPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); if (outPadded == NULL) {
if (inPadded == NULL) {
return MEMORY_E; return MEMORY_E;
} }
XMEMSET(inPadded, 0, inPadSz); XMEMSET(outPadded, 0, outPadSz);
XMEMCPY(inPadded, in, sz);
} else {
inPadSz = sz;
inPadded = (byte*)in;
} }
else {
outPadSz = sz;
outPadded = out;
}
XMEMCPY(outPadded, in, sz);
if ((authInSz % AES_BLOCK_SIZE) > 0) { if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) {
/* Need to pad the AAD to a full block with zeros. */
authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
authInPadded = XMALLOC(authPadSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); authInPadded = (byte*)XMALLOC(authPadSz, aes->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (authInPadded == NULL) { if (authInPadded == NULL) {
if (inPadded != NULL && inPadSz != sz) if (outPadded != out) {
XFREE(inPadded , aes->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(outPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
return MEMORY_E; return MEMORY_E;
} }
XMEMSET(authInPadded, 0, authPadSz); XMEMSET(authInPadded, 0, authPadSz);
@ -8591,11 +8630,7 @@ static WC_INLINE int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
} }
#ifdef WOLFSSL_STM32_CUBEMX #ifdef WOLFSSL_STM32_CUBEMX
ret = wc_Stm32_Aes_Init(aes, &hcryp); hcryp.Init.pInitVect = (uint8_t*)initialCounter;
if (ret != 0)
return ret;
hcryp.Init.pInitVect = initialCounter;
hcryp.Init.Header = authInPadded; hcryp.Init.Header = authInPadded;
hcryp.Init.HeaderSize = authInSz; hcryp.Init.HeaderSize = authInSz;
@ -8610,30 +8645,31 @@ static WC_INLINE int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
if (status == HAL_OK) { if (status == HAL_OK) {
/* GCM header phase */ /* GCM header phase */
hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE; hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE;
status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
if (status == HAL_OK) { if (status == HAL_OK) {
/* GCM payload phase */ /* GCM payload phase */
hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE; hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE;
status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)inPadded, sz, inPadded, status = HAL_CRYPEx_AES_Auth(&hcryp, outPadded, sz, outPadded,
STM32_HAL_TIMEOUT); STM32_HAL_TIMEOUT);
if (status == HAL_OK) { if (status == HAL_OK) {
/* GCM final phase */ /* GCM final phase */
hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE; hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE;
status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, (byte*)tag,
STM32_HAL_TIMEOUT); STM32_HAL_TIMEOUT);
} }
} }
} }
#else #else
HAL_CRYP_Init(&hcryp); HAL_CRYP_Init(&hcryp);
/* Use inPadded for output buffer instead of /* Use outPadded for output buffer instead of out so that we don't overflow
* out so that we don't overflow our size. */ * our size. */
status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, (byte*)inPadded, status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, outPadded, sz, outPadded,
sz, inPadded, STM32_HAL_TIMEOUT); STM32_HAL_TIMEOUT);
/* Compute the authTag */ /* Compute the authTag */
if (status == HAL_OK) { if (status == HAL_OK) {
status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, (byte*)tag,
STM32_HAL_TIMEOUT);
} }
#endif #endif
@ -8643,34 +8679,39 @@ static WC_INLINE int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
HAL_CRYP_DeInit(&hcryp); HAL_CRYP_DeInit(&hcryp);
#else /* STD_PERI_LIB */ #else /* STD_PERI_LIB */
ByteReverseWords((word32*)keyCopy, (word32*)aes->key, aes->keylen); ByteReverseWords(keyCopy, (word32*)aes->key, aes->keylen);
/* Input size and auth size need to be the actual sizes, even though /* Input size and auth size need to be the actual sizes, even though
* they are not block aligned, because this length (in bits) is used * they are not block aligned, because this length (in bits) is used
* in the final GHASH. Use inPadded for output buffer instead of * in the final GHASH. Use outPadded for output buffer instead of
* out so that we don't overflow our size. */ * out so that we don't overflow our size. */
status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)initialCounter, status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)initialCounter,
(uint8_t*)keyCopy, keySize * 8, (uint8_t*)keyCopy, keySize * 8,
(uint8_t*)inPadded, sz, (uint8_t*)outPadded, sz,
(uint8_t*)authInPadded,authInSz, (uint8_t*)authInPadded,authInSz,
(uint8_t*)inPadded, tag); (uint8_t*)outPadded, (byte*)tag);
if (status != SUCCESS) if (status != SUCCESS)
ret = AES_GCM_AUTH_E; ret = AES_GCM_AUTH_E;
#endif /* WOLFSSL_STM32_CUBEMX */ #endif /* WOLFSSL_STM32_CUBEMX */
if (ConstantCompare(authTag, tag, authTagSz) != 0) { if (ConstantCompare(authTag, (byte*)tag, authTagSz) != 0) {
ret = AES_GCM_AUTH_E; ret = AES_GCM_AUTH_E;
} }
if (ret == 0) { if (ret == 0) {
/* Only return the decrypted data if authTag success. */ /* return output if allocated padded used */
XMEMCPY(out, inPadded, sz); if (outPadded != out) {
XMEMCPY(out, outPadded, sz);
}
} }
/* only allocate padding buffers if the inputs are not a multiple of block sz */ /* Free memory if not a multiple of AES_BLOCK_SZ */
if (inPadded != NULL && inPadSz != sz) if (outPadded != out) {
XFREE(inPadded , aes->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(outPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (authInPadded != NULL && authPadSz != authInSz) }
if (authInPadded != authIn) {
XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
return ret; return ret;
} }
@ -8723,7 +8764,7 @@ int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz,
#ifdef WOLFSSL_PIC32MZ_CRYPT #ifdef WOLFSSL_PIC32MZ_CRYPT
if (blocks) { if (blocks) {
/* use intitial IV for PIC32 HW, but don't use it below */ /* use initial IV for PIC32 HW, but don't use it below */
XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE); XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE);
ret = wc_Pic32AesCrypt( ret = wc_Pic32AesCrypt(
@ -8807,21 +8848,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
defined(WOLFSSL_STM32F7) || \ defined(WOLFSSL_STM32F7) || \
defined(WOLFSSL_STM32L4)) defined(WOLFSSL_STM32L4))
/* additional argument checks - STM32 HW only supports 12 byte IV */ /* STM32 HW only supports 12 byte IV and 16 byte auth */
if (ivSz != GCM_NONCE_MID_SZ) { if (ivSz == GCM_NONCE_MID_SZ && authInSz == AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
/* STM32 HW AES-GCM requires / assumes inputs are a multiple of block size.
* We can avoid this by zero padding (authIn) AAD, but zero-padded plaintext
* will be encrypted and output incorrectly, causing a bad authTag.
* We will use HW accelerated AES-GCM if plain%AES_BLOCK_SZ==0.
* Otherwise, we will use accelerated AES_CTR for encrypt, and then
* perform GHASH in software.
* See NIST SP 800-38D */
/* Plain text is a multiple of block size, so use HW-Accelerated AES_GCM */
if (sz % AES_BLOCK_SIZE == 0) {
return wc_AesGcmDecrypt_STM32(aes, out, in, sz, iv, ivSz, return wc_AesGcmDecrypt_STM32(aes, out, in, sz, iv, ivSz,
authTag, authTagSz, authIn, authInSz); authTag, authTagSz, authIn, authInSz);
} }
@ -9039,8 +9067,9 @@ int wc_GmacVerify(const byte* key, word32 keySz,
const byte* authIn, word32 authInSz, const byte* authIn, word32 authInSz,
const byte* authTag, word32 authTagSz) const byte* authTag, word32 authTagSz)
{ {
Aes aes;
int ret; int ret;
#ifndef NO_AES_DECRYPT
Aes aes;
if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) ||
authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) { authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) {
@ -9057,7 +9086,17 @@ int wc_GmacVerify(const byte* key, word32 keySz,
wc_AesFree(&aes); wc_AesFree(&aes);
} }
ForceZero(&aes, sizeof(aes)); ForceZero(&aes, sizeof(aes));
#else
(void)key;
(void)keySz;
(void)iv;
(void)ivSz;
(void)authIn;
(void)authInSz;
(void)authTag;
(void)authTagSz;
ret = NOT_COMPILED_IN;
#endif
return ret; return ret;
} }

View File

@ -6133,7 +6133,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) { if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) {
/* make sure event is intialized */ /* make sure event is initialized */
WOLF_EVENT* event = &sigCtx->asyncDev->event; WOLF_EVENT* event = &sigCtx->asyncDev->event;
ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL,
sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN); sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN);

View File

@ -773,7 +773,8 @@ initDefaultName();
printf( "AES256 test passed!\n"); printf( "AES256 test passed!\n");
#endif #endif
#ifdef HAVE_AESGCM #ifdef HAVE_AESGCM
#if !defined(WOLFSSL_AFALG) && !defined(WOLFSSL_DEVCRYPTO) #if !defined(WOLFSSL_AFALG) && !defined(WOLFSSL_DEVCRYPTO) && \
!defined(STM32_CRYPTO)
if ( (ret = aesgcm_test()) != 0) if ( (ret = aesgcm_test()) != 0)
return err_sys("AES-GCM test failed!\n", ret); return err_sys("AES-GCM test failed!\n", ret);
else else
@ -5986,13 +5987,14 @@ int aes_test(void)
if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) if (wc_AesInit(&enc, HEAP_HINT, devId) != 0)
return -5400; return -5400;
#if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER)
if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) if (wc_AesInit(&dec, HEAP_HINT, devId) != 0)
return -5401; return -5401;
#endif
ret = wc_AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); ret = wc_AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION);
if (ret != 0) if (ret != 0)
return -5402; return -5402;
#ifdef HAVE_AES_DECRYPT #if defined(HAVE_AES_DECRYPT) || defined(WOLFSSL_AES_COUNTER)
ret = wc_AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION); ret = wc_AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION);
if (ret != 0) if (ret != 0)
return -5403; return -5403;
@ -6681,8 +6683,8 @@ static int aesgcm_default_test_helper(byte* key, int keySz, byte* iv, int ivSz,
byte* plain, int plainSz, byte* cipher, int cipherSz, byte* plain, int plainSz, byte* cipher, int cipherSz,
byte* aad, int aadSz, byte* tag, int tagSz) byte* aad, int aadSz, byte* tag, int tagSz)
{ {
Aes enc; Aes enc;
Aes dec; Aes dec;
byte resultT[AES_BLOCK_SIZE]; byte resultT[AES_BLOCK_SIZE];
byte resultP[AES_BLOCK_SIZE * 3]; byte resultP[AES_BLOCK_SIZE * 3];
@ -7306,9 +7308,9 @@ int aesgcm_test(void)
randIV, sizeof(randIV), randIV, sizeof(randIV),
resultT, sizeof(resultT), resultT, sizeof(resultT),
a, sizeof(a)); a, sizeof(a));
#if defined(WOLFSSL_ASYNC_CRYPT) #if defined(WOLFSSL_ASYNC_CRYPT)
result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif #endif
if (result != 0) if (result != 0)
return -8209; return -8209;
@ -7322,22 +7324,25 @@ int aesgcm_test(void)
return -8210; return -8210;
} }
#ifdef HAVE_AES_DECRYPT
result = wc_AesGcmDecrypt(&enc, result = wc_AesGcmDecrypt(&enc,
resultP, resultC, sizeof(resultC), resultP, resultC, sizeof(resultC),
randIV, sizeof(randIV), randIV, sizeof(randIV),
resultT, sizeof(resultT), resultT, sizeof(resultT),
a, sizeof(a)); a, sizeof(a));
#if defined(WOLFSSL_ASYNC_CRYPT) #if defined(WOLFSSL_ASYNC_CRYPT)
result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE);
#endif #endif
if (result != 0) if (result != 0)
return -8211; return -8211;
if (XMEMCMP(p, resultP, sizeof(resultP))) if (XMEMCMP(p, resultP, sizeof(resultP)))
return -8212; return -8212;
#endif /* HAVE_AES_DECRYPT */
wc_FreeRng(&rng); wc_FreeRng(&rng);
} }
#endif /* WC_NO_RNG HAVE_SELFTEST */ #endif /* WOLFSSL_AES_256 && !(WC_NO_RNG || HAVE_SELFTEST) */
#endif #endif /* HAVE_FIPS_VERSION >= 2 */
wc_AesFree(&enc); wc_AesFree(&enc);