Introduction
The secure Linux platform, provided by Foundries.io is leveraged by several layers of signed binaries which are verified during boot time. Some layers use proprietary source code (such as the secure boot on some architectures) and other layers are part of well known open source projects (such as U-Boot and Linux Kernel).
This article details how to read the available Linux log and artifacts from a booting machine, in order to detect the verification mechanism executed during a normal boot.
Boot sequence
A common Linux boot sequence starts with the execution of the content of a ROM software/firmware just after the power on. This ROM software/firmware then instructs the processor to jump to another software, the secondary program loader (SPL). Some architectures (i.e. i.MX family) support the verification of the SPL image during this jump which is performed by hardware (RoT).
For those cases, the boot sequence is as shown in the following diagram:
The hardware has the ways to verify the SPL binary, which has the information to verify the file u-boot.itb
.
The file u-boot-itb
has the information to load, execute and verify TF-A, OP-TEE and U-Boot proper.
The U-Boot proper then loads, executes and verifies the Linux Kernel image and any DTB file. The Linux Kernel modules (in tree and external drivers built as modules) are verified by kernel when they are loaded.
It is common that when an image is loaded and verified, a log prints the details for each boot phase.
Following the Linux boot logs
Secure boot
Using the following UUU script, it is possible to check the HAB status of a board and double check if this is using secure boot or not.
uuu_version 1.2.39
SDP: boot -f SPL-mfgtool
SDPV: delay 1000
SDPV: write -f u-boot-mfgtool.itb
SDPV: jump
FB: ucmd hab_status
FB: DONE
The log of the board booting and the result of the command hab_status
from a closed imx6ullevk-sec
.
U-Boot 2020.04+fio+gcbb11e17ea (Aug 12 2021 - 23:27:31 +0000)
CPU: i.MX6ULL rev1.1 900 MHz (running at 396 MHz)
CPU: Commercial temperature grade (0C to 95C) at 48C
Reset cause: POR
Model: i.MX6 ULL 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 480 MiB
WDT: Started with servicing (128s timeout)
MMC: FSL_SDHC: 0, FSL_SDHC: 1
[*]-Video Link 0 (480 x 272)
[0] lcdif@21c8000, video
In: serial
Out: serial
Err: serial
flash target is MMC:1
Fastboot: Normal
Boot from USB for uuu
Secure boot enabled
HAB Configuration: 0xcc, HAB State: 0x99
No HAB Events Found!
No HAB events are found because the booted image is signed with the same keys fused to the board. This board is closed.
SPL loads TF-A, OP-TEE and U-Boot proper
With the instructions from Flash your Device. Paying attention to the boot log for the U-Boot we have:
U-Boot SPL 2020.04+fio+gcbb11e17ea (Aug 12 2021 - 23:27:31 +0000)
Trying to boot from MMC1
SPL: Booting primary boot path: using 0x8a offset for next boot image
sha256,rsa2048:ubootdev+ ## Checking hash(es) for Image optee ... sha256+ OK
## Checking hash(es) for Image uboot ... sha256+ OK
## Checking hash(es) for Image ubootfdt ... sha256+ OK
## Checking hash(es) for Image bootscr ... sha256+ OK
From this log, we note that optee
, uboot
, ubootfdt
and bootscr
are being verified as the log shows sha256+
, the plus sign (+
) is printed when the verification processes succeed.
The key name is ubootdev
, as defined by variable UBOOT_SIGN_KEYNAME
in the conf/local.conf
from the Linux microPlatform (Yocto Project).
Linux Kernel image and DTBs
For the Linux Kernel boot log, we note the DTB files are also using the ubootdev
key, and they are properly verified.
There are several other pieces of information for each image being verified and loaded.
## Copying 'fdt-imx6ull-14x14-evk.dtb' subimage from FIT image at 80800000 ...
sha256,rsa2048:ubootdev+ sha256+ Loading part 253 ... OK
Forcing secondary boot to 0 after reboot
## Loading kernel from FIT Image at 80800000 ...
Using 'conf-imx6ull-14x14-evk.dtb' configuration
Verifying Hash Integrity ... sha256,rsa2048:ubootdev+ OK
Trying 'kernel-1' kernel subimage
Description: Linux kernel
Type: Kernel Image
Compression: uncompressed
Data Start: 0x80800110
Data Size: 7270504 Bytes = 6.9 MiB
Architecture: ARM
OS: Linux
Load Address: 0x80008000
Entry Point: 0x80008000
Hash algo: sha256
Hash value: 56c254a00858b54d2f1278a68df49eb764ac284cd1a46198b1e8664e28dac185
Verifying Hash Integrity ... sha256+ OK
## Loading ramdisk from FIT Image at 80800000 ...
Using 'conf-imx6ull-14x14-evk.dtb' configuration
Verifying Hash Integrity ... sha256,rsa2048:ubootdev+ OK
Trying 'ramdisk-1' ramdisk subimage
Description: initramfs-ostree-lmp-image
Type: RAMDisk Image
Compression: uncompressed
Data Start: 0x80f1b534
Data Size: 2922946 Bytes = 2.8 MiB
Architecture: ARM
OS: Linux
Load Address: 0x84000000
Entry Point: unavailable
Hash algo: sha256
Hash value: 834cf894b30100c4f49ae048e3749f189bff71094c50cd419bb2d7e7b5487ee6
Verifying Hash Integrity ... sha256+ OK
Loading ramdisk from 0x80f1b534 to 0x84000000
## Flattened Device Tree blob at 85800000
Booting using the fdt blob at 0x85800000
Loading Kernel Image
Using Device Tree in place at 85800000, end 8580cfff
Linux Kernel Modules
The key/certificate used to sign and verify the Linux Kernel modules are provided via Linux microPlatform by the Yocto Project variable MODSIGN_KEY_DIR
. We can make sure the running linux has this feature enabled by running the following commands to check the dmesg
log.
fio@imx6ullevk-sec:~$ dmesg | grep -i 'x.*509'
[ 2.927091] Asymmetric key parser 'x509' registered
[ 4.571906] Loading compiled-in X.509 certificates
[ 4.598640] Loaded X.509 cert 'Default insecure key from Factory II: 1b2327c0b75d0bc1e4914c8195bbf053629b8abb'
Linux Boot Log Summary
We explored just one example of a secure Linux boot sequence log in Foundries.io Linux microPlatform FoundriesFactory and where to look to understand if the expected boot log key/cert is being used and how to ensure proper verification using those keys and certificates.
For more information on secure Linux boot logs and keys see our related article below.