安全三节的起点是一个哲学问题:软件怎么相信它运行的代码没被调过包?本节的答案是 SoC 安全架构的第一原理——信任必须有一个不会说谎的物理起点,再沿着"验一级、放一级"的链条逐级传递。本节讲清信任根的三件套构成、安全启动链的完整机制,并以 CK770 启动链的设计与形式验证做实战演示。读完你应当能设计一条启动链,并说清它的每一环凭什么可信。
先想清楚为什么软件自己当不了起点。启动时最早运行的那段代码(引导程序)如果是信任的起点,那"引导程序没被篡改"这个判断由谁做?只能由更早的代码做——无穷倒退。倒退的尽头必须是一段软件改不动、攻击者换不掉的东西。这就是硬件信任根:一段固化在芯片制造阶段的逻辑加一组物理不可改的密钥,它在复位释放的第一拍就开始工作,先于一切软件存在。
信任根的三件套分工明确。固化的引导代码(只读存储里的第一段程序):逻辑极简——取下一段固件、验签、放行或拒绝,代码越少越没有漏洞。根公钥或其哈希:烧写在一次性可编程单元(6.3 节提过的物理不可改存储)里,是整条信任链的锚点。加密引擎:哈希与验签的硬件加速,让验证快到不拖累启动。三件套里最常被低估的是"逻辑极简"这条:启动 ROM 一旦有洞,全链报废,所以业界的共识是这段代码少则几百条指令,多则千余条——少,本身就是安全属性。
验签的原理一句话够用:厂商用私钥对固件做签名,芯片用烧死在片内的公钥验证签名——私钥永远不出厂,公钥不怕公开,攻击者没有私钥就造不出合法签名。固件被改一个比特,哈希就完全变样,验签必败。这条机制把"信任传递"变成了一道数学题,而数学题可以在硅前被穷举证明——这就是 5.1 节说形式验证是启动链主场的原因。

背景:启动链设计定稿后,验证计划里出现一个争论:启动链用常规仿真验证(5.2 节的平台谱系)够不够?反对者的理由是启动链的状态空间小而规则严密——正是形式验证"窄适用面内无敌"的目标画像。
操作。 团队把启动链的验证目标翻译成形式验证的三类命题。不变量:"任何被内核执行的代码,其哈希必然通过验签"——要求工具在所有可能的状态序列里证明无一例外。可达性:"存在一条从复位到内核启动的正常路径"——防过度约束把系统锁死。不可达性:"跳过验签直达内核的状态序列不存在"——这是信任无绕过的数学表述。三类命题交给形式工具穷举,配套条件是 4.2 节编码时的断言储备与 5.1 节的状态建模纪律。
结果。 不变量与不可达性命题一次通过;可达性命题暴露一个真问题——调试锁定逻辑与一级固件的握手顺序写反了一档,导致某条启动路径在"调试已锁定但固件未递交签名"的状态下卡死。修复顺序后三类命题全绿。这个缺陷若靠随机仿真去撞,命中的概率低到不现实:它需要一条特定的失败序列才能触发,而随机激励几乎总走正常路径。
解读。 案例的价值在于演示安全验证与功能验证的方法分野:功能验证问"正常用起来对不对",安全验证问"存在不存在任何一条不安全的路径"——后者是全称命题,只能靠穷举(形式)或海量样本(仿真加加速器),启动链这种小而严密的目标天然属于前者。另一个可迁移的经验是把安全需求写成命题的能力:"信任无绕过"这种口号式需求,必须翻译成工具能穷举的具体命题才有意义——安全工程的一半功夫在把需求写成可检查的形式。
变式。若产品要支持第三方固件(开放生态设备),单一信任锚不够,要升级为多锚点加证书链——公钥哈希烧的是"根证书",逐级签发下级公钥,灵活性上升、链条管理复杂度也上升;若设备量大且固件迭代频繁,反回滚计数器的管理(谁升谁降、降级白名单)会变成产品运营问题而非纯技术问题。启动链的形态跟随业务形态,机制不变、拓扑可变。
量产体系里的信任链还长着一套密钥层级,值得交代清楚:根私钥物理离线封存(生成固件签名的终极权力,几十年用不了几次),日常签发由根签出的中间密钥承担(泄露了可吊销重签,不动根基),设备会话用的临时密钥则按需生成用完即弃(泄露窗口缩到最小)。三层各管一段时期、各有一套保管规程,CK770 的设计记录里把这套层级与启动链画在同一张图上——因为链条的强度由最弱的一层决定,只盯着芯片内的验签电路、不管厂内的密钥保管,等于前门装了金库锁、后门用胶带封。
两个理由,一硬一软。硬的理由:对称方案要求"验证者持有密钥",而启动验证者是出厂的每一颗芯片——芯片会被拆解研究,密钥从一颗芯片里被提走,所有设备的大门就都换了锁。公钥方案里芯片只存公开的验证钥匙,泄露不了秘密。软的理由:公私钥体系让"谁能给设备发固件"这件事只取决于厂家的一把私钥,密钥可以在内网保险柜里,与亿万台在现场的设备物理隔离。信任的锚点离攻击者越远,锚越稳。
远程升级的每一包固件,都要过安全启动的同一条验签门——新版固件验签通过才能接管启动,这是防"升级通道变投毒通道"的根本。两者的交接点在版本与回滚策略:升级要能回退(新版本出问题退回旧版保命),回退又不能绕过反回滚机制(退回带已知漏洞的版本等于帮攻击者降级攻击)。工程解法是版本计数器记"最低可运行版本",回退只能退到计数器之上。把这条策略在设计期写进 8.1 节的启动链记录,运营期就不会出现"安全性与可用性打架"的临场拍板。
用分级解锁,而不是一锁了之。开发批次芯片烧"开发熔丝",调试口全开;量产批次默认锁定,解锁需要通过鉴别协议——调试器出示由厂商私钥签发的解锁凭证,芯片验签后按级别开放(只读观察一级,完全控制一级)。CK770 的设计记录里还留了一条兜底:灾难恢复通道的解锁凭证单独管理、双人审批。这套机制的要点是"解锁能力本身也要过验签"——调试口是头号旁路,管理它的规则必须在信任链的管辖之下,而不是之外。
不可改的特性决定了纠错只能靠冗余与流程,不能靠擦除。工程上有三层兜底:烧写前,数值要经过双通道校验与读回比对(烧写设备确认写入值与预期一致);设计上,关键字段(根公钥哈希、版本计数基线)留镜像位或纠错位,单点翻转可被纠正;流程上,烧写工位纳入 6.3 节式的签核管理——烧错的责任链可回溯。最怕的是把"不可改"当成"不用验":一颗烧错根公钥的芯片不是报废品,是永远信任错误锚点的定时炸弹,只能物理销毁。
信任的根立住了,但"启动时可信"不等于"运行时安全"——密钥与敏感操作要在整个生命周期被隔离看管。下一节进入隔离技术的地盘。