feat(dec): Decaps D5 - (K',r')=G(m'||h) + K-bar=J(z||c)
FO transform hash derivations (FIPS 203 Alg 17 steps 6-7), reusing the
shared SHA3 core:
- ST_DEC_G: (K',r') = G(m'||h) via the single-block SHA3-512 path (mode 11,
dec_g_data = {hek_r, mprime_r}; h was captured into hek_r at D0 load).
K' -> ss_r (candidate shared secret, ss_o), r' -> r_r (PRF seed for D6).
- ST_DEC_J: K-bar = J(z||c) via the multi-block absorb port (mb_en=1),
modeled on the H(ek) machine: assemble 136-byte blocks, byte source is
z_r (g<32), c_in_bram (32<=g<msglen), or SHAKE256 pad (0x1F suffix, last
byte |=0x80 -- the only difference from H's 0x06). mb_* inputs muxed
between H and J by state. K-bar -> kbar_r (dbg_kbar_o).
- FSM: MENC -> G -> J -> DONE.
Bring-up note: c_in_bram read through cin_rd_addr_r (a register) plus the
registered BRAM is 2-cycle latency, but the assemble/writeback pipeline only
budgets 1 -- so the first c byte at the z->c boundary read X and poisoned the
whole sponge. Fixed by driving cin_rd_addr combinationally from dj_c_idx
during ST_DEC_J (dropping the register stage) so data lands the next cycle.
Verified: dec D5 K=2/3/4 all cases PASS (ct 768/1088/1568B -> 6/9/12 J blocks);
K' matches the KAT shared secret for valid ciphertexts; KeyGen + Encaps
unregressed.
This commit is contained in:
@@ -88,15 +88,16 @@ module tb_mlkem_dec_katK_xsim;
|
||||
start_i=1; @(posedge clk); start_i=0;
|
||||
c=0; while(!done_o && c<2000000) begin @(posedge clk); c=c+1; end
|
||||
if(!done_o) begin $display("FAIL K=%0d case %0d: timeout", KP, casenum); $finish; end
|
||||
$display("=== Decaps D4 done in %0d cyc ===", c);
|
||||
$display("=== Decaps D5 done in %0d cyc ===", c);
|
||||
|
||||
verify_d0;
|
||||
verify_d1;
|
||||
verify_d2;
|
||||
verify_d3;
|
||||
verify_d4;
|
||||
if (errors == 0) $display("K=%0d CASE %0d PASS (D4): w + m' recovery OK", KP, casenum);
|
||||
else $display("K=%0d CASE %0d FAIL (D4): %0d total errors", KP, casenum, errors);
|
||||
verify_d5;
|
||||
if (errors == 0) $display("K=%0d CASE %0d PASS (D5): K'/r' = G(m'||h), K-bar = J(z||c) OK", KP, casenum);
|
||||
else $display("K=%0d CASE %0d FAIL (D5): %0d total errors", KP, casenum, errors);
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -286,4 +287,51 @@ module tb_mlkem_dec_katK_xsim;
|
||||
errors = errors + be;
|
||||
end
|
||||
endtask
|
||||
|
||||
// D5: verify K' (ss_o), r' (dbg_r_o), K-bar (dbg_kbar_o) against golden.
|
||||
reg [7:0] kp_b [0:31];
|
||||
reg [7:0] rp_b [0:31];
|
||||
reg [7:0] kb_b [0:31];
|
||||
task verify_d5;
|
||||
integer j, be;
|
||||
reg [8*100-1:0] fn;
|
||||
begin
|
||||
// K' = G(m'||h) low half -> ss_o
|
||||
$sformat(fn, "sync_rtl/top/TB/vectors/decgold/dc_k%0d_c%0d_kprime.hex", KP, casenum);
|
||||
$readmemh(fn, kp_b);
|
||||
be = 0;
|
||||
for (j = 0; j < 32; j = j + 1)
|
||||
if (ss_o[8*j +: 8] !== kp_b[j]) begin
|
||||
if (be < 4) $display(" K'[%0d] got=%02x exp=%02x", j, ss_o[8*j +: 8], kp_b[j]);
|
||||
be = be + 1;
|
||||
end
|
||||
if (be == 0) $display(" PASS: K' == golden (32 bytes)");
|
||||
else $display(" FAIL: K' %0d byte mismatches", be);
|
||||
errors = errors + be;
|
||||
// r' = G(m'||h) high half -> dbg_r_o
|
||||
$sformat(fn, "sync_rtl/top/TB/vectors/decgold/dc_k%0d_c%0d_rprime.hex", KP, casenum);
|
||||
$readmemh(fn, rp_b);
|
||||
be = 0;
|
||||
for (j = 0; j < 32; j = j + 1)
|
||||
if (dbg_r_o[8*j +: 8] !== rp_b[j]) begin
|
||||
if (be < 4) $display(" r'[%0d] got=%02x exp=%02x", j, dbg_r_o[8*j +: 8], rp_b[j]);
|
||||
be = be + 1;
|
||||
end
|
||||
if (be == 0) $display(" PASS: r' == golden (32 bytes)");
|
||||
else $display(" FAIL: r' %0d byte mismatches", be);
|
||||
errors = errors + be;
|
||||
// K-bar = J(z||c) -> dbg_kbar_o
|
||||
$sformat(fn, "sync_rtl/top/TB/vectors/decgold/dc_k%0d_c%0d_kbar.hex", KP, casenum);
|
||||
$readmemh(fn, kb_b);
|
||||
be = 0;
|
||||
for (j = 0; j < 32; j = j + 1)
|
||||
if (dbg_kbar_o[8*j +: 8] !== kb_b[j]) begin
|
||||
if (be < 4) $display(" K-bar[%0d] got=%02x exp=%02x", j, dbg_kbar_o[8*j +: 8], kb_b[j]);
|
||||
be = be + 1;
|
||||
end
|
||||
if (be == 0) $display(" PASS: K-bar == golden (32 bytes)");
|
||||
else $display(" FAIL: K-bar %0d byte mismatches", be);
|
||||
errors = errors + be;
|
||||
end
|
||||
endtask
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user