12、安全与可靠性:比特流加密、重构过程完整性校验、防篡改机制
说到动态部分重构,很多人第一反应是「哇,好酷」。但我在项目里摸爬滚打几年后,最深的体会其实是——重构功能越灵活,安全风险就越大。
你想想看,FPGA 的比特流本身就是硬件电路的定义。如果这个定义被人篡改了,或者重构过程中加载了恶意模块,那整个系统就相当于拱手让人了。我见过一个军工项目,就因为重构接口没做校验,被注入了非法比特流,整块板子直接失控。嗯,从那以后,安全就成了我设计流程里的第一优先级。
这一章,我们就来聊聊怎么给动态部分重构加上「锁」和「哨兵」。
12.1 比特流加密:给硬件电路上锁
比特流加密,说白了就是把配置数据用密钥加密后再存储或传输。FPGA 上电后,内部硬件解密引擎会自动解密并加载。这样就算有人拿到了你的 .bit 文件,没有密钥也白搭。
我个人习惯在项目初期就把加密方案定下来。因为一旦设计定型,再想加解密逻辑,往往要动底层布局,代价很大。
12.1.1 主流加密算法与支持
目前主流 FPGA 厂商都支持 AES 加密。Xilinx 从 7 系列开始支持 AES-256,Intel (Altera) 也类似。具体对比如下:
| 厂商 | 加密算法 | 密钥长度 | 密钥存储位置 |
|---|---|---|---|
| Xilinx (AMD) | AES-CBC / AES-GCM | 256 bit | eFuse / BBRA |
| Intel (Altera) | AES-256 | 256 bit | 安全密钥寄存器 |
| Lattice | AES-128 / 256 | 128 / 256 bit | OTP 存储 |
这里要注意,密钥存储是关键。eFuse 是一次性编程的,烧进去就改不了。BBRA (Battery-Backed RAM) 可以更新密钥,但断电需要电池维持。我在一个工业控制项目里用过 BBRA,结果现场电池接触不良,密钥丢了,整批板子报废。后来我全改成了 eFuse,虽然不能更新,但可靠性高得多。
12.1.2 部分重构的加密特殊性
动态部分重构涉及多个部分比特流。每个部分比特流都需要独立加密吗?答案是:看你的威胁模型。
如果攻击者能截获重构过程中的数据流,那每个部分比特流都应该加密。但如果攻击者只能拿到静态存储(比如 Flash),那加密整个镜像就够了。
我个人建议:统一加密。把整个配置镜像(包括静态逻辑和所有部分比特流)作为一个整体加密。这样密钥管理最简单,也最不容易出错。
具体操作时,Xilinx 的 Vivado 里可以这样设置:
# 在 Tcl 控制台设置加密
set_property BITSTREAM.ENCRYPTION.ENCRYPT YES [current_design]
set_property BITSTREAM.ENCRYPTION.KEYFILE ./aes_key_256.key [current_design]
set_property BITSTREAM.ENCRYPTION.KEY0 0x0123456789ABCDEF0123456789ABCDEF [current_design]
嗯,这里要注意,密钥文件要妥善保管。我见过有人把密钥文件直接提交到 Git 仓库里,那跟没加密没什么区别。
12.2 重构过程完整性校验:确保加载的是对的
加密解决了「别人看不懂」的问题,但没解决「加载的东西对不对」的问题。完整性校验,就是用来确认加载的比特流没有被篡改或损坏。
12.2.1 CRC 校验:最基础的防线
FPGA 配置引擎通常自带 CRC 校验。配置数据流中会插入 CRC 值,加载时硬件自动计算并比对。如果 CRC 不匹配,FPGA 会拉低 DONE 信号,表示配置失败。
但这里有个坑:CRC 只能检测随机错误,不能防恶意篡改。因为 CRC 算法是公开的,攻击者可以修改数据后重新计算 CRC。
我在一个通信基站项目里就遇到过这种情况。有人通过物理接触修改了 Flash 中的部分比特流,然后重新计算了 CRC。FPGA 加载时 CRC 校验通过,但功能已经变了。嗯,从那以后,CRC 我只当作「粗筛」,真正的安全要靠 HMAC。
12.2.2 HMAC 认证:防篡改的利器
HMAC (Hash-based Message Authentication Code) 结合了哈希函数和密钥。只有拥有密钥的人才能生成正确的认证码。攻击者就算改了数据,也生成不了新的 HMAC。
具体流程是这样的:
- 生成比特流时,用密钥对数据计算 HMAC,附加在比特流末尾。
- FPGA 加载时,硬件引擎用同样的密钥重新计算 HMAC,与附加值比对。
- 如果一致,说明数据未被篡改;否则拒绝加载。
Xilinx 的 UltraScale+ 系列支持 HMAC-SHA256。我建议在关键项目里一定要开启这个功能。配置方法如下:
# 启用 HMAC 认证
set_property BITSTREAM.ENCRYPTION.AUTHENTICATE YES [current_design]
set_property BITSTREAM.ENCRYPTION.HMAC_KEY 0xDEADBEEF0123456789ABCDEF01234567 [current_design]
12.3 防篡改机制:主动防御
加密和校验都是被动防御。防篡改机制则是主动出击——检测到攻击行为后,立即采取措施。
12.3.1 物理防篡改检测
FPGA 芯片通常有温度、电压监测功能。如果攻击者试图通过降频、升压等方式进行故障注入,监测模块可以检测到异常并触发复位或擦除密钥。
我记得在一个金融交易加速器项目里,客户要求 FPGA 在检测到电压波动超过 ±5% 时,立即擦除所有密钥并进入安全状态。实现起来其实不复杂:
// 伪代码:电压监测与响应
always @(posedge clk) begin
if (voltage_monitor.voltage_out_of_range) begin
key_storage <= 0; // 擦除密钥
secure_state <= SECURE_ERASED;
trigger_system_reset();
end
end
嗯,这里要注意,擦除密钥后系统就彻底锁死了,需要外部干预才能恢复。所以阈值不能设得太敏感,否则正常工况下也会误触发。
12.3.2 部分重构区域的隔离
动态部分重构有个天然的安全优势:重构区域之间是物理隔离的。每个 RP (Reconfigurable Partition) 有独立的布线资源和逻辑单元,静态逻辑和 RP 之间通过固定的接口(如 AXI 总线)通信。
这意味着,即使某个 RP 被加载了恶意模块,它也无法直接访问其他 RP 的内部信号。攻击者只能通过接口协议来尝试攻击,这大大增加了攻击难度。
我建议在设计阶段就把 RP 之间的接口协议设计得尽量严格。比如:
- 接口信号全部注册,不允许组合逻辑直通
- 地址范围严格限制,不允许越界访问
- 数据宽度固定,不允许动态调整
这些措施在 RTL 阶段花不了多少时间,但能有效防止「恶意模块通过接口渗透」的攻击方式。
12.4 知识体系总览
下面这张图总结了安全与可靠性在动态部分重构中的核心逻辑:
12.5 实践建议与避坑总结
说了这么多,最后给几条我自己的实践经验:
- 密钥管理是安全的核心。密钥生成、存储、分发、销毁,每个环节都要有记录。我习惯用专用的 HSM (硬件安全模块) 来管理密钥,而不是放在工程师的电脑里。
- 不要过度依赖单一防护。加密 + HMAC + 物理监测,三层都上。我在一个项目里只做了加密,结果对方通过侧信道攻击(功耗分析)拿到了密钥。后来加了 HMAC 和电压监测,才真正安心。
- 测试阶段也要模拟攻击。我曾经以为自己的设计很安全,直到请了第三方做渗透测试,才发现重构接口的握手协议有漏洞,可以注入非法命令。从那以后,每个项目我都会做至少一轮安全测试。
嗯,这一章的内容就到这里。安全是个大话题,但只要你把加密、校验、监测这三件事做扎实了,大部分攻击都能防住。剩下的,就是不断学习新的攻击手法,然后见招拆招。
公众号:蓝海资料掘金营,微信deep3321