1. Configure secure boot

To build signed artifacts, modify your conf/local.conf file to include the following:

conf/local.conf
# 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. U-Boot environment encryption

When TrustFence is enabled, the U-Boot environment is encrypted by default using the chip hardware unique key (HUK). The HUK is a symmetric encryption key stored in the OTP bits of the platform. Each chip has a unique HUK.

On the ConnectCore MP15, STMicroelectronics does not pre-provision an HUK. It is a customer choice to define and provision one.

To program the fuses in U-Boot to use the HUK:

=> fuse prog 0 62 <HUK_1>
=> fuse prog 0 63 <HUK_2>
=> fuse prog 0 64 <HUK_3>
=> fuse prog 0 65 <HUK_4>
=> saveenv

where each <HUK_n> must be a 32-bit value, and each device must have a unique full HUK.

By default, the OP-TEE uses a software HUK derivation. Configure your Digi Embedded Yocto project to enable the hardware HUK by adding the following to your project’s conf/local.conf file:

conf/local.conf
1 2
# Disable Software HUK EXTRA_OEMAKE += "CFG_STM32_HW_TESTKEY=n"
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:

  • arm-trusted-firmware/tf-a-ccmp15-dvk-nand.stm32_signed: This is the signed ARM Trusted Firmware for booting from the NAND.

  • fip/fip-ccmp15-dvk-optee_Signed.bin: This is the signed FIP image with the U-Boot bootloader and Trusted Execution Environment (OP-TEE).

  • fitImage-ccmp15-dvk.bin: This is the FIT image that contains the following artifacts with signed hashes:

    • The Linux kernel

    • The device tree

    • Device tree overlays

    • Boot script

Additionally, when not provided, the following keys are generated at the specified TRUSTFENCE_SIGN_KEYS_PATH location (by default, a subfolder in the project called trustfence/):

  • A PKI tree to sign the boot artifacts (under subfolder keys/)

  • One key pair (public/private) to sign the FIT image nodes

  • One key pair (public/private) to sign the FIT configuration nodes

The folder contains the following:

  • fitcfg.crt: public key for FIT configuration nodes

  • fitcfg.key: private key for FIT configuration nodes

  • fitimg.crt: public key for FIT image nodes

  • fitimg.key: private key for FIT image nodes

  • keys/key_pass.txt: the randomly generated password in plain text

  • keys/privateKey.pem: the private key

  • keys/publicKey.pem: the public key

  • keys/publicKeyhash.bin: hash of the ECC public key

These files need to be securely stored in order to be used in the manufacturing of secure devices.

3. Program the signed boot artifacts (TF-A and FIP)

Program the signed ARM Trusted Firmware image on the fsbl1 partition:

=> update fsbl1 tftp tf-a-ccmp15-dvk-nand.stm32_signed

Program the signed FIP image on the fip-a partition:

=> update fip-a tftp fip-ccmp15-dvk-optee_Signed.bin
Flashing signed images does not enable any security features in the target. See Secure the device to learn how to close your device to only boot signed images.

Reset the device, and check the new messages that appear:

NOTICE:  CPU: STM32MP157CAC Rev.Z
NOTICE:  Model: Digi International ConnectCore MP15 Development Kit
NOTICE:  Bootrom authentication failed
NOTICE:  BL2: v2.6-stm32mp1-r2.0(release):dey-4.0-r2.2(56756557)
NOTICE:  BL2: Built : 15:41:16, Mar 10 2023
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 BL32
optee optee: OP-TEE: revision 3.16 (da44f979)


U-Boot dub-2021.10-r2.2-00003-g7dd1458751a7 (Mar 21 2023 - 08:48:30 +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 ECC public key on 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 on 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.

4. 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:

4.1. Program the Public Key Hash (PKH)

The PKH OTP bits (words 24..31) hold the hash of the ECC public key.

The ConnectCore MP15 has two boot stages:

  • Initially, the ROM loader uses the PKH 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 PKH is not programmed, it skips the authentication and boots it; if the PKH is programmed, it validates the signature and refuses to boot if the authentication fails.

To program the PKH:

  1. Check the current status of the device:

    => trustfence status
    * PKH fuses:  [NOT PROGRAMMED] [NOT LOCKED]
    * Secure boot:  [OPEN]

    The command reports the PKH is not programmed and the device is open.

  2. Transfer the publicKeyhash.bin into an address in RAM, for example via TFTP:

    => tftp ${loadaddr} publicKeyhash.bin
  3. Read the contents of that RAM address interpreted as PKH. This command prints the hexadecimal bytes that form the PKH:

    => trustfence read_pkh ${loadaddr}
    Read PKH at 0xc2000000
    PKH OTP 24: [c2000000] 5cda63dc
    PKH OTP 25: [c2000004] 5a2b8e15
    PKH OTP 26: [c2000008] f0708804
    PKH OTP 27: [c200000c] c2dfc733
    PKH OTP 28: [c2000010] a34fb740
    PKH OTP 29: [c2000014] 246b14e3
    PKH OTP 30: [c2000018] ef53f16b
    PKH OTP 31: [c200001c] 53ef8f83
  4. Verify the hexadecimal values match the contents of the publicKeyhash.bin that 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.

  5. Program the PKH on the OTP bits (irreversible):

    => trustfence prog_pkh ${loadaddr}
    PKH OTP 24: 00000000 lock : 10000000
    PKH OTP 25: 00000000 lock : 10000000
    PKH OTP 26: 00000000 lock : 10000000
    PKH OTP 27: 00000000 lock : 10000000
    PKH OTP 28: 00000000 lock : 10000000
    PKH OTP 29: 00000000 lock : 10000000
    PKH OTP 30: 00000000 lock : 10000000
    PKH OTP 31: 00000000 lock : 10000000
    PKH is not locked!
    PKH is free!
    Writing PKH with
    PKH OTP 24: 5cda63dc lock : 50000000
    PKH OTP 25: 5a2b8e15 lock : 50000000
    PKH OTP 26: 17125380 lock : 50000000
    PKH OTP 27: c2dfc733 lock : 50000000
    PKH OTP 28: a34fb740 lock : 50000000
    PKH OTP 29: 246b14e3 lock : 50000000
    PKH OTP 30: ef53f16b lock : 50000000
    PKH OTP 31: 53ef8f83 lock : 50000000
    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
    PKH updated!

    At this point, the PKH has been programmed but the device is still open and can still boot any unsigned images.

  6. Reset the device, and check the new messages that appear:

    NOTICE:  CPU: STM32MP157CAC Rev.Z
    NOTICE:  Model: Digi International ConnectCore MP15 Development Kit
    NOTICE:  Bootrom authentication succeeded
    NOTICE:  BL2: v2.6-stm32mp1-r2.0(release):dey-4.0-r2.2(56756557)
    NOTICE:  BL2: Built : 15:41:16, Mar 10 2023
    NOTICE:  TRUSTED_BOARD_BOOT support enabled
    NOTICE:  BL2: Booting BL32
    optee optee: OP-TEE: revision 3.16 (da44f979)
    
    
    U-Boot dub-2021.10-r2.2-00003-g7dd1458751a7 (Mar 21 2023 - 08:48:30 +0000)
    
    [...]
    
    => 

    The Bootrom authentication succeeded message appears. This means the ROM loader detected that it is booting a signed image and it could successfully authenticate it against the programmed PKH.

    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.

  7. Check the TrustFence status:

    => trustfence status
    * PKH fuses:  [PROGRAMMED] [LOCKED]
    * Secure boot:  [OPEN]
On open devices you can still boot unsigned images without authentication support (without TrustFence).

4.2. Close the device

This step is irreversible and could brick your device.

Before closing the device:

  • Verify you have programmed signed, not encrypted, TF-A and FIP images in the NAND.

  • Verify you have programmed the PKH.

  • Verify the FSBL shows Bootrom authentication succeeded.

  • Verify the FSBL shows TRUSTED_BOARD_BOOT support enabled.

  • Verify the images boot up to U-Boot.

  • Make sure you have a backup of the generated PKI tree.

To close the device:

=> trustfence close
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.

  1. Check the TrustFence status:

    => trustfence status
    * 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:

conf/local.conf
# 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

You can use the following parameters to customize the location of the sensitive keys:

  • TRUSTFENCE_SIGN_KEYS_PATH: Path to a folder containing the PKI tree. If the folder does not exist or does not contain a PKI tree, a new PKI tree is generated automatically. The default value is a new folder trustfence in the Digi Embedded Yocto project home location.

conf/local.conf
# Use a custom path to the signature keys and certificates.
TRUSTFENCE_SIGN_KEYS_PATH = "/mnt/secure/PKI_tree"

Disable U-Boot environment encryption

To explicitly disable U-Boot environment encryption, set TRUSTFENCE_ENCRYPT_ENVIRONMENT to 0 as follows:

conf/local.conf
# 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.