ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
mlkem.h File Reference

ML-KEM-768 (FIPS 203): KeyGen, Encaps (responder) and Decaps (initiator). More...

#include "protocore_config.h"

Go to the source code of this file.

Classes

struct  MlKemNs
 Dispatch table. Addressed by offset, so the layout is asserted below. More...
 

Macros

#define MLKEM768_EK_BYTES   1184
 encapsulation key (public key): 384*k + 32
 
#define MLKEM768_DK_BYTES   2400
 decapsulation key (private): 768*k + 96
 
#define MLKEM768_CT_BYTES   1088
 ciphertext: 32*(du*k + dv) = 32*(30+4)
 
#define MLKEM768_SS_BYTES   32
 shared secret
 
#define MLKEM768_MSG_BYTES   32
 the random message m fed to Encaps
 
#define MLKEM768_D_BYTES   32
 KeyGen seed d (K-PKE key material)
 
#define MLKEM768_Z_BYTES   32
 KeyGen seed z (implicit-reject value)
 

Functions

 PROTOCORE_NS_LAYOUT (MlKemNs, keygen, encaps, decaps)
 
proto_bool protocore_ml_kem_keygen (uint8_t *work, const uint8_t *d, const uint8_t *z, uint8_t *ek, uint8_t *dk)
 (ek, dk) from the two seeds, deterministic given them.
 
proto_bool protocore_ml_kem_encaps (uint8_t *work, const uint8_t *ek, const uint8_t *m, uint8_t *ct, uint8_t *ss)
 (ct, ss) from a peer key and a message.
 
proto_bool protocore_ml_kem_decaps (uint8_t *work, const uint8_t *dk, const uint8_t *ct, uint8_t *ss)
 The shared secret from a ciphertext, through the FO transform.
 

Variables

PROTOCORE_NS MlKemNs MlKem PROTOCORE_UNUSED
 Module namespace.
 

Detailed Description

ML-KEM-768 (FIPS 203): KeyGen, Encaps (responder) and Decaps (initiator).

The post-quantum half of the mlkem768x25519-sha256 (SSH) and X25519MLKEM768 (TLS 1.3) hybrid key exchanges. Both KEM roles are present:

  • responder (server terminating an inbound handshake): Encaps takes the peer's encapsulation key and produces (ciphertext, shared secret);
  • initiator (the device dialling out as an SSH/TLS client): KeyGen produces (ek, dk), the peer Encaps against ek, and Decaps recovers the shared secret from the returned ciphertext.

Decaps carries the full constant-time Fujisaki-Okamoto transform (re-encrypt m' under the embedded ek and select the real key vs the implicit-reject key J(z || ct) under a constant-time ciphertext compare), so a malformed or tampered ciphertext yields a pseudorandom secret rather than leaking a decryption failure - FIPS 203 ยง6.3.

KeyGen, Encaps and Decaps are the FIPS 203 "internal" (derandomized) forms: the caller supplies the randomness (KeyGen's (d, z), Encaps's message m), drawn from the platform RNG in production and fixed in known-answer tests. Deterministic given their inputs, which is exactly what the ACVP keyGen / encapDecap vectors pin.

Arithmetic is a software NTT over q=3329 with Montgomery reduction (the twiddle factors are fixed constants premultiplied into Montgomery form, so each butterfly is two int16 multiplies and a shift - no division, and the hardware MPI, which targets RSA/DH-sized operands, would only add marshaling overhead). Zero heap; peak stack ~9 KB (Decaps, which re-encrypts).

MlKemNs::encaps runs the FIPS 203 modulus check on the peer key first: on a key whose decoded coefficients are not all < q it writes nothing and leaves MlKemNs::ok false.

MlKemNs::decaps has no failure of its own: a malformed or tampered ciphertext selects J(z || ct) in constant time and the call still reports true.

work is PROTOCORE_MLKEM_BORROW secure bytes the CALLER took, at an address it knows. It is not held past the call, so nothing here aliases it. The caller releases it, and the pool wipes on release; this module neither takes it, holds it, releases it, nor wipes it. That is what keeps the seeds, the noise and the decrypted message from outliving the caller.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file mlkem.h.

Macro Definition Documentation

◆ MLKEM768_EK_BYTES

#define MLKEM768_EK_BYTES   1184

encapsulation key (public key): 384*k + 32

Definition at line 52 of file mlkem.h.

◆ MLKEM768_DK_BYTES

#define MLKEM768_DK_BYTES   2400

decapsulation key (private): 768*k + 96

Definition at line 53 of file mlkem.h.

◆ MLKEM768_CT_BYTES

#define MLKEM768_CT_BYTES   1088

ciphertext: 32*(du*k + dv) = 32*(30+4)

Definition at line 54 of file mlkem.h.

◆ MLKEM768_SS_BYTES

#define MLKEM768_SS_BYTES   32

shared secret

Definition at line 55 of file mlkem.h.

◆ MLKEM768_MSG_BYTES

#define MLKEM768_MSG_BYTES   32

the random message m fed to Encaps

Definition at line 56 of file mlkem.h.

◆ MLKEM768_D_BYTES

#define MLKEM768_D_BYTES   32

KeyGen seed d (K-PKE key material)

Definition at line 57 of file mlkem.h.

◆ MLKEM768_Z_BYTES

#define MLKEM768_Z_BYTES   32

KeyGen seed z (implicit-reject value)

Definition at line 58 of file mlkem.h.

Function Documentation

◆ PROTOCORE_NS_LAYOUT()

PROTOCORE_NS_LAYOUT ( MlKemNs  ,
keygen  ,
encaps  ,
decaps   
)

◆ protocore_ml_kem_keygen()

proto_bool protocore_ml_kem_keygen ( uint8_t *  work,
const uint8_t *  d,
const uint8_t *  z,
uint8_t *  ek,
uint8_t *  dk 
)

(ek, dk) from the two seeds, deterministic given them.

Parameters
workPROTOCORE_ML_KEM_BORROW bytes the caller took. Not held past the call.
dMLKEM768_D_BYTES key-material seed
zMLKEM768_Z_BYTES implicit-reject seed
ekMLKEM768_EK_BYTES encapsulation key
dkMLKEM768_DK_BYTES decapsulation key, embedding ek, H(ek) and z
Returns
PROTO_TRUE on success.

◆ protocore_ml_kem_encaps()

proto_bool protocore_ml_kem_encaps ( uint8_t *  work,
const uint8_t *  ek,
const uint8_t *  m,
uint8_t *  ct,
uint8_t *  ss 
)

(ct, ss) from a peer key and a message.

Parameters
workPROTOCORE_ML_KEM_BORROW bytes the caller took. Not held past the call.
ekMLKEM768_EK_BYTES peer encapsulation key
mMLKEM768_MSG_BYTES encapsulation randomness
ctMLKEM768_CT_BYTES ciphertext
ssMLKEM768_SS_BYTES shared secret
Returns
PROTO_TRUE on success.

◆ protocore_ml_kem_decaps()

proto_bool protocore_ml_kem_decaps ( uint8_t *  work,
const uint8_t *  dk,
const uint8_t *  ct,
uint8_t *  ss 
)

The shared secret from a ciphertext, through the FO transform.

Parameters
workPROTOCORE_ML_KEM_BORROW bytes the caller took. Not held past the call.
dkMLKEM768_DK_BYTES decapsulation key from a KeyGen
ctMLKEM768_CT_BYTES ciphertext from the peer's Encaps
ssMLKEM768_SS_BYTES shared secret
Returns
PROTO_TRUE on success.

Variable Documentation

◆ PROTOCORE_UNUSED

PROTOCORE_NS MlKemNs MlKem PROTOCORE_UNUSED
Initial value:
= {
proto_bool protocore_ml_kem_keygen(uint8_t *work, const uint8_t *d, const uint8_t *z, uint8_t *ek, uint8_t *dk)
(ek, dk) from the two seeds, deterministic given them.
proto_bool protocore_ml_kem_encaps(uint8_t *work, const uint8_t *ek, const uint8_t *m, uint8_t *ct, uint8_t *ss)
(ct, ss) from a peer key and a message.
proto_bool protocore_ml_kem_decaps(uint8_t *work, const uint8_t *dk, const uint8_t *ct, uint8_t *ss)
The shared secret from a ciphertext, through the FO transform.

Module namespace.

Definition at line 100 of file mlkem.h.