libcrux_ml_kem/
lib.rs

1//! # ML-KEM
2//!
3//! This crate implements all three ML-KEM variants 512, 768, and 1024. It is
4//! formally verified using [hax](https://cryspen.com/hax) and
5//! [F*](https://fstar-lang.org).
6//!
7//! Functions in this crate use CPU feature detection to pick the most efficient version
8//! on each platform. To use a specific version with your own feature detection
9//! use e.g. one of the following
10//! - `mlkem768::avx2::generate_key_pair`,
11//! - `mlkem768::neon::generate_key_pair`,
12//! - `mlkem768::portable::generate_key_pair`,
13//!
14//! analogously for encapsulation and decapsulation."
15#![cfg_attr(
16    feature = "mlkem768",
17    doc = r##"
18```
19 use rand::{rngs::OsRng, TryRngCore};
20
21 // Ensure you use good randomness.
22 // It is not recommended to use OsRng directly!
23 // Instead it is highly encouraged to use RNGs like NISTs DRBG to account for
24 // bad system entropy.
25 fn random_array<const L: usize>() -> [u8; L] {
26     let mut rng = OsRng;
27     let mut seed = [0; L];
28     rng.try_fill_bytes(&mut seed).unwrap();
29     seed
30 }
31
32 use libcrux_ml_kem::*;
33
34 // This example uses ML-KEM 768. The other variants can be used the same way.
35
36 // Generate a key pair.
37 let key_pair = {
38    let randomness = random_array();
39    mlkem768::generate_key_pair(randomness)
40 };
41
42 // Encapsulating a shared secret to a public key.
43 let (ciphertext, shared_secret) = {
44    let randomness = random_array();
45    mlkem768::encapsulate(key_pair.public_key(), randomness)
46 };
47
48 // Decapsulating a shared secret with a private key.
49 let shared_secret_decapsulated = mlkem768::decapsulate(key_pair.private_key(), &ciphertext);
50
51 assert_eq!(shared_secret_decapsulated, shared_secret);
52```"##
53)]
54//!
55//! ## Features
56//!
57//! By default, all ML-KEM parameter sets are enabled. If required, they are
58//! available individually under feature flags `mlkem512`, `mlkem768`,
59//! `mlkem1024`.
60//!
61//! ### Kyber Round 3
62//! The `kyber` flag also gives access to an, as yet, unverified implementation
63//! of Kyber as submitted in Round 3 of the NIST PQ competition.
64//!
65
66#![no_std]
67#![deny(missing_docs)]
68#![deny(unsafe_code)]
69#![warn(rust_2018_idioms, unused_lifetimes, unused_qualifications)]
70#![allow(clippy::needless_range_loop)]
71#![warn(missing_docs)]
72// Enable doc cfg feature for doc builds. They use nightly.
73#![cfg_attr(doc_cfg, feature(doc_cfg))]
74
75#[cfg(feature = "std")]
76extern crate std;
77
78/// Feature gating helper macros
79#[macro_use]
80mod cfg;
81
82pub(crate) mod hax_utils;
83
84// This module is declared here since otherwise, hax reports the following error:
85//
86// The THIR body of item
87// DefId(0:986 ~ libcrux[92b3]::kem::kyber768::parameters::COEFFICIENTS_IN_RING_ELEMENT)
88// was stolen.
89//
90// This is being tracked in https://github.com/hacspec/hacspec-v2/issues/27
91pub(crate) mod constants;
92
93#[cfg(all(feature = "alloc", feature = "incremental"))]
94extern crate alloc;
95
96/// Helpers for verification and extraction
97mod helper;
98
99mod constant_time_ops;
100mod hash_functions;
101mod ind_cca;
102mod ind_cpa;
103mod invert_ntt;
104mod matrix;
105mod mlkem;
106mod ntt;
107mod polynomial;
108mod sampling;
109mod serialize;
110mod types;
111mod utils;
112mod variant;
113mod vector;
114
115#[cfg(feature = "mlkem512")]
116#[cfg_attr(docsrs, doc(cfg(feature = "mlkem512")))]
117pub mod mlkem512;
118
119#[cfg(feature = "mlkem768")]
120#[cfg_attr(docsrs, doc(cfg(feature = "mlkem768")))]
121pub mod mlkem768;
122
123#[cfg(feature = "mlkem1024")]
124#[cfg_attr(docsrs, doc(cfg(feature = "mlkem1024")))]
125pub mod mlkem1024;
126
127pub use constants::SHARED_SECRET_SIZE;
128
129pub use ind_cca::{MlKemSharedSecret, ENCAPS_SEED_SIZE, KEY_GENERATION_SEED_SIZE};
130
131// These types all have type aliases for the different variants.
132pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey};
133
134cfg_kyber! {
135    #[cfg(feature = "mlkem512")]
136    #[cfg_attr(docsrs, doc(cfg(all(feature = "kyber", feature = "mlkem512"))))]
137    pub mod kyber512 {
138        //! Kyber 512 (NIST PQC Round 3)
139        cfg_no_eurydice! {
140            pub use crate::mlkem512::kyber::generate_key_pair;
141            pub use crate::mlkem512::kyber::decapsulate;
142            pub use crate::mlkem512::kyber::encapsulate;
143            pub use crate::mlkem512::validate_public_key;
144            pub use crate::mlkem512::validate_private_key;
145        }
146    }
147
148    #[cfg(feature = "mlkem768")]
149    #[cfg_attr(docsrs, doc(cfg(all(feature = "kyber", feature = "mlkem768"))))]
150    pub mod kyber768 {
151        //! Kyber 768 (NIST PQC Round 3)
152        cfg_no_eurydice! {
153            pub use crate::mlkem768::kyber::generate_key_pair;
154            pub use crate::mlkem768::kyber::decapsulate;
155            pub use crate::mlkem768::kyber::encapsulate;
156            pub use crate::mlkem768::validate_public_key;
157            pub use crate::mlkem768::validate_private_key;
158        }
159    }
160
161    #[cfg(feature = "mlkem1024")]
162    #[cfg_attr(docsrs, doc(cfg(all(feature = "kyber", feature = "mlkem1024"))))]
163    pub mod kyber1024 {
164        //! Kyber 1024 (NIST PQC Round 3)
165        cfg_no_eurydice! {
166            pub use crate::mlkem1024::kyber::generate_key_pair;
167            pub use crate::mlkem1024::kyber::decapsulate;
168            pub use crate::mlkem1024::kyber::encapsulate;
169            pub use crate::mlkem1024::validate_public_key;
170            pub use crate::mlkem1024::validate_private_key;
171        }
172    }
173}