What is secure boot?
Secure boot ensures only authenticated software runs on the device and is achieved by verifying digital signatures of the software prior to executing that code. To achieve secure boot, processor/SoC support is required. In our experience, some of the more secure boot friendly processors with readily available documentation are NXP i.MX, Xilinx Zynq, and Atmel SAMA5 series. Some TI Sitara processors support secure boot, but might involve TI factory programming of signing keys and custom part numbers.
Protecting intellectual property and user data
While secure boot ensures authenticity, it does not protect the device from being counterfeited or prevent hackers from extracting user/application data from the device offline (i.e. reading the non-volatile storage like NAND, eMMC using external hardware mechanisms). If data confidentiality and/or anti-counterfeit functionality is needed, then software/user data needs to be encrypted. The key used for encrypting the data also needs to be protected (typically by encrypting using a unique key on the processor or an external TPM).
Identifying components to protect
A typical Linux based system has the below components:
- Kernel, Device Tree
- Root Filesystem + User applications
- Application data
- Optional: Firmware (FPGA, co-processor)
Let’s explore some of the methods to secure each of the above.
Bootloader authentication is processor specific. However the high level mechanism is usually the same, it involves:
- Creating a public/private key pair
- Signing the bootloader using vendor-specific code signing tools
- Flashing the public key (or hash of public key) onto One-Time programmable (OTP) fuse on the processor
The processor ROM code on power-up loads the bootloader along with the signature/certificate appended to it. It then verifies the software by performing the following steps:
- Verify the public key used in the signature/certificate with the one stored in OTP fuse
- Extract the hash of bootloader from the signature using the verified public key
- Compare the extracted hash with the computed hash of the bootloader. If it matches it proceeds with the boot process, thus authenticating the bootloader.
High-level overview (generic):
In addition to authenticating the bootloader, the bootloader can be also encrypted before signing.
Chain of trust
Extending the trust scheme all the way to user space involves establishing a chain of trust.
i.e. ROM verifies signed bootloader, bootloader verifies signed kernel and kernel verifies/mounts encrypted/signed root filesystem (RFS).
FIT image authentication
FIT stands for Flattened Image Tree and is a single binary that can contain multiple images along with metadata for storing image information along with signatures, thus making it convenient to authenticate. A typical secure boot use case is to generate a FIT image containing kernel, device tree and initramfs. The FIT image is then signed using a private key, and the signature is embedded inside the FIT image. The public key is then embedded inside U-Boot as part of U-Boot device tree. Since the signed U-Boot is authenticated by the ROM, we can trust the public key inside of U-Boot to verify the FIT image.
Verified boot using FIT image is part of mainline U-Boot and FIT image signing is supported by mainline Yocto. Depending on the version of U-Boot/Yocto, certain patches might need to backported.
Instead of using a FIT image, a combined kernel/devicetree/initramfs image can be created, and SoC vendor specific APIs (when available) can be used to verify the combined image (similar to how ROM authenticated bootloader). However, to achieve this, we need good documentation and well-supported bootloader software from the SoC vendor.
Root filesystem and application data protection
If a root filesystem is read only and small enough to run out of RAM, then embedding the root filesystem inside the FIT image should be sufficient for authenticating it. However, typical root filesystems are large, and we need to leverage on the mechanisms provided by the Linux kernel for authenticating and/or encrypting its contents.
Full disk encryption or authentication
Full disk encryption or authentication involves encrypting and/or verifying the contents of the entire disk at a block level. This is performed by the kernel’s device mapper (dm) modules. This method can be used with block devices only (eg: EMMC).
(read/write) or (read-only)
Linux desktop distros, Android
Can be used with dm-integrity/dm-verity for authentication + encryption
Needs 4.13 kernel or higher
For full disk encryption or authentication, we need an initramfs (initial RAM filesystem) which is a minimal filesystem responsible for:
- verifying the signature of the RFS before mounting a signed RFS partition, and
- decrypting and mounting an encrypted RFS partition.
Directory/File level encryption or authentication
An alternate approach is to encrypt and authenticate on a file or directory basis. Below are some mechanisms to achieve the same:
Needs 4.1 kernel or higher
Needs 4.10 kernel or higher
Linux desktop distros
- Potential issues with filesystem corruptions and offline tampering
- Complicated setup
Protecting the key used for encryption
On a desktop or cell phone, the key used to encrypt the filesystem is derived from a user password entered interactively. Embedded devices typically do not have this luxury. Hence we need to store and protect the key on the device. Below are some protection mechanisms:
- Encrypt the key using a SoC mechanism (more details below)
- Store the key in a secure storage device
- Use a TPM
- Remote attestation
Case Study: Key protection on i.MX without using a TPM
Using an NXP i.MX processor as an example, let’s explore a method to protect the key without using a TPM. On i.MX, each processor has a unique master key (pre-programmed by NXP) that can only be accessed by the Cryptographic Accelerator and Assurance Module (CAAM) module. A CAAM kernel driver can be written to encrypt filesystem encryption key with the unique processor master key. The encrypted key blob can then be stored in the boot partition. This is done as a part of the manufacturing step. During the boot process a script is run from initramfs to decrypt the key blob using CAAM kernel driver and the plain key is then used to decrypt the root filesystem.
Since only authenticated software can run on the device, we do not have to worry about malicious firmware being able to decrypt the encrypted key blob. Further, the encrypted key blob is unique to each device (because of unique master key) and thus provides anti-counterfeit feature (i.e. if an attacker cloned the contents of the flash to another device, the counterfeit device would not be able to run the software since it can not decrypt the key blob).
Example of different signing/encryption keys
SPL and/or U-Boot
Public/Private key generated by vendor tool (eg: NXP CST tool)
Public key hash is burnt to processor OTP
OPT fuse bits
Public/Private key generated using OpenSSL
Public key embedded in u-boot
dm-crypt encrypted RFS and/or Application data
LUKS Passphrase (random 256 bit key)
Encrypted key blob in boot partition
Unique processor master
Public/Private key generated using OpenSSl
Public key embedded in initramfs
Signed FIT image
Example partition scheme and its contents
-> Raw partition
-> Unencrypted partition
RFS Image 1 (active)
-> Encrypted LUKS partition (Optional read-only)
RFS Image 2 (inactive, for firmware upgrade)
-> Encrypted LUKS partition (Optional read-only)
User Application Data
-> Encrypted LUKS partition (Read/write)
Firmware upgrade security
In addition to implementing secure boot on the device, it is critical to implement a firmware update mechanism that is secure. Below are some considerations for making the process secure:
- Server authentication (for OTA updates only)
- Use of CA certificates and TLS
- Package/image signing and encryption
- Built-in feature in some package managers and/or firmware update clients
- Use gpg/openssl tools to external sign/encrypt if using custom update process
Once signing and encryption schemes have been tested, the next step is to integrate everything back into the build system and manufacturing setups.
- Build system
- Create recipes for FIT image creation
- Create recipes for signing SPL, U-Boot, FIT image
- Create recipes for generating initramfs
- Manufacturing/factory setup
- Flash OTP keys
- Create encrypted key blobs
- Create encrypted partitions before writing RFS image
- Disable JTAG access, serial console access
Security cannot be introduced as an afterthought; it needs to be baked into the product design. It also has potential impact on device boot times, file system performance, firmware upgrade process, so implementing it early in the process is highly recommended.
Next: Part 2 of “Securing Embedded Linux Devices” Series (coming soon).
Akshay Bhat is a Security Architect at Timesys. Akshay’s experience with embedded systems spans a broad range of industries with a focus on board bring-up, driver development and software security. Akshay received his MS in Electrical Engineering from NYU Polytechnic University.
Timesys has extensive experience with embedded system development and lifecycle management. Timesys has been instrumental in working with global leader semiconductor manufacturers with smart, quick and quality solutions for highly complex systems with accelerated product innovation and multiple product variants.