imx: hab: Use nxp_imx8mcst etype for i.MX8M flash.bin signing

Update documentation and use nxp_imx8mcst binman etype for signing
of flash.bin instead of previous horrible shell scripting.

Reviewed-by: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Marek Vasut <marex@denx.de>
This commit is contained in:
Marek Vasut
2024-05-21 12:48:26 +02:00
committed by Fabio Estevam
parent d415a48b40
commit 52dc74feab
4 changed files with 29 additions and 230 deletions

View File

@@ -1,92 +0,0 @@
#!/bin/sh
# 0) Generate keys
#
# WARNING: ECDSA keys are only supported by HAB 4.5 and newer (i.e. i.MX8M Plus)
#
# cd /path/to/cst-3.3.1/keys/
# ./hab4_pki_tree.sh -existing-ca n -use-ecc n -kl 4096 -duration 10 -num-srk 4 -srk-ca y
# cd /path/to/cst-3.3.1/crts/
# ../linux64/bin/srktool -h 4 -t SRK_1_2_3_4_table.bin -e SRK_1_2_3_4_fuse.bin -d sha256 -c ./SRK1_sha256_4096_65537_v3_ca_crt.pem,./SRK2_sha256_4096_65537_v3_ca_crt.pem,./SRK3_sha256_4096_65537_v3_ca_crt.pem,./SRK4_sha256_4096_65537_v3_ca_crt.pem -f 1
# 1) Build U-Boot (e.g. for i.MX8MM)
#
# cp -Lv /path/to/arm-trusted-firmware/build/imx8mm/release/bl31.bin .
# cp -Lv /path/to/firmware-imx-8.14/firmware/ddr/synopsys/ddr3* .
# make -j imx8mm_board_defconfig
# make -j`nproc` flash.bin
# 2) Sign SPL and DRAM blobs
cp doc/imx/habv4/csf_examples/mx8m/csf_spl.txt csf_spl.tmp
cp doc/imx/habv4/csf_examples/mx8m/csf_fit.txt csf_fit.tmp
# update File Paths from env vars
if ! [ -r $CSF_KEY ]; then
echo "Error: \$CSF_KEY not found"
exit 1
fi
if ! [ -r $IMG_KEY ]; then
echo "Error: \$IMG_KEY not found"
exit 1
fi
if ! [ -r $SRK_TABLE ]; then
echo "Error: \$SRK_TABLE not found"
exit 1
fi
sed -i "s:\$CSF_KEY:$CSF_KEY:" csf_spl.tmp
sed -i "s:\$IMG_KEY:$IMG_KEY:" csf_spl.tmp
sed -i "s:\$SRK_TABLE:$SRK_TABLE:" csf_spl.tmp
sed -i "s:\$CSF_KEY:$CSF_KEY:" csf_fit.tmp
sed -i "s:\$IMG_KEY:$IMG_KEY:" csf_fit.tmp
sed -i "s:\$SRK_TABLE:$SRK_TABLE:" csf_fit.tmp
# update SPL Blocks
spl_block_base=$(printf "0x%x" $(( $(sed -n "/CONFIG_SPL_TEXT_BASE=/ s@.*=@@p" .config) - 0x40)) )
spl_block_size=$(printf "0x%x" $(stat -tc %s u-boot-spl-ddr.bin))
sed -i "/Blocks = / s@.*@ Blocks = $spl_block_base 0x0 $spl_block_size \"flash.bin\"@" csf_spl.tmp
# Generate CSF blob
cst -i csf_spl.tmp -o csf_spl.bin
# Patch CSF blob into flash.bin
spl_csf_offset=$(xxd -s 24 -l 4 -e flash.bin | cut -d " " -f 2 | sed "s@^@0x@")
spl_bin_offset=$(xxd -s 4 -l 4 -e flash.bin | cut -d " " -f 2 | sed "s@^@0x@")
spl_dd_offset=$((${spl_csf_offset} - ${spl_bin_offset} + 0x40))
dd if=csf_spl.bin of=flash.bin bs=1 seek=${spl_dd_offset} conv=notrunc
# 3) Sign u-boot.itb
# fitImage
fit_block_base=$(printf "0x%x" $(sed -n "/CONFIG_SPL_LOAD_FIT_ADDRESS=/ s@.*=@@p" .config) )
fit_block_offset=$(printf "0x%s" $(fdtget -t x u-boot.dtb /binman/imx-boot/uboot offset))
fit_block_size=$(printf "0x%x" $(( ( ( $(stat -tc %s u-boot.itb) + 0x1000 - 0x1 ) & ~(0x1000 - 0x1)) + 0x20 )) )
sed -i "/Blocks = / s@.*@ Blocks = $fit_block_base $fit_block_offset $fit_block_size \"flash.bin\"@" csf_fit.tmp
# IVT
ivt_ptr_base=$(printf "%08x" ${fit_block_base} | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
ivt_block_base=$(printf "%08x" $(( ${fit_block_base} + ${fit_block_size} - 0x20 )) | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
csf_block_base=$(printf "%08x" $(( ${fit_block_base} + ${fit_block_size} )) | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
ivt_block_offset=$((${fit_block_offset} + ${fit_block_size} - 0x20))
csf_block_offset=$((${ivt_block_offset} + 0x20))
echo "0xd1002041 ${ivt_block_base} 0x00000000 0x00000000 0x00000000 ${ivt_block_base} ${csf_block_base} 0x00000000" | xxd -r -p > ivt.bin
dd if=ivt.bin of=flash.bin bs=1 seek=${ivt_block_offset} conv=notrunc
# Generate CSF blob
cst -i csf_fit.tmp -o csf_fit.bin
# When loading flash.bin via USB, we must ensure that the file being
# served is as large as the target expects (see
# board_spl_fit_size_align()), otherwise the target will hang in
# rom_api_download_image() waiting for the remaining bytes.
#
# Note that in order for dd to actually extend the file, one must not
# pass conv=notrunc here. With a non-zero seek= argument, dd is
# documented to preserve the contents of the file seeked past; in
# particular, dd does not open the file with O_TRUNC.
CSF_SIZE=$(sed -n "/CONFIG_CSF_SIZE=/ s@.*=@@p" .config)
dd if=/dev/null of=csf_fit.bin bs=1 seek=$((CSF_SIZE - 0x20)) count=0
# Patch CSF blob into flash.bin
dd if=csf_fit.bin of=flash.bin bs=1 seek=${csf_block_offset} conv=notrunc

View File

@@ -1,30 +0,0 @@
[Header]
Version = 4.3
Hash Algorithm = sha256
Engine = CAAM
Engine Configuration = 0
Certificate Format = X509
Signature Format = CMS
[Install SRK]
# SRK_TABLE is full path to SRK_1_2_3_4_table.bin
File = "$SRK_TABLE"
Source index = 0
[Install CSFK]
# CSF_KEY is full path to CSF1_1_sha256_4096_65537_v3_usr_crt.pem
File = "$CSF_KEY"
[Authenticate CSF]
[Install Key]
Verification index = 0
Target Index = 2
# IMG_KEY is full path to IMG1_1_sha256_4096_65537_v3_usr_crt.pem
File = "$IMG_KEY"
[Authenticate Data]
Verification index = 2
# FIXME:
# Line 1 -- fitImage
Blocks = CONFIG_SPL_LOAD_FIT_ADDRESS 0x57c00 0xffff "flash.bin"

View File

@@ -1,33 +0,0 @@
[Header]
Version = 4.3
Hash Algorithm = sha256
Engine = CAAM
Engine Configuration = 0
Certificate Format = X509
Signature Format = CMS
[Install SRK]
# SRK_TABLE is full path to SRK_1_2_3_4_table.bin
File = "$SRK_TABLE"
Source index = 0
[Install CSFK]
# CSF_KEY is full path to CSF1_1_sha256_4096_65537_v3_usr_crt.pem
File = "$CSF_KEY"
[Authenticate CSF]
[Unlock]
Engine = CAAM
Features = MID
[Install Key]
Verification index = 0
Target Index = 2
# IMG_KEY is full path to IMG1_1_sha256_4096_65537_v3_usr_crt.pem
File = "$IMG_KEY"
[Authenticate Data]
Verification index = 2
# FIXME: Adjust start (first column) and size (third column) here
Blocks = 0x7e0fc0 0x0 0x306f0 "flash.bin"

View File

@@ -121,6 +121,9 @@ build configuration:
- Defconfig:
CONFIG_IMX_HAB=y
CONFIG_FSL_CAAM=y
CONFIG_ARCH_MISC_INIT=y
CONFIG_SPL_CRYPTO=y
- Kconfig:
@@ -131,91 +134,42 @@ build configuration:
The CSF contains all the commands that the HAB 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.
to authenticate, which keys to install, use and etc. The CSF is generated
using the CST Code Signing Tool based on input configuration file. This tool
input configuration file is generated using binman, and the tool is invoked
from binman as well.
CSF examples are available under doc/imx/habv4/csf_examples/ directory.
The SPL and fitImage sections of the generated image are signed separately.
The signing is activated by wrapping SPL and fitImage sections into nxp-imx8mcst
etype, which is done automatically in arch/arm/dts/imx8m{m,n,p,q}-u-boot.dtsi
in case CONFIG_IMX_HAB Kconfig symbol is enabled.
CSF "Blocks" line for csf_spl.txt can be generated as follows:
Build of flash.bin target then produces a signed flash.bin automatically.
```
spl_block_base=$(printf "0x%x" $(( $(sed -n "/CONFIG_SPL_TEXT_BASE=/ s@.*=@@p" .config) - 0x40)) )
spl_block_size=$(printf "0x%x" $(stat -tc %s u-boot-spl-ddr.bin))
sed -i "/Blocks = / s@.*@ Blocks = $spl_block_base 0x0 $spl_block_size \"flash.bin\"@" csf_spl.txt
```
The nxp-imx8mcst etype is configurable using either DT properties or environment
variables. The following DT properties and environment variables are supported.
Note that environment variables override DT properties.
The resulting line looks as follows:
```
Blocks = 0x7e0fc0 0x0 0x306f0 "flash.bin"
```
+--------------------+-----------+------------------------------------------------------------------+
| DT property | Variable | Description |
+====================+===========+==================================================================+
| nxp,loader-address | | SPL base address |
+--------------------+-----------+------------------------------------------------------------------+
| nxp,srk-table | SRK_TABLE | full path to SRK_1_2_3_4_table.bin |
+--------------------+-----------+------------------------------------------------------------------+
| nxp,csf-crt | CSF_KEY | full path to the CSF Key CSF1_1_sha256_4096_65537_v3_usr_crt.pem |
+--------------------+-----------+------------------------------------------------------------------+
| nxp,img-crt | IMG_KEY | full path to the IMG Key IMG1_1_sha256_4096_65537_v3_usr_crt.pem |
+--------------------+-----------+------------------------------------------------------------------+
The columns mean:
- CONFIG_SPL_TEXT_BASE - 0x40 -- Start address of signed data, in DRAM
- 0x0 -- Start address of signed data, in "flash.bin"
- 0x306f0 -- Length of signed data, in "flash.bin"
- Filename -- "flash.bin"
To generate signature for the SPL part of flash.bin container, use CST:
```
cst -i csf_spl.tmp -o csf_spl.bin
```
The newly generated CST blob has to be patched into existing flash.bin
container. Conveniently, flash.bin IVT contains physical address of the
CSF blob. Remember, the SPL part of flash.bin container is loaded by the
BootROM at CONFIG_SPL_TEXT_BASE - 0x40 , so the offset of CSF blob in
the fitImage can be calculated and inserted into the flash.bin in the
correct location as follows:
```
# offset = IVT_HEADER[6 = CSF address] - CONFIG_SPL_TEXT_BASE - 0x40
spl_csf_offset=$(xxd -s 24 -l 4 -e flash.bin | cut -d " " -f 2 | sed "s@^@0x@")
spl_bin_offset=$(xxd -s 4 -l 4 -e flash.bin | cut -d " " -f 2 | sed "s@^@0x@")
spl_dd_offset=$((${spl_csf_offset} - ${spl_bin_offset} + 0x40))
dd if=csf_spl.bin of=flash.bin bs=1 seek=${spl_dd_offset} conv=notrunc
```
CSF "Blocks" line for csf_fit.txt can be generated as follows:
```
# fitImage
fit_block_base=$(printf "0x%x" $(sed -n "/CONFIG_SPL_LOAD_FIT_ADDRESS=/ s@.*=@@p" .config) )
fit_block_offset=$(printf "0x%s" $(fdtget -t x u-boot.dtb /binman/imx-boot/uboot offset))
fit_block_size=$(printf "0x%x" $(( ( ( $(stat -tc %s u-boot.itb) + 0x1000 - 0x1 ) & ~(0x1000 - 0x1)) + 0x20 )) )
sed -i "/Blocks = / s@.*@ Blocks = $fit_block_base $fit_block_offset $fit_block_size \"flash.bin\"@" csf_fit.tmp
```
The fitImage part of flash.bin requires separate IVT. Generate the IVT and
patch it into the correct aligned location of flash.bin as follows:
```
# IVT
ivt_ptr_base=$(printf "%08x" ${fit_block_base} | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
ivt_block_base=$(printf "%08x" $(( ${fit_block_base} + ${fit_block_size} - 0x20 )) | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
csf_block_base=$(printf "%08x" $(( ${fit_block_base} + ${fit_block_size} )) | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
ivt_block_offset=$((${fit_block_offset} + ${fit_block_size} - 0x20))
csf_block_offset=$((${ivt_block_offset} + 0x20))
echo "0xd1002041 ${ivt_block_base} 0x00000000 0x00000000 0x00000000 ${ivt_block_base} ${csf_block_base} 0x00000000" | xxd -r -p > ivt.bin
dd if=ivt.bin of=flash.bin bs=1 seek=${ivt_block_offset} conv=notrunc
```
To generate CSF signature for the fitImage part of flash.bin container, use CST:
```
cst -i csf_fit.tmp -o csf_fit.bin
```
Finally, patch the CSF signature into the fitImage right past the IVT:
```
dd if=csf_fit.bin of=flash.bin bs=1 seek=${csf_block_offset} conv=notrunc
```
The entire script is available in doc/imx/habv4/csf_examples/mx8m/csf.sh
and can be used as follows to modify flash.bin to be signed
(adjust paths as needed):
Environment variables can be set as follows to point the build process
to external key material:
```
export CST_DIR=/usr/src/cst-3.3.1/
export CSF_KEY=$CST_DIR/crts/CSF1_1_sha256_4096_65537_v3_usr_crt.pem
export IMG_KEY=$CST_DIR/crts/IMG1_1_sha256_4096_65537_v3_usr_crt.pem
export SRK_TABLE=$CST_DIR/crts/SRK_1_2_3_4_table.bin
export PATH=$CST_DIR/linux64/bin:$PATH
/bin/sh doc/imx/habv4/csf_examples/mx8m/csf.sh
make flash.bin
```
1.4 Closing the device