Skip to main content
Associate III
December 15, 2023
Solved

STMCryptoLib failures on STM32U599

  • December 15, 2023
  • 5 replies
  • 4056 views

The Issue 

  • When my bootloader jumps to the application all `AES_ECB_Encrypt_XXX` incorrectly encrypt/decrypt the data. Once the application fails to initialize too many times it will reboot due to watchdog and the ncrypt/decrypt will continue to fail in the bootloader although it was working before it jumped to the application.

Background

  • I am using the STMCryptoLib_V4.1.0 in my bootloader and application.
  • I am using the legacy_v3 APIs. As our code was originally written with the V3 library.
  • The module in question is `AES_ECB_Encrypt_xxx`.
    • The bootloader uses the modules successfully but after it jumps to the application it fails to encrypt/decrypt.
  • The CRC clock is not disable prior to the bootloader jumping to the application.
  • The CRC clock is enable on board bring up for each applications as follows..

 

 

__HAL_RCC_CRC_FORCE_RESET();
__HAL_RCC_CRC_RELEASE_RESET();
__HAL_RCC_CRC_CLK_ENABLE();

 

 

 

  • The library is not failing it's just not encrypt/decrypt correctly after jumping from the application.
  • The code that I am using has worked for years using STMCryptoLib_V3 on stm32L4. So our code isn't the issue. If I turn off encryption feature on our code everything works. 
  • If I built the application without bootloader support. That is it's the first thing to run after POR everything works. So the issue is related to jumping to the application from the bootloader after using the cyrpotLibrary.
  • If I use a CRC in software and dedicate the CRC HW to crypto library everything works fine. As we use the CRC module for software purposes too. On the STML4 using cryptoLibV3 we has to snapshot and reset the register as follow to make sure it played nicely but this doesn't help on the STMU5 and crytpoLibv4
ctx.handle.Instance->CR = ctx.regs.CR;
 ctx.handle.Instance->POL = ctx.regs.POL;
 __HAL_CRC_INITIALCRCVALUE_CONFIG(&ctx.handle, value);
 __HAL_CRC_DR_RESET(&ctx.handle);
 value = ~HAL_CRC_Accumulate(&ctx.handle, (uint32_t *)data, (uint32_t)size);
 __HAL_CRC_INITIALCRCVALUE_CONFIG(&ctx.handle, ~0);

I would like to know how to correctly reinit the CRC after jumping from my bootloader to application as everything I have tried has failed?

This topic has been closed for replies.
Best answer by desmond

I have managed to resolve the issue. 

1. Snapshot the state of the CRC peripheral on POR.

2. Snapshot the state of CR and POL register after HAL_CRC_Init().

3. Apply the snapshot from step 2 before calling HAL_CRC_Accumulate()

3. Apply the snapshot from step 1 after calling HAL_CRC_Accumulate()

 

Note you must apply the entire snapshot of the peripheral from step 1. Even if the register didn't changed. I observed that if I only reverted the changed registered back to their POR state it didn't work. I cannot say why this is though

5 replies

Jocelyn RICARD
ST Employee
December 21, 2023

Hello @desmond,

Something is not fully clear in your description.

CRC is used by cryptolib in both bootloader and application

CRC is also used by application independently from cryptolib.

You say it fails when bootloader is involved but succeeds when application runs on it own.

Does this mean that sharing CRC between cryptolib and other purpose in application is working fine and only bootloader usage make things fail ?

Also, I understand that disabling usage of CRC for other purpose in application results in bootloader + application succeed to work with cryptolib.

This is strange indeed.

I would propose 2 things:

1) in Application reset the data cache if is was enabled in bootloader

2) Check status of CRC before the call to cryptolib in application with debugger to make sure it is in good state.

 

Best regards

Jocelyn

 

 

 

 

desmondAuthor
Associate III
December 21, 2023

> Does this mean that sharing CRC between cryptolib and other purpose in application is working fine and only bootloader usage make things fail ?

Not exactly. Sharing the CRC and crytpoLib works fine until I perform an unconditional branch from the bootloader to the application. Anything out of POR and it will work anything else and it will fail. See further explanation below.

> You say it fails when bootloader is involved but succeeds when application runs on it own.

- POR

- Bootloader runs using CRC and Cryptolib. Everything works.

- Bootloader jumps to the application. CryptoLib starts failing (not API fail) ciphers are not decrypted/encrypted correctly. 

- Since the application constantly has failure the watchdog reboots the system. The system is now back in the bootloader. The bootloader cryptolib are now failing.

- Crypotlib now fails forever until I do a POR. (Via reset button or via debugger).

 

> in Application reset the data cache if is was enabled in bootloader

- Ours boards use a common board bring up sequence. The data cache and instruction cache are disabled on board bring up. So when the bootloader launches it does this. When the application launches it does this. The data cache are invalidate prior to disabling them. 

- I can give this code a closer look to ensure we have no issue though.

 

> Check status of CRC before the call to cryptolib in application with debugger to make sure it is in good state.

- Can you provide the state variables of the CRC peripheral that represent a good state? 

- Also keep in mind on board bring for any application/bootloader the following sequence is issue to the CRC peripheral which should reset the IP to POR state as far as I understand.

__HAL_RCC_CRC_FORCE_RESET();
__HAL_RCC_CRC_RELEASE_RESET();
__HAL_RCC_CRC_CLK_ENABLE();

 

Tesla DeLorean
Guru
December 21, 2023

Why do these libraries need to use the CRC at all? Is there that much of a threat of them being used on other devices where the test can't simply be patched out, or removed? Are the adversaries really assumed to be that dull-witted? For all the headaches it causes normal users?

Being SYNCHRONOUS, I'd enable the clock *before* generating resets into the state machines, this will be safe even if the reset is asynchronous.

__HAL_RCC_CRC_CLK_ENABLE(); // Sychronous Logic
__HAL_RCC_CRC_FORCE_RESET(); // Drive Reset
__HAL_RCC_CRC_RELEASE_RESET();

The test vector is driving into an STM32 CRC using ST's standard 32-bit polynomial, initial value and bit/byte reversal directions. Check registers out of reset, these are the anticipated defaults.

Is all this interaction with the HW CRC even that efficient? A clean table driven parallel solution in SW can be fast and thread-safe. The HW has no accommodation for multiple concurrent usage case and is not interrupt or thread safe.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
desmondAuthor
Associate III
December 21, 2023

Why do these libraries need to use the CRC at all?

- ST Crytpolib requirement. 

Being SYNCHRONOUS, I'd enable the clock *before* generating resets into the state machines, this will be safe even if the reset is asynchronous.

- The clock is enabled. It was not disabled prior to the unconditional jump from the bootoloader to the App. However I also tried what you said explicitly and it didn't fix the issue. I am try again to confirm

Is all this interaction with the HW CRC even that efficient? A clean table driven parallel solution in SW can be fast and thread-safe. The HW has no accommodation for multiple concurrent usage case and is not interrupt or thread safe.

- The concurrence works prior to the jump, so it should work after the jump. On the STM32L4 we have been doing this for few years with no issue but an older cryptolib that not offered for the stm32U5.

- SW solution can work but I want to try to figure out the issue before defaulting to a work around 

Jocelyn RICARD
ST Employee
December 21, 2023

Hi @desmond ,

Regarding IP reset I would first enable the clock and then perform a reset. But in your case it should be already enabled.

The values in CRC register should match the default values after reset as you can find in the reference manual (RM0351)

Anyway, the failure of cryptolib after watchdog reset looks very strange because non context should be saved.

First check would be to compare CRC registers values after POR and after WD reset just before calling first crypto lib function.

Best regards

Jocelyn

 

Tesla DeLorean
Guru
December 21, 2023

Not tested, but if the CRC is in the right mode, and reset/initialized a write of 0xDEADBEEF should see a 0x81DA1A18 response.

Init condition 0xFFFFFFFF (can read and check), Poly 0x04C11DB7, 32-bit

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
desmondAuthorBest answer
Associate III
December 22, 2023

I have managed to resolve the issue. 

1. Snapshot the state of the CRC peripheral on POR.

2. Snapshot the state of CR and POL register after HAL_CRC_Init().

3. Apply the snapshot from step 2 before calling HAL_CRC_Accumulate()

3. Apply the snapshot from step 1 after calling HAL_CRC_Accumulate()

 

Note you must apply the entire snapshot of the peripheral from step 1. Even if the register didn't changed. I observed that if I only reverted the changed registered back to their POR state it didn't work. I cannot say why this is though