3.3.2. Secure Boot

3.3.2.1. Authenticated Boot

Each device contains customer programmable keys used to authenticate, and optionally decrypt, code/data to be used on the device. A job for the Public Boot ROM of both General Purpose (GP) and High Security (HS) devices is to load the next stage of the boot process into memory. On High Security devices, Public ROM also checks the initial boot image for an attached header containing details about the image, including a signature used to verify the authorship of the image, and optionally encryption information. This header must be attached and the image must pass authentication for Public Boot ROM to continue boot. It is then the responsibility of the authors to maintain a Chain-of-Trust by ensuring each next stage is itself authenticated. One weak link and all lower trust levels could be compromised.

Note

Example: Forgetting to disable u-boot console or environment loading means a non-secured linux can be loaded. The U-Boot console (or command line interface (CLI)) and environment are powerful features that make it great for creating a customized boot process. However, leaving either or them enabled in a production system allows non-secured software to be loaded and the Chain-of-Trust to be broken.

The following is an example list where Chain-of-Trust should be maintained.

  • Remove U-Boot uEnv.txt loading support.

  • Disable environment loading (the default built-in environment must be compiled to be the one you want).

  • Environment must not fallback to other boot modes.

  • Place firewalls in board-config to match the location of loaded artifacts (ATF/OP-TEE).

  • Update debug sections of initial image cert.

  • Enable DM-verity/DM-crypt.

  • Set root password or disable root account.

  • Read the OP-TEE porting guide and turn off developer options

  • Disable kernel debug options

  • Disable/remove userspace debug tools, devmem disable, etc..

We provide methods for U-Boot’s SPL loader to securely verify/decrypt the U-Boot proper, and this U-Boot proper to securely verify/decrypt the Kernel/DTB/initfamfs. This is accomplished by calling into TIFS via TI-SCI (Texas Instruments System controller Interface). This allows us to use the same signing/encrypting tools used to authenticate the first-stage image. For more infomation using TI_SCI methods refer to the TISCI User Guide.

../_images/K3_KF.JPG

Secure boot is like an onion, it has layers. Some layers are trusted more than others. Secure ROM has the highest trust and REE (Run-time Execution Environment) non-trustzone user-space applications have the least. If any higher trust code is to be loaded by a lower trust entity, it must be verified by an even higher trust entity and not allowed to be accessed by the lower trust entity after that point. Some such trust inversions are listed below:

  • R5 U-Boot loading ATF/OP-TEE

  • R5 Public Boot ROM loading TIFS

  • Linux loading Trusted applications(TA)

These are called out in the sequence as shown in the following image and their method of ensuring trust is explained.

3.3.2.2. Secure Boot Flow

../_images/K3_BF.jpg

ROM

On device startup, execution begins with the ROM bootloader (Secure ROM) running on the DSMC/TIFS core. After initial device security setup the Secure ROM starts the Public ROM running on the R5 core. The Public Boot ROM handles loading the first stage image tiboot3.bin from a peripheral as selected by the BOOTMODE pins. This image is placed into on chip SRAM as external memory interfaces such as DDR are not yet enabled. The exact location is device dependent. More details can be found in the device “Technical Reference Manual”.

R5 SPL

R5 SPL loads the second boot stage FIT image tispl.bin from the peripheral as selected by the BOOTMODE pins. From this FIT image, TF-A, OPTEE, A53 SPL, and SPL DTB are extracted and authenticated and/or decrypted by TIFS. If authentication passed, the R5 SPL starts the ARM64 core. TF-A, OPTEE, and A53 SPL will begin execution on the ARM64 core. R5 SPL also configures DDR and the console so the user can see the first prints as seen below:

R5 SPL’s output will be similar to this: Notice the “Authentication passed” lines as TF-A, OPTEE, A53 SPL, and SPL DTB are authenticated.

U-Boot SPL 2021.01-dirty (May 13 2022 - 15:05:11 -0500)
SYSFW ABI: 3.1 (firmware rev 0x0008 '8.4.0-3-gd5cb1+ (Jolly Jellyfis')
SPL initial stack usage: 13392 bytes
Trying to boot from MMC2
Authentication passed
Authentication passed
Authentication passed
Authentication passed
Starting ATF on ARM64 core...

A53 SPL

A53 SPL then loads the U-Boot proper FIT image U-boot.img from the peripheral as selected by the BOOTMODE pins. From this FIT image, the U-boot bootloader and DTB are extracted before passing execution to u-boot proper.

A53 SPL’s output will be similar to this: (notice the “Authentication passed” lines as U-Boot and the DTB are authenticated).

U-Boot SPL 2021.01-g2de57d278b (May 16 2022 - 14:28:40 +0000)
SYSFW ABI: 3.1 (firmware rev 0x0008 '8.4.0-3-gd5cb1+ (Jolly Jellyfis')
Trying to boot from MMC2
Authentication passed
Authentication passed

U-Boot

The boot flow continues as it does on a non-secure device, until loading the next FIT image named fitImage. This FIT image includes the Linux kernel, DTB, and other required boot artifacts. Each component is extracted and authenticated from this FIT image. Once all components are authenticated, U-boot starts Linux.

U-boot’s output will be similar to this: (notice the “Authentication passed” lines as we authenticate the Linux kernel and DTB).

U-Boot 2021.01-g2de57d278b (May 16 2022 - 14:28:40 +0000)

SoC:   AM64X SR1.0
Model: Texas Instruments AM642 EVM
Board: AM64-GPEVM rev A
DRAM:  2 GiB
NAND:  0 MiB
MMC:   mmc@fa10000: 0, mmc@fa00000: 1
Loading Environment from FAT... *** Warning - bad CRC, using default environment

In:    serial@2800000
Out:   serial@2800000
Err:   serial@2800000
Net:   eth0: ethernet@8000000port@1
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc1 is current device
SD/MMC found on device 1
Failed to load 'boot.scr'
1011 bytes read in 2 ms (493.2 KiB/s)
Loaded env from uEnv.txt
Importing environment from mmc1 ...
Running uenvcmd ...
7862647 bytes read in 328 ms (22.9 MiB/s)
## Loading kernel from FIT Image at 90000000 ...
Using 'k3-am642-evm.dtb' configuration
Trying 'kernel@1' kernel subimage
    Description:  Linux kernel
    Type:         Kernel Image
    Compression:  gzip compressed
    Data Start:   0x900000f8
    Data Size:    7743643 Bytes = 7.4 MiB
    Architecture: AArch64
    OS:           Linux
    Load Address: 0x80080000
    Entry Point:  0x80080000
Verifying Hash Integrity ... OK
Authentication passed
## Loading fdt from FIT Image at 90000000 ...
Using 'k3-am642-evm.dtb' configuration
Trying 'k3-am642-evm.dtb' fdt subimage
    Description:  Flattened Device Tree blob
    Type:         Flat Device Tree
    Compression:  uncompressed
    Data Start:   0x90762a54
    Data Size:    56436 Bytes = 55.1 KiB
    Architecture: AArch64
    Load Address: 0x83000000
Verifying Hash Integrity ... OK
Authentication passed
Loading fdt from 0x90762a54 to 0x83000000
Booting using the fdt blob at 0x83000000
Uncompressing Kernel Image
Loading Device Tree to 000000008ffef000, end 000000008ffff602 ... OK

Linux

If initramfs is included, we can trust our initial modules and tasks, but we cannot trust anything beyond this as the root file-system may have been modified. To allow trusted use of files outside of our initramfs we use dm-verity. With this we can authenticate a block device as we read from it. As any changes to this block-device will cause the authentication to fail, we cannot put any user-modifiable configurations or user installed programs here. Only important, read-only, files should be placed on this partition, such as static kernel and operating system files and configurations. All other files must be placed in a non-verifiable read-write user partition.

3.3.2.3. HS Boot Flow Tools

U-boot:

The ti-u-boot source is a project used to create tiboot3.bin, tispl.bin, and u-boot.img. To create tiboot3.bin for AM64x family devices, u-boot builds R5 SPL and binman packages it in a tiboot3.bin image. To build A53 SPL, binman takes ATF (bl31.bin), OPTEE (bl32.bin), A53 SPL, and A53 DTBs and packages them in a tispl.bin image. The openssl library can then then be used to sign each component as specified in k3-am64x-binman.dtsi.

$ git clone https://git.ti.com/git/ti-u-boot/ti-u-boot.git

Example use:
$ make ARCH=arm CROSS_COMPILE=aarch64-none-linux-gnu- am64x_evm_a53_defconfig
$ make CROSS_COMPILE=aarch64-none-linux-gnu- ATF=bl31.bin TEE=tee-pager_v2.bin BINMAN_INDIRS=<path-to-tisdk>/board-support/prebuilt-images

Linux:

The ti-linux source is a TI project used to build Linux kernel, DTB, and other boot artifacts. Some of these components could be included in a verifiable image fitImage. For HS devices, only the fitImage will be allowed to boot once fitImage has been authenticated.

$ git clone https://git.ti.com/git/ti-linux-kernel/ti-linux-kernel.git

Example use:
$ make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- defconfig ti_arm64_prune.config
$ make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- menuconfig
$ make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu-

ATF:

The ATF source (now called TF-A) is used to build bl31.bin that gets packaged into tispl.bin. For HS devices, this binary needs to be signed.

$ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git

Example use:
$ make ARCH=aarch64 CROSS_COMPILE=aarch64-none-linux-gnu- PLAT=k3 TARGET_BOARD=lite SPD=opteed

OPTEE:

The OPTEE source is used to build bl32.bin/tee-pager_v2.bin that gets packaged into tispl.bin. For HS devices, this binary needs to be signed.

$ git clone https://github.com/OP-TEE/optee_os.git

Example use:
$ make CROSS_COMPILE64=aarch64-linux-gnu- PLATFORM=k3-<soc> CFG_ARM64_core=y

Ti-linux-firmware:

The ti-linux-firmware is a TI repository where all firmware releases are stored. Firmwares for a device family can also be found in the pre-built SDK under <path-to-tisdk>/board-support/prebuilt-images/am64xx-evm. Binman expects to find the device firmware with the following appended to u-boot build command: BINMAN_INDIRS=<path-to-tisdk>/board-support/prebuilt-images, and expects to find a ti-sysfw directory in this path.

$ <https://git.ti.com/git/processor-firmware/ti-linux-firmware.git
Branch: ti-linux-firmware.