title: STM32 secure boot loader security enable fails consistently with "[SBOOT] Security issue : Execution stopped !"
body: <p>I have my STM32F405RGT6 secure boot loader running with security flags disabled. So I try to introduce the security flags/options one by one. Independently of which flag I enable in app_sfu.h, the code fails in the first FLOW_CONTROL_CHECK in the SFU_BOOT_SM_VerifyUserFwSignature function in sfu_boot.c</p>
  <p>I have added logging that shows exactly what happens:</p>
  <pre><code>  /* Double security check :
   - testing &quot;static protections&quot; twice will avoid basic hardware attack
   - flow control reached : dynamic protections checked
   - re-execute static then dynamic check
   - errors caught by FLOW_CONTROL ==&gt; infinite loop */
    TRACE(&quot;= [SBOOT] FLOW_CONTROL_CHECK(%x, %x)\n&quot;, uFlowProtectValue, FLOW_CTRL_RUNTIME_PROTECT);
    FLOW_CONTROL_CHECK(uFlowProtectValue, FLOW_CTRL_RUNTIME_PROTECT);
  </code></pre>
  <p>Output from the trace shows this:</p>
  <pre><code>= [SBOOT] FLOW_CONTROL_CHECK(1554b, 30f1)
  </code></pre>
  <p>The FLOW_CONTROL_CHECK macro compares the two values. If they differ, the program fails.</p>
  <p>As I understand the code, the uFlowProtectValue contains the run time protection values that are active at the actual execution time, while FLOW_CTRL_RUNTIME_PROTECT is a compile time #define that should be the same as what we're running with.</p>
  <p>The core of the problem is that the run time protection value is what I expect it to be, while the compile time #define never differs from 0x30f1.</p>
  <p>The #define comes to be in ST-provided code that your mother might not approve of, not in the least because it doesn't seem to work:</p>
  <pre><code>  /**
    * @brief  SFU_BOOT Flow Control : Control values static protections
    */
  #define FLOW_CTRL_UBE (FLOW_CTRL_INIT_VALUE ^ FLOW_STEP_UBE)
  #define FLOW_CTRL_WRP (FLOW_CTRL_UBE ^ FLOW_STEP_WRP)
  #define FLOW_CTRL_PCROP (FLOW_CTRL_WRP ^ FLOW_STEP_PCROP)
  #define FLOW_CTRL_SEC_MEM (FLOW_CTRL_PCROP ^ FLOW_STEP_SEC_MEM)
  #define FLOW_CTRL_RDP (FLOW_CTRL_SEC_MEM ^ FLOW_STEP_RDP)
  #define FLOW_CTRL_STATIC_PROTECT FLOW_CTRL_RDP
  
  /**
    * @brief  SFU_BOOT Flow Control : Control values runtime protections
    */
  #define FLOW_CTRL_TAMPER (FLOW_CTRL_STATIC_PROTECT ^ FLOW_STEP_TAMPER)
  #define FLOW_CTRL_MPU (FLOW_CTRL_TAMPER ^ FLOW_STEP_MPU)
  #define FLOW_CTRL_FWALL (FLOW_CTRL_MPU ^ FLOW_STEP_FWALL)
  #define FLOW_CTRL_DMA (FLOW_CTRL_FWALL ^ FLOW_STEP_DMA)
  #define FLOW_CTRL_IWDG (FLOW_CTRL_DMA ^ FLOW_STEP_IWDG)
  #define FLOW_CTRL_DAP (FLOW_CTRL_IWDG ^ FLOW_STEP_DAP)
  #define FLOW_CTRL_RUNTIME_PROTECT FLOW_CTRL_DAP
  </code></pre>
  <p>The hex numbers from my trace output above are from when I enable the internal watch dog, IWDG.</p>
  <p>The values are XOR'ed from three involved bitmaps:</p>
  <pre><code>#define FLOW_CTRL_INIT_VALUE 0x00005776U         /*!&lt; Init value definition */
  #define FLOW_STEP_UBE 0x00006787U                /*!&lt; Step UBE value */
  #define FLOW_STEP_IWDG 0x000165baU               /*!&lt; Step IWDG value */
  </code></pre>
  <p>The XOR of the two first is 0x30f1, and if you add FLOW_STEP_IWDG to that, you get 0x1554b.</p>
  <p>So the run time value with IWDG enabled is correct, while the compile time value is wrong.</p>
  <p>How can that be?</p>