CL-SOM-iMX7: U-Boot: Building Secure Images

From Compulab Mediawiki
Jump to: navigation, search

Overview

Executing trusted and authentic code on an applications processor starts with securely booting the device.
The i.MX 7 processors provides this capability with the High Availability Boot (HAB) component of the on-chip ROM. The ROM is responsible for loading the initial program image from the boot medium. HAB enables the ROM to authenticate the U-Boot by using digital signatures.

This article provides a brief set of instructions related to secure boot with CompuLab i.MX7 platforms. For additional details please refer to Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using HABv4.

Building Secure Firmware images for CL-SOM-iMX7

Getting U-Boot sources

The following article assumes that you have created /home/development/cl-som-imx7/u-boot directory for the the CL-SOM-iMX7 U-Boot development. U-Boot sources with CompuLab's patch can be downloaded from CompuLab's U-Boot github.

Git clone

  • Install git version control system.
  • Create a clone of U-Boot tree
cd /home/development/cl-som-imx7/u-boot
git clone https://github.com/compulab/u-boot.git u-boot-cl-som-imx7-hab
cd /home/development/cl-som-imx7/u-boot/u-boot-cl-som-imx7-hab
  • Create a branch for HAB development. It is recommended to use exactly the same baseline to avoid merge conflicts.
git checkout -b cl-som-imx7-hab v2018.11-cl-som-imx7-hab

Building the secure firmware images

  • First, compile U-Boot. The following commands create the binaries u-boot-ivt.img and SPL (along with other image types):
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-eabi-
make mrproper
make cl-som-imx7_defconfig && make

Code Signing Example

Code Signing Tool (CST)

Download CST

Admolition note.png Sign in (registration is required) to your NXP account prior to downloading the CST tool

Extract the CST archive

cd /home/development/cl-som-imx7/u-boot
gunzip -c /path/to/downloaded/cst-3.1.0.tgz | tar xzvf -
mv release cst

Create a PKI Tree

cd /home/development/cl-som-imx7/u-boot/cst/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: 2048
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
A default 'serial' file was created!
A default file 'key_pass.txt' was created with password = test!
...

Generate SRK Table

cd ../crts/
../linux64/bin/srktool -h 4 -t SRK_1_2_3_4_table.bin -e SRK_1_2_3_4_fuse.bin -d sha256 -c SRK1_sha256_2048_65537_v3_ca_crt.pem,SRK2_sha256_2048_65537_v3_ca_crt.pem,SRK3_sha256_2048_65537_v3_ca_crt.pem,SRK4_sha256_2048_65537_v3_ca_crt.pem

CSF Description Template

  • Generate the example command sequence file template.
cd ..
mkdir bin -p
cd bin
cat <<EOF >csf.txt
#Illustrative Command Sequence File Description
[Header]
Version = 4.2
Hash Algorithm = sha256
Engine = ANY
Engine Configuration = 0
Certificate Format = X509
Signature Format = CMS

[Install SRK]
File = "../crts/SRK_1_2_3_4_table.bin"
# Index of the key location in the SRK table to be installed
Source index = 0

[Install CSFK]
# Key used to authenticate the CSF data
File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem"

[Authenticate CSF]

[Install Key]
# Key slot index used to authenticate the key to be installed
Verification index = 0
# Target key slot in HAB key store where key will be installed
Target Index = 2
# Key to install
File= "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem"

[Authenticate Data]
# Key slot index used to authenticate the image data
Verification index = 2
# Address Offset Length Data File Path
Blocks = blk_vals file_name
EOF

Signing U-Boot Firmware

CSF Description

  • Generate the example command sequence files for the U-Boot and SPL.
awk 'BEGIN {file_name="\"/home/development/cl-som-imx7/u-boot/u-boot-cl-som-imx7-hab/SPL\""} /HAB Blocks:/ {blk_vals=$3 " " $4 " " $5} {sub(/blk_vals/, blk_vals); sub(/file_name/, file_name)} printline {print} ENDFILE {printline=1}' ../../u-boot-cl-som-imx7-hab/SPL.log ./csf.txt > ./csf-spl.txt
awk 'BEGIN {file_name="\"/home/development/cl-som-imx7/u-boot/u-boot-cl-som-imx7-hab/u-boot-ivt.img\""} /HAB Blocks:/ {blk_vals=$3 " " $4 " " $5} {sub(/blk_vals/, blk_vals); sub(/file_name/, file_name)} printline {print} ENDFILE {printline=1}' ../../u-boot-cl-som-imx7-hab/u-boot-ivt.img.log ./csf.txt > ./csf-uboot.txt

CSF Binary Signature

  • Generate the CSF binary signature for the U-Boot and SPL.
../linux64/bin/cst --o csf-spl.bin --i csf-spl.txt
../linux64/bin/cst --o csf-uboot.bin --i csf-uboot.txt

Attach CSF Signature

  • Attach CSF Signature to the U-Boot and SPL Images.
cat /home/development/cl-som-imx7/u-boot/u-boot-cl-som-imx7-hab/SPL csf-spl.bin > spl-signed
cat /home/development/cl-som-imx7/u-boot/u-boot-cl-som-imx7-hab/u-boot-ivt.img csf-uboot.bin > u-boot-signed

Generate Firmware Image

  • Merge the SPL and U-Boot images into one firmware image.
dd if=/dev/zero count=640 bs=1K | tr '\000' '\377' >  cl-som-imx7-firmware
dd if=spl-signed of=cl-som-imx7-firmware bs=1K seek=1 conv=notrunc
dd if=u-boot-signed of=cl-som-imx7-firmware bs=1K seek=64 conv=notrunc
mv cl-som-imx7-firmware /tftproot/cl-som-imx7/test/

Signing Kernel Image

Image Parameters

  • Calculate kernel image parameters.

Replace /path/to/zimage/zImage with the actual kernel image path.

zimage_path=/path/to/zimage/zImage
read zimage_pad_size <<< $(ls -l $zimage_path | awk '{size=int(($5+0xfff)/0x1000)*0x1000; print size}')
zimage_self_ptr=$(printf "0x%x\n" $(($zimage_pad_size+0x80800000)))
zimage_csf_ptr=$(printf "0x%x\n" $(($zimage_self_ptr+0x20)))
zImage_pad_ivt_size=$(printf "0x%x\n" $(($zimage_pad_size+0x20)))

Image Vector Table

  • Generate the image vector table.
cat <<EOF >genIVT
#! /usr/bin/perl -w
use strict;
open(my \$out, '>:raw', 'ivt.bin') or die "Unable to open: \$!";
print \$out pack("V", 0x412000D1); # Signature
print \$out pack("V", 0x80800000); # Load Address
print \$out pack("V", 0x0); # Reserved
print \$out pack("V", 0x0); # DCD pointer
print \$out pack("V", 0x0); # Boot Data
print \$out pack("V", $zimage_self_ptr); # Self Pointer *ivt
print \$out pack("V", $zimage_csf_ptr); # CSF Pointer *csf
print \$out pack("V", 0x0); # Reserved
close(\$out);
EOF
chmod +x genIVT
./genIVT

Image Padding

objcopy -I binary -O binary --pad-to $zimage_pad_size --gap-fill=0x00 $zimage_path zImage_pad

Adding IVT

  • Append the image vector table at the end of the padded kernel image.
cat zImage_pad ivt.bin > zImage_pad_ivt

CSF Description

  • Generate the example command sequence files for the kernel image.
awk -v blk_vals="0x80800000 0x000 $zImage_pad_ivt_size" ' {sub(/blk_vals/, blk_vals); sub(/file_name/, "\"zImage_pad_ivt\""); print}' ./csf.txt > ./csf-zimage.txt

CSF Binary Signature

  • Generate the CSF binary signature for the kernel image.

../linux64/bin/cst --o csf-zImage --i csf-zimage.txt

Attach CSF Signature

  • Attach CSF Signature to the kernel image.

cat zImage_pad_ivt csf-zImage > zImage_signed

Test the Images

U-Boot Firmware

Update the U-Boot Firmware

  • Follow the Firmware Update instructions to update the firmware with the new image.
  • Reset the CL-SOM-iMX7 evaluation platform.

Fuse Programming

  • Display the new fuse values for programming.
hexdump -e '/4 "0x"' -e '/4 "%X""\n"' /home/development/cl-som-imx7/u-boot/cts/crts/SRK_1_2_3_4_fuse.bin
0x5AD817FB
0xD4C8E0B3
0xA7C3870C
0x6BCDDBAD
0x2B784081
0x2B57810
0xC5F3200B
0x6A182382
Admolition important.png Verify the values. The fuses can only be programmed once.
  • Program the fuse values from the hexdump command.
fuse prog 6 0 0x5AD817FB
fuse prog 6 1 0xD4C8E0B3
fuse prog 6 2 0xA7C3870C
fuse prog 6 3 0x6BCDDBAD
fuse prog 7 0 0x2B784081
fuse prog 7 1 0x2B57810
fuse prog 7 2 0xC5F3200B
fuse prog 7 3 0x6A182382
  • Reset the CL-SOM-iMX7 evaluation platform.
  • Verify the U-Boot firmware signature
CL-SOM-iMX7 # hab_status 

Secure boot disabled

HAB Configuration: 0xf0, HAB State: 0x66
No HAB Events Found!

Kernel Image

Load Image

  • Obtain an SD card. Any commercially available micro SD card of 1GB (or larger) may be used.
  • Create a first partition on it. The partition can be formatted either ext2/3/4 or FAT file system.
  • Copy the kernel image zImage to the root directory on the first partition of the SD card.
  • Plug the SD card into the SD socket (P9) on the SBC-iMX7.
  • Use the following U-Boot commands to load the kernel image to the RAM:
CL-SOM-iMX7 # mmc rescan
CL-SOM-iMX7 # load mmc 1:1 ${loadaddr} zImage

Test the Image

  • Verify the kernel image signature
CL-SOM-iMX7 # setexpr.l zimage_pad_size ${filesize} / 1000
CL-SOM-iMX7 # setexpr.l zimage_pad_size $zimage_pad_size * 1000
CL-SOM-iMX7 # hab_auth_img ${loadaddr} $filesize} ${zimage_pad_size}

Authenticate image from DDR location 0x80800000...

Secure boot enabled

HAB Configuration: 0xcc, HAB State: 0x99
No HAB Events Found!

Close the Device

After the device successfully boots a signed image without generating any HAB events, it is safe to secure, or close, the device.

Admolition important.png Closing the device is irreversible. The fuses can only be programmed once.
CL-SOM-iMX7 # fuse prog 1 3 0x2000000

See also