feat(dec): Decaps D6 - c' = K-PKE.Encrypt(ek_pke, m', r')
Re-encryption step of the FO transform (FIPS 203 Alg 17 step 8), done by reusing the ENTIRE Encaps E1-E7 pipeline rather than duplicating it: - FSM: ST_DEC_J (D5) -> ST_ENC_LOAD, then the existing Encaps chain LOAD->A->C->N->U->C1->TDEC->E2MV->V->C2 runs unchanged and writes c' to ct_bram. The reuse preconditions are all in place: rho loads from ek_bram's ek_pke region (same 384k offset Encaps uses; populated at D0 load via dk_ld_ekpke), the CBD seed is r_r (r' from D5), and ek_pke is in ek_bram. - D4 now packs the recovered message directly into m_r (dropping the separate mprime_r register): Encaps V's mu reads m_r[idx] and dbg_mprime_o now aliases m_r, so the re-encrypt sees m' with no extra plumbing. - ST_ENC_LOAD arming generalized to fire when entered from ST_ENC_G (Encaps) or ST_DEC_J (Decaps re-encrypt). The re-encrypt overwrites bank_a/bank_se/bank_t, so the bank-based stage checks (D1 v', D2 s_hat/u_hat, D3 w) are no longer valid at end-of-run. The dec TB now verifies the surviving register/BRAM artifacts: dk parse (D0), m' (D4, in m_r), K'/r'/K-bar (D5), and the 768/1088/1568-byte c' against golden (D6). Earlier stages remain proven by their per-stage builds and transitively by c'. Verified: dec D6 K=2/3/4 all cases PASS (c' == golden == valid ciphertext c); KeyGen + Encaps unregressed.
This commit is contained in:
@@ -88,16 +88,19 @@ 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 D5 done in %0d cyc ===", c);
|
||||
$display("=== Decaps D6 done in %0d cyc ===", c);
|
||||
|
||||
verify_d0;
|
||||
verify_d1;
|
||||
verify_d2;
|
||||
verify_d3;
|
||||
verify_d4;
|
||||
// D6 re-encrypt clobbers bank_a/bank_se/bank_t, so the bank-based stage
|
||||
// checks (D1 v', D2 s_hat/u_hat, D3 w) are no longer valid at end-of-run;
|
||||
// their correctness was proven on earlier per-stage builds and transitively
|
||||
// by c'. Here we check the surviving register/BRAM artifacts: dk parse (D0),
|
||||
// m'/K'/r'/K-bar (D5), and the re-encrypted ciphertext c' (D6).
|
||||
verify_d0; // also initializes errors = 0
|
||||
verify_d4; // m' (now in m_r, survives the re-encrypt)
|
||||
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);
|
||||
verify_d6;
|
||||
if (errors == 0) $display("K=%0d CASE %0d PASS (D6): c' = Encrypt(ek,m',r') OK", KP, casenum);
|
||||
else $display("K=%0d CASE %0d FAIL (D6): %0d total errors", KP, casenum, errors);
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -334,4 +337,31 @@ module tb_mlkem_dec_katK_xsim;
|
||||
errors = errors + be;
|
||||
end
|
||||
endtask
|
||||
|
||||
// D6: verify c' = K-PKE.Encrypt(ek_pke, m', r') in ct_bram == golden.
|
||||
// ct length = 32*(du*K + dv): K2=768, K3=1088, K4=1568.
|
||||
reg [7:0] cp_b [0:1567];
|
||||
task verify_d6;
|
||||
integer i, be, ctlen;
|
||||
reg [8*100-1:0] fn;
|
||||
reg [7:0] got;
|
||||
begin
|
||||
ctlen = (KP == 2) ? 768 : (KP == 3) ? 1088 : 1568;
|
||||
$sformat(fn, "sync_rtl/top/TB/vectors/decgold/dc_k%0d_c%0d_cprime.hex", KP, casenum);
|
||||
$readmemh(fn, cp_b);
|
||||
be = 0;
|
||||
for (i = 0; i < ctlen; i = i + 1) begin
|
||||
dbg_ct_idx_i = i[10:0];
|
||||
@(posedge clk); @(posedge clk); @(posedge clk);
|
||||
got = dbg_ct_o;
|
||||
if (got !== cp_b[i]) begin
|
||||
if (be < 6) $display(" c'[%0d] got=%02x exp=%02x", i, got, cp_b[i]);
|
||||
be = be + 1;
|
||||
end
|
||||
end
|
||||
if (be == 0) $display(" PASS: c' == golden (%0d bytes)", ctlen);
|
||||
else $display(" FAIL: c' %0d byte mismatches", be);
|
||||
errors = errors + be;
|
||||
end
|
||||
endtask
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user