XUELK-WP-001: Secure boot on iMX6UL

From DAVE Developer's Wiki
Jump to: navigation, search
Info Box
SBC Lynx-top.png Applies to SBC Lynx
AXEL ULite-top.png Applies to AXEL ULite

History

Version Date Notes
1.0.0 February 2018 First public release

Introduction

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: [1] See for example Secure Boot on i.MX 6 using HABv4.

[2] See starting from pag.19 the follwoing document i.MX High Assurance Boot - Enablement & Tools

[3] See NXP i.MX6UL: i.MX 6UltraLite Processor.

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".

Code signing participants


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.

Implementation

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)
Is this case the role of the father is to authenticates the children before passing the software control to it.
Chain of trust example

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.sh from NXP it is possible to create the Public Keys
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 srktool from 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 cst tool 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_status and hab_auth_img) autenthicates the boot.scr
    • boot.scr, using HAB's API (hab_status and 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 
...
...

Conclusions

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:

  1. Make the process secure and controlled
  2. Chech and verify the code carefully before deplying
  3. Authenticate all SW pieces
  4. 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