Embedded Linux Secure Boot

Published

MAB Labs recently worked on a feature for one of our clients called “Secure Boot” on an Nvidia Jetson Nano platform. In this blog post, we will see one mechanism for performing secure boot on a Linux based embedded system. In a later blog post, we will see how this was achieved on an Nvidia based Jetson Nano platform.

“Secure Boot” is a mechanism that ensures every single binary that is loaded during the boot process has been authorized to boot, usually by the product manufacturer. The general secure boot process is outlined in the graphic below:

First, the ROM bootloader executes. Since the ROM bootloader is burned into the processor at the manufacturer, we are guaranteed that it is authorized to run. Thus, we can designate the ROM bootloader as the “Root of Trust”, meaning we can always trust its integrity. The ROM bootloader will be the basis of ensuring that subsequent binaries are authorized to execute.

The ROM bootloader loads the public portion of the signing key. The private portion of this key is secured by the manufacturer and used to sign the binaries that will reside on the target embedded platform. The public portion of the signing key is used to verify that any binaries that will be loaded originate from the manufacturer. The primary Flash bootloader is loaded, verified by the ROM bootloader, and executed.

The primary bootloader repeats the same process as the ROM bootloader, but with u-boot instead. First it loads the u-boot binary from Flash and verifies its signature. If the u-boot image is successfully verified, the primary bootloader loads and executes u-boot. 

Finally, u-boot does the same with the Linux kernel. However, u-boot has a built-in mechanism wherein a specific package of the kernel is generated to make the signing process seamless. This is referred to as “Verified U-boot” (https://lwn.net/Articles/571031/). Essentially, a FIT image is created and signed and instructions are provided to u-boot (via the FIT image) to ensure that it verifies the signature of the kernel image. If the kernel in the FIT image is not signed or signed with the incorrect key, u-boot will fail to load the kernel. A FIT image, or Flattened Image Tree image, contains multiple binaries in a single file along with instructions on which combinations of binaries to load. Briefly, this allows u-boot to use a single binary to load both the device tree and kernel. Additionally, if there are multiple configurations of kernel and device tree combinations, these can be specified in a FIT image and u-boot can be instructed to load the appropriate configuration on boot. Joel Fernandes provides an excellent presentation on the history behind a FIT image (https://elinux.org/images/f/f4/Elc2013_Fernandes.pdf). 

As mentioned, all of the bootloaders use the public portion of the private key pair to verify the signature of the next binary before executing it. Since the public portion of the key is an integral part of the verification process, it must also be secured on the platform. In the case of the Jetson Nano and other Linux-based embedded systems, the key is usually “burned” into the fuses of the system processor, which is a secure location. However, care must be taken when performing this operation since this process is not reversible.

To summarize, we discussed the Secure Boot process for an example Linux-based embedded system. One of the important aspects of this process is to ensure there is a chain of trust in each execution element and any cryptographic element that is used. We demonstrated how the root of trust usually starts with a ROM based bootloader, and each binary in the boot process verifies that the next binary is authorized to boot by validating its signature. Since the public portion of the key is used to perform this verification, it must also be secured. Usually, it is secured by burning it into the fuses of the system processor.

In a following blog post, we will discuss how this feature is implemented on the board support package (BSP) for a Nvidia Jetson Nano.