use rand_core::{OsRng, RngCore};
#[repr(C)]
pub struct ml_kem_shared_secret {
data: [u8; fips203::SSK_LEN],
}
#[repr(C)]
pub struct ml_kem_seed {
data: [u8; 64],
}
pub const ML_KEM_OK: u8 = 0;
pub const ML_KEM_NULL_PTR_ERROR: u8 = 1;
pub const ML_KEM_SERIALIZATION_ERROR: u8 = 2;
pub const ML_KEM_DESERIALIZATION_ERROR: u8 = 3;
pub const ML_KEM_KEYGEN_ERROR: u8 = 4;
pub const ML_KEM_ENCAPSULATION_ERROR: u8 = 5;
pub const ML_KEM_DECAPSULATION_ERROR: u8 = 6;
#[no_mangle]
pub extern "C" fn ml_kem_populate_seed(seed_out: Option<&mut ml_kem_seed>) -> u8 {
let Some(seed_out) = seed_out else {
return ML_KEM_NULL_PTR_ERROR;
};
OsRng.fill_bytes(&mut seed_out.data);
ML_KEM_OK
}
#[repr(C)]
pub struct ml_kem_512_encaps_key {
data: [u8; fips203::ml_kem_512::EK_LEN],
}
#[repr(C)]
pub struct ml_kem_512_decaps_key {
data: [u8; fips203::ml_kem_512::DK_LEN],
}
#[repr(C)]
pub struct ml_kem_512_ciphertext {
data: [u8; fips203::ml_kem_512::CT_LEN],
}
#[no_mangle]
pub extern "C" fn ml_kem_512_keygen(
encaps_out: Option<&mut ml_kem_512_encaps_key>,
decaps_out: Option<&mut ml_kem_512_decaps_key>,
) -> u8 {
use fips203::traits::{KeyGen, SerDes};
let (Some(encaps_out), Some(decaps_out)) = (encaps_out, decaps_out) else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok((ek, dk)) = fips203::ml_kem_512::KG::try_keygen() else {
return ML_KEM_KEYGEN_ERROR;
};
encaps_out.data = ek.into_bytes();
decaps_out.data = dk.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_512_keygen_from_seed(
seed: Option<&ml_kem_seed>,
encaps_out: Option<&mut ml_kem_512_encaps_key>,
decaps_out: Option<&mut ml_kem_512_decaps_key>,
) -> u8 {
use fips203::traits::{KeyGen, SerDes};
let (Some(encaps_out), Some(decaps_out), Some(seed)) = (encaps_out, decaps_out, seed) else {
return ML_KEM_NULL_PTR_ERROR;
};
let (ek, dk) = fips203::ml_kem_512::KG::keygen_from_seed(
seed.data[0..32].try_into().unwrap(),
seed.data[32..64].try_into().unwrap(),
);
encaps_out.data = ek.into_bytes();
decaps_out.data = dk.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_512_encaps(
encaps: Option<&ml_kem_512_encaps_key>,
ciphertext_out: Option<&mut ml_kem_512_ciphertext>,
shared_secret_out: Option<&mut ml_kem_shared_secret>,
) -> u8 {
use fips203::traits::{Encaps, SerDes};
let (Some(encaps), Some(ciphertext_out), Some(shared_secret_out)) =
(encaps, ciphertext_out, shared_secret_out)
else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok(ek) = fips203::ml_kem_512::EncapsKey::try_from_bytes(encaps.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok((ssk, ct)) = ek.try_encaps() else {
return ML_KEM_ENCAPSULATION_ERROR;
};
shared_secret_out.data = ssk.into_bytes();
ciphertext_out.data = ct.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_512_decaps(
decaps: Option<&ml_kem_512_decaps_key>,
ciphertext: Option<&ml_kem_512_ciphertext>,
shared_secret_out: Option<&mut ml_kem_shared_secret>,
) -> u8 {
use fips203::traits::{Decaps, SerDes};
let (Some(decaps), Some(ciphertext), Some(shared_secret_out)) =
(decaps, ciphertext, shared_secret_out)
else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok(dk) = fips203::ml_kem_512::DecapsKey::try_from_bytes(decaps.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok(ct) = fips203::ml_kem_512::CipherText::try_from_bytes(ciphertext.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok(ssk) = dk.try_decaps(&ct) else {
return ML_KEM_DECAPSULATION_ERROR;
};
shared_secret_out.data = ssk.into_bytes();
ML_KEM_OK
}
#[repr(C)]
pub struct ml_kem_768_encaps_key {
data: [u8; fips203::ml_kem_768::EK_LEN],
}
#[repr(C)]
pub struct ml_kem_768_decaps_key {
data: [u8; fips203::ml_kem_768::DK_LEN],
}
#[repr(C)]
pub struct ml_kem_768_ciphertext {
data: [u8; fips203::ml_kem_768::CT_LEN],
}
#[no_mangle]
pub extern "C" fn ml_kem_768_keygen(
encaps_out: Option<&mut ml_kem_768_encaps_key>,
decaps_out: Option<&mut ml_kem_768_decaps_key>,
) -> u8 {
use fips203::traits::{KeyGen, SerDes};
let (Some(encaps_out), Some(decaps_out)) = (encaps_out, decaps_out) else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok((ek, dk)) = fips203::ml_kem_768::KG::try_keygen() else {
return ML_KEM_KEYGEN_ERROR;
};
encaps_out.data = ek.into_bytes();
decaps_out.data = dk.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_768_keygen_from_seed(
seed: Option<&ml_kem_seed>,
encaps_out: Option<&mut ml_kem_768_encaps_key>,
decaps_out: Option<&mut ml_kem_768_decaps_key>,
) -> u8 {
use fips203::traits::{KeyGen, SerDes};
let (Some(encaps_out), Some(decaps_out), Some(seed)) = (encaps_out, decaps_out, seed) else {
return ML_KEM_NULL_PTR_ERROR;
};
let (ek, dk) = fips203::ml_kem_768::KG::keygen_from_seed(
seed.data[0..32].try_into().unwrap(),
seed.data[32..64].try_into().unwrap(),
);
encaps_out.data = ek.into_bytes();
decaps_out.data = dk.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_768_encaps(
encaps: Option<&ml_kem_768_encaps_key>,
ciphertext_out: Option<&mut ml_kem_768_ciphertext>,
shared_secret_out: Option<&mut ml_kem_shared_secret>,
) -> u8 {
use fips203::traits::{Encaps, SerDes};
let (Some(encaps), Some(ciphertext_out), Some(shared_secret_out)) =
(encaps, ciphertext_out, shared_secret_out)
else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok(ek) = fips203::ml_kem_768::EncapsKey::try_from_bytes(encaps.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok((ssk, ct)) = ek.try_encaps() else {
return ML_KEM_ENCAPSULATION_ERROR;
};
shared_secret_out.data = ssk.into_bytes();
ciphertext_out.data = ct.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_768_decaps(
decaps: Option<&ml_kem_768_decaps_key>,
ciphertext: Option<&ml_kem_768_ciphertext>,
shared_secret_out: Option<&mut ml_kem_shared_secret>,
) -> u8 {
use fips203::traits::{Decaps, SerDes};
let (Some(decaps), Some(ciphertext), Some(shared_secret_out)) =
(decaps, ciphertext, shared_secret_out)
else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok(dk) = fips203::ml_kem_768::DecapsKey::try_from_bytes(decaps.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok(ct) = fips203::ml_kem_768::CipherText::try_from_bytes(ciphertext.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok(ssk) = dk.try_decaps(&ct) else {
return ML_KEM_DECAPSULATION_ERROR;
};
shared_secret_out.data = ssk.into_bytes();
ML_KEM_OK
}
#[repr(C)]
pub struct ml_kem_1024_encaps_key {
data: [u8; fips203::ml_kem_1024::EK_LEN],
}
#[repr(C)]
pub struct ml_kem_1024_decaps_key {
data: [u8; fips203::ml_kem_1024::DK_LEN],
}
#[repr(C)]
pub struct ml_kem_1024_ciphertext {
data: [u8; fips203::ml_kem_1024::CT_LEN],
}
#[no_mangle]
pub extern "C" fn ml_kem_1024_keygen(
encaps_out: Option<&mut ml_kem_1024_encaps_key>,
decaps_out: Option<&mut ml_kem_1024_decaps_key>,
) -> u8 {
use fips203::traits::{KeyGen, SerDes};
let (Some(encaps_out), Some(decaps_out)) = (encaps_out, decaps_out) else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok((ek, dk)) = fips203::ml_kem_1024::KG::try_keygen() else {
return ML_KEM_KEYGEN_ERROR;
};
encaps_out.data = ek.into_bytes();
decaps_out.data = dk.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_1024_keygen_from_seed(
seed: Option<&ml_kem_seed>,
encaps_out: Option<&mut ml_kem_1024_encaps_key>,
decaps_out: Option<&mut ml_kem_1024_decaps_key>,
) -> u8 {
use fips203::traits::{KeyGen, SerDes};
let (Some(encaps_out), Some(decaps_out), Some(seed)) = (encaps_out, decaps_out, seed) else {
return ML_KEM_NULL_PTR_ERROR;
};
let (ek, dk) = fips203::ml_kem_1024::KG::keygen_from_seed(
seed.data[0..32].try_into().unwrap(),
seed.data[32..64].try_into().unwrap(),
);
encaps_out.data = ek.into_bytes();
decaps_out.data = dk.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_1024_encaps(
encaps: Option<&ml_kem_1024_encaps_key>,
ciphertext_out: Option<&mut ml_kem_1024_ciphertext>,
shared_secret_out: Option<&mut ml_kem_shared_secret>,
) -> u8 {
use fips203::traits::{Encaps, SerDes};
let (Some(encaps), Some(ciphertext_out), Some(shared_secret_out)) =
(encaps, ciphertext_out, shared_secret_out)
else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok(ek) = fips203::ml_kem_1024::EncapsKey::try_from_bytes(encaps.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok((ssk, ct)) = ek.try_encaps() else {
return ML_KEM_ENCAPSULATION_ERROR;
};
shared_secret_out.data = ssk.into_bytes();
ciphertext_out.data = ct.into_bytes();
ML_KEM_OK
}
#[no_mangle]
pub extern "C" fn ml_kem_1024_decaps(
decaps: Option<&ml_kem_1024_decaps_key>,
ciphertext: Option<&ml_kem_1024_ciphertext>,
shared_secret_out: Option<&mut ml_kem_shared_secret>,
) -> u8 {
use fips203::traits::{Decaps, SerDes};
let (Some(decaps), Some(ciphertext), Some(shared_secret_out)) =
(decaps, ciphertext, shared_secret_out)
else {
return ML_KEM_NULL_PTR_ERROR;
};
let Ok(dk) = fips203::ml_kem_1024::DecapsKey::try_from_bytes(decaps.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok(ct) = fips203::ml_kem_1024::CipherText::try_from_bytes(ciphertext.data) else {
return ML_KEM_DESERIALIZATION_ERROR;
};
let Ok(ssk) = dk.try_decaps(&ct) else {
return ML_KEM_DECAPSULATION_ERROR;
};
shared_secret_out.data = ssk.into_bytes();
ML_KEM_OK
}