热度 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