17、安全启动与OTA:安全启动链(HABv4)、AVB(Android Verified Boot)实现、OTA升级方案(AB系统)、回滚保护机制

各位同学,今天我们来啃一块硬骨头——安全启动与OTA。说实话,这块内容在i.MX Android Automotive系统移植中,是真正决定产品能否量产的关键。我见过不少团队,功能调通了,结果卡在安全启动上,一卡就是好几周。咱们今天就把这块彻底讲透。

17.1 安全启动链:从ROM到内核的信任传递

安全启动,说白了就是「谁也别想在我的地盘上跑没签名的代码」。从芯片上电的第一条指令开始,每一级代码都要验证下一级的签名。这个链条一旦断了,系统就拒绝启动。

在i.MX8M系列上,我们用的是NXP的HABv4(High Assurance Boot version 4)。我个人习惯把HABv4理解成一个「硬件看门狗」——它不负责跑业务逻辑,只负责检查签名对不对。

核心流程:

  1. ROM代码:芯片出厂固化的,不可修改。它验证Bootloader的第一级(SPL/SCU)
  2. SPL/SCU:验证ATF(ARM Trusted Firmware)和U-Boot
  3. U-Boot:验证Linux内核和DTB
  4. Linux内核:验证Android系统(通过AVB)

嗯,这里要注意:HABv4的签名密钥分为SRK(Super Root Key)CSF(Command Sequence File)。SRK是根信任,一旦烧写到eFuse里,就再也改不了了。我曾经在项目里遇到过SRK烧写顺序搞反的情况——芯片直接变砖,只能换料重焊。所以,烧写eFuse之前,一定要三检查。

17.2 AVB(Android Verified Boot)实现

AVB是Android系统层面的安全启动机制。它和HABv4的关系是什么?我打个比方:HABv4是「小区大门保安」,AVB是「你家门口的指纹锁」。两者缺一不可。

AVB的核心是vbmeta分区。这个分区里存着所有系统分区的哈希值和签名。启动时,内核会读取vbmeta,然后逐个验证system、vendor、product等分区。

我的经验:在i.MX平台上配置AVB,最容易踩的坑是分区大小对齐。AVB要求每个分区的起始扇区必须是4K对齐的,否则验证会失败。我曾经因为这个原因,排查了整整两天,最后发现是分区表里一个数字写错了。

配置AVB的步骤大致如下:

# 1. 生成密钥对
openssl genrsa -out rsa_key.pem 2048

# 2. 生成vbmeta镜像
avbtool make_vbmeta_image \
  --key rsa_key.pem \
  --algorithm SHA256_RSA2048 \
  --include_descriptors_from_image system.img \
  --include_descriptors_from_image vendor.img \
  --out vbmeta.img

# 3. 烧写vbmeta到对应分区
fastboot flash vbmeta vbmeta.img

你想想看,如果vbmeta被篡改了,系统会直接进入「橙色警告」状态,提示用户设备不安全。在车载场景下,这绝对是不能接受的。

17.3 OTA升级方案:AB系统

车载设备不像手机,不能随便重启。OTA升级必须做到「无感」——用户开车到一半,系统在后台默默升级,下次启动时自动切换到新版本。

这就是AB系统(无缝升级)的用武之地。简单来说,系统有两套分区:slot A和slot B。当前运行在slot A,升级包写入slot B。下次启动时,bootloader检查slot B的完整性,如果没问题就切过去。

重要提醒:AB系统不是简单的「双分区」。它要求bootloader、内核、系统分区全部双份。这意味着存储空间要翻倍。我在做项目时,客户一开始说「我们只要AB系统」,结果发现eMMC容量不够,最后只能砍掉一些预装应用。

AB系统的核心逻辑在boot_control HAL里。Android 12以后,Google推荐使用Virtual AB——它不需要真正的双分区,而是通过快照和写时复制(COW)来实现。不过,i.MX平台上我建议还是用传统AB,因为Virtual AB对存储性能要求较高,i.MX8M的eMMC有时候扛不住。

17.4 回滚保护机制

回滚保护,说白了就是「不让系统降级到有漏洞的旧版本」。攻击者经常利用降级攻击——先刷回有漏洞的旧版本,然后利用漏洞提权。回滚保护就是堵死这条路。

实现方式很简单:每个系统版本都有一个版本号(rollback index),存储在防篡改的RPMB(Replay Protected Memory Block)分区里。bootloader启动时,会检查当前版本的rollback index是否大于等于RPMB里记录的值。如果小于,就拒绝启动。

组件 回滚保护方式 存储位置
U-Boot HABv4版本检查 eFuse
Linux内核 AVB rollback index vbmeta分区
Android系统 update_engine回滚保护 RPMB分区

我曾经在调试回滚保护时,遇到过一个诡异的问题:明明版本号是对的,但系统就是报「rollback failed」。后来发现是RPMB的写次数限制——RPMB的写入寿命是有限的,频繁OTA测试把RPMB写坏了。从那以后,我建议团队在开发阶段先关掉RPMB回滚保护,等量产前再打开。

17.5 整体架构图

下面这张图,是我自己总结的安全启动与OTA的完整流程。你可以把它打印出来贴在工位上。

安全启动与OTA整体架构 硬件信任根(HABv4) SRK烧写 → eFuse锁定 → ROM验证SPL → SPL验证U-Boot 系统启动验证(AVB) U-Boot验证内核 → 内核验证vbmeta → vbmeta验证system/vendor OTA升级(AB系统) 后台下载 → 写入备用slot → 标记成功 → 下次启动切换 回滚保护机制 RPMB存储rollback index → 启动时比较版本号 → 拒绝降级 注:每一层都依赖下一层的信任,形成完整的信任链

17.6 实战中的几个关键点

最后,我总结几个实战中容易出问题的地方:

  • 密钥管理:SRK私钥一定要放在离线机器上,不要联网。我见过有团队把私钥放在Git仓库里,结果被泄露了,整个安全体系形同虚设。
  • OTA测试:不要只在开发板上测。车载设备的网络环境、电源稳定性都和开发板不一样。我曾经在客户现场遇到OTA升级到一半断电的情况——AB系统虽然能恢复,但数据丢了。后来我们加了「升级前备份用户数据」的逻辑。
  • 回滚保护阈值:rollback index不要设得太死。比如你发布了V1.0,发现有个小bug,紧急发布V1.1。如果rollback index从1跳到100,那V1.0就永远回不去了。我建议每次递增1,留点余地。

我的习惯:每次做安全启动相关的修改,我都会先在QEMU模拟器上跑一遍。虽然模拟器不能完全模拟eFuse,但至少能验证签名流程对不对。等模拟器通过了,再上真机。这样能省下不少调试时间。

好了,安全启动和OTA这块内容就讲到这里。内容不少,但都是实打实的干货。你回去之后,可以先把HABv4的签名工具链搭起来,生成一对测试密钥,走一遍完整的签名和验证流程。只有亲手做过,才能真正理解这些概念。

公众号:蓝海资料掘金营,微信deep3321