mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-01 03:34:39 +02:00
Fix for STM32 issue with some Cube HAL versions (such as F777) which could modify non-block aligned bytes in the output buffer during decrypt. For TLS these bytes are the authentication tag. Workaround is to save off the incoming expected authentication tag. ZD 10961.
This commit is contained in:
@@ -6347,12 +6347,12 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
|
||||
word32 keySize;
|
||||
word32 partial = sz % AES_BLOCK_SIZE;
|
||||
word32 tag[AES_BLOCK_SIZE/sizeof(word32)];
|
||||
word32 tagExpected[AES_BLOCK_SIZE/sizeof(word32)];
|
||||
word32 partialBlock[AES_BLOCK_SIZE/sizeof(word32)];
|
||||
word32 ctr[AES_BLOCK_SIZE/sizeof(word32)];
|
||||
word32 ctrInit[AES_BLOCK_SIZE/sizeof(word32)];
|
||||
word32 authhdr[AES_BLOCK_SIZE/sizeof(word32)];
|
||||
byte* authInPadded = NULL;
|
||||
int authPadSz, wasAlloc = 0;
|
||||
int authPadSz, wasAlloc = 0, tagComputed = 0;
|
||||
|
||||
ret = wc_AesGetKeySize(aes, &keySize);
|
||||
if (ret != 0)
|
||||
@@ -6373,7 +6373,19 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
|
||||
else {
|
||||
GHASH(aes, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
|
||||
}
|
||||
XMEMCPY(ctrInit, ctr, sizeof(ctr)); /* save off initial counter for GMAC */
|
||||
|
||||
/* Make copy of expected authTag, which could get corrupted in some
|
||||
* Cube HAL versions without proper partial block support.
|
||||
* For TLS blocks the authTag is after the output buffer, so save it */
|
||||
XMEMCPY(tagExpected, authTag, authTagSz);
|
||||
|
||||
/* for cases where hardware cannot be used for authTag calculate it */
|
||||
if (sz == 0 || partial != 0 || ivSz != GCM_NONCE_MID_SZ) {
|
||||
GHASH(aes, authIn, authInSz, in, sz, (byte*)tag, sizeof(tag));
|
||||
wc_AesEncrypt(aes, (byte*)ctr, (byte*)partialBlock);
|
||||
xorbuf(tag, partialBlock, sizeof(tag));
|
||||
tagComputed = 1;
|
||||
}
|
||||
|
||||
/* Authentication buffer - must be 4-byte multiple zero padded */
|
||||
authPadSz = authInSz % sizeof(word32);
|
||||
@@ -6419,7 +6431,7 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
|
||||
/* GCM payload phase - can handle partial blocks */
|
||||
status = HAL_CRYP_Decrypt(&hcryp, (uint32_t*)in,
|
||||
(blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT);
|
||||
if (status == HAL_OK) {
|
||||
if (status == HAL_OK && tagComputed == 0) {
|
||||
/* Compute the authTag */
|
||||
status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
|
||||
STM32_HAL_TIMEOUT);
|
||||
@@ -6457,7 +6469,7 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
|
||||
(byte*)partialBlock, STM32_HAL_TIMEOUT);
|
||||
XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
|
||||
}
|
||||
if (status == HAL_OK) {
|
||||
if (status == HAL_OK && tagComputed == 0) {
|
||||
/* GCM final phase */
|
||||
hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE;
|
||||
status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, (byte*)tag, STM32_HAL_TIMEOUT);
|
||||
@@ -6478,7 +6490,7 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
|
||||
(byte*)partialBlock, STM32_HAL_TIMEOUT);
|
||||
XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
|
||||
}
|
||||
if (status == HAL_OK) {
|
||||
if (status == HAL_OK && tagComputed == 0) {
|
||||
/* Compute the authTag */
|
||||
status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, (byte*)tag, STM32_HAL_TIMEOUT);
|
||||
}
|
||||
@@ -6495,25 +6507,21 @@ static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out,
|
||||
/* 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
|
||||
* in the final GHASH. */
|
||||
XMEMSET(partialBlock, 0, sizeof(partialBlock)); /* use this to get tag */
|
||||
status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)ctr,
|
||||
(uint8_t*)keyCopy, keySize * 8,
|
||||
(uint8_t*)in, sz,
|
||||
(uint8_t*)authInPadded, authInSz,
|
||||
(uint8_t*)out, (uint8_t*)tag);
|
||||
(uint8_t*)out, (uint8_t*)partialBlock);
|
||||
if (status != SUCCESS)
|
||||
ret = AES_GCM_AUTH_E;
|
||||
if (tagComputed == 0)
|
||||
XMEMCPY(tag, partialBlock, authTagSz);
|
||||
#endif /* WOLFSSL_STM32_CUBEMX */
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
|
||||
/* For STM32 GCM fallback to software if partial AES block or IV != 12 */
|
||||
if (sz == 0 || partial != 0 || ivSz != GCM_NONCE_MID_SZ) {
|
||||
GHASH(aes, authIn, authInSz, in, sz, (byte*)tag, sizeof(tag));
|
||||
wc_AesEncrypt(aes, (byte*)ctrInit, (byte*)partialBlock);
|
||||
xorbuf(tag, partialBlock, sizeof(tag));
|
||||
}
|
||||
|
||||
/* Check authentication tag */
|
||||
if (ConstantCompare(authTag, (byte*)tag, authTagSz) != 0) {
|
||||
if (ConstantCompare((const byte*)tagExpected, (byte*)tag, authTagSz) != 0) {
|
||||
ret = AES_GCM_AUTH_E;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user