Amid growing attacks on Linux devices, the 2016 Embedded Linux Conference demonstrated a renewed focus on security. One well-attended presentation at ELC Europe covered the topic of verified boot schemes. In this talk, Marc Kleine-Budde of Pengutronix revealed the architecture and strategies of a recently developed verified boot scheme for a single-core, Cortex-A9 NXP i.MX6 running on the RIoTboard SBC.
The stack works on most i.MX SoC models, and its structure and most of its components are transferable to other ARM processors. “It’s easy to do this yourself using a number of open source stacks,” said Kleine-Budde, who is also the Linux kernel project’s CAN driver maintainer.
Verified boot is “a complex Linux stack in userspace” designed to detect if any stage of the boot process has been tampered with, he explained. Considering that embedded devices typically lack the advanced security software and physical safeguards found in the server world, it’s one of the most effective — and cost-effective — security strategies available.
“If you can change the bootloader of an embedded system you can have complete control over it,” said Kleine-Budde, “If an attacker wants to root your system, they first try to put in their own bootloader, usually from an unprotected source like SD, USB, or eMMC. For our customers, we wanted to protect the bootloader, kernel, file system, and even read-write data.”
On these ARM systems, ROM code verifies the bootloader before it launches it. On i.MX SoCs this is done by signing the bootloader with a proprietary tool and a public key. The corresponding certificate is burned into the i.MX itself to verify the bootloader. The ROM code decides where to boot from and then passes off to a bootloader, such as U-boot or in this case barebox, which then loads the kernel device trees and root file system.
For the initial ROM stage, the i.MX SoCs use a proprietary extension ROM code called high assurance boot, or short HAB, which in turn taps standard cryptographic SHA and RSA algorithms. Barebox has another key that verifies the image of the kernel and the InitRAMFS (initial RAM file system).
“In the boot process, the ROM code runs first,” said Kleine-Budde. “In production, you burn the fuses into your SoC, which verify the public key that comes with the bootloader. ROM code verifies that the pubkey is correct, and then the pubkey verifies the signature, which goes over the bootloader itself. A second pubkey is used to verify the kernel stage.”
FIT-Image, ext4, and UBIFS
For user space verification, Pengutronix used a FIT-Image, which consists of kernel, device-tree(s), and InitRAMFS. “This is all included in one image, and can be used in several configurations, so you can use one FIT-Image on a variety of boards,” said Kleine-Budde. “If your bootloader knows which board you have, it can pick the right configuration from the FIT-Image, which can be stored on untrusted media.”
The bootloader checks against the bootloader’s public key to see if the FIT-Image configuration is valid. To do this, it checks the signature, and then analyzes three hashes for kernel, device-tree, and InitRAMFS.
Once verified, the kernel then secures each file in the root file system, which must be able to support extended attributes. “We used the ext4 file system with extended attributes,” said Kleine-Budde. “You can use a flash chip or naked NAND chip with UBI and UBIFS, or you can use block media storage such as eMMC.”
To verify the file system, Pengutronix employed the mainline kernel’s IMA (Integrity Measurement Architecture), which uses a hash for every file, thereby indicating if the file has been modified. The content is hashed, and then stored as an extended attribute, in this case security-ima.
“If attackers gain access to this system, they can modify a file, recalculate the hash and write it to the media,” said Kleine-Budde. “To avoid this, we make use of the kernel’s EVM (Extended Verification Module), and create a signature over the extended attributes. This is done on your development PC during image creation. You take a private key, create the root file system, and sign every file and extended attribute. It contains the hash, so you can be sure the file and the checksum have not been modified. The EVM-signature is then verified by the kernel’s public key.”
Protecting read/write storage with a SHA-HMAC Secret
Pengutronix’s customers also wanted to be able to verify read/write media. “For this, we used EVM with SHA-HMAC, a clever way of hashing things that lets you guarantee integrity and authentication,” said Kleine-Budde. HMACs can be verified faster than RSA, thereby reducing boot time, he added.
“With SHA-HMAC, you need a different ’Shared Secret’ for each system because if an attacker opens one system and modifies it, and HMAC gets used, he could transfer a modified file from one system to another,” said Kleine-Budde. “Once the kernel touches every file, it will recalculate the HMAC-based verification and write it down. The attacker cannot recalculate the HMAC unless he has the EVM’s Secret.”
The Secret is generated on the i.MX SoC. “If you have created a properly signed bootloader, you have access to a unique key, which is unique to every individual SoC,” said Kleine-Budde. “The SoC’s fuses contain certification hashes that correspond to the secret key used to sign the bootloader. You can only burn the fuses once, and there’s even a separate fuse that can disallow the burning of other fuses. You sign the bootloader when you build your BSP.”
The unique key is used to encrypt a shared Secret for the EVM, stored on media. “You can decrypt only on the system you used to encrypt it, and only if you have a properly signed bootloader,” said Kleine-Budde. “You then use InitRAMFS to decrypt the blob and obtain access to its EVM-Secret, which is required if you want to do read/write. This checks to see if EVM, IMA, and contents are all correct.”
About 22 minutes into the video, Kleine-Budde answered about 10 minutes of questions about whether the blob was properly secured. Kleine-Budde stuck to his original answer: “The blob is encrypted with a unique key. You cannot decrypt the blob unless you have a unique key.”
He then explained how he used eCryptfs for file system level encryption. “eCryptfsworks works on both NAND and UBIFS,” he said. “Every file in the encrypted file system corresponds to a file in the unencrypted system. File names and content are encrypted, but the directory layout and permissions are clear text. eCryptfs requires a different shared Secret for each system. You do not need IMA/EVM because integrity is provided by GCM and AES within the i.MX crypto engine.”
Finally, Kleine-Budde demonstrated the verified boot process running Linux 4.0.9 with patches on the i.MX6-based RIoTboard. He also passed on some lessons learned for others attempting to create a similar ARM-based trusted boot stack.
“Keep your packages in two configurations: one secure package with production keys and another that people can play with,” said Kleine-Budde. Similarly, one production bootloader and
Kernel/InitRAMFS configuration should reboot upon discovery of attack while another one simply displays a notification. He also noted that the combination of UBIFS with IMA/EVM is sensitive to sudden power loss. This issue is fixed with the upcoming Linux v4.10 release.
Kleine-Budde acknowledged that verified boot extends your boot time, in this case by about 10 percent. The overhead is worth it, however, when you consider the alternative. “There are a lot of Linux targets on the Internet that are attractive for hacking,” said Kleine-Budde.
You can watch the complete presentation below:
Embedded Linux Conference + OpenIoT Summit North America will be held on February 21 – 23, 2017 in Portland, Oregon. Check out over 130 sessions on the Linux kernel, embedded development & systems, and the latest on the open Internet of Things.
Linux.com readers can register now with the discount code, LINUXRD5, for 5% off the attendee registration price. Register now>>