top of page

Secure Provisioning of STM32H503 Devices: A Comprehensive Guide

Mar 27
5 min read

Updated: Apr 7

Understanding STM32H503 and Its Security Features


The STM32H503 family from STMicroelectronics is built on the ARM Cortex-M33 core. It includes an advanced security lifecycle as part of the STM32H5 architecture. Unlike older STM32 series, STM32H5 devices support controlled product states. This allows a device to be provisioned, secured, locked, and later reopened through an authenticated regression process. This mechanism is essential for secure production environments where firmware, keys, and configuration data must be protected.




In this article, I will explain a complete example of provisioning and securing an STM32H503 device. This includes programming the required OTP data, changing the PRODUCT_STATE through the defined lifecycle stages, locking the device, and performing regression using password authentication. I will also show how the same sequence can be integrated into a production programming flow using the Cyclone programmer from PEMicro. This allows the entire procedure to be executed in a consistent and repeatable manner during manufacturing.


STM32H5 Product Lifecycle and PRODUCT_STATE


STM32H5 devices store their lifecycle status in option bytes called PRODUCT_STATE. The device always starts in the OPEN state, where full debug access is allowed. Before a device can be locked, it must first move into the PROVISIONING state. This state allows programming of security-related data such as OTP passwords and configuration masks. After provisioning is complete, the device can be moved to the CLOSED state. When the device is closed, debug access is disabled. The only way to return to the open state is by performing regression with the correct password.


A direct transition from OPEN to CLOSED is not allowed by the hardware. The device must always pass through PROVISIONING. Once the state becomes CLOSED, the protection is enforced by hardware and cannot be bypassed without authentication.


The PRODUCT_STATE value is stored in option bytes and is programmed using user option files with the extension .OPT.


Required Files for the Example


To demonstrate the full lifecycle, several files are required. Two option files are used to change the product state: one for PROVISIONING and one for CLOSED. A user password file is created by the developer, and a hashed version of that password is generated and programmed into OTP memory. A security mask file is also programmed into OTP, and finally, a normal user application is programmed into flash.


The example uses the following files:


  • `provisioning.OPT`

  • `closed.OPT`

  • `user_password.bin`

  • `board_password.bin`

  • `data_soc_mask.bin`

  • `GPIO_Toggle.hex`


The option files control the PRODUCT_STATE transition. The password files define the debug authentication key. The mask file contains SoC security configuration, and the hex file represents the user firmware.


Creating PRODUCT_STATE Option Files


Option files are created using the user option editor inside the programming tools. The PRODUCT_STATE field must be modified manually. In this example, the provisioning state uses the value `0x17`, and the closed state uses the value `0x72`. After saving the first file as `provisioning.OPT`, the same process is repeated to create `closed.OPT`.



These files will later be programmed after the firmware and OTP data are written.


Creating Password and OTP Data


The STM32H5 debug authentication mechanism requires that a password hash be stored in OTP memory. The original password must be kept by the developer because it will be required for regression. The password is first written as an ASCII file named `user_password.bin`. This file is then processed using the script provided in the STM32Cube firmware package to generate the hashed password file `board_password.bin`.


The script `create_password.bat` is located inside the STM32Cube H5 example projects. Running this script generates the binary that must be programmed into OTP at address `0x08FFF000`. A second OTP file called `data_soc_mask.bin` must also be programmed at address `0x08FFF020`. This file contains security configuration bits for the system-on-chip.


OTP memory can only be written once. After these locations are programmed, they cannot be erased or rewritten, so the password must be stored safely before continuing.


Programming Sequence using Cyclone


Programming can be performed using the Cyclone image creation utility. The sequence begins by selecting the correct programming algorithm for the STM32H503 device, followed by erase and blank check. The user application is queued, then the OTP binaries are queued with explicit addresses. After programming and verification, the provisioning option file is loaded and programmed, and the options are launched. The process is then repeated for the closed option file.



A typical command sequence is shown below:


```

CM C:\PEMicro\cyclone\supportfiles\supportFiles_ARM\ST\STM32H5\ST_STM43H503RB_128.arp

EM ;Erase Module

BM ;Blank Check

QO C:\GPIO_Toggle.hex

QB C:\board_password.bin 08FFF000

QB C:\data_soc_mask.bin 08FFF020

PM ;Program Module

VM ;Verify Module

SU C:\Provisioning.opt

PU ;Program User Options

VU ;Verify User Options

LO ;Launch User Options

SU C:\Closed.opt

PU ;Program user options

VU ;Verify

LO ;Launch

```


The launch option command is required after each option programming step because the new option bytes only take effect after reloading. If the device is programmed again later, the OTP programming commands must be removed because those locations can only be written once.


After the image is built and deployed, it can be stored inside the Cyclone programmer and used for stand-alone programming without a PC.


Device Behaviour After Closing


When the PRODUCT_STATE becomes CLOSED, the device disables debug access. The firmware will still run normally, but the debugger cannot connect. Option bytes are locked, flash is protected, and OTP cannot be modified. The only supported way to reopen the device is through debug authentication using the correct password.


This mechanism allows production units to be shipped in a locked state while still allowing controlled recovery in manufacturing.


Debug Authentication and Regression


To perform regression, the programmer must provide the same password that was used to generate the OTP hash. In the Cyclone control interface, regression is enabled in the security settings, and the password is entered before connecting to the device. If the password is correct, the device performs a mass erase and returns to the OPEN state. Flash and option bytes are erased, but OTP memory remains unchanged.



The same operation can also be performed using the PEmicro Connection Manager or PROGACMP by enabling regression and entering the password in the security dialog before connecting.




After regression completes, the device behaves like a new device in the OPEN state and can be programmed again.


Production Programming Flow


In a typical production line, the device starts in the OPEN state. Then, OTP data and security configuration are programmed while in the PROVISIONING state. After the firmware is written and verified, the device is moved to the CLOSED state and shipped. If rework is required, regression is performed using the stored password, returning the device to OPEN so it can be programmed again.


This flow allows secure manufacturing while still providing controlled recovery capability.


Conclusion


The STM32H503 lifecycle security combined with Cyclone production programming provides a reliable method for secure provisioning in manufacturing. The use of PRODUCT_STATE transitions, OTP password hashing, and regression authentication ensures that firmware and configuration data remain protected while still allowing authorized reprogramming when necessary.


This approach is well-suited for high-volume production, IoT devices, industrial controllers, and any application where firmware security is required.


For more information on STM32H5 devices and their capabilities, check out the official documentation here.

Comments


bottom of page