DHCOM STM32MP15 Secure Boot: Difference between revisions
m Fix plural of SoC →Write U-Boot SPL and U-Boot to your boot media |
Jneuhauser (talk | contribs) →Secure Boot in Trusted Boot with BootROM authentication, TF-A and OP-TEE: Update upstreaming status |
||
(27 intermediate revisions by 2 users not shown) | |||
Line 9: | Line 9: | ||
<div class="toclimit-3">__TOC__</div> | <div class="toclimit-3">__TOC__</div> | ||
= Introduction = | |||
== Abbreviations == | |||
<!--TODO: Check for non listed/used abbreviation--> | <!--TODO: Check for non listed/used abbreviation--> | ||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
Line 21: | Line 21: | ||
| CoM || Computer on module | | CoM || Computer on module | ||
|- | |- | ||
| FIT || Flattened Image Tree | | FIT || Flattened Image Tree (U-Boot) | ||
|- | |- | ||
| FSBL || Fist Stage Bootloader (TF-A or U-Boot SPL) | | FSBL || Fist Stage Bootloader (TF-A or U-Boot SPL) | ||
|- | |||
| ITS || Image Tree Source (U-Boot) | |||
|- | |- | ||
| OTP || One Time Programmable (eFuses) | | OTP || One Time Programmable (eFuses) | ||
Line 46: | Line 48: | ||
|} | |} | ||
== Secure Boot == | |||
The term Secure Boot originally comes from the UEFI specification<ref name="UEFI specification" /> and describes a secure boot process in which only signed software is loaded and executed during the boot process. | The term Secure Boot originally comes from the UEFI specification<ref name="UEFI specification" /> and describes a secure boot process in which only signed software is loaded and executed during the boot process. | ||
Line 59: | Line 61: | ||
Program code and certificate need to be trustworthy and therefore protected against tampering in each stage, otherwise the secure boot chain can be compromised. Except for the first stage, all binary images are protected against third-party tampering by the signature. As this is practically impossible for the first stage, manipulation protection has to be enforced by hardware measures to make said stage immutable, with the first stage's program code and the verification certificate for the second stage being stored in read-only memory (ROM). | Program code and certificate need to be trustworthy and therefore protected against tampering in each stage, otherwise the secure boot chain can be compromised. Except for the first stage, all binary images are protected against third-party tampering by the signature. As this is practically impossible for the first stage, manipulation protection has to be enforced by hardware measures to make said stage immutable, with the first stage's program code and the verification certificate for the second stage being stored in read-only memory (ROM). | ||
== Basic and trusted boot in the context of Secure Boot == | |||
When booting Linux on the STM32MP1 SoC with U-Boot SPL and U-Boot only, STM speaks of "Basic Boot"<ref name="Basic Boot" />. | When booting Linux on the STM32MP1 SoC with U-Boot SPL and U-Boot only, STM speaks of "Basic Boot"<ref name="Basic Boot" />. | ||
Line 73: | Line 75: | ||
|} | |} | ||
= Secure Boot in Basic Boot with BootROM authentication and Verified Boot = | |||
This Secure Boot implementation does use the the BootROM integrated image authentication to authenticate the U-Boot SPL as FSBL. | This Secure Boot implementation does use the the BootROM integrated image authentication to authenticate the U-Boot SPL as FSBL. | ||
Line 80: | Line 82: | ||
This also means that everything from U-Boot SPL onwards is platform independent, as we do not rely on hardware specific implementations. | This also means that everything from U-Boot SPL onwards is platform independent, as we do not rely on hardware specific implementations. | ||
== Verified Boot == | |||
Developers of Google's Chromium project worked out a concept for the Verified Boot called Secure Boot mechanism on the basis of the boot loader "Das U-Boot". | Developers of Google's Chromium project worked out a concept for the Verified Boot called Secure Boot mechanism on the basis of the boot loader "Das U-Boot". | ||
Line 91: | Line 93: | ||
The number of public keys that can be integrated is theoretically unlimited, but they must be distinguishable by name. | The number of public keys that can be integrated is theoretically unlimited, but they must be distinguishable by name. | ||
=== Technical details of Verified Boot === | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 120: | Line 122: | ||
|} | |} | ||
=== In-depth references for Verified Boot === | |||
<!--TODO: Use <references group="XYZ"><ref group="A" name="O">ABCDEF</ref></references>--> | <!--TODO: Use <references group="XYZ"><ref group="A" name="O">ABCDEF</ref></references>--> | ||
==== Flatten Image Tree ==== | |||
* [https://source.denx.de/u-boot/u-boot/tree/master/doc/uImage.FIT U-Boot Documentation: doc/uImage.FIT] | * [https://source.denx.de/u-boot/u-boot/tree/master/doc/uImage.FIT U-Boot Documentation: doc/uImage.FIT] | ||
* [https://source.denx.de/u-boot/u-boot/-/commit/d5934ad7 U-Boot Commit d5934ad7: "new uImage: Add dual format uImage support framework"] | * [https://source.denx.de/u-boot/u-boot/-/commit/d5934ad7 U-Boot Commit d5934ad7: "new uImage: Add dual format uImage support framework"] | ||
Line 129: | Line 131: | ||
* [https://source.denx.de/u-boot/u-boot/-/commit/3310c549 U-Boot Commit d5934ad7: "new uImage: Add new uImage format documentation and examples"] | * [https://source.denx.de/u-boot/u-boot/-/commit/3310c549 U-Boot Commit d5934ad7: "new uImage: Add new uImage format documentation and examples"] | ||
==== Verified Boot ==== | |||
<!--<references group="Verified Boot">--> | <!--<references group="Verified Boot">--> | ||
* [https://source.denx.de/u-boot/u-boot/tree/master/doc/uImage.FIT/signature.txt U-Boot Documentation: doc/uImage.FIT/signature.txt] | * [https://source.denx.de/u-boot/u-boot/tree/master/doc/uImage.FIT/signature.txt U-Boot Documentation: doc/uImage.FIT/signature.txt] | ||
Line 136: | Line 138: | ||
* [https://source.denx.de/u-boot/u-boot/-/commit/4d098529 U-Boot Commit 4d098529: "image: Add support for signing of FIT configurations"] | * [https://source.denx.de/u-boot/u-boot/-/commit/4d098529 U-Boot Commit 4d098529: "image: Add support for signing of FIT configurations"] | ||
==== ECDSA signature verification ==== | |||
<div style="color:red">TODO: Mention ECDSA limitations</div> | <div style="color:red">TODO: Mention ECDSA limitations</div> | ||
Line 145: | Line 147: | ||
* [https://source.denx.de/u-boot/u-boot/-/commit/ee870859 U-Boot Commit ee870859: "arm: stm32mp1: Implement ECDSA signature verification"] | * [https://source.denx.de/u-boot/u-boot/-/commit/ee870859 U-Boot Commit ee870859: "arm: stm32mp1: Implement ECDSA signature verification"] | ||
== Tutorial: Secure boot from BootROM to Linux with basic boot == | |||
=== System requirements and needed tools === | |||
The following table lists all requirements to create the key pairs and build the signed images with embedded public keys. | The following table lists all requirements to create the key pairs and build the signed images with embedded public keys. | ||
Line 166: | Line 168: | ||
* make | * make | ||
* openssl | * openssl | ||
* swig | |||
|- | |- | ||
| '''STM32 Tools''' || | | '''STM32 Tools''' || | ||
Line 174: | Line 177: | ||
<div style="color:red">TODO: Should we give host setup instructions?</div> | <div style="color:red">TODO: Should we give host setup instructions?</div> | ||
=== Add STM32CubeProrammer binaries to user environment === | |||
<syntaxhighlight lang="shell"> | |||
export PATH=${PATH}:~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin | |||
</syntaxhighlight> | |||
<!-- | <!-- | ||
'''Install debian packages:''' | '''Install debian packages:''' | ||
Line 183: | Line 191: | ||
--> | --> | ||
=== Intended use of the four generated key pairs === | |||
We've decided to create and use as few certificates as reasonable to ensure a high level of security. | We've decided to create and use as few certificates as reasonable to ensure a high level of security. | ||
Line 204: | Line 212: | ||
|} | |} | ||
=== Created/Modified files in the U-Boot source for Verified Boot === | |||
The created or modified files to build U-Boot with Verified Boot on STM32MP15 are described in the following table. | The created or modified files to build U-Boot with Verified Boot on STM32MP15 are described in the following table. | ||
Line 226: | Line 234: | ||
|} | |} | ||
=== Build Verified Boot enabled U-Boot SPL and U-Boot === | |||
To build the U-Boot SPL and U-Boot images, you need to check out the source code and run a build script that automates everything from key generation to image creation and signing. | To build the U-Boot SPL and U-Boot images, you need to check out the source code and run a build script that automates everything from key generation to image creation and signing. | ||
==== Checkout source code for Verified Boot ==== | |||
Checkout the branch <syntaxhighlight lang="shell" inline>v2022.01_dhcom_secure_boot</syntaxhighlight> from DH electronics GitHub repository with: | |||
Checkout the branch <syntaxhighlight lang="shell" inline>v2022.01_dhcom_secure_boot</syntaxhighlight> | |||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
git clone | git clone https://github.com/dh-electronics/u-boot-stm32mp1.git -b v2022.01_dhcom_secure_boot | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 243: | Line 250: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
cd /path/to/u-boot | cd /path/to/u-boot | ||
git remote add | git remote add u-boot-stm32mp1 https://github.com/dh-electronics/u-boot-stm32mp1.git | ||
git fetch | git fetch u-boot-stm32mp1 | ||
git checkout v2022.01_dhcom_secure_boot | git checkout v2022.01_dhcom_secure_boot | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Run the build script <syntaxhighlight lang="shell" inline>build_signed_uboot.sh</syntaxhighlight> ==== | |||
The shell script <syntaxhighlight lang="shell" inline>build_signed_uboot.sh</syntaxhighlight> included in the U-Boot source performs the following steps. | The shell script <syntaxhighlight lang="shell" inline>build_signed_uboot.sh</syntaxhighlight> included in the U-Boot source performs the following steps. | ||
Line 286: | Line 293: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
If this process completes without | If this process completes without errors, there are two boot loader images in the root directory of the U-Boot source. | ||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
|- | |- | ||
Line 293: | Line 300: | ||
| u-boot-spl.stm32 || FSBL || U-Boot SPL binary with appended Device Tree and prepended STM32 image header<ref name="STM32 image header" />. | | u-boot-spl.stm32 || FSBL || U-Boot SPL binary with appended Device Tree and prepended STM32 image header<ref name="STM32 image header" />. | ||
|- | |- | ||
| u-boot.itb || SSBL || U-Boot and Device Tree's contained in a | | u-boot-spl-signed.stm32 || FSBL || Same as above but as signed STM32 image. Is created in [[#Sign U-Boot SPL with STM32MP_SigningTool_CLI|Sign U-Boot SPL with STM32MP_SigningTool_CLI]]. | ||
|- | |||
| u-boot.itb || SSBL || U-Boot and Device Tree's contained in a FIT image. | |||
|- | |||
| u-boot-signed.itb || SSBL || Same as above but with signed configs and images. | |||
|} | |} | ||
=== Generate key pair and sign U-Boot SPL for BootROM authentication === | |||
To sign the U-Boot SPL as SSBL image for authentication with the BootROM we have to use the STM32 tools <syntaxhighlight lang="shell" inline>STM32MP_KeyGen_CLI</syntaxhighlight> and <syntaxhighlight lang="shell" inline>STM32MP_SigningTool_CLI</syntaxhighlight>. | To sign the U-Boot SPL as SSBL image for authentication with the BootROM we have to use the STM32 tools <syntaxhighlight lang="shell" inline>STM32MP_KeyGen_CLI</syntaxhighlight> and <syntaxhighlight lang="shell" inline>STM32MP_SigningTool_CLI</syntaxhighlight>. | ||
==== Generate key pair with <syntaxhighlight lang="shell" inline>STM32MP_KeyGen_CLI</syntaxhighlight> ==== | |||
All STM32MP15 SoCs only support one key pair for authenticating images through the BootROM. | All STM32MP15 SoCs only support one key pair for authenticating images through the BootROM. | ||
Line 324: | Line 335: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Sign U-Boot SPL with <syntaxhighlight lang="shell" inline>STM32MP_SigningTool_CLI</syntaxhighlight> ==== | |||
To add the public key and the image signature to our built U-Boot SPL binary with STM32 image header, we are using the tool <syntaxhighlight lang="shell" inline>STM32MP_SigningTool_CLI</syntaxhighlight><ref name="Signing_tool" /> to update the existing STM32 image header of <syntaxhighlight lang="shell" inline>u-boot-spl.stm32</syntaxhighlight> with the required details. | To add the public key and the image signature to our built U-Boot SPL binary with STM32 image header, we are using the tool <syntaxhighlight lang="shell" inline>STM32MP_SigningTool_CLI</syntaxhighlight><ref name="Signing_tool" /> to update the existing STM32 image header of <syntaxhighlight lang="shell" inline>u-boot-spl.stm32</syntaxhighlight> with the required details. | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
STM32MP_SigningTool_CLI --binary-image /path/to/u-boot/u-boot-spl.stm32 --public-key publicKey.pem --private-key privateKey.pem --password <a secure password> --output /path/to/u-boot/u-boot-spl.stm32 | STM32MP_SigningTool_CLI --binary-image /path/to/u-boot/u-boot-spl.stm32 --public-key publicKey.pem --private-key privateKey.pem --password <a secure password> --output /path/to/u-boot/u-boot-spl-signed.stm32 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
Line 340: | Line 351: | ||
ECDSA signature generated. | ECDSA signature generated. | ||
Signature verification: SUCCESS | Signature verification: SUCCESS | ||
The Signed image file generated successfully: /path/to/u-boot/u-boot-spl.stm32 | The Signed image file generated successfully: /path/to/u-boot/u-boot-spl-signed.stm32 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
You can check the STM32 image header details with: | You can check the STM32 image header details with: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
STM32MP_SigningTool_CLI --dump-header /path/to/u-boot/u-boot-spl.stm32 | STM32MP_SigningTool_CLI --dump-header /path/to/u-boot/u-boot-spl-signed.stm32 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
Line 372: | Line 383: | ||
The difference to an unsigned STM32 image header is that the values for "Signature" and "ECDSA pub key" are not all zeros and that "Option flags" is 0x0 for enabled signature verification instead of 0x1 for disabled signature verification. | The difference to an unsigned STM32 image header is that the values for "Signature" and "ECDSA pub key" are not all zeros and that "Option flags" is 0x0 for enabled signature verification instead of 0x1 for disabled signature verification. | ||
=== Write U-Boot SPL and U-Boot to your boot media === | |||
The first step to verify that the built U-Boot SPL and U-Boot works as expected is to program both images to your boot media. | The first step to verify that the built U-Boot SPL and U-Boot works as expected is to program both images to your boot media. | ||
Line 381: | Line 392: | ||
<div style="color:red">TODO: How to enforce boot media on Secure Boot enabled devices?</div> | <div style="color:red">TODO: How to enforce boot media on Secure Boot enabled devices?</div> | ||
==== Write U-Boot SPL and U-Boot to the SPI-NOR flash of the SoM ==== | |||
The following '''commands for the U-Boot Shell''' calculate some addresses based on the image offsets expected by the BootROM, load the required images from SD card or via TFTP into memory and finally write the prepared memory into the SPI-NOR flash on the SoM. | The following '''commands for the U-Boot Shell''' calculate some addresses based on the image offsets expected by the BootROM, load the required images from SD card or via TFTP into memory and finally write the prepared memory into the SPI-NOR flash on the SoM. | ||
Prepare for loading <syntaxhighlight lang="shell" inline>u-boot-spl.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot.itb</syntaxhighlight> into memory: | Prepare for loading <syntaxhighlight lang="shell" inline>u-boot-spl-signed.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot-signed.itb</syntaxhighlight> into memory: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
mw.b ${loadaddr} 0xff 0x200000 | mw.b ${loadaddr} 0xff 0x200000 | ||
Line 393: | Line 404: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Load <syntaxhighlight lang="shell" inline>u-boot-spl.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot.itb</syntaxhighlight> from SD card: | Load <syntaxhighlight lang="shell" inline>u-boot-spl-signed.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot-signed.itb</syntaxhighlight> from SD card: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
load mmc 0:4 ${fsbl1addr} u-boot-spl.stm32 | load mmc 0:4 ${fsbl1addr} u-boot-spl-signed.stm32 | ||
load mmc 0:4 ${fsbl2addr} u-boot-spl.stm32 | load mmc 0:4 ${fsbl2addr} u-boot-spl-signed.stm32 | ||
load mmc 0:4 ${ssbl1addr} u-boot.itb | load mmc 0:4 ${ssbl1addr} u-boot-signed.itb | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Load <syntaxhighlight lang="shell" inline>u-boot-spl.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot.itb</syntaxhighlight> from tftp server: | Load <syntaxhighlight lang="shell" inline>u-boot-spl-signed.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot-signed.itb</syntaxhighlight> from tftp server: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
setenv serverip 10.20.30.1 | setenv serverip 10.20.30.1 | ||
setenv ipaddr 10.20.30.100 | setenv ipaddr 10.20.30.100 | ||
setenv netmask 255.255.255.0 | setenv netmask 255.255.255.0 | ||
tftp ${fsbl1addr} ${serverip}:u-boot-spl.stm32 | tftp ${fsbl1addr} ${serverip}:u-boot-spl-signed.stm32 | ||
tftp ${fsbl2addr} ${serverip}:u-boot-spl.stm32 | tftp ${fsbl2addr} ${serverip}:u-boot-spl-signed.stm32 | ||
tftp ${ssbl1addr} ${serverip}:u-boot.itb | tftp ${ssbl1addr} ${serverip}:u-boot-signed.itb | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 417: | Line 428: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Write U-Boot SPL and U-Boot to an SD card ==== | |||
<div style="color:red">TODO:</div> | <div style="color:red">TODO:</div> | ||
Line 434: | Line 445: | ||
--> | --> | ||
==== Write U-Boot SPL and U-Boot to the eMMC ==== | |||
<div style="color:red">TODO:</div> | <div style="color:red">TODO:</div> | ||
<!-- | <!-- | ||
Write <syntaxhighlight lang="shell" inline>u-boot-spl.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot.itb</syntaxhighlight> to eMMC boot hardware partition: | Write <syntaxhighlight lang="shell" inline>u-boot-spl-signed.stm32</syntaxhighlight> and <syntaxhighlight lang="shell" inline>u-boot-signed.itb</syntaxhighlight> to eMMC boot hardware partition: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
mmc dev 1 1 | mmc dev 1 1 | ||
Line 451: | Line 462: | ||
--> | --> | ||
=== Enroll, test and enforce BootROM image authentication === | |||
To enroll, test and enforce image authentication by the BootROM you need to program the PKH into the OTP of the STM32MP15 SoC. | To enroll, test and enforce image authentication by the BootROM you need to program the PKH into the OTP of the STM32MP15 SoC. | ||
Line 457: | Line 468: | ||
If the <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command does fail or is not available on the target U-Boot, you can also write the PKH manually with the more generic <syntaxhighlight lang="shell" inline>fuse</syntaxhighlight> command into the OTP. | If the <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command does fail or is not available on the target U-Boot, you can also write the PKH manually with the more generic <syntaxhighlight lang="shell" inline>fuse</syntaxhighlight> command into the OTP. | ||
==== Program public key hash to eFuses ==== | |||
The following '''commands for the U-Boot Shell''' load the file <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> into memory and program the contained PKH to the OTP of the STM32MP15 SoC. | The following '''commands for the U-Boot Shell''' load the file <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> into memory and program the contained PKH to the OTP of the STM32MP15 SoC. | ||
Line 463: | Line 474: | ||
If this fails or the <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command is not available, you can also write and lock the OTP with the <syntaxhighlight lang="shell" inline>fuse</syntaxhighlight> command | If this fails or the <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command is not available, you can also write and lock the OTP with the <syntaxhighlight lang="shell" inline>fuse</syntaxhighlight> command | ||
===== Program <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> into OTP with <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command ===== | |||
Load <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> | <div style="color:blue">Note: If you have any problems with the <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command use the manual procedure with the generic <syntaxhighlight lang="shell" inline>fuse</syntaxhighlight> command in the next section.</div> | ||
Load <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> from SD card: | |||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
load mmc 0:4 ${loadaddr} publicKeyhash.bin | load mmc 0:4 ${loadaddr} publicKeyhash.bin | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Or load <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> | Or load <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> per TFTP: | ||
<syntaxhighlight lang="shell"> | <syntaxhighlight lang="shell"> | ||
setenv serverip 10.20.30.1 | setenv serverip 10.20.30.1 | ||
Line 502: | Line 515: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===== Program PKH manually into OTP with <syntaxhighlight lang="shell" inline>fuse</syntaxhighlight> command ===== | |||
<div style="color:blue">Note: Use this manual procedure only if you have problems with the simpler <syntaxhighlight lang="shell" inline>stm32key</syntaxhighlight> command from the previous section.</div> | |||
Generate fuse command with hexdump from file <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> on linux host: | Generate fuse command with hexdump from file <syntaxhighlight lang="shell" inline>publicKeyhash.bin</syntaxhighlight> on linux host: | ||
Line 524: | Line 539: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Test BootROM image authentication ==== | |||
To verify the image authentication by the BootROM with the programmed PKH and the programmed signed images, you must reboot your device. | To verify the image authentication by the BootROM with the programmed PKH and the programmed signed images, you must reboot your device. | ||
Line 545: | Line 560: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== Enforce BootROM image authentication ==== | |||
Without any further changes, the BootROM is able to perform authentication of the FSBL image, but unauthenticated images can still be used and executed. | Without any further changes, the BootROM is able to perform authentication of the FSBL image, but unauthenticated images can still be used and executed. | ||
Line 569: | Line 584: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
= Secure Boot in Trusted Boot with BootROM authentication, TF-A and OP-TEE = | |||
<div style="color:red">TODO: A Yocto example project would be the best!</div> | |||
== Support of STM32MP1 DHSOM in TF-A, OP-TEE OS and OP-TEE Developer Setup == | |||
The following table shows the Support status of our STM32MP1-based DHSOMs in the TF-A, OP-TEE OS and OP-TEE Developer Setup projects. | |||
This table is also a good starting point for what is required to support custom boards based on the STM32MP1 DHSOM in these projects. | |||
{| class="wikitable" style="margin:auto" | |||
|+ Support of STM32MP1 DHSOM in TF-A, OP-TEE OS and OP-TEE Developer Setup | |||
|- | |||
! DHSOM | |||
! TF-A<ref name="TF-A" /> | |||
! OP-TEE OS<ref name="OP-TEE/optee_os" /> | |||
! OP-TEE developer setup<ref name="OP-TEE/build" /> | |||
! OP-TEE developer setup Linux<ref name="linaro-swg/linux" /> | |||
! OP-TEE developer setup manifest<ref name="OP-TEE/manifest" /> | |||
|- | |||
! STM32MP157C DHCOM PDK2 | |||
| upstreamed in [https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=eef485abb13b6df9a94137edd82904aab0ecf02d commit eef485ab] | |||
| upstreamed in [https://github.com/OP-TEE/optee_os/commit/6e9896c08ac4d8e81bb95ba1afa46cf6028fd4df commit 6e9896c0] | |||
| upstreamed in [https://github.com/OP-TEE/build/commit/5914639cb690f57a3ce8ba0277ddc6eea2fc3985 commit 5914639c] | |||
| upstreamed in [https://github.com/linaro-swg/linux/commit/2e9ae24784dd51d0a8325871b400795b88f04e2a commit 2e9ae247] | |||
| upstreamed in [https://github.com/OP-TEE/manifest/commit/ef96a36f1821dad69a3fec14c9b75160cdcad351 commit ef96a36f] and [https://github.com/OP-TEE/manifest/commit/2ebdc19d56b2dec9e57dcd2b8024a8023a8665b9 commit 2ebdc19d] | |||
|- | |||
! STM32MP157A DHCOR Avenger96 | |||
| upstreamed in [https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=51e223058fe70b311542178f1865514745fa7874 commit 51e22305] | |||
| upstreamed in [https://github.com/OP-TEE/optee_os/commit/5c932a03de3f1126c4710b3b6b296eb720746182 commit 5c932a03] | |||
| upstreamed in [https://github.com/OP-TEE/build/commit/e43efa5b691a5f594db982134d4116ad1e625412 commit e43efa5b] | |||
| upstreamed in [https://github.com/linaro-swg/linux/commit/29aee39cfa576029922eee42542571f730850877 commit 29aee39c] | |||
| upstreamed in [https://github.com/OP-TEE/manifest/commit/ef96a36f1821dad69a3fec14c9b75160cdcad351 commit ef96a36f] and [https://github.com/OP-TEE/manifest/commit/2ebdc19d56b2dec9e57dcd2b8024a8023a8665b9 commit 2ebdc19d] | |||
|} | |||
= Examples for Flatten Image Tree Source files = | |||
This example shows how to define an ITS file with your own content and how to use it from the U-Boot shell. | |||
To build the FIT binary, there is the <syntaxhighlight lang="shell" inline>build_signed_fit_image.sh</syntaxhighlight> script included in the repository mentioned in [[#Checkout_source_code_for_Verified_Boot|Checkout Source Code for Verified Boot]]. | |||
<div style="color:blue">Note that you have to change <syntaxhighlight lang="shell" inline>KEY_ALGO</syntaxhighlight>, <syntaxhighlight lang="shell" inline>KEY_NAME_SSBL_IMG</syntaxhighlight> and <syntaxhighlight lang="shell" inline>KEY_NAME_SSBL_CFG</syntaxhighlight> to valid values if you build your image manually with <syntaxhighlight lang="shell" inline>mkimage</syntaxhighlight>.</div> | |||
See [https://source.denx.de/u-boot/u-boot/tree/master/doc/uImage.FIT U-Boot Documentation: doc/uImage.FIT] for more examples and explanations of the possible properties. | |||
== Signed FIT with Linux, ramdisk and device trees == | |||
Example of an ITS file with Linux, ramdisk and two device trees as images and a configuration for each valid image combination: | |||
<syntaxhighlight lang="c"> | |||
/dts-v1/; | |||
/ { | |||
description = "Linux, ramdisk and FDT for DHCOM STM32MP1"; | |||
#address-cells = <1>; | |||
images { | |||
linux { | |||
description = "Linux STM32MP15 DHSOM"; | |||
data = /incbin/("/mnt/work/linux/arch/arm/boot/Image.gz"); | |||
type = "kernel"; | |||
os = "linux"; | |||
arch = "arm"; | |||
/* Image compressed with gzip and decrompressed by U-Boot */ | |||
compression = "gzip"; | |||
load = <0xc0008000>; | |||
entry = <0xc0008000>; | |||
hash-1 { | |||
algo = "sha256"; | |||
}; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_IMG"; | |||
}; | |||
}; | |||
ramdisk { | |||
description = "RootFS ramdisk DHSOM ARMv7"; | |||
data = /incbin/("/mnt/work/rootfs/ramdisk.cpio.gz"); | |||
type = "ramdisk"; | |||
arch = "arm"; | |||
os = "linux"; | |||
/* ramdisk.cpio.gz compressed with gzip and decrompressed by Linux instead of by U-Boot */ | |||
compression = "none"; | |||
hash-1 { | |||
algo = "sha256"; | |||
}; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_IMG"; | |||
}; | |||
}; | |||
fdt-stm32mp157c-dhcom-pdk2 { | |||
description = "FDT STM32MP157C DHCOM Premium Developer Kit (2)"; | |||
data = /incbin/("/mnt/work/linux/arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dtb"); | |||
type = "flat_dt"; | |||
arch = "arm"; | |||
compression = "none"; | |||
hash-1 { | |||
algo = "sha256"; | |||
}; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_IMG"; | |||
}; | |||
}; | |||
fdt-stm32mp157c-dhcom-picoitx { | |||
description = "FDT STM32MP157C DHCOM PicoITX"; | |||
data = /incbin/("/mnt/work/linux/arch/arm/boot/dts/stm32mp157c-dhcom-picoitx.dtb"); | |||
type = "flat_dt"; | |||
arch = "arm"; | |||
compression = "none"; | |||
hash-1 { | |||
algo = "sha256"; | |||
}; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_IMG"; | |||
}; | |||
}; | |||
}; | |||
configurations { | |||
default = "stm32mp157c-dhcom-pdk2"; | |||
stm32mp157c-dhcom-pdk2 { | |||
description = "STM32MP157C DHCOM Premium Developer Kit (2)"; | |||
kernel = "linux"; | |||
ramdisk = "ramdisk"; | |||
fdt = "fdt-stm32mp157c-dhcom-pdk2"; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_CFG"; | |||
sign-images = "kernel", "ramdisk", "fdt"; | |||
}; | |||
}; | |||
stm32mp157c-dhcom-picoitx { | |||
description = "STM32MP157C DHCOM PicoITX"; | |||
kernel = "linux"; | |||
ramdisk = "ramdisk"; | |||
fdt = "fdt-stm32mp157c-dhcom-picoitx"; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_CFG"; | |||
sign-images = "kernel", "ramdisk", "fdt"; | |||
}; | |||
}; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
Example U-Boot shell commands to load the FIT file '''linux-signed.itb''' and boot the configuration '''stm32mp157c-dhcom-pdk2''': | |||
<syntaxhighlight lang="shell"> | |||
load mmc 0:4 ${loadaddr} /boot/linux-signed.itb | |||
bootm ${loadaddr}#stm32mp157c-dhcom-pdk2 | |||
</syntaxhighlight> | |||
== Signed FIT with U-Boot scripts == | |||
Example of an ITS file with images '''boot''' and '''recovery''' of type script: | |||
<syntaxhighlight lang="c"> | |||
/dts-v1/; | |||
/ { | |||
description = "Various signed scripts"; | |||
#address-cells = <1>; | |||
images { | |||
boot { | |||
description = "Signed boot script"; | |||
data = /incbin/("/mnt/work/u-boot_scripts/boot.scr"); | |||
type = "script"; | |||
compression = "none"; | |||
hash-1 { | |||
algo = "sha256"; | |||
}; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_IMG"; | |||
}; | |||
}; | |||
recovery { | |||
description = "Signed recovery script"; | |||
data = /incbin/("/mnt/work/u-boot_scripts/recovery.scr"); | |||
type = "script"; | |||
compression = "none"; | |||
hash-1 { | |||
algo = "sha256"; | |||
}; | |||
signature-1 { | |||
algo = "sha256,KEY_ALGO"; | |||
key-name-hint = "KEY_NAME_SSBL_IMG"; | |||
}; | |||
}; | |||
}; | |||
configurations { /* Mandatory node */ }; | |||
}; | |||
</syntaxhighlight> | |||
Example U-Boot shell commands to load FIT file '''scripts-signed.itb''' and run the image '''boot''' with type script: | |||
<syntaxhighlight lang="shell"> | |||
load mmc 0:4 ${scriptaddr} /boot/scripts-signed.itb | |||
source ${scriptaddr}:boot | |||
</syntaxhighlight> | |||
= References = | |||
<references> | <references> | ||
Line 589: | Line 802: | ||
<ref name="TF-A">[https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/ Trusted Firmware-A (TF-A)]</ref> | <ref name="TF-A">[https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/ Trusted Firmware-A (TF-A)]</ref> | ||
<ref name="OP-TEE/optee_os">[https://github.com/OP-TEE/optee_os OP-TEE Trusted OS]</ref> | <ref name="OP-TEE/optee_os">[https://github.com/OP-TEE/optee_os OP-TEE Trusted OS]</ref> | ||
<ref name="OP-TEE/build">[https://github.com/OP-TEE/build | <ref name="OP-TEE/build">[https://github.com/OP-TEE/build OP-TEE developer setup]</ref> | ||
<ref name="OP-TEE/manifest">[https://github.com/OP-TEE/build OP-TEE developer setup manifest]</ref> | |||
<ref name="linaro-swg/linux">[https://github.com/linaro-swg/linux Linux for OP-TEE developer setup]</ref> | |||
</references> | </references> |
Latest revision as of 11:15, 23 November 2022
Introduction
Abbreviations
Abbreviation | Description |
---|---|
BSI | Bundesamt für Sicherheit in der Informationstechnik |
CoM | Computer on module |
FIT | Flattened Image Tree (U-Boot) |
FSBL | Fist Stage Bootloader (TF-A or U-Boot SPL) |
ITS | Image Tree Source (U-Boot) |
OTP | One Time Programmable (eFuses) |
OP-TEE | Open Portable Trusted Execution Environment |
PKH | Public Key Hash |
ROM | Read-Only Memory |
RSA | Rivest, Shamir und Adleman (asynchronous encryption) |
SHA | Secure Hash Algorithm |
SoC | System on chip |
SoM | System on module |
SSBL | Second Stage Bootloader (U-Boot) |
TF-A | Trusted Firmware A |
Secure Boot
The term Secure Boot originally comes from the UEFI specification[1] and describes a secure boot process in which only signed software is loaded and executed during the boot process.
Secure Boot is a necessary cornerstone for enforcing security mechanisms in a trusted computing environment. Enforcing the execution of signed software only during the boot process, as long as the chain of trust is secure, can guarantee that said software is free from tampering, as any manipulation will invalidate the software's signature and prevent the software from being executed.
The figure Secure Boot Generic shows an example of a secure boot process that leads to a reset in the event of an error in the signature check. Each stage uses the certificate and signature to check the origin and integrity of the next stage. On success, the next stage is executed, and in the event of an error, this always leads to a defined error state. In the simplest case, the certificates are integrated into the binary image of the previous stage.
Program code and certificate need to be trustworthy and therefore protected against tampering in each stage, otherwise the secure boot chain can be compromised. Except for the first stage, all binary images are protected against third-party tampering by the signature. As this is practically impossible for the first stage, manipulation protection has to be enforced by hardware measures to make said stage immutable, with the first stage's program code and the verification certificate for the second stage being stored in read-only memory (ROM).
Basic and trusted boot in the context of Secure Boot
When booting Linux on the STM32MP1 SoC with U-Boot SPL and U-Boot only, STM speaks of "Basic Boot"[2]. However, if Linux is booted with a combination of TF-A, U-Boot and OP-TEE, STM refers to this as "Trusted Boot"[3].
Boot chain | Description |
---|---|
Basic boot | BootROM -> U-Boot SPL -> U-Boot -> Linux |
Trusted boot | BootROM -> TF-A -> U-Boot + OP-TEE -> Linux |
Secure Boot in Basic Boot with BootROM authentication and Verified Boot
This Secure Boot implementation does use the the BootROM integrated image authentication to authenticate the U-Boot SPL as FSBL. Authentication of U-Boot as SSBL by the U-Boot SPL and authentication of the Linux kernel, Device Tree and ramdisk by U-Boot is done using the open source implementation Verified Boot. This also means that everything from U-Boot SPL onwards is platform independent, as we do not rely on hardware specific implementations.
Verified Boot
Developers of Google's Chromium project worked out a concept for the Verified Boot called Secure Boot mechanism on the basis of the boot loader "Das U-Boot".
They use the existing infrastructure of the FIT images and for the system configuration at runtime via a Device Tree.
The description language for the FIT images was extended by an additional signature node and the Device Tree of the platform was used to store the certificate(s) for the authentication of the images.
The signature node can be used to sign individual subimages as well as combinations of individual subimages in the FIT image.
The tool mkimage
takes care the signature creation for the FIT images and the addition of the certificate in a Device Tree.
With Verified Boot, the Device Tree with included public key is integrated into the program image of the stage, which accomplishes the authentication and is thus very similar to the general procedure shown in figure Secure Boot Generic. The number of public keys that can be integrated is theoretically unlimited, but they must be distinguishable by name.
Technical details of Verified Boot
Name | Verified Boot |
Implementierung | Software (Open Source) |
Hash algorithms |
|
Crypto algorithms |
|
Number of key pairs | unlimited |
In-depth references for Verified Boot
Flatten Image Tree
- U-Boot Documentation: doc/uImage.FIT
- U-Boot Commit d5934ad7: "new uImage: Add dual format uImage support framework"
- ...
- U-Boot Commit d5934ad7: "new uImage: Add new uImage format documentation and examples"
Verified Boot
- U-Boot Documentation: doc/uImage.FIT/signature.txt
- U-Boot Commit 3e569a6b: "image: Add signing infrastructure"
- U-Boot Commit 56518e71: "image: Support signing of images"
- U-Boot Commit 4d098529: "image: Add support for signing of FIT configurations"
ECDSA signature verification
Note: This has currently some limitations!
- U-Boot Commit 928a8be7: "lib: ecdsa: Implement UCLASS_ECDSA verification on target"
- U-Boot Commit ee870859: "arm: stm32mp1: Implement ECDSA signature verification"
Tutorial: Secure boot from BootROM to Linux with basic boot
System requirements and needed tools
The following table lists all requirements to create the key pairs and build the signed images with embedded public keys.
Category | Description |
---|---|
Host operating system |
|
Debian packages |
|
STM32 Tools |
|
Add STM32CubeProrammer binaries to user environment
export PATH=${PATH}:~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin
Intended use of the four generated key pairs
We've decided to create and use as few certificates as reasonable to ensure a high level of security. Therefore, we chose a separate key pair for each boot stage and also a separate key pair for image and configuration nodes. If you're confused about the difference between image and configuration nodes, head over to Flatten Image Tree to refresh your knowledge. The exact purpose of the four key pairs generated for Verified Boot is described in the following table.
File name | Intended use |
---|---|
fsbl-img | Authenticate image nodes of FIT images loaded by U-Boot SPL (U-Boot, Device Tree, firmware) |
fsbl-cfg | Authenticate config nodes of FIT images loaded by U-Boot SPL (U-Boot + Device Tree + firmware) |
ssbl-img | Authenticate image nodes of FIT images loaded by U-Boot (Kernel, Device Tree, InitRamFS) |
ssbl-cfg | Authenticate config nodes of FIT images loaded by U-Boot (Kernel + Device Tree + InitRamFS) |
Created/Modified files in the U-Boot source for Verified Boot
The created or modified files to build U-Boot with Verified Boot on STM32MP15 are described in the following table.
File | Description |
---|---|
build_signed_uboot.sh | Shell script that automates the creation of key pairs, the modification of FIT source files and Device Tree's and building of U-Boot SPL and U-Boot. |
board/dhelectronics/dh_stm32mp1/u-boot-dhco?.its | FIT source files with defined U-Boot image and Device Tree's for DHSOM platforms. |
board/dhelectronics/dh_stm32mp1/linux-dhcom.its | Dummy FIT source file with defined dummy kernel image and dummy Device Tree for DHSOM platforms. To avoid relying on a built kernel image on a fixed path, we created this dummy, since adding the public keys with mkimage requires a valid FIT source file.
|
configs/stm32mp15_dhco?_secure_defconfig | Example U-Boot defconfig's with enabled CONFIG_FIT_SIGNATURE and CONFIG_SPL_FIT_SIGNATURE .
|
Build Verified Boot enabled U-Boot SPL and U-Boot
To build the U-Boot SPL and U-Boot images, you need to check out the source code and run a build script that automates everything from key generation to image creation and signing.
Checkout source code for Verified Boot
Checkout the branch v2022.01_dhcom_secure_boot
from DH electronics GitHub repository with:
git clone https://github.com/dh-electronics/u-boot-stm32mp1.git -b v2022.01_dhcom_secure_boot
If you already have a cloned U-Boot source code, you can also fetch it into your existing repository with:
cd /path/to/u-boot
git remote add u-boot-stm32mp1 https://github.com/dh-electronics/u-boot-stm32mp1.git
git fetch u-boot-stm32mp1
git checkout v2022.01_dhcom_secure_boot
Run the build script build_signed_uboot.sh
The shell script build_signed_uboot.sh
included in the U-Boot source performs the following steps.
- Prebuild U-Boat SPL and U-Boat to build the required tools and Device Tree's
- Generate the four key pairs if not already created
- Generate/Modify FIT image source files for Linux (dummy) and U-Boot
- Add public keys to the built Device Tree's used by U-Boot SPL and U-Boot
- Rebuild U-Boot SPL and U-Boot with new Device Tree's containing the public keys
The script supports the following environment variables to configure the target architecture, the cross compiler, the defconfig, the key algorithm, the key directory, and a key postfix:
Name | Description | Default |
---|---|---|
ARCH | Target architecture for the U-Boot build | arm |
CROSS_COMPILE | Used cross compiler to build U-Boot | arm-linux-gnueabihf- |
DEFCONFIG | Used defconfig for the U-Boot build | stm32mp15_dhcom_secure_defconfig |
KEY_ALGO | Signature algorithm used for Verified Boot | rsa |
KEY_DIR | Directory where the key pairs are stored | ../keys |
KEY_POSTFIX | Postfix which is appended to the key names | -$(date +%F) |
To perform the steps mentioned above, you just need to run the shell script build_signed_uboot.sh
like below.
In this example, we override the default value for KEY_POSTFIX
with -testing
to append this string to the four key file names.
The script has debug output enabled by default, which should output all the statements in the script itself and the output of the commands used in the script.
If you have any problems with the script, feel free to get in touch with us and attach a logfile.
cd /path/to/u-boot
KEY_POSTFIX="-testing" ./build_signed_uboot.sh | tee build_signed_uboot.log
If this process completes without errors, there are two boot loader images in the root directory of the U-Boot source.
File name | Stage | Description |
---|---|---|
u-boot-spl.stm32 | FSBL | U-Boot SPL binary with appended Device Tree and prepended STM32 image header[5]. |
u-boot-spl-signed.stm32 | FSBL | Same as above but as signed STM32 image. Is created in Sign U-Boot SPL with STM32MP_SigningTool_CLI. |
u-boot.itb | SSBL | U-Boot and Device Tree's contained in a FIT image. |
u-boot-signed.itb | SSBL | Same as above but with signed configs and images. |
Generate key pair and sign U-Boot SPL for BootROM authentication
To sign the U-Boot SPL as SSBL image for authentication with the BootROM we have to use the STM32 tools STM32MP_KeyGen_CLI
and STM32MP_SigningTool_CLI
.
Generate key pair with STM32MP_KeyGen_CLI
All STM32MP15 SoCs only support one key pair for authenticating images through the BootROM.
To generate a ECDSA key pair for the STM32MP Secure Boot use the tool STM32MP_KeyGen_CLI
[6]:
STM32MP_KeyGen_CLI --absolute-path "$(pwd)" --password <a secure password>
-------------------------------------------------------------------
STM32MP Key Generator v2.9.0
-------------------------------------------------------------------
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: publicKey.pem
+ private key: privateKey.pem
+ public hash key: publicKeyhash.bin
Sign U-Boot SPL with STM32MP_SigningTool_CLI
To add the public key and the image signature to our built U-Boot SPL binary with STM32 image header, we are using the tool STM32MP_SigningTool_CLI
[7] to update the existing STM32 image header of u-boot-spl.stm32
with the required details.
STM32MP_SigningTool_CLI --binary-image /path/to/u-boot/u-boot-spl.stm32 --public-key publicKey.pem --private-key privateKey.pem --password <a secure password> --output /path/to/u-boot/u-boot-spl-signed.stm32
-------------------------------------------------------------------
STM32MP Signing Tool v2.9.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: /path/to/u-boot/u-boot-spl-signed.stm32
You can check the STM32 image header details with:
STM32MP_SigningTool_CLI --dump-header /path/to/u-boot/u-boot-spl-signed.stm32
-------------------------------------------------------------------
STM32MP Signing Tool v2.9.0
-------------------------------------------------------------------
Header description:
Magic: 0x53544d32
Signature: c8 30 a0 62 2d 6d 4e 1b b9 f7 fe 38 27 65 e0 44 f0 f5 9d e6 8a a6 02 cb 74 52 26 9c 1e e9 07 17
1a c7 da 8e 96 fa 82 d3 b1 dc d5 3a 05 0e 87 83 94 4d 47 ad 17 07 88 0d b5 ae 2e 38 1d 90 22 ad
Checksum: 0xa8ca85
Header version: 0x10000
Size: 0x22dec
Load address: 0x2ffc2500
Entry point: 0x2ffc2500
Image version: 0x0
Option flags: 0x0
ECDSA Algo: 0x1
ECDSA pub key: 3b 71 8e 59 f1 ee 4c a8 4b 72 5f 4a 1c 63 8b 6e b8 01 ec 1a 3f 8c 98 2f d2 1d 77 f9 09 10 8f 04
30 da 5c 3a 24 53 0d 71 93 f0 a5 d9 c9 a7 27 b4 5f a5 c4 4d 55 8b 7a 25 e3 03 ef ca 87 ff 04 25
Binary type: 0x0
The difference to an unsigned STM32 image header is that the values for "Signature" and "ECDSA pub key" are not all zeros and that "Option flags" is 0x0 for enabled signature verification instead of 0x1 for disabled signature verification.
Write U-Boot SPL and U-Boot to your boot media
The first step to verify that the built U-Boot SPL and U-Boot works as expected is to program both images to your boot media. Depending on the boot configuration, your DHSOM will boot from the module's SPI-NOR flash, from the module's or baseboard's eMMC or from an SD card. The boot configuration is always defined by the boot pins by default, because the boot pins have no alternative function on the STM32MP15 SoCs.
Write U-Boot SPL and U-Boot to the SPI-NOR flash of the SoM
The following commands for the U-Boot Shell calculate some addresses based on the image offsets expected by the BootROM, load the required images from SD card or via TFTP into memory and finally write the prepared memory into the SPI-NOR flash on the SoM.
Prepare for loading u-boot-spl-signed.stm32
and u-boot-signed.itb
into memory:
mw.b ${loadaddr} 0xff 0x200000
setexpr fsbl1addr ${loadaddr} + 0x0
setexpr fsbl2addr ${loadaddr} + 0x40000
setexpr ssbl1addr ${loadaddr} + 0x80000
Load u-boot-spl-signed.stm32
and u-boot-signed.itb
from SD card:
load mmc 0:4 ${fsbl1addr} u-boot-spl-signed.stm32
load mmc 0:4 ${fsbl2addr} u-boot-spl-signed.stm32
load mmc 0:4 ${ssbl1addr} u-boot-signed.itb
Load u-boot-spl-signed.stm32
and u-boot-signed.itb
from tftp server:
setenv serverip 10.20.30.1
setenv ipaddr 10.20.30.100
setenv netmask 255.255.255.0
tftp ${fsbl1addr} ${serverip}:u-boot-spl-signed.stm32
tftp ${fsbl2addr} ${serverip}:u-boot-spl-signed.stm32
tftp ${ssbl1addr} ${serverip}:u-boot-signed.itb
Check for magic numbers of expected image headers and conditionally program the SPI-NOR flash:
if itest *${fsbl1addr} == 0x324d5453 && itest *${fsbl2addr} == 0x324d5453 && itest *${ssbl1addr} == 0xedfe0dd0; then
sf probe && sf update ${loadaddr} 0 0x200000
fi
Write U-Boot SPL and U-Boot to an SD card
Write U-Boot SPL and U-Boot to the eMMC
Enroll, test and enforce BootROM image authentication
To enroll, test and enforce image authentication by the BootROM you need to program the PKH into the OTP of the STM32MP15 SoC.
The publicKeyhash.bin
file that you created in the Generate key pair with STM32MP_KeyGen_CLI step contains the PKH in binary format for use with the stm32key
U-Boot command.
If the stm32key
command does fail or is not available on the target U-Boot, you can also write the PKH manually with the more generic fuse
command into the OTP.
Program public key hash to eFuses
The following commands for the U-Boot Shell load the file publicKeyhash.bin
into memory and program the contained PKH to the OTP of the STM32MP15 SoC.
The used command stm32key
writes and locks the words of the OTP automatically without knowing anything about the OTP layout/addresses.
If this fails or the stm32key
command is not available, you can also write and lock the OTP with the fuse
command
Program publicKeyhash.bin
into OTP with stm32key
command
stm32key
command use the manual procedure with the generic fuse
command in the next section.Load publicKeyhash.bin
from SD card:
load mmc 0:4 ${loadaddr} publicKeyhash.bin
Or load publicKeyhash.bin
per TFTP:
setenv serverip 10.20.30.1
setenv ipaddr 10.20.30.100
setenv netmask 255.255.255.0
tftp ${loadaddr} ${serverip}:publicKeyhash.bin
Show the contents of publicKeyhash.bin
:
stm32key read ${loadaddr}
Read KEY at 0xc2000000
OTP value 24: 4e31bbcd
OTP value 25: 51e827dd
OTP value 26: 3511f521
OTP value 27: fd9c11a2
OTP value 28: 5b997b82
OTP value 29: 8150adc5
OTP value 30: a9c68fa9
OTP value 31: 72a3ba74
Write the contents of publicKeyhash.bin
to OTP with the stm32key
command:
stm32key fuse ${loadaddr}
TODO: Add output
Program PKH manually into OTP with fuse
command
stm32key
command from the previous section.Generate fuse command with hexdump from file publicKeyhash.bin
on linux host:
echo fuse prog -y 0 0x18 $(hexdump -e '/4 "0x"' -e '/1 "%x"' -e '" "' /path/to/publicKeyhash.bin)
fuse prog -y 0 0x18 0x4e31bbcd 0x51e827dd 0x3511f521 0xfd9c11a2 0x5b997b82 0x8150adc5 0xa9c68fa9 0x72a3ba74
Write the PKH into OTP manually with the fuse
command:
fuse prog -y 0 0x18 0x4e31bbcd 0x51e827dd 0x3511f521 0xfd9c11a2 0x5b997b82 0x8150adc5 0xa9c68fa9 0x72a3ba74
Lock the related OTP words manually with the fuse
command:
fuse prog -y 0 0x10000018 1 1 1 1 1 1 1 1
Test BootROM image authentication
To verify the image authentication by the BootROM with the programmed PKH and the programmed signed images, you must reboot your device.
On the third line of the U-Boot SPL output, check the BootROM authentication status.
The status output should look like this: Bootrom authentication: succeeded
.
Note the succeeded
status for successful authentication of the U-Boot SPL image by the BootROM.
The following output shows successful authentication of the U-Boot-SPL image in line 3, as well as successful authentication of the used configuration in line 7 and the U-Boot and Device Tree subimages in lines 8 and 9 of the U-Boot-FIT image.
U-Boot SPL 2022.01-00012-g6c5892c90c28 (Feb 16 2022 - 11:11:16 +0100)
Model: STMicroelectronics STM32MP15xx DHCOM Premium Developer Kit (2)
Bootrom authentication: succeeded
Code: SoM:rev=1,ddr3=3 Board:rev=0
RAM: DDR3L 32bits 2x4Gb 533MHz
Trying to boot from SPI
## Checking hash(es) for config config-2 ... sha256,rsa4096:fsbl-cfg-2022-02-16+ OK
## Checking hash(es) for Image uboot ... sha256,rsa4096:fsbl-img-2022-02-16+ sha256+ OK
## Checking hash(es) for Image fdt-1 ... sha256,rsa4096:fsbl-img-2022-02-16+ sha256+ OK
Enforce BootROM image authentication
Without any further changes, the BootROM is able to perform authentication of the FSBL image, but unauthenticated images can still be used and executed. The device is still open, let's see this as a kind of test mode to check if the PKH is set correctly.
Once the authentication process is confirmed, the device can be closed and the user is forced to use signed images.
The 6th bit in the 1st word of the OTP is responsible that the BootROM only accepts signed images. Burning this bit enforces authentication of images by the BootROM and unsigned binaries are no longer supported on the target device.
To program this bit, the U-Boot Shell can be used with the stm32key
command or with the more general fuse
command.
With usage of the stm32key
command:
stm32key close
Or with usage of the fuse
command:
fuse prog 0 0x0 0x40
Secure Boot in Trusted Boot with BootROM authentication, TF-A and OP-TEE
Support of STM32MP1 DHSOM in TF-A, OP-TEE OS and OP-TEE Developer Setup
The following table shows the Support status of our STM32MP1-based DHSOMs in the TF-A, OP-TEE OS and OP-TEE Developer Setup projects. This table is also a good starting point for what is required to support custom boards based on the STM32MP1 DHSOM in these projects.
DHSOM | TF-A[8] | OP-TEE OS[9] | OP-TEE developer setup[10] | OP-TEE developer setup Linux[11] | OP-TEE developer setup manifest[12] |
---|---|---|---|---|---|
STM32MP157C DHCOM PDK2 | upstreamed in commit eef485ab | upstreamed in commit 6e9896c0 | upstreamed in commit 5914639c | upstreamed in commit 2e9ae247 | upstreamed in commit ef96a36f and commit 2ebdc19d |
STM32MP157A DHCOR Avenger96 | upstreamed in commit 51e22305 | upstreamed in commit 5c932a03 | upstreamed in commit e43efa5b | upstreamed in commit 29aee39c | upstreamed in commit ef96a36f and commit 2ebdc19d |
Examples for Flatten Image Tree Source files
This example shows how to define an ITS file with your own content and how to use it from the U-Boot shell.
To build the FIT binary, there is the build_signed_fit_image.sh
script included in the repository mentioned in Checkout Source Code for Verified Boot.
KEY_ALGO
, KEY_NAME_SSBL_IMG
and KEY_NAME_SSBL_CFG
to valid values if you build your image manually with mkimage
.See U-Boot Documentation: doc/uImage.FIT for more examples and explanations of the possible properties.
Signed FIT with Linux, ramdisk and device trees
Example of an ITS file with Linux, ramdisk and two device trees as images and a configuration for each valid image combination:
/dts-v1/;
/ {
description = "Linux, ramdisk and FDT for DHCOM STM32MP1";
#address-cells = <1>;
images {
linux {
description = "Linux STM32MP15 DHSOM";
data = /incbin/("/mnt/work/linux/arch/arm/boot/Image.gz");
type = "kernel";
os = "linux";
arch = "arm";
/* Image compressed with gzip and decrompressed by U-Boot */
compression = "gzip";
load = <0xc0008000>;
entry = <0xc0008000>;
hash-1 {
algo = "sha256";
};
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_IMG";
};
};
ramdisk {
description = "RootFS ramdisk DHSOM ARMv7";
data = /incbin/("/mnt/work/rootfs/ramdisk.cpio.gz");
type = "ramdisk";
arch = "arm";
os = "linux";
/* ramdisk.cpio.gz compressed with gzip and decrompressed by Linux instead of by U-Boot */
compression = "none";
hash-1 {
algo = "sha256";
};
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_IMG";
};
};
fdt-stm32mp157c-dhcom-pdk2 {
description = "FDT STM32MP157C DHCOM Premium Developer Kit (2)";
data = /incbin/("/mnt/work/linux/arch/arm/boot/dts/stm32mp157c-dhcom-pdk2.dtb");
type = "flat_dt";
arch = "arm";
compression = "none";
hash-1 {
algo = "sha256";
};
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_IMG";
};
};
fdt-stm32mp157c-dhcom-picoitx {
description = "FDT STM32MP157C DHCOM PicoITX";
data = /incbin/("/mnt/work/linux/arch/arm/boot/dts/stm32mp157c-dhcom-picoitx.dtb");
type = "flat_dt";
arch = "arm";
compression = "none";
hash-1 {
algo = "sha256";
};
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_IMG";
};
};
};
configurations {
default = "stm32mp157c-dhcom-pdk2";
stm32mp157c-dhcom-pdk2 {
description = "STM32MP157C DHCOM Premium Developer Kit (2)";
kernel = "linux";
ramdisk = "ramdisk";
fdt = "fdt-stm32mp157c-dhcom-pdk2";
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_CFG";
sign-images = "kernel", "ramdisk", "fdt";
};
};
stm32mp157c-dhcom-picoitx {
description = "STM32MP157C DHCOM PicoITX";
kernel = "linux";
ramdisk = "ramdisk";
fdt = "fdt-stm32mp157c-dhcom-picoitx";
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_CFG";
sign-images = "kernel", "ramdisk", "fdt";
};
};
};
};
Example U-Boot shell commands to load the FIT file linux-signed.itb and boot the configuration stm32mp157c-dhcom-pdk2:
load mmc 0:4 ${loadaddr} /boot/linux-signed.itb
bootm ${loadaddr}#stm32mp157c-dhcom-pdk2
Signed FIT with U-Boot scripts
Example of an ITS file with images boot and recovery of type script:
/dts-v1/;
/ {
description = "Various signed scripts";
#address-cells = <1>;
images {
boot {
description = "Signed boot script";
data = /incbin/("/mnt/work/u-boot_scripts/boot.scr");
type = "script";
compression = "none";
hash-1 {
algo = "sha256";
};
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_IMG";
};
};
recovery {
description = "Signed recovery script";
data = /incbin/("/mnt/work/u-boot_scripts/recovery.scr");
type = "script";
compression = "none";
hash-1 {
algo = "sha256";
};
signature-1 {
algo = "sha256,KEY_ALGO";
key-name-hint = "KEY_NAME_SSBL_IMG";
};
};
};
configurations { /* Mandatory node */ };
};
Example U-Boot shell commands to load FIT file scripts-signed.itb and run the image boot with type script:
load mmc 0:4 ${scriptaddr} /boot/scripts-signed.itb
source ${scriptaddr}:boot
References
- ↑ http://www.uefi.org/specifications
- ↑ U-Boot Source stm32mp15_basic_defconfig
- ↑ U-Boot Source stm32mp15_trusted_defconfig
- ↑ 4.0 4.1 BSI - Technische Richtlinie, "Kryptographische Algorithmen und Schlüssellängen", BSI TR-02102-1
- ↑ STM32 header for binary files
- ↑ STM32MP KeyGen tool
- ↑ STM32MP Signing tool
- ↑ Trusted Firmware-A (TF-A)
- ↑ OP-TEE Trusted OS
- ↑ OP-TEE developer setup
- ↑ Linux for OP-TEE developer setup
- ↑ OP-TEE developer setup manifest