1. Configure secure boot
To build signed and encrypted artifacts, modify your conf/local.conf file to include the following:
# Required to include trustfence support.
INHERIT += "trustfence"
Digi Embedded Yocto generates a PKI tree by default under a new folder called trustfence inside your project.
To specify a custom path for the PKI tree, see Advanced options.
1.1. Hardware unique key (HUK)
The hardware unique key (HUK) is a symmetric encryption key stored in the OTP bits of the platform. The HUK is not used directly to encrypt data. Instead, it is used as a derivative for other keys. This means you can use different keys for different encryption purposes and know that the keys cannot be used to access data on a different device, even if they are leaked.
Each chip has a unique HUK pre-provisioned by STMicroelectronics.
1.2. U-Boot environment encryption
When TrustFence is enabled, the U-Boot environment is encrypted by default using a key derived from the chip hardware unique key (HUK).
| To explicitly disable U-Boot environment encryption, see Advanced options. |
2. Build your target images
Once TrustFence is enabled and configured in your Digi Embedded Yocto project, you can build your target image. For example:
$ bitbake dey-image-webkit
When the build process finishes, several secure artifacts appear in the deployment directory:
-
tf-a-ccmp25-dvk-optee-emmc_Encrypted_Signed.stm32: This is the signed and encrypted ARM Trusted Firmware for booting from the eMMC. -
fip-ccmp25-dvk-optee-emmc_Encrypted_Signed.bin: This is the signed and encrypted FIP image with the U-Boot bootloader and Trusted Execution Environment (OP-TEE). -
fitImage-ccmp25-dvk.bin: This is a signed FIT image that contains the following artifacts with signed hashes:-
The Linux kernel
-
The device tree
-
Device tree overlays
-
Boot script
-
The fitImage-ccmp25-dvk.bin is contained inside the <image-name>-boot.vfat image file.
|
Additionally, when not provided, TrustFence keys are generated at the specified TRUSTFENCE_KEYS_PATH location (by default, a subfolder in the project called trustfence/).
For additional details on TrustFence keys, see Summary of TrustFence keys.
| These files need to be securely stored in order to be used in the manufacturing of secure devices. |
3. Program the signed artifacts
Deploy the built artifacts. See Update firmware using system images for reference.
|
The default U-Boot is prepared to boot a regular Linux kernel with Image.gz format.
This is determined by variable If you use a different method to deploy the images, you must set this variable manually in U-Boot as follows:
|
4. Boot the signed artifacts
Reset the device. Check the new messages that appear:
NOTICE: CPU: STM32MP255CAL Rev.Y
NOTICE: Model: Digi International ConnectCore MP25 Development Kit
NOTICE: Reset reason: Power-on reset (por_rstn) (0x2035)
NOTICE: Bootrom authentication failed
NOTICE: BL2: v2.10-stm32mp2-r1.0(release):dey-5.0-r1.3-v2.10-21-g8a2c4b322-dirty(8a2c4b32)
NOTICE: BL2: Built : 11:53:45, Apr 9 2025
NOTICE: TRUSTED_BOARD_BOOT support enabled
NOTICE: ROTPK is not deployed on platform. Skipping ROTPK verification.
NOTICE: ROTPK is not deployed on platform. Skipping ROTPK verification.
NOTICE: BL2: Booting BL31
NOTICE: BL31: v2.10-stm32mp2-r1.0(release):dey-5.0-r1.3-v2.10-21-g8a2c4b322-dirty(8a2c4b32)
NOTICE: BL31: Built : 11:53:45, Apr 9 2025
[ 0.000000] SCP-firmware 2.13.0-intree-optee-os-dey-5.0-r1.3-v4.0-14-gb56
[ 0.000000]
[ 0.000000] [FWK] Module initialization complete!
U-Boot dub-2023.10-r2.1-git (Mar 28 2025 - 11:12:09 +0000)
[...]
The Bootrom authentication failed message appears.
This means the ROM loader detected that it is booting a signed image, but it could not authenticate it.
This is expected because you have not yet programmed the hash of the eight ECC public keys hashes table in the OTP bits.
The next message is TRUSTED_BOARD_BOOT support enabled.
This means the TF-A image (or first-stage bootloader) has been built with authentication support enabled; that is, FSBL will either authenticate the second-stage boot loader or refuse to boot.
The next message is ROTPK is not deployed on platform. Skipping ROTPK verification.
This displays because the Root Of Trust Public Key (ROTPK) has not yet been programmed in the OTP bits, so the FSBL skips the authentication of the second-stage bootloader and just boots it.
Following that, OP-TEE runs and then U-Boot starts.
The U-Boot environment encryption feature is enabled by default, so U-Boot will import the MAC addresses (and any other write-once environment variables) from the previous (not encrypted) environment, and will reset any other variable to the default values. After that, a save operation will overwrite the environment with encrypted data.
To ensure that both copies of the environment get encrypted, save the environment twice right after booting a U-Boot with environment encryption support, as follows:
=> saveenv
Saving Environment to MMC...
Writing to MMC(0)... done
=> saveenv
Saving Environment to MMC...
Writing to redundant MMC(0)... done
4.1. Boot the FIT image
As part of the Digi Embedded Yocto project, the U-Boot recipe includes a U-Boot boot script to boot the ConnectCore MP25 Development Kit. This script determines the variant of the ConnectCore MP25 SoM and the version of the carrier board and selects the device tree overlays to apply on top of the base device tree (wireless, Bluetooth, etc.) before booting the kernel. This boot script is embedded and signed in the FIT image and is run by default when you start the device.
|
The default U-Boot (without TrustFence) is prepared to boot a regular Linux kernel with zImage format.
This is determined by variable If you used a different method to deploy the images, you must set this variable manually in U-Boot as follows:
|
Let U-Boot run, or run the boot command if you stopped at the U-Boot prompt.
Check the new messages that appear:
## Executing script at 94000000
sha256+ sha256,rsa2048:fitimg+ Booting from system A
## Loading fitImage: fitImage-ccmp25-dvk.bin
11710394 bytes read in 301 ms (37.1 MiB/s)
## Loading kernel from FIT Image at 84000000 ...
Explanation of output:
-
The FIT image is loaded into RAM memory and the boot script is authenticated against the public key.
-
Authentication succeeds and the boot script prints the message:
"sha256,rsa2048:fitimg+ sha256+ Booting from system A". -
The boot script calls the
dbootcommand to boot the system. While this command typically loads the image into RAM, in this case the FIT image is not reloaded because it was already loaded to run the boot script.
Next, U-Boot successfully authenticates the default configuration:
## Loading kernel from FIT Image at 84000000 ...
Using 'conf-ccmp25-dvk.dtb' configuration
Verifying Hash Integrity ... OK
Trying 'kernel-1' kernel subimage
Description: Linux kernel
Created: 2025-04-08 14:32:11 UTC
Type: Kernel Image
Compression: gzip compressed
Data Start: 0x840000e8
Data Size: 11545299 Bytes = 11 MiB
Architecture: AArch64
OS: Linux
Load Address: 0x88000000
Entry Point: 0x88000000
Hash algo: sha256
Hash value: a1fac39ca6bf3a858b8f82992abc02de85904994dc12b98c44a005a10a2ea198
Sign algo: sha256,rsa2048:fitimg
Sign value: a16a06512b2230b2884560455cbd6c072c321923b424f50bd72e26da2a27337ce6a8ebd2efcac87c9172c16264c4b8e48c35eca705a0d76b490d05ccc6f8ce2b42d2725bbe008433cf51f264616911aba07e
Timestamp: 2025-04-08 14:32:11 UTC
Verifying Hash Integrity ... sha256+ sha256,rsa2048:fitimg- OK
Explanation of output:
-
The first item in the default configuration is the Linux kernel.
-
U-Boot also authenticates the kernel image successfully.
-
Similar messages appear for the base device tree and the selected overlays that the boot script populated as a list in U-Boot environment variable
overlays. -
After all the artifacts have been authenticated, the Linux system boots.
| The FIT image is the only file that’s stored in the linux partition, as it includes all the required files to boot the system. |
5. Secure the device
The final step in configuring secure boot for a device is burning the secure OTP configuration.
| The secure OTP configuration can only be written once and is irreversible. |
To secure the device:
5.1. Program the Public Key Hash Table Hash for FSBL (OEM-KEY1)
The OEM-KEY1 OTP bits (words 144..151) hold the hash of the eight ECC public keys hashes table. For additional details on TrustFence keys, see Summary of TrustFence keys.
The ConnectCore MP25 has two boot stages:
-
Initially, the ROM loader uses the OEM-KEY1 OTP bits to authenticate the FSBL (TF-A). In open devices, the FSBL will boot in any case and the log reports whether the authentication was successful or failed.
-
Next, the FSBL (built with authentication support when TrustFence is enabled) authenticates the second stage bootloader (SSBL), the FIP image. If the OEM-KEY1 is not programmed, it skips the authentication and boots it; if the OEM-KEY1 is programmed, it validates the signature and refuses to boot if the authentication fails.
To program the OEM-KEY1:
-
Check the current status of the device:
=> trustfence status * OEM-KEY1 fuses: [NOT PROGRAMMED] [NOT LOCKED] * OEM-KEY2 fuses: [NOT PROGRAMMED] [NOT LOCKED] * RPROC-FW-PKH fuses: [NOT PROGRAMMED] [NOT LOCKED] * Secure boot: [OPEN]The command reports the OEM-KEY1 is not programmed and the device is open.
-
Transfer the
publicKeysHashHashes.bin(by default inside thetrustfence/folder in your project) into an address in RAM, for example via TFTP:=> tftp ${loadaddr} publicKeysHashHashes.bin -
Read the contents of that RAM address interpreted as OEM-KEY1. This command prints the hexadecimal bytes that form the OEM-KEY1:
=> trustfence read_pkhth ${loadaddr} Read OEM-KEY1 at 0x84000000 OEM-KEY1 OTP 144: [84000000] b53a0bb4 OEM-KEY1 OTP 145: [84000004] 6a809bfa OEM-KEY1 OTP 146: [84000008] 5c461350 OEM-KEY1 OTP 147: [8400000c] f8979d6f OEM-KEY1 OTP 148: [84000010] ad1e36dd OEM-KEY1 OTP 149: [84000014] e573053f OEM-KEY1 OTP 150: [84000018] db27c6da OEM-KEY1 OTP 151: [8400001c] 5d297f18 -
Verify the hexadecimal values match the contents of the
publicKeysHashHashes.binthat corresponds to the PKI tree you are using to sign the files. Remember to back up this PKI tree to be able to sign future images. -
Program the OEM-KEY1 in the OTP bits (irreversible):
=> trustfence prog_pkhth ${loadaddr} OEM-KEY1 OTP 144: 00000000 lock : 00000000 OEM-KEY1 OTP 145: 00000000 lock : 00000000 OEM-KEY1 OTP 146: 00000000 lock : 00000000 OEM-KEY1 OTP 147: 00000000 lock : 00000000 OEM-KEY1 OTP 148: 00000000 lock : 00000000 OEM-KEY1 OTP 149: 00000000 lock : 00000000 OEM-KEY1 OTP 150: 00000000 lock : 00000000 OEM-KEY1 OTP 151: 00000000 lock : 00000000 OEM-KEY1 is not locked! OEM-KEY1 is free! Writing OEM-KEY1 with OEM-KEY1 OTP 144: [84000000] b53a0bb4 OEM-KEY1 OTP 145: [84000004] 6a809bfa OEM-KEY1 OTP 146: [84000008] 5c461350 OEM-KEY1 OTP 147: [8400000c] f8979d6f OEM-KEY1 OTP 148: [84000010] ad1e36dd OEM-KEY1 OTP 149: [84000014] e573053f OEM-KEY1 OTP 150: [84000018] db27c6da OEM-KEY1 OTP 151: [8400001c] 5d297f18 Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y Fuse OEM-KEY1 OTP 144 : b53a0bb4 Fuse OEM-KEY1 OTP 145 : 6a809bfa Fuse OEM-KEY1 OTP 146 : 5c461350 Fuse OEM-KEY1 OTP 147 : f8979d6f Fuse OEM-KEY1 OTP 148 : ad1e36dd Fuse OEM-KEY1 OTP 149 : e573053f Fuse OEM-KEY1 OTP 150 : db27c6da Fuse OEM-KEY1 OTP 151 : 5d297f18 OEM-KEY1 updated ! =>At this point, the OEM-KEY1 has been programmed but the device is still open and can still boot any unsigned images.
-
Reset the device, and check the new messages that appear:
NOTICE: CPU: STM32MP255CAL Rev.Y NOTICE: Model: Digi International ConnectCore MP25 Development Kit NOTICE: Bootrom authentication succeeded NOTICE: BL2: v2.10-stm32mp2-r1.0(release):dey-5.0-r1.3-v2.10-19-g38a33604d-dirty(38a33604) NOTICE: BL2: Built : 14:55:23, Mar 17 2025 NOTICE: TRUSTED_BOARD_BOOT support enabled NOTICE: BL2: Booting BL31 NOTICE: BL31: v2.10-stm32mp2-r1.0(release):dey-5.0-r1.3-v2.10-19-g38a33604d-dirty(38a33604) NOTICE: BL31: Built : 14:55:23, Mar 17 2025 [ 0.000000] SCP-firmware 2.13.0-intree-optee-os-dey-5.0-r1.3-v4.0-14-gb56 [ 0.000000] [ 0.000000] [FWK] Module initialization complete! U-Boot dub-2023.10-r2.1-git (Mar 28 2025 - 11:12:09 +0000) [...] =>The
Bootrom authentication succeededmessage appears. This means the ROM loader detected that it is booting a signed image and it could successfully authenticate it against the programmed OEM-KEY1.The next message is
TRUSTED_BOARD_BOOT support enabled. This means the TF-A image (or first-stage bootloader) has been built with authentication support enabled; that is, FSBL will either authenticate the second-stage bootloader or refuse to boot.If the boot continues at this point, the FIP image was authenticated successfully. If authentication fails, the FIP image won’t boot at all, even if the device is open.
-
Check the TrustFence status:
=> trustfence status * OEM-KEY1 fuses: [PROGRAMMED] [LOCKED] * OEM-KEY2 fuses: [NOT PROGRAMMED] [NOT LOCKED] * RPROC-FW-PKH fuses: [NOT PROGRAMMED] [NOT LOCKED] * Secure boot: [OPEN]
| On open devices you can still boot unsigned images without authentication support (without TrustFence). |
5.2. Program the Encryption/Decryption Master Key for FSBL (EDMK1)
When you enable TrustFence, FSBL image is encrypted. Follow these instructions unless you have specifically disabled image encryption. The EDMK1 OTP bits (words 364..367) hold the encryption/decryption master key. For additional details on TrustFence keys, see Summary of TrustFence keys.
To program the EDMK1:
-
Transfer the
encryption_key_fsbl.bin(by default inside thetrustfence/folder in your project) into an address in RAM, for example via TFTP:=> tftp ${loadaddr} encryption_key_fsbl.bin -
Read the contents of that RAM address interpreted as EDMK1. This command prints the hexadecimal bytes that form the EDMK1:
=> trustfence read_edmk ${loadaddr} Read EDMK1 at 0x84000000 EDMK1 OTP 364: [84000000] 4ded46e4 EDMK1 OTP 365: [84000004] 1e5d21f7 EDMK1 OTP 366: [84000008] 5ae70156 EDMK1 OTP 367: [8400000c] a787a33d -
Verify the hexadecimal values match the contents of the
encryption_key_fsbl.binthat corresponds to the PKI tree you are using to sign the files. Remember to back up this PKI tree to be able to sign future images. -
Program the EDMK1 in the OTP bits (irreversible):
=> trustfence prog_edmk ${loadaddr} EDMK1 OTP 364: 00000000 lock : 30000000 EDMK1 OTP 365: 00000000 lock : 30000000 EDMK1 OTP 366: 00000000 lock : 30000000 EDMK1 OTP 367: 00000000 lock : 30000000 EDMK1 is not locked! EDMK1 is free! Writing OEM-KEY1 with EDMK1 OTP 364: [84000000] 4ded46e4 EDMK1 OTP 365: [84000004] 1e5d21f7 EDMK1 OTP 366: [84000008] 5ae70156 EDMK1 OTP 367: [8400000c] a787a33d Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y Fuse EDMK1 OTP 364 : 4ded46e4 Fuse EDMK1 OTP 365 : 1e5d21f7 Fuse EDMK1 OTP 366 : 5ae70156 Fuse EDMK1 OTP 367 : a787a33d EDMK1 updated ! =>At this point, the EDMK1 has been programmed but the device is still open and can still boot any unencrypted images.
-
Reset the device
| EDMK1 OTP bits are not readable after programming. |
5.3. Program the Encryption/Decryption Master Key for FIP (FIP-EDMK)
When you enable TrustFence, FIP image is encrypted. Follow these instructions unless you have specifically disabled image encryption. The FIP-EDMK OTP bits (words 260..267) hold the encryption/decryption master key for FIP. For additional details on TrustFence keys, see Summary of TrustFence keys.
To program the FIP-EDMK:
-
Transfer the
encryption_key_fip.bin(by default inside thetrustfence/folder in your project) into an address in RAM, for example via TFTP:=> tftp ${loadaddr} encryption_key_fip.bin -
Read the contents of that RAM address interpreted as FIP-EDMK. This command prints the hexadecimal bytes that form the FIP-EDMK:
=> trustfence read_fip_edmk ${loadaddr} Read FIP-EDMK at 0x84000000 FIP-EDMK OTP 260: [84000000] 1d044f50 FIP-EDMK OTP 261: [84000004] 957dea68 FIP-EDMK OTP 262: [84000008] 22c31f28 FIP-EDMK OTP 263: [8400000c] f80fe0f7 FIP-EDMK OTP 264: [84000010] f2db630a FIP-EDMK OTP 265: [84000014] 8c6c0d8a FIP-EDMK OTP 266: [84000018] 043bda1f FIP-EDMK OTP 267: [8400001c] 28e56955 -
Verify the hexadecimal values match the contents of the
encryption_key_fip.binthat corresponds to the PKI tree you are using to sign the files. Remember to back up this PKI tree to be able to sign future images. -
Program the FIP-EDMK in the OTP bits (irreversible):
=> trustfence prog_fip_edmk ${loadaddr} FIP-EDMK OTP 260: 00000000 lock : 00000000 FIP-EDMK OTP 261: 00000000 lock : 00000000 FIP-EDMK OTP 262: 00000000 lock : 00000000 FIP-EDMK OTP 263: 00000000 lock : 00000000 FIP-EDMK OTP 264: 00000000 lock : 00000000 FIP-EDMK OTP 265: 00000000 lock : 00000000 FIP-EDMK OTP 266: 00000000 lock : 00000000 FIP-EDMK OTP 267: 00000000 lock : 00000000 FIP-EDMK is not locked! FIP-EDMK is free! Writing FIP-EDMK with FIP-EDMK OTP 260: [84000000] 1d044f50 FIP-EDMK OTP 261: [84000004] 957dea68 FIP-EDMK OTP 262: [84000008] 22c31f28 FIP-EDMK OTP 263: [8400000c] f80fe0f7 FIP-EDMK OTP 264: [84000010] f2db630a FIP-EDMK OTP 265: [84000014] 8c6c0d8a FIP-EDMK OTP 266: [84000018] 043bda1f FIP-EDMK OTP 267: [8400001c] 28e56955 Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y Fuse FIP-EDMK OTP 260 : 1d044f50 Fuse FIP-EDMK OTP 261 : 957dea68 Fuse FIP-EDMK OTP 262 : 22c31f28 Fuse FIP-EDMK OTP 263 : f80fe0f7 Fuse FIP-EDMK OTP 264 : f2db630a Fuse FIP-EDMK OTP 265 : 8c6c0d8a Fuse FIP-EDMK OTP 266 : 043bda1f Fuse FIP-EDMK OTP 267 : 28e56955 FIP-EDMK updated ! =>At this point, the FIP-EDMK has been programmed but the device is still open and can still boot any unencrypted images.
-
Reset the device
| FIP-EDMK OTP bits are not readable after programming. |
5.4. Protect the Cortex-M33 coprocessor firmware
Protecting the Cortex-M33 coprocessor firmware relies on a secure-boot chain that authenticates and decrypts the image before hand-off to remote processor (RPROC) framework. The public key is stored in RPROC-FW-PKH OTP bits to signature verification, while the encryption key is saved in RPROC-FW-ENC-KEY OTP bits. Execution integrity is preserved by isolating the Cortex-M33 code/data regions via security policies so only verified images will be executed. For additional details on TrustFence keys, see Summary of TrustFence keys.
5.4.1. Program the Public Key Hash for remote processor firmware (RPROC-FW-PKH)
The RPROC-FW-PKH OTP bits (words 176..183) hold the hash of the ECC public key. For additional details on TrustFence keys, see Summary of TrustFence keys.
To program the RPROC-FW-PKH:
-
Check the current status of the device:
=> trustfence status * OEM-KEY1 fuses: [PROGRAMMED] [LOCKED] * OEM-KEY2 fuses: [NOT PROGRAMMED] [NOT LOCKED] * RPROC-FW-PKH fuses: [NOT PROGRAMMED] [NOT LOCKED] * Secure boot: [OPEN]The command reports the RPROC-FW-PKH is not programmed and the device is open.
-
Transfer the RPROC
publicKeyhash.bin(by default inside thetrustfence/rproc-keys/folder in your project) into an address in RAM, for example via TFTP:=> tftp ${loadaddr} publicKeyhash.bin -
Read the contents of that RAM address interpreted as RPROC-FW-PKH. This command prints the hexadecimal bytes that form the RPROC-FW-PKH:
=> trustfence read_rproc_pkh ${loadaddr} Read RPROC-FW-PKH at 0x84000000 RPROC-FW-PKH OTP 176: [84000000] 977e5164 RPROC-FW-PKH OTP 177: [84000004] 5510b3b7 RPROC-FW-PKH OTP 178: [84000008] 824f52db RPROC-FW-PKH OTP 179: [8400000c] c2706965 RPROC-FW-PKH OTP 180: [84000010] 99f63dcd RPROC-FW-PKH OTP 181: [84000014] c0bbcb10 RPROC-FW-PKH OTP 182: [84000018] 7292c19b RPROC-FW-PKH OTP 183: [8400001c] c1f07005 -
Verify the hexadecimal values match the contents of the
publicKeyhash.binthat corresponds to the PKI tree you are using to sign the files. Remember to back up this PKI tree to be able to sign future images. -
Program the RPROC-FW-PKH in the OTP bits (irreversible):
=> trustfence prog_rproc_pkh ${loadaddr} RPROC-FW-PKH OTP 176: 00000000 lock : 00000000 RPROC-FW-PKH OTP 177: 00000000 lock : 00000000 RPROC-FW-PKH OTP 178: 00000000 lock : 00000000 RPROC-FW-PKH OTP 179: 00000000 lock : 00000000 RPROC-FW-PKH OTP 180: 00000000 lock : 00000000 RPROC-FW-PKH OTP 181: 00000000 lock : 00000000 RPROC-FW-PKH OTP 182: 00000000 lock : 00000000 RPROC-FW-PKH OTP 183: 00000000 lock : 00000000 RPROC-FW-PKH is not locked! RPROC-FW-PKH is free! Writing RPROC-FW-PKH with RPROC-FW-PKH OTP 176: [84000000] 977e5164 RPROC-FW-PKH OTP 177: [84000004] 5510b3b7 RPROC-FW-PKH OTP 178: [84000008] 824f52db RPROC-FW-PKH OTP 179: [8400000c] c2706965 RPROC-FW-PKH OTP 180: [84000010] 99f63dcd RPROC-FW-PKH OTP 181: [84000014] c0bbcb10 RPROC-FW-PKH OTP 182: [84000018] 7292c19b RPROC-FW-PKH OTP 183: [8400001c] c1f07005 Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y Fuse RPROC-FW-PKH OTP 176 : 977e5164 Fuse RPROC-FW-PKH OTP 177 : 5510b3b7 Fuse RPROC-FW-PKH OTP 178 : 824f52db Fuse RPROC-FW-PKH OTP 179 : c2706965 Fuse RPROC-FW-PKH OTP 180 : 99f63dcd Fuse RPROC-FW-PKH OTP 181 : c0bbcb10 Fuse RPROC-FW-PKH OTP 182 : 7292c19b Fuse RPROC-FW-PKH OTP 183 : c1f07005 RPROC-FW-PKH updated ! =>At this point, the RPROC-FW-PKH has been programmed and is ready to enable the authentication in OP-TEE RPROC.
-
Reset the device
-
Check the TrustFence status:
=> trustfence status * OEM-KEY1 fuses: [PROGRAMMED] [LOCKED] * OEM-KEY2 fuses: [NOT PROGRAMMED] [NOT LOCKED] * RPROC-FW-PKH fuses: [PROGRAMMED] [LOCKED] * Secure boot: [OPEN]
5.4.2. Program the Encryption/Decryption Master Key for remote processor firmware (RPROC-FW-ENC-KEY)
The RPROC-FW-ENC-KEY OTP bits (words 336..343) hold the encryption/decryption master key for remote processor. For additional details on TrustFence keys, see Summary of TrustFence keys.
To program the RPROC-FW-ENC-KEY:
-
Transfer the
encryption_key_rproc.bin(by default inside thetrustfence/rproc-keys/folder in your project) into an address in RAM, for example via TFTP:=> tftp ${loadaddr} encryption_key_rproc.bin -
Read the contents of that RAM address interpreted as RPROC-FW-ENC-KEY. This command prints the hexadecimal bytes that form the RPROC-FW-ENC-KEY:
=> trustfence read_rproc_edmk ${loadaddr} Read RPROC-FW-ENC-KEY at 0x84000000 RPROC-FW-ENC-KEY OTP 336: [84000000] 9fbe507c RPROC-FW-ENC-KEY OTP 337: [84000004] cbb10285 RPROC-FW-ENC-KEY OTP 338: [84000008] a016e1fc RPROC-FW-ENC-KEY OTP 339: [8400000c] d534e4dd RPROC-FW-ENC-KEY OTP 340: [84000010] 6df71b3e RPROC-FW-ENC-KEY OTP 341: [84000014] e9b451f4 RPROC-FW-ENC-KEY OTP 342: [84000018] 4e4a47da RPROC-FW-ENC-KEY OTP 343: [8400001c] bca0fd04 -
Verify the hexadecimal values match the contents of the
encryption_key_rproc.binthat corresponds to the PKI tree you are using to sign the files. Remember to back up this PKI tree to be able to sign future images. -
Program the RPROC-FW-ENC-KEY in the OTP bits (irreversible):
=> trustfence prog_rproc_edmk ${loadaddr} RPROC-FW-ENC-KEY OTP 336: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 337: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 338: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 339: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 340: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 341: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 342: 00000000 lock : 00000000 RPROC-FW-ENC-KEY OTP 343: 00000000 lock : 00000000 RPROC-FW-ENC-KEY is not locked! RPROC-FW-ENC-KEY is free! Writing RPROC-FW-ENC-KEY with RPROC-FW-ENC-KEY OTP 336: [84000000] 9fbe507c RPROC-FW-ENC-KEY OTP 337: [84000004] cbb10285 RPROC-FW-ENC-KEY OTP 338: [84000008] a016e1fc RPROC-FW-ENC-KEY OTP 339: [8400000c] d534e4dd RPROC-FW-ENC-KEY OTP 340: [84000010] 6df71b3e RPROC-FW-ENC-KEY OTP 341: [84000014] e9b451f4 RPROC-FW-ENC-KEY OTP 342: [84000018] 4e4a47da RPROC-FW-ENC-KEY OTP 343: [8400001c] bca0fd04 Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y Fuse RPROC-FW-ENC-KEY OTP 336 : 9fbe507c Fuse RPROC-FW-ENC-KEY OTP 337 : cbb10285 Fuse RPROC-FW-ENC-KEY OTP 338 : a016e1fc Fuse RPROC-FW-ENC-KEY OTP 339 : d534e4dd Fuse RPROC-FW-ENC-KEY OTP 340 : 6df71b3e Fuse RPROC-FW-ENC-KEY OTP 341 : e9b451f4 Fuse RPROC-FW-ENC-KEY OTP 342 : 4e4a47da Fuse RPROC-FW-ENC-KEY OTP 343 : bca0fd04 RPROC-FW-ENC-KEY updated ! =>At this point, the RPROC-FW-ENC-KEY has been programmed and OP-TEE is ready to decrypt the RPROC firmware.
-
Reset the device
5.4.3. Load the signed firmware onto the Cortex-M33
Once the device has been provisioned with the required OTP keys, you can deploy and run the signed firmware. Signing of the RPROC firmware is described in Protect the Cortex-M33 coprocessor firmware.
5.5. Close the device
| This step is irreversible and could brick your device. |
Before closing the device:
-
Verify you have programmed signed and encrypted TF-A and FIP images in the eMMC.
-
Verify you have programmed the OEM-KEY1, EDMK1 and FIP-EDMK in the OTP bits.
-
Verify you have programmed the RPROC-FW-PKH and RPROC-FW-ENC-KEY for Cortex-M33 coprocessor in the OTP bits.
-
Verify the FSBL shows
Bootrom authentication succeeded. -
Verify the FSBL shows
TRUSTED_BOARD_BOOT support enabled. -
Verify the images boot up to Linux.
-
Make sure you have a backup of the generated PKI tree (by default in the
trustfence/folder in your project).
To close the device:
=> trustfence close
OTP 18: closed status: 0 lock : 00000000
OEM-KEY1 OTP 144: b53a0bb4 lock : 40000000
OEM-KEY1 OTP 145: 6a809bfa lock : 40000000
OEM-KEY1 OTP 146: 5c461350 lock : 40000000
OEM-KEY1 OTP 147: f8979d6f lock : 40000000
OEM-KEY1 OTP 148: ad1e36dd lock : 40000000
OEM-KEY1 OTP 149: e573053f lock : 40000000
OEM-KEY1 OTP 150: db27c6da lock : 40000000
OEM-KEY1 OTP 151: 5d297f18 lock : 40000000
Warning: Programming fuses is an irreversible operation!
This may brick your system.
Use this command only if you are sure of what you are doing!
Really perform this fuse programming? <y/N> y
Device is closed !
After that, the device will only boot properly signed images.
-
Reboot the device
-
Check the TrustFence status:
=> trustfence status * OEM-KEY1 fuses: [PROGRAMMED] [LOCKED] * OEM-KEY2 fuses: [NOT PROGRAMMED] [NOT LOCKED] * RPROC-FW-PKH fuses: [PROGRAMMED] [LOCKED] * Secure boot: [CLOSED]
Advanced options
Disable signing of images
Signing of images is automatically enabled as part of TrustFence.
To explicitly disable the generation of signed images, define TRUSTFENCE_SIGN to 0:
# Disable signed images
TRUSTFENCE_SIGN = "0"
The use case for disabling image signing is to separate the generation of the image from the signing process. For instance, you may want to avoid managing security keys on development machines and instead only sign images on a separate, more secure computer.
Use a custom PKI tree path
Digi Embedded Yocto creates by default a folder called trustfence/ inside your project to hold all keys.
To customize the location of the TrustFence keys set variable TRUSTFENCE_SIGN_KEY_PATH in your project’s conf/local.conf:
# Use a custom path to the signature keys and certificates.
TRUSTFENCE_KEYS_PATH = "/home/username/trustfence/mydevice"
Use custom FIT sign keys
Digi Embedded Yocto generates random keys to sign the artifacts in the FIT image, but you can optionally provide custom ones:
-
If it doesn’t already exist, create a subdirectory
fitinside your PKI tree path to hold the key pairs.$ mkdir <your-trustfence-sign-keys-path>/fit -
Optionally, edit your project config file
conf/local.confand set the following variables to give your keys custom names. (If not provided, the default filenames arefitcfgandfitimg.)conf/local.confTRUSTFENCE_FIT_CFG_SIGN_KEYNAME = "my-fitcfg" TRUSTFENCE_FIT_IMG_SIGN_KEYNAME = "my-fitimg" -
Generate an RSA private key to sign the FIT image nodes and another one to sign the configuration nodes:
$ openssl genrsa -F4 -out <your-trustfence-sign-keys-path>/fit/<your-fitcfg-name>.key 2048 $ openssl genrsa -F4 -out <your-trustfence-sign-keys-path>/fit/<your-fitimg-name>.key 2048 -
Generate public certificates out of the private keys:
$ openssl req -batch -new -x509 -key <your-trustfence-sign-keys-path>/fit/<your-fitcfg-name>.key -out <your-trustfence-sign-keys-path>/fit/<your-fitcfg-name>.crt $ openssl req -batch -new -x509 -key <your-trustfence-sign-keys-path>/fit/<your-fitimg-name>.key -out <your-trustfence-sign-keys-path>/fit/<your-fitimg-name>.crt -
Rebuild your project.
Disable U-Boot environment encryption
To explicitly disable U-Boot environment encryption, set TRUSTFENCE_ENCRYPT_ENVIRONMENT to 0 as follows:
# Disable U-Boot environment encryption
TRUSTFENCE_ENCRYPT_ENVIRONMENT = "0"
| When flashing U-Boot without the environment encryption feature in a device with an encrypted environment, all the values will be lost. Be sure to save any important data such as MAC addresses before you execute this procedure. |