cancel
Showing results for 
Search instead for 
Did you mean: 

AES256 GCM Output incorrect on STM32WB55

POliv
Associate II

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

POliv_0-1714243055322.png

In comparison, the output from the .NET operation is

POliv_1-1714243097071.png

and python is

POliv_2-1714243259294.png

What have I missed in using the AES peripheral on the device?

Thank you in advance

1 ACCEPTED SOLUTION

Accepted Solutions
POliv
Associate II

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).

  1. The encryption key and IV must be in little endian (not a big deal but would be worth noting somewhere in the documentation.
  2. 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
  3. 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!

View solution in original post

3 REPLIES 3

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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?

POliv
Associate II

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).

  1. The encryption key and IV must be in little endian (not a big deal but would be worth noting somewhere in the documentation.
  2. 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
  3. 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!