i.MX 93 OTFAD (On-The-Fly AES Decryption) Example#

This notebook describes how to build a bootable AHAB image that is encrypted using the i.MX 93 OTFAD (On-The-Fly AES Decryption) feature. The i.MX 93 OTFAD is a hardware accelerator that can be used to encrypt and decrypt data on-the-fly. The OTFAD is also used to decrypt the boot image when the i.MX 93 boots.

1. Prerequisites#

  • SPSDK is needed with examples extension. pip install spsdk[examples] (Please refer to the installation documentation.)

  • This demo was tested with i.MX93 EVK board

1.1 Images preparation#

  • We use U-Boot image in this example. Prepare the U-Boot image for flexSPI imx-boot-imx93-14x14-lpddr4x-evk-fspi.bin-flash_singleboot_flexspi using the imx-mkimage or nxpimage tool or use the prebuilt image from the NXP website.

  1. Put the U-Boot image to the inputs directory.

  2. Extract the FCB block and image container set from the data

    nxpimage -v utils binary-image extract -b inputs/imx-boot-imx91-11x11-lpddr4-evk-fspi.bin-flash_singleboot_flexspi -a 0x400 -s 0x200 -o workspace/fcb.bin
    nxpimage -v utils binary-image extract -b inputs/imx-boot-imx91-11x11-lpddr4-evk-fspi.bin-flash_singleboot_flexspi -a 0x1000 -s 0 -o workspace/imx-boot.bin
    
FILENAME = "inputs/imx-boot-imx91-11x11-lpddr4-evk-fspi.bin-flash_singleboot_flexspi"

%! nxpimage -v utils binary-image extract -b $FILENAME -a 0x400 -s 0x200 -o workspace/fcb.bin
%! nxpimage -v utils binary-image extract -b $FILENAME -a 0x1000 -s 0 -o workspace/imx-boot.bin
nxpimage -v utils binary-image extract -b inputs/imx-boot-imx91-11x11-lpddr4-evk-fspi.bin-flash_singleboot_flexspi -a 0x400 -s 0x200 -o workspace/fcb.bin
Success. (Extracted chunk: workspace/fcb.bin created.)
nxpimage -v utils binary-image extract -b inputs/imx-boot-imx91-11x11-lpddr4-evk-fspi.bin-flash_singleboot_flexspi -a 0x1000 -s 0 -o workspace/imx-boot.bin
Success. (Extracted chunk: workspace/imx-boot.bin created.)

2. OTFAD#

  • The OTFAD engine includes complete hardware support for a standard AES key unwrap mechanism to decrypt a key BLOB data instruction containing the parameters needed for up to 4 unique AES contexts. Each context has a unique 128-bit key, 64-bit counter and 64-bit memory region descriptor.

  • OTFAD can only be used with flexSPI 1, it can’t be used for other boot medias like eMMC.

  • OTFAD will be enabled by system ROM when booting from flexSPI, user just need to prepare encrypted boot image and program OTFAD related fuses.

  • Please check more information about OTFAD IP from the i.MX93 security reference manual.

OTFAD structure

2.1 OTFAD Key Scrambling#

Key scrambling is an encryption algorithm designed to obfuscate the secret key information. It is an optional feature. When enabled, the OTFAD engine implements a key scrambling algorithm, wherein, the input OTFAD key is scrambled and then utilized to unwrap the key blobs containing the image encryption keys.

The OTFAD tool takes three inputs to scramble the OTFAD key:

  • OTFAD key: An OEM programmed input 128-bit key used to wrap/un-wrap the image encryption keys.

  • Key Scramble: An OEM programmed input 32-bit key used to scramble the input OTFAD key.

  • Key Scramble Align: An OEM programmed 8-bit key aligns value used along with Key Scramble in scrambling algorithm.

2.2 OTFAD Template#

The following command generates the template:

nxpimage otfad get-template -f mimx9352 -o ahab_template.yaml

2.3 Exporting the OTFAD Image#

The following command exports the OTFAD image with fuse programming script for flexSPI instance 1.

nxpimage otfad export -f mimx9352 -c ahab_template.yaml -i 1

If the FlexSPI instance is specified, the OTFAD image will be exported with the fuse programming script for the specified FlexSPI instance.

nxpimage otfad get-template -f mimx9352 -o workspace/otfad_template.yaml --force
Creating workspace/otfad_template.yaml template file.

Configuration Differences

%! nxpimage otfad export -c inputs/otfad_mx93.yaml -i 1
nxpimage otfad export -c inputs/otfad_mx93.yaml -i 1
Created OTFAD BLHOST load fuses script:
workspace/encrypted/otfad1_mimx9352.bcf
Success. OTFAD files have been created

3. Bootable Image with OTFAD encrypted image#

The following command merges the OTFAD image with the bootable image:

nxpimage -v bootable-image merge -c u-boot-flash_template.yaml -o flash.bin

We have to prepare the configuration.

nxpimage utils binary-image get-template -o workspace/bimg_template.yaml --force
Creating workspace/bimg_template.yaml template file.

Configuration Differences

%! nxpimage -v utils binary-image merge --config inputs/bimg.yaml --output workspace/encrypted_full_image.bin
nxpimage -v utils binary-image merge --config inputs/bimg.yaml --output workspace/encrypted_full_image.bin
INFO:spsdk.apps.nxpimage:Merged Image:
Name:      OTFAD encrypted AHAB image with FCB
Starts:    0x0
Ends:      0x1ed7ff
Size:      Size: 1.9 MiB; 2,021,376 B
Alignment: 1 B
Execution Start Address: Not defined
Pattern:zeros

INFO:spsdk.apps.nxpimage:Merged Image:

+==0x0000_0000= OTFAD encrypted AHAB image with FCB ==+
|             Size: 1.9 MiB; 2,021,376 B              |
|                   Pattern: zeros                    |
|+==0x0000_0000= OTFAD keyblob ======================+|
||                    Size: 256 B                    ||
||              The image loaded from:               ||
||       workspace/encrypted/OTFAD_Table.bin .       ||
||                  Pattern: zeros                   ||
||+==0x0000_0000= Segment 0 ========================+||
|||                   Size: 256 B                   |||
|||                 Pattern: zeros                  |||
||+==0x0000_00ff====================================+||
|+==0x0000_00ff======================================+|
|                     Gap: 768 B                      |
|+==0x0000_0400= FCB ================================+|
||                    Size: 512 B                    ||
||    The image loaded from: workspace/fcb.bin .     ||
||                  Pattern: zeros                   ||
||+==0x0000_0400= Segment 0 ========================+||
|||                   Size: 512 B                   |||
|||                 Pattern: zeros                  |||
||+==0x0000_05ff====================================+||
|+==0x0000_05ff======================================+|
|                    Gap: 2.5 kiB                     |
|+==0x0000_1000= OTFAD encrypted blob ===============+|
||            Size: 1.9 MiB; 2,017,280 B             ||
||              The image loaded from:               ||
||     workspace/encrypted/encrypted_blobs.bin .     ||
||                  Pattern: zeros                   ||
||+==0x0000_1000= Segment 0 ========================+||
|||           Size: 1.9 MiB; 2,017,280 B            |||
|||                 Pattern: zeros                  |||
||+==0x001e_d7ff====================================+||
|+==0x001e_d7ff======================================+|
+==0x001e_d7ff========================================+

Success. (Merged image: workspace/encrypted_full_image.bin created.)

4. Program OTFAD Fuses#

The Following fuses need to be programmed to enable the OTFAD feature:

Fuse

Location

OTFAD_ENABLE

Bank 23, word 4, bit 3

OTFAD_KEY[127:0]

Bank 23, word 0~4

OTFAD1_KEY_SCRAMBLE_EN

Bank 23, word 4, bit 7

OTFAD1_KEY_SCRAMBLE_ALIGN[7:0]

Bank 23, word 4, bit 8~15

OTFAD1_KEY_SCRAMBLE[31:0]

Bank 23, word 5

4.1 Program OTFAD Fuses using the NXPELE#

Fuses can be programmed by the SPSDK nxpele tool. Refer to the AHAB notebook for more information about how to use the nxpele tool The following command programs the OTFAD fuses:

nxpele batch -c "workspace/encrypted/otfad1_mimx9352.bcf"

Example of the bcf file:


# Family: mimx9352 Revision: a1

# Value: 0x8
# Description: Fuse 188
# Bitfield: OTFAD1_ENABLE, Description: OTFAD1 enable, Value: 0x1
# Bitfield: OTFAD1_KEY_SCRAMBLE_EN, Description: OTFAD1 key scramble enable, write-only, Value: 0x0
# Bitfield: OTFAD1_KEY_SCRAMBLE_ALIGN, Description: OTFAD1 key scramble align, write-only, Value: 0x00
# WARNING! Partially set register, check all bitfields before writing
# OTP ID: OTFAD1_CFG

write-fuse --index 188 --data 0x00000008

# Value: 0x0
# Description: OTFAD1 key scramble
# OTP ID: OTFAD1_KEY_SCRAMBLE

write-fuse --index 189 --data 0x00000000

# Value: 0x112233445566778899aaabbccddeeff
# Description: OTFAD1 Key known as KEK.
# Grouped register name: OTFAD1_KEY

# OTP ID: OTFAD1_KEY3, Value: 0xffeeddcc
write-fuse --index 184 --data 0xFFEEDDCC
# OTP ID: OTFAD1_KEY2, Value: 0xbbaa9a89
write-fuse --index 185 --data 0xBBAA9A89
# OTP ID: OTFAD1_KEY1, Value: 0x78675645
write-fuse --index 186 --data 0x78675645
# OTP ID: OTFAD1_KEY0, Value: 0x34231201
write-fuse --index 187 --data 0x34231201

4.2 Program OTFAD Fuses using the U-Boot CLI#

Another option is to use the U-Boot CLI interface and fuse prog command

u-boot=> fuse prog -y 23 0 0xffeeddcc <= burn test keys
u-boot=> fuse prog -y 23 1 0xbbaa9988
u-boot=> fuse prog -y 23 2 0x77665544
u-boot=> fuse prog -y 23 3 0x33221100
u-boot=> fuse prog 23 4 0x8    <= enable OTFAD

4. Image download#

First we put the iMX93 into serial downloader mode for Cortex-A (0011), and use nxpuuu to programm the encrypted image to flexSPI. First argument is bootloader image that contains u-boot second argument is our encrypted u-boot.

The picture below shows the desired DIP switch configuration for flashing Cortex-A:

Download Mode Cortex-A

%! nxpuuu $VERBOSITY write -f mimx9352 -b qspi "inputs/imx-boot-imx91-11x11-lpddr4-evk-fspi.bin-flash_singleboot_flexspi" "workspace/encrypted_full_image.bin"
nxpuuu -v write -f mimx9352 -b emmc outputs/flash.bin 
SDPS: boot -f outputs/flash.bin


Done