4. Sitara启动镜像格式与签名机制
在TI Sitara(AM335x/AM437x/AM57xx等)的安全启动体系中,ROM Code是信任链的起点。它上电后首先从选定的启动介质(MMC、SPI、NAND、UART等)读取一段固定格式的头部数据,再据此定位并加载真正的启动镜像。理解这套镜像格式与签名机制,是后续做安全启动配置、固件升级和故障排查的基础。
Boot Image的整体布局
Sitara的启动镜像(通常称为Boot Image或MLO镜像)并不是裸的二进制代码,而是一个带有元数据的容器。它由三部分组成:最前面是GP Header(General Purpose Header,通用头部),紧接着是证书区(Certificate,仅在安全启动时存在),最后才是实际要执行的镜像数据(如SPL/U-Boot或应用固件)。ROM Code按固定偏移解析这些区域,因此各部分的长度、对齐和字节序都必须严格符合规范。
GP Header是ROM Code最先读取的结构,它告诉ROM“镜像有多大、要加载到内存的哪个地址”。其核心字段包括:
- Image Size:镜像总长度(含头部与证书),决定ROM要搬运多少字节。
- Load Address:镜像在目标内存(如片上SRAM或DDR)中的加载地址。
- Header类型/标志:区分普通镜像与安全镜像,决定后续是否走证书校验流程。
需要特别注意的是,GP Header本身不携带签名,它只是“导航信息”。真正的完整性保护由证书区承担。因此攻击者若篡改GP Header中的Load Address,可能改变加载位置,这也是为什么安全启动方案中往往要求对头部一并做校验或使用固定加载地址。
证书结构与签名算法
在安全启动模式下,GP Header之后紧跟一段证书(Certificate)。Sitara的证书采用TI定义的X.509风格结构,但为嵌入式场景做了裁剪。它主要包含:
- 证书头:标识证书类型、长度和版本。
- 公钥/密钥信息:用于验证镜像签名的公钥或密钥哈希。
- 镜像哈希:对镜像数据计算得到的摘要值。
- 数字签名:用私钥对镜像哈希加密后的结果。
签名算法方面,Sitara安全启动通常使用RSA(如RSA-2048)配合SHA-256摘要。流程是:先对镜像数据做SHA-256得到哈希,再用私钥对该哈希做RSA签名,把签名和哈希一起写入证书区。ROM Code在加载时用烧录在芯片内部的一次性可编程(OTP)eFuse中的公钥哈希来验证证书中的公钥是否可信,再用该公钥验证签名,最后重新计算镜像哈希并与证书中的哈希比对。只有全部通过,才会跳转到镜像入口执行。
镜像完整性校验流程
把上面的机制串起来,ROM Code的校验流程可以概括为:读取GP Header → 定位证书 → 用eFuse公钥哈希验证证书公钥 → 用公钥验证镜像签名 → 重算镜像哈希并比对 → 通过则跳转执行,失败则进入错误处理(如尝试备用启动介质或停机)。下面这张图展示了从介质读取到最终跳转的完整信号与数据流。
工具链概览
在实际开发中,我们不会手工拼装这些二进制结构,而是借助TI提供的工具链完成镜像生成与签名。常用的工具包括:
- mkimage:U-Boot自带的镜像打包工具,可生成带GP Header的镜像,支持指定加载地址和入口地址。
- signGP / ti-signed-image:TI提供的签名工具,负责在镜像中插入证书区并完成RSA签名。
- openssl:用于生成RSA密钥对、计算SHA-256摘要和验证签名,是密钥管理的基础工具。
- CCS / UniFlash:用于将公钥哈希烧录到eFuse,以及将签名后的镜像写入启动介质。
一个典型的签名命令流程如下(示例参数,实际使用时需替换为项目中的密钥和镜像路径):
# 1. 生成RSA私钥和公钥
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# 2. 计算公钥哈希(用于烧录eFuse)
openssl dgst -sha256 -binary public.pem | openssl dgst -sha256 -hex
# 3. 用mkimage打包镜像(带GP Header)
mkimage -A arm -O linux -T firmware -C none \
-a 0x402F0400 -e 0x402F0400 \
-n "SPL" -d spl.bin spl-gp.bin
# 4. 用TI签名工具插入证书并签名
signGP -key private.pem -cert cert.bin spl-gp.bin spl-signed.bin
执行完成后,spl-signed.bin就是可写入启动介质的最终镜像。ROM Code上电后会按前述流程完成校验。如果校验失败,串口通常会输出类似“Authentication failed”或“Image signature verification failed”的提示,此时应优先检查eFuse中烧录的公钥哈希是否与签名所用公钥匹配,以及镜像是否在签名后被再次修改。
总结来说,Sitara启动镜像格式的核心是“GP Header定位 + 证书保护 + eFuse信任根”。GP Header负责让ROM知道去哪里加载,证书负责证明镜像未被篡改,eFuse则确保验证所用的公钥本身可信。三者缺一不可,共同构成了从ROM Code到SPL、再到U-Boot和应用固件的完整信任链。掌握这套格式与工具链,是后续进行安全启动配置、固件加密升级和故障定位的必要前提。