2025-12-18 7:27 PM
Hello, I am trying to use SAES with a wrapped key to decrypt firmware updates on an stm32u5g9vjtxq. I am not sure how I should be changing the InitVect in CRYP_AES_CBC mode after hcryp is already initialized with HAL_CRYP_Init. To elaborate on what I am trying to do I have created a wrapped key that is being stored in OTP memory along with the IV used to encrypt / decrypt that wrapped key. My bootloader calls HAL_CRYPEx_UnwrapKey using the OTP memory address of the wrapped key and the IV also stored in OTP. I then want to change the IV to match that of what was used to encrypt the new firmware image, the unwrapped key is what was used to encrypt the firmware image. I am not sure how to accomplish this without having to call HAL_CRYP_Init again...I think the second call to HAL_CRYP_Init looses the unwrapped key and replaces it with whatever is defined in hcryp.Init.KeySelect which I have set to CRYP_KEYSEL_HW.
To summarize I need to be able to change the InitVect without affecting the key I have unwrapped, My understanding of how all of this is designed to work may be flawed.
My code to initially write the wrapped key and IV used to OTP
uint32_t AESKey256[8] = { MY 256 BIT KEY };
uint32_t pInitVectSAES[4] = { MY IV USED TO WRAP / UNWRAP KEY }
uint32_t Encryptedkey[8];
HAL_CRYPEx_WrapKey(&hcryp, AESKey256, Encryptedkey, HAL_MAX_DELAY)
HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, key_addr, (uint32_t)Encryptedkey);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, key_addr + 0x10, (uint32_t)(Encryptedkey + 4) );
HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, iv_addr, (uint32_t)(pInitVectSAES) );
My bootloader init code
static void MX_SAES_AES_Init(void) {
hcryp.Instance = SAES;
hcryp.Init.DataType = CRYP_NO_SWAP;
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp.Init.pInitVect = (uint32_t *)pInitVectSAES; // Initalized to 0x00000000...
hcryp.Init.Algorithm = CRYP_AES_CBC;
hcryp.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD;
hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE;
hcryp.Init.KeyMode = CRYP_KEYMODE_WRAPPED;
hcryp.Init.KeySelect = CRYP_KEYSEL_HW;
hcryp.Init.KeyProtection = CRYP_KEYPROT_DISABLE;
if (HAL_CRYP_Init(&hcryp) != HAL_OK)
{
Error_Handler();
}
}
I update the InitVect pointer to what I have written in OTP and use it to unwrap the key that is also in OTP
uintptr_t key_addr = 0x0BFA00D0;
uint32_t iv_addr = 0x0BFA00F0;
hcryp.Init.pInitVect = (uint32_t*)iv_addr;
HAL_CRYP_DeInit(&hcryp);
HAL_CRYP_Init(&hcryp);
HAL_CRYPEx_UnwrapKey(&hcryp, (uint32_t*)key_addr, HAL_MAX_DELAY);
Up to this point everything works, but I now need to change the InitVect to what was used to encrypt the firmware. I have tried a couple things
// I believe calling Init with the new InitVect pointer looses the unwrapped key
hcryp.Init.pInitVect = (uint32_t*)fw_header.iv;
HAL_CRYP_Init(&hcryp);
// This seems like it should work without having to call Init but the decrypted firmware does not match the original.
hcryp.Instance->IVR3 = *(uint32_t *)(fw_header.iv);
hcryp.Instance->IVR2 = *(uint32_t *)(fw_header.iv + 1U);
hcryp.Instance->IVR1 = *(uint32_t *)(fw_header.iv + 2U);
hcryp.Instance->IVR0 = *(uint32_t *)(fw_header.iv + 3U);