How to start with code confidentiality on STM32H7S

How to start with code confidentiality on STM32H7S

Literature

Target description
The purpose of this article is to explain step by step how to encrypt an application and use the MCE to decrypt it, based on the MCE execute AES crypted code STM32CubeFW example provided by ST. The user application flashed during the provisioning is the GPIO_IOToggle example from STM32CubeFW, that will be encrypted and installed in external memory.

Introduction
In this "getting started" a simple way to encrypt and flash a user application in external memory, to provision the chip and to execute the encrypted code is shown based on the example provided in STM32CubeFW. Through this practical example, you will learn:

  • How to use the STM32CubeFW example, which is provided.
  • How to encrypt an application using OpenSSL.
  • How to install the boot example and the encrypted application.

Prerequisites

  • Hardware
    • STM32H7S discovery board: the STM32H7S devices have all the available security features, including the HW crypto accelerator (the HW cryptographic acceleration is not support for STM327R devices).
    • Discovery MB1736- STM32H7S (need USBC cable)
STM32H7S DK.png
  • Required tools
    • STM32Cube_FW_H7RS_V1.0.0 or later
    • STM32CubeProgrammer v2.18.0 or more recent (with trusted package creator (TPC) selected at installation)
    • IAR Embedded Workbench® rev 9.60.2 or later
    • Tera Term / Putty or equivalent terminal emulator
  • STM32Cube Firmware
    • Download the STM32Cube_FW_H7RS Cube firmware (advise is to place it close form the C: in order to avoid long windows paths).
    • A directory STM32H7S78-DK is included in "STM32Cube_FW_H7RS\Projects" .

1. Application binary generation

  • Open the GPIO_IOToggle example.
  • First go to Options -> Output Converter and change the format to Raw binary, then click on OK.
  • In Options -> Linker -> Config click on Edit... to update the .icf file.

This example has been made to be stored in flash, so the address needs to be updated to have addresses inline with our storage in external memory. Update the Vector Table and Memory Regions as it follows :

ICF File Updated For Execution In External Memory
  • Compile the project.

2. Application encryption

The application can be encrypted in three different modes :

  • Block cipher
  • Fast block cipher
  • Stream cipher

The two block cipher mode encryptions (normal and fast) will be done through the STM32TrustedPackageCreator tool. The stream cipher mode will be done using the AES-128 CTR algorithm available in OpenSSL.

2.1. Block mode

STM32TrustedPackageCreator tool provides a way to encrypt the application in block mode using a simple command line and a binary file containing the key used.

  • Create a binary file (.bin) containing only the key for the encryption :
7123456789ABCDEF7123456789ABCDEF
  • Use STM32TrustedPackageCreator to create the encrypted binary file :
STM32TrustedPackageCreator_CLI.exe -mce -app %fw_location%\Projects\STM32H7S78-DK\Examples\GPIO\GPIO_IOToggle\EWARM\Appli\GPIO_IOToggle_Appli\Exe\GPIO_IOToggle_Appli.bin -key %key_location%\key.bin -directory %fw_location%\Projects\STM32H7S78-DK\Examples\GPIO\GPIO_IOToggle\EWARM\Appli\GPIO_IOToggle_Appli\Exe -add 0x90000000 -mode 0

Replace %fw_location% by the STM32Cube_FW_H7RS location, and %key_location% by the key location. The -add argument refers to the address where the encrypted application will be loaded. The -mode argument allows to select the block mode : 0 for the normal block cipher, 1 for the fast block cipher.

This will generate the encrypted application binary Encrypted_Image.bin.

2.2. Stream mode

The application is encrypted in stream mode using the AES-128 CTR algorithm available in OpenSSL. The data encryption with AES 128 CTR is handled in 16 byte block unit (128bit). A binary file generated from an IDE (e.g. IAR) is in order from lower address to higher address. The binary file need to be pre-processed before encryption and post-processed after encryption for the data ordering. The pre-processing and post-processing consist on a byte swap for every 16 bytes block :

Byte swap for every 16 bytes block

The byte swap can be performed through a script, for example we used the xxd command available by installing the related script (native command for Linux, can be found by searching xxd-for-windows in a browser).

The following commands must be executed in a command prompt, opened in the same folder as the generated binary, after the OpenSSL installation and the binary generation from the GPIO_IOToggle example.

  • First byte swap :
xxd.exe -e -g 16 GPIO_IOToggle_Appli.bin > tmp.txt
xxd.exe -r tmp.txt > tmp.bin
  • Encryption :
openssl enc -aes-128-ctr -nosalt -e -in tmp.bin -out tmp_enc.bin -iv C3C3C3C3A5A5A5A50000FEDC09000000 -K 89ABCDEF7123456789ABCDEF71234567
  • Second byte swap :
xxd.exe -e -g 16 tmp_enc.bin > tmp.txt
xxd.exe -r tmp.txt > Encrypted_Image.bin

The -K option refers to the key used and -iv refers to the initialization vector necessary to perform the encryption. Both can be configurable but need to be updated in the MCE configuration in MCE_ExecuteAESCryptedCode_Boot example.

MCE Key and IV parameters location to be updated in the main.c file of the MCE_ExecuteAES_CryptedCode_Boot example.

Care must be taken when declaring the IV and Key. The Key parts declared in the boot example needs to be swapped for the OpenSSL encryption. Same for the nonce that needs to be swapped to become the first half of the IV. Regarding the IV, it is the equivalent of the MCE counter[127:0] data block. For more information about the MCE implementation of stream cipher, refer to the dedicated chapter in the reference manual [1]

Correlation between OpenSSL Key and IV and MCE parameters configuration

Temporary files tmp.txt, tmp.bin, and tmp_enc.bin can be deleted after the process.

3. MCE_ExecuteAESCryptedCode_Boot configuration

  • Open the MCE_ExecuteAESCryptedCode_Boot example.
  • The MCE_ExecuteAESCryptedCode_Boot example code is flashing in the external memory an encrypted application image.

Since we are using our own encrypted application, this line must be deleted in the private include section in main.c file :

Line to be deleted in main.c
  • Update the MCE configuration depending on the encryption mode used for the application in previous steps :
Stream Cipher mode enabled in the MCE configuration











RegionConfig.Mode value must be chosen between MCE_BLOCK_CIPHER, MCE_FASTBLOCK_CIPHER or MCE_STREAM_CIPHER. If the IV and Key have been updated, parameters such as the key, the nonce and the version of the MCE configuration need to be updated. For the block modes only the Key update is needed. Regarding the stream mode, refer to the picture in previous step to avoid mistake during these parameters update. For more information about the MCE implementation and configuration of the block and stream ciphers, refer to the dedicated chapter in the reference manual[1]

  • Generate the .bin file :

First go to Options -> Output Converter and change the format to Raw binary, then click on OK.

Output configuration to be changed to binary file
  • Compile the project.

4. Debug Authentication

The STM32 debug authentication controls the product life cycle, such as regressions (for more details about the life cycle, refer to the reference manual), debug reopening, and download forcing. When the STM32 product state is not open, the user can trigger the debug authentication services by sending a password or a certificate chain to the STM32 device. These two options are named the debug authentication methods. In this How to we will use a debug authentication with certificate, with pre-configured certificate and debug authentication.

For more information on the debug authentication on STM32H7Rx/Sx please refer to the dedicated page : Debug authentication for STM32H7Rx/7Sx To understand how to configure and tailor the debug authentication on STM32H7rx/Rx please refer to the dedicated How to : How to start with DA access on STM32H7RS

5. Provisioning flow for the STM32H7Sx

This section describes the basic steps to provision a product in the targeted configuration. The command that will be used have to be entered in a command prompt. The function RSSLIB_PFUNC->DataProvisioning uses SRAM3 so a prerequisite is to ensure that SRAM3 is fully available.

  • As a prerequisite to provisioning, check that DTCM_AXI_SHARE and ITCM_AXI_SHARE are cleared, and

if it is not the case, force them to 0:

STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -ob DTCM_AXI_SHARE=0 ITCM_AXI_SHARE=0
Provisioning flow and regression

Find below the CLI commands matching the steps 1, 2, 3 and 4 in Figure XX. This provisioning flow example integrates the OB setup (WRP, HDP, etc).

  • Step 1 : Set the PRODUCT_STATE to provisioning
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -psrss 0x17

This step must be done in the open product state. The product state can only be written with “-psrss” (product State RSS change). This is handled by RSSLIB_PFUNC->SetProductState(). More information about this function is available in the STM32H7Rx/7Sx reference manual[1]

  • Step 2 : Provision the OBKeys for DA
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -hardRst
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -sdp ./../DA/Binary/DA_Config.obk
  • Step 3 : Remove the protections, load MCE_ExecuteAESCryptedCode_Boot.bin in user flash and Encrypted_Image.bin in external flash
    • Remove :
  • The write protection through the programming register FLASH_WRPSRP. Address: 0x5200221C, mask: 0x000000FF, value: 0xFF, bit shift: 0x00.
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR >> nul
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -obrss 0x5200221C 0x000000FF 0xFF 0x00
  • The HDP protection through the programming register FLASH_HDPSRP. Address: 0x52002234, mask: 0x00FF00FF, value: 0x000000FF, bit shift: 0x00.
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR >> nul
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -obrss 0x52002234 0x00FF00FF 0x000000FF 0x00
  • Erase the user flash :
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR >> nul
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -e all
  • Set SRAM ECC protection and XSPI configuration (needed to use external memories) :
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -ob ECC_ON_SRAM=1
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -ob XSPI1_HSLV=1
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -ob XSPI2_HSLV=1
  • Download the binary in user flash and set the related protections :

Replace %fw_location% by the STM32Cube_FW_H7RS location.

STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -d %fw_location%\Projects\STM32H7S78-DK\Examples\MCE\MCE_ExecuteAESCryptedCode\EWARM\Boot\MCE_ExecuteAESCryptedCode_Boot\Exe\MCE_ExecuteAESCryptedCode_Boot.bin 0x8000000 -v
  • Set WRP and HDP protections on user flash :
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR >> nul
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -obrss 0x5200221C 0x000000FF 0 0x00

STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR >> nul
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -obrss 0x52002234 0x00FF00FF 0x00FF0000 0x00
  • Download the encypted binary in external flash :

Replace %com_port% by the connected COM port. Replace %fw_location% by the STM32Cube_FW_H7RS location. MX66UW1G45G_STM32H7S78-DK_XSPIM1-SFIx.stldr is used with the external flash MX66UW1G45G with the swapped mode of the XSPI I/O manager enabled. This means that the external flash is mapped at 0x90000000.

STM32_Programmer_CLI.exe -c port=%com_port% br=921600 -elbl "C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\ExternalLoader\MX66UW1G45G_S
TM32H7S78-DK_XSPIM1-SFIx.stldr" -d %fw_location%\Projects\STM32H7S78-DK\Examples\GPIO\GPIO_IOToggle\EWARM\Appli\GPIO_IOToggle_Appli\Exe\Encrypted_Image.bin 0x90000000 --verify
  • Step 4 : Change PRODUCT_STATE to closed
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -psrss 0x72
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR >> nul

The command STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=UR is used to force a reset on the device but results in an expected error No STM32 target found! since the product state is at least provisioning.

6. Managing regression

If the process requires a full regression of the product, launch a regression using the debug authentication. It corresponds to the step 5 in Figure XX.

STM32_Programmer_CLI.exe -c port=SWD speed=fast per=a key=.\Keys\key_3_leaf.pem cert=.\Certificates\cert_leaf_chain.b64 debugauth=1

The STM32CubeProgrammer command debugauth is described in the STM32CubeProgrammer documentation. The example files (.pem and .b64) can be found in the folders (Keys and Certificates) in STM32Cube_FW_H7RS_V1.0.0\Projects\STM32H7S78-DK\ROT_Provisioning\DA.

In the CubeFW example, the requested action is linked with the “per” (permissions) parameter. The list of allowed permissions is detailed below. Syntax: per=[Permission] The user can choose from the following permission values: • “a”: Full regression • “b”: Debug opening Level 3 • “c”: Debug opening Level 2 • “d”: Debug opening Level 1 • “e”: Forced download

7. Verifying the product configuration

At any stage of the provisioning, the product configuration can be verified. This paragraph describes several possibilities to perform checks.

  • Product state

When moving to closed product state, the available interfaces become very limited. In the closed product state, the debug authentication allows through the discovery command to get device information.

STM32_Programmer_CLI.exe -c port=SWD debugauth=2
  • User flash provisioning

The command used to provision the MCE_ExecuteAESCryptedCode_Boot binary in the user flash is :

STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -d %fw_location%\Projects\STM32H7S78-DK\Examples\MCE\MCE_ExecuteAESCryptedCode\EWARM\Boot\MCE_ExecuteAESCryptedCode_Boot\Exe\MCE_ExecuteAESCryptedCode_Boot.bin 0x8000000 -v

The -v is for --verify, to ensure that the download is successfully executed. %fw_location%is the STM32Cube_FW_H7RS location.

  • External flash provisioning

The command used to provision the GPIO_IOToggle_Crypted binary in the external flash is :

STM32_Programmer_CLI.exe -c port=%com_port% br=921600 -elbl "C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\ExternalLoader\MX66UW1G45G_STM32H7S78-DK_XSPIM1-SFIx.stldr" -d %fw_location%\Projects\STM32H7S78-DK\Examples\GPIO\GPIO_IOToggle\EWARM\Appli\GPIO_IOToggle_Appli\Exe\Encrypted_Image.bin 0x90000000 –verify

%com_port% must be replaced by the connected COM port and %fw_location% is the STM32Cube_FW_H7RS location.

  • Option bytes

Find below a command line example that is used to set option bytes :

STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -ob ECC_ON_SRAM=1

This command checks that the option byte is properly written. When the execution result is positive, the change is successfully completed. To ensure that the option byte is changed successfully, add -ob displ in the command line, or have a dedicated line to check all the option bytes changes you have done. -ob displ prints all the OB values.

  • OBKeys

Find below command line examples that are used to set OBKeys :

STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -hardRst
STM32_Programmer_CLI.exe -c port=SWD speed=fast ap=1 mode=Hotplug -sdp ./../DA/Binary/DA_Config.obk

When calling the -sdp command, a positive feedback OBKey Provisioned successfully means data are written as expected.

8. References