Secure Boot on STM32MP1

Secure Boot is a key feature towards having a secure platform. The STM32MP1 boot sequence supports a trusted boot chain. This ensures that the loaded images are authenticated and integrity checked before being used.

Our Implementation

The LmP uses U-Boot as the bootloader, with TF-A BL2 as the first stage loader. The Secure Boot implementation puts the IC in a secure state, accepting only signed TF-A BL2 firmware.

Next, TF-A boots the trusted execution environment—OP-TEE—where we run an ‘early’ trusted application: fiovb (Foundries.io Verified Boot). This trusted application provides secure access to the Replay Protected Memory Block partition in eMMC. This is used to store keys, firmware, and rollback information.

OP-TEE also prepares the next stage bootloader—U-Boot—and generates an overlay DTS for Linux® kernel consumption. U-boot also implements the fiovb command to validate the trusted application functionality. U-boot then jumps to the kernel entry point.

Generate RoT ECC key Pair

The first step is generating the ECC key pair and committing the fuse table to the hardware. This can be done with the STM32 KeyGen tool, part of the STM32CubeProgrammer SDK software package.

Note

For development purposes, we keep sample keys and certificates at lmp-tools/security/stm32mp1.

Here is an example of generating a key pair using the KeyGen tool:

$ cd STM32CubeProgrammer
STM32CubeProgrammer$ ./bin/STM32MP_KeyGen_CLI
-------------------------------------------------------------------
                STM32MP Key Generator v2.10.0
-------------------------------------------------------------------

STM32AP Key Generator [Version v2.10.0] <'-? for help>
Copyright (c) 2018 STMicroelectronics. All rights reserved.
Please enter Path for output files  < /tmp/ >
/tmp/
Please enter Password
Please re-enter your Password
Please select algorithm:  1. prime256v1   2. brainpoolP256t1 (1/2)?
1
Please select encrypting algorithm:  1. aes256   2. aes128 (1/2)?
1
Prime256v1 curve is selected.
AES_256_cbc algorithm is selected for private key encryption
Generating Prime256v1 keys...
Private key PEM file created
Public key PEM file created
public key hash file created
Keys generated successfully.
+ public key:       /tmp/publicKey.pem
+ private key:      /tmp/privateKey.pem
+ public hash key:  /tmp/publicKeyhash.bin

Note

The password for lmp-tools sample keys is foundries.

The tool also generates a third file containing the public key hash (PKH) that should be fused to OTP. This is used to authenticate the public key on the target. For more details refer to ST’s STM32 KeyGen tool guide.

How to Secure the Platform (Automatic Approach)

This approach can be used for both STM32MP15 Discovery and the Evaluation kits.

Automatic Signing Using LmP

The FSBL binary (TF-A BL2) must be signed using a key pair generated by STM32MP_KeyGen_CLI. There are two possible ways to do this: during LmP build time, or manually, before deploying binaries to a destination board. In both cases, the STM32 Signing tool needs to be installed.

To enable implicit, automatic signing of boot images during build time, uncomment the following lines in your conf/local.conf:

#
# STM32CubeProgrammer STM32MP Signing Tool configuration
#
STM32_ROT_SIGN_ENABLE ??= "1"
STM32_CUBE_PATH ??= "/usr/local/STMicroelectronics/STM32Cube/STM32CubeProgrammer"
STM32_ROT_KEY_PATH ??= "${TOPDIR}/../tools/lmp-tools/security/stm32mp1/"
STM32_ROT_KEY_PATH[vardepsexclude] += "TOPDIR"
STM32_ROT_KEY_PASSWORD ??= "foundries"
  • STM32_CUBE_PATH contains the correct path to STM32Cube installation.
  • STM32_ROT_KEY_PATH contains the correct path to generated RoT key pair.
  • STM32_ROT_KEY_PASSWORD contains the correct password to RoT private key.

To sign boot images manually using the STM32 Signing tool, sign each tf-a-*.stm32 image in the flashlayouts-stm32mp1 deploy directory. Place them alongside the unsigned binaries:

flashlayouts-stm32mp1$ ls -lah
total 558M
drwxr-xr-x 2 user user 4,0K aug 17 12:47 .
drwxr-xr-x 9 user user  12K aug 17 12:48 ..
-rwxr-xr-x 1 user user  28K aug 17 12:47 create_sdcard_from_flashlayout.sh
-rw-r--r-- 1 user user 1,5M aug 17 12:47 fip-stm32mp157c-dk2-optee.bin
-rwxr-xr-x 1 user user  609 aug 17 12:47 FlashLayout_sd_stm32mp157c-dk2-optee.tsv
-rw-r--r-- 1 user user 709M aug 17 12:47 lmp-base-console-image-stm32mp15-disco-sec.ext4
-rw-r--r-- 1 user user 198K aug 17 12:47 tf-a-stm32mp157c-dk2-sdcard_Signed.stm32
-rw-r--r-- 1 user user 198K aug 17 12:47 tf-a-stm32mp157c-dk2-sdcard.stm32
-rw-r--r-- 1 user user 198K aug 17 12:47 tf-a-stm32mp157c-dk2-emmc_Signed.stm32
-rw-r--r-- 1 user user 198K aug 17 12:47 tf-a-stm32mp157c-dk2-emmc.stm32
-rw-r--r-- 1 user user 194K aug 17 12:47 tf-a-stm32mp157c-dk2-uart_Signed.stm32
-rw-r--r-- 1 user user 194K aug 17 12:47 tf-a-stm32mp157c-dk2-uart.stm32
-rw-r--r-- 1 user user 198K aug 17 12:47 tf-a-stm32mp157c-dk2-usb_Signed.stm32
-rw-r--r-- 1 user user 198K aug 17 12:47 tf-a-stm32mp157c-dk2-usb.stm32

Create combo* images using signed binaries in the deploy directory:

flashlayouts-stm32mp1$ cp tf-a-stm32mp157c-dk2-emmc_Signed.stm32 combo-emmc-tfa-fip-stm32mp157c-ev1.bin
flashlayouts-stm32mp1$ dd if=fip-stm32mp157c-dk2-optee.bin of=combo-emmc-tfa-fip-stm32mp157c-ev1.bin bs=1024 seek=256 conv=notrunc

Adjust the FlashLayout file, so it uses the signed version (s/tf-a-stm32mp157c-ev1-usb.stm32/tf-a-stm32mp157c-ev1-usb_Signed.stm32/g):

flashlayouts-stm32mp1$ cat FlashLayout_emmc_stm32mp157c-ev1-optee.tsv
#Opt    Id      Name            Type            IP      Offset          Binary
-       0x01    fsbl-boot       Binary          none    0x0             tf-a-stm32mp157c-ev1-usb_Signed.stm32
-       0x03    fip-boot        Binary          none    0x0             fip-stm32mp157c-ev1-optee.bin
PD      0x04    fsbl1           Binary          mmc1    boot1           combo-emmc-tfa-fip-stm32mp157c-ev1.bin
PD      0x05    fsbl2           Binary          mmc1    boot2           combo-emmc-tfa-fip-stm32mp157c-ev1.bin
PED     0x06    u-boot-env      Binary          mmc1    0x00080000      none
P       0x10    rootfs          System          mmc1    0x00100000      lmp-base-console-image-stm32mp15-eval.ext4

Provision PKH, HUK and RPMB

The stm32-mfgtool-files recipe contains the tools needed for provisioning PKH/HUK, and programming the RPMB key on the destination device. To use, build the lmp-mfgtool distro:

$ DISTRO=lmp-mfgtool MACHINE=stm32mp15-eval-sec . setup-environment
$ bitbake stm32-mfgtool-files

Warning

If automatic signing is disabled, sign all boot images manually, and copy to the stm32-mfgtool-files directory before executing provision.sh. See the Sign and Deploy the BL2 Image Manually section for a similar approach for flashlayout-stm32mp1.

Switch to user root, and add the path to STM32Cube to PATH:

sudo -s
export PATH=$PATH:<path_to_stm32cube>

Execute script, providing the path to the PKH binary file:

cd deploy/images/stm32mp15-eval-sec
./stm32-mfgtool-files/provision.sh --pub-key-hash <key_dir>/publicKeyhash.bin
ubkey: dab712cd a4b45564 f70a5706 2135e39c 88e89139 0c20219b 93da5419 c65d1fbd
ount: 8
      -------------------------------------------------------------------
                       STM32CubeProgrammer v2.11.0
      -------------------------------------------------------------------

...
...
rovision is finished

After execution, the device is provisioned with PKH and HUK values. The RPMB key (relevant only when eMMC-based board is used) is programmed as well.

Flash System Images to SD/eMMC

How to Secure the Platform (Manual Approach)

Fuse PKH Manually

If you need to fuse the public key hash manually, copy it to the first FAT partition of your SD boot card. During the boot process, drop into the U-Boot console and run these commands:

=> mmc rescan
=> STM32MP> fatls mmc 0:4
   3007   boot.itb
     32   publicKeyhash.bin
=> load mmc 0:4 0xc0000000 publicKeyhash.bin
=> stm32key read 0xc0000000
Read KEY at 0xc0000000
OTP value 24: 1ce94f90
OTP value 25: 971d082f
OTP value 26: d443cf29
OTP value 27: f7c345d4
OTP value 28: 14873635
OTP value 29: b288ad40
OTP value 30: 38841b57
OTP value 31: b7a16954

Warning

Once the fuses have been programmed, they can not be modified.

Verify that stm32key has printed valid key hashes. If everything is correct, fuse these values to OTP:

=> stm32key fuse 0xc0000000

The device now contains public key hashes to authenticate boot images. To validate, read back the OTP, using the same stm32key command:

=> stm32key read
OTP HASH 24: 1ce94f90 lock : 0
OTP HASH 25: 971d082f lock : 0
OTP HASH 26: d443cf29 lock : 0
OTP HASH 27: f7c345d4 lock : 0
OTP HASH 28: 14873635 lock : 0
OTP HASH 29: b288ad40 lock : 0
OTP HASH 30: 38841b57 lock : 0
OTP HASH 31: b7a16954 lock : 0
OTP 0: closed status: 0 lock : 0
HASK key is not locked!

Sign and Deploy the BL2 Image Manually

STM32 Signing tool allows you to fill the STM32 binary header that is parsed by the embedded software to authenticate each binary.

To sign the image run:

STM32CubeProgrammer$ ./bin/STM32MP_SigningTool_CLI -bin /build-lmp/deploy/images/stm32mp15-disco/arm-trusted-firmware/tf-a-stm32mp157c-dk2-sync -pubk /tmp/publicKey.pem -prvk /tmp/privateKey.pem -iv 5 -pwd qwerty123 -t fsbl
-------------------------------------------------------------------
           STM32MP Signing Tool v2.10.0
-------------------------------------------------------------------

Prime256v1 curve is selected.
Header version 1 preparation ...
Reading Private Key File...
ECDSA signature generated.
Signature verification:  SUCCESS
The Signed image file generated successfully:  /build-lmp/deploy/images/stm32mp15-disco/arm-trusted-firmware/tf-a-stm32mp157c-dk2-sdcard_Signed.stm32

Validate that signature and sign info (algo etc) were added to the image:

STM32CubeProgrammer$ ./bin/STM32MP_SigningTool_CLI -dump /build-lmp/deploy/images/stm32mp15-disco/arm-trusted-firmware/tf-a-stm32mp157c-dk2-sdcard_Signed.stm32
Magic: 0x53544d32
Signature: f1 f7 3e 73 35 38 a5 00 43 b2 78 fe cd 12 0a ec 39 2e 8a c7 60 35 f4 1f 7f 47 1a 99 11 8a 5b 07
           9e dc 1c 51 27 bc e2 e0 4c cf 23 6d 87 92 cb c9 a6 ea a1 7f b0 30 18 f4 73 d5 18 ef 50 c6 56 e3
Checksum: 0x6d09b9
Header version: 0x10000
Size: 0x36fd1
Load address: 0x2ffc2500
Entry point: 0x2ffe9000
Image version: 0x5
Option flags: 0x0
ECDSA Algo: 0x1
ECDSA pub key: f9 0e db 1b d6 91 a5 9d 9f d9 0a a8 63 f2 8b 4c ca 37 c6 65 48 e3 5b 5a 69 b8 8f a9 72 b1 3f 44
               01 df ae 4c cd 99 12 bc d3 fc 9b 30 7a 77 c5 2b f0 5b 01 f3 2e bb c3 71 db a4 40 93 2c 01 3f a2
Binary type: 0x10

When a WIC image is used for flashing, deploy the signed images to the SD card after flashing the WIC image. Here the existing unsigned images must be replaced. This can be achieved with a dd command as well (instead of mmcblkx specify correct device):

$ sudo dd if=/build-lmp/deploy/images/stm32mp15-disco/arm-trusted-firmware/tf-a-stm32mp157c-dk2-sdcard_Signed.stm32 bs=1024 seek=17 of=/dev/mmcblkx
$ sudo dd if=/build-lmp/deploy/images/stm32mp15-disco/arm-trusted-firmware/tf-a-stm32mp157c-dk2-sdcard_Signed.stm32 bs=1024 seek=273 of=/dev/mmcblkx

Warning

dd is not needed if the FlashLayout approach is used.

Booting Signed Images

When a signed binary is used, the BootROM code will authenticate and start the FSBL, which will report authentication status:

NOTICE:  CPU: STM32MP157CAC Rev.B
NOTICE:  Model: STMicroelectronics STM32MP157C-DK2 Discovery Board
NOTICE:  Board: MB1272 Var2.0 Rev.C-01
NOTICE:  Bootrom authentication succeeded <------- auth confirmation

A Bootrom authentication succeeded message means that BootROM managed to authenticate the FSBL image and the device can be closed. If the device is not closed, it will be still able to perform image authentication. However,it will boot the image regardless of the result of that authentication.

Closing the Device

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

OTP WORD0 bit 6 is the OTP bit that closes the device. Fusing this bit will lock authentication processing, and force authentication from the BootROM. Unsigned binaries will no longer be supported on the target.

To close the device by fusing OTP WORD0 bit 6, run the stm32key cmd in U-Boot:

=> stm32key close