1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8#![allow(non_snake_case)] #![allow(clippy::clone_on_copy)] #![cfg_attr(feature = "getrandom", doc = "```")]
21#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
22mod algebra;
49
50mod crypto;
52
53mod compress;
55
56mod decapsulation_key;
58
59mod encapsulation_key;
61
62mod pke;
64
65mod param;
67
68pub mod pkcs8;
70
71pub use array::{self, ArraySize};
72pub use decapsulation_key::DecapsulationKey;
73#[allow(deprecated)]
74pub use decapsulation_key::ExpandedKeyEncoding;
75pub use encapsulation_key::EncapsulationKey;
76pub use kem::{
77 self, Ciphertext, Decapsulate, Encapsulate, FromSeed, Generate, InvalidKey, Kem, Key,
78 KeyExport, KeyInit, KeySizeUser, TryKeyInit,
79};
80pub use ml_kem_512::MlKem512;
81pub use ml_kem_768::MlKem768;
82pub use ml_kem_1024::MlKem1024;
83pub use param::{ExpandedDecapsulationKey, ParameterSet};
84
85use array::{
86 Array,
87 sizes::{U2, U3, U4, U5, U10, U11, U32, U64},
88};
89use core::fmt::Debug;
90
91pub type B32 = Array<u8, U32>;
93
94pub type Seed = Array<u8, U64>;
97
98pub mod ml_kem_512 {
101 use crate::{
102 Debug, ParameterSet, U2, U3, U4, U10,
103 kem::Kem,
104 param::{self, EncodedUSize, EncodedVSize},
105 };
106 use array::{sizes::U32, typenum::Sum};
107
108 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
111 pub struct MlKem512;
112
113 impl ParameterSet for MlKem512 {
114 type K = U2;
115 type Eta1 = U3;
116 type Eta2 = U2;
117 type Du = U10;
118 type Dv = U4;
119 }
120
121 impl Kem for MlKem512 {
122 type DecapsulationKey = DecapsulationKey;
123 type EncapsulationKey = EncapsulationKey;
124 type CiphertextSize = Sum<EncodedUSize<Self>, EncodedVSize<Self>>;
125 type SharedKeySize = U32;
126 }
127
128 pub type DecapsulationKey = crate::DecapsulationKey<MlKem512>;
131
132 pub type EncapsulationKey = crate::EncapsulationKey<MlKem512>;
135
136 pub type Ciphertext = kem::Ciphertext<MlKem512>;
138
139 #[doc(hidden)]
141 #[deprecated(since = "0.3.0", note = "use `Seed` instead")]
142 pub type ExpandedDecapsulationKey = param::ExpandedDecapsulationKey<MlKem512>;
143}
144
145pub mod ml_kem_768 {
148 use crate::{
149 Debug, ParameterSet, U2, U3, U4, U10,
150 kem::Kem,
151 param::{self, EncodedUSize, EncodedVSize},
152 };
153 use array::sizes::U32;
154 use array::typenum::Sum;
155
156 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
159 pub struct MlKem768;
160
161 impl ParameterSet for MlKem768 {
162 type K = U3;
163 type Eta1 = U2;
164 type Eta2 = U2;
165 type Du = U10;
166 type Dv = U4;
167 }
168
169 impl Kem for MlKem768 {
170 type DecapsulationKey = DecapsulationKey;
171 type EncapsulationKey = EncapsulationKey;
172 type CiphertextSize = Sum<EncodedUSize<Self>, EncodedVSize<Self>>;
173 type SharedKeySize = U32;
174 }
175
176 pub type DecapsulationKey = crate::DecapsulationKey<MlKem768>;
179
180 pub type EncapsulationKey = crate::EncapsulationKey<MlKem768>;
183
184 pub type Ciphertext = kem::Ciphertext<MlKem768>;
186
187 #[doc(hidden)]
189 #[deprecated(since = "0.3.0", note = "use `Seed` instead")]
190 pub type ExpandedDecapsulationKey = param::ExpandedDecapsulationKey<MlKem768>;
191}
192
193pub mod ml_kem_1024 {
196 use crate::{
197 Debug, ParameterSet, U2, U4, U5, U11,
198 kem::Kem,
199 param::{self, EncodedUSize, EncodedVSize},
200 };
201 use array::{sizes::U32, typenum::Sum};
202
203 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
206 pub struct MlKem1024;
207
208 impl ParameterSet for MlKem1024 {
209 type K = U4;
210 type Eta1 = U2;
211 type Eta2 = U2;
212 type Du = U11;
213 type Dv = U5;
214 }
215
216 impl Kem for MlKem1024 {
217 type DecapsulationKey = DecapsulationKey;
218 type EncapsulationKey = EncapsulationKey;
219 type CiphertextSize = Sum<EncodedUSize<Self>, EncodedVSize<Self>>;
220 type SharedKeySize = U32;
221 }
222
223 pub type DecapsulationKey = crate::DecapsulationKey<MlKem1024>;
226
227 pub type EncapsulationKey = crate::EncapsulationKey<MlKem1024>;
230
231 pub type Ciphertext = kem::Ciphertext<MlKem1024>;
233
234 #[doc(hidden)]
236 #[deprecated(since = "0.3.0", note = "use `Seed` instead")]
237 pub type ExpandedDecapsulationKey = param::ExpandedDecapsulationKey<MlKem1024>;
238}
239
240pub type DecapsulationKey512 = ml_kem_512::DecapsulationKey;
243
244pub type EncapsulationKey512 = ml_kem_512::EncapsulationKey;
247
248pub type DecapsulationKey768 = ml_kem_768::DecapsulationKey;
251
252pub type EncapsulationKey768 = ml_kem_768::EncapsulationKey;
255
256pub type DecapsulationKey1024 = ml_kem_1024::DecapsulationKey;
259
260pub type EncapsulationKey1024 = ml_kem_1024::EncapsulationKey;
263
264pub type SharedKey = Array<u8, U32>;
266
267#[cfg(test)]
268#[cfg(feature = "getrandom")]
269mod test {
270 use super::*;
271 use crate::{MlKem512, MlKem768, MlKem1024, param::KemParams};
272 use ::kem::{Encapsulate, Generate, InvalidKey, TryDecapsulate};
273 use array::typenum::Unsigned;
274 use getrandom::SysRng;
275 use rand_core::{TryRng, UnwrapErr};
276
277 fn round_trip_test<K>()
278 where
279 K: Kem,
280 {
281 let (dk, ek) = K::generate_keypair();
282 let (ct, k_send) = ek.encapsulate();
283 let k_recv = dk.try_decapsulate(&ct).unwrap();
284 assert_eq!(k_send, k_recv);
285 }
286
287 #[test]
288 fn round_trip() {
289 round_trip_test::<MlKem512>();
290 round_trip_test::<MlKem768>();
291 round_trip_test::<MlKem1024>();
292 }
293
294 fn seed_test<P>()
295 where
296 P: KemParams,
297 {
298 let mut rng = UnwrapErr(SysRng);
299 let mut seed = Seed::default();
300 rng.try_fill_bytes(&mut seed).unwrap();
301
302 let dk = DecapsulationKey::<P>::from_seed(seed.clone());
303 let seed_encoded = dk.to_seed().unwrap();
304 assert_eq!(seed, seed_encoded);
305
306 let ek_original = dk.encapsulation_key();
307 let ek_encoded = ek_original.to_bytes();
308 let ek_decoded = EncapsulationKey::new(&ek_encoded).unwrap();
309 assert_eq!(ek_original, &ek_decoded);
310 }
311
312 #[test]
313 fn seed() {
314 seed_test::<MlKem512>();
315 seed_test::<MlKem768>();
316 seed_test::<MlKem1024>();
317 }
318
319 #[allow(deprecated)]
320 fn expanded_key_test<P>()
321 where
322 P: KemParams,
323 {
324 let mut rng = UnwrapErr(SysRng);
325 let dk_original = DecapsulationKey::<P>::generate_from_rng(&mut rng);
326 let dk_encoded = dk_original.to_expanded_bytes();
327 let dk_decoded = DecapsulationKey::from_expanded_bytes(&dk_encoded).unwrap();
328 assert_eq!(dk_original, dk_decoded);
329 }
330
331 #[test]
332 fn expanded_key() {
333 expanded_key_test::<MlKem512>();
334 expanded_key_test::<MlKem768>();
335 expanded_key_test::<MlKem1024>();
336 }
337
338 fn invalid_hash_expanded_key_test<P>()
339 where
340 P: KemParams,
341 {
342 let mut rng = UnwrapErr(SysRng);
343 let dk_original = DecapsulationKey::<P>::generate_from_rng(&mut rng);
344
345 #[allow(deprecated)]
346 let mut dk_encoded = dk_original.to_expanded_bytes();
347
348 let hash_offset = P::NttVectorSize::USIZE + P::EncryptionKeySize::USIZE;
350 dk_encoded[hash_offset] ^= 0xFF;
351
352 #[allow(deprecated)]
353 let dk_decoded: Result<DecapsulationKey<P>, InvalidKey> =
354 DecapsulationKey::from_expanded_bytes(&dk_encoded);
355
356 assert!(dk_decoded.is_err());
357 }
358
359 #[test]
360 fn invalid_hash_expanded_key() {
361 invalid_hash_expanded_key_test::<MlKem512>();
362 invalid_hash_expanded_key_test::<MlKem768>();
363 invalid_hash_expanded_key_test::<MlKem1024>();
364 }
365
366 fn key_inequality_test<P>()
367 where
368 P: KemParams,
369 {
370 let mut rng = UnwrapErr(SysRng);
371
372 let dk1 = DecapsulationKey::<P>::generate_from_rng(&mut rng);
374 let dk2 = DecapsulationKey::<P>::generate_from_rng(&mut rng);
375
376 let ek1 = dk1.encapsulation_key();
377 let ek2 = dk2.encapsulation_key();
378
379 assert_ne!(dk1, dk2);
381 assert_ne!(ek1, ek2);
382 }
383
384 #[test]
385 fn key_inequality() {
386 key_inequality_test::<MlKem512>();
387 key_inequality_test::<MlKem768>();
388 key_inequality_test::<MlKem1024>();
389 }
390}