3. 数据安全策略总览
说实话,很多工程师把数据安全想得太简单了。
他们觉得,只要烧录时把固件加密了,就万事大吉。但我在实际项目中见过太多翻车案例——有人加密了烧录文件,却忘了校验签名;有人做了签名校验,但启动链上有个环节没锁住。结果呢?产品被抄板、固件被提取、系统被植入后门。
这一章,我就带你捋一遍从烧录到运行的完整安全链路。说白了,就是三个核心环节:签名校验、加密存储、安全启动链。这三者缺一不可,环环相扣。
核心观点:数据安全不是单点防护,而是链路防护。攻击者只要攻破一个环节,整条链就废了。所以,每个环节都必须独立可靠,且相互验证。
3.1 签名校验:确保固件的“身份”和“完整性”
签名校验是安全链的第一道门。它的作用很简单:确认固件是谁签发的,以及固件有没有被篡改过。
我习惯把签名校验比作“身份证+防伪标签”。身份证证明你是谁,防伪标签证明这东西没被换过。
3.1.1 签名与验签流程
标准的签名流程是这样的:
- 生成密钥对:私钥留在安全服务器上,公钥烧进芯片的 OTP(一次性可编程)区域。
- 计算哈希:对固件镜像做 SHA-256 或 SHA-512 哈希,得到一个固定长度的摘要。
- 签名:用私钥对哈希值做 RSA 或 ECDSA 签名,生成签名数据。
- 打包:将固件 + 签名数据 + 公钥证书(可选)打包成一个烧录文件。
芯片端验签时,反过来做:
- 用烧录在 OTP 里的公钥,解密签名数据,得到原始哈希值。
- 对收到的固件重新计算哈希。
- 比对两个哈希值。一致则通过,不一致则拒绝启动。
我的经验:公钥一定要烧在 OTP 里,而且烧完后要锁死。我曾经见过一个项目,公钥放在 Flash 里,结果攻击者直接替换了公钥,用自己的私钥签了个恶意固件……嗯,那项目后来重做了。
3.1.2 常见签名算法对比
| 算法 | 密钥长度 | 签名速度 | 验签速度 | 安全性 | 典型场景 |
|---|---|---|---|---|---|
| RSA-2048 | 2048 bit | 慢 | 快 | 高 | 服务器签名,芯片验签 |
| RSA-4096 | 4096 bit | 很慢 | 较慢 | 极高 | 高安全等级场景 |
| ECDSA-P256 | 256 bit | 快 | 快 | 高 | 资源受限的嵌入式设备 |
| ECDSA-P384 | 384 bit | 较快 | 较快 | 极高 | 车规、工业控制 |
我个人更倾向于 ECDSA-P256。为什么?因为它在安全性和性能之间平衡得最好。你想想看,很多 MCU 主频才几百兆赫兹,跑 RSA-4096 验签可能要几百毫秒,用户都开机了还在等验签……这体验太差了。
3.2 加密存储:让固件“看不见、读不懂”
签名校验解决了“固件是不是原厂的”问题,但没解决“固件内容会不会被偷看”的问题。攻击者如果通过 JTAG 或其它接口把 Flash 里的二进制读出来,虽然改不了,但可以逆向分析。
加密存储就是干这个的——让固件在存储介质上是密文,只有运行时才解密。
3.2.1 加密方案选型
嵌入式设备常用的加密方案有两种:
- 对称加密(AES):加密和解密用同一个密钥。速度快,适合大数据量。密钥必须安全存储。
- 非对称加密(RSA/ECC):加密和解密用不同密钥。速度慢,适合小数据量或密钥交换。
在实际项目中,我几乎只用 AES-256-GCM。为什么?
- AES-256 足够安全,目前没有有效攻击手段。
- GCM 模式自带认证标签,能检测密文是否被篡改。这相当于“加密 + 校验”二合一。
注意:千万不要用 ECB 模式!ECB 模式下,相同的明文块会生成相同的密文块。攻击者可以通过统计规律推断出固件结构。我曾经接手过一个项目,就是用 ECB 加密的,攻击者只用了两天就还原出了固件的大致布局……
3.2.2 密钥管理:安全链的“命门”
加密算法再强,密钥泄露了也白搭。密钥管理是加密存储中最容易被忽视、也最容易出问题的地方。
我总结了几条密钥管理的“铁律”:
- 密钥永远不落盘:密钥只在芯片内部使用,不能以明文形式出现在 Flash、文件系统或日志中。
- 硬件隔离:使用芯片自带的 HUK(硬件唯一密钥)或 eFuse 存储密钥。软件无法直接读取。
- 密钥分级:不要用同一个密钥加密所有东西。我习惯分三级:
- 根密钥:烧在 OTP 里,用于解密二级密钥。
- 固件密钥:由根密钥解密后加载到 RAM,用于解密固件。
- 会话密钥:每次启动随机生成,用于加密运行时临时数据。
- 密钥轮换:产品迭代时,新固件要用新密钥加密。旧密钥只用于兼容旧版本。
3.3 安全启动链:从 BootROM 到应用的“信任传递”
签名校验和加密存储都是“点”上的防护。安全启动链则是把这些“点”串成一条“线”,确保从芯片上电的第一条指令开始,每一步都是可信的。
安全启动链的核心思想是:信任链的每一级都验证下一级的完整性和合法性,然后才把控制权交出去。
3.3.1 典型的安全启动链结构
一个标准的嵌入式安全启动链通常包含以下层级:
- BootROM:芯片出厂固化的只读代码。上电后第一个执行。它验证下一级 Bootloader 的签名。
- 一级 Bootloader(SPL/FSBL):初始化 DDR、时钟等基础外设。验证二级 Bootloader 的签名。
- 二级 Bootloader(U-Boot/ATF):加载操作系统内核。验证内核镜像的签名。
- 操作系统内核:验证文件系统或应用分区的签名。
- 应用程序:运行时验证动态加载模块或配置文件的签名。
每一级都只信任上一级传递过来的公钥或哈希值。如果任何一级验证失败,芯片就进入“安全错误”状态,停止启动。
关键点:BootROM 是信任链的“根”。它必须是只读的、不可篡改的。如果 BootROM 有漏洞,整条链就全完了。所以芯片厂商对 BootROM 的审查极其严格。
3.3.2 安全启动链流程图
下面这张图展示了从 BootROM 到应用的安全启动流程。你可以看到,每个环节都有“验签”和“解密”两个动作。
3.4 三个环节的协同与常见陷阱
签名校验、加密存储、安全启动链,这三个环节不是各自为战的。它们必须协同工作,才能形成真正的安全链路。
我举个例子你就明白了:
- 签名校验保证固件是原厂签发的,没被改过。
- 加密存储保证固件内容在 Flash 里是密文,读出来也没用。
- 安全启动链保证从 BootROM 到应用的每一级都经过了签名校验和加密解密。
三者缺一不可。少了签名校验,攻击者可以伪造固件;少了加密存储,攻击者可以逆向分析;少了安全启动链,攻击者可以跳过某些环节直接加载恶意代码。
避坑指南:我曾经见过一个产品,签名校验和安全启动链都做了,但加密存储的密钥是写死在代码里的。攻击者通过反编译拿到了密钥,直接把 Flash 里的固件解密了……嗯,那个项目后来打了补丁,但损失已经造成了。
3.4.1 常见陷阱清单
| 陷阱 | 后果 | 解决方案 |
|---|---|---|
| 公钥未锁死在 OTP | 攻击者可替换公钥 | 烧录后锁死 OTP 写保护位 |
| 加密密钥写死在代码中 | 反编译即可获取密钥 | 使用 HUK 或硬件密钥存储 |
| 安全启动链有“跳转漏洞” | 攻击者可绕过验签直接加载代码 | 严格检查跳转地址和权限位 |
| 未验证动态加载模块 | 攻击者可注入恶意模块 | 运行时对模块做签名校验 |
| 调试接口未关闭 | 攻击者可通过 JTAG/SWD 读取内存 | 量产时熔断调试接口 |