概述

本文主要介绍基于 ARM 架构的展锐芯片 sl8541e Android平台的 Secureboot 方案功能设计实现,其他展锐芯片的安全方案设计都差不多,以经典芯片方案授之以渔。

缩略语

android bootloader interface无法运行 android secure boot_人工智能

 1 安全启动介绍

Android 采用了业界领先的安全功能,并与开发者和设备实现人员密切合作,以确保 Android 平台和生态系统的安全。 验证启动会尽力确保所有已执行的代码均来自可信的来源(通常是设备的 OEM),以防受到攻击或者损 坏。它建立了一个完整的信任链,该信任链从硬件保护的信任根开始,延伸到引导加载程序,再延伸到 启动分区及其它验证分区。 除了确保设备运行的是安全的 Android 版本外,验证启动还会检查是否存在内置了回滚保护的正确 Android 版本。回滚保护可确保设备只会更新到更高的 Android 版本,从而帮助避免可能的漏洞持续存 在。 OEM 厂商确保用户的设备不应该用于和设计不同的目的,不能运行未经允许的软件并保护用户的有价值 的资产;终端用户需要确保自己的设备没有被篡改,是值得被信赖的。

1.1 密码学原理

数字签名是通过一些密码算法对数据进行签名,以保护源数据的做法。典型的数字签名方案包括以下三 个算法:
1. 密钥生成算法,用来输出公钥和私钥。
2. 签名算法,用私钥对给定数据进行加密来生成签名。
3. 签名验证算法,用公钥对加密过的消息进行解密验证。

android bootloader interface无法运行 android secure boot_Android_02

Secureboot 中的数字签名由哈希算法和 Rsa 算法组成。在 PC 端进行密钥的生成和部署,以及镜像的签 名。在手机端启动时完成镜像的签名验证工作。 RSA 私钥是 Secure boot 的保障,需要被小心的保存起来。

1.2 TEE 介绍

 Trusty 是一种安全的操作系统(OS),可为 Android 提供可信执行环境 (TEE)。Trusty 操作系统与 Android 操作系统在同一处理器上运行,但 Trusty 通过硬件和软件与系统的其余组件隔离开来。Trusty 与 Android 彼此并行运行。Trusty 可以访问设备主处理器和内存的全部功能,但完全隔离。隔离可以保护 Trusty 免 受用户安装的恶意应用以及可能在 Android 中发现的潜在漏洞的侵害。 Trusty 与 ARM 和 Intel 处理器兼容。在 ARM 系统中,Trusty 使用 ARM 的 Trustzone™ 虚拟化主处理器, 并创建安全的可信执行环境。

android bootloader interface无法运行 android secure boot_android_03

 Trusty 包含以下组件:  TOS,由 Little Kernel 衍生的小型操作系统内核.  Linux 内核驱动程序,用于在安全环境和 Android 之间传输数据.  Android 用户空间库,用于通过内核驱动程序与可信应用(即安全任务/服务)通信。

2 镜像签名

针对需要保护镜像的特点,采取不同的签名和验证方案。原理是相似的,不同之处在于基于加载阶段的 不同,签名方案的算法及用来验证签名的元数据的组织方式不一样。

2.1 镜像签名介绍

在引导阶段加载启动的镜像,采用展锐特有的签名验签方案。这些镜像有 fdl1.bin、fdl2.bin、u-boot-spl16k.bin、sml.bin、tos.bim u-boot.bin。这些镜像的执行处于系统早期的引导阶段, 一般都运行在安全级别 较高的模式。 Uboot 启动后,会逐步加载和校验内核及 android 系统和 modem 系统镜像,这些系统镜像均采用 Avb2.0 方案进行签名和验证。对仅读取一次的小分区(例如 boot、dtbo、recovery 和 modem bins)通常是通过将 整个内容计算哈希并签名;对于内存装不下的较大分区(如文件系统 system, vendor, product 和 socko 及 odmko 分区)可以使用哈希树的方式签名;启动时,验证流程会在将数据加载到内存时持续进行。

2.2 生成签名密钥对

安全启动方案需要配置如下的密钥来完成所有系统镜像的签名和校验。

主要有以下几对: rsa2048_0.pem & rsa2048_0_pub.pem rsa2048_1.pem & rsa2048_1_pub.pem rsa4096_vbmeta.pem & Rsa4096_vbmeta.pem

可以通过下面的命令生成密钥对: 

生成 rsa 私钥

$ openssl genrsa -out rsa2048_0.pem 2048
Generating RSA private key, 2048 bit long modulus

生成 rsa 公钥

$ openssl rsa -in rsa2048_0.pem -pubout -out rsa2048_0_pub.pem
writing RSA key

Bsp 签名是在对 chipram,bootloader 及 trusty 等目标进行编译过程中自动进行的,其中 rsa2048_0 公钥对是用来对 chipram 部分(fdl1.bin & u-boot-spl-16k.bin)签名。rsa2048_1*.pem 用来对 sml.bin, tos.bin 和 u-boot.bin 进行签名。

2.3 签名方案

安全启动对于在引导启动阶段加载的镜像使用 BSP 签名方案;其余的则采用 Android 验证启动签名方案,跟BSP签名方案类似

2.3.1 BSP 签名方案

BSP 方案签名工具主要有 packimage.sh 和 sprd_sign 及 imageheaderinsert 两个工具;工具在成功编译后将 其安装在“out / host / linux-x86 / bin”目录中,会在编译过程中自动参与系统镜像的签名。

  • Packimage.sh:起始签名脚本,包含了工程配置信息,需要签名的可信固件,签名方式等,会去调用 imageheaderinsert 工具对镜像头部插入用来校验的元数据和尾部插入签名证书。
  • Imageheaderinsert:执行将检验需要的元数据插入到镜像头文件的工具。
  • Sprd_sign:使用密钥对镜像进行签名的工具。

BSP 签名方案签名的镜像包括:spl、fdl1、uboot、fdl2、sml、tos、vbmeta。 对可信固件签名后的格式如下:

android bootloader interface无法运行 android secure boot_android_04

 2.3.2 OTA包编译签名和升级

OTA 编译时,OTA 包编译系统使用 target 目录的内容生成新的 system,vendor 和 product 分区镜像,这样 为了保持 OTA 包中的版本和将来从 PRODUCT_OUT 目录打包到 pac 包中的版本保持一致,需要用 OTA 编译生成的新的镜像替换 PRODUCT_OUT 下的 system,vendor,product,vbmeta_system 和 vbmeta_vendor 镜像。 相关的脚本位于 vendor/sprd/build/tasks/sprdbuildota.mk

$(hide) -$(ACP) $(SPRD_BUILT_TARGET_FILES_PACKAGE)/IMAGES/vbmeta_system.img
$(PRODUCT_OUT)/vbmeta_system.img -rfv
$(hide) -$(ACP) $(SPRD_BUILT_TARGET_FILES_PACKAGE)/IMAGES/vbmeta_vendor.img
$(PRODUCT_OUT)/vbmeta_vendor.img -rfv

System、vendor 和 product 镜像则是通过使用 target 目录的动态分区镜像重新编译生成 PRODUCT_OUT 下的 super.img 完成同步:

lpmake --metadata-size 65536 --super-name super --metadata-slots 2 --device super:4299161600 --group group_unisoc:4299161600 -
-partition system:readonly:1345548288:group_unisoc --image
system=out/target/product/s9863a1h10/obj/PACKAGING/target_files_intermediates/s9863a1h10_Natv-target_fileseng.wenquan.zhang/IMAGES/system.img --partition vendor:readonly:405712896: group_unisoc --image
vendor=out/target/product/s9863a1h10/obj/PACKAGING/target_files_intermediates/s9863a1h10_Natv-target_files-eng.wenquan.zh
ang/IMAGES/vendor.img --partition product:readonly:454574080:group_unisoc --image
product=out/target/product/s9863a1h10/obj/PACKAGING/target_f iles_intermediates/s9863a1h10_Natv-target_fileseng.wenquan.zhang/IMAGES/product.img --sparse --output out/target/product/s9863a1h10/super.img "

所以编译完成 OTA 包之后,PRODUCT_OUT 目录的 system, vendor 和 product 分区的内容和 super.img unpack 出来的 system vendor 和 product 镜像应该是不一致的,只需要确认 super image unpack 出来的 system vendor 和 product 镜像的 metadata 和 PRODUCT_OUT 目录下的 vbmeta_system&vendor 镜像的 metadata 一致即可。

3 安全启动过程

3.1 AP 安全启动过程

系统从 AP 的 Romcode 开始允许,启动时运行在安全模式,在逐级加载和校验安全事件的镜像之后,再 引导正常事件的系统镜像,直到内核和安卓系统启动完毕。

安全部署的设备会在 AP Soc 的 ROTPK efuse 区域写入用于验证 spl 镜像签名的第一级公钥 (rsa2048_0_pub.bin)的哈希。

  •  Romcode 作为信任根的一部分,是不能被重写(篡改)的,是安全启动的基础。上电后 Romcode 加 载 spl 镜像,从 spl 分区读取第一级公钥,并计算其哈希和 ROTPK 记录的公钥哈希比较,一致才能 使用这个公钥来验证 spl 镜像的数字签名。
  • SPL 镜像作为 secureboot loader 运行在 Secure IRAM,负责初始化 DRAM 并将 sml(Arm Trusted firmware),tos(trusty os)和 uboot(REE bootloader)加载到 DRAM,同时负责校验这三个系统镜像 的合法性;校验通过后将执行 sml。
  • Sml 运行 tos,tos 运行内置的 TA,然后 tos 返回到 sml,sml 返回到 uboot 执行。  Uboot 运行在 Hypervisor 模式,负责检查设备状态,加载和校验 dtbo 和 boot/recovery 镜像的内容, 并准备验证启动 Android 系统的内核参数。
  • Uboot 引导内核启动后,内核将负责验证 Android 系统分区,验证通过后将其挂载为只读的系统分 区。
  • Android 启动后,modem_control 服务负责校验和加载 modem 子系统的固件。

3.2 Modem 类子系统的安全启动

对于不含 ROM 的子系统,通常需要主控配合来完成子系统的安全启动流程。大的设计思路是

  • 通过 Register Firewall 限制子系统的启动
  • 通过 DDR Firewall 来限制子系统的地址访问范围,通常仅访问自己的地址空间。
  • 镜像先通过 AP 子系统加载到 DDR,然后限制这段空间的访问,验签成功后启动相应的子系统。避 免验签和运行的是不同的子系统。

这类子系统常见的如 Modem,Audio,VDSP,GPU firmware,SCP 等。

android bootloader interface无法运行 android secure boot_android_05

4. 生产部署

安全启动相关的数据在产线 eFuse 分区需要写入的内容如表 。 

android bootloader interface无法运行 android secure boot_人工智能_06

5. OTA升级和防版本回退

终端用户通过安全更新来获取新的发布版本,新版本除了配置防回退的版本外,也都需要合法的签名, OTA 更新包也会做整体的签名和验证,保证用户更新版本的合法性和完整性。

即使更新流程完全安全,攻击者仍可能会利用非永久性系统漏洞来手动安装更易受攻击的旧版系统,重 新启动进入易受攻击的版本,然后通过该版本来安装永久性漏洞。在这种情况下,攻击者可通过这种漏 洞永久拥有相应设备,并可以执行任何操作(包括停用更新)。

防范这类攻击的保护措施称为“回滚保护”。“回滚保护”通常通过以下方式实现:使用防篡改的存储空 间来记录最新的版本,并在版本低于记录的版本时拒绝启动系统。

方法1:谷歌OTA方案自带可参考,也就是OTA升级代码里面有build/tools/releasetools/ota_from_target_files一个升级脚本,函数 script.AssertOlderBuild(ts, ts_text)会校检时间戳。

方法2:展锐支持对每一个分区进行防版本回退的配置,放回退的版本号 s 可以在下面的代码中配置:

  • Bsp/build/packimage_scripts/config/version.cfg
  • Vendor/sprd/proprietaries-source/packimage_scripts/signimage/sprd/config/version.cfg

 防回退版本会编译到安全启动的元数据中,在安全启动过程中,系统会在各个启动阶段比较当前启动的 系统镜像的版本号是否大于等于记录在 efuse(trusty firmware)和 rpmb 分区(avb2.0 签名镜像)的版本 号,只有版本号满足条件,才会允许启动,且在系统完全启动后,如果时新的版本号,则更新到一次性 可写区域。

注:  这是参考相关文档总结出的精华,若有侵权问题,请立即联系我删除该文档