-
Notifications
You must be signed in to change notification settings - Fork 55
Description
Describe the bug
An invalid tag is generated for payloads that are not a multiple of 4, as described in Re: STM32U545 AES GCM Tag mismatch - STMicroelectronics Community.
ST Internal ticket number: 210917.
How To Reproduce
An example STM32Cube-IDE project is generated with STM32CubeMX and attached in the mentioned community thread.
Describe the set-up
Custom board with STM32H730XX.
AES GCM encryption and decryption are performed with settings:
DataType = CRYP_DATATYPE_8B
DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE
KeySize = CRYP_KEYSIZE_128B
HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE
Additional context
Tag is generated correctly when:
- When the input array is 16 bytes, but we decode 15 bytes (as there is only 15 bytes of data).
- When we dynamically allocate an aligned input array of size that is a multiple of 4,
but decode with real size (i.e, 15). - When the input array is in the global scope (regardless of its size).
The tag is generated incorrectly:
- When the input array is 15 bytes on the stack.
Tried to flush and invalidate the input memory area, as well as to flush ECC (as buffers are located within SRAM with enabled ECC), no difference.
After further investigation, the culprit seems to be the padding bytes.
During the encryption, the CRYP_CR_NPBLB is used to let HW know which bytes to discard;
However, during the decryption process, it is not used/or available.
Here is the debug info, which shows that the input with 16 bytes has explicit 00 padding in the last word (0x00a989d1); whereas when the input buffer is 15 bytes, we get 8a instead of 00 in the last word (0x8aa989d1).
Working with 16 length:
x/15xb hcryp->pCrypInBuffPtr
0x2402a5d8: 0x13 0xb4 0xc7 0x2b 0x38 0x9d 0xc5 0x01
0x2402a5e0: 0x8e 0x72 0xa1 0x71 0xd1 0x89 0xa9
x/4xw hcryp->pCrypInBuffPtr
0x2402a5d8: 0x2bc7b413 0x01c59d38 0x71a1728e 0x00a989d1
When CrypInCount == 3
p/x *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount)
$2 = 0xa989d1Not working with 15 length:
x/15xb hcryp->pCrypInBuffPtr
0x24021c54: 0x13 0xb4 0xc7 0x2b 0x38 0x9d 0xc5 0x01
0x24021c5c: 0x8e 0x72 0xa1 0x71 0xd1 0x89 0xa9
x/4xw hcryp->pCrypInBuffPtr
0x24021c54: 0x2bc7b413 0x01c59d38 0x71a1728e 0x8aa989d1After correction of the padding in the last block (16 bytes) of the last writable word (4 bytes) the tag generation works fine after decryption, required changes are applied to CRYP_AESGCM_Process in stm32h7xx_hal_cryp.c:
--- a/stm32cube/stm32h7xx/drivers/src/stm32h7xx_hal_cryp.c
+++ b/stm32cube/stm32h7xx/drivers/src/stm32h7xx_hal_cryp.c
@@ -3085,10 +3085,17 @@ static HAL_StatusTypeDef CRYP_AESGCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t
}
/* Write the last input block in the IN FIFO */
+ unsigned pad_bytes = ((((uint32_t)(hcryp->Size) / 4U) + 1U) * 4U) - (uint32_t)(hcryp->Size);
for (index = 0U; index < lastwordsize; index ++)
{
- hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
- hcryp->CrypInCount++;
+ if (((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT) &&
+ (((pad_bytes != 0)) && (index + 1 == lastwordsize))) {
+ // set pad bytes to 0
+ hcryp->Instance->DIN = (*(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount) << (pad_bytes * 8)) >> (pad_bytes * 8);
+ } else {
+ hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
+ }
+ hcryp->CrypInCount++;
}PS: Although the fix appears to work (tested with input data of 15 and 42 bytes, with and without AD of size 13 and 20 bytes), I'm uncertain if it's entirely correct; therefore, I'm opening this as an issue. I can also submit a PR if needed.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status