[S32G] S32g247's Secure Boot using HSE firmware

1. Overview

  • HSE Firmware

  • Secure Boot Flow

2. HSE Firmware

The NXP Hardware Security Engine is a security subsystem aimed at running relevant security functions for applications with stringent confidentiality and authenticity requirements.

The HSE Firmware is required to support the following features. The following firmware versions are supported:

  • HSE_FW_S32G2_0_1_0_0

  • HSE_FW_S32G2_0_1_0_1

  • HSE_FW_S32G2_0_1_0_5 (current)

  • HSE_FW_S32G2_1_1_0_0

  • HSE_FW_S32G2_1_1_0_1

  • HSE_FW_S32G3_0_0_21_0

  • HSE_FW_S32G3_1_0_21_0

  • HSE_FW_S32R45_0_1_0_1

Information on how to configure the HSE Firmware is available in the HSE Reference Manual. More information regarding the HSE API is available in the HSE Service API Reference Manual, available on https://drive.google.com/file/d/1Rgf4kMXKEcfVVmGLXYbr4j5-rejWtLU6/view?usp=drive_link

3. Secure Boot

Secure boot refers to a two-stage process of successive authentication of the U-Boot and Linux kernel images. This process requires a "root of trust", which is known to be secure. In this case, the root of trust is HSE itself.

Each image is authenticated by the preceding step. Thus, the secure boot flow is the following:

  • BootROM passes control over to HSE FW;

  • HSE FW authenticates the U-Boot image;

  • Boot authenticates the Kernel image.

Note,

  • U-Boot authentication is currently only supported when booting from an SD card!

  • Currently, enabling secure boot cannot be done via Yocto. As such, U-Boot must be built manually with HSE-provided secure boot options enabled!

3.1 Secure Boot Flow

3.1.1 U-Boot Authentication

The U-Boot image is populated into the fip.s32 that is generated by the TF-A firmware. When the device is booting, the HSE firmware loads the fip.s32 and fip.bin (signature file) from the SD card. Then put the RSA public key in the SD card into the NVM key catalog (doc). Then verify the U-Boot image in fip.s32 with the fip.bin signature using the RSA public key in NVM key catalog.

Signing

Since the FIP signature is stored in the FIP, space is reserved within it. As such, the fip.bin must be signed without the reserved space. First, determine how much of the FIP must be signed:

tools/fiptool/fiptool info fip.bin
Trusted Boot Firmware BL2: offset=0x100, size=0x7D6AC, cmdline="--tb-fw"
EL3 Runtime Firmware BL31: offset=0x7D7B0, size=0x2FF5D, cmdline="--soc-fw"
Non-Trusted Firmware BL33: offset=0xAD710, size=0xAADD0, cmdline="--nt-fw"
SOC_FW_CONFIG: offset=0x1584E0, size=0x5C1F, cmdline="--soc-fw-config"
Trusted Boot Firmware BL2 certificate: offset=0x15E100, size=0x100, cmdline="--tb-fw-cert"

The relevant part of the FIP can be extracted and signed with the private key. In this example, the first 0x15E100 bytes of the FIP must be signed:

dd if=fip.bin of=tosign-fip.bin bs=1 count=`printf "%d" 0x15e100` conv=notrunc
openssl dgst -sha1 -sign rsa2048_private.pem -out fip-signature.bin tosign-fip.bin

The resulting fip-signature.bin must be written back into the fip.bin:

tools/fiptool/fiptool update --align 16 --tb-fw-cert fip-signature.bin fip.bin

The public RSA key must be copied to the boot partition of the SD Card, next to the Linux Kernel Image and DTB file. fip.s32 and fip.bin must be written to the SD Card. fip.bin must be written at the address pointed to by the Application label in the compile log; in this example, the address is 0x5e640.

For shell seek=`printf "%d" 0x5e640`, please convert the hex to decimal manually.

dd if=build/<board>/release/fip.s32 of=/dev/<sdcard_dev> seek=512 skip=512 \
iflag=skip_bytes oflag=seek_bytes conv=notrunc,fsync
dd if=build/<board>/release/fip.bin of=/dev/<sdcard_dev> seek=`printf "%d" 0x5e640` \
conv=notrunc,fsync

Please note (limitation):

For some old EVB boards. The HSE hardware feature cannot be enabled.

The old EVB boards (chips) haven’t HSE hardware IP, named CSE3 Security. As the result, the secure boot feature (HSE features) cannot be supported on the CSE3 Security related platform.

How to test it?

When you type hse_secboot_enable rsa2048_public.der in the uboot console, uboot returns ERROR: HSE not initialised or missing firmware!, which can help you testing wether the HSE features enabled or not.

The sign process should be finished by sign server, the code can be found by:

Verifying

HSE FW authenticates the U-Boot image.

Self-provisioning Public Key

The secure boot is enabled in the default configuration of the Bootloader. For the First time boot after image deployment on S32G2, the secure boot is not enabled, which means, the BOOT_SEQ in the IVT is set to zero. When the bootloader runs for the first time, it detects this condition and configures the HSE for secure boot, and then set BOOT_SEQ=1. After setting BOOT_SEQ=1, the bootloader issues a functional reset.

For more information, please refer to doc.

Note, The command can be called from the U-Boot command line:

=> hse_secboot_enable rsa2048_public.der

<public_key_file>.der refers to the public RSA key on the SD Card boot partition, generated in the chapter.

After the command is finished, simply reset the board to boot in secure mode. To verify if the board has booted in secure mode, check the BOOT_SEQ bit in the IVT, at offset 0x28:

Verify U-Boot

To authenticate the U-Boot image, HSE uses Advanced Secure Boot (ASB).

The SD card contains:

  • Signed Boot Image (IVT + signed FIP.bin) in the raw partition;

  • RSA Public key in DER format.

The self-provisioning process loaded the RSA Public Key into the HSE Key catalog. The RSA HSE engine loads the public key from HSE key catalog directly while the RSA engine calculates the RSA digest.

3.1.2 Kernel Authentication

Kernel image authentication is provided by U-Boot, using the upstream verified boot method. This method will use an .its file, which defines a dtb/kernel configuration and a signing scheme. Please refer to the link https://lwn.net/Articles/571031/ and https://github.com/ARM-software/u-boot/blob/master/doc/uImage.FIT/signature.txt

PKI

The public key is:

Signing

Sign the kernel image and pack it into a FIT image. After the kernel has been compiled, from the u-boot directory, run:

tools/mkimage -f ../linux/<its-filename>.its
-K ../arm-trusted-firmware/build/<board>/release/fdts/<dtb-filename>.dtb
-k ../kernel_keys
-r <itb-filename>.itb

The output of the mkimage command should display the parts of the FIT image: the kernel, dtb and configuration. The kernel and dtb will have a hash value, while the configuration will have a signed hash, if using the configuration signing method. Otherwise, the kernel and fdt will have a signed hash. The sign format please refer to https://github.com/carloscn/blog/issues/186.

The options for mkimage specify:

For the signing information, please refer to https://app.gitbook.com/o/eTBeA3vhkOtihTJASkhd/s/tqiX1ZbXhRorHX3bwk1r/~/changes/12/s32g_documents/s32g-s32g247s-secure-boot-using-hse-firmware/s32g-secure-boot-signature-generation

Verifying

For the signing information, please refer to https://app.gitbook.com/o/eTBeA3vhkOtihTJASkhd/s/tqiX1ZbXhRorHX3bwk1r/~/changes/12/s32g_documents/s32g-s32g247s-secure-boot-using-hse-firmware/s32g-secure-boot-signature-generation

U-Boot must use the bootm command to boot, not booti. Trying to boot using booti will display the "Bad Linux ARM64 Image magic!" error, since the header for the FIT image is not recognized by booti.

To optionally enable U-Boot secure boot, run:

=> hse_secboot_enable <rsa_public_key>.der

Copy the FIT image from the SD Card to memory:

=> fatload mmc 0:1 <load-address> <fit-image-name>
=> run mmcargs
=> bootm <load-address>

To check if the FIT image loaded on the board is correct, run:

iminfo

The command will check the hashes of the image, dtb, and configuration, but will not check if the FIT image is properly signed.

4. Procedure Secure Boot

Please refer to the link: https://app.gitbook.com/o/eTBeA3vhkOtihTJASkhd/s/tqiX1ZbXhRorHX3bwk1r/~/changes/12/s32g_documents/s32g-s32g247s-secure-boot-using-hse-firmware/how-to-download-and-build-s32g-secure-boot-image

4.1 Notes for TF-A

To build ATF with support for HSE Secure Boot, the following make command needs to be run from the ATF repo: make ARCH=aarch64 CROSS_COMPILE=aarch64-none-linux-gnu- PLAT=s32g2xxaevb BL33=u-boot-nodtb.bin HSE_SECBOOT=1 -j8

BL2 uses FIP_MEMORY_OFFSET as the address from which to read the FIP Header. In the case of Secure Boot, ATF is compiled with HSE_SECBOOT=1, which configures the IVT header to set the entire FIP as an Application boot code. BootROM loads the entire FIP at the Load Address. The FIP_MEMORY_OFFSET must be set to have the same value as the Load Address, and it is computed as:

FIP_MEMORY_OFFSET = BL2_ENTRY - BL2_DTB_SIZE - FIP_TOC_HEADER_SIZE

To avoid manually computing FIP_MEMORY_OFFSET, it is possible to first compile without the FIP_MEMORY_OFFSET option, but with HSE_SECBOOT enabled (optionally, with DEBUG enabled, as well), to get the correct Load Address.

Since the FIP signature is stored in the FIP, space is reserved within it. As such, the fip.bin must be signed without the reserved space. First, determine how much of the FIP must be signed:

The relevant part of the FIP can be extracted and signed with the private key. In this example, the first 0x15E100 bytes of the FIP must be signed:

dd if=fip.bin of=tosign-fip.bin bs=1 count=printf "%d" 0x15e100 conv=notrunc openssl dgst -sha1 -sign rsa2048_private.pem -out fip-signature.bin tosign-fip.bin

fiptool update --align 16 --tb-fw-cert fip-signature.bin fip.bin

The public RSA key must be copied to the boot partition of the SD Card, next to the Linux Kernel Image and DTB file. fip.s32 and fip.bin must be written to the SD Card. fip.bin must be written at the address pointed to by the Application label in the compile log; in this example, the address is 0x5e440.

dd if=build/<board>/release/fip.s32 of=/dev/<sdcard_dev> seek=512 skip=512 \
iflag=skip_bytes oflag=seek_bytes conv=notrunc,fsync
dd if=build/<board>/release/fip.bin of=/dev/<sdcard_dev> seek=`printf "%d" 0x5e440` \
conv=notrunc,fsync

最后更新于