Last edited 4 months ago

STM32 MPU ROM code secure boot

1. Purpose[edit | edit source]

Secure boot is a key feature to guarantee a secure platform.

STM32MP1 boot sequence supports a trusted boot chain that ensures that the loaded images are authenticated and checked in integrity before being used.

Warning.png The secure boot feature availability is indicated in the security field of the chip part number.

2. Authentication processing[edit | edit source]

STM32 MPU provides authentication processing with ECDSA [1] verification algorithm, based on ECC [2]. ECDSA offers better result than RSA with a smaller key. STM32 MPU relies on a 256 bits ECDSA key.

Two algorithms are supported for ECDSA calculation:

  • P-256 NIST
  • Brainpool 256

The algorithm selection is done via the signed binary header, as shown in STM32 header (subchapter in this same article).

The EDCSA verification follows the process below:

2.1. Key generation[edit | edit source]

First step is to generate the ECC pair of keys with STM32 KeyGen tool. This is the key pair that will be used to sign the images.
The tool also generates a third file containing the public key hash (PKH) that will be used to authenticate the public key on the target.

2.2. Key registration[edit | edit source]

Warning.png Make sure that a device with Secure boot enabled is used: this is mentionned in the part number, otherwise the device will become permanently unusable.

2.2.1. Register hash public key[edit | edit source]

First step to enable the authentication is to burn the OTP WORD 24 to 31 in BSEC with the corresponding public key hash (PKH, output file from STM32 KeyGen). OpenSTLinux embeds a stm32key tool that can be called from U-Boot command line interface to program the PKH into the OTP.
Make sure that a trusted image was programmed on your board, because below operation will not be possible with optee boot.

PKH file (publicKeyhash.bin) must be available in a filesystem partition (like bootfs) on a storage device (like sdcard) before proceeding.

 Board $> ext4load mmc 0:4 0xc0000000 publicKeyhash.bin                  Load hash file from mmc 0 partition 4 (ext4) in DDR
 32 bytes read in 50 ms (0 Bytes/s)
 Board $> stm32key read 0xc0000000                                       Read loaded key from DDR to confirm it is valid (without writing it in OTP)
 OTP value 24: 12345678
 OTP value 25: 12345678
 OTP value 26: 12345678
 OTP value 27: 12345678
 OTP value 28: 12345678
 OTP value 29: 12345678
 OTP value 30: 12345678
 OTP value 31: 12345678
Warning.png If hash key is ok, the key in OTP can be fused
 Board $> stm32key fuse -y 0xc0000000                                    Write the key in OTP

The device now contains the hash to authenticate images. To read back the OTP, you can use NVMEM framework.

2.3. Image signing[edit | edit source]

In a second step, FSBL and SSBL binaries must be signed. STM32 Signing tool allows to fill the STM32 binary header that is parsed by the embedded software to authenticate each binary.

2.3.1. STM32 Header[edit | edit source]

STM32 header.png

Each binary image (signed or not) loaded by ROM code and by TF-A need to include a specific STM32 header added on top of the binary data. The header includes the authentication information.

Name Length Byte Offset Description
Magic number 32 bits 0 4 bytes in big endian:
'S', 'T', 'M', 0x32 = 0x53544D32
Image signature 512 bits 4 ECDSA signature for image authentication[Note 1]
Image checksum 32 bits 68 Checksum of the payload[Note 2]
Header version 32 bits 72 Header version v1.0 = 0x00010000
Byte0: reserved
Byte1:major version = 0x01
Byte2: minor version = 0x00
Byte3: reserved
Image length 32 bits 76 Length of image in bytes[Note 3]
Image entry Point 32 bits 80 Entry point of image
Reserved1 32 bits 84 Reserved
Load address 32 bits 88 Load address of image[Note 4]
Reserved2 32 bits 92 Reserved
Version number 32 bits 96 Image Version (monotonic number)[Note 5]
Option flags 32 bits 100 b0=1: no signature verification[Note 6]
ECDSA algorithm 32 bits 104 1: P-256 NIST ; 2: brainpool 256
ECDSA public key 512 bits 108 ECDSA public key to be used to verify the signature.[Note 7]
Padding 83 Bytes 172 Reserved padding bytes[Note 8]. Must all be set to 0
Binary type 1 Byte 255 Used to check the binary type
0x00: U-Boot
0x10-0x1F: TF-A
0x20-0X2F: OPTEE
0x30: Copro
  1. Signature is calculated from first byte of header version field to last byte of image given by image length field.
  2. 32-bit sum of all payload bytes accessed as 8-bit unsigned numbers, discarding any overflow bits. Used to check the downloaded image integrity when signature is not used (if b0=1 in Option flags).
  3. Length is the length of the built image, it does not include the length of the STM32 header.
  4. This field is not used by ROM code.
  5. Image version number is an anti rollback monotonic counter. The ROM code checks that it is higher or equal to the monotonic counter stored in OTP.
  6. Enabling signature verification is mandatory on secure closed chips.
  7. This field is an extract of PEM public key file that only kept the ECC Point coordinates x and y in a raw binary format (RFC 5480). This field will be hashed with SHA-256 and compared to the Hash of pubKey that is stored in OTP.
  8. This padding forces STM32 header size to 256 bytes (0x100).


For STM32MP15x lines More info.png:

2.4. Image programming[edit | edit source]

Once the images are signed, they can be programmed into the flash on the target board with STM32CubeProgrammer.

2.5. PKH check[edit | edit source]

Before really starting the authentication process, the ROM code compares the hash of the public key carried in the STM32 header with the one that was provisionned in OTP.

2.6. Authentication[edit | edit source]

2.6.1. Bootrom authentication[edit | edit source]

Using a signed binary, the ROM code authenticates and starts the FSBL.

If the authentication fails, the ROM code enters into a serial boot loop indicated by the blinking Error LED (cf Bootrom common debug and error cases)

The ROM code provides secure services to the FSBL for image authentication with the same ECC pair of keys, so there is no need to support ECDSA algorithm in FSBL.

2.6.2. TF-A authentication[edit | edit source]

TF-A is the FSBL used by the Trusted boot chain. It is in charge of loading and verifying U-boot and (if used) OP-TEE image binaries.

Each time a signed binary is used, TF-A will print the following status:

INFO:    Check signature on Non-Full-Secured platform

If the image authentication fails the boot stage traps the CPU and no more trace is displayed.

2.7. Closing the device[edit | edit source]

Notice that this last step is not shown in the diagram above.

Without any other modification, the device is able to perform image authentication but non authenticated images can still be used and executed: the device is still opened, let's see this as a kind of test mode to check that the PKH is properly set.

As soon as the authentication process is confirmed, the device can be closed and the user forced to use signed images.

OTP WORD0 bit 6 is the OTP bit that closes the device. Burning this bit will lock authentication processing and force authentication from the Boot ROM. Non signed binaries will not be supported anymore on the target.

To program this bit, the STM32CubeProgrammer or U-Boot command line interface can be used.

Here is how to proceed with U-Boot:

 Board $> fuse prog 0 0x0 0x40
Warning.png Once this bit is written the platform is locked