2024-08-05 10:32 PM - edited 2024-08-05 10:42 PM
Hi Everyone!
I am trying to understand why I cannot get the result of the AES in GCM mode HAL_CRYP_Encrypt on the F439ZI board to match the AES in GCM result anywhere else. I am using Python's pycryptodome library for result comparison. I have previously seen this very informative post: https://community.st.com/t5/stm32-mcus-security/a-guide-to-the-hal-of-the-aes-accelerator-or-how-to-fix-it/m-p/134252
However, I am still stuck somewhat.
I am also using the default AES-256 key together with the default IV provided by the CubeMX:
CRYP_HandleTypeDef hcryp;
__ALIGN_BEGIN static const uint32_t pKeyCRYP[8] __ALIGN_END = {
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};
__ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
0x00000000,0x00000000,0x00000000,0x00000002};
__ALIGN_BEGIN static const uint32_t HeaderCRYP[1] __ALIGN_END = {
0x00000000};
/**
* @brief CRYP Initialization Function
* None
* @retval None
*/
static void MX_CRYP_Init(void)
{
/* USER CODE BEGIN CRYP_Init 0 */
/* USER CODE END CRYP_Init 0 */
/* USER CODE BEGIN CRYP_Init 1 */
/* USER CODE END CRYP_Init 1 */
hcryp.Instance = CRYP;
hcryp.Init.DataType = CRYP_DATATYPE_32B;
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp.Init.pKey = (uint32_t *)pKeyCRYP;
hcryp.Init.pInitVect = (uint32_t *)pInitVectCRYP;
hcryp.Init.Algorithm = CRYP_AES_GCM;
hcryp.Init.Header = (uint32_t *)HeaderCRYP;
hcryp.Init.HeaderSize = 1;
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
if (HAL_CRYP_Init(&hcryp) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRYP_Init 2 */
/* USER CODE END CRYP_Init 2 */
}
int main(void)
{
.
.
.
.
MX_CRYP_Init();
uint8_t keyBuff[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint32_t ivBuff[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
uint32_t plain[4] = {0x61616161, 0x61616161, 0x61616161, 0x61616161};
uint8_t ciphertext[16];
if (HAL_CRYP_Encrypt(&hcryp, plain, 4, ciphertext, HAL_MAX_DELAY) != HAL_OK) {
// HANDE THE ERROR
}
// Print debugging information
for (int i = 0; i < 16; ++i) {
char printy[10];
int len = sprintf(printy, " -%x-", ciphertext[i]);
HAL_UART_Transmit(&huart3, (uint8_t*)printy, len, 5000);
}
HAL_UART_Transmit(&huart3, "\n\n", 2, 5000);
}
I am getting the output of: -5c- -21- -c6- -af- -f- -a- -1- -2c- -b2- -a4- -2f- -66- -79- -fc- -92- -db-
When I simulate above in the following Python code:
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
# Key and IV (Initialization Vector) from your STM32 code
key = bytes([0x00] * 32) # 256-bit key
key = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
iv = bytes([0x00] * 15 + [0x02]) # 96-bit IV (12 bytes)
# Header (AAD - Additional Authenticated Data)
header = bytes([0x00]*4)
# Data to encrypt
plaintext = b'aaaaaaaaaaaaaaaa'
plaintext = b'\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61'
# Create AES-GCM cipher object
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
# Encrypt the data
#cipher.update(header) # Add AAD
ciphertext, tag = cipher.encrypt_and_digest(plaintext)
print(f'Ciphertext: {ciphertext.hex()}')
#print(f'Tag: {tag.hex()}')
I get 981e09865ee3f41ea3d5fc7981166d94
I am still lost on why the discrepancy exists. Did lots of looking and read much documentation and posts, but no luck. Any help would be much appreciated.
Solved! Go to Solution.
2024-08-15 02:15 PM
Hello @CatChips ,
in fact, this is a problem with the python script and not with the calculated value in the STM32.
the last four Hex digits in the initialization vector should not be used in the python script here you will find attached a version of the script implementing your desired test with the same calculated value in the STM32 as well as the main.c config used.
here is the calculated cipher with the script:
and here is the calculated cipher with the MCU:
Regards
2024-08-15 02:15 PM
Hello @CatChips ,
in fact, this is a problem with the python script and not with the calculated value in the STM32.
the last four Hex digits in the initialization vector should not be used in the python script here you will find attached a version of the script implementing your desired test with the same calculated value in the STM32 as well as the main.c config used.
here is the calculated cipher with the script:
and here is the calculated cipher with the MCU:
Regards
2024-08-15 03:25 PM
You've got endian issues with your IV, pass the array as bytes to be consistent
Or
__ALIGN_BEGIN static const uint32_t pInitVectCRYP[4] __ALIGN_END = {
0x00000000,0x00000000,0x00000000,0x02000000};
2024-08-15 09:03 PM - edited 2024-08-15 09:41 PM
Thank you so much @STea and @Tesla DeLorean ! This is very helpful! I am now able to get the same results for a single encryption.
However, I noticed that whenever I encrypt the same block using STM32 using HAL_CRYP_Encrypt with AES-GCM, it seems to be generating the same result. This goes against the GCM mode.
Any ideas?
Thank you.
Edit: I have added the following to the config, but it does not have effect. Seems like the state of the CRYP device is reset after each call to HAL_CRYP_Encrypt:
hcryp->Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE;
2024-08-19 03:07 AM
Hello @CatChips ,
One of the key features of GCM mode is that it uses a unique initialization vector (IV) for each encryption operation to ensure that the same plaintext encrypted multiple times will produce different ciphertexts. This is crucial for maintaining security, as reusing the same IV with the same key can lead to vulnerabilities. If the IV is not changing between encryption operations, the same plaintext will produce the same ciphertext. Ensure that the IV is unique for each encryption operation. Properly manage the IV to ensure it is not reused is required. This can be done by incrementing a counter or using a random number generator to create a new IV for each encryption.
Regards