tag 标签: Secureboot

相关博文
  • 热度 1
    2024-9-18 17:48
    1137 次阅读|
    0 个评论
    By Toradex秦海 1).简介 嵌入式设备对于网络安全的要求越来越高,而 Secure boot就是其中重要的一部分。 TI AM62X处理器基于行业标准 X.509认证来提供 Secure boot启动过程中的 Chain of Trust; X.509认证是基于公共密钥加密 (Public Key Cryptography)和数字签名 (Digital Signature)技术来实现 Secure boot的。AM62X处理器涉及 Security的架构框图如下。 AM62X处理器启动流程图参考如下。本文就基于 TI AM625处理器平台简单介绍其 Secure Boot的部署流程。 本文所演示的平台来自于ToradexVerdinAM62嵌入式平台,主要介绍基本的 Chain of Trust,也就是 U-boot和Linux Kernel/DTB两个层级的加密和验证启动,后面 Rootfs以及 Application层面暂不涉及。 2.准备 a).Verdin AM62 ARM核心版配合Dahlia载板,并连接调试串口用于测试。 这里下载 Toradex Yocto Linux BSP6 Reference Image用于后续测试,目前最新的是 6.7.0版本。 3). 生成 Customer Key Set文件 a).TI AM62处理器有如下三种设备类型,其中 GP (General Purpose)类型的处理器是不具备支持 Secure Boot功能的,只有 HS (High Security)类型的处理器是支持的,然后其还细分为两个状态,HS-FS (Field Securable)和 HS-SE (Security Enforced),具体的说明请见如下。TI AM62X HS类型处理器出厂配置为 HS-FS状态,且都已经预先写入了 TI Dummy Key在设备中。 b).由于将 HS设备从 HS-FS状态配置为 HS-SE状态是不可逆的,因此本文为了方便演示流程仅仅使用 TI预置的 Dummy Key在 HS-FS状态下进行 Signed Image Authentication流程演示,但会将 Customer key的生成和烧录流程进行说明。 c).通过下面命令生成 Customer Root Key Set (SMPK)和 Customer Back-up Key Set (BMPK)文件,用于后续的 Boot Image签名以及烧录 Image生成。 -------------------------------- ### key name should not be changed ### $exportCustomer_KEYS_DIR= $ export SMPK_NAME=custMpk $ export BMPK_NAME=backMpk ###Create the SMPK key pair and certificate using RSA 4096### $ cd $Customer_KEYS_DIR $ openssl genrsa -F4 -out ${SMPK_NAME}.key 4096 $ cp ${SMPK_NAME}.key ${SMPK_NAME}.pem $ openssl req -batch -new -x509 -key ${SMPK_NAME}.key -out ${SMPK_NAME}.crt ###Create the BMPK key pair and certificate using RSA 4096### $ openssl genrsa -F4 -out ${BMPK_NAME}.key 4096 $ cp ${BMPK_NAME}.key ${BMPK_NAME}.pem $ openssl req -batch -new -x509 -key ${BMPK_NAME}.key -out ${BMPK_NAME}.crt ### Remove write access to the keys and certificates ### $ chmod a-w * -------------------------------- 4). Boot Image编译和签名 这里说明下载Toradex YoctoLinuxBSP 6.x.y版本包含 U-boot在内的编译 Boot Images所需要的全部源代码 -------------------------------- ###Get the U-Boot source codefor Yocto Linux BSP 6.x.y ### $ git clone -b toradex_ti-u-boot-2023.04 https://git.toradex.cn/u-boot-toradex.git $ export UBOOT_DIR=$(pwd)/u-boot-toradex ###Get the binary-only System Firmware (SYSFW)### $ git clone git://git.ti.com/k3-image-gen/k3-image-gen.git $ export K3_DIR=$(pwd)/k3-image-gen ###Get the TI Linux Firmware### $ git clone -b ti-linux-firmware git://git.ti.com/processor-firmware/ti-linux-firmware.git $ export TI_LINUX_FW_DIR=$(pwd)/ti-linux-firmware ###Get the ARM Trusted Firmware (ATF/TF-A)### $ git clone https://github.com/ARM-software/arm-trusted-firmware.git $ export TFA_DIR=$(pwd)/arm-trusted-firmware ###Get the OP-TEE image source code### $ git clone https://github.com/OP-TEE/optee_os.git $ export OPTEE_DIR=$(pwd)/optee_os ###Get the K3 Security development package:### $ git clone https://git.ti.com/git/security-development-tools/core-secdev-k3.git -b master $ export CORE_SECDEV_K3_DIR=$(pwd)/core-secdev-k3 -------------------------------- b).Customer Key Set需要部署在K3 Security development package和U-Boot source code如下位置,默认部署的是 TI Dummy Key,本文因为都是基于 TI Dummy Key进行测试,因此不做替换修改。 ./K3 Security development package -------------------------------- $ cd $CORE_SECDEV_K3_DIR/keys $ ls custMpk.crt custMpk.key custMpk.pem swrv.txt ti-degenerate-key.pem $ md5sum custMpk.key bd90ee9fe69667315eeee32bc7a01b39 custMpk.key $ md5sum custMpk.pem bd90ee9fe69667315eeee32bc7a01b39 custMpk.pem $ md5sum custMpk.crt f2a1562c002fc38319bf82471b0661a3 custMpk.crt ### replace TI Dummy Key with Customer Key if needed ### $ cp $Customer_KEYS_DIR/* $CORE_SECDEV_K3_DIR/keys -------------------------------- ./U-Boot source code -------------------------------- $ cd $UBOOT_DIR/board/ti/keys/ $ ls custMpk.crt custMpk.key custMpk.pem swrv.txt ti-degenerate-key.pem $ md5sum custMpk.key bd90ee9fe69667315eeee32bc7a01b39 custMpk.key $ md5sum custMpk.pem bd90ee9fe69667315eeee32bc7a01b39 custMpk.pem $ md5sum custMpk.crt f2a1562c002fc38319bf82471b0661a3 custMpk.crt ### replace TI Dummy Key with Customer Key if needed ### $ cp $Customer_KEYS_DIR/* $CORE_SECDEV_K3_DIR/keys -------------------------------- 这里配置交叉编译 toolchain,注意由于不同的固件需要对应 32bit或者 64bit toolchain编译器,因此这里两种 toolchain都需要配置,配置完成后参考如下命令 export 32bit/64bit toolchain相应的环境变量。 -------------------------------- ### 64bit toolchain env ### $ export ARCH=arm64 $ export DTC_FLAGS="-@" $ export PATH=~/gcc-linaro-aarch64/bin/:$PATH $ export CROSS_COMPILE=aarch64-none-linux-gnu- ### 32bit toolchain env ### $ export PATH=~/gcc-linaro-arm/bin/:$PATH -------------------------------- d).参考这里对 Boot Images进行编译 ./ Build ARM Trusted Firmware (ATF/TF-A) -------------------------------- $ cd $TFA_DIR $ export ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- $ unset TFA_EXTRA_ARGS $ make PLAT=k3 SPD=opteed $TFA_EXTRA_ARGS TARGET_BOARD=lite -------------------------------- ./ Build OP-TEE Image -------------------------------- $ cd $OPTEE_DIR $ export OPTEE_EXTRA_ARGS="CFG_WITH_SOFTWARE_PRNG=y" $ export ARCH=arm $ export CROSS_COMPILE=arm-none-linux-gnueabihf- $ export CROSS_COMPILE64=aarch64-none-linux-gnu- $ make PLATFORM=k3-am62x CFG_ARM64_core=y $OPTEE_EXTRA_ARGS -------------------------------- ./ Build U-Boot for R5 -------------------------------- ### Step-1 under U-boot directory ### $ cd $UBOOT_DIR $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- verdin-am62_r5_defconfig $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- BINMAN_INDIRS=$TI_LINUX_FW_DIR ### Step-2 under System Firmware directory ### $ cd $K3_DIR $ make SOC=am62x SOC_TYPE="hs-fs" TI_SECURE_DEV_PKG=$CORE_SECDEV_K3_DIR SBL=$UBOOT_DIR/spl/u-boot-spl.bin SYSFW_DIR=$TI_LINUX_FW_DIR/ti-sysfw $ cp tiboot3-am62x-hs-fs-evm.bin ../tiboot3-am62x-hs-fs-verdin.bin -------------------------------- //对应不同的 SOC_TYPE选项,会生成不同的 Binary Image,其对应关系参考如下两个表格,在出厂默认的 HS-FS SoC Type下,需要编译HS-FS对应的固件;而一旦通过 TI OTP Keywriter工具将 Customer Key写入 eFUSE并将设备配置为 HS-SE状态后,就需要编译 HS-SE SOC Type对应的固件才能正常启动了。 ./ Build U-Boot for A53 -------------------------------- ### Default configuration ### $ cd $UBOOT_DIR $ export ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- $ make verdin-am62_a53_defconfig ### Customized configuration to force FIT image to be authenticated ### $ make menuconfig CONFIG_FIT_SIGNATURE_ENFORCE=y ### Compile ### $ make BINMAN_INDIRS=$TI_LINUX_FW_DIR \ BL31=$TFA_DIR/build/k3/lite/release/bl31.bin \ TEE=$OPTEE_DIR/out/arm-plat-k3/core/tee-raw.bin $ cp tispl.bin ../ $ cp u-boot.img ../ -------------------------------- 5). 签名 Linux kernel FIT Image a).此步骤为可选步骤,如果不需要强制 FIT Image Authentication则在上面 4.d Build U-Boot for A53步骤中可以不使能CONFIG_FIT_SIGNATURE_ENFORCE配置,然后跳过此章节直接进行 BSP Image修改部署章节即可。 b).解压 Toradex Ycoto Linux BSP6 Image,获得 LInux Kernel/DTB/DTBO等文件 -------------------------------- ### uncompress BSP Image package ### $ tar xvf Verdin-AM62_Reference-Minimal-Image-Tezi_6.7.0+build.13.tar $ cd Verdin-AM62_Reference-Minimal-Image-Tezi_6.7.0+build.13/ ### uncompress boot filesystem ### $ mkdir bootfs/ $ tarJxfReference-Minimal-Image-verdin-am62.bootfs.tar.xz -C bootfs/ ### copy kernel/dtb/dtbo image fit image work folder ### $ export FIT_IMAGE_DIR= $ cd bootfs/ $cp -r * $FIT_IMAGE_DIR -------------------------------- c).修改 FIT Image描述文件,一个示例说明部分如下,需要根据你实际存放 Linux Kernel/DTB/DTBO文件的位置来修改文件“data”参数本文使用的完整描述文件模板请从这里下载。 ./ fitImage-its--6.1.83+git0+0a32d33d5f-r0-verdin-am62-20240701094251.its -------------------------------- /dts-v1/; / { description = "Kernel fitImage for TDX Wayland with XWayland/6.1.83+gitAUTOINC+0a32d33d5f/verdin-am62"; #address-cells = ; images { kernel-1 { description = "Linux kernel"; data = /incbin/("$FIT_IMAGE_DIR/Image.gz"); type = "kernel"; arch = "arm64"; os = "linux"; compression = "gzip"; load = ; entry = ; hash-1 { algo = "sha512"; }; }; fdt-ti_k3-am625-verdin-nonwifi-dahlia.dtb { description = "Flattened Device Tree blob"; data = /incbin/("$FIT_IMAGE_DIR/k3-am625-verdin-nonwifi-dahlia.dtb"); type = "flat_dt"; arch = "arm64"; compression = "none"; load = ; hash-1 { algo = "sha512"; }; }; ... ... -------------------------------- d).生成 FIT Image ./由于在生成 FIT Image的时候需要同时将 Public Key信息嵌入到 u-boot.dtb,因此这里需要找到 U-Boot默认的 dtb文件。根据 U-Boot编译 default configuration来确认默认的 dtb文件即为 "arch/arm/dts/k3-am625-verdin-wifi-dev.dtb" -------------------------------- $vi $UBOOT_DIR/configs/verdin-am62_a53_defconfig ... CONFIG_DEFAULT_DEVICE_TREE="k3-am625-verdin-wifi-dev" ... -------------------------------- ./在 FIT Image work folder通过下面命令生成签名的 FIT Image -------------------------------- $ mkimage -f fitImage-its--6.1.83+git0+0a32d33d5f-r0-verdin-am62-20240701094251.its -k $UBOOT_DIR/board/ti/keys -K $UBOOT_DIR/arch/arm/dts/k3-am625-verdin-wifi-dev.dtb -r fitImage -------------------------------- e).根据 4.d Build U-Boot for A53步骤,不修改任何 configuration的情况下,重新编译 U-Boot Image -------------------------------- $ cd $UBOOT_DIR ### Compile ### $ make BINMAN_INDIRS=$TI_LINUX_FW_DIR \ BL31=$TFA_DIR/build/k3/lite/release/bl31.bin \ TEE=$OPTEE_DIR/out/arm-plat-k3/core/tee-raw.bin $ cp tispl.bin ../ $ cp u-boot.img ../ -------------------------------- 6 ). 修改和部署 Yocto Linux BSP a).使用 4.d Build U-Boot for R5步骤生成的“tiboot3-am62x-hs-fs-verdin.bin”文件和 5.e步骤重新编译生成的“tispl.bin”和“u-boot.img”文件修改 Yocto Linux BSP对应的 Boot Images文件 -------------------------------- $ cdVerdin-AM62_Reference-Minimal-Image-Tezi_6.7.0+build.13/ $ rm tiboot3-am62x-hs-fs-verdin.bin tispl.bin u-boot.img $ cp .../tiboot3-am62x-hs-fs-verdin.bin . $ cp .../tispl.bin . $ cp .../u-boot.img . -------------------------------- b).将 5.d步骤生成的 FIT Image部署到刚才解压的Ycoto Linux BSP6 bootfs中,并重新创建bootfs压缩包 -------------------------------- ### copy FIT image to bsp rootfs folder ### $ cp$$FIT_IMAGE_DIR/fitImage.../Verdin-AM62_Reference-Minimal-Image-Tezi_6.7.0+build.13/bootfs/ ### remove default Linux kernel/dtb/dtbo files ### $ cd .../Verdin-AM62_Reference-Minimal-Image-Tezi_6.7.0+build.13/bootfs/ $ rm -rf Image.gz k3-am625-verdin-* overlays ### check bootfs files ### $ tree -L 1 . ├── boot.scr ├── fitImage └── overlays.txt ### compress new bootfs package ### $ tar Jcf ../Reference-Minimal-Image-verdin-am62.bootfs.tar.xz* ### clear bootfs $ cd .. $ rm -rf bootfs/ -------------------------------- c).修改BSP package中的“u-boot-initial-env-sd”文件,增加如下环境变量用于使能 U-Boot加载 FIT Image来启动 -------------------------------- ---a/u-boot-initial-env-sd2024-07-01 18:00:22.000000000 +0800 +++b/u-boot-initial-env-sd2024-09-12 16:35:02.000000000 +0800 @@ -30,6 +30,7 @@ kernel_addr_r=0x88200000 kernel_comp_addr_r=0x80200000 kernel_comp_size=0x08000000 +kernel_image=fitImage load_efi_dtb=load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${prefix}${efi_fdtfile} loadaddr=0x88200000 mmc_boot=if mmc dev ${devnum}; then devtype=mmc; run scan_dev_for_boot_part; fi -------------------------------- d).需要注意的是由于Kernel阶段的Secure Boot相关认证和加载都是基于U-Boot环境变量来实现的, 因此如果要让这个启动机制更加安全可靠,则要让U-Boot保持在上述安全启动路径,而不能通过其他启动介质或者脚本来启动而绕开 Secure Boot,比如 Toradex U-Boot默认是使能 Distro Boot功能的,可以自动扫描外设介质的启动脚本,那么这个功能就需要关闭掉,类似这样的 U-Boot定制化和启动路径固化可以参考如下文章,本文不做进一步介绍。 https://developer.toradex.cn/torizon/security/u-boot-hardening-for-secure-boot/ e).如果你的 Linux BSP Image是通过 Yocto Project编译生成,那么如下是一个 Toradex Security Meta Layer,你可以直接将其集成到你的 Yocto Project编译环境中,然后按照说明配置后直接生成签名甚至加密好的 BSP Image。 https://github.com/toradex/meta-toradex-security 7 ).部署 测试 a).参考这里将上述制作完成数字签名的 BSP Image通过 Toradex Easy Installer更新到 Verdin AM62模块。因为本文测试基于 TI已经预先烧写到 SoC的 dummy key,所以可以直接启动测试,如果是使用 Customized Key,则还需要参考后续 eFuse烧写操作将 Customized Key烧写到 SoC才能正确验证并启动。 ./启动后查看启动log,可以看到 Boot Images和 Linux FIT Image (Kernel Image/DTB/DTBO) Secure Boot验证签名成功并最终完整启动 -------------------------------- U-Boot SPL 2023.04-28170-gc997b1b09fb (Sep 10 2024 - 17:41:33 +0800) SYSFW ABI: 4.0 (firmware rev 0x000a '10.0.8--v10.00.08 (Fiery Fox)') Changed A53 CPU frequency to 1250000000Hz (T grade) in DT SPL initial stack usage: 13472 bytes Trying to boot from MMC1 Authentication passed // ATF authentication Authentication passed // TEE authentication Authentication passed // DM-FW authentication Loading Environment from nowhere... OK init_env from device 9 not supported! Authentication passed // A53 SPL authentication Authentication passed // A53 SPL DTB authentication Starting ATF on ARM64 core... NOTICE: BL31: v2.11.0(release):v2.10.0-1555-g8e9bdc5b1 NOTICE: BL31: Built : 17:04:05, Aug 30 2024 ... U-Boot SPL 2023.04-28170-gc997b1b09fb (Sep 12 2024 - 16:56:27 +0800) SYSFW ABI: 4.0 (firmware rev 0x000a '10.0.8--v10.00.08 (Fiery Fox)') SPL initial stack usage: 1904 bytes Trying to boot from MMC1 Authentication passed // A53 u-boot authentication Authentication passed // A53 u-boot DTB authentication U-Boot 2023.04-28170-gc997b1b09fb (Sep 12 2024 - 16:56:27 +0800) SoC: AM62X SR1.0 HS-FS DRAM: 1 GiB Core: 143 devices, 31 uclasses, devicetree: separate ... Found U-Boot script /boot.scr 6003 bytes read in 10 ms (585.9 KiB/s) ## Executing script at 90280000 82 bytes read in 9 ms (8.8 KiB/s) 8918270 bytes read in 78 ms (109 MiB/s) Bootargs: root=PARTUUID=33e36968-02 ro rootwait console=tty1 console=ttyS2,115200 consol0 ## Loading kernel from FIT Image at 90300000 ... Using 'conf-ti_k3-am625-verdin-wifi-dev.dtb' configuration Verifying Hash Integrity ... sha512,rsa4096:custMpk+ OK // Kernel Image authentication Trying 'kernel-1' kernel subimage Description: Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x90300108 Data Size: 8305029 Bytes = 7.9 MiB Architecture: AArch64 OS: Linux Load Address: 0x80200000 Entry Point: 0x80200000 Hash algo: sha512 Hash value: 1eae3ec7c7d250d709d07f8af174e8de9c2293a9a61683f1f1a4f5981e96dc9ab090cc Verifying Hash Integrity ... sha512+ OK ## Loading fdt from FIT Image at 90300000 ... Using 'conf-ti_k3-am625-verdin-wifi-dev.dtb' configuration Verifying Hash Integrity ... sha512,rsa4096:custMpk+ OK // Kernel DTB authentication Trying 'fdt-ti_k3-am625-verdin-wifi-dev.dtb' fdt subimage ... Verifying Hash Integrity ... sha512+ OK Loading fdt from 0x90b40bd0 to 0x83000000 ## Loading fdt from FIT Image at 90300000 ... Using 'conf-verdin-am62_dsi-to-hdmi_overlay.dtbo' configuration Verifying Hash Integrity ... sha512,rsa4096:custMpk+ OK // DTBO authentication Trying 'fdt-verdin-am62_dsi-to-hdmi_overlay.dtbo' fdt subimage ... Verifying Hash Integrity ... sha512+ OK ## Loading fdt from FIT Image at 90300000 ... Using 'conf-verdin-am62_spidev_overlay.dtbo' configuration Verifying Hash Integrity ... sha512,rsa4096:custMpk+ OK // DTBO authentication Trying 'fdt-verdin-am62_spidev_overlay.dtbo' fdt subimage ... Verifying Hash Integrity ... sha512+ OK Booting using the fdt blob at 0x83000000 Working FDT set to 83000000 Uncompressing Kernel Image Loading Device Tree to 0000000098ec8000, end 0000000098edc6b5 ... OK Working FDT set to 98ec8000 Starting kernel ... Booting Linux on physical CPU 0x0000000000 Linux version 6.1.83-6.7.0+git.0a32d33d5fb7 (oe-user@oe-host) (aarch64-td4 Machine model: Toradex Verdin AM62 WB on Verdin Development Board ... -------------------------------- b). AM62x SoC eFuse烧写以及将设备从 HS-FS转换为 HS-SE状态 ./ eFuse烧写流程详细烧写流程可以参考这里。 ./首先下载安装最新 TI MCU+ SDK,以及对应版本的 CCS和 sysconfig工具到 Linux开发主机 (推荐为 ${HOME}/ti/ )目录,详细过程参考上面的文章链接。 ./安装 TI OTP Keywriter工具软件和使用指南,这些是 secure资料,需要在 TI网站上面注册申请通过后才能获取。安装路径为 /mcu_plus_sdk_am62x_10_00_00_14/source/security。OTP Keywriter的详细使用指南文档是 AM62X_OTP_Keywriter_User_Guide。 -------------------------------- $ tree -L 2 ~/ti/mcu_plus_sdk_am62x_10_00_00_14/source/security/ /home/simon/ti/mcu_plus_sdk_am62x_10_00_00_14/source/security/ ├── sbl_keywriter │├── am62x-sk │├── boardcfgs │├── keywr_bin │├── manifest │├── scripts │└── tools ├── uninstall └── uninstall.dat -------------------------------- ./生成 X.509 Certificate // Keywriter预置 TI dummy key,因此如果是基于 TI dummy key set进行生成,则命令如下。注意“--keyrev”参数,只要这个参数被烧写到了 eFuse上面,那么这个设备就立即转化为 HS-SE状态,所有 secure boot限制将都生效,设备也无法再次刷写其他 key信息,因此此过程可以分步或者一次进行,前期测试阶段建议分步,先烧写 key,进行验证通过后,再进行 keyrev烧写,将设备变更为 HS-SE状态。 -------------------------------- ### Generate X.509 certificate ### ### Option-1, step by step $ cd /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/scripts/cert_gen/am62x ## Generate certificate for programming MSV(Model Specific Value) and TI dummy key sets, but not turn device into HS-SE $ ./gen_keywr_cert.sh -t tifek/ti_fek_public.pem --msv 0xC0FFE -b-def --bmek-def -s-def --smek-def --keycnt 2 ## Generates certificate for setting the program key revision to 1 ./gen_keywr_cert.sh -t tifek/ti_fek_public.pem --keyrev 1 ### Option-2, one-shot ## programming MSV, key sets, and turn device into HS-SE in one shot command $ ./gen_keywr_cert.sh -t tifek/ti_fek_public.pem --msv 0xC0FFE -b-def --bmek-def -s-def --smek-def --keycnt 2 --keyrev 1 ### Convert certificate binary to .h format ### $ cd /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/scripts/x509cert $ python3 ../../../../../tools/bin2c/bin2c.py final_certificate.bin keycert.h KEYCERT 2024 -------------------------------- //如果是基于 customized key set,则要将相关命令修改如下: -------------------------------- ### Copy customized key set for keywriter ### $ cd /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/scripts/cert_gen/am62x $ cp $Customer_KEYS_DIR/custMpk.key keys_devel/smek.key $ cp $Customer_KEYS_DIR/custMpk.pem keys_devel/smpk.pem $ cp $Customer_KEYS_DIR/backMpk.key keys_devel/bmek.key $ cp $Customer_KEYS_DIR/backMpk.pem keys_devel/bmpk.pem ### Generate X.509 certificate ### ### Option-1, step by step $ cd /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/scripts/cert_gen/am62x ## Generate certificate for programming MSV(Model Specific Value) and TI dummy key sets, but not turn device into HS-SE $ ./gen_keywr_cert.sh -t tifek/ti_fek_public.pem --msv 0xC0FFE -b keys_devel/bmpk.pem --bmek keys_devel/bmek.key -s keys_devel/smpk.pem --smek keys_devel/smek.key --keycnt 2 ## Generates certificate for setting the program key revision to 1 ./gen_keywr_cert.sh -t tifek/ti_fek_public.pem --keyrev 1 ### Option-2, one-shot ## programming MSV, key sets, and turn device into HS-SE in one shot command $ ./gen_keywr_cert.sh -t tifek/ti_fek_public.pem --msv 0xC0FFE -b keys_devel/bmpk.pem --bmek keys_devel/bmek.key -s keys_devel/smpk.pem --smek keys_devel/smek.key --keycnt 2 --keyrev 1 ### Convert certificate binary to .h format ### $ cd /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/scripts/x509cert $ python3 ../../../../../tools/bin2c/bin2c.py final_certificate.bin keycert.h KEYCERT 2024 -------------------------------- ./生成 keywriter binary - tiboot3.bin -------------------------------- ###createcompiler softlink### $ cd $ ln -s ccs1271/ccs/tools/compiler/ti-cgt-armllvm_3.2.2.LTS ti-cgt-armllvm_3.2.2.LTS ###Generate binary### $ cd /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/am62x-sk/r5fss0-0_nortos/ti-arm-clang $ make -sj clean PROFILE=debug $ make -sj PROFILE=debug -------------------------------- ./将 tiboot3.bin通过 USB DFU模式加载运行起来,具体的命令可以参考这里,只是需要注意的是由于烧写 eFuse的过程中还需要 AM62X SoC VPP管脚上拉到 1.8V同时具备至少 400mA瞬态电流负载能力,因此需要在载板上面部署相应的硬件设计,以保证仅在烧写 eFuse的时候拉高 VPP管脚同时提供足够的瞬变电流,而在其他任何时候 VPP管脚都是拉低的状态。参考如下 TI AM62 SK开发板设计,如图一布置了一个单独的 LDO电源芯片(TLV75518PDQNR)来给 VPP管脚提供 400mA/1.8V供电,正式由于极高的瞬变电流负载需求,load switch或者 DC/DC电源是不建议使用的;而 LDO的开关则通过 VPP_LDO_EN信号来控制。如图二,则是 AM62X SoC通过 I2C总线连接了一个 GPIO Expander芯片来扩展 GPIO管脚提供 VPP_LDO_EN信号控制。 //对于 IO Expander VPP_LDO_EN GPIO管脚的控制软件代码请参考 MCU+ SDK如下文件,你也可以根据你的实际载板设计来相应修改适配。 /mcu_plus_sdk_am62x_10_00_00_14/source/security/sbl_keywriter/am62x-sk/r5fss0-0_nortos/board.c 8 ).总结 本文基于 TI AM62X处理器简单演示了 Secure Boot流程,涉及 Boot Images和 Linux Kernel/DTB,至于 Rootfs的加密,则需要配置类似 Squashfs只读文件系统配合 Initramfs RAM Disk镜像进行加解密挂载启动,可以结合参考如下两篇文章和相关 meta-toradex-security layer数据参考,本文不做具体测试。 ./嵌入式 ARM 平台使用dm-crypt加密磁盘分区 ./使用Squashfs和Overlayfs提高嵌入式Linux文件系统可靠性 ./https://github.com/toradex/meta-toradex-security ​
  • 热度 4
    2024-4-25 16:35
    923 次阅读|
    0 个评论
    By Toradex秦海 1).简介 嵌入式设备对于网络安全的要求越来越高,而Secure boot就是其中重要的一部分。NXP i.MX8MM/i.MX8MP处理器基于HABv4特性来提供Secure boot启动过程中的Chain of Trust;HABv4是基于公共密钥加密(Public Key Cryptography)和数字签名(Digital Signature)技术来实现Secure boot的,一个简单的流程图参考如下。本文就基于NXP i.MX8M Mini处理器平台测试部署Secure boot功能。 本文所演示的平台来自于ToradexVerdini.MX8MM嵌入式平台,主要测试基本的Chain of Trust,也就是U-boot和Linux Kernel两个层级的加密和验证启动,后面Rootfs以及Application层面暂不涉及。 2.准备 a).Verdin i.MX8MM ARM核心版配合Dahlia载板,并连接调试串口用于测试。 这里下载Toradex Yocto Linux BSP6 Reference Image用于后续测试,目前最新的是6.6.0版本。 3). 生成PKI Tree文件 a).从NXP官方网站下载Code Signing Tools软件包(需注册),目前最新版本是3.4.0版本,然后解压后使用预设的脚本生成Public Key Infrastructure (PKI) tree,用于后面签名U-boot/Linux Kernel Image文件 -------------------------------- $ tree -L 1 cst-3.4.0/ cst-3.4.0/ ├──add-ons ├──BUILD.md ├──ca ├──code ├──crts ├──Dockerfile ├──Dockerfile.hsm ├──docs ├──keys ├──LICENSE.bsd3 ├──LICENSE.hidapi ├──LICENSE.openssl ├──linux32 ├──linux64 ├──Makefile ├──mingw32 ├──Release_Notes.txt └──Software_Content_Register_CST.txt -------------------------------- b).生成PKI TREE ./首先创建serial和key_pass.txt文件 -------------------------------- $ cd .../cst-3.4.0/keys ### create serial number for OpenSSL certification ### $viserial 1234567C ### create key_pass for protection of private keys $vikey_pass.txt Toradex123! Toradex123! -------------------------------- ./运行CST工具预制脚本通过交互方式生成PKI TREE,这里生成一个2048bit RSA key SRK PKI TREE示例,更多可以参考如下U-Boot源代码中的文档说明 https://git.toradex.cn/cgit/u-boot-toradex.git/tree/doc/imx/habv4/introduction_habv4.txt?h=toradex_imx_lf_v2022.04 -------------------------------- ### generate PKI TREE ### $ ./hab4_pki_tree.sh ... Do you want to use an existing CA key (y/n)?: n Key type options (confirm targeted device supports desired key type): Select the key type (possible values: rsa, rsa-pss, ecc)?: rsa Enter key length in bits for PKI tree: 2048 Enter PKI tree duration (years): 10 How many Super Root Keys should be generated? 1 Do you want the SRK certificates to have the CA flag set? (y/n)?:y ... ### check generated SRK keys ### $ ls SRK* SRK1_sha256_2048_65537_v3_ca_key.der SRK1_sha256_2048_65537_v3_ca_key.pem ### generate HABv4 SRK Table和Efuse Hash ### $ cd ../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_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 Number of certificates = 1 SRK table binary filename = SRK_1_2_3_4_table.bin SRK Fuse binary filename = SRK_1_2_3_4_fuse.bin SRK Fuse binary dump: SRK HASH = 0x3D06A4A9 SRK HASH = 0x4BC55D12 SRK HASH = 0xA5F45E7F SRK HASH = 0x1F1F68FC SRK HASH = 0x3B9B4AE8 SRK HASH = 0xFC658293 SRK HASH = 0x40A706C9 SRK HASH = 0x94A9139E ### check SRK Table and Efuse Hash ### $ ls SRK_* SRK_1_2_3_4_fuse.bin SRK_1_2_3_4_table.bin -------------------------------- c).上面最后生成的两个文件就是我们后面签名和fuse设备需要用到的,”SRK_1_2_3_4_table.bin”文件是SRK Table,用于签名Container Image;”SRK_1_2_3_4_fuse.bin”文件是Efuse Hash,用于fuse到Verdin i.MX8MM设备的eFuse。更多CST工具使用说明可以参考如下CST User Guide文档 cst-3.4.0/docs/CST_UG.pdf 4). Boot Container配置和签名 a).参考这里说明下载Toradex YoctoLinuxBSP 6.x.y版本U-boot源代码,默认配置并未使能HABv4功能支持,需要在config中使能如下选项,当前Verdin i.MX8MM使用的Downstream U-boot版本2022.04还需要一个patch来保证开启HABv4后SPL启动成功,修改完成后重新编译U-Boot文件。 ./ U-boot配置修改 -------------------------------- ### add HAB and related crypto driver support ### →ARM architecture Support i.MX HAB features →SPL / TPL Support crypto drivers Start-up hooks Call arch-specific init after relocation, when console is ready ### remove some modules to reduce SPL size ### →SPL / TPL Suppport USB Gadget drivers Hashing Support Enable SHA1 support in SPL -------------------------------- ./ Patch文件 -------------------------------- --- a/board/toradex/verdin-imx8mm/spl.c +++ b/board/toradex/verdin-imx8mm/spl.c @@ -59,7 +59,7 @@ void spl_board_init(void) ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev); if (ret) name, ret); + printf("Failed to initialize caam_jr(FSL_CAAM) : %d\n", ret); } } -------------------------------- b).参考如下文档,使用编译生成的U-Boot相关文件打包生成Verdin iMX8MM Boot Container Image文件”flash.bin” https://developer.toradex.cn/linux-bsp/os-development/build-u-boot-and-linux-kernel-from-source-code/build-u-boot/build-u-boot-for-nxp-imx8m-mini-plus-modules/ ./ imx-mkimage工具生成Boot container image的一些打印参数需要保留后面生成csf文件时候需要 -------------------------------- ### generate boot container image flash.bin ### $ make clean; make SOC=iMX8MM V=1 dtbs=fsl-imx8mp-evk.dtb flash_evk_emmc_fastboot ... ... ========= OFFSET dump ========= Loader IMAGE: header_image_off0x0 dcd_off0x0 image_off0x40 csf_off0x35c00 spl hab block:0x7e0fc0 0x0 0x35c00 Second Loader IMAGE: sld_header_off0x5fc00 sld_csf_off0x60c20 sld hab block:0x401fcdc0 0x5fc00 0x1020 -------------------------------- ##spl hab block: includes IVT (SPL) + u-boot-spl-ddr.bin ##sld hab block: includes FDT (FIT header) + IVT (FIT) ##csf_off:CSF SPL binary offset ##sld_csf_off:CSF FIT binary offset ### print fit image hab infomation ### ## changePRINT_FIT_HAB_OFFSET=0x60000if using“flash_evk”as target in flash.bin generation such as for i.MX8MP SoC ## $ make SOC=iMX8MM V=1 dtbs=fsl-imx8mp-evk.dtb PRINT_FIT_HAB_OFFSET=0x68000 print_fit_hab ... TEE_LOAD_ADDR=0xbe000000 ATF_LOAD_ADDR=0x00920000 VERSION=v1 ../iMX8M/print_fit_hab.sh 0x68000 evk.dtb 0x40200000 0x62C00 0xBC468 0x402BC468 0x11F068 0xE538 0x920000 0x12D5A0 0xA0D0 ## above 3 lines stands for address/offset of: ##u-boot-nodtb.bin ##u-boot.dtb ##bl31.bin (ARM Trusted Firmware) -------------------------------- c).此时先将上一步骤生成的“flash.bin”文件重命名为“imx-boot”,然后通过这里的说明通过Toradex Easy Installer更新到Verdin i.MX8MM模块并启动查看HAB功能使能情况。 ./ SPL启动log,由于boot container image没有完成签名,因此会提示“CSF header command not found”。 -------------------------------- U-Boot SPL 2022.04-21749-g3428b47019-dirty (Apr 22 2024 - 17:52:20 +0800) ... Authenticate image from DDR location 0x401fcdc0... Error: CSF header command not found ... -------------------------------- ./ U-boot命令行下查看HAB状态,目前会有4个HAB Event错误。从Event2的地址来看正好是SPL IVT的地址,也印证了因为没有签名从SPL加载就验证出错了。 -------------------------------- Verdin iMX8MM # hab_status Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 --------- HAB Event 1 ----------------- event data: 0xdb 0x00 0x08 0x43 0x33 0x11 0xcf 0x00 ... --------- HAB Event 2 ----------------- event data: 0xdb 0x00 0x14 0x43 0x33 0x0c 0xa0 0x00 0x00 0x00 0x00 0x00 0x000x7e 0x0f 0xc0 0x00 0x00 0x000x20 ... --------- HAB Event 3 ----------------- ... --------- HAB Event 4 ----------------- ... -------------------------------- d).通过CST工具对上一步骤使用imx-mkimage生成的Boot Container Image“flash.bin”文件进行签名 ./首先生成csf_spl.txt文件 -------------------------------- ### copy csf_spl.txt template to CST tool containing folder ### $ cp u-boot-toradex/doc/imx/habv4/csf_examples/mx8m/csf_spl.txt.../cst-3.4.0/ ### modifycsf_spl.txt“Authenticate data”item according to 4.b chapterspl hab blockfield value ### ---a/csf_spl.txt2024-04-16 17:51:40.087230224 +0800 +++b/csf_spl.txt2024-04-23 12:17:38.322221868 +0800 @@ -8,12 +8,12 @@ # Index of the key location in the SRK table to be installed - File = "../crts/SRK_1_2_3_4_table.bin" + File = "./crts/SRK_1_2_3_4_table.bin" Source index = 0 # Key used to authenticate the CSF data - File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" + File = "./crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" @@ -28,10 +28,10 @@ # Target key slot in HAB key store where key will be installed Target index = 2 # Key to install - File = "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" + File = "./crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" # Key slot index used to authenticate the image data Verification index = 2 # Authenticate Start Address, Offset, Length and file - Blocks = 0x7e0fc0 0x1a000 0x2a600 "flash.bin" + Blocks =0x7e0fc0 0x0 0x35c00"flash.bin" -------------------------------- ./然后生成csf_fit.txt文件 -------------------------------- ### copy csf_fit.txt template to CST tool containing folder ### $ cp u-boot-toradex/doc/imx/habv4/csf_examples/mx8m/csf_fit.txt.../cst-3.4.0/ ### modifycsf_fit.txt“Authenticate data”item according to 4.b chaptersld hab blockfield value andprint_fit_haboutput information ### ---a/csf_fit.txt.bak2024-04-23 12:24:07.177249415 +0800 +++b/csf_fit.txt2024-04-23 12:40:15.342934544 +0800 @@ -8,12 +8,12 @@ # Index of the key location in the SRK table to be installed - File = "../crts/SRK_1_2_3_4_table.bin" + File = "./crts/SRK_1_2_3_4_table.bin" Source index = 0 # Key used to authenticate the CSF data - File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" + File = "./crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" @@ -23,14 +23,13 @@ # Target key slot in HAB key store where key will be installed Target index = 2 # Key to install - File = "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" + File = "./crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" # Key slot index used to authenticate the image data Verification index = 2 # Authenticate Start Address, Offset, Length and file - Blocks = 0x401fcdc0 0x057c00 0x01020 "flash.bin", \ - 0x40200000 0x05CC00 0x9AAC8 "flash.bin", \ - 0x00910000 0x0F76C8 0x09139 "flash.bin", \ - 0xFE000000 0x100804 0x4D268 "flash.bin", \ - 0x4029AAC8 0x14DA6C 0x06DCF "flash.bin" + Blocks =0x401fcdc0 0x5fc00 0x1020"flash.bin", \ + 0x40200000 0x62C00 0xBC468"flash.bin", \ + 0x402BC468 0x11F068 0xE538"flash.bin", \ + 0x920000 0x12D5A0 0xA0D0"flash.bin" -------------------------------- ./创建SPL CSF和FIT CSF binary文件 -------------------------------- ### copy boot container image file to CST tool containing folder ### $ cp .../imx-mkimage/iMX8M/flash.bin .../cst-3.4.0/ ### create SPL CSF binary ### $ cd.../cst-3.4.0/ $ ./linux64/bin/cst -i csf_spl.txt -o csf_spl.bin CSF Processed successfully and signed data available in csf_spl.bin ### create FIT CSF binary ### $ ./linux64/bin/cst -i csf_fit.txt -o csf_fit.bin CSF Processed successfully and signed data available in csf_fit.bin -------------------------------- ./组装CSF binary到flash.bin binary以生成签名后的Boot container image -------------------------------- $ cd.../cst-3.4.0/ ###Create a flash.bin copy### $ cp flash.bin signed_flash.bin ###Insert csf_spl.bin in signed_flash.binatoffsetfrom 4.b chaptercsf_offfield value ### $ dd if=csf_spl.bin of=signed_flash.bin seek=$((0x35c00)) bs=1 conv=notrunc ###Insert csf_fit.bin in signed_flash.binatoffsetfrom 4.b chaptersld_csf_offfield value ### $ dd if=csf_fit.bin of=signed_flash.bin seek=$((0x60c20)) bs=1 conv=notrunc -------------------------------- e).烧写SRK Hash ./签名的Boot Container Image文件要通过i.MX8MM SOC SRK_HASH fuses烧写的SRK Hash进行校验 ./烧录的SRK HASH即3.b章节SRK Fuse binary dumpfield value,也可以通过如下命令重新导出SRK HASH fuse对应数值 -------------------------------- $ cd cst-3.4.0/crts/ ### dump SRK HASH fuses value ### $ hexdump -e '/4 "0x"' -e '/4 "%X""\n"' SRK_1_2_3_4_fuse.bin 0x3D06A4A9 0x4BC55D12 0xA5F45E7F 0x1F1F68FC 0x3B9B4AE8 0xFC658293 0x40A706C9 0x94A9139E -------------------------------- ./进入Verdin i.MX8MM U-Boot命令行,通过如下命令写入fuses,注意这些fuses都是一次写入的,因此请务必保证一次写入正确。为了操作方便,可以将上述命令生成U-Boot脚本文件或者通过NXP Universal Update Utility (UUU)工具脚本来进行操作,本文不做赘述。 -------------------------------- Verdin iMX8MM # fuse prog -y 6 0 0x3D06A4A9 Verdin iMX8MM # fuse prog -y 6 1 0x4BC55D12 Verdin iMX8MM # fuse prog -y 6 2 0xA5F45E7F Verdin iMX8MM # fuse prog -y 6 3 0x1F1F68FC Verdin iMX8MM # fuse prog -y 7 0 0x3B9B4AE8 Verdin iMX8MM # fuse prog -y 7 1 0xFC658293 Verdin iMX8MM # fuse prog -y 7 2 0x40A706C9 Verdin iMX8MM # fuse prog -y 7 3 0x94A9139E -------------------------------- f).此时再将上一步骤签名成功的“signed_flash.bin”文件重命名为“imx-boot”并更新到Verdin i.MX8MM模块上面启动查看HAB功能使能情况。 ./ SPL启动log,由于boot container image已经签名,因此提示已经变为“Authenticate image ...”。 -------------------------------- U-Boot SPL 2022.04-21749-g3428b47019-dirty (Apr 22 2024 - 17:52:20 +0800) ... Authenticate image from DDR location 0x401fcdc0... ... -------------------------------- ./ U-boot命令行下查看HAB状态,已经没有错误事件。 -------------------------------- Verdin iMX8MM # hab_status Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! -------------------------------- g).更多关于此步骤的说明请参考如下文档 ./ U-Boot documentation https://git.toradex.cn/cgit/u-boot-toradex.git/tree/doc/imx/habv4/guides/mx8m_secure_boot.txt?h=toradex_imx_lf_v2022.04 ./ NXP Application Note - AN4581 i.MX Secure Boot on HABv4 Supported Devices 5). 签名 Linux kernel a).此步骤为可选步骤,如果不需要Linux Kernel Secure Boot功能则可以通过如下patch文件关闭booti HAB验证,然后close设备即可。 -------------------------------- --- a/cmd/booti.c +++ b/cmd/booti.c @@ -78,7 +78,7 @@ static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc, if (ret != 0) return 1; -#if defined(CONFIG_IMX_HAB) && !defined(CONFIG_AVB_SUPPORT) +#if 0 extern int authenticate_image( uint32_t ddr_start, uint32_t raw_image_size); if (authenticate_image(ld, image_size) != 0) { -------------------------------- b).解压Toradex Ycoto Linux BSP 6.6 Multimedia Image,获得LInux Kernel文件 -------------------------------- ### uncompress BSP Image package ### $ tar xvf Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12.tar $ cd Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12/ ### uncompress boot filesystem ### $ mkdir bootfs/ $ tarJxfReference-Multimedia-Image-verdin-imx8mm.bootfs.tar.xz -C bootfs/ ### extract kernel image from compressed package ### $ cd bootfs/ $ gzip -d Image.gz $ file Image Image: Linux kernel ARM64 boot executable Image, little-endian, 4K pages -------------------------------- c).签名Linux kernel image文件 ./ Padding image文件 -------------------------------- $ cd .../Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12/bootfs ### read Image size ### $ od -x -j 0x10 -N 0x4 --endian=little Image 0000020 0000 01c3 0000024 ### pad the Image, Image_pad.bin size =0x1c30000### $ objcopy -I binary -O binary --pad-to 0x1c30000 --gap-fill=0x00 Image Image_pad.bin ### get IVT generator script from U-boot source ### $ cp.../u-boot-toradex/doc/imx/habv4/script_examples/genIVT.pl.../Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12/bootfs ### customized script according to your device kernel loading address ### #! /usr/bin/perl -w use strict; :raw', 'ivt.bin') or die "Unable to open: $!"; print $out pack("V", 0x412000D1); # Signature print $out pack("V",0x48200000); # Load Address (*load_address) print $out pack("V", 0x0); # Reserved print $out pack("V", 0x0); # DCD pointer print $out pack("V", 0x0); # Boot Data print $out pack("V",0x49e30000); # Self Pointer (*ivt) print $out pack("V",0x49e30020); # CSF Pointer (*csf) print $out pack("V", 0x0); # Reserved close($out); ## Load Address - kernel_addr_r value from U-boot env ## Self Pointer -0x48200000(Load Address) +0x1c30000(the size of Image_pad.bin) ## CSF Pointer -0x49e30000(Self Pointer) + 0x20 (the size of IVT binary) ### generate IVT binary ### $ ./genIVT.pl ### Append the ivt.bin at the end of the padded Image ### Image_pad_ivt.bin -------------------------------- ./然后生成CSF文件用于后续签名kernel image -------------------------------- ### copy csf_additional_images.txt template to CST tool containing folder ### $ cp.../u-boot-toradex/doc/imx/habv4/csf_examples/additional_images/csf_additional_images.txt.../cst-3.4.0/ ### customized CSF file ### --- csf_additional_images.txt.bak2024-04-24 16:43:28.038751461 +0800 +++ csf_additional_images.txt2024-04-24 16:50:40.484115829 +0800 @@ -8,12 +8,12 @@ # Index of the key location in the SRK table to be installed - File = "../crts/SRK_1_2_3_4_table.bin" + File = "./crts/SRK_1_2_3_4_table.bin" Source index = 0 # Key used to authenticate the CSF data - File = "../crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" + File = "./crts/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" @@ -23,12 +23,10 @@ # Target key slot in HAB key store where key will be installed Target Index = 2 # Key to install - File= "../crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" + File= "./crts/IMG1_1_sha256_2048_65537_v3_usr_crt.pem" # Key slot index used to authenticate the image data Verification index = 2 # Authenticate Start Address, Offset, Length and file - Blocks = 0x80800000 0x00000000 0x006EA000 "zImage", \ -0x83800000 0x00000000 0x0000B927 "imx7d-sdb.dtb", \ -0x84000000 0x00000000 0x000425B8 "uTee-7dsdb" + Blocks = 0x48200000 0x000000000x1c30020"Image_pad_ivt.bin" ## Blocks = ## Image_length =0x1c30020(the size of Image_pad_ivt.bin) ### create CSF binary file ### $ ./linux64/bin/cst --i csf_additional_images.txt --o csf_Image.bin CSF Processed successfully and signed data available in csf_Image.bin -------------------------------- ./签名Kernel image -------------------------------- $ cp .../Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12/bootfs/Image_pad_ivt.bin.../cst-3.4.0/ $ cd .../cst-3.4.0/ Image_signed.bin -------------------------------- d).本文以Kernel image为例,实际其他的如device tree文件或者FIT Image等,都可以用类似方法进行签名。 6 ). 部署Kernel Image a).将上述签名好的Kernel image文件部署到Verdin i.MX8MM模块Linux系统“/boot”目录下,替换原来的Image文件“Image.gz”。 b).重启进入U-boot命令行模式,通过如下命令行参数配置验证签名的Kernel image文件,如果没有任何HAB Events,说明签名正确可以进行下一步。 -------------------------------- ### set boot device info mmc 0:1 ### Verdin iMX8MM # setenv pre_boot 'devnum=0; if mmc dev ${devnum}; then devtype=mmc; setenv load_cmd \"load ${devtype} ${devnum}:1\"; fi' Verdin iMX8MM #run pre_boot ### signed kernel image loading ### Verdin iMX8MM # setenv cntr_file 'Image_signed.bin' Verdin iMX8MM # setenv cntr_load '${load_cmd} ${loadaddr} ${cntr_file} Verdin iMX8MM #run cntr_load ### authenticate signed os container image ### Verdin iMX8MM # setenv ivt_offset0x1c30000 Verdin iMX8MM # setenv entr_filesize0x1c30c34 ##entr_filesize is the hex size of Image_signed.bin ## ivt_offset isthe hex size of Image_pad_ivt.bin Verdin iMX8MM #setenv auth_os 'hab_auth_img ${loadaddr} ${entr_filesize}${ivt_offset}' Verdin iMX8MM # run auth_os hab fuse not enabled Authenticate image from DDR location 0x48200000... Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! -------------------------------- c).将测试通过的签名Kernel Image重新部署到刚才解压的Ycoto Linux Multimedia BSP6.6 bootfs中,并重新创建bootfs压缩包 -------------------------------- ### copy signed kernel image to bsp rootfs folder ### $ cp Image_signed.bin.../Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12/bootfs/ ### remove default boot script and linux kernel files ### $ cd .../Verdin-iMX8MM_Reference-Multimedia-Image-Tezi_6.6.0+build.12/bootfs/ $ rm boot.scr Image ### check bootfs files ### $ tree -L 1 . ├── Image_signed.bin ├── imx8mm-verdin-nonwifi-dahlia.dtb ├── imx8mm-verdin-nonwifi-dev.dtb ├── imx8mm-verdin-nonwifi-mallow.dtb ├── imx8mm-verdin-nonwifi-yavia.dtb ├── imx8mm-verdin-wifi-dahlia.dtb ├── imx8mm-verdin-wifi-dev.dtb ├── imx8mm-verdin-wifi-mallow.dtb ├── imx8mm-verdin-wifi-yavia.dtb ├── overlays └── overlays.txt ### compress new bootfs package ### $ tar Jcf ../Reference-Multimedia-Image-verdin-imx8mm.bootfs.tar.xz * ### obtain bootfs size ### $ du bootfs/ 36bootfs/overlays 29452bootfs/ ### clear bootfs $ cd .. $ rm -rf bootfs/ -------------------------------- d).修改BSP package中的“image.json”文件,适配新的bootfs文件夹大小 -------------------------------- ---a/image.json2024-04-25 15:02:40.445846395 +0800 +++b/image.json2024-04-25 15:03:10.010252080 +0800 @@ -32,7 +32,7 @@ "filesystem_type": "FAT", "mkfs_options": "", "filename": "Reference-Multimedia-Image-verdin-imx8mm.bootfs.tar.xz", - "uncompressed_size": 11.671875 + "uncompressed_size": 28.76171875 } }, { -------------------------------- e).修改BSP package中的“u-boot-initial-env-sd”文件,增加如下环境变量用于Secure Boot ./命令方式格式 -------------------------------- ### set boot device info mmc 0:1 ### Verdin iMX8MM # setenv pre_boot 'devnum=0; if mmc dev ${devnum}; then devtype=mmc; setenv load_cmd \"load ${devtype} ${devnum}:1\"; fi' ### signed kernel image loading info ### Verdin iMX8MM # setenv cntr_file 'Image_signed.bin' Verdin iMX8MM # setenv cntr_load '${load_cmd} ${loadaddr} ${cntr_file}' ### authenticate signed os container image ### Verdin iMX8MM # setenv ivt_offset0x1c30000 Verdin iMX8MM # setenv entr_filesize0x1c30c34 Verdin iMX8MM #setenv auth_os 'hab_auth_img ${loadaddr} ${entr_filesize}${ivt_offset}' ### device tree overlay apply ### Verdin iMX8MM #setenv overlays_file 'overlays.txt' Verdin iMX8MM #setenv overlays_prefix 'overlays/' Verdin iMX8MM #setenv load_overlays_file '${load_cmd} ${loadaddr} ${overlays_file} && env import -t ${loadaddr} ${filesize}' Verdin iMX8MM #setenv fdt_resize 'fdt addr ${fdt_addr_r} && fdt resize 0x20000' Verdin iMX8MM #setenvapply_overlays 'for overlay_file in ${fdt_overlays}; do echo Applying Overlay: ${overlay_file} && ${load_cmd} ${loadaddr} ${overlays_prefix}\${overlay_file} && fdt apply ${loadaddr}; env set overlay_file; done; true' Verdin iMX8MM #setenv bootcmd_overlays 'run load_overlays_file && run fdt_resize && run apply_overlays' ### prepare arguments ### Verdin iMX8MM # setenvroot_part2 Verdin iMX8MM # setenvuuid_set 'part uuid ${devtype} ${devnum}:${root_part} uuid' Verdin iMX8MM # setenvrootfsargs_set 'run uuid_set && env set rootfsargs root=PARTUUID=${uuid} ro rootwait' Verdin iMX8MM # setenvbootcmd_args 'run rootfsargs_set && env set bootargs ${defargs} ${rootfsargs} ${setupargs} ${vidargs} ${tdxargs}' ### prepare device tree loading ### Verdin iMX8MM # setenvset_bootcmd_dtb 'env set bootcmd_dtb "echo Loading DeviceTree: \\${fdtfile}; ${load_cmd} \\${fdt_addr_r} \\${fdtfile}"' ### boot kernel&dtb ### Verdin iMX8MM #setenv bootcmd_boot 'echo "Bootargs: \${bootargs}" && booti ${kernel_addr_r} - ${fdt_addr_r}' ### config for all boot process ### Verdin iMX8MM #setenv bootcmd_run 'run pre_boot && run set_bootcmd_dtb&&run bootcmd_dtb&&run bootcmd_overlays && run bootcmd_args &&runcntr_load&& runauth_os&&run bootcmd_boot; echo "Booting from ${devtype} failed!" && false' ### auto run config ### Verdin iMX8MM #setenv bootcmd 'run bootcmd_run' -------------------------------- ./文件方式定义 -------------------------------- ---a/u-boot-initial-env-sd2024-04-25 14:55:07.599626789 +0800 +++b/u-boot-initial-env-sd2024-04-25 15:34:22.349957180 +0800 @@ -14,7 +14,7 @@ boot_scripts=boot.scr.uimg boot.scr boot_syslinux_conf=extlinux/extlinux.conf boot_targets=mmc1 mmc0 dhcp -bootcmd=run distro_bootcmd +bootcmd=run bootcmd_run bootcmd_dhcp=devtype=dhcp; run boot_net_usb_start; if dhcp ${scriptaddr} ${boot_script_dhcp}; then source ${scriptaddr}; fi;setenv efi_fdtfile ${fdtfile}; setenv efi_old_vci ${bootp_vci};setenv efi_old_arch ${bootp_arch};setenv bootp_vci PXEClient:Arch:00011:UNDI:003000;setenv bootp_arch 0xb;if dhcp ${kernel_addr_r}; then tftpboot ${fdt_addr_r} dtb/${efi_fdtfile};if fdt addr ${fdt_addr_r}; then bootefi ${kernel_addr_r} ${fdt_addr_r}; else bootefi ${kernel_addr_r} ${fdtcontroladdr};fi;fi;setenv bootp_vci ${efi_old_vci};setenv bootp_arch ${efi_old_arch};setenv efi_fdtfile;setenv efi_old_arch;setenv efi_old_vci; bootcmd_mmc0=devnum=0; run mmc_boot bootcmd_mmc1=devnum=1; run mmc_boot @@ -51,3 +51,22 @@ update_uboot=askenv confirm Did you load flash.bin (y/N)?; if test "$confirm" = "y"; then setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt ${blkcnt} / 0x200; mmc dev 0 1; mmc write ${loadaddr} 0x2 ${blkcnt}; fi usb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boot_part; fi vendor=toradex +pre_boot=devnum=0; if mmc dev ${devnum}; then devtype=mmc; setenv load_cmd \"load ${devtype} ${devnum}:1\"; fi +cntr_file=Image_signed.bin +cntr_load=${load_cmd} ${loadaddr} ${cntr_file} +ivt_offset=0x1c30000 +entr_filesize=0x1c30c34 +auth_os=hab_auth_img ${loadaddr} ${entr_filesize} ${ivt_offset} +overlays_file=overlays.txt +overlays_prefix=overlays/ +load_overlays_file=${load_cmd} ${loadaddr} ${overlays_file} && env import -t ${loadaddr} ${filesize} +fdt_resize=fdt addr ${fdt_addr_r} && fdt resize 0x20000 +apply_overlays=for overlay_file in ${fdt_overlays}; do echo Applying Overlay: ${overlay_file} && ${load_cmd} ${loadaddr} ${overlays_prefix}\${overlay_file} && fdt apply ${loadaddr}; env set overlay_file; done; true +bootcmd_overlays=run load_overlays_file && run fdt_resize && run apply_overlays +root_part=2 +uuid_set=part uuid ${devtype} ${devnum}:${root_part} uuid +rootfsargs_set=run uuid_set && env set rootfsargs root=PARTUUID=${uuid} ro rootwait +bootcmd_args=run rootfsargs_set && env set bootargs ${defargs} ${rootfsargs} ${setupargs} ${vidargs} ${tdxargs} +set_bootcmd_dtb=env set bootcmd_dtb "echo Loading DeviceTree: \\${fdtfile}; ${load_cmd} \\${fdt_addr_r} \\${fdtfile}" +bootcmd_boot=echo "Bootargs: \${bootargs}" && booti ${kernel_addr_r} - ${fdt_addr_r} +bootcmd_run=run pre_boot && run set_bootcmd_dtb && run bootcmd_dtb && run bootcmd_overlays && run bootcmd_args && run cntr_load && run auth_os && run bootcmd_boot; echo "Booting from ${devtype} failed!" && false -------------------------------- f).需要注意的是由于Kernel阶段的Secure Boot相关认证和加载都是基于U-Boot命令行来实现的, 因此如果要让这个启动机制更加安全可靠,则要让U-Boot保持在上述安全启动路径,而不能通过其他启动介质或者脚本来启动而绕开Secure Boot,比如Toradex U-Boot默认是使能Distro Boot功能的,可以自动扫描外设介质的启动脚本,那么这个功能就需要关闭掉,类似这样的U-Boot定制化和启动路径固化可以参考如下文章,本文不做具体测试。 https://developer.toradex.cn/torizon/security/u-boot-hardening-for-secure-boot/ g).如果你的Linux BSP Image是通过Yocto Project编译生成,那么如下是一个包含上述全部内容的Meta Layer,你可以直接将其集成到你的Yocto Project编译环境中,然后按照说明配置后直接生成签名好的BSP Image。 https://github.com/toradex/meta-toradex-security 7 ).部署 测试 a).参考这里将上述制作的支持Secure Boot的Image通过Toradex Easy Installer更新到Verdin i.MX8MM模块 ./启动后查看启动log,可以看到U-Boot和Linux Kernel Image Secure Boot验证签名成功并最终完整启动 -------------------------------- U-Boot SPL 2022.04-21749-g3428b47019-dirty (Apr 22 2024 - 17:52:20 +0800) ... Authenticate image from DDR location 0x401fcdc0... NOTICE: BL31: v2.6(release):lf_v2.6-g3c1583ba0a NOTICE: BL31: Built : 11:00:38, Nov 21 2022 U-Boot 2022.04-21749-g3428b47019-dirty (Apr 22 2024 - 17:52:20 +0800) CPU: i.MX8MMQ rev1.0 1600 MHz (running at 1200 MHz) CPU: Industrial temperature grade (-40C to 105C) at 59C ... switch to partitions #0, OK mmc0(part 0) is current device Loading DeviceTree: imx8mm-verdin-wifi-dev.dtb 66160 bytes read in 2 ms (31.5 MiB/s) 86 bytes read in 1 ms (84 KiB/s) Applying Overlay: verdin-imx8mm_dsi-to-hdmi_overlay.dtbo 2317 bytes read in 2 ms (1.1 MiB/s) Applying Overlay: verdin-imx8mm_spidev_overlay.dtbo 561 bytes read in 2 ms (273.4 KiB/s) 29559860 bytes read in 191 ms (147.6 MiB/s) hab fuse not enabled Authenticate image from DDR location 0x48200000... Secure boot disabled HAB Configuration: 0xf0, HAB State: 0x66 No HAB Events Found! Bootargs: root=PARTUUID=ba09f564-02 ro rootwait ... Starting kernel ... Booting Linux on physical CPU 0x0000000000 Linux version 5.15.148-6.6.0-6.6.0+git.23a8e831749d (oe-user@oe-host) (aarch64-tdx ... TDX Wayland with XWayland 6.6.0+build.12 (kirkstone) verdin-imx8mm-07276322 - Verdin-iMX8MM_Reference-Multimedia-Image verdin-imx8mm-07276322 login: -------------------------------- b). Close设备 经过上述测试已经确认从U-Boot到Linux Kernel Secure Boot正常,即可以在U-Boot命令行下面执行下面命令Close设备,请注意此操作之后,没有签名的Image就无法再在此模块加载运行了,因此请谨慎操作。 -------------------------------- ###Program SRK_LOCK### Verdin iMX8MM #fuse prog 0 0 0x200 ###Program DIR_BT_DIS### Verdin iMX8MM #fuse prog 1 3 0x8000000 ###Program SJC_DISABLE### Verdin iMX8MM #fuse prog 1 3 0x200000 ###JTAG_SMODE### Verdin iMX8MM #fuse prog 1 3 0xC00000 -------------------------------- 8 ).总结 本文基于NXP i.MX8M Mini处理器演示了基于HABv4的Secure Boot功能,涉及U-Boot和Linux Kernel,至于Rootfs的加密,则需要配置类似Squashfs只读文件系统配合Initramfs RAM Disk镜像进行加解密挂载启动,可以结合参考如下两篇文章和相关meta-toradex-security layer数据参考,本文不做具体测试。 ./嵌入式ARM平台使用dm-crypt加密磁盘分区 ./使用Squashfs和Overlayfs提高嵌入式Linux文件系统可靠性 ./https://github.com/toradex/meta-toradex-security ​
  • 热度 12
    2022-8-30 12:12
    4077 次阅读|
    0 个评论
    B y Toradex 秦海 1). 简介 由于 NXP 从 iMX8/iMX8x 处理器开始引入了 SCU/SECO 等底层控制模块来进行包含启动管理等多项底层初始化功能,因此对于 Secure Boot 功能支持,也同样升级为 Advanced High Assurance Boot (AHAB) 特性来配合,以区别于 iMX6/iMX8MM/iMX8MP 处理器所使用的 HABv4 特性; AHAB 和 HABv4 都是基于公共密钥加密 (Public Key Cryptography) 和数字签名 (Digital Signature) 技术来实现 Secure Boot 的, SCU 负责协调各个启动组件和流程, SECO 用于验证签名的 Image 文件并授权加载运行,一个简单的流程图参考如下。 本文就 基于 NXP iMX8 平台测试部署 Secure Boot 功能 。 本文所演示的平台来自于 Toradex Apalis iMX 8 嵌入式平台,这个平台是基于 近年发布的 NXP iMX 8 系列 ARM 处理器,核心为 Cortex-A 72/A53 。 2. 准备 a). Apalis iMX8 ARM 核心版配合 Ixora 载板, 并连接调试串口用于测试 。 b). 参考 这里 下载 Toradex Ycoto Linux BSP5 Image 用于后续测试,目前最新的是 5.7 版本。 3). 生成 PKI Tree 文件 a). 从 NXP 官方网站下载 Code Signing Tools 软件包(需注册),目前最新版本是 3.3.1 版本,然后解压后使用预设的脚本生成 Public Key Infrastructure (PKI) tree ,用于后面签名 U-boot/Linux Kernel Image 文件 -------------------------------- $ cp .../cst-3.3.1.tgz ~/. $ cd ~ $ tar xvf cst-3.3.1.tgz $ tree -L 1 cst-3.3.1/ cst-3.3.1/ ├── ca ├── code ├── crts ├── docs ├── keys ├── LICENSE.bsd3 ├── LICENSE.hidapi ├── LICENSE.openssl ├── linux32 ├── linux64 ├── mingw32 ├── osx ├── Release_Notes.txt └── Software_Content_Register_CST.txt -------------------------------- b). 生成 PKI TREE ./ 修改 CST 工具默认的 serial 和 key_pass ,本文因为仅测试需要则保持默认没有修改,实际应用可以根据需要自行修改以保证安全 -------------------------------- $ cd ~/cst-3.3.1/keys ### default serial number for OpenSSL certification ### $ cat serial 1234567C ### default key_pass for protection of private keys $ cat key_pass.txt test test -------------------------------- ./ 运行 CST 工具预制脚本通过交互方式生成 PKI TREE ,这里生成一个 P384 ECC SRK PKI TREE 示例,还可以选择其他选项或者生成包含下级 SGK Key 的 PKI TREE ,更多可以参考如下 U-Boot 源代码中的文档说明 https://git.toradex.cn/cgit/u-boot-toradex.git/tree/doc/imx/ahab/introduction_ahab.txt?h=toradex_imx_v2020.04_5.4.70_2.3.0 -------------------------------- ### generate P384 ECC PKI TREE ### $ ./ahab_pki_tree.sh ... Do you want to use an existing CA key (y/n)?: n Do you want to use Elliptic Curve Cryptography (y/n)?: y Enter length for elliptic curve to be used for PKI tree: Possible values p256, p384, p521: p384 Enter the digest algorithm to use: sha384 Enter PKI tree duration (years): 5 Do you want the SRK certificates to have the CA flag set? (y/n)?: n ### check generated SRK keys ### $ ls SRK * SRK1_sha384_secp384r1_v3_usr_key.der SRK2_sha384_secp384r1_v3_usr_key.pem SRK4_sha384_secp384r1_v3_usr_key.der SRK1_sha384_secp384r1_v3_usr_key.pem SRK3_sha384_secp384r1_v3_usr_key.der SRK4_sha384_secp384r1_v3_usr_key.pem SRK2_sha384_secp384r1_v3_usr_key.der SRK3_sha384_secp384r1_v3_usr_key.pem ### generate SRK Table 和 SRK Hash ### $ cd ../crts/ $ ../linux64/bin/srktool -a -s sha384 -t SRK_1_2_3_4_table.bin \ -e SRK_1_2_3_4_fuse.bin -f 1 -c \ SRK1_sha384_secp384r1_v3_usr_crt.pem,\ SRK2_sha384_secp384r1_v3_usr_crt.pem,\ SRK3_sha384_secp384r1_v3_usr_crt.pem,\ SRK4_sha384_secp384r1_v3_usr_crt.pem ### check SRK Table and SRK Hash ### $ ls SRK_* SRK_1_2_3_4_fuse.bin SRK_1_2_3_4_table.bin -------------------------------- c ). 上面最后生成的两个文件就是我们后面签名和 fuse 设备需要用到的, ”SRK_1_2_3_4_table.bin” 文件是 SRK Table ,用于签名 Container Image ; ”SRK_1_2_3_4_ fuse .bin” 文件是 SRK Hash ,用于 fuse 到 Apalis iMX8 设备的 eFuse 。更多 CST 工具使用说明可以参考如下 CST User Guide 文档 cst-3.3.1/docs/CST_UG.pdf 4). Boot Container 配置和签名 a). 参考 这里 说明下载 Toradex Ycoto Linux BSP 5.x.y 版本 U- boot 源代码, 默认配置并未使能 AHAB 功能支持,需要在 config 中使能如下选项,并重新编译生成新的 U-Boot 文件 ” u-boot.bin ” -------------------------------- → ARM architecture Support i.MX8 AHAB features -------------------------------- b). 参考上面 U-boot 源码下载编译文章以及下面参考文档,使用编译生成的 U-Boot 文件生成 Apalis iMX8 Boot Container Image 文件 ” flash.bin ” https://www.toradex.cn/blog/nxp-imx8-scfw-heboot-container-image-bian-yi c). 此时先将上一步骤生成的 “ flash.bin ” 文件重命名为 “ imx-boot ” ,然后通过 这里 的说明通过 Toradex Easy Installer 更新到 Apalis iMX8 模块并启动进入 U-Boot 命令行,通过如下命令可以查看 AHAB 功能以及使能成功,但是由于 Boot Container Image 并未签名,因此提示 “ 0xEE ” 事件。 -------------------------------- ### check AHAB enable status ### Apalis iMX8 # ahab_status Lifecycle: 0x0020, NXP closed SECO Event = 0x0087 EE 00 CMD = AHAB_AUTH_CONTAINER_REQ (0x87) IND = AHAB_NO_AUTHENTICATION_IND (0x EE ) sc_seco_get_event: idx: 1, res:3 -------------------------------- d). 通过 CST 工具对上一步骤使用 imx-mkimage 生成的 Boot Container Image “ flash.bin ” 文件进行签名 -------------------------------- ### copy boot container image file to CST tool containing folder ### $ cp .../imx-mkimage/iMX8QM/flash.bin ~/ ### copy CSF template to CST tool containing folder ### $ cp u-boot-toradex/doc/imx/ahab/csf_examples/csf_boot_image.txt ~/ ### modify csf_boot_image.txt to adopt your settings ### vi csf_boot_image.txt Target = AHAB Version = 1.0 # SRK table generated by srktool File = "./cst-3.3.1/crts/SRK_1_2_3_4_table.bin" # Public key certificate in PEM format Source = "./cst-3.3.1/crts/SRK1_sha384_secp384r1_v3_usr_crt.pem" # Index of the public key certificate within the SRK table (0 .. 3) Source index = 0 # Type of SRK set (NXP or OEM) Source set = OEM # bitmask of the revoked SRKs Revocations = 0x0 # Binary to be signed generated by mkimage File = "flash.bin" # Offsets = Container header Signature block (printed out by mkimage) Offsets = 0x400 0x590 ### sign boot container image ### ./cst-3.3.1/linux64/bin/cst -i csf_boot_image.txt -o flash_signed.bin Install SRK Authenticate data CSF Processed successfully and signed image available in flash_signed.bin -------------------------------- e ). 此时再将上一步骤签名成功的 “ flash_signed.bin ” 文件重命名为 “ imx-boot ” 并更新到 Apalis iMX8 模块上面,此时 AHAB 状态命令变化如下,因为并未将对应的 Hash 烧写到 Apalis iMX8 eFuse ,因此提示 “ 0xEA ” 事件。 -------------------------------- ### check AHAB enable status ### Apalis iMX8 # ahab_status Lifecycle: 0x0020, NXP closed SECO Event = 0x0087FA00 CMD = AHAB_AUTH_CONTAINER_REQ (0x87) IND = AHAB_BAD_KEY_HASH_IND (0xFA) sc_seco_get_event: idx: 1, res:3 -------------------------------- f). 烧写 SRK Hash ./ 签名的 Boot Container Image 文件要通过 iMX8 SOC SRK_HASH fuse 烧写的 SRK Hash 进行校验 ./ 导出 SRK HASH fuse 对应数值 -------------------------------- ### dump SRK HASH fuse value ### $ od -t x4 ~/ cst-3.3.1/crts/SRK_1_2_3_4_fuse.bin 0000000 7ef8ad2a 4a3e54b6 ffa3df87 1774beb6 0000020 6f7b4d2e a9e90a59 c5fa9ea2 55c59bf4 0000040 b55aa0b9 8b30c2ec 519814df 26a0f058 0000060 52c0edda 7e686983 4bf5f8d7 27d7727a -------------------------------- ./ 进入 Apalis iMX8 U-Boot 命令行,通过如下命令写入 fuses ,注意这些 fuses 都是一次写入的,因此请务必保证一次写入正确。另外不同的 SOC 有不同的地址,如下只适用于 iMX8QM ,如果是 iMX8X 要参考文档修改。 -------------------------------- Apalis iMX8 # fuse prog 0 722 7ef8ad2a Apalis iMX8 # fuse prog 0 72 3 4a3e54b6 Apalis iMX8 # fuse prog 0 72 4 ffa3df87 Apalis iMX8 # fuse prog 0 72 5 1774beb6 Apalis iMX8 # fuse prog 0 72 6 6f7b4d2e ... Apalis iMX8 # fuse prog 0 7 36 4bf5f8d7 Apalis iMX8 # fuse prog 0 7 37 27d7727a -------------------------------- 为了操作方便,可以将上述命令生成 U-Boot 脚本文件来执行,或者可以通过类似如下 NXP Universal Update Utility (UUU) 工具脚本来进行操作 -------------------------------- # This command will be run when ROM support stream mode # i.MX8QXP, i.MX8QM SDPS: boot -f imx-boot # refer related module tezi image recovery folder uuu.auto file CFG: FB: -vid 0x0525 -pid 0x4000 CFG: FB: -vid 0x0525 -pid 0x4025 CFG: FB: -vid 0x0525 -pid 0x402F CFG: FB: -vid 0x0525 -pid 0x4030 CFG: FB: -vid 0x0525 -pid 0x4031 SPDU: delay 1000 FB: ucmd setenv cmd 'fuse prog -y 0' FB: ucmd ${cmd} 722 0x7ef8ad2a FB: ucmd ${cmd} 723 0x.... .. ... FB: ucmd ${cmd} 737 0x27d7727a FB: done -------------------------------- e ). SRK HASH 烧写完成后, AHAB 状态命令变化如下,只有如下状态下 close 设备才是安全的,否则设备就无法启动了。 -------------------------------- ### check AHAB enable status ### Apalis iMX8 # ahab_status Lifecycle: 0x0020, NXP closed sc_seco_get_event: idx: 1, res:3 No SECO Events Found! -------------------------------- f). 更多关于此步骤的说明请参考如下文档 ./ U-Boot documentation https://git.toradex.cn/cgit/u-boot-toradex.git/tree/doc/imx/ahab/guides/mx8_mx8x_secure_boot.txt?h=toradex_imx_v2020.04_5.4.70_2.3.0 ./ NXP Application Note - AN12312 Secure Boot on i.MX 8 and i.MX 8X Families using AHAB 5). 签名包含 Linux kernel 和 D evice T ree 文件的 OS Container Image a). 此步骤为可选步骤,如果不需要 Linux Kernel Secure Boot 功能则无需操作直接 close 设备即可。 b ). 解压 Toradex Ycoto Linux BSP 5.7 Multimedia Image ,获得 LInux Kernel 和需要加载的 Device Tree 文件 -------------------------------- ### uncompress BSP Image package ### $ tar xvf Apalis-iMX8_Reference-Multimedia-Image-Tezi_5.7.0+build.20.tar $ cd Apalis-iMX8_Reference-M ultimedia -Image-Tezi_5.7.0+build.20/ ### uncompress boot filesystem ### $ mkdir bootfs/ $ tar Jxf Reference-Minimal-Image-apalis-imx8.bootfs.tar.xz -C bootfs/ ### copy Kernel and Device Tree files to imx-mkimage tools related device folder ### $ cd bootfs/ $ gzip -d Image.gz $ cp Image imx8qm-apalis-v1.1-eval.dtb .../imx-mkimage/iMX8QM/ -------------------------------- b). 使用 imx-mkimage 工具生成 OS Container Image ./ 如下修改默认配置,将 Linux Kernel 和 Device Tree 文件的命名和加载地址修改为适合你当前设备定义的配置, Toradex U-Boot 默认配置 Kernel 加载地址为 “ 0x96000000 ” , Device Tree 加载地址为 “ 0x83000000 ” 。 -------------------------------- --- a/iMX8QM/soc.mak 2022-08-19 17:31:57.488554800 +0800 +++ b/iMX8QM/soc.mak 2022-08-22 15:15:45.393002799 +0800 @@ -140,8 +140,8 @@ flash_scfw: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin ./$(MKIMG) -soc QM -rev B0 -dcd skip -append $(AHAB_IMG) -c -scfw scfw_tcm.bin -out flash.bin -flash_kernel: $(MKIMG) Image fsl-imx8qm-mek.dtb - ./$(MKIMG) -soc QM -rev B0 -c -ap Image a53 0x80280000 --data fsl-imx8qm-mek.dtb 0x83000000 -out flash.bin +flash_kernel: $(MKIMG) Image imx8qm-apalis-v1.1-eval.dtb + ./$(MKIMG) -soc QM -rev B0 -c -ap Image a53 0x96000000 --data imx8qm-apalis-v1.1-eval.dtb 0x83000000 -out flash_os.bin flash_ca72: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin u-boot-atf.bin ./$(MKIMG) -soc QM -rev B0 -append $(AHAB_IMG) -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a72 0x80000000 -out flash.bin -------------------------------- ./ 生成 OS Container Image 文件 “ flash_os.bin ” ,并记录生成记录最后的 IVT_OFFSET + IMAGE_OFFSET 数值用于后续 CSF 文件定义。 -------------------------------- $ cd .../imx-mkimage/ $ make SOC=iMX8QM flash_kernel ... CST: CONTAINER 0 offset: 0x0 CST: CONTAINER 0: Signature Block: offset is at 0x110 DONE. Note: Please copy image to offset: IVT_OFFSET + IMAGE_OFFSET -------------------------------- c). 使用 CST 工具签名刚才生成的 OS Container Image ./ 准备 CSF 文件 -------------------------------- ### copy CSF template to CST tool containing folder ### $ cp u-boot-toradex/doc/imx/ahab/csf_examples/csf_linux_img.txt ~/ ### modify csf_linux_img.txt to adopt your settings ### vi csf_linux_img.txt Target = AHAB Version = 1.0 # SRK table generated by srktool File = "./cst-3.3.1/crts/SRK_1_2_3_4_table.bin" # Public key certificate in PEM format Source = "./cst-3.3.1/crts/SRK1_sha384_secp384r1_v3_usr_crt.pem" # Index of the public key certificate within the SRK table (0 .. 3) Source index = 0 # Type of SRK set (NXP or OEM) Source set = OEM # bitmask of the revoked SRKs Revocations = 0x0 # Binary to be signed generated by mkimage File = "flash_os.bin" # Offsets = Container header Signature block (printed out by mkimage) Offsets = 0x0 0x110 -------------------------------- ./ 签名,获得签名好的 OS Container Image 文件 “os_cntr_signed.bin” -------------------------------- $ cp .../imx-mkimage/iMX8QM/flash_os.bin ~/ $ ./cst-3.3.1/linux64/bin/cst -i csf_linux_img.txt -o os_cntr_signed.bin -------------------------------- 6 ). 部署 OS Container Image a ). 将 OS Container Image 重新部署到刚才解压的 Ycoto Linux Multimedia BSP5.7 bootfs 中,并重新创建 bootfs 压缩包 -------------------------------- ### copy signed os container image to bsp rootfs folder ### $ cp os_cntr_signed.bin ... /Apalis-iMX8_Reference- Multimedia -Image-Tezi_5.7.0+build.20/bootfs/ ### remove default boot script and linux kernel/device tree files ### $ cd ... /Apalis-iMX8_Reference- Multimedia -Image-Tezi_5.7.0+build.20/ bootfs/ $ rm boot.scr Image *.dtb ### check bootfs files ### $ tree -L 2 . ├── dpfw.bin ├── hdmitxfw.bin ├── os_cntr_signed.bin ├── overlays │ ├── apalis-imx8_ar0521_overlay.dtbo │ ├── apalis-imx8_atmel-mxt_overlay.dtbo │ ├── apalis-imx8_hdmi_overlay.dtbo │ ├── apalis-imx8_lvds_overlay.dtbo │ ├── apalis-imx8_mezzanine-can_overlay.dtbo │ ├── apalis-imx8_mezzanine_lvds_overlay.dtbo │ ├── apalis-imx8_mezzanine_ov5640_overlay.dtbo │ ├── apalis-imx8_ov5640_overlay.dtbo │ ├── apalis-imx8_resistive-touch_overlay.dtbo │ ├── display-dpi-lt170410_overlay.dtbo │ ├── display-edt5.7_overlay.dtbo │ ├── display-edt7_overlay.dtbo │ ├── display-fullhd_overlay.dtbo │ ├── display-lt161010_overlay.dtbo │ ├── display-lt170410_overlay.dtbo │ ├── display-vga_overlay.dtbo │ └── touch-atmel-mxt_overlay.dtbo └── overlays.txt 1 directory, 21 files ### compress new bootfs package ### $ tar Jcf ../Reference-Minimal-Image-apalis-imx8.bootfs.tar.xz * ### clear bootfs $ cd .. $ rm -rf bootfs/ -------------------------------- b ). 修改 BSP package 中的 “u-boot-initial-env-sd” 文件,增加如下环境变量用于 Secure Boot ./ 命令方式格式 -------------------------------- ### set boot device info mmc 0:1 ### Apalis iMX8 # setenv pre_boot 'devnum=0; if mmc dev ${devnum}; then devtype=mmc; setenv load_cmd \"load ${devtype} ${devnum}:1\"; fi' ### signed os container image loading info ### Apalis iMX8 # setenv cntr_addr '0x98000000' Apalis iMX8 # setenv cntr_file 'os_cntr_signed.bin' Apalis iMX8 # setenv cntr_load '${load_cmd} ${cntr_addr} ${cntr_file}' ### authenticate signed os container image ### Apalis iMX8 # setenv auth_os 'auth_cntr ${cntr_addr}' ### device tree overlay apply ### Apalis iMX8 # setenv overlays_file 'overlays.txt' Apalis iMX8 # setenv overlays_prefix 'overlays/' Apalis iMX8 # setenv load_overlays_file '${load_cmd} ${loadaddr} ${overlays_file} && env import -t ${loadaddr} ${filesize}' Apalis iMX8 # setenv fdt_resize 'fdt addr ${fdt_addr_r} && fdt resize 0x20000' Apalis iMX8 # s etenv apply_overlays 'for overlay_file in ${fdt_overlays}; do echo Applying Overlay: ${overlay_file} && ${load_cmd} ${loadaddr} ${overlays_prefix}\${overlay_file} && fdt apply ${loadaddr}; env set overlay_file; done; true' Apalis iMX8 # setenv bootcmd_overlays 'run load_overlays_file && run fdt_resize && run apply_overlays' ### kernel/dtb loading ### Apalis iMX8 # setenv bootcmd_boot 'echo "Bootargs: \${bootargs}" && booti ${kernel_addr_r} - ${fdt_addr_r}' ### config for all boot process ### Apalis iMX8 # setenv bootcmd_run 'run pre_boot && run cntr_load && run auth_os && run bootcmd_overlays && run finduuid && run setup && run bootcmd_boot; echo "Booting from ${devtype} failed!" && false' ### auto run config ### Apalis iMX8 # setenv bootcmd 'run bootcmd_run' -------------------------------- ./ 文件方式定义 -------------------------------- --- a /u-boot-initial-env-sd 2022-08-29 17:22:27.668166883 +0800 +++ b/ u-boot-initial-env-sd 2022-08-29 17:52:18.795402902 +0800 @@ -1,4 +1,4 @@ -bootcmd=run distro_bootcmd +bootcmd=run bootcmd_run bootdelay=1 baudrate=115200 ipaddr=192.168.10.2 @@ -71,4 +71,16 @@ video=imxdpufb5:off video=imxdpufb6:off video=imxdpufb7:off setup=run loadhdp; hdp load ${hdp_addr}; run mmcargs defargs=pci=nomsi - +pre_boot=devnum=0; if mmc dev ${devnum}; then devtype=mmc; setenv load_cmd "load ${devtype} ${devnum}:1"; fi +cntr_addr=0x98000000 +cntr_file=os_cntr_signed.bin +cntr_load=${load_cmd} ${cntr_addr} ${cntr_file} +auth_os=auth_cntr ${cntr_addr} +overlays_file=overlays.txt +overlays_prefix=overlays/ +load_overlays_file=${load_cmd} ${loadaddr} ${overlays_file} && env import -t ${loadaddr} ${filesize} +fdt_resize=fdt addr ${fdt_addr_r} && fdt resize 0x20000 +apply_overlays=for overlay_file in ${fdt_overlays}; do echo Applying Overlay: ${overlay_file} && ${load_cmd} ${loadaddr} ${overlays_prefix}${overlay_file} && fdt apply ${loadaddr}; env set overlay_file; done; true +bootcmd_overlays=run load_overlays_file && run fdt_resize && run apply_overlays +bootcmd_boot=echo "Bootargs: ${bootargs}" && booti ${kernel_addr_r} - ${fdt_addr_r} +bootcmd_run=run pre_boot && run cntr_load && run auth_os && run bootcmd_overlays && run finduuid && run setup && run bootcmd_boot; echo "Booting from ${devtype} failed!" && false -------------------------------- c). 需要注意的是由于 Kernel 阶段的 Secure Boot 相关认证和加载都是基于 U-Boot 命令行来实现的, 因此如果要让这个启动机制更加安全可靠,则要让 U-Boot 保持在上述安全启动路径,而不能通过其他启动介质或者脚本来启动而绕开 Secure Boot ,比如 Toradex U-Boot 默认是使能 Distro Boot 功能的,可以自动扫描外设介质的启动脚本,那么这个功能就需要关闭掉,类似这样的 U-Boot 定制化需要自行根据实际使用场景来配置。 7 ). 部署 测试 a). 参考 这里 将上述制作的支持 Secure Boot 的 Image 通过 Toradex Easy Installer 更新到 Apalis iMX8 模块 ./ 启动后首先进入 U-Boot 命令行下,测试 AHAB 状态 -------------------------------- Apalis iMX8 # ahab_status Lifecycle: 0x0020, NXP closed sc_seco_get_event: idx: 0, res:3 No SECO Events Found! -------------------------------- ./ 然后重新启动,查看启动 log , Secure Boot 成功完整加载 U-Boot 、 Linux Kernel 和 Rootfs -------------------------------- U-Boot 2020.04-06964-g33bb8e9683 (Aug 15 2022 - 15:32:22 +0800) CPU: NXP i.MX8QM RevB A53 at 1200 MHz DRAM: 4 GiB MMC: FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2 Loading Environment from MMC... OK In: serial Out: serial Err: serial Model: Toradex Apalis iMX8 QuadMax 4GB Wi-Fi / BT IT V1.1B, Serial# 06738378 BuildInfo: - SCFW 216a2c2e, SECO-FW c9de51c0, IMX-MKIMAGE fe124bce, ATF 2fa8c63 - U-Boot 2020.04-06964-g33bb8e9683 switch to partitions #0, OK mmc0(part 0) is current device flash target is MMC:0 Net: eth0: ethernet@5b040000 Fastboot: Normal Normal Boot Hit any key to stop autoboot: 0 switch to partitions #0, OK mmc0(part 0) is current device 25877504 bytes read in 787 ms (31.4 MiB/s) Authenticate OS container at 0x98000000 43 bytes read in 12 ms (2.9 KiB/s) Applying Overlay: apalis-imx8_hdmi_overlay.dtbo 2177 bytes read in 31 ms (68.4 KiB/s) 106496 bytes read in 16 ms (6.3 MiB/s) Loading hdp firmware from 0x000000009c000000 offset 0x0000000000002000 Loading hdp firmware Complete Bootargs: console=ttyLP1 earlycon,115200 root=PARTUUID=e8daf485-02 rootwait mmcdev=0 ## Flattened Device Tree blob at 83000000 Booting using the fdt blob at 0x83000000 Loading Device Tree to 00000000fd5fc000, end 00000000fd648fff ... OK Starting kernel ... Booting Linux on physical CPU 0x0000000000 Linux version 5.4.193-5.7.0+git.f78299297185 (oe-user@oe-host) (gcc version 9.2 ... Started Start a wayland application. Reached target Multi-User System. Reached target Graphical Interface. Starting Update UTMP about System Runlevel Changes... Started Update UTMP about System Runlevel Changes. TDX Wayland with XWayland 5.7.0+build.20 (dunfell) apalis-imx8-06738378 ttyLP1 Apalis-iMX8_Reference-Multimedia-Image apalis-imx8-06738378 login: -------------------------------- b). Close 设备 经过上述测试已经确认从 U-Boot 到 Linux Kernel Secure Boot 正常,即可以在 U-Boot 命令行下面执行下面命令 Close 设备,请注意此操作之后,没有签名的 Image 就无法再在此模块加载运行了,因此请谨慎操作。 -------------------------------- Apalis iMX8 # ahab_close -------------------------------- 10 ). 总结 本文 基于 NXP iMX8 处理器演示了基于 AHAB 的 Secure Boot 功能,设计 U-Boot 和 Linux Kernel 、 Device Tree 等,至于 Rootfs 的加密,则需要配置类似 Squashfs 只读文件系统配合 initramfs 最小启动镜像进行加解密挂载启动,可以结合参考如下两篇文章,本文不做具体测试。 ./ 嵌入式 ARM 平台使用 dm-crypt 加密磁盘分区 ./ 使用 Squashfs 和 Overlayfs 提高嵌入式 Linux 文件系统可靠性 参考文档 https://git.toradex.cn/cgit/u-boot-toradex.git/tree/doc/imx/ahab/introduction_ahab.txt?h=toradex_imx_v2020.04_5.4.70_2.3.0 https://git.toradex.cn/cgit/u-boot-toradex.git/tree/doc/imx/ahab/guides/mx8_mx8x_secure_boot.txt?h=toradex_imx_v2020.04_5.4.70_2.3.0 NXP Application Note AN12312 Secure Boot on i.MX 8 and i.MX 8X Families using AHAB