const n … const q … const log2q … const k … const η … const du … const dv … const encodingSize12 … const encodingSize10 … const encodingSize4 … const encodingSize1 … const messageSize … const decryptionKeySize … const encryptionKeySize … const CiphertextSize … const EncapsulationKeySize … const DecapsulationKeySize … const SharedKeySize … const SeedSize … type DecapsulationKey … // Bytes returns the extended encoding of the decapsulation key, according to // FIPS 203 (DRAFT). func (dk *DecapsulationKey) Bytes() []byte { … } // EncapsulationKey returns the public encapsulation key necessary to produce // ciphertexts. func (dk *DecapsulationKey) EncapsulationKey() []byte { … } type encryptionKey … type decryptionKey … // GenerateKey generates a new decapsulation key, drawing random bytes from // crypto/rand. The decapsulation key must be kept secret. func GenerateKey() (*DecapsulationKey, error) { … } func generateKey(dk *DecapsulationKey) (*DecapsulationKey, error) { … } // NewKeyFromSeed deterministically generates a decapsulation key from a 64-byte // seed in the "d || z" form. The seed must be uniformly random. func NewKeyFromSeed(seed []byte) (*DecapsulationKey, error) { … } func newKeyFromSeed(dk *DecapsulationKey, seed []byte) (*DecapsulationKey, error) { … } // NewKeyFromExtendedEncoding parses a decapsulation key from its FIPS 203 // (DRAFT) extended encoding. func NewKeyFromExtendedEncoding(decapsulationKey []byte) (*DecapsulationKey, error) { … } func newKeyFromExtendedEncoding(dk *DecapsulationKey, dkBytes []byte) (*DecapsulationKey, error) { … } // kemKeyGen generates a decapsulation key. // // It implements ML-KEM.KeyGen according to FIPS 203 (DRAFT), Algorithm 15, and // K-PKE.KeyGen according to FIPS 203 (DRAFT), Algorithm 12. The two are merged // to save copies and allocations. func kemKeyGen(dk *DecapsulationKey, d, z *[32]byte) *DecapsulationKey { … } // Encapsulate generates a shared key and an associated ciphertext from an // encapsulation key, drawing random bytes from crypto/rand. // If the encapsulation key is not valid, Encapsulate returns an error. // // The shared key must be kept secret. func Encapsulate(encapsulationKey []byte) (ciphertext, sharedKey []byte, err error) { … } func encapsulate(cc *[CiphertextSize]byte, encapsulationKey []byte) (ciphertext, sharedKey []byte, err error) { … } // kemEncaps generates a shared key and an associated ciphertext. // // It implements ML-KEM.Encaps according to FIPS 203 (DRAFT), Algorithm 16. func kemEncaps(cc *[CiphertextSize]byte, ek []byte, m *[messageSize]byte) (c, K []byte, err error) { … } // parseEK parses an encryption key from its encoded form. // // It implements the initial stages of K-PKE.Encrypt according to FIPS 203 // (DRAFT), Algorithm 13. func parseEK(ex *encryptionKey, ekPKE []byte) error { … } // pkeEncrypt encrypt a plaintext message. // // It implements K-PKE.Encrypt according to FIPS 203 (DRAFT), Algorithm 13, // although the computation of t and AT is done in parseEK. func pkeEncrypt(cc *[CiphertextSize]byte, ex *encryptionKey, m *[messageSize]byte, rnd []byte) []byte { … } // Decapsulate generates a shared key from a ciphertext and a decapsulation key. // If the ciphertext is not valid, Decapsulate returns an error. // // The shared key must be kept secret. func Decapsulate(dk *DecapsulationKey, ciphertext []byte) (sharedKey []byte, err error) { … } // kemDecaps produces a shared key from a ciphertext. // // It implements ML-KEM.Decaps according to FIPS 203 (DRAFT), Algorithm 17. func kemDecaps(dk *DecapsulationKey, c *[CiphertextSize]byte) (K []byte) { … } // parseDK parses a decryption key from its encoded form. // // It implements the computation of s from K-PKE.Decrypt according to FIPS 203 // (DRAFT), Algorithm 14. func parseDK(dx *decryptionKey, dkPKE []byte) error { … } // pkeDecrypt decrypts a ciphertext. // // It implements K-PKE.Decrypt according to FIPS 203 (DRAFT), Algorithm 14, // although the computation of s is done in parseDK. func pkeDecrypt(dx *decryptionKey, c *[CiphertextSize]byte) []byte { … } type fieldElement … // fieldCheckReduced checks that a value a is < q. func fieldCheckReduced(a uint16) (fieldElement, error) { … } // fieldReduceOnce reduces a value a < 2q. func fieldReduceOnce(a uint16) fieldElement { … } func fieldAdd(a, b fieldElement) fieldElement { … } func fieldSub(a, b fieldElement) fieldElement { … } const barrettMultiplier … const barrettShift … // fieldReduce reduces a value a < 2q² using Barrett reduction, to avoid // potentially variable-time division. func fieldReduce(a uint32) fieldElement { … } func fieldMul(a, b fieldElement) fieldElement { … } // fieldMulSub returns a * (b - c). This operation is fused to save a // fieldReduceOnce after the subtraction. func fieldMulSub(a, b, c fieldElement) fieldElement { … } // fieldAddMul returns a * b + c * d. This operation is fused to save a // fieldReduceOnce and a fieldReduce. func fieldAddMul(a, b, c, d fieldElement) fieldElement { … } // compress maps a field element uniformly to the range 0 to 2ᵈ-1, according to // FIPS 203 (DRAFT), Definition 4.5. func compress(x fieldElement, d uint8) uint16 { … } // decompress maps a number x between 0 and 2ᵈ-1 uniformly to the full range of // field elements, according to FIPS 203 (DRAFT), Definition 4.6. func decompress(y uint16, d uint8) fieldElement { … } type ringElement … // polyAdd adds two ringElements or nttElements. func polyAdd[T ~[n]fieldElement](a, b T) (s T) { … } // polySub subtracts two ringElements or nttElements. func polySub[T ~[n]fieldElement](a, b T) (s T) { … } // polyByteEncode appends the 384-byte encoding of f to b. // // It implements ByteEncode₁₂, according to FIPS 203 (DRAFT), Algorithm 4. func polyByteEncode[T ~[n]fieldElement](b []byte, f T) []byte { … } // polyByteDecode decodes the 384-byte encoding of a polynomial, checking that // all the coefficients are properly reduced. This achieves the "Modulus check" // step of ML-KEM Encapsulation Input Validation. // // polyByteDecode is also used in ML-KEM Decapsulation, where the input // validation is not required, but implicitly allowed by the specification. // // It implements ByteDecode₁₂, according to FIPS 203 (DRAFT), Algorithm 5. func polyByteDecode[T ~[n]fieldElement](b []byte) (T, error) { … } // sliceForAppend takes a slice and a requested number of bytes. It returns a // slice with the contents of the given slice followed by that many bytes and a // second slice that aliases into it and contains only the extra bytes. If the // original slice has sufficient capacity then no allocation is performed. func sliceForAppend(in []byte, n int) (head, tail []byte) { … } // ringCompressAndEncode1 appends a 32-byte encoding of a ring element to s, // compressing one coefficients per bit. // // It implements Compress₁, according to FIPS 203 (DRAFT), Definition 4.5, // followed by ByteEncode₁, according to FIPS 203 (DRAFT), Algorithm 4. func ringCompressAndEncode1(s []byte, f ringElement) []byte { … } // ringDecodeAndDecompress1 decodes a 32-byte slice to a ring element where each // bit is mapped to 0 or ⌈q/2⌋. // // It implements ByteDecode₁, according to FIPS 203 (DRAFT), Algorithm 5, // followed by Decompress₁, according to FIPS 203 (DRAFT), Definition 4.6. func ringDecodeAndDecompress1(b *[encodingSize1]byte) ringElement { … } // ringCompressAndEncode4 appends a 128-byte encoding of a ring element to s, // compressing two coefficients per byte. // // It implements Compress₄, according to FIPS 203 (DRAFT), Definition 4.5, // followed by ByteEncode₄, according to FIPS 203 (DRAFT), Algorithm 4. func ringCompressAndEncode4(s []byte, f ringElement) []byte { … } // ringDecodeAndDecompress4 decodes a 128-byte encoding of a ring element where // each four bits are mapped to an equidistant distribution. // // It implements ByteDecode₄, according to FIPS 203 (DRAFT), Algorithm 5, // followed by Decompress₄, according to FIPS 203 (DRAFT), Definition 4.6. func ringDecodeAndDecompress4(b *[encodingSize4]byte) ringElement { … } // ringCompressAndEncode10 appends a 320-byte encoding of a ring element to s, // compressing four coefficients per five bytes. // // It implements Compress₁₀, according to FIPS 203 (DRAFT), Definition 4.5, // followed by ByteEncode₁₀, according to FIPS 203 (DRAFT), Algorithm 4. func ringCompressAndEncode10(s []byte, f ringElement) []byte { … } // ringDecodeAndDecompress10 decodes a 320-byte encoding of a ring element where // each ten bits are mapped to an equidistant distribution. // // It implements ByteDecode₁₀, according to FIPS 203 (DRAFT), Algorithm 5, // followed by Decompress₁₀, according to FIPS 203 (DRAFT), Definition 4.6. func ringDecodeAndDecompress10(bb *[encodingSize10]byte) ringElement { … } // samplePolyCBD draws a ringElement from the special Dη distribution given a // stream of random bytes generated by the PRF function, according to FIPS 203 // (DRAFT), Algorithm 7 and Definition 4.1. func samplePolyCBD(s []byte, b byte) ringElement { … } type nttElement … var gammas … // nttMul multiplies two nttElements. // // It implements MultiplyNTTs, according to FIPS 203 (DRAFT), Algorithm 10. func nttMul(f, g nttElement) nttElement { … } var zetas … // ntt maps a ringElement to its nttElement representation. // // It implements NTT, according to FIPS 203 (DRAFT), Algorithm 8. func ntt(f ringElement) nttElement { … } // inverseNTT maps a nttElement back to the ringElement it represents. // // It implements NTT⁻¹, according to FIPS 203 (DRAFT), Algorithm 9. func inverseNTT(f nttElement) ringElement { … } // sampleNTT draws a uniformly random nttElement from a stream of uniformly // random bytes generated by the XOF function, according to FIPS 203 (DRAFT), // Algorithm 6 and Definition 4.2. func sampleNTT(rho []byte, ii, jj byte) nttElement { … }