Files
mlkem-sync/docs/design_report.md

14 KiB
Raw Permalink Blame History

ML-KEM 硬件 IP 设计报告

模块:mlkem_topFIPS 203 ML-KEM 全功能加速器) 器件:Xilinx Artix-7 xc7a200tfbg676-1 工具:Vivado 2019.2(综合)+ XSIM功能仿真 日期:2026-06


1. 概述

1.1 设计目标

本 IP 实现 NIST FIPS 203 标准化的后量子密钥封装机制 ML-KEM(源自 CRYSTALS-Kyber 在单一硬件模块 mlkem_top 中同时支持三种核心操作,并在运行时可选三种安全等级:

操作 op_i FIPS 203 算法 输入 输出
密钥生成 KeyGen 0 算法 16 种子 d, z 公钥 ek、私钥 dk
密钥封装 Encaps 1 算法 17 ek, 消息 m 共享密钥 K、密文 c
密钥解封装 Decaps 2 算法 18 dk, 密文 c 共享密钥 K(含隐式拒绝)
等级 (k_i) 方案 K η₁ (d_u,d_v) ek dk 密文 c
2 ML-KEM-512 2 3 (10,4) 800 B 1632 B 768 B
3 ML-KEM-768 3 2 (10,4) 1184 B 2400 B 1088 B
4 ML-KEM-1024 4 2 (11,5) 1568 B 3168 B 1568 B

固定参数:模数 q = 3329、多项式次数 n = 256、共享密钥 32 B。

1.2 关键特性

  • 运行时可重构:k_i/op_istart_i 时锁存存储按最坏情况ML-KEM-1024静态分配 无需为不同等级重新综合。
  • 资源高度复用:同一套叶子算子与存储库被三条数据通路分时复用;Decaps 的重加密 FO 变换核心)直接复用整条 Encaps 流水线。
  • 共享 Keccak 核:G/H/J、SampleNTT、CBD 三类哈希消费者分时共用单个 keccak_core
  • 逐字节流式 I/O:ek/dk/c 经 BRAM 端口逐字节装载与回读,避免超宽顶层总线。
  • 常量时间隐式拒绝:Decaps 比较 c'==c 全程恒定工作量,无早退分支。
  • 完整 KAT 验证:三种等级、三种操作全部对 NIST KAT 标准答案逐字节比对通过。

1.3 代码规模

行数
mlkem_top.v(顶层集成 + FSM + 数据通路) 2252
RTL 合计(不含测试平台) 5517

2. 顶层接口

module mlkem_top #(parameter KMAX = 4) (
    input              clk, rst_n,        // 100 MHz 设计时钟, 低电平异步复位
    input  [2:0]       k_i,              // 运行时等级 2/3/4 (start_i 锁存)
    input  [1:0]       op_i,             // 0=KeyGen 1=Encaps 2=Decaps
    input  [255:0]     d_i, z_i, msg_i,  // 种子 d/z, Encaps 消息 m
    input              start_i,
    output             busy_o, done_o,
    output [255:0]     ss_o,             // 共享密钥 K

    input              ek_in_we;  input [10:0] ek_in_addr;  input [7:0] ek_in_byte; // Encaps ek 装载
    input              dk_in_we;  input [11:0] dk_in_addr;  input [7:0] dk_in_byte; // Decaps dk 装载
    input              c_in_we;   input [10:0] c_in_addr;   input [7:0] c_in_byte;  // Decaps c 装载

    // 调试 / 结果回读抽头(只读)
    input  [10:0] dbg_ct_idx_i;  output [7:0]  dbg_ct_o;      // 密文 c
    input  [5:0]  dbg_slot_i; input [7:0] dbg_idx_i; output [11:0] dbg_coeff_o; // 系数
    input         dbg_byte_sel_i; input [10:0] dbg_byte_idx_i; output [7:0] dbg_byte_o; // ek/dk_pke
    input  [11:0] dbg_dk_idx_i;  output [7:0]  dbg_dk_o;      // 完整 dk
    output [255:0] dbg_rho_o, dbg_sigma_o, dbg_r_o, dbg_hek_o,
                   dbg_mprime_o, dbg_kbar_o, dbg_decz_o, dbg_dech_o
);

握手时序:外部先经流式端口预装载所需数据Encaps→ekDecaps→dk+c start_i 拉一拍锁存 k_i/op_i 并启动;busy_ost≠IDLE 期间为高; done_ost==DONE 拉高,此时 ss_o 及各 BRAM 产物有效。

数据约定:所有 256-bit 端口为「byte0 在低位」,即 value[8m+:8] = byte m


3. 微架构

3.1 总体结构

mlkem_top 采用「单 FSM 调度 + 共享叶子算子 + 统一存储库」架构。顶层 RTL 结构见 docs/mlkem_top_rtl.svg。数据流分为四层:

输入端口 ──► 控制 FSM / 状态寄存器 ──► 叶子算子(共享 keccak + 算术引擎) ◄──► 存储库 ──► 输出/回读

3.2 叶子算子

实例 模块 功能
u_keccak keccak_core Keccak-f[1600] 置换(单核,三方共享)
u_sha3 sha3_top_shared SHA3-512 (G) / SHA3-256 (H) / SHAKE-256 (J),单/多块吸收
u_snt sample_ntt_sync_shared SampleNTTSHAKE-128 拒绝采样)生成 Â
u_cbd sample_cbd_sync_shared CBD_η 中心二项分布采样s/e/y/e1/e2
u_ntt ntt_core 前向 NTT / 逆向 NTTmode 选择×3303 尾乘)
u_pmul poly_mul_sync NTT 域逐点乘basecase含 Barrett 模乘)
u_comp comp_decomp_sync Compress_d / Decompress_dBarrett 除法约简)

模加、byteEncode₁₂/byteDecode₁₂、bit-packer/解包、c'==c 比较等轻量逻辑在顶层内联实现。

3.3 共享 Keccak 核

G/H/J、SampleNTT、CBD 都需要 Keccak 置换,但分处互斥的 FSM 阶段,故共用单个 u_keccak:

  • 输入复用:kc_state_i_mux / kc_valid_i_mux 按相位三选一 sel_snt / sel_cbd / 默认 SHA3
  • 输出门控:核输出 kc_state_o / kc_valid_o 广播给所有消费者,但只有当前激活方看到有效信号 kc_valid_o_sha3 / _snt / _cbd)。
  • 相位选择由 FSM 状态推导:sel_sha3 = (st∈{G,H,J,…})sel_snt = (st∈{A,ENC_A})sel_cbd = (st∈{C,ENC_C})

此设计省去 Keccak 核的多份例化Keccak-f 是面积大户),是 LUT 占用仅 25% 的主要原因之一。

3.4 存储库

实例 宽×深 用途 读写信号
u_bank_a 12×4096 Â[i][j] 矩阵Decaps 中转 ŝ/e2/v' ba_rd_* / ba_we/wa/wd
u_bank_se 12×2048 ŝ/ê (KeyGen)·ŷ (Encaps)·û (Decaps) bse_rd_* / bse_we/wa/wd
u_bank_t 12×1024 t̂·累加和·Encaps v·Decaps w bt_rd_* / bt_we/wa/wd
u_ek_bram 8×2048 ek = byteEncode₁₂(t̂)‖ρ
u_dkp_bram 8×2048 dk_pke = byteEncode₁₂(ŝ)
u_ct_bram 8×2048 计算出的密文 c / Decaps c'
u_c_in_bram 8×2048 Decaps 输入密文 c与 ct 分开以便比较)

全部基于 sd_bram1R/1W、寄存读、1 拍读延迟,综合映射为块 RAM。系数库槽基址由 k_r 运行时推导:Â 占 slot 0..K²-1slot_s=K²slot_e=K²+Kslot_t=K²+2K

3.5 控制 FSM 与数据流

5-bit 状态机从 ST_IDLE 按锁存的 op_r 分支为三条数据通路:

KeyGen算法 16

G:  (ρ,σ)=G(d‖K)                         SHA3-512
A:  Â[i][j]=SampleNTT(ρ‖j‖i)             → bank_a
C:  s/e = CBD_η1(PRF(σ,·))               → bank_se
N:  ŝ=NTT(s), ê=NTT(e)                    原地
M:  t̂=ê+Σⱼ Â∘ŝ                            逐点乘+modQ 累加 → bank_t
E:  ek=Enc12(t̂)‖ρ, dk_pke=Enc12(ŝ)       → ek/dkp_bram
H:  H(ek)                                 多块 SHA3-256
    dk = dk_pke‖ek‖H(ek)‖z

Encaps算法 17

ENC_H/G:  H(ek), (K,r)=G(m‖H(ek))
ENC_LOAD/A/TDEC: ρ载入, Â重生成, t̂=byteDecode12(ek)
ENC_C/N:  y,e1,e2=CBD(PRF(r,·)), ŷ=NTT(y)
ENC_U:    u=INTT(Σ Âᵀ∘ŷ)+e1
ENC_C1:   c1=Enc_du(Compress_du(u))
ENC_V:    v=INTT(Σ t̂∘ŷ)+e2+Decompress1(m)
ENC_C2:   c2=Enc_dv(Compress_dv(v));  c=c1‖c2;  K=共享密钥

Decaps算法 18FO 变换 + 隐式拒绝)

DEC_DECOMP:  u'/v' = Decompress(byteDecode(c))         D1
DEC_SDEC/NTT: ŝ=byteDecode12(dk_pke), û=NTT(u')         D2
DEC_W:       w=v'-INTT(Σⱼ ŝ∘û)                          D3
DEC_MENC:    m'=Enc1(Compress1(w))                      D4
DEC_G/J:     (K',r')=G(m'‖h),  K̄=J(z‖c)                D5
(重加密):    c'=K-PKE.Encrypt(ek_pke,m',r')  ←复用 Encaps 流水  D6
DEC_CMP:     ss = (c'==c) ? K' : K̄                      D7

核心复用点:D6 重加密整段复用 Encaps 的 ENC_LOAD…ENC_C2——m' 写入 m_r、 r' 在 r_r、ek_pke 已在 ek_bram,前置条件天然就位,无需另起数据通路。 D7 逐字节比较 u_ct_bram(c') 与 u_c_in_bram(c),恒定工作量,按 dec_rejectss_r(K') 与 kbar_r(K̄) 间选择:ss_o = dec_reject ? kbar_r : ss_r

3.6 模运算策略

所有模 qq=3329约简采用 Barrett 乘法替代除法器:floor(x/q) ≈ (x·5039)>>24 其中 5039 = floor(2²⁴/q),再做至多两次条件减校正。q·x 用移位加实现 3329 = 2048+512+256+1无需第二个乘法器。早期版本使用组合除法器已于提交 717a992 替换为 Barrett显著缩短关键路径。按设计约束全部乘法标注 use_dsp="no",不使用 DSP48


4. 功能验证

4.1 验证策略

采用「分阶段中间量核对 + 端到端 KAT 比对」双层策略,全部对照 NIST FIPS 203 的 KAT 标准答案:

  • 分阶段:KeyGen 按 G/A/C/N/M/E/H、Encaps 按 E1E7、Decaps 按 D0D7 逐级验证中间多项式 /哈希/编码,经调试抽头逐字节回读比对。
  • 端到端:KeyGen 核对 ek==pkdk==sk;Encaps 核对 ssc;Decaps 核对最终 ss 并用 KAT 自带的损坏密文 ct_n/ss_n 验证隐式拒绝路径(ss==ss_n=J(z‖ct_n))。

4.2 测试平台

测试平台 操作 覆盖
tb_mlkem_kg_katK_xsim.v KeyGen K=2/3/4 各 KAT 用例,ek==pk/dk==sk
tb_mlkem_enc_katK_xsim.v Encaps E1E7 分阶段 + ss/c
tb_mlkem_dec_katK_xsim.v Decaps D0D7 分阶段 + 接受/拒绝双路径
tb_mlkem_hello_world_xsim.v 全流程(单实例) KeyGen→Encaps→XOR→Decaps→XOR
tb_mlkem_two_inst_xsim.v 全流程(双实例) 实例 A 做 KeyGen+Encaps实例 B 做 Decaps

参数化 TB 通过 xelab -generic_top KP=2|3|4 选等级,+CASE=n 选用例。统一脚本 run_tb.sh {top|enc|dec|hello} 驱动。

4.3 验证结果

  • KeyGen / Encaps / Decaps 三操作、K=2/3/4 三等级全部 KAT 用例逐字节 PASS。
  • 隐式拒绝:损坏密文路径正确输出 K̄dec_reject=1
  • 端到端:hello_world 单/双实例均通过,共享密钥与消息正确还原 shared_key=ced0c031a4bee34a…decrypted="hello world")。

4.4 增量验证里程碑git 记录)

设计按阶段增量构建,每阶段独立提交并通过 KAT历史可二分定位:

KeyGen 各阶段 → Encaps E1E7 (7228beb…) → Decaps D0D7 (030931d…2b70431)
→ hello_world 端到端 (f279222, ee2bf1c)

5. 综合与实现结果

5.1 资源占用OOC 综合xc7a200tfbg676-1

资源 使用 可用 占用率
Slice LUTs全为逻辑 34 318 134 600 25.5 %
Slice Registers (FF) 23 254 269 200 8.6 %
F7 Muxes 3 645 67 300 5.4 %
F8 Muxes 1 191 33 650 3.5 %
Block RAM Tile 5RAMB36×2 + RAMB18×6 365 1.4 %
DSP48 0 740 0 %

面积占用低DSP 完全未用(符合设计约束),器件资源充裕。

5.2 性能(周期数,实测)

操作 周期数K=2ML-KEM-512
KeyGen ≈ 22 904
Encaps ≈ 32 493
Decaps ≈ 50 819

K=3/4 因模秩增大按比例上升。Decaps 最长,因其包含完整重加密(≈ 一次 Encaps

5.3 时序现状与瓶颈

当前对 50 MHz20 ns 目标尚未收敛:

指标
WNS -32.2 ns关键路径实际 ≈ 52 ns
失败端点 3 132 / 44 689
Hold (WHS) +0.134 ns无违例
关键路径 u_pmul/mem_A_reg → u_pmul/c0_reg70 逻辑级

根因:basecase_mul 单周期组合计算 c0=(a0·b0+(a1·b1)·zeta) mod q,其中 两级 Barrett 模乘串联t2=a1·b1t2·zeta+ 模加;在 use_dsp="no" 约束下, 每级 Barrett 约 24 ns串联即 ≈ 52 ns。

修复方向(不使用 DSP详见 timing_analysis.md:将 barrett_mul 改为 3 级内部流水 (乘法 / ×K 移位 / ×q 约简各一拍),basecase_mul 的 c0 双乘级联为 6 拍、c1 对齐, poly_mul_sync 节拍相应加深。吞吐几乎不变(仅增加固定启动延迟,相对数万周期可忽略), WNS 预计转正。每步需重跑全部 KAT 确保功能不变。


6. 设计权衡与结论

6.1 主要权衡

决策 收益 代价
单 FSM 串行调度 + 资源复用 面积小LUT 25%)、控制清晰 串行执行,周期数较高
共享单 Keccak 核 省大量面积 哈希/采样不能并行
Decaps 复用 Encaps 流水 省去独立重加密通路 FSM 状态耦合较紧
运行时选 k_i/op_i 单比特流支持全部配置 存储按最坏情况分配
不使用 DSP 满足约束、可移植性强 乘法走 LUT时序压力大

6.2 结论

mlkem_top 是一个功能完整、KAT 全过的 ML-KEM 硬件 IP在单模块内支持 KeyGen/Encaps/Decaps 三种操作与三种安全等级面积占用低LUT 25.5%、零 DSP。设计经分阶段增量验证正确性可靠。

当前唯一未达标项是 50 MHz 时序收敛:瓶颈明确(basecase_mul 双 Barrett 串联组合路径), 修复方案已制定(纯流水化,不依赖 DSP改动范围可控。完成该流水化改造并重跑 KAT 后, 预计可收敛至 50 MHz 目标。

6.3 后续工作

  1. timing_analysis.md 实施 Barrett / basecase / poly_mul 流水化,收敛 50 MHz。
  2. 流水化后检查次要瓶颈(如 comp_decomp 的 Barrett同法处理。
  3. 补充布局布线implementation后的时序签核目前仅有综合后时序。
  4. 视吞吐需求评估关键算子NTT、采样并行化以降低周期数。

附:复现命令

source /opt/Xilinx/Vivado/2019.2/settings64.sh
export LD_PRELOAD=/usr/lib64/libtinfo.so.5

# 功能验证
./run_tb.sh top        # KeyGen KAT (K=2/3/4)
./run_tb.sh enc        # Encaps KAT
./run_tb.sh dec        # Decaps KAT (含拒绝路径)
./run_tb.sh hello      # 端到端 hello_world

# 综合 + 时序报告
vivado -mode batch -source synth_timing.tcl   # → timing.rpt / timing_worst.rpt / util.rpt

相关文档:README.md(使用说明)、docs/mlkem_top_rtl.svgRTL 结构图)、 timing_analysis.md(时序分析与修复方案)。