ml_kem_768.nx
buildroot/runtime/ml_kem_768.nx
about
ml_kem_768.nx -- ML-KEM-768 post-quantum key encapsulation.
NIST FIPS 203 (August 2024). Lattice-based (Module-LWE),
security category 3 (AES-192 equivalent against both classical
and quantum adversaries). Drop-in replacement for the X25519
key-exchange primitive we ship today -- X25519 is broken by
Shor's algorithm once a sufficiently large fault-tolerant
quantum computer exists. ML-KEM stays secure even then.
Parameters (FIPS 203 Table 2, ML-KEM-768):
n = 256 polynomial degree
q = 3329 modulus
k = 3 module rank
eta1 = 2 secret / error distribution parameter
eta2 = 2 noise distribution parameter
d_u = 10 ciphertext compression (u part)
d_v = 4 ciphertext compression (v part)
Key / ciphertext sizes:
public key = 1184 bytes
secret key = 2400 bytes
ciphertext = 1088 bytes
shared secret = 32 bytes
Status (2026-04-23): SKELETON. Structures + API signatures +
test vectors scaffolded. Heart of the impl -- NTT over
Z_3329[x]/(x^256+1), sample_poly, compress/decompress, K-PKE
wrapping -- is bounded ~600 LoC port from the NIST reference
and will ship next.
Dependencies:
- sha3.nx (shipped) for SHAKE-128/256 + SHA3-256/512
- rand.nx (shipped) for 32-byte randomness at keygen + encap
Invariants:
ML1 Output bytes match FIPS 203 Appendix A test vectors.
ML2 Constant-time critical paths (sample_ntt / compress /
decapsulate re-encrypt) -- no secret-dependent branches.
ML3 Zero dynamic allocation in decap hot path (fixed-size
buffers) for embedded deployability.
dependencies 1 imports · 0 importers
imports: syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 44 | const MLKEM_N: i64 = 256 |
| 45 | const MLKEM_Q: i64 = 3329 |
| 46 | const MLKEM_K: i64 = 3 |
| 47 | const MLKEM_ETA1: i64 = 2 |
| 48 | const MLKEM_ETA2: i64 = 2 |
| 49 | const MLKEM_DU: i64 = 10 |
| 50 | const MLKEM_DV: i64 = 4 |
| 52 | const MLKEM_PK_BYTES: i64 = 1184 |
| 53 | const MLKEM_SK_BYTES: i64 = 2400 |
| 54 | const MLKEM_CT_BYTES: i64 = 1088 |
| 55 | const MLKEM_SS_BYTES: i64 = 32 |
| 57 | const MLKEM_ERR_PENDING: i64 = -1 |
| 58 | const MLKEM_ERR_RANDOM: i64 = -2 |
| 59 | const MLKEM_ERR_DECAP: i64 = -3 |
functions
| 67 | func ml_kem_768_keygen(pk_out: *u8, sk_out: *u8) -> i64 {
called by 1: main |
| 80 | func ml_kem_768_encaps(pk_in: *u8,
called by 1: main |
| 93 | func ml_kem_768_decaps(sk_in: *u8, ct_in: *u8,
called by 1: main |
| 103 | func main() -> i64 { |