Understanding Secure Boot for Embedded Devices
Learn How Secure Boot Works with a Simple Example for Embedded Systems
Hey! This is where I share stuff from my product development journey. Subscribe to get it all in your inbox! 😉
⚠️ Also, heads up: Substack said no to code highlighting, so the code here is just fancy little images. But don’t worry—there’s a link at the end where you can grab all the real code like a proper hacker. 💾💅
Secure boot is a critical security feature for embedded devices. It ensures that only authorized firmware runs on a device, protecting against unauthorized modifications or attacks. In this post, I’ll explain how secure boot works using a simple example.
Chain of Trust
Secure boot relies on the chain of trust—a sequence of steps where each step verifies the integrity of the next before executing it.
For example, in a boot sequence A -> B -> C
, secure boot ensures that A
verifies B
, and B
verifies C
. If any step fails, the boot process is halted to prevent running untrusted code.
🤔 Questions you may have
Why should the firware be verified every time the device boots? Because the firmware can be tampered with or replaced, compromising the device’s security.
Why multiple steps? Each stage has different privileges and responsibilities. Also you may update, for example, an application without modifying the OS or bootloader.
Quick Security Concepts
To understand secure boot, you need to be familiar with a few key concepts:
Public/Private Key: A cryptographic key pair where the private key is secret, and the public key is shared.
Encryption/Decryption: Data encoded with a public key can only be decrypted by the corresponding private key (and vice versa).
Hash: A function that generates a unique fixed-size output for an input. Even a small change in input drastically alters the hash.
Digital Signature: A hash encrypted with a private key.
Signing/Verification: The process of signing data with a private key and verifying it with a public key.
Secure Boot Components
Secure boot involves the following components:
Public/Private Key Pairs: Used to sign and verify firmware.
Digital Signatures of Firmware: Signed binary files to verify authenticity.
Firmware Files: The bootloader, OS Kernel, and Application code to be verified.
Secure Boot Process
Secure boot typically involves these stages:
Boot ROM (in hardware): Loads the first-stage bootloader and initialize hardware components required in the next stage.
First-Stage Bootloader (FSBL): A simple, immutable, secure bootloader that verifies and loads the second-stage bootloader.
Second-Stage Bootloader: A more complex bootloader responsible for loading the OS and handling updates.
OS Kernel: The core of the operating system.
Application: The final software running on the device.
🤔 Questions you may have
Why multiple bootloaders?
The second-stage bootloader is complex (handling tasks like OS loading and OTA updates) and may have vulnerabilities. The first-stage bootloader is kept simple, secure, and immutable, ensuring a reliable anchor in the chain of trust. In practice, you can update also the first-stage bootloader but it’s not desireable to do so.
I usually got only with “signed” file instead of a digital signature plus binary file. Why?
It’s common to embed the signature in the binary file for simplicity like in the case of U-Boot. However, in this example, I’ll keep them separate for clarity.
Why don’t I see an encrypted firmware file during Secure boot?
Firmware is encrypted while it’s being sent (like during an OTA update over a secure MQTT connection) and while it’s stored (like when you encrypt your hard drive). Also the encryption keys used for these are different from the ones used for secure boot. That’s because secure boot isn’t about keeping the firmware secret—it’s about making sure it hasn’t been tampered with and comes from a trusted source.
Example: Secure Boot Concept
For simplicity, let’s consider a setup with only an FSBL and an Application.
Step 1: Generate Keys
We generate two key pairs—one for the FSBL and one for the Application, and a bad key.
# FSBL key
openssl ecparam -genkey -name prime256v1 -noout -out root_private.pem
openssl ec -in root_private.pem -pubout -out root_public.pem
# Application key
openssl ecparam -genkey -name prime256v1 -noout -out second_private.pem
openssl ec -in second_private.pem -pubout -out second_public.pem
## Bad key
openssl ecparam -genkey -name prime256v1 -noout -out bad_private.pem
Step 2: Store FSBL Public Key Hash
openssl dgst -sha256 -binary root_public.pem | openssl base64 > OTP.txt
Step 3: Sign Bootloader
echo "bootloader code" > bootloader.txt
# Using FSBL key
openssl dgst -sha256 -sign root_private.pem -out bootloader.sig bootloader.txt
# Using bad key
openssl dgst -sha256 -sign bad_private.pem -out bootloader_bad.sig bootloader.txt
Step 4: Sign Application
echo "application code" > application.txt
# Using Application key
openssl dgst -sha256 -sign second_private.pem -out application.sig application.txt
# Using bad key
openssl dgst -sha256 -sign bad_private.pem -out application_bad.sig application.txt
I created a script (setup.sh
) to automate these steps:
Simulating Secure Boot Verification
The following script (secure_boot.sh
) checks each step before executing it:
Running the Simulation
Run the setup and secure boot scripts:
bash setup.sh
bash secure_boot.sh
Expected output:
Testing Failure Cases
If you modify root_public.pem
, the root public key verification fails:
FAILED on root public key verification
If you modify bootloader.txt
with unauthorized content or signed with a bad key, the bootloader verification fails:
FAILED on bootloader signature verification
If you signed the application.txt
with a wrong key, the application verification fails:
FAILED on application signature verification
Conclusion
Secure boot ensures that only trusted firmware runs on a device. This post covered the chain of trust, key security concepts, and a working example of a simple secure boot implementation.
Understanding and implementing secure boot is critical for securing embedded devices against tampering and unauthorized code execution. Hopefully, this post made the concept clearer and easier to grasp.
References
If you’re finding this newsletter valuable, share it with a friend, and consider subscribing if you haven’t already.
Cheers, and here's the link to the code.
Daniel! 😉