FPGA安全NTT架构设计与防护机制解析
1. FPGA安全NTT架构设计背景与挑战
数论变换(Number Theoretic Transform, NTT)作为现代格密码(如Kyber、Dilithium等)的核心运算模块,其硬件实现面临着日益严峻的安全威胁。在FPGA平台上,NTT模块不仅需要保证运算效率,更需要应对硬件木马注入、侧信道攻击等安全风险。传统NTT架构通常仅关注性能优化,而忽视了安全防护机制,这使得攻击者可以通过控制信号篡改、时序扰动等方式破坏NTT运算的正确性,甚至窃取密钥信息。
我们团队在Artix-7 FPGA平台上实测发现,未受保护的NTT模块在面对以下攻击时表现脆弱:
- 硬件木马攻击:通过植入恶意电路篡改控制信号(如rd_en、wr_en等),导致NTT运算流程异常
- 时序攻击:人为引入时钟延迟或停顿,破坏NTT的严格时序要求
- 单次攻击侧信道分析(SASCA):通过监测未受保护的中间值恢复密钥信息
2. 安全NTT架构总体设计
2.1 三重防护机制
针对上述威胁,我们提出如图1所示的安全NTT架构,包含三大核心防护层:
[控制流完整性检查(CFI)] ↓ [时钟周期计数器(CCC)] ↓ [局部掩码(LM)单元]控制流完整性检查(CFI):采用独立于主控制器的备份状态寄存器(CSR),通过移位寄存器结构实时验证控制信号的合法性。当检测到异常状态跳转时,立即触发故障警报。
时钟周期计数器(CCC):为每个关键操作(多项式读取、蝶形运算等)建立严格的时钟周期预算。任何超时操作都会被判定为潜在攻击。
局部掩码(LM):在NTT运算过程中动态掩码中间值,防止SASCA攻击获取有效信息。掩码因子ωr在每次NTT初始化时随机生成。
2.2 硬件架构实现
在Artix-7 FPGA上的具体实现包含以下模块:
- 主NTT引擎:采用基2时域抽取(DIT)结构,支持256点变换
- 故障检测单元:集成CFI和CCC电路
- 位流修补器(Bit Patcher):管理部分重配置(PR)位流
- 内部配置访问端口(ICAP):实现动态重配置
- 总线互连:采用AXI4-Stream接口确保数据传输安全
关键参数配置:
- 时钟频率:100MHz
- 多项式系数:n=256,模数q=3329
- 系数位宽:12bit
- 内存配置:
- poly_mem:12×256 bits
- w_mem:12×256 bits
3. 故障检测机制详解
3.1 控制流完整性检查(CFI)
CFI模块通过双轨验证机制确保控制信号的合法性:
- 主控制器:生成原始控制信号
- 备份CSR:采用LFSR结构模拟理想控制流
- 比较器:每个周期比对两者输出
当检测到不匹配时,更新故障计数器:
if (csr_state /= ctrl_state) then cfi_fault <= cfi_fault + 1; end if;3.2 时钟周期计数器(CCC)
CCC模块监控六个关键操作的时序:
- 多项式读取
- 蝶形运算
- 模约减
- 写回操作
- UV计算
- Barrett约减
每个操作设有最大允许时钟周期数(如Barrett运算≤8周期)。超时触发ccc_fault计数。
3.3 故障分级与阈值
设置两级故障阈值实现分级响应:
| 故障类型 | 轻度阈值 | 严重阈值 |
|---|---|---|
| CFI | 256 | 512 |
| CCC | 256 | 512 |
4. 自适应校正策略
4.1 校正流程决策树
如图2所示,校正策略根据故障严重程度动态选择:
if (n_cfi_fault > cfi_th_reld) & (n_cfi_fault < cfi_th_relc) → 执行Measure III-A1 else if (n_cfi_fault > cfi_th_relc) → 执行Measure III-A2 else if (n_cfi_fault < cfi_th_reld) & (n_cfi_fault < cfi_th_relc) → 执行Measure III-A34.2 三种校正措施
Measure III-A1(寄存器更新):
- 操作:仅更新可靠性指数Ri
- 硬件参与:主机CPU
- 时延:10ns(1时钟周期)
- 适用场景:瞬时干扰
Measure III-A2(同PR位流重载):
- 通过ICAP重载当前位流
- 更新Ri值
- 时延:~150μs(56KB位流@100MHz)
Measure III-A3(最优PR切换):
- 选择Ri最低的备用NTT位流
- 通过ICAP加载新位流
- 时延:~256μs(包含搜索时间)
5. 硬件木马防护场景分析
表1总结了不同木马位置的防护效果:
| 木马位置 | 影响范围 | CFI有效性 | CCC有效性 | LM有效性 |
|---|---|---|---|---|
| 上游(Outside Up) | 输入信号 | × | × | ✓ |
| 内部(Inside NTT) | 控制流/时序 | ✓ | ✓ | × |
| 下游(Outside Dn) | 输出信号 | × | × | ✓ |
| 监测模块内部 | 检测电路失效 | 可能失效 | 可能失效 | - |
典型防护案例:
- RTL级木马:CFI检测到非法状态跳转
- 综合后木马:CCC捕获异常时序
- 位流级攻击:LM阻止SASCA泄漏
6. 实现结果与性能分析
6.1 资源开销对比
在Vivado 2022.2下的实现结果:
| 版本 | LUTs | FFs | DSPs | 功耗 |
|---|---|---|---|---|
| 基线NTT | 273 | 298 | 4 | 2991nJ |
| 仅检测(CFI+CCC+LM) | 297 | 324 | 4 | 3021nJ |
| 完整方案 | 327 | 356 | 4 | 3094nJ |
开销分析:
- 切片资源增加19.7%
- 功耗增加3%
- 无时序违例(满足100MHz)
6.2 防护效果验证
在Kyber-1024上的测试结果:
| 操作类型 | 执行次数 | 注入故障数 | 检测率 | 校正率 |
|---|---|---|---|---|
| 密钥生成 | 16,384 | 16,384 | 100% | 100% |
| 封装 | 16,384 | 16,384 | 100% | 100% |
| 解封装 | 16,384 | 16,384 | 100% | 100% |
故障注入方法:
// 主机端故障注入控制 void inject_fault(uint16_t Rt, uint16_t Rs) { pci_write(FAULT_REG, (Rt << 16) | Rs); }其中:
- Rt∈[0,1023]:攻击时钟周期
- Rs∈[0,1023]:故障信号选择
7. 工程实践建议
7.1 阈值配置经验
根据实测数据推荐:
- 轻量级应用:阈值设为128/256
- 高安全场景:阈值设为256/512
- 需平衡误报率与响应速度
7.2 位流管理技巧
- 存储至少4个不同布局的PR位流
- 定期轮换使用位流以增强防护
- 使用XDC约束确保关键路径隔离
7.3 调试注意事项
- 使用ILA监控CFI状态机
- 添加调试头输出CCC计数值
- 预留JTAG接口用于Ri读取
8. 典型问题排查
问题1:CFI误报率高
现象:未受攻击时频繁报错排查步骤:
- 检查主CSR与备份CSR的初始状态是否一致
- 验证时钟域交叉处理(CDC)是否恰当
- 调整比较器采样时钟相位
问题2:重配置失败
现象:ICAP传输超时解决方案:
- 检查ICAP时钟是否稳定(建议≤100MHz)
- 验证位流头格式是否正确
- 添加硬件看门狗定时器
问题3:LM导致运算错误
现象:NTT结果验证失败调试方法:
- 捕获ωr值与理论值比对
- 检查模乘运算单元是否溢出
- 验证去掩码时序是否符合要求
我们在Artix-7 AC701开发板上实测发现,当采用上述架构后,Kyber-1024的加解密操作仍能保持约12,800次/秒的吞吐量,相比无防护版本仅降低7.2%。这种性能折损对于大多数实际应用场景是可接受的。
