AES256 GCM Output incorrect on STM32WB55
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-27 11:42 AM
Good afternoon,
I am trying to encrypt some data using the AES peripheral and compare the results to the same operation in python and .NET.
The cipher text output from the operation on the STM32 is different than that of the other two languages.
The code I am testing is
/**
* @brief AES1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_AES1_Init(void)
{
/* USER CODE BEGIN AES1_Init 0 */
uint8_t key[32] = {0};
uint8_t iv[12] = {0};
/* USER CODE END AES1_Init 0 */
/* USER CODE BEGIN AES1_Init 1 */
/* USER CODE END AES1_Init 1 */
hcryp1.Instance = AES1;
hcryp1.Init.DataType = CRYP_DATATYPE_8B;
hcryp1.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp1.Init.pKey = (uint32_t *)key;
hcryp1.Init.pInitVect = (uint32_t *)iv;
hcryp1.Init.Algorithm = CRYP_AES_GCM_GMAC;
hcryp1.Init.Header = (uint32_t *)HeaderAES1;
hcryp1.Init.HeaderSize = 1;
hcryp1.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
hcryp1.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE;
if (HAL_CRYP_Init(&hcryp1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN AES1_Init 2 */
uint8_t plainText[12] = {72,101,108,108,111,32,87,111,114,108,100,49};
uint8_t cipherText[50] = {0};
HAL_StatusTypeDef status = HAL_CRYP_Encrypt(&hcryp1, (uint32_t*)plainText, 12, (uint32_t*)cipherText, HAL_MAX_DELAY);
if (status != HAL_OK){
}
/* USER CODE END AES1_Init 2 */
}
The output cipher text is
In comparison, the output from the .NET operation is
and python is
What have I missed in using the AES peripheral on the device?
Thank you in advance
Solved! Go to Solution.
- Labels:
-
Cryptography
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-28 7:35 AM
After reading many other reported issues and various amounts of documentation, I have found the solutions, but also the problems with the implementation of AESGCM within the peripheral (thanks STM).
- The encryption key and IV must be in little endian (not a big deal but would be worth noting somewhere in the documentation.
- The IV (nonce) for GCM is 12 bytes in length, but the STM implementation requires 16 bytes and the last 4 bytes must be 0x2000000 for GCM more specific information can be found here https://community.st.com/t5/stm32-mcus-security/a-guide-to-the-hal-of-the-aes-accelerator-or-how-to-fix-it/td-p/134252
- Header is an array of uint32_t, therefore you must be careful when using headers which do not conform to this as TAG generation fails.
After all the above is corrected, the encryption and decryption works fine for variable length data, i.e. blocks not equal to 4 bytes.
But, then we come to TAG generation.
If you encrypt 11 bytes of data and generate a TAG using HAL_CRYPEX_AESGCM_GenerateAuthTAG it works fine, however, decryption works but when you generate the TAG for it it is incorrect so the data can not be verified.
It looks like for TAG generation on decryption, the input must be uint32_t therefore, you are unable to generate a TAG for an 11byte input as it is incorrect.
It all works fine if you perform the process on 12 bytes. @Tesla DeLorean your comment about padding makes sense now.
All in all a very frustrating experience, if it was not for the performance I would have given up and reverted to a software implementation.
STM, implementations should at least be able to be verified against known test vectors!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-27 12:17 PM
Isn't it going to expect data in multiples of 16-bytes? And careful/consistent management of the pad bytes.
AES-CTR less so because you're basically generating an XOR pattern
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-27 12:24 PM - edited ‎2024-04-28 7:20 AM
AES-GCM doesnt require padding as it is a streaming mode cipher. Therefore it is possible to encrypt 12 bytes of data. Or have I misunderstood your comment?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-04-28 7:35 AM
After reading many other reported issues and various amounts of documentation, I have found the solutions, but also the problems with the implementation of AESGCM within the peripheral (thanks STM).
- The encryption key and IV must be in little endian (not a big deal but would be worth noting somewhere in the documentation.
- The IV (nonce) for GCM is 12 bytes in length, but the STM implementation requires 16 bytes and the last 4 bytes must be 0x2000000 for GCM more specific information can be found here https://community.st.com/t5/stm32-mcus-security/a-guide-to-the-hal-of-the-aes-accelerator-or-how-to-fix-it/td-p/134252
- Header is an array of uint32_t, therefore you must be careful when using headers which do not conform to this as TAG generation fails.
After all the above is corrected, the encryption and decryption works fine for variable length data, i.e. blocks not equal to 4 bytes.
But, then we come to TAG generation.
If you encrypt 11 bytes of data and generate a TAG using HAL_CRYPEX_AESGCM_GenerateAuthTAG it works fine, however, decryption works but when you generate the TAG for it it is incorrect so the data can not be verified.
It looks like for TAG generation on decryption, the input must be uint32_t therefore, you are unable to generate a TAG for an 11byte input as it is incorrect.
It all works fine if you perform the process on 12 bytes. @Tesla DeLorean your comment about padding makes sense now.
All in all a very frustrating experience, if it was not for the performance I would have given up and reverted to a software implementation.
STM, implementations should at least be able to be verified against known test vectors!
