XUELK-WP-001: Secure boot on iMX6UL
|1.0.0||February 2018||First public release|
Nowdays, thanks to embedded systems diffusion and explosive growth anyone is aware about security. One of the key factors is to grant that on a specific hardware devices should be executed only authorized SW. This is extremely important in devices which can be upgraded Over The Air (OTA).
As we said before, security on Embedded Device is getting important in the embedded world. In particular, one of the most important targets, discussed in this article is the software authentication: it is particularly important to guarantee that the embedded processor executes only authenticated software code which should be originally certified (i.e. u-boot, kernel,..).
In this article, it is described the process applied on DAVE Embedded Systems' devices in order to:
(1) demonstrate the capability of the authentication mechanisms and
(2) give an idea about the effort required for implementing the process on the in-house production.
It is important to highlight that this is not just a SW procedure but also a company arrangement design because of security pass through company procedure and good practice (any alarm system doesn't work properly if you live the keys on the door...).
What described in the following, starts from the HAB Security mechanism provided on iMX6/iMX6UL processor family by NXP. This mechanism permits only that authentic/original software is executed. Then is described how an HAB enabled system, via bootrom proper configuration, guarantees that software loaded from external memory devices, like NOR, NAND flash memories or SD card, will be executed only if has been authenticated.
References:  See for example Secure Boot on i.MX 6 using HABv4.
 See starting from pag.19 the follwoing document i.MX High Assurance Boot - Enablement & Tools
Code Signing theory
The following image shows a generic code signing flow and the different actors involved. As stated above, secure an embedded devices means not only to define a SW update procedure; it requires to define a secure manufacturing procedure where it is important to ensure that security is applied to the information access. In particular an embedded systems is secure if the Super Root Keys are well protected and if the code signing keys are protected. Nowdays, very often, in the manufacturing process, some third parties are involved. This means that secure those keys is fundamental as well as define properly formal agreements with those suppliers in order to define well the responsability and calculate the "security risk".
In this image it clear the process foo generate keys and certificates. Now these concepts should be applied to the embedded context. In the following it is described how this can be implemented in a real case scenario.
The following image shows a simplified block diagram of the implemented solution. Basically this image describes how to apply the generic concepts in a real case scenario. In particular it is clear that any piece of SW should be signed and then authenticated before execution in order to grant security. This process is called Secure Boot and it is the essential tool for making possible the chain of authentication in an embedded device. In detail, Secure Boot is the mechanism used for verify (authenticate) the signature of any piece of SW. In the following sections it is described and listed the implementation procedure for make this possible in a DAVE EMbedded Systems' device called SBC Lynx based on NXP i.MX6 UL platform.
The main steps involved on Secure Boot usage are the following:
- create the Public Keys starting from the Super Root Keys. The Public Keys are then used by the bootrom RSA algorithm to authenticate the binaries to be executed.
- properly configures the iMX6UL eFuse for the bootrom to authenticate the signed binaries versus the Public/Private keys
- signing the binaries images to be validated (u-boot, bootscript, dtb and kernel, ramdisk, etc..)
- create a chain of trust avoiding any external possibility to interrupt the authenticatin process flow (i.e. only if a binary is validated it will be executed)
Security process and flow
Going deep in the description, in this section it is described in detail the process with some shots on console log in order to give the precise idea about the entire procedure.
- download Code Signing Tool (CST) NXP for CSF generation and digital signatures: the tool, once installed on a Linux environment, allows to:
- create the PKI tree (Public Key Infrastructure): using the
hab4_pki_tree.shfrom NXP it is possible to create the Public Keys
- create the PKI tree (Public Key Infrastructure): using the
dvdk@vagrant-ubuntu-trusty-64:~/lynx/hab/cst-2.3.3/keys$ ./hab4_pki_tree.sh +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ This script is a part of the Code signing tools for Freescale's High Assurance Boot. It generates a basic PKI tree. The PKI tree consists of one or more Super Root Keys (SRK), with each SRK having two subordinate keys: + a Command Sequence File (CSF) key + Image key. Additional keys can be added to the PKI tree but a separate script is available for this. This this script assumes openssl is installed on your system and is included in your search path. Finally, the private keys generated are password protectedwith the password provided by the file key_pass.txt. The format of the file is the password repeated twice: my_password my_password All private keys in the PKI tree are in PKCS #8 format will be protected by the same password. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Do you want to use an existing CA key (y/n)?: n Do you want to use Elliptic Curve Cryptography (y/n)?: n Enter key length in bits for PKI tree: 3072 Enter PKI tree duration (years): 10 How many Super Root Keys should be generated? 4 Do you want the SRK certificates to have the CA flag set? (y/n)?: y +++++++++++++++++++++++++++++++++++++ + Generating CA key and certificate + +++++++++++++++++++++++++++++++++++++ Generating a 3072 bit RSA private key .........++ ........................................................................................++ writing new private key to 'temp_ca.pem' ----- ++++++++++++++++++++++++++++++++++++++++ + Generating SRK key and certificate 1 + ++++++++++++++++++++++++++++++++++++++++ Generating RSA private key, 3072 bit long modulus ..............................++ ..................................++ ... ... ... ++++++++++++++++++++++++++++++++++++++++ + Generating IMG key and certificate 4 + ++++++++++++++++++++++++++++++++++++++++ Generating RSA private key, 3072 bit long modulus ................................................................................................................................................++ .....................++ e is 65537 (0x10001) Using configuration from ../ca/openssl.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'IMG4_1_sha256_3072_65537_v3_usr' Certificate is to be certified until Jan 9 16:35:07 2028 GMT (3650 days) Write out database with 1 new entries Data Base Updated dvdk@vagrant-ubuntu-trusty-64:~/lynx/hab/cst-2.3.3/keys$
- create the SRK table and SRK fuse table: using the
srktoolfrom NXP is it possible to generate the value to be programmed on eFuse OTP This process should be kept secret as much as possible. The ability to maintain secret the private keys (Super Root Keys) is the crucial factor which security depends. Once the processor is secured there is no way to load unsecured code. This because of the verification values are stored in eFuse OTP(One Time programming) which cannot be modified once programed. This means also that it is fundamental that the bootloader process is properly tested and prepared before deploying on the field the Secure Boot process.
- program the eFuse values using the fuse command on u-boot. Once the eFuses are programmed it is not possible to modify them.
=> fuse prog -y 3 0 0x56D3468C Programming bank 3 word 0x00000000 to 0x56d3468c... => fuse prog -y 3 1 0x2313CE16 Programming bank 3 word 0x00000001 to 0x2313ce16... => fuse prog -y 3 2 0xF374DA2D Programming bank 3 word 0x00000002 to 0xf374da2d... => fuse prog -y 3 3 0xB0843A55 Programming bank 3 word 0x00000003 to 0xb0843a55... => fuse prog -y 3 4 0x74F39B9 Programming bank 3 word 0x00000004 to 0x074f39b9... => fuse prog -y 3 5 0xEF12FBA6 Programming bank 3 word 0x00000005 to 0xef12fba6... => fuse prog -y 3 6 0x2555E044 Programming bank 3 word 0x00000006 to 0x2555e044... => fuse prog -y 3 7 0x242C46B8 Programming bank 3 word 0x00000007 to 0x242c46b8...
- digital signature of binaries to be loaded
- CSF (Command Sequence File)
- u-boot signature using the
csttool from NXP and the CSF configuration file
- bootscript, kernel and dtb digital signature This process should be kept secret as much as possible. The signature of SW is directly linked to the private key generation so kepting this process secured is fundamental. Hacking a systems should happen at any system level. For this reason any SW layer should be signed. Only with this approach it is possbile to ensure a complete Secure Boot. This principle is calles also chain of trust.
- chain of trust. In this section it is possible to see how the chain of trust works. Any piece of SW is authenticated before execution. Who is in charge of this check? The piece of code authenticated before... This means that Secure Boot will check with bootrom the u-boot and then any following piece of SW should be designed integrating the authentication check of the next stage. This is the chain of trust principle.
- the bootrom authenticates u-boot
- u-boot, using HAB's API (
hab_auth_img) autenthicates the boot.scr
- boot.scr, using HAB's API (
hab_auth_img) autenthicates kernel, dtb e ramdisk
Examples of authentication process on u-boot
- u-boot not signed with status open
U-Boot 2016.03-xuelk-2.0.0-hab-00002-g3a4f591 (Jan 11 2018 - 17:18:25 +0100) CPU: Freescale i.MX6UL rev1.2 528 MHz (running at 396 MHz) CPU: Industrial temperature grade (-40C to 105C) at 44C Reset cause: POR Environment: MMC I2C: ready DRAM: 512 MiB Relocating to 9ff20000, new gd at 9ef1deb8, sp at 9ef1de90 PMIC: PFUZE3000 DEV_ID=0x30 REV_ID=0x11 NAND: 2048 MiB MMC: FSL_SDHC: 0 In: serial Out: serial Err: serial switch to partitions #0, OK mmc0 is current device SOM ConfigID#: 00000013 SOM UniqueID#: ea9c2afe:3b0899d4 CB ConfigID#: 0000002f CB UniqueID#: 00000000:00000000 Board: MX6UL SBC Lynx Net: FEC0 Normal Boot Hit any key to stop autoboot: 0 => hab_status Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 --------- HAB Event 1 ----------------- event data: 0xdb 0x00 0x14 0x42 0x33 0x28 0x33 0x00 0x00 0x00 0x00 0x0f 0x87 0x7f 0xbb 0xd4 0x00 0x09 0x00 0x00 STS = HAB_FAILURE (0x33) RSN = HAB_INV_CALL (0x28) CTX = HAB_CTX_TARGET (0x33) ENG = HAB_ENG_ANY (0x00) ... ...
- u-boot signed with valid signature
U-Boot 2016.03-xuelk-2.0.0-hab-00002-g3a4f591 (Jan 11 2018 - 18:30:36 +0100) CPU: Freescale i.MX6UL rev1.2 528 MHz (running at 396 MHz) CPU: Industrial temperature grade (-40C to 105C) at 45C Reset cause: POR Environment: MMC I2C: ready DRAM: 512 MiB Relocating to 9ff20000, new gd at 9ef1deb8, sp at 9ef1de90 PMIC: PFUZE3000 DEV_ID=0x30 REV_ID=0x11 NAND: 2048 MiB MMC: FSL_SDHC: 0 In: serial Out: serial Err: serial switch to partitions #0, OK mmc0 is current device SOM ConfigID#: 00000013 SOM UniqueID#: ea9c2afe:3b0899d4 CB ConfigID#: 0000002f CB UniqueID#: 00000000:00000000 Board: MX6UL SBC Lynx Net: FEC0 Normal Boot Hit any key to stop autoboot: 0 => hab_status Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! =>
- bootscript, kernel and dtb with valid signature
U-Boot 2016.03-xuelk-2.0.0-hab-00002-g3a4f591 (Jan 11 2018 - 18:30:36 +0100) CPU: Freescale i.MX6UL rev1.2 528 MHz (running at 396 MHz) CPU: Industrial temperature grade (-40C to 105C) at 45C Reset cause: POR Environment: MMC I2C: ready DRAM: 512 MiB Relocating to 9ff20000, new gd at 9ef1deb8, sp at 9ef1de90 PMIC: PFUZE3000 DEV_ID=0x30 REV_ID=0x11 NAND: 2048 MiB MMC: FSL_SDHC: 0 In: serial Out: serial Err: serial switch to partitions #0, OK mmc0 is current device SOM ConfigID#: 00000013 SOM UniqueID#: ea9c2afe:3b0899d4 CB ConfigID#: 0000002f CB UniqueID#: 00000000:00000000 Board: MX6UL SBC Lynx Net: FEC0 Normal Boot Hit any key to stop autoboot: 0 reading boot.scr 20512 bytes read in 19 ms (1 MiB/s) Authenticate image from DDR location 0x80700000... Secure boot enabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! bootscript AUTHENTICATED ## Executing script at 80700000 reading xuelk-2.0.1-signed_uImage 7106592 bytes read in 323 ms (21 MiB/s) Authenticate image from DDR location 0x80800000... Secure boot enabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! kernel AUTHENTICATED reading xuelk-2.0.1-signed_imx6ul-lynx-som0013-cb002f.dtb 53280 bytes read in 24 ms (2.1 MiB/s) Authenticate image from DDR location 0x83000000... Secure boot enabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! fdt AUTHENTICATED Authenticate image from DDR location 0x80800000... Secure boot enabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! ## Booting kernel from Legacy Image at 80800000 ... Image Name: Linux-4.1.15-xuelk-2.0.1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 7090064 Bytes = 6.8 MiB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 83000000 Booting using the fdt blob at 0x83000000 Loading Kernel Image ... OK Using Device Tree in place at 83000000, end 8300b21d Modify /soc/aips-bus@02000000/bee@02044000:status disabled ft_system_setup for mx6 Starting kernel ... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.1.15-xuelk-2.0.1 (jenkins@linuxserver2) (gcc version 5.3.0 (GCC) ) #1 SMP PREEMPT Tue Oct 3 16:18:51 CEST 2017 [ 0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=10c53c7d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache [ 0.000000] Machine model: Freescale i.MX6 UltraLite LYNX Board [ 0.000000] cma: Reserved 64 MiB at 0x9c000000 [ 0.000000] Memory policy: Data cache writealloc [ 0.000000] PERCPU: Embedded 12 pages/cpu @9bbb2000 s17420 r8192 d23540 u49152 [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048 [ 0.000000] Kernel command line: root=/dev/mmcblk0p2 rootwait rw ip=192.168.0.99:192.168.0.23::255.255.255.0:xelk:eth0:off panic=1 console=ttymxc0,115200 vmalloc=400M ... ...
The complete authentication process based on Secure Boot was described in this White Paper. There are many details around how to deploy this process in a manufacturing line. DAVE Embedded Systems' has successfully completed several projects with or without external manufacturing suppliers. In any case it is important to keep in mind:
- Make the process secure and controlled
- Chech and verify the code carefully before deplying
- Authenticate all SW pieces
- Evaluate carefully the Security level needed. On top of the authentication process there is also the possibility to have encryption mechanisms but not all application should require other security mechanisms expecially because of the high level of impact in the manufacturing process and in the resources required in the embedded systems