Files
mlkem-sync/sync_rtl
FallenSigh 189411e8d1 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.
2026-06-29 20:37:03 +08:00
..