| +=======================================================+ |
| + i.MX8M, i.MX8MM Secure Boot guide using HABv4 + |
| +=======================================================+ |
| |
| 1. HABv4 secure boot process |
| ----------------------------- |
| |
| This document describes a step-by-step procedure on how to sign and securely |
| boot a bootloader image on i.MX8M and i.MX8MM devices. It is assumed that |
| the reader is familiar with basic HAB concepts and with the PKI tree generation. |
| |
| Details about HAB can be found in the application note AN4581[1] and in the |
| introduction_habv4.txt document. |
| |
| 1.1 Understanding the i.MX8M and i.MX8MM flash.bin image layout |
| ---------------------------------------------------------------- |
| |
| Due to the new the architecture, multiple firmwares and softwares are required |
| to boot i.MX8M and i.MX8MM devices. In order to store all the images in a |
| single binary the FIT (Flattened Image Tree) image structure is used. |
| |
| The final image is generated by the imx-mkimage project, the tool combines all |
| the input images in a FIT structure, generating a flash.bin image with an |
| appropriate IVT set. |
| |
| For a secure boot process users should ensure all images included in flash.bin |
| file are covered by a digital signature. |
| |
| - The diagram below illustrate a signed flash.bin image layout: |
| |
| +-----------------------------+ |
| | | |
| | *Signed HDMI/DP FW | |
| | | |
| +-----------------------------+ |
| | Padding | |
| ------- +-----------------------------+ -------- |
| ^ | IVT - SPL | ^ |
| Signed | +-----------------------------+ | |
| Data | | u-boot-spl.bin | | |
| | | + | | SPL |
| v | DDR FW | | Image |
| ------- +-----------------------------+ | |
| | CSF - SPL + DDR FW | v |
| +-----------------------------+ -------- |
| | Padding | |
| ------- +-----------------------------+ -------- |
| Signed ^ | FDT - FIT | ^ |
| Data | +-----------------------------+ | |
| v | IVT - FIT | | |
| ------- +-----------------------------+ | |
| | CSF - FIT | | |
| ------- +-----------------------------+ | |
| ^ | u-boot-nodtb.bin | | FIT |
| | | + | | Image |
| | | u-boot.bin | | |
| Signed | +-----------------------------+ | |
| Data | | OP-TEE (Optional) | | |
| | +-----------------------------+ | |
| | | bl31.bin (ATF) | | |
| | +-----------------------------+ | |
| v | u-boot.dtb | v |
| ------- +-----------------------------+ -------- |
| * Only supported on i.MX8M series |
| |
| The boot flow on i.MX8M and i.MX8MM devices are slightly different when compared |
| with i.MX6 and i.MX7 series, the diagram below illustrate the boot sequence |
| overview: |
| |
| - i.MX8M and i.MX8MM devices boot flow: |
| |
| Secure World Non-Secure World |
| | |
| | |
| +------------+ +------------+ | |
| | SPL | | i.MX 8M/MM | | |
| | + | ---> | ROM | | |
| | DDR FW | | + HAB | | |
| +------------+ +------------+ | |
| | | |
| v | |
| +------------+ | |
| | *Signed | | |
| | HDMI/DP FW | | |
| +------------+ | |
| | | |
| v | |
| +------------+ +------------+ | |
| | FIT Image: | | SPL | | |
| | ATF + TEE | ---> | + | | |
| | + U-Boot | | DDR FW | | +-----------+ |
| +------------+ +------------+ | | Linux | |
| | | +-----------+ |
| v | ^ |
| +------------+ | | +-------+ |
| | ARM | | +-----------+ | Linux | |
| | Trusted | ----+---> | U-Boot | <--- | + | |
| | Firmware | | +-----------+ | DTB | |
| +------------+ | +-------+ |
| | | |
| v | |
| +----------+ | |
| | **OP-TEE | | |
| +----------+ | |
| * Only supported on i.MX8M series |
| ** Optional |
| |
| On i.MX8M devices the HDMI firmware or DisplayPort firmware are the first image |
| to boot on the device. These firmwares are signed and distributed by NXP, and |
| are always authenticated regardless of security configuration. In case not |
| required by the application the HDMI or DisplayPort controllers can be disabled |
| by eFuses and the firmwares are not required anymore. |
| |
| The next images are not signed by NXP and users should follow the signing |
| procedure as described in this document. |
| |
| The Second Program Loader (SPL) and DDR firmware are loaded and authenticated |
| by the ROM code, these images are executed in the internal RAM and responsible |
| for initializing essential features such as DDR, UART, PMIC and clock |
| enablement. |
| |
| Once the DDR is available, the SPL code loads all the images included in the |
| FIT structure to their specific execution addresses, the HAB APIs are called |
| to extend the root of trust, authenticating the U-Boot, ARM trusted firmware |
| (ATF) and OP-TEE (If included). |
| |
| The root of trust can be extended again at U-Boot level to authenticate Kernel |
| and M4 images. |
| |
| 1.2 Enabling the secure boot support in U-Boot |
| ----------------------------------------------- |
| |
| The first step is to generate an U-Boot image supporting the HAB features, |
| similar to i.MX6 and i.MX7 series the U-Boot provides extra functions for |
| HAB, such as the HAB status logs retrievement through the hab_status command |
| and support to extend the root of trust. |
| |
| The support is enabled by adding the CONFIG_SECURE_BOOT to the build |
| configuration: |
| |
| - Defconfig: |
| |
| CONFIG_SECURE_BOOT=y |
| |
| - Kconfig: |
| |
| ARM architecture -> Support i.MX HAB features |
| |
| 1.3 Preparing the fit image |
| ---------------------------- |
| |
| The imx-mkimage project is used to combines all the images in a single |
| flash.bin binary, the following files are required: |
| |
| - U-Boot: |
| u-boot.bin |
| u-boot-nodtb.bin |
| u-boot-spl.bin |
| U-Boot DTB file (e.g. fsl-imx8mq-evk.dtb) |
| |
| - ATF image: |
| bl31.bin |
| |
| - DDR firmware: |
| lpddr4_pmu_train_1d_dmem.bin |
| lpddr4_pmu_train_1d_imem.bin |
| lpddr4_pmu_train_2d_dmem.bin |
| lpddr4_pmu_train_2d_imem.bin |
| |
| - HDMI firmware (Only in i.MX8M): |
| signed_hdmi_imx8m.bin |
| |
| - DisplayPort firmware (Only in i.MX8M): |
| signed_dp_imx8m.bin |
| |
| - OP-TEE (Optional): |
| tee.bin |
| |
| The procedure to build ATF and download the firmwares are out of the scope |
| of this document, please refer to the Linux BSP Release Notes and AN12212[2] |
| for further details. |
| |
| Copy all files to iMX8M directory and run the following command according to |
| the target device, on this example we are building a HDMI target and also |
| including the OP-TEE binary: |
| |
| - Assembly flash.bin binary: |
| |
| $ make SOC=<SoC Name> flash_hdmi_spl_uboot |
| |
| The mkimage log can be used to calculate the authenticate image command |
| parameters and CSF offsets: |
| |
| - imx-mkimage build log: |
| |
| Loader IMAGE: |
| header_image_off 0x1a000 |
| dcd_off 0x0 |
| image_off 0x1a040 |
| csf_off 0x44600 |
| spl hab block: 0x7e0fd0 0x1a000 0x2e600 |
| |
| Second Loader IMAGE: |
| sld_header_off 0x57c00 |
| sld_csf_off 0x58c20 |
| sld hab block: 0x401fcdc0 0x57c00 0x1020 |
| |
| Additional HAB information is provided by running the following command: |
| |
| - Printing HAB FIT information: |
| |
| $ make SOC=<SoC Name> print_fit_hab |
| |
| TEE_LOAD_ADDR=0xfe000000 ATF_LOAD_ADDR=0x00910000 ./print_fit_hab.sh \ |
| 0x60000 fsl-imx8mq-evk.dtb |
| 0x40200000 0x5AC00 0x9AAC8 |
| 0x910000 0xF56C8 0x9139 |
| 0xFE000000 0xFE804 0x4D268 |
| 0x4029AAC8 0x14BA6C 0x6DCF |
| |
| 1.4 Creating the CSF description file |
| -------------------------------------- |
| |
| The CSF contains all the commands that the ROM executes during the secure |
| boot. These commands instruct the HAB code on which memory areas of the image |
| to authenticate, which keys to install, use and etc. |
| |
| CSF examples are available under doc/imx/hab/habv4/csf_examples/ directory. |
| |
| As explained in sections above the SPL is first authenticated by the ROM code |
| and the root of trust is extended to the FIT image, hence two CSF files are |
| necessary to completely sign an flash.bin image. |
| |
| The build log provided by imx-mkimage can be used to define the "Authenticate |
| Data" parameter in CSF. |
| |
| - SPL "Authenticate Data" addresses in flash.bin build log: |
| |
| spl hab block: 0x7e0fd0 0x1a000 0x2e600 |
| |
| - "Authenticate Data" command in csf_spl.txt file: |
| |
| Blocks = 0x7e0fd0 0x1a000 0x2e600 "flash.bin" |
| |
| - FIT image "Authenticate Data" addresses in flash.bin build log: |
| |
| sld hab block: 0x401fcdc0 0x57c00 0x1020 |
| |
| - FIT image "Authenticate Data" addresses in print_fit_hab build log: |
| |
| 0x40200000 0x5AC00 0x9AAC8 |
| 0x910000 0xF56C8 0x9139 |
| 0xFE000000 0xFE804 0x4D268 |
| 0x4029AAC8 0x14BA6C 0x6DCF |
| |
| - "Authenticate Data" command in csf_fit.txt file: |
| |
| Blocks = 0x401fcdc0 0x057c00 0x01020 "flash.bin", \ |
| 0x40200000 0x05AC00 0x9AAC8 "flash.bin", \ |
| 0x00910000 0x0F56C8 0x09139 "flash.bin", \ |
| 0xFE000000 0x0FE804 0x4D268 "flash.bin", \ |
| 0x4029AAC8 0x14BA6C 0x06DCF "flash.bin" |
| |
| 1.4.1 Avoiding Kernel crash in closed devices |
| ---------------------------------------------- |
| |
| For devices prior to HAB v4.4.0, the HAB code locks the Job Ring and DECO |
| master ID registers in closed configuration. In case the user specific |
| application requires any changes in CAAM MID registers it's necessary to |
| add the "Unlock CAAM MID" command in CSF file. |
| |
| The current NXP BSP implementation expects the CAAM registers to be unlocked |
| when configuring CAAM to operate in non-secure TrustZone world. |
| |
| The Unlock command is already included by default in the signed HDMI and |
| DisplayPort firmwares, on i.MX8MM devices or in case the HDMI or DisplayPort |
| controllers are disabled, users must ensure this command is included in SPL CSF. |
| |
| - Add Unlock MID command in csf_spl.txt: |
| |
| [Unlock] |
| Engine = CAAM |
| Features = MID |
| |
| 1.5 Signing the flash.bin binary |
| --------------------------------- |
| |
| The CST tool is used for singing the flash.bin image and generating the CSF |
| binary. Users should input the CSF description file created in the step above |
| and receive a CSF binary, which contains the CSF commands, SRK table, |
| signatures and certificates. |
| |
| - Create SPL CSF binary file: |
| |
| $ ./cst -i csf_spl.txt -o csf_spl.bin |
| |
| - Create FIT CSF binary file: |
| |
| $ ./cst -i csf_fit.txt -o csf_fit.bin |
| |
| 1.6 Assembling the CSF in flash.bin binary |
| ------------------------------------------- |
| |
| The CSF binaries generated in the step above have to be inserted into the |
| flash.bin image. |
| |
| The CSF offsets can be obtained from the flash.bin build log: |
| |
| - SPL CSF offset: |
| |
| csf_off 0x44600 |
| |
| - FIT CSF offset: |
| |
| sld_csf_off 0x58c20 |
| |
| The signed flash.bin image can be then assembled: |
| |
| - Create a flash.bin copy: |
| |
| $ cp flash.bin signed_flash.bin |
| |
| - Insert csf_spl.bin in signed_flash.bin at 0x44600 offset: |
| |
| $ dd if=csf_spl.bin of=signed_flash.bin seek=$((0x44600)) bs=1 conv=notrunc |
| |
| - Insert csf_fit.bin in signed_flash.bin at 0x58c20 offset: |
| |
| $ dd if=csf_fit.bin of=signed_flash.bin seek=$((0x58c20)) bs=1 conv=notrunc |
| |
| - Flash signed flash.bin image: |
| |
| $ sudo dd if=signed_flash.bin of=/dev/sd<x> bs=1K seek=33 && sync |
| |
| 1.7 Programming SRK Hash |
| ------------------------- |
| |
| As explained in AN4581[1] and in introduction_habv4.txt document the SRK Hash |
| fuse values are generated by the srktool and should be programmed in the |
| SoC SRK_HASH[255:0] fuses. |
| |
| Be careful when programming these values, as this data is the basis for the |
| root of trust. An error in SRK Hash results in a part that does not boot. |
| |
| The U-Boot fuse tool can be used for programming eFuses on i.MX SoCs. |
| |
| - Dump SRK Hash fuses values in host machine: |
| |
| $ hexdump -e '/4 "0x"' -e '/4 "%X""\n"' SRK_1_2_3_4_fuse.bin |
| 0x20593752 |
| 0x6ACE6962 |
| 0x26E0D06C |
| 0xFC600661 |
| 0x1240E88F |
| 0x1209F144 |
| 0x831C8117 |
| 0x1190FD4D |
| |
| - Program SRK_HASH[255:0] fuses on i.MX8MQ and i.MX8MM devices: |
| |
| => fuse prog 6 0 0x20593752 |
| => fuse prog 6 1 0x6ACE6962 |
| => fuse prog 6 2 0x26E0D06C |
| => fuse prog 6 3 0xFC600661 |
| => fuse prog 7 0 0x1240E88F |
| => fuse prog 7 1 0x1209F144 |
| => fuse prog 7 2 0x831C8117 |
| => fuse prog 7 3 0x1190FD4D |
| |
| |
| 1.8 Verifying HAB events |
| ------------------------- |
| |
| The next step is to verify that the signatures included in flash.bin image is |
| successfully processed without errors. HAB generates events when processing |
| the commands if it encounters issues. |
| |
| The hab_status U-Boot command call the hab_report_event() and hab_status() |
| HAB API functions to verify the processor security configuration and status. |
| This command displays any events that were generated during the process. |
| |
| Prior to closing the device users should ensure no HAB events were found, as |
| the example below: |
| |
| - Verify HAB events: |
| |
| => hab_status |
| |
| Secure boot disabled |
| |
| HAB Configuration: 0xf0, HAB State: 0x66 |
| |
| 1.9 Closing the device |
| ----------------------- |
| |
| After the device successfully boots a signed image without generating any HAB |
| events, it is safe to close the device. This is the last step in the HAB |
| process, and is achieved by programming the SEC_CONFIG[1] fuse bit. |
| |
| Once the fuse is programmed, the chip does not load an image that has not been |
| signed using the correct PKI tree. |
| |
| - Program SEC_CONFIG[1] fuse on i.MX8MQ and i.MX8MM devices: |
| |
| => fuse prog 1 3 0x2000000 |
| |
| 1.10 Completely secure the device |
| ---------------------------------- |
| |
| Additional fuses can be programmed for completely secure the device, more |
| details about these fuses and their possible impact can be found at AN4581[1]. |
| |
| - Program SRK_LOCK: |
| |
| => fuse prog 0 0 0x200 |
| |
| - Program DIR_BT_DIS: |
| |
| => fuse prog 1 3 0x8000000 |
| |
| - Program SJC_DISABLE: |
| |
| => fuse prog 1 3 0x200000 |
| |
| - JTAG_SMODE: |
| |
| => fuse prog 1 3 0xC00000 |
| |
| 2. Authenticating additional boot images |
| ----------------------------------------- |
| |
| The High Assurance Boot (HAB) code located in the on-chip ROM provides an |
| Application Programming Interface (API) making it possible to call back |
| into the HAB code for authenticating additional boot images. |
| |
| The U-Boot is running in non-secure TrustZone world and to make use of this |
| feature it's necessary to use a SIP call to the ATF, this is already |
| implemented in hab.c code and it's transparent to the user. |
| |
| The process of signing an additional image is similar as in i.MX6 and i.MX7 |
| series devices, the steps below are using the Linux Kernel image as example. |
| |
| The diagram below illustrate the Image layout: |
| |
| ------- +-----------------------------+ <-- *load_address |
| ^ | | |
| | | | |
| | | | |
| | | | |
| | | Image | |
| Signed | | | |
| Data | | | |
| | | | |
| | +-----------------------------+ |
| | | Padding to Image size | |
| | | in header | |
| | +-----------------------------+ <-- *ivt |
| v | Image Vector Table | |
| ------- +-----------------------------+ <-- *csf |
| | | |
| | Command Sequence File (CSF) | |
| | | |
| +-----------------------------+ |
| | Padding (optional) | |
| +-----------------------------+ |
| |
| 2.1 Padding the image |
| ---------------------- |
| |
| The Image must be padded to the size specified in the Image header, this can be |
| achieved by using the od command. |
| |
| - Read Image size: |
| |
| $ od -x -j 0x10 -N 0x4 --endian=little Image |
| 0000020 5000 0145 |
| 0000024 |
| |
| The tool objcopy can be used for padding the image. |
| |
| - Pad the Image: |
| |
| $ objcopy -I binary -O binary --pad-to 0x1455000 --gap-fill=0x00 \ |
| Image Image_pad.bin |
| |
| 2.2 Generating Image Vector Table |
| ---------------------------------- |
| |
| The HAB code requires an Image Vector Table (IVT) for determining the image |
| length and the CSF location. Since Image does not include an IVT this has |
| to be manually created and appended to the end of the padded Image, the |
| script genIVT.pl in script_examples directory can be used as reference. |
| |
| - Generate IVT: |
| |
| $ genIVT.pl |
| |
| Note: The load Address may change depending on the device. |
| |
| - Append the ivt.bin at the end of the padded Image: |
| |
| $ cat Image_pad.bin ivt.bin > Image_pad_ivt.bin |
| |
| 2.3 Signing the image |
| ---------------------- |
| |
| A CSF file has to be created to sign the image. HAB does not allow to change |
| the SRK once the first image is authenticated, so the same SRK key used in |
| the initial image must be used when extending the root of trust. |
| |
| CSF examples are available in ../csf_examples/additional_images/ directory. |
| |
| - Create CSF binary file: |
| |
| $ ./cst --i csf_additional_images.txt --o csf_Image.bin |
| |
| - Attach the CSF binary to the end of the image: |
| |
| $ cat Image_pad_ivt.bin csf_Image.bin > Image_signed.bin |
| |
| 2.4 Verifying HAB events |
| ------------------------- |
| |
| The U-Boot includes the hab_auth_img command which can be used for |
| authenticating and troubleshooting the signed image, the Image must be |
| loaded at the load address specified in the IVT. |
| |
| - Authenticate additional image: |
| |
| => hab_auth_img <Load Address> <Image Size> <IVT Offset> |
| |
| If no HAB events were found the Image is successfully signed. |
| |
| References: |
| [1] AN4581: "Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using |
| HABv4" - Rev 2. |
| [2] AN12212: "Software Solutions for Migration Guide from Aarch32 to |
| Aarch64" - Rev 0. |