4. 镜像格式与元数据

在安全Boot体系中,镜像格式不只是“把固件打包”的容器,而是承载信任链、版本策略与回滚防护的结构化载体。一个设计良好的镜像格式,应当让BootROM、一级引导、二级引导和操作系统加载器都能以统一方式解析、验签和决策。本章围绕镜像头、签名区、证书链、版本号与回滚索引五个关键字段展开,说明它们如何共同构成可验证、可升级、可回滚的镜像元数据体系。

一、核心原理:镜像元数据是信任链的“数据契约”

安全Boot的验签过程本质上是“读取元数据 → 计算摘要 → 验证签名 → 检查策略”的流水线。镜像头负责描述“这是什么、有多大、用什么算法”;签名区负责证明“内容未被篡改”;证书链负责回答“签名者是否被信任”;版本号与回滚索引负责回答“这个镜像是否允许被启动”。这五者缺一不可:缺少版本号,攻击者可降级到含漏洞的旧固件;缺少回滚索引,设备无法区分“合法回滚”与“恶意降级”。

设计原则:镜像头必须可被最小可信代码解析;签名区必须覆盖镜像头与镜像体;证书链必须可裁剪到设备信任根;版本号必须单调递增;回滚索引必须与安全存储中的计数器联动。

二、关键字段设计详解

1. 镜像头(Image Header):通常位于镜像起始偏移,包含魔数、头长度、镜像类型、镜像体长度、加载地址、入口地址、算法ID、签名区偏移、证书链偏移、版本号、回滚索引、头CRC等。魔数用于快速识别格式,头CRC用于在验签前做完整性初筛。头长度必须固定或可自描述,避免解析歧义。

2. 签名区(Signature Block):存放对镜像头与镜像体的数字签名。推荐采用“先哈希后签名”的两级结构:先对镜像体计算SHA-256/SHA-384摘要,再将摘要与镜像头关键字段一起签名。签名区应包含签名算法、签名长度、签名值以及被签名数据的范围描述,防止“签名覆盖不全”导致的部分篡改攻击。

3. 证书链(Certificate Chain):从设备信任根(如BootROM中烧录的根公钥哈希)到镜像签名证书的路径。典型链为“根CA → 中间CA → 固件签名证书”。每级证书需包含公钥、有效期、用途扩展、签名算法和上级签名。设备可只验证到信任根,无需联网。证书链应支持裁剪,避免镜像过大。

4. 版本号(Version):采用语义化版本或单调递增整数,如major.minor.patch.build。版本号必须被签名覆盖,防止被篡改。Bootloader在启动前比较镜像版本与安全存储中的当前版本,决定是否允许升级或回滚。

5. 回滚索引(Rollback Index):一个单调递增的计数器,通常与安全存储(OTP、TEE、RPMB)中的“最低允许版本”比较。若镜像回滚索引小于安全存储中的值,则拒绝启动。回滚索引与版本号可分离:版本号用于展示,回滚索引用于安全决策。

安全镜像格式与元数据布局 镜像头 Magic Header Size Image Type Body Length Load / Entry Algo ID Sig Offset Cert Offset Version Rollback Index Header CRC 签名区 Sig Algorithm Sig Length Signature Value Signed Range Hash Algorithm Body Digest Header Digest Timestamp Key ID Reserved Sig CRC 证书链 Root CA Hash Intermediate CA Leaf Cert Public Key Validity Key Usage Signature Algo Serial Number Issuer Subject Chain CRC 镜像体 Firmware Code Data Section Resource Blob Padding Body Digest Compression Encryption Alignment Body CRC Reserved End Marker 验签与启动决策流程 解析镜像头 验证签名区 校验证书链 检查版本/回滚 启动或拒绝

三、方法流程:从镜像生成到启动校验

镜像生成阶段,构建系统按固定顺序拼接:镜像头 → 证书链 → 签名区 → 镜像体。签名区中的签名值由私钥对“镜像头关键字段 + 镜像体摘要”计算得到。启动阶段,Bootloader按以下顺序执行:

  1. 读取镜像头,校验魔数与头CRC,确认格式合法。
  2. 根据头中偏移定位证书链,从信任根逐级验证证书签名与有效期。
  3. 用叶子证书公钥验证签名区,确认镜像头与镜像体未被篡改。
  4. 比较镜像版本号与安全存储中的当前版本,判断升级/回滚合法性。
  5. 比较回滚索引与安全存储中的最低允许值,拒绝降级攻击。
  6. 全部通过后,跳转到入口地址执行。

四、案例场景:OTA升级中的回滚索引联动

某设备当前运行版本为2.3.0,安全存储中回滚索引为23。服务器下发新镜像2.4.0,回滚索引24。Bootloader验签通过后,将回滚索引更新为24并写入OTP。若攻击者随后尝试刷入旧版2.2.0(回滚索引22),Bootloader读取到22 < 24,直接拒绝启动。这样即使旧镜像签名合法,也无法被用于降级攻击。

# 镜像头关键字段示例(伪代码)
struct image_header {
    uint32_t magic;          // 0x53454342 "SECB"
    uint16_t header_size;    // 固定 128 字节
    uint16_t image_type;     // 0=BL1, 1=BL2, 2=OS
    uint32_t body_length;
    uint32_t load_addr;
    uint32_t entry_addr;
    uint8_t  algo_id;        // 0=SHA256+RSA2048, 1=SHA384+ECDSA
    uint32_t sig_offset;
    uint32_t cert_offset;
    uint32_t version;        // 语义化版本编码
    uint32_t rollback_index; // 单调递增
    uint32_t header_crc;
};

五、误区与复盘

常见误区:只签名镜像体、不签名镜像头。攻击者可篡改版本号或回滚索引,使旧镜像“看起来”是新版本,或绕过降级检查。正确做法是将镜像头关键字段纳入签名范围,并在签名区中记录被签名数据的范围描述。

字段作用是否必须被签名典型长度
Magic格式识别是4 字节
Header Size解析边界是2 字节
Body Length镜像体范围是4 字节
Algo ID算法选择是1 字节
Version版本决策是4 字节
Rollback Index防降级是4 字节
Signature Value完整性证明—256/384 字节
Cert Chain信任传递—可变

复盘建议:镜像格式设计完成后,应做三项检查:一是签名覆盖范围是否包含所有安全关键字段;二是回滚索引是否与安全存储形成闭环;三是证书链是否支持离线验证与裁剪。只有这三项都满足,镜像格式才能真正支撑安全Boot的信任链与升级策略。