【分享】Linux方案的安全启动

网关设备, 语音中控设备等
Post Reply
Jason
Posts: 5

前言

在 IoT 中保证设备安全性的重要一环就是保证代码的完整性,不让恶意代码影响业务的正常逻辑。一般而言是及时修复现有攻击面所面临的漏洞,比如浏览器、蓝牙、调试接口;另一方面需要确保的是即便恶意代码获取了执行权限,也无法修改系统镜像进行持久化。针对这点所构造的安全方案通常称为 Secure Boot。

Secure Boot

Secure Boot 顾名思义就是安全启动,确保设备启动之后所加载执行的代码都是可信的。其中涉及的主要概念有两个:信任链和信任根。前者保障执行流程的可靠交接,后者则保障初始信任代码的可信。

信任链

可信启动的一个核心思路就是在当前启动代码加载下一级代码之前,对所加载的代码进行完整性校验,并且使用PKI公钥基础设施进行核实。这些启动代码通常可以分为若干个阶段(stage),例如在ARM中有:

  • BL1:CPU复位之后执行的第一段代码,即复位向量所指向的位置。通常该位置在ROM里,执行过程中将自身数据复制到SRAM,并进行最小的初始化,比如寄存器和CPU等的初始化操作,随后加载BL2代码执行。
  • BL2:主要工作是执行架构和平台相关的初始化,比如配置MMU完成内存地址和权限的映射,完成外部存储器的初始化等。随后加载BL3代码并执行。
  • BL3:执行运行时的初始化操作,并加载内核执行。

信任根

信任链的作用是对下一阶段要执行的代码进行校验,那么就会回归到一个问题:最初的代码由谁来校验?其实上面有提到,最初的代码即BL1的代码,是保存在BootROM中,出厂烧写后不可修改的。因此BootROM代码需要尽可能简单,只需要进行必要的初始化操作。

这样一来,信任根就变成了可以烧写BootROM代码的芯片厂商。信任是可以传递的,芯片厂商作为信任根将代码执行权限交给下一级之后,比如OEM厂商,下级代码就拥有了信任链所有权,也就是说下级代码就变成了新的信任根。但是ROM的空间有限,所以通常还使用OTP(One-Time-Programmable)来保存不同阶段的签名信息。OTP是支持一次性编程的硬件,如多晶硅熔断器(poly-silicon fuses),烧毁之后无法恢复,从而保证写入后无法被篡改。

uboot 引导内核

方案一: AVB

AVB 是 Android Verfied Boot 的简称,谷歌设计的一套固件校验流程,主要用于校验 boot system 等固件。

在整个AVB验证的过程中,需要借助于vbmeta分区,需要增加vbmeta分区和vbmeta.img镜像。
可使用avbtool提供的工具查看编译出来的vbmeta.img镜像内容:

Code: Select all

$ ./scripts/avbtool info_image --image out/vbmeta.img 
Minimum libavb version:   1.0
Header Block:             256 bytes
Authentication Block:     576 bytes
Auxiliary Block:          4480 bytes
Algorithm:                SHA256_RSA4096
Rollback Index:           0
Flags:                    0
Release String:           'avbtool 1.1.0'
Descriptors:
    Hash descriptor:
      Image Size:            12744704 bytes
      Hash Algorithm:        sha256
      Partition Name:        boot
      Salt:                  f5612dab28bd643de91d2aded2ea06148668da7bd5fc25405a09cc03896603fd
      Digest:                beefe6ffe61e85daedeabe543f1eac1a5de12768c206d125ef9fea583f698303
      Flags:                 0

vbmeta分区描述内容:

截图 2023-11-14 14-25-22.png

vbmeta镜像的加解密过程简述:

  • 加密过程
    根据摘要信息生成private key(私钥),利用私钥extra生成public key(公钥),同时利用私钥对vbmeta镜像进行签名(signature),并将公钥和计算的hash写到vbmeta镜像的header中。
  • 解密过程
    先验证公钥是否平台签发的(公钥比对,防止vbmeta镜像的公钥和签名都被篡改掉),然后利用公钥进行解密签名。
    截图 2023-11-14 14-38-15.png

AVB中对boot.img 镜像的加密和解密过程:
编译制作boot.img时进行签名时,先通过SHA-256算法得到一个散列值digest(十六进制长度为64),然后用带RSA算法的私钥加密这个digest,并生成签名后和公钥一起加在镜像的footer尾部上,编译时也会将这个digest存一份到vbmeta.img镜像中。

在bootloader中加载boot镜像时,先从vbmeta.img镜像分区中读出boot descriptor的digest,然后利用boot镜像中的公钥进行解密计算得到一个digest,和自己SHA-256计算得到的digest进行比较;

digest相等则说明boot.img是平台编译签名的,如果不相等,则boot.img可能是被篡改过的,boot启动失败。
最后再计算一次boot镜像内容的hash是否相等,hash不相等,启动也是失败。

截图 2023-11-14 14-40-33.png

内核的cmdline 也会打印 digest

Code: Select all

androidboot.vbmeta.digest=51424ad5d01cefe1cb5a4d1b8d1fd94e86f7ee247bfd071225a77c86d9eea481

方案二: FIT

FIT(flattened image tree)是U-Boot支持的一种新固件类型的引导方案,支持任意多个image打包和
校验。FIT 使用 its (image source file) 文件描述image信息,最后通过mkimage工具生成 itb
(flattened image tree blob) 镜像。its文件使用 DTS 的语法规则,非常灵活,可以直接使用libfdt 库和
相关工具。

简单来说就是存储 boot.img 的一些签名信息跟摘要值存放在 its 文件中:

Code: Select all

signature {
	hashed-strings = <0x00000000 0x000000da>;
	// 指定被签名内容
	hashed-nodes = "/", "/configurations/conf", "/images/fdt",
"/images/fdt/hash", "/images/optee", "/images/optee/hash", "/images/uboot",
"/images/uboot/hash";
	// 进行签名的时间、签名者、版本
	timestamp = <0x5e9427b4>;
	signer-version = "2017.09-g8bb63db-200413-dirty #cjh";
	signer-name = "mkimage";
	// 签名结果!!(采用sha256+rsa2048)
	value = <0x78397d5d 0xb9219a0b 0xa7cb91a7 0xe1f32867 0x62719d9b
0x8901200c 0xfcbac03a 0x1295ccc8 0x1cff9608 0xdf5f69d2 0x21391225 0x7af10ca7
0x5527864f 0xb13f527e 0xddf9ee62 0xea50199d 0x00000003 0x35362c72 0x00000004
0x00000017 0x77617265 0x00000002 0x00000009 0x23616464 0x6d616765 0x73006172
0x6f6e006c 0x72790064 0x61636b2d 0x7265006c 0x006b6579 0x69676e2d 0x706f7369
0x7a650074 0x75650073 0x69676e65 0x73686564 0x642d7374 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000>;
algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "fdt", "firmware", "loadables";

};

内核引导文件系统 DM-V

使用DM-V 原理的一个前提是boot.img 必须是安全的, 该方案会在boot.img 中打包一个 ramdisk, ramdisk 的安全由 AVB 保证,ramdisk 中利用 veritysetup 工具验证后续挂载固件。

DM-V 的 优点在于,校验速度快,固件越大,效果越明显
缺点是: DM-V 是适用于只读文件系统,Boot 跟 rootfs 的体积会增大

基本原理是使用 Device-Mapper-Verity 技术,该机制会对校验固件进行4K划分,并对每个4K数据片进行hash 机算,迭代多层,并生成对应的Hash-Map(30M 以内) 和 Root-Hash, 创建基于DM-V 的虚拟分区时,会对 Hash-Map 进行校验,保证Hash-Map 无误。

截图 2023-11-14 14-53-40.png

分区被挂载后,由数据访问时, 会对数据所在的4K分区进行单独的HASH校验, 当校验出错的时候,返回I/O错误,无法使用对应的位置,跟文件系统损坏一样。

ramdisk 验证 rootfs的过程

截图 2023-11-14 14-57-00.png

Tags:
Post Reply