#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
)]
#![allow(non_snake_case)] #![allow(clippy::clone_on_copy)] #![deny(missing_docs)] #![warn(clippy::pedantic)] #![warn(clippy::integer_division_remainder_used)]
mod util;
mod algebra;
mod crypto;
mod compress;
mod encode;
mod pke;
#[cfg(feature = "hardened")]
mod hardened_rng;
#[cfg(feature = "hardened")]
mod masking;
pub mod kem;
#[cfg(feature = "wasm")]
pub mod wasm;
mod param;
use core::fmt::Debug;
pub use hybrid_array as array;
use hybrid_array::Array;
use hybrid_array::typenum::{
U2,
U3,
U4,
U5,
U10,
U11,
Unsigned,
};
use rand_core::CryptoRng;
pub use zeroize::Zeroizing;
pub trait Encapsulate<EK, SS> {
type Error: Debug;
fn encapsulate<R: CryptoRng + ?Sized>(&self, rng: &mut R) -> Result<(EK, SS), Self::Error>;
}
pub trait Decapsulate<EK, SS> {
type Error: Debug;
fn decapsulate(&self, encapsulated_key: &EK) -> Result<SS, Self::Error>;
}
pub use param::{
ArraySize,
ParameterSet,
};
#[cfg(feature = "deterministic")]
pub use util::B32;
pub trait EncodedSizeUser {
type EncodedSize: ArraySize;
fn from_bytes(enc: &Encoded<Self>) -> Self;
fn as_bytes(&self) -> Zeroizing<Encoded<Self>>;
}
pub type Encoded<T> = Array<u8, <T as EncodedSizeUser>::EncodedSize>;
#[cfg(feature = "deterministic")]
pub trait EncapsulateDeterministic<EK, SS> {
type Error: Debug;
fn encapsulate_deterministic(&self, m: &B32) -> Result<(EK, SS), Self::Error>;
}
pub trait KemCore: Clone {
type SharedKeySize: ArraySize;
type CiphertextSize: ArraySize;
type DecapsulationKey: Decapsulate<Ciphertext<Self>, SharedKey<Self>>
+ EncodedSizeUser
+ Debug
+ PartialEq;
#[cfg(not(feature = "deterministic"))]
type EncapsulationKey: Encapsulate<Ciphertext<Self>, SharedKey<Self>>
+ EncodedSizeUser
+ Clone
+ Debug
+ PartialEq;
#[cfg(feature = "deterministic")]
type EncapsulationKey: Encapsulate<Ciphertext<Self>, SharedKey<Self>>
+ EncapsulateDeterministic<Ciphertext<Self>, SharedKey<Self>>
+ EncodedSizeUser
+ Clone
+ Debug
+ PartialEq;
fn generate<R: CryptoRng + ?Sized>(
rng: &mut R,
) -> (Self::DecapsulationKey, Self::EncapsulationKey);
#[cfg(feature = "deterministic")]
fn generate_deterministic(d: &B32, z: &B32)
-> (Self::DecapsulationKey, Self::EncapsulationKey);
}
#[derive(Default, Clone, Debug, PartialEq)]
pub struct MlKem512Params;
impl ParameterSet for MlKem512Params {
type K = U2;
type Eta1 = U3;
type Eta2 = U2;
type Du = U10;
type Dv = U4;
}
#[derive(Default, Clone, Debug, PartialEq)]
pub struct MlKem768Params;
impl ParameterSet for MlKem768Params {
type K = U3;
type Eta1 = U2;
type Eta2 = U2;
type Du = U10;
type Dv = U4;
}
#[derive(Default, Clone, Debug, PartialEq)]
pub struct MlKem1024Params;
impl ParameterSet for MlKem1024Params {
type K = U4;
type Eta1 = U2;
type Eta2 = U2;
type Du = U11;
type Dv = U5;
}
pub type SharedKey<K> = Array<u8, <K as KemCore>::SharedKeySize>;
pub type Ciphertext<K> = Array<u8, <K as KemCore>::CiphertextSize>;
pub type MlKem512 = kem::Kem<MlKem512Params>;
pub type MlKem768 = kem::Kem<MlKem768Params>;
pub type MlKem1024 = kem::Kem<MlKem1024Params>;
pub const MLKEM512_PUBLIC_KEY_SIZE: usize =
<kem::EncapsulationKey<MlKem512Params> as EncodedSizeUser>::EncodedSize::USIZE;
pub const MLKEM512_SECRET_KEY_SIZE: usize =
<kem::DecapsulationKey<MlKem512Params> as EncodedSizeUser>::EncodedSize::USIZE;
pub const MLKEM512_CIPHERTEXT_SIZE: usize = <MlKem512 as KemCore>::CiphertextSize::USIZE;
pub const MLKEM_SHARED_KEY_SIZE: usize = <MlKem512 as KemCore>::SharedKeySize::USIZE;
pub const MLKEM768_PUBLIC_KEY_SIZE: usize =
<kem::EncapsulationKey<MlKem768Params> as EncodedSizeUser>::EncodedSize::USIZE;
pub const MLKEM768_SECRET_KEY_SIZE: usize =
<kem::DecapsulationKey<MlKem768Params> as EncodedSizeUser>::EncodedSize::USIZE;
pub const MLKEM768_CIPHERTEXT_SIZE: usize = <MlKem768 as KemCore>::CiphertextSize::USIZE;
pub const MLKEM1024_PUBLIC_KEY_SIZE: usize =
<kem::EncapsulationKey<MlKem1024Params> as EncodedSizeUser>::EncodedSize::USIZE;
pub const MLKEM1024_SECRET_KEY_SIZE: usize =
<kem::DecapsulationKey<MlKem1024Params> as EncodedSizeUser>::EncodedSize::USIZE;
pub const MLKEM1024_CIPHERTEXT_SIZE: usize = <MlKem1024 as KemCore>::CiphertextSize::USIZE;
#[cfg(test)]
mod test {
#[cfg(feature = "random")]
use super::*;
#[cfg(feature = "random")]
fn round_trip_test<K>()
where
K: KemCore,
{
let mut rng = lib_q_random::LibQRng::new_secure().expect("Failed to create secure RNG");
let (dk, ek) = K::generate(&mut rng);
let (ct, k_send) = ek.encapsulate(&mut rng).unwrap();
let k_recv = dk.decapsulate(&ct).unwrap();
assert_eq!(k_send, k_recv);
}
#[test]
#[cfg(feature = "random")]
fn round_trip() {
round_trip_test::<MlKem512>();
round_trip_test::<MlKem768>();
round_trip_test::<MlKem1024>();
}
}