nx_ml_dsa_65_wasm.nx
buildroot/runtime/nx_ml_dsa_65_wasm.nx
about
nx_ml_dsa_65_wasm.nx -- Sovereign single-WASM FIPS 204 ML-DSA-65 (foundation).
L131 iteration 1: math foundation only. Ships:
* Constants + i32 polynomial helpers (256 i32 LE = 1024 B per poly)
* Keccak-f[1600] + SHA-3-256 + SHAKE256 sponges (inlined verbatim from L126)
* Montgomery + Barrett reductions for Z_8380417
* Full ML-DSA NTT + INVNTT with 256-entry zeta table (Montgomery form,
primitive 512th root zeta=1753 mod q, bit-reversed indexed)
* Pointwise basemul + montgomery acc
* KAT export: nx_mldsa_ntt_round_trip_test(poly_ptr) returns 0 if
INVNTT(NTT(poly)) ≡ original (mod q, accounting for the
Montgomery factor R=2^32 that invntt_tomont leaves behind)
Next iterations layer on:
L132: sampling (rej_uniform for matrix A, rej_eta for s1/s2, sample_in_ball)
L133: power-of-2 decompose + make_hint / use_hint
L134: keygen + tobytes/frombytes for pk/sk
L135: sign with rejection loop
L136: verify
L137: end-to-end round-trip self-test
Final public API (after L137):
nx_mldsa_keygen(seed_32, scratch, pk_out, sk_out)
nx_mldsa_sign(sk, msg, msg_len, scratch, sig_out, sig_len_out)
nx_mldsa_verify(pk, msg, msg_len, sig, sig_len, scratch) -> i64 1/0
Pillar 4 alignment: uses the same scratch-layout annotation pattern as
L126 (F-meta-8 grader-compatible).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/fips_204
lineage_id: nishi_ml_dsa_65_wasm_q1
safe_shift_audit: shared Keccak _rotl64 uses gold-standard mask
dependencies 0 imports · 0 importers
imports: none
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 39 | const MLDSA_Q: i64 = 8380417 |
| 40 | const MLDSA_QINV: i64 = 58728449 // q^{-1} mod 2^32 (unsigned) |
| 41 | const MLDSA_N: i64 = 256 |
| 42 | const MLDSA_K: i64 = 6 // matrix rows |
| 43 | const MLDSA_L: i64 = 5 // matrix cols |
| 44 | const MLDSA_ETA: i64 = 4 |
| 45 | const MLDSA_TAU: i64 = 49 |
| 46 | const MLDSA_BETA: i64 = 196 // tau * eta |
| 47 | const MLDSA_GAMMA1: i64 = 524288 // 2^19 |
| 48 | const MLDSA_GAMMA2: i64 = 261888 // (q-1)/32 |
| 49 | const MLDSA_OMEGA: i64 = 55 |
| 50 | const MLDSA_D: i64 = 13 |
| 52 | const MLDSA_PK_BYTES: i64 = 1952 |
| 53 | const MLDSA_SK_BYTES: i64 = 4032 |
| 54 | const MLDSA_SIG_BYTES: i64 = 3309 |
| 57 | const POLY_BUF: i64 = 1024 |
functions
| 63 | func _i32_load_le(p: *u8, i: i64) -> i64 |
| 73 | func _i32_store_le(p: *u8, i: i64, v: i64) -> i64 |
| 89 | func _mont_reduce(a: i64) -> i64 called by 1: _fqmul |
| 96 | func _reduce32(a: i64) -> i64 |
| 102 | func _fqmul(a: i64, b: i64) -> i64 { return _mont_reduce(a * b) } called by 8: nx_mldsa_nttnx_mldsa_invnttnx_mldsa_basemulnx_mldsa_keygennx_mldsa_signnx_mldsa_verify+2 calls 1: _mont_reduce |
| 105 | func _rotl64(x: i64, n: i64) -> i64 called by 1: _keccak_f1600 |
| 117 | func _lane_load(p: *u8) -> i64 called by 1: _keccak_f1600 |
| 122 | func _lane_store(p: *u8, v: i64) -> i64 called by 1: _keccak_f1600 |
| 127 | func _keccak_rc(i: i64) -> i64 called by 1: _keccak_f1600 |
| 142 | func _rho_off(lane_idx: i64) -> i64 called by 1: _keccak_f1600 |
| 157 | func _keccak_f1600(state_ptr: *u8) -> i64 |
| 226 | func _sponge_one_shot(msg: *u8, msg_len: i64, rate: i64, dom_byte: i64, |
| 255 | func _sha3_256(msg: *u8, msg_len: i64, state: *u8, out: *u8) -> i64 calls 1: _sponge_one_shot |
| 258 | func _shake256(msg: *u8, msg_len: i64, state: *u8, out: *u8, out_len: i64) -> i64 |
| 261 | func _shake128(msg: *u8, msg_len: i64, state: *u8, out: *u8, out_len: i64) -> i64 |
| 271 | func _zeta(i: i64) -> i64 |
| 345 | func nx_mldsa_ntt(poly: *u8) -> i64 |
| 371 | func nx_mldsa_invntt(poly: *u8) -> i64 |
| 403 | func nx_mldsa_basemul(out: *u8, a: *u8, b: *u8) -> i64 |
| 423 | func nx_mldsa_rej_uniform(poly: *u8, buf: *u8, buf_len: i64) -> i64 |
| 445 | func nx_mldsa_rej_eta4(poly: *u8, buf: *u8, buf_len: i64) -> i64 |
| 482 | func nx_mldsa_sample_in_ball(poly: *u8, c_tilde_32: *u8, scratch: *u8) -> i64 |
| 536 | func _power2round_coef(a: i64, out_a1: *u8, out_a0: *u8) -> i64 calls 1: _i32_store_le |
| 545 | func nx_mldsa_poly_power2round(a1_poly: *u8, a0_poly: *u8, in_poly: *u8) -> i64 |
| 568 | func _decompose_coef(a: i64, out_a0: *u8, off: i64) -> i64 |
| 584 | func nx_mldsa_poly_decompose(a1_poly: *u8, a0_poly: *u8, in_poly: *u8) -> i64 |
| 598 | func _make_hint_coef(a0: i64, a1: i64) -> i64 called by 1: nx_mldsa_poly_make_hint |
| 610 | func nx_mldsa_poly_make_hint(hint_out: *u8, a0_poly: *u8, a1_poly: *u8) -> i64 |
| 627 | func _use_hint_coef(a: i64, hint: i64) -> i64 called by 1: nx_mldsa_poly_use_hint |
| 641 | func nx_mldsa_poly_use_hint(out_poly: *u8, in_poly: *u8, hint_poly: *u8) -> i64 |
| 658 | func _pack_t1_poly(out: *u8, poly: *u8) -> i64 |
| 678 | func _pack_eta4_poly(out: *u8, poly: *u8) -> i64 |
| 691 | func _pack_t0_poly(out: *u8, poly: *u8) -> i64 |
| 728 | func _expand_a_entry(out_poly: *u8, rho: *u8, j: i64, i_row: i64, |
| 748 | func _expand_s_entry(out_poly: *u8, rho_prime: *u8, nonce: i64, |
| 774 | func nx_mldsa_keygen(seed_32: *u8, scratch: *u8, pk_out: *u8, sk_out: *u8) -> i64 |
| 926 | func nx_mldsa_keygen_deterministic_test(seed_32: *u8, scratch: *u8) -> i64 calls 1: nx_mldsa_keygen |
| 961 | func _unpack_z_chunk(out_poly: *u8, base_idx: i64, buf: *u8, buf_off: i64) -> i64 |
| 986 | func _pack_z_poly(out: *u8, poly: *u8) -> i64 |
| 1009 | func _unpack_z_poly(poly: *u8, bytes_in: *u8) -> i64 |
| 1019 | func _pack_w1_poly(out: *u8, poly: *u8) -> i64 |
| 1036 | func _pack_hint_vec(out: *u8, hint_polys: *u8) -> i64 |
| 1062 | func _unpack_hint_vec(hint_polys: *u8, bytes_in: *u8) -> i64 |
| 1098 | func _expand_mask_entry(out_poly: *u8, rho_prime: *u8, kappa_plus_i: i64, |
| 1121 | func nx_mldsa_l135_encoders_test(scratch: *u8) -> i64 |
| 1239 | func _unpack_eta4_poly(out: *u8, bytes_in: *u8) -> i64 |
| 1251 | func _unpack_t0_poly(out: *u8, bytes_in: *u8) -> i64 |
| 1287 | func _poly_inf_norm(poly: *u8) -> i64 |
| 1300 | func _vec_inf_norm(vec: *u8, n_polys: i64) -> i64 |
| 1318 | func nx_mldsa_sign(sk: *u8, msg: *u8, msg_len: i64, |
| 1634 | func nx_mldsa_sign_test(seed_32: *u8, msg_32: *u8, scratch: *u8) -> i64 |
| 1691 | func _unpack_t1_poly(out_poly: *u8, packed: *u8) -> i64 |
| 1723 | func nx_mldsa_verify(pk: *u8, msg: *u8, msg_len: i64, |
| 1942 | func nx_mldsa_verify_test(seed_32: *u8, msg_32: *u8, scratch: *u8) -> i64 |
| 1981 | func nx_mldsa_acc_basemul_large_test(scratch: *u8) -> i64 |
| 2076 | func nx_mldsa_acc_basemul_round_trip_test(scratch: *u8) -> i64 |
| 2176 | func nx_mldsa_basemul_round_trip_test(scratch: *u8) -> i64 |
| 2251 | func nx_mldsa_ntt_signed_round_trip_test(scratch: *u8) -> i64 |
| 2285 | func nx_mldsa_unpack_t1_debug(pk: *u8, out_poly: *u8) -> i64 calls 1: _unpack_t1_poly |
| 2294 | func nx_mldsa_pack_t1_debug(in_poly: *u8, out_packed: *u8) -> i64 calls 1: _pack_t1_poly |
| 2302 | func nx_mldsa_verify_debug_one(seed_32: *u8, msg_32: *u8, scratch: *u8) -> i64 |
| 2311 | func nx_mldsa_ntt_round_trip_test(scratch: *u8) -> i64 |