This documents shows how to secure and encrypt boot loader image for i.MX6 processor. Secure boot is necessary to be sure that CPU is allowed to run genuine and authentic images. Encrypted image secures your intellectual property from theft. Both methods secure/encryption can be extended to cover whole software on board.
Boot loader image encryption is easy to do with CST tools and HAB feature build in Freescale processor. Encrypted image preparation is consist of three parts:
In this document as reference board we used SABRESD iMX6q. But it's easily to adjust it for any other board based on i.MX6 CPU with HAB4.1 feature.
Encrypted u-boot image consist of: IVT, DCD, u-boot.bin, CSF, dek_blob.bin. In our example finished u-boot_encrypted.imx image looks like:
Address in file | Data |
---|---|
0x000000 | IVT |
0x000020 | DCD + pad to address 0xC00 |
0x000C00 | u-boot.bin + pad to address* 0x7BC000 |
0x07DBB8 | CSF bin data + pad to address** 0x07DBB8 + Wrapped DEK (dek_blob.bin)** |
* (IVT + DCD + u-boot.bin) has to be padded to align 0x1000.
** (CSF bin data + padding + dek_blob.bin) has to have size 0x2000
Step-by-step instruction:
$ mkdir ~/imx6encryption
$ cd ~/imx6encryption
$ git clone git://git.denx.de/u-boot.git
$ cd u-boot
$ git checkout v2016.03 -b tmp
$ nano arch/arm/imx-common/timer.c
Press Ctrl+X and Y and Enter to save changes.unsigned long usec2ticks(unsigned long usec)
{
ulong ticks;
if (usec < 1000)
ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
else
ticks = ((usec / 10) * (get_tbclk() / 100000));
return ticks;
}
$ nano board/freescale/mx6sabresd/mx6q_4x_mt41j128.cfg
Press Ctrl+X and Y and Enter to save changes.
Add defines in file mx6sabresd.h before string #define CONFIG_MACH_TYPE 3980.
$ nano include/configs/mx6sabresd.h
#define CONFIG_SECURE_BOOT
#define CONFIG_SYS_FSL_SEC_COMPAT 4 /* HAB version */
#define CONFIG_FSL_CAAM
#define CONFIG_CMD_DEKBLOB
#define CONFIG_SYS_FSL_SEC_LE
#define CONFIG_FAT_WRITE
Press Ctrl+X and Y and Enter to save changes.
in Makefile.gpimage.0 \
gpimage-common.o \
omapimage.o \
$ nano tools/Makefile
Press Ctrl+X and Y and Enter to save changes
$ cd ~/imx6encryption
$ wget -c https://releases.linaro.org/components/toolchain/binaries/5.3-2016.02/arm-linux-gnueabihf/gcc-linaro...
$ tar xf gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf.tar.xz
$ export CC=`pwd`/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
$ ${CC}gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC 5.3-2016.02) 5.3.1 20160113
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cd u-boot
$ make ARCH=arm CROSS_COMPILE=${CC} distclean
$ make ARCH=arm CROSS_COMPILE=${CC} mx6qsabresd_defconfig
$ make ARCH=arm CROSS_COMPILE=${CC}
$ ./tools/mkimage -T imximage -n board/freescale/mx6sabresd/mx6q_4x_mt41j128.cfg.cfgtmp -e 0x17800000 -d u-boot.bin u-boot.imx
Image Type: Freescale IMX Boot Image
Image Ver: 2 (i.MX53/6/7 compatible)
Data Size: 516096 Bytes = 504.00 kB = 0.49 MB
Load Address: 177ff420
Entry Point: 17800000
HAB Blocks: 177ff400 00000000 0007bc00
$ cd ~/imx6encryption
$ tar xf cst-2.3.1.tar.gz
$ cd cst-2.3.1
$ chmod u+x linux64/* keys/*
$ sudo apt-get install libssl-dev
$ cd ~/imx6encryption/cst-2.3.1/code/back_end/src
$ gcc -o cst -I ../hdr -L ../../../linux64/lib *.c -lfrontend -lcrypto
$ mv cst ../../../linux64
$ cd ~/imx6encryption/cst-2.3.1/keys
Enter 8 random digits, for example:$ nano serial
Press Ctrl+X and Y and Enter to save changes.12345678
Enter two lines of identical text:$ nano key_pass.txt
HelloWorld
HelloWorld
Press Ctrl+X and Y and Enter to save changes.
Execute hab4_pki_tree.sh.
$ ./hab4_pki_tree.sh
Do you want to use an existing CA key (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
$ cd ~/imx6encryption/cst-2.3.1/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
CST utility requires CSF script. This file describes certificates, keys and the data ranges used in sign and encryption functions. Create u-boot.csf file.
$ cd ~/imx6encryption/cst-2.3.1/linux64
$ nano u-boot.csf
And put the following text:
[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"
# 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]
[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]
# Key slot index used to authenticate the image data
Verification Index = 2
# Address Offset Length Data File Path
Blocks = 0x177ff400 0x00000000 0x00000C10 "./u-boot.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 = 0x1787CFB8
#Provide DEK blob location to decrypt
[Decrypt Data]
Verification Index = 0
Mac Bytes = 16
Blocks = 0x17800010 0x00000C10 0x0007AFF0 "./u-boot.imx"
Press Ctrl+X and Y and Enter to save changes.
$ cp ~/imx6encryption/u-boot/u-boot.imx .
$ ./cst --o u-boot_csf.bin < u-boot.csf
$ objcopy -I binary -O binary --pad-to=0x1FB8 --gap-fill=0x00 u-boot_csf.bin u-boot_csf.bin
$ echo -e "o""\n""n""\n""p""\n""1""\n""2048""\n""+256M""\n""w" | sudo fdisk /dev/sdb
$ sudo mkfs.vfat /dev/sdb1
$ cd ~/imx6encryption/u-boot
$ sudo dd if=u-boot.imx of=/dev/sdb bs=512 seek=2
$ sync
$ cd ~/imx6encryption/cst-2.3.1/linux64
$ mkdir /tmp/partition0
$ sudo mount /dev/sdb1 /tmp/partition0
$ sudo cp dek.bin /tmp/partition0
$ sudo umount /tmp/partition0
=> fatload mmc 1:1 0x10800000 dek.bin
=> dek_blob 0x10800000 0x10801000 128
=> fatwrite mmc 1:1 0x10801000 dek_blob.bin 0x48
$ mkdir -p /tmp/partition0
$ sudo mount /dev/sdb1 /tmp/partition0
$ cd /tmp/partition0
$ cp dek_blob.bin ~/imx6encryption/cst-2.3.1/linux64/
$ cd ~/imx6encryption/cst-2.3.1/linux64/
$ sudo umount /tmp/partition0
$ cat u-boot_csf.bin >> u-boot.imx
$ cat dek_blob.bin >> u-boot.imx
$ sudo dd if=u-boot.imx of=/dev/sdb bs=512 seek=2
$ sync
=> hab_status
As a result we have encrypted boot image which can be loaded and executed by only current board. Because dek_blob.bin is unique per i.MX6 CPU.
Vitaliy Vasinovich
April 2016
Hi Vitaliy Vasinovich,
It is useful for me.
I could run u-boot.imx with HAB.
Now i want to load SPL and u-boot.img with HAB on imx6q, i have built SPL and u-boot.img and run successfully without HAB. I have a question: how to run SPL and u-boot.img with HAB?
Thanks you so much.
Dang
Hi Dang,
In my design I use u-boot image without SPL.
Looks like HAB with (SPL + U-boot) has quite different preparation procedure.
I guess you need to attach IVT, DCD, CSF to SPL image.
CPU's ROM will decrypt and verify SPL image and execute SPL.
Hi Vitaliy Vasinovich,
I tried to attach IVT, DCD, CSF to SPL image but it could not work.
Can you help me??
IVT, device configuration data (DCD in code) are already included in SPL image.
Try sign/encrypt SPL separately, it requires to adjust IVT a little bit, and attach CSF data at the end of SPL.
Please pay attention to u-boot.bin executable address in SPL image.
Hello Vitaliy Vasinovich,
many thanks for this example. It shows all necessary steps.
However, I have a slightly different environment:
6sx sabre-SDB evaluation board, buildroot-2015.11.1, uboot-rel_imx_3.10.53_1.1.0_ga
The steps 1 .. 4 worked with light deviations (tools/Makefile does not reference files gpimages* and without omapimage.o build is not successful).
The first real problem I got with step 5:
./tools/mkimage -T imximage -n board/freescale/mx6sxsabresd/imximage.cfg.cfgtmp -e 0x17800000 -d u-boot.bin u-boot.imx
Image Type: Freescale IMX Boot Image
Image Ver: 2 (i.MX53/6 compatible)
Mode: DCD
Data Size: 352256 Bytes = 344.00 kB = 0.34 MB
Load Address: 177ff420
Entry Point: 17800000
There is no line "HAB Blocks". How can I get it? --help did not help me there.
Steps 6 .. 9 worked perfectly.
Step 10 I used the same values as in your example, which is obviously wrong since in step 11 I get the following error:
./cst --o u-boot_csf.bin < u-boot.csf
Invalid Block arguments, Blocks start offset and length together exceed file size in command AuthenticateData
May you please explain how to get the values for addresses, offset, length? Why is authenticate data address 0x20 different to load address? Why is decrypt data 0x10 different to entry point? ...
Is there already a document where this is captured?
Thank you very much
Alex
Thank you very much for a very useful document!
However, it's failed to boot encrypted u-boot.
1. I followed all steps that most of them are successful, except step 17, hab_status. Nothing shown, u-boot is not loaded, isn't it? Because the uboot was encrypted, "for i.MX 6 Seriesin Open configuration, the HAB always skips the
verification of the SRK table, regardless of whether the SRK fuse field has been provisioned or not
" (in AN4581, 7.1 SRK Authentication for i.MX 6 Series in Open Configuration). Am I correct?
2. If encryption skipped by removing #Encrypt the boot image and create a DEK till the end of u-boot.csf, the u-boot is only signed, so I can check hab_status and "No HAB Events Found!".
After all, I did Close Configuration (fuse prog 0 6 0x2), only signed u-boot can be loaded. However, encrypted u-boot cann't.
Could you instruct me more?
Thank you!
An.
Hi,
Thank you for the guide. I have been able to experiment with both signing-only and signing+encryption on my open device, making sure "No HAB Events Found!" was reported in U-Boot.
Then after blowing the fuse to close the device didn't boot. So my first reaction was: "it is very buggy to have HAB reporting no error in open configuration but then fail in close configuration".
I kept digging and found this post:
i.MX6 HAB secure boot fuse problem
Thanks to that undocumented comment, I realized my problem was that I use 4096-bit keys.
So for recovering my board using the Serial Download Protocol (SDP) with imx_usb_loader, I was able to load a signed-only binary by adding this to my signing-only csf:
Engine = CAAM
However I still can't get encryption to work, although, once again, it was working fine in open configuration reporting no HAB Events.
So my question: have 4096-bit keys been tested with encryption on close devices?
Looking at the HABCST_UG.pdf, it seems that a configuration for 4096 keys is provided (section 5.3.5):
Please advise.
Regards,
Gary
Hi.
Where do you get the signed header length from (0xc10 in the example above)?
Thanks.
I realize this thread is more than a year old, but I've been through the pain-staking process of trying to get encrypted, secure boot working on i.MX6 plus a usable bulk manufacturing production process (which NXP doesn't seem to consider with encrypted boot), and I've learned a lot, including perhaps a reason why your encrypted boot still doesn't work.
If you read this thread:
https://community.nxp.com/thread/308950
you find that the i.MX SoCs use a common test master key when it is not "closed" (booted with secure boot lock) and the unique OTP master key when secure boot is closed. So if you follow the mostly excellent steps provided by Vitaliy, you get the dek blob of the test key, NOT the OTPMK that is used once the device is closed. So if you wrapped a DEK using u-boot dek_blob command before closing secure boot, HAB will fail to decrypt the image after secure boot is closed since the DEK is wrapped with a different key.
I understand the point of having test keys versus unique "production" keys in a single SoC (although other SoC vendors use different part numbers for these), but it does mean that a manufacturing process has to burn the hash fuses and secure boot lock fuse, then reboot, and then wrap the DEK for the encrypted image. The horrible NXP mfgtools doesn't handle multi-step mfg process (with reboot) well, so it's "left to the engineer" to come up with a solution, which I've already had to do to support programming unique MAC addresses.
The forums here are really nice. I just wish NXP put more effort into accurate and complete documentation and usable tools so each of us doesn't have to spend hours on google trying to find answers that should have been in the application note in the first place.
dek_blob.bin need to generate by u-boot , How to do this in production?
You have to get creative. You can have mfgtool push the DEK to an address before you jump to u-boot, and then have your mfg version of u-boot automatically create a dek_blob from that address and store it somewhere (i.e. some unused / reserved area of RAM or specific block of flash) so that when the mfg linux os runs it can pull the dek blob from there and dynamically append it to the encrypted image before writing. It's ugly, but unfortunately I don't know how to do this all within linux.