i.MX6中的安全启动

i.MX6中的安全启动


在为嵌入式系统开发任何项目时,开发人员必须解决两个其他问题:

  • 如何防止固件欺骗产品;
  • 如何保护软件免受复制。

本文介绍如何保护i.MX6处理器免于更改产品中的引导程序,并使复制固件的过程复杂化。



介绍


在裸机项目[1]主要帮助硬件复杂性(既存在于微控制器中又存在于外部)的情况下,为了保护知识产权。在信誉良好的网站上提供了示例[2]使用了其他软件方法,例如[3],但是它们基于未知的保护机制。这是由于设备的低计算能力和实现动态固件生成的不便。

当SoC在Linux之类的操作系统中发挥作用时,需要同时在几个级别上组织保护:

  • 最终应用程序级别
  • 操作系统级别
  • 引导程序级别

在获得任何级别的访问权限的情况下,很容易影响进一步级别的软件并更改级别间的交互。
最简单的例子:安装在Linux上的软件通过UART协议(例如,通过/ dev / ttyACM0)与微控制器通信。获得系统访问权限的攻击者使用相同的UART资源,并重复发送随机发送的程序包。或者,例如,如果驱动程序内置在内核中,则攻击者会通过以另一种方式重写UART驱动程序代码来重新编译内核。最终的应用程序不知道发生了什么。

什么是安全启动,为什么需要它?


目标系统上软件的第一级保护是安全启动。在下文中,将说明i.MX6系列处理器的安全启动。

i.MX6中的安全启动是通过高保证启动(HAB)实现的,并且可以执行两个功能:

  • 安全启动
  • 加密下载。

在本文中,我将介绍确保安全加载处理器的过程。I.MX6还实现了提供引导加载程序加密的算法。但是,其使用要求为每个产品生成唯一的引导加载程序,因为它为每个处理器使用唯一的加密功能。这是该系列中的一个不方便的过程,因此我没有对其进行描述。如果您对此话题有什么要说的,我将很高兴听到。
安全启动试图确保引导程序开始于你的产品,与内核装进去。

关于我给安全启动的定义。安全启动并不能使您免于复制产品。是的,这使过程更加困难,但难度不大。引导加载程序无法对整个FS进行签名,因此它无法在OS级别以及最终应用程序级别提供保护。一切都经典地进行:通过非对称加密。我将用手指来描述该过程;可以在[4]中更深入地阅读它。引导加载程序指示HAB的脚本,指示已签名的存储区域,以及数字签名所在的位置。公钥已预先放置在一次性可编程(OTP)处理器内存中。加载时,脚本使用附带的数字签名和有线密钥检查指定的存储区域。如果测试失败,则处理器不会开始下载。还必须通过在OTP存储区中设置一个位来激活HAB操作。

安全启动的缺点:

  • 如果未激活HAB,则固件仍将启动。这意味着无需添加。保护方法您的固件将在产品的副本上运行。为了防止这种情况的发生,引导加载程序必须在启动时独立激活HAB。但是,通过将USB闪存驱动器插入另一个产品中而忘记刷新公钥,则可以将处理器扔掉。
  • 访问处理器内存时,您可以复制公共密钥,这足以复制产品。

实作


总体上,Internet 有很多关于实现主题的英语文章[5] [6],但是没有一次提出的建议方法立即出现,并且与软件的链接也开始消失,因此我决定将其保存为文章,主要是为我自己,当以后我会再谈这个问题。

首先,您需要下载以下软件:代码签名工具[7]和用于生成密钥和签名的必要脚本。在指定的归档文件中,我删除了所有不必要的实用程序和库,因为我们的任务有很多未使用的东西。

接下来,您需要生成密钥:

cd ${CST_PATH}/release/keys
echo ${serial} > serial //8 ,     
echo ${password} >  key_pass.txt //   ,     
echo ${password} >>  key_pass.txt //
./hab4_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)?: n
Enter key length in bits for PKI tree: 4096
Enter PKI tree duration (years): 10
How many Super Root Keys should be generated? 4
Do you want the SRK certificates to have the CA flag set? (y/n)?: y
 ../linux64/bin/srktool -h 4 -t SRK_1_2_3_4_table.bin -e SRK_1_2_3_4_fuse.bin \
 -d sha256 -c ./SRK1_sha256_4096_65537_v3_ca_crt.pem,\
./SRK2_sha256_4096_65537_v3_ca_crt.pem,./SRK3_sha256_4096_65537_v3_ca_crt.pem,\
./SRK4_sha256_4096_65537_v3_ca_crt.pem -f 1

密钥生成脚本提出了以上问题。我举了一个标准选项的例子。它们的答案确定如何调用生成的键和生成的键的参数。考虑使用其他命令。接下来,我们读取写入处理器所需的公共密钥。为此,我们将使用[5]中的便捷脚本

cd ${CST_PATH}/release/linux64/bin
./var-u-boot_fuse_commands.sh 
fuse prog 3 0 0xFFFFFFFF //   uboot.
fuse prog 3 1 0xFFFFFFFF //     
fuse prog 3 2 0xFFFFFFFF //       .
fuse prog 3 3 0xFFFFFFFF //  -   .
fuse prog 3 4 0xFFFFFFFF //      .
fuse prog 3 5 0xFFFFFFFF //
fuse prog 3 6 0xFFFFFFFF  //
fuse prog 3 7 0xFFFFFFFF //

此任务可以应用于具有集成SPL或具有单独的SPL和uboot(例如rocko版本)的uboot。我正在编写一个发行版,以便您知道它们在哪里用作标准。如果您自己编译uboot,则很有可能将您的SPL集成到uboot中。defconfig引导加载程序中的重要一点是添加以下选项:

CONFIG_SECURE_BOOT=y
CONFIG_SYS_FSL_HAS_SEC=y 
#define CONFIG_SYS_FSL_SEC_COMPAT    4 /* HAB version */
#define CONFIG_FSL_CAAM
#define CONFIG_CMD_DEKBLOB
#define CONFIG_SYS_FSL_SEC_LE
#define CONFIG_FAT_WRITE

这些选项激活用于使用硬件模块的驱动程序。一切就像在Linux的menuconfig中一样。编译引导加载程序时,请使用详细模式(删除V =1。具有此参数的程序集已在指南中编写。但是,我自己对其进行了清理)。在这种情况下,有关入口点地址和记录数字签名所需的其他事项的信息将添加到编译日志中。编译后,我们需要以下输出文件:

  • u-boot-ivt.img
  • u-boot-ivt.img.log
  • 声压级
  • SPL.log

将它们复制到$ {CST_PATH} / release / linux64 / bin。接下来,您需要运行一个相当简单的脚本。

脚本过程的详细说明
(*.csf). , :

  • .

. , ( ).

:

Image Name:   U-Boot 2019 //  U-boot
Created:      XXXXXX
Image Type:   ARM U-Boot Firmware with HABv4 IVT (uncompressed)
Data Size:    339904 Bytes = 331.94 KiB = 0.32 MiB
Load Address: 17800000
Entry Point:  00000000
HAB Blocks:   0x177fffc0   0x0000   0x00051020

Image Type:   Freescale IMX Boot Image //  SPL
Image Ver:    2 (i.MX53/6/7 compatible)
Mode:         DCD
Data Size:    61440 Bytes = 60.00 KiB = 0.06 MiB
Load Address: 00907420
Entry Point:  00908000
HAB Blocks:   00907400 00000000 0000cc00
DCD Blocks:   00910000 0000002c 00000004

«HAB Blocks». ,

cd ${CST_PATH}/release/linux64/bin
./cst --o u-boot_csf.bin --i u-boot.csf
cat u-boot-ivt.img u-boot_csf.bin > u-boot_signed.img


据我所记得,在集成SPL的情况下,很可能一切都以相同的方式工作,但是值得一试。我现在不记得了,撰写本文时也没有开始编译。

cd ${CST_PATH}/release/linux64/bin
SOC=mx6 ./var-som_sign_image.sh SPL u-boot-ivt.img

根据脚本的结果,您将获得两个文件:SPL_signed,u-boot-ivt.img_signed,必须将其写入目标系统的磁盘中。我将录制脚本的示例应用于目标系统。没有须藤,以免意外射中你的腿。

dd if=SPL_signed of=${DEVICE(/dev/sd*)} bs=1K seek=1; sync
dd if=u-boot-ivt.img_signed of=${DEVICE(/dev/sd*)} bs=1K seek=69; sync

写入空白介质后,您应该获得没有内核的引导程序,该引导程序将崩溃到控制台,因为它将找不到dtb和内核。在控制台中,您可以检查所做的工作是否真的有效。在发生事件的情况下-出现了问题。重要说明:如果引导加载程序是在没有HAB支持的情况下编译的,则也不会出现错误。

hab_status
HAB Configuration: 0xf0, HAB State: 0x66
No HAB Events Found!

最后一步是激活HAB,注意是一次性命令,无法修复,因此请小心

fuse prog 0 6 0x2

结论


我没有开始描述将所有这些都集成到yocto中的过程,但是我必须保守秘密。但是,这是可行的,并且不需要太多时间。

参考


[1]直接在硬件上运行的裸机嵌入式软件,无需以操作系统的形式进行任何抽象
[2] we.easyelectronics.ru/Soft/zaschita-ustroystva-ot-vzloma-i-kopirovaniya.html
[3 ] ] habr.com/zh/post/350602
[4] HAB4_API.pdf,网址为github.com/BMValeev/CST_TOOL
[5] variwiki.com/index.php?title=High_Assurance_Boot
[6] boundarydevices.com/high-assurance-boot -hab-dummies
[7] github.com/BMValeev/CST_TOOL

All Articles