This tutorial describe the information and usage about i.MX Secure Architecture.
Verify the loaded software to ensure that it is authorized during runtime is usually termed as Verified or Secure or Trusted system mechanism.
i.MX Trust Architecture - Overview¶
Below are the threats that are identified and processed with trusted architecture.
- Rootkits, trojans, viruses, worms, keyloggers, bots
- Risk enhanced by rich & open OS
- Countermeasures: trusted execution, high assurance boot
- Reverse engineering, brute force
- Countermeasures: secure storage, secure debug, encryption
- Bus snooping, glitching,
- Countermeasures: secure storage, tamper detection
i.MX Trust Architecture - Features¶
TrustZone Secure & Normal Worlds (processor modes)
Isolates execution of critical SW from possible malware
Hardware firewalls between CPU & DMA masters and memory & peripherals
High Assurance Boot:
Authenticate/Signed boot: prevent unauthorized software execution
Encrypted boot: protects software confidentiality
Signature checks embedded in on-chip boot ROM
Run every time processor reset
i.MX family dependent
Symmetric: AES-128, AES-256, 3DES, ARC4
Message Digest & HMAC: SHA-1, SHA-256, MD-5
Protects data confidentiality and integrity
HW-only keys: no SW access
Off-chip: cryptographic protection including device binding
On-chip: self-clearing Secure RAM (CAAM)
HW Random Number Generation:
Ensures strong keys and protects against protocol replay
On-chip entropy generation
Cryptographically secure deterministic RNG (NIST compliant)
SNVS Secure Clock:
Provides reliable time source
On-chip, separately-powered real-time clock
Protection from SW tampering
Three security levels + complete JTAG disable
Protects against HW debug (JTAG) exploitation for Security circumvention and Reverse engineering
Protects against run-time tampering
Monitoring of various alarm sources
External alarm (e.g. cover seal)
SW integrity checks
SW alarm flags
High Assurance Boot (HAB)¶
Below are the recommend acronyms related to this tutorial.
Boot ROM: Small piece of one-time programmable firmware written in on-chip read-only memory location and the very first unsigned-software which is executed by the processor on power-on or reset.
Secure Boot ROM: Similar to Boot ROM, but capable of running signed-software using secure libraries.
HAB Library: Secure software library executed in i.MX Boot ROM, using Signing and Encryption processes.
Signed Software/Image: Software Image further padded or processed using Signature that can capable to run only on secure environment.
Signature: Legally binding secure attributes to Signed Image, these attributes can be Private/Public keys, HAB data, Certificate, Secrete keys etc which is understandable by the HAB.
CSF: Command Sequence File, a binary data structure interpreted by the HAB to guide signing and/or decryption process.
CST: Code Signing Tool, like OpenSSL an application running on a build host to generate PKI tree, SRK table along with associated CSF file.
PKI tree: Public Key Infrastructure, a hierarchy of public key certificates in which each certificate (except the root certificate) can be verified using the public key above it.
RSA: Public key cryptography algorithm used for Signing or Authentication process.
SRK: Super Root Key, an RSA key pair which forms the start of the boot time authentication chain. The hash of the SRK public key is embedded in the processor using OTP hardware(e-fuse). The SRK private key is held by the Signature generation for software image.
DEK: Data Encryption Key (DEK), is the key that will be used to actually encrypt the image.
DEK Blob: Encryption of DEK using OTPMK with the help of CAAM HW
OTPMK: AES-256 key burned to fuses by NXP before the IC is shipped. This is unique per chip and only CAAM can access the key.
Secret Key: Generally an outcome key of DEK Blob key used to encrypt and decrypt.
AES: Advanced Encryption Standard used for Encryption process
HAB Secure Boot chain¶
Upon reset i.MX Boot ROM reads the efuse to determine the security configuration of the SoC and the type of the boot device.
The ROM then loads the bootloader image(signed-image) to DDR memory. The image contains both the bootloader itself and signature data and public key certificate data which are collectively called CSF data.
Once the bootloader is loaded, execution is then passed to the HAB library which will verify the signatures of the bootloader stage.
If signature verification fails, execution is not allowed to leave the ROM for securely configured SoCs, also called “closed” devices
If signature verification pass, execution is allowed to leave the ROM for securely configured SoCs, also called “open” devices
- HAB support Signing and Encryption process, where later one change the software-data into unreadable random gibberish using secrete key.
- HABv4 is the version supported by i.MX6
- HAB interfaces with SNVS and CAAM secure boot components.
- CAAM accelerate SHA-256 operation during signature verification and AES-128 operation during decryption boot operation.
- HAB support X.509 Public key certificate, in CMS signature format.
HAB - Signed Boot¶
Signed Boot Flow¶
During Signing, host need to generate PKI tree, Super Root Keys, or SRK, are components of the PKI tree, then the table of public SRK should burn to E-Fuse and finally signed image can be generated using table of public SRK plus private SRKs by defining them in a format of CSF.
During Verification, HAB evaluates the SRK table included in the signature by hashing it and comparing the result to the SRK fuse values.
If the SRK verification is successful, this establishes the root of trust, and the remainder of the signature can be processed to authenticate the image.
Image Signer Flow¶
Signed Boot - Usage¶
Signed Image Format (U-Boot)¶
The below procedure will describe an example on how signed boot has been done with Engicam i.CoreM6 Quad board.
Download cryptographic tool¶
$ tar xvf cst-2.3.2.tar.gz $ cd cst-2.3.2/keys
Generate PKI tree (Private keys)¶
serial - 8-digit OpenSSL uses the contents of this file for the certificate serial numbers.
key_pass.txt - Contains your pass phrase that will protect the HAB code signing private keys.
$ echo "42424242" > serial $ echo "Amarual357" > key_pass.txt $ echo "Amarual357" >> key_pass.txt $ ./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
Private keys will generate on keys directory and corresponding Certificates are placed in the crts directory.
Generate SRK table (Public keys)¶
$ cd ../crts $ ../linux64/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 \ > -f 1
SRK_1_2_3_4_table.bin - SRK table contents with HAB data SRK_1_2_3_4_fuse.bin - contains SHA256 result to be burned to fuse
Build Secure-enabled U-Boot¶
u-boot> git clone https://github.com/openedev/u-boot-amarula.git -b hab u-boot> make imx6q_icore_mmc_defconfigu-boot> make u-boot> cat u-boot-dtb.imx.log Image Type: Freescale IMX Boot Image Image Ver: 2 (i.MX53/6/7 compatible) Mode: DCD Data Size: 536576 Bytes = 524.00 KiB = 0.51 MiB Load Address: 177ff420 Entry Point: 17800000 HAB Blocks: 177ff400 00000000 00082c00 DCD Blocks: 00910000 0000002c 00000328
Generate Signature for U-Boot Image¶
$ cd ~/cst-2.3.2/linux64 $ cat U-Boot.CST [Header] Version = 4.1 Security Configuration = Open Hash Algorithm = sha256 Engine Configuration = 0 Certificate Format = X509 Signature Format = CMS Engine = CAAM [Install SRK] File = "../crts/SRK_1_2_3_4_table.bin" Source index = 0 [Install CSFK] File = "../crts/CSF1_1_sha256_4096_65537_v3_usr_crt.pem" [Authenticate CSF] [Install Key] # Key slot index used to authenticate the key to be installed Verification index = 0 # Key to install Target index = 2 File = "../crts/IMG1_1_sha256_4096_65537_v3_usr_crt.pem" [Authenticate Data] Verification index = 2 Blocks = 0x177ff400 0x0 0x82c00 "u-boot-dtb.imx" $ cp u-boot/u-boot-dtb.imx . $ ./cst --o U-Boot_CSF.bin --i U-Boot.CSF CSF Processed successfully and signed data available in U-Boot_CSF.bin
Create Signed U-Boot¶
$ objcopy -I binary -O binary --pad-to 0x2000 --gap-fill=0x00 U-Boot_CSF.bin U-Boot_CSF_pad.bin $ cat u-boot-dtb.imx U-Boot_CSF_pad.bin > u-boot-dtb-signed.imx $ dd if=u-boot-dtb-signed.imx of=/dev/sda bs=1K seek=1 && sync
<< Put SD card and power-on the board >>
Burn e-fuse with SRK¶
efuse dump $ cd ../crts $ hexdump -e '/4 "0x"' -e '/4 "%X""\n"' < SRK_1_2_3_4_fuse.bin 0x67C7506F 0x7D51EFD0 0x9E450811 0x74ED8483 0xB774A2A 0xD33FF045 0x3343F187 0xC86DDA92
Burn on efuse U-Boot 2017.05-rc2-00058-g7d6c4ef (Apr 25 2017 - 11:30:36 +0530) CPU: Freescale i.MX6Q rev1.2 at 792MHz CPU: Industrial temperature grade (-40C to 105C) at 53C Reset cause: POR Model: Engicam i.CoreM6 Quad/Dual Starter Kit DRAM: 2 GiB MMC: FSL_SDHC: 0 *** Warning - bad CRC, using default environment No panel detected: default to Amp-WD Display: Amp-WD (800x480) In: serial Out: serial Err: serial switch to partitions #0, OK mmc0 is current device Net: Error: ethernet@02188000 address not set. No ethernet found. Hit any key to stop autoboot: 0 icorem6qdl> fuse prog -y 3 0 0x67C7506F Programming bank 3 word 0x00000000 to 0x67c7506f... icorem6qdl> fuse prog -y 3 1 0x7D51EFD0 Programming bank 3 word 0x00000001 to 0x7d51efd0... icorem6qdl> fuse prog -y 3 2 0x9E450811 Programming bank 3 word 0x00000002 to 0x9e450811... icorem6qdl> fuse prog -y 3 3 0x74ED8483 Programming bank 3 word 0x00000003 to 0x74ed8483... icorem6qdl> fuse prog -y 3 4 0xB774A2A Programming bank 3 word 0x00000004 to 0x0b774a2a... icorem6qdl> fuse prog -y 3 5 0xD33FF045 Programming bank 3 word 0x00000005 to 0xd33ff045... icorem6qdl> fuse prog -y 3 6 0x3343F187 Programming bank 3 word 0x00000006 to 0x3343f187... icorem6qdl> fuse prog -y 3 7 0xC86DDA92 Programming bank 3 word 0x00000007 to 0xc86dda92...
Check HAB isn’t finding ERRORS?¶
icorem6qdl> hab_status Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found!
HAB authentication works fine, and the hab_status show ‘No HAB Events Found!’ So the device is open now try to close for enabling Secure boot
Enable Secure boot¶
Be careful with this step and if you’re sure with all steps above and hab_status should show ‘No HAB Events Found!’ Once this setup executed, chip will only boot an image signed with the keys that match the SRK blown fuses.
icorem6qdl> fuse prog 0 6 0x2 Programming bank 0 word 0x00000006 to 0x00000002... Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y icorem6qdl> reset resetting ... U-Boot 2017.05-rc2-00058-g5c41464-dirty (Apr 25 2017 - 13:11:59 +0530) CPU: Freescale i.MX6Q rev1.2 at 792MHz CPU: Industrial temperature grade (-40C to 105C) at 49C Reset cause: WDOG Model: Engicam i.CoreM6 Quad/Dual Starter Kit DRAM: 2 GiB MMC: FSL_SDHC: 0 *** Warning - bad CRC, using default environment No panel detected: default to Amp-WD Display: Amp-WD (800x480) In: serial Out: serial Err: serial switch to partitions #0, OK mmc0 is current device Net: Error: ethernet@02188000 address not set. No ethernet found. Hit any key to stop autoboot: 0 icorem6qdl> hab_ hab_auth_img hab_status icorem6qdl> hab_status Secure boot enabled HAB Configuration: 0xcc, HAB State: 0x99 No HAB Events Found!
HAB - Encrypted boot¶
Encrypted Boot Flow¶
During Encryption, host need to follow similar steps as Signing process for ‘Header’ of Software Data. then the table of public SRK should burn to E-Fuse and finally payload cab be encrypted using table of public SRK, private SRKs, and DEK_blob(secret key) by defining them in a format of CSF.
DEK(dek.bin) is generated by cst_encrypt during encryption process but
The problem then is how do we protect the DEK since it is required on the IC to decrypt the image at boot time? The solution is to create a DEK blob.
How to generate DEK_blob? Target will encrypt the DEK using OTPMK from CAAM.
During Decryption, First HAB evaluates the SRK table included in the signature by hashing it and comparing the result to the SRK fuse values like Verification process and HAB evaluates secrete key by decrypt the DEK_blob using OTPMK and encrypted payload is further decrypt using secrete key ie generated before.
Image Encrypt Flow¶
Encrypted boot - Usage¶
Encrypted Image Format (U-Boot)¶
The below procedure will describe an example on how encrypted boot has been done with Engicam i.CoreM6 Quad board.
See the same steps in Signed Boot - Usage PKI tree, SRK table and E-fuse burn.
Generate Signature for U-Boot Image¶
CST from NXP doesn’t allow to use encryption, so you need to build a new binary
$ cd ~/cst-2.3.2/code/back_end/src $ gcc -o cst_encrypt -I ../hdr -L ../../../linux64/lib *.c -lfrontend -lcrypto $ cp cst_encrypt ../../../linux64/
$ cd ~/cst-2.3.2/linux64 $ cat U-Boot.CST [Header] Version = 4.1 Hash Algorithm = SHA256 Engine Configuration = 0 Certificate Format = X509 Signature Format = CMS Engine = CAAM [Install SRK] File = "../../crts/SRK_1_2_3_4_table.bin" Source index = 0 [Install CSFK] File = "../../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" [Authenticate CSF] [Unlock] Engine = CAAM Features = RNG [Install Key] # Key slot index used to authenticate the key to be installed Verification index = 0 # Key to install Target index = 2 File = "../../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" [Authenticate Data] Verification index = 2 Blocks = 0x177ff400 0x0 0xC00 "u-boot-dtb.imx" #Encrypt the boot image and create a DEK [Install Secret Key] Verification Index = 0 Target Index = 0 Key = "dek.bin" Key Length = 128 Blob Address = 0x17883FB8 #Provide DEK blob location to decrypt [Decrypt Data] Verification Index = 0 Mac Bytes = 16 Blocks = 0x17800000 0x00000C00 0x82000 "u-boot-dtb.imx" $ cp u-boot/u-boot-dtb.imx . $ ./cst_encrypt --o U-Boot_CSF.bin --i U-Boot.CSF CSF Processed successfully and signed data available in U-Boot_CSF.bin
Once dek.bin generated by cst_encrypt need to protect the dek.bin by creating DEK_blob.bin at target
icorem6qdl> fatload mmc 0:1 0x10800000 dek.bin reading dek.bin 16 bytes read in 11 ms (1000 Bytes/s) icorem6qdl> dek_blob 0x10800000 0x10801000 128 SEC0: RNG instantiated Encapsulating provided DEK to form blob DEK Blob 8100484166551000307CB52A999D6D9191D4D7C479DE7DF60A13C0EA7D9ACF92D9491CEA82B91C6F194EC134D9B63005 36F20FFD063C8700F4513BE57F7C7BE43E038C1133138757 icorem6qdl> fatwrite mmc 0 0x10801000 DEK_blob.bin 0x48 writing DEK_blob.bin 72 bytes written
Create Encrypted U-Boot¶
$ objcopy -I binary -O binary --pad-to=0x1FB8 --gap-fill=0x00 U-Boot_CSF.bin U-Boot_CSF_pad.bin $ cat cat u-boot-dtb.imx U-Boot_CSF_pad.bin DEK_blob.bin > u-boot-dtb-encrypte.imx $ dd if=u-boot-dtb-encrypted.imx of=/dev/sda bs=1K seek=1 && sync
HAB - Signed uImage¶
Now that your bootloader image is properly authenticated/encrypted and that your device is secured, you can sign your kernel image so U-Boot ensures to load a known version.
Here are the details of Signing uImage from linux-next.
Signed uImage Format¶
See uImage format, which built from linux-next tree
$ mkimage -l uImage Image Name: Linux-4.11.0-next-20170510 Created: Wed May 10 21:27:58 2017 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 6940664 Bytes = 6777.99 kB = 6.62 MB Load Address: 10008000
See the same uImage is fitting on memory after proper signed, just numerical understanding nevertheless same procedure as with “HAB - Signed Boot”
Signed uImage Creation¶
Use the same PKI tree and SRK keys that been tested with U-Boot and proceed with “Image Signer Flow” of U-Boot except the numerical difference, nevertheless the same procedure.
Since Linux follows 4K pagesize format for Image process, So pad the built uImage to nearest 4K padding. here the actual uImage size is 0x69E838 after nearest 4K padding it becomes 0x69F000.
$ objcopy -I binary -O binary --pad-to=0x69F000 --gap-fill=0x00 uImage uImage-pad.bin
By default imx header attach the IVT for U-Boot (u-boot-dtb.imx), but Linux we need to explicitly attach the IVT based on the perl script as below.
Size of the IVT is 0x20 bytes
Self pointer size is the uImage size once padded to 4K
CSF pointer size is Self pointer + 0x20
$ cat genIVT #! /usr/bin/perl -w use strict; open(my $out, '>:raw', 'ivt.bin') or die "Unable to open: $!"; print $out pack("V", 0x412000D1); # IVT Header print $out pack("V", 0x10801000); # Jump Location print $out pack("V", 0x0); # Reserved print $out pack("V", 0x0); # DCD pointer print $out pack("V", 0x0); # Boot Data print $out pack("V", 0x10E9F000); # Self Pointer print $out pack("V", 0x10E9F020); # CSF Pointer print $out pack("V", 0x0); # Reserved close($out);
Create IVT uImage¶
Build the genIVT that should create ivt.bin
$ perl genIVT
Attach ivt.bin to padded uImage
$ cat uImage-pad.bin ivt.bin > uImage-pad-ivt.bin
Create CSF uImage¶
Create uImage.CSF file and build the binary.
$ cat uImage.CSF [Header] Version = 4.1 Security Configuration = Open Hash Algorithm = sha256 Engine Configuration = 0 Certificate Format = X509 Signature Format = CMS Engine = CAAM [Install SRK] File = "../../crts/SRK_1_2_3_4_table.bin" Source index = 0 [Install CSFK] 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 # Key to install Target index = 2 File = "../../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" [Authenticate Data] Verification index = 2 Blocks = 0x10800000 0x0 0x69F020 "uImage-pad-ivt.bin" $ ./cst --o uImage_CSF.bin --i uImage.CSF CSF Processed successfully and signed data available in uImage_CSF.bin
Attach uImage_CSF.bin with padded ivt uImage
$ cat uImage-pad-ivt.bin uImage_CSF.bin > uImage-pad-ivt-csf.bin
Create Signed uImage¶
$ objcopy -I binary -O binary --pad-to=0x6A1020 --gap-fill=0x00 uImage-pad-ivt-csf.bin uImage-signed.bin
That’s it, you can now modify your U-Boot bootcmd so it includes the HAB command that checks the kernel,
Signed uImage CHECK??¶
icorem6qdl> fatload mmc 0:1 0x10800000 uImage-signed.bin reading uImage-signed.bin 6950944 bytes read in 351 ms (18.9 MiB/s) icorem6qdl> hab_auth_img 0x10800000 0x69F000 Authenticate image from DDR location 0x10800000... Secure boot enabled HAB Configuration: 0xcc, HAB State: 0x99 No HAB Events Found!