Skip to main content
Version: Torizon OS 7.x.y

Signing Secure Boot Image Components on Torizon OS

warning

Secure Boot is an Early Access feature. Please note that:

Introduction​

This article details the Secure Boot implementation using TorizonCore Builder to re-sign a pre-signed Torizon OS image with up to Basic Chain of Trust (BCoT), which covers the validation of the bootloader components and the kernel artifacts, as defined in the Secure Boot on Torizon OS article.

The process requires a pre-signed image because its bootloader and kernel are built with the required features for Secure Boot. These features include: a kernel in FIT format, U-Boot Kconfigs correctly set up for Verified Boot, U-Boot hardening, etc.

Note that an unsigned Torizon OS image does not have these features built in. Therefore, these images cannot be used to enable Secure Boot.

info

This implementation is a way to obtain a user-signed Torizon OS image with Secure Boot features enabled without manually building one with Yocto Project/OpenEmbedded. If you need to build your own Torizon OS image, please refer to Integrate Secure Boot on Torizon OS.

In this implementation both the bootloader components and the kernel artifacts are re-signed with user-provided keys using TorizonCore Builder.

This article complies with the Typographic Conventions for Torizon Documentation.

Prerequisites​

  • A terminal environment with the TorizonCore Builder setup script sourced and with the tool available, as instructed in Install TorizonCore Builder.
tip

When working with Secure Boot, Toradex recommends using the early-access version of TorizonCore Builder to access the latest features and CLI updates. Note that features in this version are subject to breaking changes.

Throughout this article, $PROJDIR refers to the path where the script was sourced. The following example uses ~/secboot:

$ export PROJDIR=~/secboot
$ mkdir -p $PROJDIR
$ cd $PROJDIR

This path can be any writable directory on the system.

  • A Toradex SoM supported by the Secure Boot signing feature of TorizonCore Builder. Refer to Support Status and Limitations for more information.

  • A pre-signed Torizon OS image of a supported SoM, built with BCoT support. More specifically, the image must have been built with the tdx-signed BitBake class of the meta-toradex-security Yocto layer.

A pre-signed image can be obtained on the Download Links page.

danger

The provided pre-signed images are signed with engineering keys and are only meant for development and testing purposes.

Always re-sign the pre-signed images with new keys before using in production.

Create a Kernel Signing Key Pair​

This example creates a RSA key pair for signing the kernel using OpenSSL. If using another tool to generate the keys, adapt the steps accordingly.

info

Skip this section if you already have an asymmetric key pair and certificate to sign the kernel FIT image.

  1. Create a directory to store the key pair:
$ mkdir -p kernel_key
  1. Create a new 2048-bit RSA key:
$ export KERNEL_KEY_NAME=test_key
$ openssl genpkey -algorithm RSA -out kernel_key/$KERNEL_KEY_NAME.key \
-pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537

test_key was used as an example. Replace the value of KERNEL_KEY_NAME with your key name.

  1. Create a certificate for the public key:
$ openssl req -batch -days 30 -new -x509 -key kernel_key/$KERNEL_KEY_NAME.key -out kernel_key/$KERNEL_KEY_NAME.crt

This key is used in the following sections to re-sign the Torizon OS image. Ensure to handle the key carefully if used in production images.

Setup for NXP i.MX SoMs​

In order to sign the bootloader for SoCs compatible with HAB/AHAB (High Assurance Boot/Advanced High Assurance Boot), users should first download the latest Code Signing Tool (CST) on the NXP website and follow the instructions in the Code-Signing Tool User's Guide to generate keys, certificates, SRK tables and Efuse Hash, all of which are used by TorizonCore Builder for the re-signing process.

Some choices provided during the key generation script, like the key type, bit length, CA flag, etc. need to be passed as arguments to TorizonCore Builder. See the following sections for more details.

In this example the CST directory is unpacked and copied inside of $PROJDIR. For demonstration sake the name of this directory is cst-4.0.1.

Setup for TI K3 SoMs​

On SoMs based on TI K3 SoCs, such as the Verdin AM62 and the Verdin AM62P, the bootloader is signed with a customer key whose public counterpart is hashed into the SoC fuses when the device is closed. This key establishes the root of the Chain of Trust and is the only signing material you need to provide. Unlike the HABv4 workflow, no separate signing tool is required because TorizonCore Builder includes the tools needed for the signing process.

TI's OTP Keywriter for the AM62x and AM62Px can program the primary and backup public key hashes (SMPKH/BMPKH) of 4096-bit RSA keys. Check the OTP Keywriter release documentation for support for other key types.

The following example uses OpenSSL to create an RSA-4096 key, as used for Torizon OS images; adapt the steps if you use another method.

$ mkdir -p k3_key
$ openssl genrsa -F4 -out k3_key/custMpk.pem 4096
info

Unlike a Yocto build, which requires the key file to be named custMpk, TorizonCore Builder does not require a specific filename. You provide the key file through the --k3-key option or the k3-key configuration property.

On SoCs with a GP (General Purpose) variant, such as the AM62x, components intended for GP silicon are signed with a degenerate key published by TI. Because GP silicon does not verify signatures, the key provides no security guarantees, and components signed with different degenerate keys are equivalent from a boot verification perspective. The AM62Px has no GP variant, so components for the Verdin AM62P are not signed with a degenerate key. However, TorizonCore Builder still requires the key file when building the bootloader. In both cases, TorizonCore Builder includes TI's degenerate key and uses it by default, so you do not need to provide an additional key.

Approach 1: Re-Signing Image Components Using the Build Command​

The TorizonCore Builder build command can generate a custom Torizon OS image with the re-signing of the kernel and bootloader done, ready to be installed with Toradex Easy Installer, named torizon-os-signed in the following example.

This is achieved using the tcbuild.yaml configuration file, which is the recommended approach for production programming and CI/CD (continuous integration / continuous development) pipelines.

To learn about TorizonCore Builder workflow and the different approaches to use the tool, with explanatory diagrams, please refer to the TorizonCore Builder Overview article.

Re-signing data and configuration are specified through properties under customization.secboot. Because the bootloader configuration depends on the Secure Boot technology, the following sections provide a separate example for each supported technology.

NXP HABv4 Configuration Example​

On SoMs based on NXP HAB (High-Assurance Boot), the bootloader section is sign-bootloader-hab:

tcbuild.yaml
# Sample configuration file:
input:
easy-installer:
local: "<Path to pre-signed Torizon OS Easy Installer image>"

customization:
secboot:
sign-bootloader-hab:
cst-dir: "cst-4.0.1"
cst-args:
crypto: "rsa"
key-size: "4096"
key-exp: "65537"
dig-algo: "sha256"
srk-index: "1"
srk-table: "SRK_1_2_3_4_table.bin"
srk-fuse: "SRK_1_2_3_4_fuse.bin"
# srk-no-ca-flag: true
kernel-key-dir: "kernel_key"
kernel-key:
- name: "test_key"
algo: "sha256,rsa2048"
sign-kernel:
kernel-key-dir: "kernel_key"
kernel-key:
- name: "test_key"
algo: "sha256,rsa2048"

output:
easy-installer:
local: "torizon-os-signed"

The preceding YAML file was created using the information in the Create a Kernel Signing Key Pair and Setup for NXP i.MX SoMs sections. Make sure to adjust your configuration file appropriately for your information.

TI K3 Configuration Example​

On SoMs based on TI K3 SoCs the bootloader section is sign-bootloader-k3, and it takes the customer key created in Setup for TI K3 SoMs; the kernel signing section uses the key pair generated as per Create a Kernel Signing Key Pair:

tcbuild.yaml
# Sample configuration file:
input:
easy-installer:
local: "<Path to pre-signed Torizon OS Easy Installer image>"

customization:
secboot:
sign-bootloader-k3:
k3-key: "k3_key/custMpk.pem"
kernel-key-dir: "kernel_key"
kernel-key:
- name: "test_key"
algo: "sha256,rsa2048"
# target-device: "hs-se"
sign-kernel:
kernel-key-dir: "kernel_key"
kernel-key:
- name: "test_key"
algo: "sha256,rsa2048"

output:
easy-installer:
local: "torizon-os-signed"

The target-device property is commented out in the preceding example on purpose. Refer to Choosing the Kind of Module the Image Targets for when to set it.

warning

Both sections, sign-bootloader-k3 and sign-kernel, are required to produce a bootable image.

The sign-bootloader-k3 section configures the public key that the bootloader uses to verify the kernel, while sign-kernel signs the kernel with the corresponding private key. Both sections are required; omitting either results in an image that does not boot. Refer to Re-signing the Kernel With the Same Key for more details.

Build the Custom Image​

To generate the Torizon OS image, run the command below, in the same directory where the tcbuild.yaml file is:

$ torizoncore-builder build

...
1091 metadata, 12741 content objects imported; 412.2 MB content written
Pulling done.
Deploying OSTree with checksum 58629613a342197c31c5911d0874aac1b0fcb46b68a63f59760c03bacc4df08a
Deploying done.
Copy files not under OSTree control from original deployment.
Packing rootfs...
Packing rootfs done.

=>> Build command successfully executed!

In case of using a configuration file with a different name than tcbuild.yaml, run the command specifying the configuration file name:

$ torizoncore-builder build --file <configuration_file_name>

The image produced here must be installed with Toradex Easy Installer for all of the signing related customizations to take effect.

Approach 2: Re-signing Image Components Using Standalone Commands​

Signing the Kernel FIT image​

The signatures of the kernel FIT configurations are checked at run-time by U-Boot using the Verified Boot feature, which supports RSA and ECDSA keys. For more details on supported algorithms, see the U-Boot documentation on FIT Signature Verification.

Signing with the New Key​

info

If you skipped the Create a Kernel Signing Key Pair section due to already having a key pair and certificate, copy both files to a directory inside $PROJDIR, for example, $PROJDIR/kernel_key, and replace $KERNEL_KEY_NAME with the name of your key.

  1. Copy the pre-signed Torizon OS image inside $PROJDIR, for example in $PROJDIR/images/. The image should be in Toradex Easy Installer format, either as a tarfile or as a directory:
$ tree images/
images/
└── torizon-docker-verdin-imx8mp-Tezi_7.6.0-devel-20260312+build.417
├── image.json
├── imx-boot
├── LA_OPT_NXP_SW.html
├── marketing.tar
├── prepare.sh
├── tcb_signing_files.tar.gz
├── toradexlinux.png
├── torizon-docker-verdin-imx8mp.ota.tar.zst
├── u-boot-initial-env-sd
└── wrapup.sh
  1. Run images unpack to provide TorizonCore Builder with the input image:
$ torizoncore-builder images unpack images/<your-torizon-os-image-directory>
  1. Run secboot sign-kernel to re-sign the image with the new key:
$ torizoncore-builder secboot sign-kernel \
--kernel-key-dir kernel_key/ \
--kernel-key "name=$KERNEL_KEY_NAME;algo=sha256,rsa2048"

The algo field in --kernel-key corresponds to the --algo option of the U-Boot tool mkimage; its second value should be the cryptographic algorithm of the new key (rsa2048 in this example). Check the mkimage manpage for more details on possible values.

On a successful run, TorizonCore Builder should confirm the provided values and print the actual mkimage command executed to update the kernel FIT:

Detected image for machine "verdin-imx8mp".
Found kernel in FIT format.
...
Signature written to '/storage/secure_boot_workdir/vmlinuz'...
...
Execute: SOURCE_DATE_EPOCH=0 /u-boot/tools/mkimage ...
...
Kernel in unpacked Torizon OS image signed successfully!
caution

Keep in mind that the bootloader is the component that verifies the kernel FIT. As such, every time the kernel is signed with a new key U-Boot needs to be updated with the corresponding public key information. This can be done when re-signing the bootloader container, as detailed in Signing the Bootloader Container.

To create a final installable image, refer to the Creating Final Signed Image section.

Signing the Bootloader Container​

This section uses the same Torizon OS image from the previous section made available via images unpack. The resulting image has both the bootloader and the kernel FIT re-signed with user keys.

If you skipped the previous section and only want to re-sign the bootloader container, run images unpack on your pre-signed Torizon OS image before following the rest of this section.

Signing the Bootloader Container for SoCs using HABv4​

Run secboot sign-bootloader-hab to re-sign the image with the new key:

$ torizoncore-builder secboot sign-bootloader-hab \
--cst-dir cst-4.0.1/ \
--kernel-key "name=$KERNEL_KEY_NAME;algo=sha256,rsa2048" \
--kernel-key-dir kernel_key \
--cst-crypto rsa \
--cst-key-size 4096 \
--cst-key-exp 65537 \
--cst-dig-algo sha256 \
--cst-srk-table SRK_1_2_3_4_table.bin \
--cst-srk-fuse SRK_1_2_3_4_fuse.bin \
--cst-srk-index 1
note

If you only want to re-sign the bootloader and don't intend to re-sign the kernel FIT, remove --kernel-key and --kernel-key-dir. Otherwise, use the same values for their corresponding arguments given in secboot sign-kernel.

With these two arguments provided TorizonCore Builder updates the public key in U-Boot used to verify the kernel FIT before re-signing the bootloader container itself. Any previously existing public keys in U-Boot are replaced with the newly provided keys.

Replace the values of --cst-crypto, --cst-key-size, --cst-key-exp, --cst-dig-algo according to the answers given in the CST key generation script. --cst-srk-table and --cst-srk-fuse refer to the given filenames of the SRK table and Efuse hash binaries, respectively.

Replace the value of --cst-srk-index with the desired SRK table index to be used for the signing process.

note

If the CA flag was not set when generating the SRK certificates, add the --cst-srk-no-ca argument.

On a successful run, TorizonCore Builder should confirm the provided values and print the commands executed to create and sign the bootloader container:

Detected image for machine "verdin-imx8mp".
Found kernel in FIT format.
Attempting to sign the bootloader container with the following options:
- Key type: rsa
- Key length: 4096
...
Running CST found in ./cst-4.0.1/linux64/bin/cst
...
Public key 'test_key' in kernel_key will be used by the bootloader to verify the kernel signature.

Bootloader in Torizon OS image signed successfully!

To create a final installable image, refer to the Creating Final Signed Image section.

Signing the Bootloader Container for SoCs using TI K3​

Run secboot sign-bootloader-k3 to re-sign the bootloader with the customer key created in Setup for TI K3 SoMs:

$ torizoncore-builder secboot sign-bootloader-k3 \
--k3-key k3_key/custMpk.pem \
--kernel-key "name=$KERNEL_KEY_NAME;algo=sha256,rsa2048" \
--kernel-key-dir kernel_key

As with the HABv4 command, --kernel-key and --kernel-key-dir specify the public key that the signed bootloader uses to verify the kernel. Their values must match those provided to secboot sign-kernel.

On a successful run, TorizonCore Builder displays the detected machine, the key used for signing, and the generated binaries:

Detected image for machine "verdin-am62".
Signing the bootloader binaries of a "verdin-am62" image with "custMpk.pem".
Adding public key 'test_key' in kernel_key to u-boot.dtb
...
Assembling the boot binaries of "k3r5" with binman
...
Assembling the boot binaries of "a53" with binman
...
Signed bootloader binaries: tiboot3-am62x-hs-fs-verdin.bin, tiboot3-am62x-hs-verdin.bin, tiboot3-am62x-gp-verdin.bin, tispl.bin, u-boot.img.
Public key 'test_key' in kernel_key will be used by the bootloader to verify the kernel signature.

Bootloader in Torizon OS image signed successfully!

One boot container is generated for each kind of silicon the SoC supports: three on the Verdin AM62 (GP, HS-FS and HS-SE) and two on the Verdin AM62P (HS-FS and HS-SE). The HS-FS and HS-SE containers are signed with your key. The image installs the appropriate boot container based on the type of module it targets.

Re-Signing the Kernel With the Same Key​

--kernel-key is optional on this command. When it is omitted, TorizonCore Builder carries over the public key already present in the image being signed and says so:

Warning: no kernel key was passed, so the public key 'dev' read from "u-boot.img" in this image is being carried over to the signed bootloader.
This is the key of whoever built the image, not yours: on a Toradex image it is an engineering key meant for development and testing. Pass --kernel-key to have the bootloader verify the kernel with a key of your own.

Please note that this is a convenience for development. For production, ensure to pass your own --kernel-key and re-sign the kernel with the matching private key using secboot sign-kernel.

warning

The bootloader verifies the kernel, so both must use the same key pair. Signing the bootloader with your key while leaving the kernel signed with a different key results in an image that does not boot because the bootloader cannot verify the kernel. Run both signing commands, or use the build command with both the sign-bootloader-k3 and sign-kernel sections.

Choosing the Kind of Module the Image Targets​

A module based on a TI K3 SoC boots a different boot container depending on whether its fuses have been programmed: HS-FS (High Security - Field Securable) for a module that is not fused, and HS-SE (High Security - Security Enforced) for one whose keys have been fused. A Torizon OS image installs one of them, and the pre-signed images published by Toradex target HS-FS.

This is important in production modules. Fusing a module makes it HS-SE, and an image targeting HS-FS does not boot on it. Pass --target-device to choose which one the deployed image installs:

$ torizoncore-builder secboot sign-bootloader-k3 \
--k3-key k3_key/custMpk.pem \
--kernel-key "name=$KERNEL_KEY_NAME;algo=sha256,rsa2048" \
--kernel-key-dir kernel_key \
--target-device hs-se

TorizonCore Builder warns about what the choice means, in either direction:

Warning: the image will boot only on a module whose keys have been fused; make sure the module is properly fused, otherwise the image will hang at boot.
Note: the Toradex Easy Installer recovery files are not affected by this setting. Recovering a module over USB requires a recovery image built for the kind of device being recovered.

If --target-device is not specified, the image retains its existing target. Every boot container remains in the signed image, with the HS-FS and HS-SE ones signed with your key, allowing the image to be re-targeted later without re-signing.

info

Toradex Easy Installer recovery files are part of the recovery bundle rather than the Torizon OS image. Therefore, recovering a fused module over USB requires a recovery image built for an HS-SE device.

To create a final installable image, refer to the Creating Final Signed Image section.

Creating Final Signed Image​

Once you have re-signed the kernel and/or bootloader, create an image containing the re-signed components and install it using Toradex Easy Installer. This is mandatory to ensure that all signing-related customizations are applied correctly.

Deploy the re-signed kernel and/or bootloader with the following commands:

$ torizoncore-builder union test
Found signed bootloader in storage. Applying changes.
...
Commit b738e1b... has been generated for changes and is ready to be deployed.
$ torizoncore-builder deploy --output-directory signed test

You should see an output similar to the following:

Deploying commit ref: test
...
# Fusing instructions to be executed in U-Boot:

# These are One-Time Programmable e-fuses. Once you write them you can't
# go back, so get it right the first time!
fuse prog -y 6 0 0xB30C7ED2
fuse prog -y 6 1 0x9E5A86D4
...
# You can recheck the instructions given above in fuse-cmds.txt created in directory 'signed'.

The final re-signed image should be available in the directory passed as an argument in the deploy command.

Next Steps​

Check the Production Programming Secure Boot with Torizon article to learn how to make the newly re-signed image automatically fuse the device on first boot.

Send Feedback!