Signing Secure Boot Image Components on Torizon OS
Secure Boot is an Early Access feature. Please note that:
- Breaking changes may be introduced at any given time, irrespective of the Toradex Embedded Linux Support Strategy.
- Software support and features are limited.
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.
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. 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.
- The features in this article require a minimum version of 3.14.0 of TorizonCore Builder
The Secure Boot features in TorizonCore Builder are currently in early access status. As a result, breaking changes may occur at any time. When working with Secure Boot, Toradex recommends using the early-access version of TorizonCore Builder to ensure you have access to the latest features and an up-to-date CLI.
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-signedBitBake class of themeta-toradex-securityYocto layer.
A pre-signed image can be obtained on the Download Links page.
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.
Creating a New RSA Key Pair
This example creates a RSA key using OpenSSL. If using another tool to generate the keys, adapt the steps accordingly.
Skip this section if you already have an asymmetric key pair and certificate to sign the kernel FIT image.
- Create a directory to store the key pair:
$ mkdir -p kernel_key
- 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.
- 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.
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 example below.
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.
The data and configuration for the re-signing is passed via the properties under customization.secboot.
# 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 Creating a New RSA Key Pair and Setup for NXP i.MX SoMs sections. Make sure to adjust your configuration file appropriately for your information.
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
If you skipped the Creating a New RSA 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.
- 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
- Run
images unpackto provide TorizonCore Builder with the input image:
$ torizoncore-builder images unpack images/<your-torizon-os-image-directory>
- Run
secboot sign-kernelto 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!
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
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.
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.
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.