Encrypted boot loader on SabreSD i.MX6q board

Showing results for 
Search instead for 
Did you mean: 

Encrypted boot loader on SabreSD i.MX6q board

No ratings

Encrypted boot loader on SabreSD i.MX6q board

     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:

    • Encrypt u-boot.imx plain image by CST utility;
    • Wrap DEK to get DEK blob by specific board;
    • Append DEK blob key to the u-boot image.

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
0x000020DCD + pad to address 0xC00

u-boot.bin + pad to address* 0x7BC000

0x07DBB8CSF 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:

  1. Clone u-boot git repository.

    $ mkdir ~/imx6encryption

    $ cd ~/imx6encryption

    $ git clone git://git.denx.de/u-boot.git

    $ cd u-boot

    $ git checkout v2016.03 -b tmp

  2. To enable secure features in u-boot modify the following files:
    • Add function usec2ticks to the end of file timer.c.

      $ nano arch/arm/imx-common/timer.c

      unsigned long usec2ticks(unsigned long usec)


              ulong ticks;

              if (usec < 1000)

                      ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;


                      ticks = ((usec / 10) * (get_tbclk() / 100000));

              return ticks;


      Press Ctrl+X and Y and Enter to save changes.

    • In file mx6q_4x_mt41j128.cfg add string CSF 0x2000 after string BOOT_FROM sd

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

    • Delete the following strings:

      gpimage.0 \

      gpimage-common.o \

      omapimage.o \

      in Makefile.

      $ nano tools/Makefile

      Press Ctrl+X and Y and Enter to save changes

  3. Download Linaro GCC compiler.

    $ 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-

    Check compiler version.

    $ ${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


  4. Build u-boot image with mx6qsabresd_defconfig.

    $ cd u-boot

    $ make ARCH=arm CROSS_COMPILE=${CC} distclean

    $ make ARCH=arm CROSS_COMPILE=${CC} mx6qsabresd_defconfig

    $ make ARCH=arm CROSS_COMPILE=${CC}

  5. Using mkimage utility build and get information of u-boot.imx image.

    $ ./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

  6. Register an account on NXP website to have access to download NXP Code Signing Tool for the High Assurance Boot library. Copy downloaded archive into imx6encryption folder.

    $ cd ~/imx6encryption

    $ tar xf cst-2.3.1.tar.gz

    $ cd cst-2.3.1

    $ chmod u+x linux64/* keys/*

  7. Compile back end sources of CST utility

    $ 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

  8. Generate keys and certificates which will be used to sign boot loader image.

    $ cd ~/imx6encryption/cst-2.3.1/keys

    • Create file serial.

      $ nano serial

      Enter 8 random digits, for example:


      Press Ctrl+X and Y and Enter to save changes.

    • Create key_pass.txt

      $ nano key_pass.txt

      Enter two lines of identical text:



      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

  9. Generate SRK table.

    $ 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

  10. 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:


    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]


    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.

  11. Execute CST utility to encrypt image. Note that after execution u-boot.imx file will be encrypted.

    $ 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

  12. Prepare SD card partition table. Check SD card name in system ($dmesg | tail), for example used /dev/sdb.

    $ 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

  13. Wrap DEK to get DEK blob from i.MX6 CPU. Mount partition 1 and copy dek.bin file to the 1st FAT partition on SD card.

    $ 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

  14. Insert SD card into the board. And press any key to enter into u-boot prompt. Firstly load dek.bin to the RAM memory. Use dek_blob command to wrap dek.bin. Write file from RAM memory to SD card.

    => fatload mmc 1:1 0x10800000 dek.bin

    => dek_blob 0x10800000 0x10801000 128

    => fatwrite mmc 1:1 0x10801000 dek_blob.bin 0x48

  15. Append DEK blob key to the u-boot image. Mount SD card partition 1 and copy dek_blob.bin file to the linux64 folder.

    $ 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

  16. Install encrypted u-boot.imx into SD card.

    $ sudo dd if=u-boot.imx of=/dev/sdb bs=512 seek=2

    $ sync

  17. Insert SD card into the board. Press any key to enter into u-boot prompt. And check if hab_status command executes without HAB Event errors.

    => hab_status

  18. Attention, OTP fuses can be programmed once, double check everything before burning. If everything is fine, burn required fuses SRK_HASH, SEC_CONFIG as described in AN4581.

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.


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


Hi Vitaliy Vasinovich

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!



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):

  • It doesn't have the [UNLOCK] section
    • Does this configuration force to set the RNG Trim in Fuse?
  • It is providing the .der files instead of the .pem files, is it normal?

Please advise.




Where do you get the signed header length from (0xc10 in the example above)?


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:


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.

Version history
Revision #:
1 of 1
Last update:
‎04-18-2016 01:28 PM
Updated by: