In-field Upgrades to Secure Boot on Torizon OS
This document complies with the Typographic Conventions for the Toradex Documentation.
Introduction
This article presents recommended procedures for upgrading devices in the field to Secure Boot, assuming they are running Torizon OS. Basically, we describe methods for the following types of upgrade:
- Non-Secure Boot to BCoT (Basic Chain of Trust)
- BCoT to ECoT (Extended Chain of Trust)
- Non-Secure Boot to ECoT
Each type is explained on a separate section along with the motivation for performing (or not) the upgrade.
Currently, in-field upgrades are supported on the following Toradex devices:
- Colibri i.MX6DL
- Colibri i.MX6ULL 1GB
- Colibri i.MX7D 1GB
- Colibri i.MX8X
- Apalis i.MX6
- Apalis i.MX8
- Verdin i.MX8M Mini
- Verdin i.MX8M Plus
Before reading this document, please familiarize yourself with the terminology introduced in the main article: Secure Boot on Torizon OS.
Prerequisites
- The procedures described in the present article require Torizon OS version 7.2.0 or newer, though the system being upgraded can be older (within the Torizon OS 7.x.y series).
- The reader is assumed to be familiar with TorizonCore Builder, particularly with its use to push OS packages to the platform (Torizon Cloud).
Users intending to upgrade to Secure Boot must first upgrade to Torizon OS 7.
Upgrading from Non-Secure Boot to BCoT
In this section, we describe a procedure for upgrading devices from Non-Secure Boot to BCoT (Basic Chain of Trust) – a coverage level spanning ROM → bootloader → kernel. Since the affected artifacts (bootloader, boot scripts and kernel) are rarely customized, most users can benefit from this upgrade with minimal development and maintenance effort. Moreover, once a BCoT system boots, applications are expected to behave identically. This means end-users won't be affected by the upgrade – except positively, by the enhanced security. Given that, users are always encouraged to consider this type of upgrade.
Overall, the procedure consists in creating the necessary packages on the platform and then performing a sequence of updates on each device in the field, as detailed in the following sections.
Create the necessary packages
First of all, we'll need to create packages on the platform for the components that will be replaced when upgrading to BCoT (namely: OS, bootloader and fuse packages):
-
Build a
tdx-signedimage:Follow the instructions on Build Secure Boot Image to build an image with the
tdx-signedclass. The final result will be an OpenEmbedded (OE) deployment directory underdeploy/images/<MACHINE>with multiple artifacts – we'll refer to this directory as<deploydir>. From the artifacts in that directory, the following ones will be needed:- A tarball with the Toradex Installer image (e.g.
torizon-minimal-verdin-imx8mp-Tezi_7.3.0-devel-20250611005152+build.0.tar). This tarball contains the root filesystem for the OS which in turn has an OSTree repository with a commit that can be pushed to the platform via TorizonCore Builder. - A signed bootloader binary (
u-boot-ota.bin) suitable for OTA updates along with a JSON file (u-boot-ota.json) with information required for pushing the binary to the platform via TorizonCore Builder. - A file with fuse programming values (
fuse-cmds.txt) which one can employ to create and push a fuse package to the platform.
- A tarball with the Toradex Installer image (e.g.
With the mentioned artifacts available, you can go ahead and push the various packages to the platform.
-
Push the OS part of the image (OSTree commit) to the platform.
This fairly common operation can be easily achieved by running, for example:
$ torizoncore-builder images unpack <deploydir>/torizon-minimal-verdin-imx8mp-Tezi_7.3.0-devel-20250611005152+build.0.tar
$ torizoncore-builder platform push --credentials <credentials-zip-file> --package-name <bcot-os-package-name> --package-version <bcot-os-package-version> base -
Push the bootloader binary to the platform.
This requires a special procedure described in Custom Bootloader Updates. Notice this will take as input the already mentioned bootloader files (
u-boot-ota.bin,u-boot-ota.json) that you should have at hand. Be sure to follow only the part of the procedure regarding the package upload (i.e. do not perform the actual update as we have a separate step for it in the present document). -
Create and push a fuse package to the platform.
This also requires a special procedure which consists in:
- Creating a "fuse yaml" file based on information extracted from
fuse-cmds.txt– this is described in Fuse Yaml File. - Uploading the "fuse yaml" file to the platform – this is outlined in Fuse Update. Again, make sure to follow only the package upload steps in that procedure (i.e. do not perform any device updates), and verify that the correct hardware ID is set for the uploaded package.
- Creating a "fuse yaml" file based on information extracted from
Upgrade devices in the field
Once the BCoT packages are available, users can upgrade one or multiple devices in the field by performing a sequence of component updates:
-
Perform an OS update.
-
When booting with this new OS version, the kernel FIT binary will be signed but its signature will not yet be validated since at this step the bootloader will be still the unsigned one which does not contain the key required for validating the next artifact in the Chain of Trust (the kernel).
-
Users with access to the serial console of the device can follow up this update step.
noteworthy messages when device boots with the new OS
## Loading kernel from FIT Image at 50300000 ... <----- (1)
Using 'conf-freescale_imx8mp-verdin-wifi-dev.dtb' configuration <--+-- (2)
Trying 'kernel-1' kernel subimage <--+
Description: Linux kernel
Type: Kernel Image
Compression: gzip compressed
...
Hash algo: sha256
Hash value: f88bd67575ce743803c10a19bdfdd4bef468150fa388d4b0f1a712328fd9d9bb
Verifying Hash Integrity ... sha256+ OK- (1) Notice the message saying that the kernel is being loaded from a FIT image (required).
- (2) Notice the absence of a message about "hash integrity" at this point. Compare with the output after the bootloader update on the next step.
-
-
Perform a bootloader update.
-
When booting with this new bootloader version, the kernel and the kernel boot arguments will be validated but the bootloader binary won't.
-
Users with access to the serial console of the device can follow up this update step.
noteworthy messages when device boots with the new bootloader
## NOTE: Bootloader seems to support secure boot. <----- (1)
...
## Loading kernel from FIT Image at 50300000 ...
Using 'conf-freescale_imx8mp-verdin-wifi-dev.dtb' configuration <--+
Verifying Hash Integrity ... sha256,rsa2048:dev+ OK <--+-- (2)
Trying 'kernel-1' kernel subimage <--+
Description: Linux kernel
Type: Kernel Image
Compression: gzip compressed
Data Start: 0x503000e8
Data Size: 11474515 Bytes = 10.9 MiB
Architecture: AArch64
OS: Linux
Load Address: 0x48200000
Entry Point: 0x48200000
Hash algo: sha256
Hash value: f88bd67575ce743803c10a19bdfdd4bef468150fa388d4b0f1a712328fd9d9bb
Verifying Hash Integrity ... sha256+ OK
...
## Validation of bootargs succeeded. <----- (3)- (1) Message from the Torizon OS boot script indicating that the bootloader has support for secure boot and fusing.
- (2) Message informing the hashing and signing algorithms employed and the name of the key used for validation of the FIT image component.
- (3) Message indicating that the arguments passed to the kernel match the expected value; this is part of the checks done by the hardening features implemented by Toradex on U-Boot.
-
-
Perform a fuse update.
- After this step, the Basic Chain of Trust is fully established.
- Users testing this procedure are advised to check the main article on Secure Boot Fuse Programming for tips on validating this type of update.
Upgrading from BCoT to ECoT
In the present section, we describe a procedure for upgrading devices from BCoT to ECoT (Extended Chain of Trust) – a coverage level spanning ROM → bootloader → kernel → root filesystem. Unlike the upgrade to BCoT, the protection to the root filesystem added by ECoT will generally produce visible changes in system behavior that are likely to impact features of a product. This comes from the fact that runtime changes to the /etc directory become non-persistent across reboots (unless further actions are taken). Therefore, users interested in this upgrade to their products should carefully read the article about the Root filesystem protection on Torizon OS before moving forward to ECoT.
Here we assume that the required design changes to accommodate to the behavioral changes have been made and the decision to go to ECoT has been taken. The upgrade procedure itself is quite simple and again consists in creating the necessary packages on the platform and then executing a sequence of updates on each device in the field.
Pushing ECoT images to the platform requires TorizonCore Builder version 3.13 or newer.
Create the necessary packages
-
Build a transitional
torizon-signedimage:Follow the instructions on Build Secure Boot Image to set up the build with the
torizon-signedclass, but do not build the image yet. Additionally to the normal configuration, set the following variables in yourlocal.conffile:PREP_ROOT_CFS_ENABLED = "maybe"
CFS_UPGRADE_ENABLE = "1"With this extra configuration, the image will include support for the root filesystem protection but it will not enforce it (necessary when transitioning from an unprotected to a protected filesystem). A dedicated routine in the initial ramdisk will also be enabled to upgrade the existing root filesystem with the required features for the protection to take effect.
Since the
torizon-signedclass (covering ECoT) encompasses thetdx-signedclass (covering BCoT), the setup for the BCoT features should match the one used when building the BCoT image running on the devices that will be upgraded. This includes using the same bootloader and kernel signing keys from BCoT.Now that the setup part is finished, go ahead and build your transitional ECoT image (via
bitbake). As a result of the build, a Toradex Installer image should be produced in the OpenEmbedded (OE) deployment directory (what we call here<deploydir>) along with many other artifacts.In this procedure, we are interested only in the Toradex Installer image tarball containing the new OS version that we will upload to the platform in the next step. Let's assume the produced tarball was named
torizon-minimal-verdin-imx8mp-Tezi_7.3.0-devel-20250616204215+build.0.tar. -
Push the transitional
torizon-signedimage to the platform:As with any OS image, this can be achieved by running:
$ torizoncore-builder images unpack <deploydir>/torizon-minimal-verdin-imx8mp-Tezi_7.3.0-devel-20250616204215+build.0.tar
$ torizoncore-builder platform push --credentials <credentials-zip-file> --package-name <transitional-ecot-os-package-name> --package-version <transitional-ecot-os-package-version> base -
Build a standard (non-transitional)
torizon-signedimage:Repeat the build from the first step but this time do not set the additional variables. For this, you can create a whole new setup or reuse the setup from that step removing or commenting out the extra variables in the
local.conffile, e.g. (notice the hash marks at the beginning of the line):#PREP_ROOT_CFS_ENABLED = "maybe"
#CFS_UPGRADE_ENABLE = "1"After the build is finished, the OpenEmbedded deployment directory will contain several artifacts but we are interested only in the Toradex Installer image. Let's assume that image in tarball form is now named
torizon-minimal-verdin-imx8mp-Tezi_7.3.0-devel-20250617012742+build.0.tar. -
Push the standard
torizon-signedimage to the platform:Again, using TorizonCore Builder:
$ torizoncore-builder images unpack <deploydir>/torizon-minimal-verdin-imx8mp-Tezi_7.3.0-devel-20250617012742+build.0.tar
$ torizoncore-builder platform push --credentials <credentials-zip-file> --package-name <standard-ecot-os-package-name> --package-version <standard-ecot-os-package-version> base
Upgrade devices in the field
Devices in the field can now be upgraded from BCoT to ECoT by following these steps:
-
Perform an OS update to the transitional
torizon-signedimage.-
When booting with this OS version, a routine in the initial ramdisk will be executed to enable fs-verity on the individual files of the OSTree repository. This process can take 2-5 minutes to complete and it will be resumed in case the device is rebooted before it's fully finished.
-
Users with access to the serial console of the device can follow up this update step.
noteworthy messages when booting with the transitional ECoT version
...
Enabling "verity" feature on the filesystem succeeded. <----- (1)
Enabling fsverity on the ostree repository - this may take a few minutes.
Progress: [=======================================] (13233/13233) <----- (2)
Enabling fsverity took 143 seconds.
...
composefs: No image present <----- (3)- (1) Message indicating that the fs-verity has been successfully enabled at the filesystem level.
- (2) Progress bar showing the status of the fs-verity enablement on the individual OSTree repository files.
- (3) Message indicating that the composefs image is not yet present. This is the normal situation during the transition – the system will still boot because the protection is not being enforced.
-
-
Perform an OS update to the standard
torizon-signedimage.-
When booting with this OS version, the root filesystem protection will be enforced by the code in the initial ramdisk along with the already present protections for the bootloader and the kernel. In other words, we finally have the Extend Chain of Trust in place.
-
Users with access to the serial console of the device can follow up this update step.
noteworthy messages when booting with the standard ECoT version
...
composefs+ostree: Validated commit signature using '/etc/ostree/initramfs-root-binding.key'
composefs: Verifying digest: 7c3cf70463ef17a3c34ec2190647df14e5546fef15253792e8eca4a297365f03
composefs: mounted successfully <----- (1)
...- (1) The most important message shows that the composefs image was mounted successfully.
-
Upgrading from Non-Secure Boot to ECoT
This section outlines a procedure for upgrading devices from Non-Secure Boot to ECoT more directly (without passing through BCoT). Users aiming ECoT may prefer this procedure instead of going through BCoT because not only it takes less steps but it also can be considered more secure. The gain in terms of security comes from the fact that a valid BCoT version of the system would never exist in the field preventing attackers with access to a BCoT system from rolling an ECoT system back to BCoT, thereby withdrawing the root filesystem protection from the system.
Before proceeding, make sure to review the section on Upgrading from BCoT to ECoT, as all notes regarding the root filesystem protection apply here as well. Also, notice that the steps here are presented concisely since the details are already available from previous sections.
Create the necessary packages
-
Build a transitional
torizon-signedimage. -
Push the OS part of the transitional image to the platform.
-
Switch to a new set of kernel and root filesystem signing keys.
The idea is to rotate those signing keys such that the kernel from the transitional image is not bootable with the bootloader from the standard image that we'll build on the following step, which is achieved by the rotation of the kernel signing keys. Switching the root filesystem signing keys prevents the kernel from the transitional image from booting the root filesystem of the new image, which is not strictly needed but helps against attempts of mix-and-match attacks.
-
Build a standard (non-transitional)
torizon-signedimage. -
Push the OS part of the standard image to the platform.
-
Push the corresponding bootloader to the platform.
-
Create and push a corresponding fuse package to the platform.
Upgrade devices in the field
At this point, you should have at hand the transitional OS package plus the three standard/non-transitional packages (OS, bootloader and fuse). The upgrade can then be performed by following these steps:
- Perform an OS update to the transitional image.
- Perform an OS update to the standard image.
- Perform a bootloader update.
- Perform a fuse update.
Limitations & Known Issues
- When rotating the kernel signing keys, users are advised to force the rebuild of the bootloader binary because changes in the signing key files are known to not be detected by Bitbake at the moment. This can be done by running:
before rebuilding the image with the new keys.
$ bitbake virtual/bootloader -c cleansstate