pub mod encode;
pub mod kem;
pub mod kpke;
pub mod masked;
pub mod ntt;
pub mod params;
pub mod rng;
pub mod sample;
pub mod sha3;
pub mod shuffle;
pub use params::{MlKem512, MlKem768, MlKem1024, Params};
pub use rng::CryptoRng;
#[cfg(feature = "std")]
pub use rng::OsRng;
use crate::secret::{SecretArray, SecretBytes};
use alloc::vec::Vec;
use core::marker::PhantomData;
pub struct EncapsulationKey<P: Params> {
bytes: Vec<u8>,
_marker: PhantomData<P>,
}
impl<P: Params> EncapsulationKey<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MlKemError> {
if bytes.len() != P::EK_LEN {
return Err(MlKemError::InvalidEncapsulationKey);
}
Ok(Self {
bytes: bytes.to_vec(),
_marker: PhantomData,
})
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn len(&self) -> usize {
self.bytes.len()
}
}
impl<P: Params> AsRef<[u8]> for EncapsulationKey<P> {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> core::ops::Deref for EncapsulationKey<P> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> Clone for EncapsulationKey<P> {
fn clone(&self) -> Self {
Self {
bytes: self.bytes.clone(),
_marker: PhantomData,
}
}
}
pub struct DecapsulationKey<P: Params> {
bytes: SecretBytes,
_marker: PhantomData<P>,
}
impl<P: Params> DecapsulationKey<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MlKemError> {
if bytes.len() != P::DK_LEN {
return Err(MlKemError::InvalidDecapsulationKey);
}
Ok(Self {
bytes: SecretBytes::from_slice(bytes),
_marker: PhantomData,
})
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_bytes()
}
pub fn len(&self) -> usize {
self.bytes.len()
}
}
impl<P: Params> AsRef<[u8]> for DecapsulationKey<P> {
fn as_ref(&self) -> &[u8] {
self.bytes.as_bytes()
}
}
impl<P: Params> core::ops::Deref for DecapsulationKey<P> {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.bytes.as_bytes()
}
}
pub struct Ciphertext<P: Params> {
bytes: Vec<u8>,
_marker: PhantomData<P>,
}
impl<P: Params> Ciphertext<P> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, MlKemError> {
if bytes.len() != P::CT_LEN {
return Err(MlKemError::InvalidCiphertext);
}
Ok(Self {
bytes: bytes.to_vec(),
_marker: PhantomData,
})
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn len(&self) -> usize {
self.bytes.len()
}
}
impl<P: Params> AsRef<[u8]> for Ciphertext<P> {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> core::ops::Deref for Ciphertext<P> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes
}
}
impl<P: Params> Clone for Ciphertext<P> {
fn clone(&self) -> Self {
Self {
bytes: self.bytes.clone(),
_marker: PhantomData,
}
}
}
pub type SharedSecret = SecretArray<32>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MlKemError {
RngFailure,
InvalidEncapsulationKey,
InvalidDecapsulationKey,
InvalidCiphertext,
}
impl core::fmt::Display for MlKemError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::RngFailure => write!(f, "Random bit generation failed"),
Self::InvalidEncapsulationKey => write!(f, "Invalid encapsulation key"),
Self::InvalidDecapsulationKey => write!(f, "Invalid decapsulation key"),
Self::InvalidCiphertext => write!(f, "Invalid ciphertext"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for MlKemError {}
pub struct MlKem<P: Params>(core::marker::PhantomData<P>);
impl<P: Params> MlKem<P> {
pub fn keygen(rng: &mut impl CryptoRng) -> Result<(EncapsulationKey<P>, DecapsulationKey<P>), MlKemError> {
let (ek_v, dk_v) = kem::keygen::<P>(rng)?;
Ok((
EncapsulationKey {
bytes: ek_v,
_marker: PhantomData,
},
DecapsulationKey {
bytes: SecretBytes::from_vec(dk_v),
_marker: PhantomData,
},
))
}
pub fn encaps(
ek: &EncapsulationKey<P>,
rng: &mut impl CryptoRng,
) -> Result<(SharedSecret, Ciphertext<P>), MlKemError> {
let (ss, ct) = kem::encaps::<P>(ek.as_bytes(), rng)?;
Ok((
SharedSecret::new(ss),
Ciphertext {
bytes: ct,
_marker: PhantomData,
},
))
}
pub fn decaps(
dk: &DecapsulationKey<P>,
ct: &Ciphertext<P>,
rng: &mut impl CryptoRng,
) -> Result<SharedSecret, MlKemError> {
kem::decaps::<P>(dk.as_bytes(), ct.as_bytes(), rng).map(SharedSecret::new)
}
pub fn decaps_fast(dk: &DecapsulationKey<P>, ct: &Ciphertext<P>) -> Result<SharedSecret, MlKemError> {
kem::decaps_single::<P>(dk.as_bytes(), ct.as_bytes()).map(SharedSecret::new)
}
pub fn keygen_internal(d: &[u8; 32], z: &[u8; 32]) -> (Vec<u8>, Vec<u8>) {
kem::keygen_internal::<P>(d, z)
}
pub fn encaps_internal(ek: &[u8], m: &[u8; 32]) -> ([u8; 32], Vec<u8>) {
kem::encaps_internal::<P>(ek, m)
}
pub fn decaps_internal(dk: &[u8], ct: &[u8]) -> [u8; 32] {
kem::decaps_internal::<P>(dk, ct)
}
}