cancel
Showing results for 
Search instead for 
Did you mean: 

SBSFU with STM32H7 gets constantly rebooted on gcc-arm configuration

sskim
Visitor

Hi, 

I've been working on porting the SBSFU onto a STM32H7A series with my custom gcc-arm build environment.

The example project I am referring to is: x-cube-sbsfu-v2-7-0\STM32CubeExpansion_SBSFU_V2.7.0\Projects\STM32H7B3I-DK\Applications\2_Images.

Everything seems to be working fine, but I have one issue that I am struggling with. 

So, the main SBSFU is supposed to call SE_CallGate() being the entry to the core secure engine, and it gets rebooted constantly. And, what I found is that the reboot doesn't happen if I get "IS_CALLER_SE_IF()" commented out. 

 
// se_callgate.c
SE_ErrorStatus SE_CallGate(SE_FunctionIDTypeDef eID, SE_StatusTypeDef *const peSE_Status, uint32_t PrimaskParam, ...)
{
  SE_ErrorStatus e_ret_status;
  va_list arguments;
  volatile uint32_t LR;

#if defined(__CC_ARM) || defined(__ICCARM__)
  LR = get_LR();
#elif defined(__ARMCC_VERSION)
  __asm volatile("MOV %0, LR\n" : "=r"(LR));
#elif defined(__GNUC__)
  register unsigned lr asm("lr");
  LR = lr;
#endif /* defined(__CC_ARM) || defined(__ICCARM__) */

  /* Enter the protected area */
  ENTER_PROTECTED_AREA();

  /*
   * Warning : It is mandatory to call NVIC_SystemReset() in case of error
   * instead of return(SE_ERROR) to avoid any attempt of attack by modifying
   * the call stack (LR) in order to execute code inside secure enclave
   */

  /* Check the Callgate was called only from SE Interface */
  IS_CALLER_SE_IF();

  ...
}

Also, I found that the reboot also doesn't happen if SE_SysCall() is commented out, when IS_CALLER_SE_IF() remains to be called.

// se_interface_common.c
void SE_SysCall(SE_ErrorStatus *e_ret_status, uint32_t syscall, SE_StatusTypeDef *peSE_Status, void *params)
{
  /*
    * You cannot directly change to privileged mode from unprivileged mode without going through an exception,
    * for example an SVC.
    * Handled by @ref MPU_SVC_Handler()  and finally @ref SE_SVC_Handler()
    */
  __ASM __IO("SVC #0");    /* 0 is the hard-coded value to indicate a Secure Engine syscall */
}

// se_interface_bootloader.c
SE_ErrorStatus SE_SFU_IMG_Read(SE_StatusTypeDef *pSE_Status, uint8_t *pDestination, const uint8_t *pSource,
                               uint32_t Length)
{
  SE_ErrorStatus e_ret_status;
  uint32_t primask_bit; /*!< interruption mask saved when disabling ITs then restore when re-enabling ITs */

  /* Check if the call is coming from SFU code */
  __IS_SFU_RESERVED();
#ifdef SFU_ISOLATE_SE_WITH_MPU
  if (0U != SE_IsUnprivileged())
  {
    uint32_t params[3] = {(uint32_t)pDestination, (uint32_t)pSource, (uint32_t)Length};
    SE_SysCall(&e_ret_status, SE_IMG_READ, pSE_Status, &params);
  }
  else
  
  ...
}

My initial suspicion on this was that there might be some issues with getting the caller's location information, i.e., accessing LR register, which potentially causes something later to get the MCU rebooted like contaminating register values. However, I haven't got any concrete evidence on that yet and thus solutions to the issue.

One quick solution I found to detour this issue is not call IS_CALLER_SE_IF() at all in the first place, but then what it means is it won't care which function it called the SE_CallGate(), which I think should be avoided in the security point of view.

 

Any ideas?

Thanks!!

0 REPLIES 0