diff --git a/Cargo.toml b/Cargo.toml index 20a135918..a9fbcfd09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,7 @@ hax-lib = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/", br libjade-sys = { version = "=0.0.2-pre.2", path = "sys/libjade" } [dev-dependencies] -libcrux = { path = ".", features = ["rand"] } +libcrux = { path = ".", features = ["rand", "tests"] } pretty_env_logger = "0.5" rand = { version = "0.8" } rand_core = { version = "0.6" } @@ -73,3 +73,4 @@ hacspec = [] # TODO: #7 Use specs instead of efficient implementation rand = [] wasm = ["wasm-bindgen"] log = ["dep:log"] +tests = [] # Expose functions for testing. diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index bd745ddf3..31ea8ebae 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -7,11 +7,12 @@ homepage.workspace = true edition.workspace = true repository.workspace = true readme.workspace = true +publish = false [dependencies] [dev-dependencies] -libcrux = { path = "../", features = ["rand"] } +libcrux = { path = "../", features = ["rand", "tests"] } rand = { version = "0.8" } rand_core = { version = "0.6" } # Benchmarking "RustCrypto" diff --git a/benchmarks/benches/boringssl/.gitignore b/benchmarks/benches/boringssl/.gitignore new file mode 100644 index 000000000..567609b12 --- /dev/null +++ b/benchmarks/benches/boringssl/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/benchmarks/benches/kyber768.rs b/benchmarks/benches/kyber768.rs index aafef1201..d49c57fde 100644 --- a/benchmarks/benches/kyber768.rs +++ b/benchmarks/benches/kyber768.rs @@ -18,21 +18,21 @@ pub fn comparisons_key_generation(c: &mut Criterion) { let mut seed = [0; 64]; rng.fill_bytes(&mut seed); b.iter(|| { - let _kp = libcrux::kem::kyber768_generate_keypair_derand(seed); + let _kp = libcrux::kem::deterministic::kyber768_generate_keypair_derand(seed); }) }); group.bench_function("libcrux portable (HACL-DRBG)", |b| { b.iter(|| { let (_secret_key, _public_key) = - libcrux::kem::key_gen(Algorithm::Kyber768, &mut drbg).unwrap(); + libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); }) }); group.bench_function("libcrux portable (OsRng)", |b| { b.iter(|| { let (_secret_key, _public_key) = - libcrux::kem::key_gen(Algorithm::Kyber768, &mut rng).unwrap(); + libcrux::kem::key_gen(Algorithm::MlKem768, &mut rng).unwrap(); }) }); @@ -53,10 +53,13 @@ pub fn comparisons_encapsulation(c: &mut Criterion) { let mut seed2 = [0; 32]; OsRng.fill_bytes(&mut seed2); b.iter_batched( - || libcrux::kem::kyber768_generate_keypair_derand(seed1), + || libcrux::kem::deterministic::kyber768_generate_keypair_derand(seed1), |keypair| { let (_shared_secret, _ciphertext) = - libcrux::kem::kyber768_encapsulate_derand(&keypair.public_key(), seed2); + libcrux::kem::deterministic::kyber768_encapsulate_derand( + &keypair.public_key(), + seed2, + ); }, BatchSize::SmallInput, ) @@ -67,13 +70,12 @@ pub fn comparisons_encapsulation(c: &mut Criterion) { || { let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); let (_secret_key, public_key) = - libcrux::kem::key_gen(Algorithm::Kyber768, &mut drbg).unwrap(); + libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); (drbg, public_key) }, |(mut rng, public_key)| { - let (_shared_secret, _ciphertext) = - libcrux::kem::encapsulate(&public_key, &mut rng).unwrap(); + let (_shared_secret, _ciphertext) = public_key.encapsulate(&mut rng).unwrap(); }, BatchSize::SmallInput, ) @@ -84,13 +86,12 @@ pub fn comparisons_encapsulation(c: &mut Criterion) { || { let mut drbg = OsRng; let (_secret_key, public_key) = - libcrux::kem::key_gen(Algorithm::Kyber768, &mut drbg).unwrap(); + libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); (drbg, public_key) }, |(mut rng, public_key)| { - let (_shared_secret, _ciphertext) = - libcrux::kem::encapsulate(&public_key, &mut rng).unwrap(); + let (_shared_secret, _ciphertext) = public_key.encapsulate(&mut rng).unwrap(); }, BatchSize::SmallInput, ) @@ -121,13 +122,12 @@ pub fn comparisons_decapsulation(c: &mut Criterion) { || { let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); let (secret_key, public_key) = - libcrux::kem::key_gen(Algorithm::Kyber768, &mut drbg).unwrap(); - let (_shared_secret, ciphertext) = - libcrux::kem::encapsulate(&public_key, &mut drbg).unwrap(); + libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); + let (_shared_secret, ciphertext) = public_key.encapsulate(&mut drbg).unwrap(); (secret_key, ciphertext) }, |(secret_key, ciphertext)| { - let _shared_secret = libcrux::kem::decapsulate(&ciphertext, &secret_key); + let _shared_secret = ciphertext.decapsulate(&secret_key); }, BatchSize::SmallInput, ) diff --git a/examples/kyber768_encapsulate.rs b/examples/kyber768_encapsulate.rs index 74ec77643..e57f33cbe 100644 --- a/examples/kyber768_encapsulate.rs +++ b/examples/kyber768_encapsulate.rs @@ -11,9 +11,9 @@ fn main() { #[cfg(target_arch = "wasm32")] let mut rng = OsRng; - let (_secret_key, public_key) = kem::key_gen(kem::Algorithm::Kyber768, &mut rng).unwrap(); + let (_secret_key, public_key) = kem::key_gen(kem::Algorithm::MlKem768, &mut rng).unwrap(); for _i in 0..100000 { - let (_shared_secret, _ciphertext) = kem::encapsulate(&public_key, &mut rng).unwrap(); + let (_shared_secret, _ciphertext) = public_key.encapsulate(&mut rng).unwrap(); } } diff --git a/examples/kyber768_generate_keypair.rs b/examples/kyber768_generate_keypair.rs index 2c723d809..d2f0e4a29 100644 --- a/examples/kyber768_generate_keypair.rs +++ b/examples/kyber768_generate_keypair.rs @@ -12,6 +12,6 @@ fn main() { let mut rng = OsRng; for _i in 0..100000 { - let (_secret_key, _public_key) = kem::key_gen(kem::Algorithm::Kyber768, &mut rng).unwrap(); + let (_secret_key, _public_key) = kem::key_gen(kem::Algorithm::MlKem768, &mut rng).unwrap(); } } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 3533bacd9..43e434d2e 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -14,6 +14,7 @@ rand = { version = "0.8" } [dependencies.libcrux] path = "../" +features = ["tests"] [[bin]] name = "kyber768_implicit_rejection" @@ -38,3 +39,9 @@ test = false doc = false harness = false bench = false + +[[bin]] +name = "mlkem_pk_validation" +path = "fuzz_targets/mlkem_pk_validation.rs" +test = false +doc = false diff --git a/fuzz/fuzz_targets/fuzz_rng.rs b/fuzz/fuzz_targets/fuzz_rng.rs new file mode 100644 index 000000000..2d40ada0f --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_rng.rs @@ -0,0 +1,44 @@ +use libcrux::digest::shake128; +use rand::CryptoRng; + +use rand; + +use rand::RngCore; + +pub(crate) struct FuzzRng { + pub(crate) data: Vec, +} + +impl FuzzRng { + /// Create a new rng for fuzzing with 1024 bytes, using shake128. + pub(crate) fn new(e: &[u8]) -> Self { + let data: [u8; 1024] = shake128(e); + Self { + data: data.to_vec(), + } + } +} + +impl RngCore for FuzzRng { + fn next_u32(&mut self) -> u32 { + let mut bytes: [u8; 4] = [0; 4]; + self.fill_bytes(&mut bytes); + u32::from_be_bytes(bytes) + } + + fn next_u64(&mut self) -> u64 { + todo!() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + dest.copy_from_slice(&self.data[0..dest.len()]); + self.data = self.data.drain(dest.len()..).collect(); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +impl CryptoRng for FuzzRng {} diff --git a/fuzz/fuzz_targets/implicit_rejection_util.rs b/fuzz/fuzz_targets/implicit_rejection_util.rs new file mode 100644 index 000000000..3acd1a5b4 --- /dev/null +++ b/fuzz/fuzz_targets/implicit_rejection_util.rs @@ -0,0 +1,73 @@ +use libcrux::digest::shake256; + +use libcrux::kem::PrivateKey; + +use libcrux::kem::Ct; + +use rand::Rng; + +use rand::CryptoRng; + +use libcrux::kem::Algorithm; + +pub(crate) fn modify_ciphertext( + alg: Algorithm, + rng: &mut (impl CryptoRng + Rng), + ciphertext: Ct, +) -> Ct { + let mut raw_ciphertext = ciphertext.encode(); + + let mut random_u32: usize = rng.next_u32().try_into().unwrap(); + + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; + } + random_u32 >>= 8; + + let position = random_u32 % raw_ciphertext.len(); + raw_ciphertext[position] ^= random_byte; + + Ct::decode(alg, &raw_ciphertext).unwrap() +} + +pub(crate) const SHARED_SECRET_SIZE: usize = 32; + +pub(crate) fn modify_secret_key( + alg: Algorithm, + rng: &mut (impl CryptoRng + Rng), + secret_key: PrivateKey, + modify_implicit_rejection_value: bool, +) -> PrivateKey { + let mut raw_secret_key = secret_key.encode(); + + let mut random_u32: usize = rng.next_u32().try_into().unwrap(); + + let mut random_byte: u8 = (random_u32 & 0xFF) as u8; + if random_byte == 0 { + random_byte += 1; + } + random_u32 >>= 8; + + let position = if modify_implicit_rejection_value { + (raw_secret_key.len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) + } else { + random_u32 % (raw_secret_key.len() - SHARED_SECRET_SIZE) + }; + + raw_secret_key[position] ^= random_byte; + + PrivateKey::decode(alg, &raw_secret_key).unwrap() +} + +pub(crate) fn compute_implicit_rejection_shared_secret( + ciphertext: Ct, + secret_key: PrivateKey, +) -> [u8; SHARED_SECRET_SIZE] { + let raw_secret_key = secret_key.encode(); + + let mut to_hash = raw_secret_key[raw_secret_key.len() - SHARED_SECRET_SIZE..].to_vec(); + to_hash.extend_from_slice(&ciphertext.encode()); + + shake256(&to_hash) +} diff --git a/fuzz/fuzz_targets/kyber1024_implicit_rejection.rs b/fuzz/fuzz_targets/kyber1024_implicit_rejection.rs index 8cacb5cd4..67469c62e 100644 --- a/fuzz/fuzz_targets/kyber1024_implicit_rejection.rs +++ b/fuzz/fuzz_targets/kyber1024_implicit_rejection.rs @@ -1,115 +1,24 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use libcrux::{ - digest::shake256, - kem::{self, Algorithm, Ct, PrivateKey}, -}; -use rand::{CryptoRng, Rng, RngCore}; +use libcrux::kem::{self, Algorithm}; -struct FuzzRng { - data: Vec, -} +mod fuzz_rng; +use fuzz_rng::FuzzRng; -impl RngCore for FuzzRng { - fn next_u32(&mut self) -> u32 { - let mut bytes: [u8; 4] = [0; 4]; - self.fill_bytes(&mut bytes); - u32::from_be_bytes(bytes) - } - - fn next_u64(&mut self) -> u64 { - todo!() - } - - fn fill_bytes(&mut self, dest: &mut [u8]) { - dest.copy_from_slice(&self.data[0..dest.len()]); - self.data = self.data.drain(dest.len()..).collect(); - } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { - self.fill_bytes(dest); - Ok(()) - } -} - -impl CryptoRng for FuzzRng {} - -fn modify_ciphertext(alg: Algorithm, rng: &mut (impl CryptoRng + Rng), ciphertext: Ct) -> Ct { - let mut raw_ciphertext = ciphertext.encode(); - - let mut random_u32: usize = rng.next_u32().try_into().unwrap(); - - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; - } - random_u32 >>= 8; - - let position = random_u32 % raw_ciphertext.len(); - raw_ciphertext[position] ^= random_byte; - - Ct::decode(alg, &raw_ciphertext).unwrap() -} - -const SHARED_SECRET_SIZE: usize = 32; - -fn modify_secret_key( - alg: Algorithm, - rng: &mut (impl CryptoRng + Rng), - secret_key: PrivateKey, - modify_implicit_rejection_value: bool, -) -> PrivateKey { - let mut raw_secret_key = secret_key.encode(); - - let mut random_u32: usize = rng.next_u32().try_into().unwrap(); - - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; - } - random_u32 >>= 8; - - let position = if modify_implicit_rejection_value { - (raw_secret_key.len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) - } else { - random_u32 % (raw_secret_key.len() - SHARED_SECRET_SIZE) - }; - - raw_secret_key[position] ^= random_byte; - - PrivateKey::decode(alg, &raw_secret_key).unwrap() -} - -fn compute_implicit_rejection_shared_secret( - ciphertext: Ct, - secret_key: PrivateKey, -) -> [u8; SHARED_SECRET_SIZE] { - let raw_secret_key = secret_key.encode(); - - let mut to_hash = raw_secret_key[raw_secret_key.len() - SHARED_SECRET_SIZE..].to_vec(); - to_hash.extend_from_slice(&ciphertext.encode()); - - shake256(&to_hash) -} +mod implicit_rejection_util; +use implicit_rejection_util::*; fuzz_target!(|data: &[u8]| { - if data.len() < 256 { - // This is not enough randomness for the test. - return; - } - - let mut rng = FuzzRng { - data: data.to_vec(), - }; + let mut rng = FuzzRng::new(data); - if let Ok((secret_key, public_key)) = kem::key_gen(Algorithm::Kyber1024, &mut rng) { - if let Ok((_, ciphertext)) = kem::encapsulate(&public_key, &mut rng) { - let ciphertext = modify_ciphertext(Algorithm::Kyber1024, &mut rng, ciphertext); - let shared_secret_decapsulated = kem::decapsulate(&ciphertext, &secret_key).unwrap(); + if let Ok((secret_key, public_key)) = kem::key_gen(Algorithm::MlKem1024, &mut rng) { + if let Ok((_, ciphertext)) = public_key.encapsulate(&mut rng) { + let ciphertext = modify_ciphertext(Algorithm::MlKem1024, &mut rng, ciphertext); + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); - let secret_key = modify_secret_key(Algorithm::Kyber1024, &mut rng, secret_key, true); - let shared_secret_decapsulated_1 = kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let secret_key = modify_secret_key(Algorithm::MlKem1024, &mut rng, secret_key, true); + let shared_secret_decapsulated_1 = ciphertext.decapsulate(&secret_key).unwrap(); assert_ne!( shared_secret_decapsulated.encode(), @@ -120,6 +29,10 @@ fuzz_target!(|data: &[u8]| { shared_secret_decapsulated_1.encode(), compute_implicit_rejection_shared_secret(ciphertext, secret_key) ); + } else { + unreachable!("Error encapsulating") } + } else { + unreachable!("Error in key generation") } }); diff --git a/fuzz/fuzz_targets/kyber768_implicit_rejection.rs b/fuzz/fuzz_targets/kyber768_implicit_rejection.rs index 358a99514..631b709f1 100644 --- a/fuzz/fuzz_targets/kyber768_implicit_rejection.rs +++ b/fuzz/fuzz_targets/kyber768_implicit_rejection.rs @@ -1,115 +1,24 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use libcrux::{ - digest::shake256, - kem::{self, Algorithm, Ct, PrivateKey}, -}; -use rand::{CryptoRng, Rng, RngCore}; +use libcrux::kem::{self, Algorithm}; -struct FuzzRng { - data: Vec, -} +mod fuzz_rng; +use fuzz_rng::FuzzRng; -impl RngCore for FuzzRng { - fn next_u32(&mut self) -> u32 { - let mut bytes: [u8; 4] = [0; 4]; - self.fill_bytes(&mut bytes); - u32::from_be_bytes(bytes) - } - - fn next_u64(&mut self) -> u64 { - todo!() - } - - fn fill_bytes(&mut self, dest: &mut [u8]) { - dest.copy_from_slice(&self.data[0..dest.len()]); - self.data = self.data.drain(dest.len()..).collect(); - } - - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { - self.fill_bytes(dest); - Ok(()) - } -} - -impl CryptoRng for FuzzRng {} - -fn modify_ciphertext(alg: Algorithm, rng: &mut (impl CryptoRng + Rng), ciphertext: Ct) -> Ct { - let mut raw_ciphertext = ciphertext.encode(); - - let mut random_u32: usize = rng.next_u32().try_into().unwrap(); - - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; - } - random_u32 >>= 8; - - let position = random_u32 % raw_ciphertext.len(); - raw_ciphertext[position] ^= random_byte; - - Ct::decode(alg, &raw_ciphertext).unwrap() -} - -const SHARED_SECRET_SIZE: usize = 32; - -fn modify_secret_key( - alg: Algorithm, - rng: &mut (impl CryptoRng + Rng), - secret_key: PrivateKey, - modify_implicit_rejection_value: bool, -) -> PrivateKey { - let mut raw_secret_key = secret_key.encode(); - - let mut random_u32: usize = rng.next_u32().try_into().unwrap(); - - let mut random_byte: u8 = (random_u32 & 0xFF) as u8; - if random_byte == 0 { - random_byte += 1; - } - random_u32 >>= 8; - - let position = if modify_implicit_rejection_value { - (raw_secret_key.len() - SHARED_SECRET_SIZE) + (random_u32 % SHARED_SECRET_SIZE) - } else { - random_u32 % (raw_secret_key.len() - SHARED_SECRET_SIZE) - }; - - raw_secret_key[position] ^= random_byte; - - PrivateKey::decode(alg, &raw_secret_key).unwrap() -} - -fn compute_implicit_rejection_shared_secret( - ciphertext: Ct, - secret_key: PrivateKey, -) -> [u8; SHARED_SECRET_SIZE] { - let raw_secret_key = secret_key.encode(); - - let mut to_hash = raw_secret_key[raw_secret_key.len() - SHARED_SECRET_SIZE..].to_vec(); - to_hash.extend_from_slice(&ciphertext.encode()); - - shake256(&to_hash) -} +mod implicit_rejection_util; +use implicit_rejection_util::*; fuzz_target!(|data: &[u8]| { - if data.len() < 256 { - // This is not enough randomness for the test. - return; - } - - let mut rng = FuzzRng { - data: data.to_vec(), - }; + let mut rng = FuzzRng::new(data); - if let Ok((secret_key, public_key)) = kem::key_gen(Algorithm::Kyber768, &mut rng) { - if let Ok((_, ciphertext)) = kem::encapsulate(&public_key, &mut rng) { - let ciphertext = modify_ciphertext(Algorithm::Kyber768, &mut rng, ciphertext); - let shared_secret_decapsulated = kem::decapsulate(&ciphertext, &secret_key).unwrap(); + if let Ok((secret_key, public_key)) = kem::key_gen(Algorithm::MlKem768, &mut rng) { + if let Ok((_, ciphertext)) = public_key.encapsulate(&mut rng) { + let ciphertext = modify_ciphertext(Algorithm::MlKem768, &mut rng, ciphertext); + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); - let secret_key = modify_secret_key(Algorithm::Kyber768, &mut rng, secret_key, true); - let shared_secret_decapsulated_1 = kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let secret_key = modify_secret_key(Algorithm::MlKem768, &mut rng, secret_key, true); + let shared_secret_decapsulated_1 = ciphertext.decapsulate(&secret_key).unwrap(); assert_ne!( shared_secret_decapsulated.encode(), @@ -120,6 +29,10 @@ fuzz_target!(|data: &[u8]| { shared_secret_decapsulated_1.encode(), compute_implicit_rejection_shared_secret(ciphertext, secret_key) ); + } else { + unreachable!("Error encapsulating") } + } else { + unreachable!("Error in key generation") } }); diff --git a/fuzz/fuzz_targets/mlkem_pk_validation.rs b/fuzz/fuzz_targets/mlkem_pk_validation.rs new file mode 100644 index 000000000..71aa2c8d7 --- /dev/null +++ b/fuzz/fuzz_targets/mlkem_pk_validation.rs @@ -0,0 +1,18 @@ +#![no_main] + +use libcrux::kem::{self, Algorithm, PublicKey}; +use libfuzzer_sys::fuzz_target; + +mod fuzz_rng; +use fuzz_rng::FuzzRng; + +fuzz_target!(|data: &[u8]| { + let mut rng = FuzzRng::new(data); + + if let Ok((_, public_key)) = kem::key_gen(Algorithm::MlKem768, &mut rng) { + let encoded = public_key.encode(); + let _ = PublicKey::decode(Algorithm::MlKem768, &encoded).unwrap(); + } else { + eprintln!("Error in key generation {:x?}", data); + } +}); diff --git a/hax-driver.py b/hax-driver.py index 395fb630a..7ea434ed0 100755 --- a/hax-driver.py +++ b/hax-driver.py @@ -115,20 +115,27 @@ def shell(command, expect=0, cwd=None, env={}): if options.verify_extraction: shell(["make", "-C", "proofs/fstar/extraction/"]) elif options.kyber_reference: + # Delete all extracted F* files + shell(["rm", "-f", "./proofs/fstar/extraction/Libcrux*"]) + # Extract both `libcrux` and `libcrux-platform` shell( - cargo_hax_into - + [ + [ + "cargo", "hax", + "-C", "-p", "libcrux", "-p", "libcrux-platform", ";", + "into", "-i", - "-** +libcrux::kem::kyber::** {} -libcrux::digest::** -libcrux::**::types::index_impls::**".format( - exclude_sha3_implementations - ), + f"-** +libcrux::kem::kyber::** +libcrux_platform::** {exclude_sha3_implementations} -libcrux::**::types::index_impls::**", "fstar", "--interfaces", - "+* -libcrux::kem::kyber::types", + "+* -libcrux::kem::kyber::types +!libcrux_platform::**", ], cwd=".", env=hax_env, ) + # Delete F* implementation modules for `libcrux_platform` (TODO: + # remove this when https://github.com/hacspec/hax/issues/465 is + # closed) + shell(["rm", "-f", "./sys/platform/proofs/fstar/extraction/*.fst"]) elif options.kyber_specification: shell( cargo_hax_into diff --git a/proofs/fstar/extraction/Libcrux.Digest.fsti b/proofs/fstar/extraction/Libcrux.Digest.fsti index fa09425b3..59887e419 100644 --- a/proofs/fstar/extraction/Libcrux.Digest.fsti +++ b/proofs/fstar/extraction/Libcrux.Digest.fsti @@ -1,41 +1,31 @@ module Libcrux.Digest #set-options "--fuel 0 --ifuel 1 --z3rlimit 15" -open Rust_primitives open Core +open FStar.Mul -type t_Algorithm = - | Algorithm_Sha1 : t_Algorithm - | Algorithm_Sha224 : t_Algorithm - | Algorithm_Sha256 : t_Algorithm - | Algorithm_Sha384 : t_Algorithm - | Algorithm_Sha512 : t_Algorithm - | Algorithm_Blake2s : t_Algorithm - | Algorithm_Blake2b : t_Algorithm - | Algorithm_Sha3_224_ : t_Algorithm - | Algorithm_Sha3_256_ : t_Algorithm - | Algorithm_Sha3_384_ : t_Algorithm - | Algorithm_Sha3_512_ : t_Algorithm +val sha3_256_ (payload: t_Slice u8) + : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -let digest_size (mode: t_Algorithm) : usize = - match mode with - | Algorithm_Sha1 -> sz 20 - | Algorithm_Sha224 -> sz 28 - | Algorithm_Sha256 -> sz 32 - | Algorithm_Sha384 -> sz 48 - | Algorithm_Sha512 -> sz 64 - | Algorithm_Blake2s -> sz 32 - | Algorithm_Blake2b -> sz 64 - | Algorithm_Sha3_224_ -> sz 28 - | Algorithm_Sha3_256_ -> sz 32 - | Algorithm_Sha3_384_ -> sz 48 - | Algorithm_Sha3_512_ -> sz 64 +val sha3_512_ (payload: t_Slice u8) + : Prims.Pure (t_Array u8 (sz 64)) Prims.l_True (fun _ -> Prims.l_True) -val sha3_256_ (payload: t_Slice u8) : t_Array u8 (sz 32) +val shake128 (v_LEN: usize) (data: t_Slice u8) + : Prims.Pure (t_Array u8 v_LEN) Prims.l_True (fun _ -> Prims.l_True) -val sha3_512_ (payload: t_Slice u8) : t_Array u8 (sz 64) +val shake256 (v_LEN: usize) (data: t_Slice u8) + : Prims.Pure (t_Array u8 v_LEN) Prims.l_True (fun _ -> Prims.l_True) -val shake128 (v_LEN: usize) (data: t_Slice u8) : t_Array u8 v_LEN +val shake128x4_portable (v_LEN: usize) (data0 data1 data2 data3: t_Slice u8) + : Prims.Pure (t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN) + Prims.l_True + (fun _ -> Prims.l_True) -val shake128x4 (v_LEN: usize) (data0: t_Slice u8) (data1: t_Slice u8) (data2: t_Slice u8) (data3: t_Slice u8): (t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN) +val shake128x4_256_ (v_LEN: usize) (data0 data1 data2 data3: t_Slice u8) + : Prims.Pure (t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN) + Prims.l_True + (fun _ -> Prims.l_True) -val shake256 (v_LEN: usize) (data: t_Slice u8) : t_Array u8 v_LEN +val shake128x4 (v_LEN: usize) (data0 data1 data2 data3: t_Slice u8) + : Prims.Pure (t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN & t_Array u8 v_LEN) + Prims.l_True + (fun _ -> Prims.l_True) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Conversions.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Conversions.fst deleted file mode 100644 index 1be616fef..000000000 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Conversions.fst +++ /dev/null @@ -1,87 +0,0 @@ -module Libcrux.Kem.Kyber.Conversions -#set-options "--fuel 0 --ifuel 1 --z3rlimit 15" -open Core - -let into_padded_array (#v_LEN: usize) (slice: t_Slice u8) : t_Array u8 v_LEN = - let _:Prims.unit = - if true - then - let _:Prims.unit = - if ~.((Core.Slice.impl__len slice <: usize) <=. v_LEN <: bool) - then - Rust_primitives.Hax.never_to_any (Core.Panicking.panic "assertion failed: slice.len() <= LEN" - - <: - Rust_primitives.Hax.t_Never) - in - () - in - let out:t_Array u8 v_LEN = Rust_primitives.Hax.repeat 0uy v_LEN in - let out:t_Array u8 v_LEN = - Rust_primitives.Hax.update_at out - ({ Core.Ops.Range.f_start = sz 0; Core.Ops.Range.f_end = Core.Slice.impl__len slice <: usize } - ) - (Core.Slice.impl__copy_from_slice (Core.Ops.Index.IndexMut.index_mut out - ({ - Core.Ops.Range.f_start = sz 0; - Core.Ops.Range.f_end = Core.Slice.impl__len slice <: usize - }) - <: - t_Slice u8) - slice - <: - t_Slice u8) - in - out - -class t_UpdatingArray (#v_Self: Type) = { f_push:v_Self -> t_Slice u8 -> v_Self } - -type t_UpdatableArray (v_LEN: usize) = { - f_value:t_Array u8 v_LEN; - f_pointer:usize -} - -let impl__new (#v_LEN: usize) (value: t_Array u8 v_LEN) : t_UpdatableArray v_LEN = - { f_value = value; f_pointer = sz 0 } - -let impl__array (#v_LEN: usize) (self: t_UpdatableArray v_LEN) : t_Array u8 v_LEN = self.f_value - -let impl_1 (#v_LEN: usize) : t_UpdatingArray (t_UpdatableArray v_LEN) = - { - f_push - = - fun (self: t_UpdatableArray v_LEN) (other: t_Slice u8) -> - let self:t_UpdatableArray v_LEN = - { - self with - f_value - = - Rust_primitives.Hax.update_at (f_value self <: t_UpdatableArray v_LEN) - ({ - Core.Ops.Range.f_start = self.f_pointer; - Core.Ops.Range.f_end - = - self.f_pointer +! (Core.Slice.impl__len other <: usize) <: usize - }) - (Core.Slice.impl__copy_from_slice (Core.Ops.Index.IndexMut.index_mut self.f_value - ({ - Core.Ops.Range.f_start = self.f_pointer; - Core.Ops.Range.f_end - = - self.f_pointer +! (Core.Slice.impl__len other <: usize) <: usize - }) - <: - t_Slice u8) - other - <: - t_Slice u8) - } - in - let self:t_UpdatableArray v_LEN = - { self with f_pointer = self.f_pointer +! (Core.Slice.impl__len other <: usize) } - in - self - } - -let to_unsigned_representative (fe: i32) : u16 = - cast (fe +! ((fe >>! 15l <: i32) &. Libcrux.Kem.Kyber.Constants.v_FIELD_MODULUS <: i32)) <: u16 \ No newline at end of file diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Helper.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Helper.fst deleted file mode 100644 index cb989f39e..000000000 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Helper.fst +++ /dev/null @@ -1,6 +0,0 @@ -module Libcrux.Kem.Kyber.Helper -#set-options "--fuel 0 --ifuel 1 --z3rlimit 15" -open Core -open FStar.Mul - - diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fst index ace2e4dba..87276fe9b 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fst +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fst @@ -3,21 +3,36 @@ module Libcrux.Kem.Kyber.Kyber1024 open Core open FStar.Mul -let decapsulate_1024_ - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 3168)) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1568)) +let decapsulate + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 3168)) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1568)) = Libcrux.Kem.Kyber.decapsulate (sz 4) (sz 3168) (sz 1536) (sz 1568) (sz 1568) (sz 1536) (sz 1408) (sz 160) (sz 11) (sz 5) (sz 352) (sz 2) (sz 128) (sz 2) (sz 128) (sz 1600) secret_key ciphertext -let encapsulate_1024_ - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 1568)) +let encapsulate + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568)) (randomness: t_Array u8 (sz 32)) = Libcrux.Kem.Kyber.encapsulate (sz 4) (sz 1568) (sz 1568) (sz 1536) (sz 1408) (sz 160) (sz 11) (sz 5) (sz 352) (sz 2) (sz 128) (sz 2) (sz 128) public_key randomness -let generate_key_pair_1024_ (randomness: t_Array u8 (sz 64)) = +let validate_public_key (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568)) = + if + Libcrux.Kem.Kyber.validate_public_key (sz 4) + (sz 1536) + (sz 1568) + public_key.Libcrux.Kem.Kyber.Types.f_value + then + Core.Option.Option_Some public_key + <: + Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568)) + else + Core.Option.Option_None + <: + Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568)) + +let generate_key_pair (randomness: t_Array u8 (sz 64)) = Libcrux.Kem.Kyber.generate_keypair (sz 4) (sz 1536) (sz 3168) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fsti b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fsti index 8ac9ea907..fafa6c85a 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fsti +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber1024.fsti @@ -63,27 +63,32 @@ let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = Libcrux.Kem.Kyber.Constants.v_SHARED_SECRET_SIZE +! v_CPA_PKE_CIPHERTEXT_SIZE_1024_ unfold -let t_Kyber1024Ciphertext = Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1568) +let t_MlKem1024Ciphertext = Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1568) unfold -let t_Kyber1024PrivateKey = Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 3168) +let t_MlKem1024PrivateKey = Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 3168) unfold -let t_Kyber1024PublicKey = Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 1568) +let t_MlKem1024PublicKey = Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568) -val decapsulate_1024_ - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 3168)) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1568)) +val decapsulate + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 3168)) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1568)) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -val encapsulate_1024_ - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 1568)) +val encapsulate + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568)) (randomness: t_Array u8 (sz 32)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1568) & t_Array u8 (sz 32)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1568) & t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -val generate_key_pair_1024_ (randomness: t_Array u8 (sz 64)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberKeyPair (sz 3168) (sz 1568)) +val validate_public_key (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568)) + : Prims.Pure (Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1568))) + Prims.l_True + (fun _ -> Prims.l_True) + +val generate_key_pair (randomness: t_Array u8 (sz 64)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemKeyPair (sz 3168) (sz 1568)) Prims.l_True (fun _ -> Prims.l_True) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fst index ca5e6845b..f86ddb2c0 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fst +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fst @@ -3,21 +3,36 @@ module Libcrux.Kem.Kyber.Kyber512 open Core open FStar.Mul -let decapsulate_512_ - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 1632)) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 768)) +let decapsulate + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 1632)) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 768)) = Libcrux.Kem.Kyber.decapsulate (sz 2) (sz 1632) (sz 768) (sz 800) (sz 768) (sz 768) (sz 640) (sz 128) (sz 10) (sz 4) (sz 320) (sz 3) (sz 192) (sz 2) (sz 128) (sz 800) secret_key ciphertext -let encapsulate_512_ - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 800)) +let encapsulate + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800)) (randomness: t_Array u8 (sz 32)) = Libcrux.Kem.Kyber.encapsulate (sz 2) (sz 768) (sz 800) (sz 768) (sz 640) (sz 128) (sz 10) (sz 4) (sz 320) (sz 3) (sz 192) (sz 2) (sz 128) public_key randomness -let generate_key_pair_512_ (randomness: t_Array u8 (sz 64)) = +let validate_public_key (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800)) = + if + Libcrux.Kem.Kyber.validate_public_key (sz 2) + (sz 768) + (sz 800) + public_key.Libcrux.Kem.Kyber.Types.f_value + then + Core.Option.Option_Some public_key + <: + Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800)) + else + Core.Option.Option_None + <: + Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800)) + +let generate_key_pair (randomness: t_Array u8 (sz 64)) = Libcrux.Kem.Kyber.generate_keypair (sz 2) (sz 768) (sz 1632) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fsti b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fsti index acbfb1379..33108ba19 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fsti +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber512.fsti @@ -63,27 +63,32 @@ let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = Libcrux.Kem.Kyber.Constants.v_SHARED_SECRET_SIZE +! v_CPA_PKE_CIPHERTEXT_SIZE_512_ unfold -let t_Kyber512Ciphertext = Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 768) +let t_MlKem512Ciphertext = Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 768) unfold -let t_Kyber512PrivateKey = Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 1632) +let t_MlKem512PrivateKey = Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 1632) unfold -let t_Kyber512PublicKey = Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 800) +let t_MlKem512PublicKey = Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800) -val decapsulate_512_ - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 1632)) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 768)) +val decapsulate + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 1632)) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 768)) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -val encapsulate_512_ - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 800)) +val encapsulate + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800)) (randomness: t_Array u8 (sz 32)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 768) & t_Array u8 (sz 32)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 768) & t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -val generate_key_pair_512_ (randomness: t_Array u8 (sz 64)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberKeyPair (sz 1632) (sz 800)) +val validate_public_key (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800)) + : Prims.Pure (Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 800))) + Prims.l_True + (fun _ -> Prims.l_True) + +val generate_key_pair (randomness: t_Array u8 (sz 64)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemKeyPair (sz 1632) (sz 800)) Prims.l_True (fun _ -> Prims.l_True) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fst index 656952b25..7b7edf6d7 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fst +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fst @@ -3,21 +3,36 @@ module Libcrux.Kem.Kyber.Kyber768 open Core open FStar.Mul -let decapsulate_768_ - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 2400)) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1088)) +let decapsulate + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 2400)) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1088)) = Libcrux.Kem.Kyber.decapsulate (sz 3) (sz 2400) (sz 1152) (sz 1184) (sz 1088) (sz 1152) (sz 960) (sz 128) (sz 10) (sz 4) (sz 320) (sz 2) (sz 128) (sz 2) (sz 128) (sz 1120) secret_key ciphertext -let encapsulate_768_ - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 1184)) +let encapsulate + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184)) (randomness: t_Array u8 (sz 32)) = Libcrux.Kem.Kyber.encapsulate (sz 3) (sz 1088) (sz 1184) (sz 1152) (sz 960) (sz 128) (sz 10) (sz 4) (sz 320) (sz 2) (sz 128) (sz 2) (sz 128) public_key randomness -let generate_key_pair_768_ (randomness: t_Array u8 (sz 64)) = +let validate_public_key (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184)) = + if + Libcrux.Kem.Kyber.validate_public_key (sz 3) + (sz 1152) + (sz 1184) + public_key.Libcrux.Kem.Kyber.Types.f_value + then + Core.Option.Option_Some public_key + <: + Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184)) + else + Core.Option.Option_None + <: + Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184)) + +let generate_key_pair (randomness: t_Array u8 (sz 64)) = Libcrux.Kem.Kyber.generate_keypair (sz 3) (sz 1152) (sz 2400) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fsti b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fsti index b5bbadddc..5f68851e0 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fsti +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Kyber768.fsti @@ -63,27 +63,32 @@ let v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = Libcrux.Kem.Kyber.Constants.v_SHARED_SECRET_SIZE +! v_CPA_PKE_CIPHERTEXT_SIZE_768_ unfold -let t_Kyber768Ciphertext = Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1088) +let t_MlKem768Ciphertext = Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1088) unfold -let t_Kyber768PrivateKey = Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 2400) +let t_MlKem768PrivateKey = Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 2400) unfold -let t_Kyber768PublicKey = Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 1184) +let t_MlKem768PublicKey = Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184) -val decapsulate_768_ - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey (sz 2400)) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1088)) +val decapsulate + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey (sz 2400)) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1088)) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -val encapsulate_768_ - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey (sz 1184)) +val encapsulate + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184)) (randomness: t_Array u8 (sz 32)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberCiphertext (sz 1088) & t_Array u8 (sz 32)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemCiphertext (sz 1088) & t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) -val generate_key_pair_768_ (randomness: t_Array u8 (sz 64)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberKeyPair (sz 2400) (sz 1184)) +val validate_public_key (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184)) + : Prims.Pure (Core.Option.t_Option (Libcrux.Kem.Kyber.Types.t_MlKemPublicKey (sz 1184))) + Prims.l_True + (fun _ -> Prims.l_True) + +val generate_key_pair (randomness: t_Array u8 (sz 64)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemKeyPair (sz 2400) (sz 1184)) Prims.l_True (fun _ -> Prims.l_True) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Types.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Types.fst index 7a8f911ff..6a7f5b43f 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.Types.fst +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.Types.fst @@ -3,31 +3,31 @@ module Libcrux.Kem.Kyber.Types open Core open FStar.Mul -type t_KyberCiphertext (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } +type t_MlKemCiphertext (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_1 (v_SIZE: usize) : Core.Convert.t_AsRef (t_KyberCiphertext v_SIZE) (t_Slice u8) = - { f_as_ref = fun (self: t_KyberCiphertext v_SIZE) -> Rust_primitives.unsize self.f_value } +let impl_1 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemCiphertext v_SIZE) (t_Slice u8) = + { f_as_ref = fun (self: t_MlKemCiphertext v_SIZE) -> Rust_primitives.unsize self.f_value } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_2 (v_SIZE: usize) : Core.Convert.t_From (t_KyberCiphertext v_SIZE) (t_Array u8 v_SIZE) = - { f_from = fun (value: t_Array u8 v_SIZE) -> { f_value = value } <: t_KyberCiphertext v_SIZE } +let impl_2 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemCiphertext v_SIZE) (t_Array u8 v_SIZE) = + { f_from = fun (value: t_Array u8 v_SIZE) -> { f_value = value } <: t_MlKemCiphertext v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_3 (v_SIZE: usize) : Core.Convert.t_From (t_KyberCiphertext v_SIZE) (t_Array u8 v_SIZE) = +let impl_3 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemCiphertext v_SIZE) (t_Array u8 v_SIZE) = { f_from = fun (value: t_Array u8 v_SIZE) -> - { f_value = Core.Clone.f_clone value } <: t_KyberCiphertext v_SIZE + { f_value = Core.Clone.f_clone value } <: t_MlKemCiphertext v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_4 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_KyberCiphertext v_SIZE) = - { f_from = fun (value: t_KyberCiphertext v_SIZE) -> value.f_value } +let impl_4 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_MlKemCiphertext v_SIZE) = + { f_from = fun (value: t_MlKemCiphertext v_SIZE) -> value.f_value } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_5 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_KyberCiphertext v_SIZE) (t_Slice u8) = +let impl_5 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemCiphertext v_SIZE) (t_Slice u8) = { f_Error = Core.Array.t_TryFromSliceError; f_try_from @@ -35,49 +35,49 @@ let impl_5 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_KyberCiphertext v_SIZE) ( fun (value: t_Slice u8) -> match Core.Convert.f_try_into value with | Core.Result.Result_Ok value -> - Core.Result.Result_Ok ({ f_value = value } <: t_KyberCiphertext v_SIZE) + Core.Result.Result_Ok ({ f_value = value } <: t_MlKemCiphertext v_SIZE) <: - Core.Result.t_Result (t_KyberCiphertext v_SIZE) Core.Array.t_TryFromSliceError + Core.Result.t_Result (t_MlKemCiphertext v_SIZE) Core.Array.t_TryFromSliceError | Core.Result.Result_Err e -> Core.Result.Result_Err e <: - Core.Result.t_Result (t_KyberCiphertext v_SIZE) Core.Array.t_TryFromSliceError + Core.Result.t_Result (t_MlKemCiphertext v_SIZE) Core.Array.t_TryFromSliceError } -let impl_6__as_slice (v_SIZE: usize) (self: t_KyberCiphertext v_SIZE) : t_Array u8 v_SIZE = +let impl_6__as_slice (v_SIZE: usize) (self: t_MlKemCiphertext v_SIZE) : t_Array u8 v_SIZE = self.f_value -let impl_6__len (v_SIZE: usize) (self: t_KyberCiphertext v_SIZE) : usize = v_SIZE +let impl_6__len (v_SIZE: usize) (self: t_MlKemCiphertext v_SIZE) : usize = v_SIZE -let impl_6__split_at (v_SIZE: usize) (self: t_KyberCiphertext v_SIZE) (mid: usize) +let impl_6__split_at (v_SIZE: usize) (self: t_MlKemCiphertext v_SIZE) (mid: usize) : (t_Slice u8 & t_Slice u8) = Core.Slice.impl__split_at (Rust_primitives.unsize self.f_value <: t_Slice u8) mid -type t_KyberPrivateKey (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } +type t_MlKemPrivateKey (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_7 (v_SIZE: usize) : Core.Convert.t_AsRef (t_KyberPrivateKey v_SIZE) (t_Slice u8) = - { f_as_ref = fun (self: t_KyberPrivateKey v_SIZE) -> Rust_primitives.unsize self.f_value } +let impl_7 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemPrivateKey v_SIZE) (t_Slice u8) = + { f_as_ref = fun (self: t_MlKemPrivateKey v_SIZE) -> Rust_primitives.unsize self.f_value } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_8 (v_SIZE: usize) : Core.Convert.t_From (t_KyberPrivateKey v_SIZE) (t_Array u8 v_SIZE) = - { f_from = fun (value: t_Array u8 v_SIZE) -> { f_value = value } <: t_KyberPrivateKey v_SIZE } +let impl_8 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPrivateKey v_SIZE) (t_Array u8 v_SIZE) = + { f_from = fun (value: t_Array u8 v_SIZE) -> { f_value = value } <: t_MlKemPrivateKey v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_9 (v_SIZE: usize) : Core.Convert.t_From (t_KyberPrivateKey v_SIZE) (t_Array u8 v_SIZE) = +let impl_9 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPrivateKey v_SIZE) (t_Array u8 v_SIZE) = { f_from = fun (value: t_Array u8 v_SIZE) -> - { f_value = Core.Clone.f_clone value } <: t_KyberPrivateKey v_SIZE + { f_value = Core.Clone.f_clone value } <: t_MlKemPrivateKey v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_10 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_KyberPrivateKey v_SIZE) = - { f_from = fun (value: t_KyberPrivateKey v_SIZE) -> value.f_value } +let impl_10 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_MlKemPrivateKey v_SIZE) = + { f_from = fun (value: t_MlKemPrivateKey v_SIZE) -> value.f_value } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_11 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_KyberPrivateKey v_SIZE) (t_Slice u8) = +let impl_11 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemPrivateKey v_SIZE) (t_Slice u8) = { f_Error = Core.Array.t_TryFromSliceError; f_try_from @@ -85,49 +85,49 @@ let impl_11 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_KyberPrivateKey v_SIZE) fun (value: t_Slice u8) -> match Core.Convert.f_try_into value with | Core.Result.Result_Ok value -> - Core.Result.Result_Ok ({ f_value = value } <: t_KyberPrivateKey v_SIZE) + Core.Result.Result_Ok ({ f_value = value } <: t_MlKemPrivateKey v_SIZE) <: - Core.Result.t_Result (t_KyberPrivateKey v_SIZE) Core.Array.t_TryFromSliceError + Core.Result.t_Result (t_MlKemPrivateKey v_SIZE) Core.Array.t_TryFromSliceError | Core.Result.Result_Err e -> Core.Result.Result_Err e <: - Core.Result.t_Result (t_KyberPrivateKey v_SIZE) Core.Array.t_TryFromSliceError + Core.Result.t_Result (t_MlKemPrivateKey v_SIZE) Core.Array.t_TryFromSliceError } -let impl_12__as_slice (v_SIZE: usize) (self: t_KyberPrivateKey v_SIZE) : t_Array u8 v_SIZE = +let impl_12__as_slice (v_SIZE: usize) (self: t_MlKemPrivateKey v_SIZE) : t_Array u8 v_SIZE = self.f_value -let impl_12__len (v_SIZE: usize) (self: t_KyberPrivateKey v_SIZE) : usize = v_SIZE +let impl_12__len (v_SIZE: usize) (self: t_MlKemPrivateKey v_SIZE) : usize = v_SIZE -let impl_12__split_at (v_SIZE: usize) (self: t_KyberPrivateKey v_SIZE) (mid: usize) +let impl_12__split_at (v_SIZE: usize) (self: t_MlKemPrivateKey v_SIZE) (mid: usize) : (t_Slice u8 & t_Slice u8) = Core.Slice.impl__split_at (Rust_primitives.unsize self.f_value <: t_Slice u8) mid -type t_KyberPublicKey (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } +type t_MlKemPublicKey (v_SIZE: usize) = { f_value:t_Array u8 v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_13 (v_SIZE: usize) : Core.Convert.t_AsRef (t_KyberPublicKey v_SIZE) (t_Slice u8) = - { f_as_ref = fun (self: t_KyberPublicKey v_SIZE) -> Rust_primitives.unsize self.f_value } +let impl_13 (v_SIZE: usize) : Core.Convert.t_AsRef (t_MlKemPublicKey v_SIZE) (t_Slice u8) = + { f_as_ref = fun (self: t_MlKemPublicKey v_SIZE) -> Rust_primitives.unsize self.f_value } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_14 (v_SIZE: usize) : Core.Convert.t_From (t_KyberPublicKey v_SIZE) (t_Array u8 v_SIZE) = - { f_from = fun (value: t_Array u8 v_SIZE) -> { f_value = value } <: t_KyberPublicKey v_SIZE } +let impl_14 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPublicKey v_SIZE) (t_Array u8 v_SIZE) = + { f_from = fun (value: t_Array u8 v_SIZE) -> { f_value = value } <: t_MlKemPublicKey v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_15 (v_SIZE: usize) : Core.Convert.t_From (t_KyberPublicKey v_SIZE) (t_Array u8 v_SIZE) = +let impl_15 (v_SIZE: usize) : Core.Convert.t_From (t_MlKemPublicKey v_SIZE) (t_Array u8 v_SIZE) = { f_from = fun (value: t_Array u8 v_SIZE) -> - { f_value = Core.Clone.f_clone value } <: t_KyberPublicKey v_SIZE + { f_value = Core.Clone.f_clone value } <: t_MlKemPublicKey v_SIZE } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_16 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_KyberPublicKey v_SIZE) = - { f_from = fun (value: t_KyberPublicKey v_SIZE) -> value.f_value } +let impl_16 (v_SIZE: usize) : Core.Convert.t_From (t_Array u8 v_SIZE) (t_MlKemPublicKey v_SIZE) = + { f_from = fun (value: t_MlKemPublicKey v_SIZE) -> value.f_value } [@@ FStar.Tactics.Typeclasses.tcinstance] -let impl_17 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_KyberPublicKey v_SIZE) (t_Slice u8) = +let impl_17 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_MlKemPublicKey v_SIZE) (t_Slice u8) = { f_Error = Core.Array.t_TryFromSliceError; f_try_from @@ -135,61 +135,61 @@ let impl_17 (v_SIZE: usize) : Core.Convert.t_TryFrom (t_KyberPublicKey v_SIZE) ( fun (value: t_Slice u8) -> match Core.Convert.f_try_into value with | Core.Result.Result_Ok value -> - Core.Result.Result_Ok ({ f_value = value } <: t_KyberPublicKey v_SIZE) + Core.Result.Result_Ok ({ f_value = value } <: t_MlKemPublicKey v_SIZE) <: - Core.Result.t_Result (t_KyberPublicKey v_SIZE) Core.Array.t_TryFromSliceError + Core.Result.t_Result (t_MlKemPublicKey v_SIZE) Core.Array.t_TryFromSliceError | Core.Result.Result_Err e -> Core.Result.Result_Err e <: - Core.Result.t_Result (t_KyberPublicKey v_SIZE) Core.Array.t_TryFromSliceError + Core.Result.t_Result (t_MlKemPublicKey v_SIZE) Core.Array.t_TryFromSliceError } -let impl_18__as_slice (v_SIZE: usize) (self: t_KyberPublicKey v_SIZE) : t_Array u8 v_SIZE = +let impl_18__as_slice (v_SIZE: usize) (self: t_MlKemPublicKey v_SIZE) : t_Array u8 v_SIZE = self.f_value -let impl_18__len (v_SIZE: usize) (self: t_KyberPublicKey v_SIZE) : usize = v_SIZE +let impl_18__len (v_SIZE: usize) (self: t_MlKemPublicKey v_SIZE) : usize = v_SIZE -let impl_18__split_at (v_SIZE: usize) (self: t_KyberPublicKey v_SIZE) (mid: usize) +let impl_18__split_at (v_SIZE: usize) (self: t_MlKemPublicKey v_SIZE) (mid: usize) : (t_Slice u8 & t_Slice u8) = Core.Slice.impl__split_at (Rust_primitives.unsize self.f_value <: t_Slice u8) mid -type t_KyberKeyPair (v_PRIVATE_KEY_SIZE: usize) (v_PUBLIC_KEY_SIZE: usize) = { - f_sk:t_KyberPrivateKey v_PRIVATE_KEY_SIZE; - f_pk:t_KyberPublicKey v_PUBLIC_KEY_SIZE +type t_MlKemKeyPair (v_PRIVATE_KEY_SIZE: usize) (v_PUBLIC_KEY_SIZE: usize) = { + f_sk:t_MlKemPrivateKey v_PRIVATE_KEY_SIZE; + f_pk:t_MlKemPublicKey v_PUBLIC_KEY_SIZE } let impl__from (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) - (sk: t_KyberPrivateKey v_PRIVATE_KEY_SIZE) - (pk: t_KyberPublicKey v_PUBLIC_KEY_SIZE) - : t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE = - { f_sk = sk; f_pk = pk } <: t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE + (sk: t_MlKemPrivateKey v_PRIVATE_KEY_SIZE) + (pk: t_MlKemPublicKey v_PUBLIC_KEY_SIZE) + : t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE = + { f_sk = sk; f_pk = pk } <: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE let impl__new (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) (sk: t_Array u8 v_PRIVATE_KEY_SIZE) (pk: t_Array u8 v_PUBLIC_KEY_SIZE) - : t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE = + : t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE = { f_sk = Core.Convert.f_into sk; f_pk = Core.Convert.f_into pk } <: - t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE + t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE let impl__pk (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) - (self: t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + (self: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) : t_Array u8 v_PUBLIC_KEY_SIZE = impl_18__as_slice v_PUBLIC_KEY_SIZE self.f_pk let impl__private_key (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) - (self: t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) - : t_KyberPrivateKey v_PRIVATE_KEY_SIZE = self.f_sk + (self: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + : t_MlKemPrivateKey v_PRIVATE_KEY_SIZE = self.f_sk let impl__public_key (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) - (self: t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) - : t_KyberPublicKey v_PUBLIC_KEY_SIZE = self.f_pk + (self: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + : t_MlKemPublicKey v_PUBLIC_KEY_SIZE = self.f_pk let impl__sk (v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE: usize) - (self: t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + (self: t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) : t_Array u8 v_PRIVATE_KEY_SIZE = impl_12__as_slice v_PRIVATE_KEY_SIZE self.f_sk diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.fst b/proofs/fstar/extraction/Libcrux.Kem.Kyber.fst index 5abd24d15..4b965142d 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.fst +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.fst @@ -111,8 +111,8 @@ let serialize_kem_secret_key let decapsulate (v_K v_SECRET_KEY_SIZE v_CPA_SECRET_KEY_SIZE v_PUBLIC_KEY_SIZE v_CIPHERTEXT_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize) - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey v_SECRET_KEY_SIZE) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext v_CIPHERTEXT_SIZE) + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey v_SECRET_KEY_SIZE) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) = let ind_cpa_secret_key, secret_key:(t_Slice u8 & t_Slice u8) = Libcrux.Kem.Kyber.Types.impl_12__split_at v_SECRET_KEY_SIZE secret_key v_CPA_SECRET_KEY_SIZE @@ -201,7 +201,7 @@ let decapsulate let encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: usize) - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey v_PUBLIC_KEY_SIZE) + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey v_PUBLIC_KEY_SIZE) (randomness: t_Array u8 (sz 32)) = let (to_hash: t_Array u8 (sz 64)):t_Array u8 (sz 64) = @@ -262,7 +262,28 @@ let encapsulate in Core.Convert.f_into ciphertext, shared_secret <: - (Libcrux.Kem.Kyber.Types.t_KyberCiphertext v_CIPHERTEXT_SIZE & t_Array u8 (sz 32)) + (Libcrux.Kem.Kyber.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE & t_Array u8 (sz 32)) + +let validate_public_key + (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) + (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) + = + let pk:t_Array Libcrux.Kem.Kyber.Arithmetic.t_PolynomialRingElement v_K = + Libcrux.Kem.Kyber.Ind_cpa.deserialize_public_key v_K + (Rust_primitives.unsize public_key <: t_Slice u8) + in + let public_key_serialized:t_Array u8 v_PUBLIC_KEY_SIZE = + Libcrux.Kem.Kyber.Ind_cpa.serialize_public_key v_K + v_RANKED_BYTES_PER_RING_ELEMENT + v_PUBLIC_KEY_SIZE + pk + (public_key.[ { Core.Ops.Range.f_start = v_RANKED_BYTES_PER_RING_ELEMENT } + <: + Core.Ops.Range.t_RangeFrom usize ] + <: + t_Slice u8) + in + public_key =. public_key_serialized let generate_keypair (v_K v_CPA_PRIVATE_KEY_SIZE v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE v_BYTES_PER_RING_ELEMENT v_ETA1 v_ETA1_RANDOMNESS_SIZE: @@ -300,11 +321,11 @@ let generate_keypair (Rust_primitives.unsize public_key <: t_Slice u8) implicit_rejection_value in - let (private_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey v_PRIVATE_KEY_SIZE):Libcrux.Kem.Kyber.Types.t_KyberPrivateKey + let (private_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey v_PRIVATE_KEY_SIZE):Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey v_PRIVATE_KEY_SIZE = Core.Convert.f_from secret_key_serialized in Libcrux.Kem.Kyber.Types.impl__from v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE private_key - (Core.Convert.f_into public_key <: Libcrux.Kem.Kyber.Types.t_KyberPublicKey v_PUBLIC_KEY_SIZE) + (Core.Convert.f_into public_key <: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey v_PUBLIC_KEY_SIZE) diff --git a/proofs/fstar/extraction/Libcrux.Kem.Kyber.fsti b/proofs/fstar/extraction/Libcrux.Kem.Kyber.fsti index 5858b4cfc..45e259a23 100644 --- a/proofs/fstar/extraction/Libcrux.Kem.Kyber.fsti +++ b/proofs/fstar/extraction/Libcrux.Kem.Kyber.fsti @@ -4,7 +4,7 @@ open Core open FStar.Mul unfold -let t_KyberSharedSecret = t_Array u8 (sz 32) +let t_MlKemSharedSecret = t_Array u8 (sz 32) let v_KEY_GENERATION_SEED_SIZE: usize = Libcrux.Kem.Kyber.Constants.v_CPA_PKE_KEY_GENERATION_SEED_SIZE +! @@ -18,23 +18,28 @@ val serialize_kem_secret_key val decapsulate (v_K v_SECRET_KEY_SIZE v_CPA_SECRET_KEY_SIZE v_PUBLIC_KEY_SIZE v_CIPHERTEXT_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_C1_BLOCK_SIZE v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE v_IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize) - (secret_key: Libcrux.Kem.Kyber.Types.t_KyberPrivateKey v_SECRET_KEY_SIZE) - (ciphertext: Libcrux.Kem.Kyber.Types.t_KyberCiphertext v_CIPHERTEXT_SIZE) + (secret_key: Libcrux.Kem.Kyber.Types.t_MlKemPrivateKey v_SECRET_KEY_SIZE) + (ciphertext: Libcrux.Kem.Kyber.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE) : Prims.Pure (t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) val encapsulate (v_K v_CIPHERTEXT_SIZE v_PUBLIC_KEY_SIZE v_T_AS_NTT_ENCODED_SIZE v_C1_SIZE v_C2_SIZE v_VECTOR_U_COMPRESSION_FACTOR v_VECTOR_V_COMPRESSION_FACTOR v_VECTOR_U_BLOCK_LEN v_ETA1 v_ETA1_RANDOMNESS_SIZE v_ETA2 v_ETA2_RANDOMNESS_SIZE: usize) - (public_key: Libcrux.Kem.Kyber.Types.t_KyberPublicKey v_PUBLIC_KEY_SIZE) + (public_key: Libcrux.Kem.Kyber.Types.t_MlKemPublicKey v_PUBLIC_KEY_SIZE) (randomness: t_Array u8 (sz 32)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberCiphertext v_CIPHERTEXT_SIZE & t_Array u8 (sz 32)) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemCiphertext v_CIPHERTEXT_SIZE & t_Array u8 (sz 32)) Prims.l_True (fun _ -> Prims.l_True) +val validate_public_key + (v_K v_RANKED_BYTES_PER_RING_ELEMENT v_PUBLIC_KEY_SIZE: usize) + (public_key: t_Array u8 v_PUBLIC_KEY_SIZE) + : Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + val generate_keypair (v_K v_CPA_PRIVATE_KEY_SIZE v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE v_BYTES_PER_RING_ELEMENT v_ETA1 v_ETA1_RANDOMNESS_SIZE: usize) (randomness: t_Array u8 (sz 64)) - : Prims.Pure (Libcrux.Kem.Kyber.Types.t_KyberKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) + : Prims.Pure (Libcrux.Kem.Kyber.Types.t_MlKemKeyPair v_PRIVATE_KEY_SIZE v_PUBLIC_KEY_SIZE) Prims.l_True (fun _ -> Prims.l_True) diff --git a/proofs/fstar/extraction/Libcrux.Kem.fst b/proofs/fstar/extraction/Libcrux.Kem.fst deleted file mode 100644 index 32db92756..000000000 --- a/proofs/fstar/extraction/Libcrux.Kem.fst +++ /dev/null @@ -1,6 +0,0 @@ -module Libcrux.Kem -#set-options "--fuel 0 --ifuel 1 --z3rlimit 15" -open Core -open FStar.Mul - - diff --git a/proofs/fstar/extraction/Libcrux_platform.fsti b/proofs/fstar/extraction/Libcrux_platform.fsti index e97df7666..eb72fb629 100644 --- a/proofs/fstar/extraction/Libcrux_platform.fsti +++ b/proofs/fstar/extraction/Libcrux_platform.fsti @@ -1,4 +1,20 @@ module Libcrux_platform #set-options "--fuel 0 --ifuel 1 --z3rlimit 15" +open Core +open FStar.Mul -val simd256_support : unit -> bool +val bmi2_adx_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val simd256_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val x25519_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val adv_simd_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val aes_ni_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val pmull_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val sha256_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) + +val simd128_support: Prims.unit -> Prims.Pure bool Prims.l_True (fun _ -> Prims.l_True) diff --git a/proofs/fstar/extraction/Makefile b/proofs/fstar/extraction/Makefile index 1bbb2f2db..3f5af74f7 100644 --- a/proofs/fstar/extraction/Makefile +++ b/proofs/fstar/extraction/Makefile @@ -50,9 +50,7 @@ all: VERIFIED = \ Libcrux_platform.fsti \ - Libcrux.Kem.fst \ Libcrux.Kem.Kyber.Constants.fsti \ - Libcrux.Digest.fsti \ Libcrux.Kem.Kyber.Kyber768.fst \ Libcrux.Kem.Kyber.Kyber1024.fst \ Libcrux.Kem.Kyber.Kyber512.fst @@ -79,7 +77,7 @@ UNVERIFIED_CHECKED = $(addsuffix .checked, $(addprefix $(CACHE_DIR)/,$(UNVERIFIE # *extend* the set of relevant files with the tests. ROOTS = $(UNVERIFIED) $(VERIFIED) -FSTAR_INCLUDE_DIRS = $(HACL_HOME)/lib $(HAX_PROOF_LIBS_HOME)/rust_primitives $(HAX_PROOF_LIBS_HOME)/core $(HAX_LIBS_HOME) +FSTAR_INCLUDE_DIRS = $(HACL_HOME)/lib $(HAX_PROOF_LIBS_HOME)/rust_primitives $(HAX_PROOF_LIBS_HOME)/core $(HAX_LIBS_HOME) ../../../sys/platform/proofs/fstar/extraction/ FSTAR_FLAGS = --cmi \ --warn_error -331-321-274 \ diff --git a/specs/kyber/Cargo.toml b/specs/kyber/Cargo.toml index 63d3458c5..0d1a92fa2 100644 --- a/specs/kyber/Cargo.toml +++ b/specs/kyber/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -libcrux = { version = "=0.0.2-pre.2", path = "../../" } +libcrux = { version = "=0.0.2-pre.2", path = "../../", features = ["tests"] } hacspec-lib = { version = "0.0.1", path = "../hacspec-lib" } [dev-dependencies] diff --git a/specs/kyber/tests/interop_with_libcrux.rs b/specs/kyber/tests/interop_with_libcrux.rs index 18875c76a..d10850518 100644 --- a/specs/kyber/tests/interop_with_libcrux.rs +++ b/specs/kyber/tests/interop_with_libcrux.rs @@ -3,7 +3,7 @@ use hacspec_kyber::{ KYBER768_CIPHERTEXT_SIZE, KYBER768_KEY_GENERATION_SEED_SIZE, KYBER768_SHARED_SECRET_SIZE, }; -use libcrux::kem::KyberCiphertext; +use libcrux::kem::MlKemCiphertext; use rand::{rngs::OsRng, RngCore}; #[test] @@ -12,7 +12,8 @@ fn same_inputs_result_in_same_output() { OsRng.fill_bytes(&mut keygen_seed); let spec_key_pair = hacspec_kyber::generate_keypair(keygen_seed).unwrap(); - let libcrux_key_pair = libcrux::kem::kyber768_generate_keypair_derand(keygen_seed); + let libcrux_key_pair = + libcrux::kem::deterministic::kyber768_generate_keypair_derand(keygen_seed); assert_eq!(libcrux_key_pair.pk(), spec_key_pair.pk()); assert_eq!(libcrux_key_pair.sk(), spec_key_pair.sk()); @@ -21,31 +22,37 @@ fn same_inputs_result_in_same_output() { OsRng.fill_bytes(&mut message); let (spec_ct, spec_ss) = hacspec_kyber::encapsulate(*spec_key_pair.pk(), message).unwrap(); - let (libcrux_ct, libcrux_ss) = - libcrux::kem::kyber768_encapsulate_derand(&libcrux_key_pair.pk().into(), message); + let (libcrux_ct, libcrux_ss) = libcrux::kem::deterministic::kyber768_encapsulate_derand( + &libcrux_key_pair.pk().into(), + message, + ); assert_eq!(libcrux_ct.as_ref(), spec_ct); assert_eq!(libcrux_ss.as_ref(), spec_ss); let (spec_ct, spec_ss) = hacspec_kyber::encapsulate(*spec_key_pair.pk(), message).unwrap(); - let (libcrux_ct, libcrux_ss) = - libcrux::kem::kyber768_encapsulate_derand(&libcrux_key_pair.pk().into(), message); + let (libcrux_ct, libcrux_ss) = libcrux::kem::deterministic::kyber768_encapsulate_derand( + &libcrux_key_pair.pk().into(), + message, + ); assert_eq!(libcrux_ct.as_ref(), spec_ct); assert_eq!(libcrux_ss.as_ref(), spec_ss); let spec_ss = hacspec_kyber::decapsulate(spec_ct, *spec_key_pair.sk()); - let libcrux_ss = - libcrux::kem::kyber768_decapsulate_derand(libcrux_key_pair.private_key(), &libcrux_ct); + let libcrux_ss = libcrux::kem::deterministic::kyber768_decapsulate_derand( + libcrux_key_pair.private_key(), + &libcrux_ct, + ); assert_eq!(libcrux_ss, spec_ss); } fn modify_ciphertext_pair( - libcrux_ct: KyberCiphertext, + libcrux_ct: MlKemCiphertext, mut spec_ct: hacspec_kyber::Ciphertext, ) -> ( - KyberCiphertext, + MlKemCiphertext, hacspec_kyber::Ciphertext, ) { let mut random_bytes = [0u8; 3]; @@ -73,26 +80,31 @@ fn implicit_rejection_happens_the_same_way() { OsRng.fill_bytes(&mut keygen_seed); let spec_key_pair = hacspec_kyber::generate_keypair(keygen_seed).unwrap(); - let libcrux_key_pair = libcrux::kem::kyber768_generate_keypair_derand(keygen_seed); + let libcrux_key_pair = + libcrux::kem::deterministic::kyber768_generate_keypair_derand(keygen_seed); let mut message = [0u8; KYBER768_SHARED_SECRET_SIZE]; OsRng.fill_bytes(&mut message); let (spec_ct, spec_ss) = hacspec_kyber::encapsulate(*spec_key_pair.pk(), message).unwrap(); - let (libcrux_ct, libcrux_ss) = - libcrux::kem::kyber768_encapsulate_derand(&libcrux_key_pair.pk().into(), message); + let (libcrux_ct, libcrux_ss) = libcrux::kem::deterministic::kyber768_encapsulate_derand( + &libcrux_key_pair.pk().into(), + message, + ); assert_eq!(libcrux_ct.as_ref(), spec_ct); assert_eq!(libcrux_ss.as_ref(), spec_ss); let (spec_ct, _) = hacspec_kyber::encapsulate(*spec_key_pair.pk(), message).unwrap(); - let (libcrux_ct, _) = - libcrux::kem::kyber768_encapsulate_derand(&libcrux_key_pair.pk().into(), message); + let (libcrux_ct, _) = libcrux::kem::deterministic::kyber768_encapsulate_derand( + &libcrux_key_pair.pk().into(), + message, + ); let (modified_libcrux_ct, modified_spec_ct) = modify_ciphertext_pair(libcrux_ct, spec_ct); let spec_ss = hacspec_kyber::decapsulate(modified_spec_ct, *spec_key_pair.sk()); - let libcrux_ss = libcrux::kem::kyber768_decapsulate_derand( + let libcrux_ss = libcrux::kem::deterministic::kyber768_decapsulate_derand( libcrux_key_pair.private_key(), &modified_libcrux_ct, ); diff --git a/src/hpke/hpke.rs b/src/hpke/hpke.rs index 46575a99b..8db6e054e 100644 --- a/src/hpke/hpke.rs +++ b/src/hpke/hpke.rs @@ -1,7 +1,6 @@ #![allow(non_camel_case_types, non_snake_case, unused_imports)] -use crate::kem::Kyber768X25519PrivateKey; -use crate::kem::Kyber768X25519PublicKey; +use crate::kem::{X25519MlKem768Draft00PrivateKey, X25519MlKem768Draft00PublicKey}; use super::aead::*; use super::kdf::*; @@ -406,19 +405,21 @@ pub fn SetupBaseS( KEM::X25519Kyber768Draft00 => { // FIXME: clean up // Decode the public key - let Kyber768X25519PublicKey { kyber, x25519 } = - crate::kem::Kyber768X25519PublicKey::decode(pkR).unwrap(); + let X25519MlKem768Draft00PublicKey { + mlkem: kyber, + x25519, + } = X25519MlKem768Draft00PublicKey::decode(pkR).unwrap(); let (ss1, enc1) = Encap( KEM::DHKEM_X25519_HKDF_SHA256, &x25519.0, randomness[0..32].to_vec(), )?; let (ss2, enc2) = Kyber768Draft00_Encap(kyber.as_ref(), randomness[32..64].to_vec())?; - let ct = crate::kem::Ct::Kyber768X25519( + let ct = crate::kem::Ct::X25519MlKem768Draft00( enc2.as_slice().try_into().unwrap(), crate::ecdh::x25519::PublicKey(enc1.try_into().unwrap()), ); - let ss = crate::kem::Ss::Kyber768X25519( + let ss = crate::kem::Ss::X25519MlKem768Draft00( ss2.as_slice().try_into().unwrap(), crate::ecdh::x25519::PublicKey(ss1.try_into().unwrap()), ); @@ -461,11 +462,13 @@ pub fn SetupBaseR( KEM::X25519Kyber768Draft00 => { // FIXME: clean up // Decode the public key - let Kyber768X25519PrivateKey { kyber, x25519 } = - Kyber768X25519PrivateKey::decode(skR).unwrap(); + let X25519MlKem768Draft00PrivateKey { + mlkem: kyber, + x25519, + } = X25519MlKem768Draft00PrivateKey::decode(skR).unwrap(); let ss1 = Decap(KEM::DHKEM_X25519_HKDF_SHA256, &enc[0..32], &x25519.0)?; let ss2 = Kyber768Draft00_Decap(kyber.as_ref(), &enc[32..])?; - let ss = crate::kem::Ss::Kyber768X25519( + let ss = crate::kem::Ss::X25519MlKem768Draft00( ss2.as_slice().try_into().unwrap(), crate::ecdh::x25519::PublicKey(ss1.try_into().unwrap()), ); diff --git a/src/hpke/kem.rs b/src/hpke/kem.rs index 68fcc968e..1f03a8cd2 100644 --- a/src/hpke/kem.rs +++ b/src/hpke/kem.rs @@ -2,7 +2,10 @@ #![doc = include_str!("KEM_Security.md")] #![allow(non_camel_case_types, non_snake_case)] -use crate::kem::{kyber::KyberKeyPair, kyber768_generate_keypair_derand, *}; +use crate::kem::{ + kyber::{kyber768, MlKemKeyPair}, + *, +}; use super::errors::*; use super::kdf::*; @@ -512,15 +515,15 @@ pub fn GenerateKeyPair(alg: KEM, randomness: Randomness) -> Result EncapResult /// /// FIXME: vec conversions and unwraps pub fn Kyber768Draft00_Encap(pkR: &PublicKeyIn, randomness: Randomness) -> EncapResult { - let (ct, ss) = crate::kem::kyber768_encapsulate_derand( - &pkR.try_into().unwrap(), - randomness.try_into().unwrap(), - ); + let (ct, ss) = kyber768::encapsulate(&pkR.try_into().unwrap(), randomness.try_into().unwrap()); EncapResult::Ok((ss.as_ref().to_vec(), ct.as_ref().to_vec())) } @@ -569,10 +569,7 @@ pub fn Kyber768Draft00_Encap(pkR: &PublicKeyIn, randomness: Randomness) -> Encap /// /// FIXME: vec conversions and unwraps pub fn Kyber768Draft00_Decap(skR: &PrivateKeyIn, enc: &[u8]) -> Result { - Ok( - crate::kem::kyber768_decapsulate_derand(&skR.try_into().unwrap(), &enc.try_into().unwrap()) - .to_vec(), - ) + Ok(kyber768::decapsulate(&skR.try_into().unwrap(), &enc.try_into().unwrap()).to_vec()) } /// ```text diff --git a/src/kem.rs b/src/kem.rs index 6303afc8f..1cdf529ed 100644 --- a/src/kem.rs +++ b/src/kem.rs @@ -1,13 +1,38 @@ //! # Key Encapsulation Mechanism //! //! A KEM interface. +//! +//! For ECDH structs, check the [`ecdh`] module. +//! +//! Available algorithms: +//! * [`Algorithm::X25519`]\: x25519 ECDH KEM. Also see [`ecdh#x25519`]. +//! * [`Algorithm::Secp256r1`]\: NIST P256 ECDH KEM. Also see [`ecdh#P256`]. +//! * [`Algorithm::MlKem512`]\: ML-KEM 512 from [FIPS 203]. +//! * [`Algorithm::MlKem768`]\: ML-KEM 768 from [FIPS 203]. +//! * [`Algorithm::MlKem1024`]\: ML-KEM 1024 from [FIPS 203]. +//! * [`Algorithm::X25519MlKem768Draft00`]\: Hybrid x25519 - ML-KEM 768 [draft kem for hpke](https://www.ietf.org/archive/id/draft-westerbaan-cfrg-hpke-xyber768d00-00.html). +//! +//! ``` +//! use libcrux::{kem::*, drbg::Drbg, digest::Algorithm::Sha256}; +//! +//! let mut rng = Drbg::new(Sha256).unwrap(); +//! let (sk_a, pk_a) = key_gen(Algorithm::MlKem768, &mut rng).unwrap(); +//! let received_pk = pk_a.encode(); +//! +//! let pk = PublicKey::decode(Algorithm::MlKem768, &received_pk).unwrap(); +//! let (ss_b, ct_b) = pk.encapsulate(&mut rng).unwrap(); +//! let received_ct = ct_b.encode(); +//! +//! let ct_a = Ct::decode(Algorithm::MlKem768, &received_ct).unwrap(); +//! let ss_a = ct_a.decapsulate(&sk_a).unwrap(); +//! assert_eq!(ss_b.encode(), ss_a.encode()); +//! ``` +//! +//! [FIPS 203]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf use rand::{CryptoRng, Rng}; -use crate::ecdh; -use crate::ecdh::p256; -use crate::ecdh::p256_derive; -use crate::ecdh::x25519; +use crate::ecdh::{self, p256, p256_derive, x25519}; // hacspec code: don't let clippy touch it. #[allow(clippy::all)] @@ -18,23 +43,27 @@ pub(crate) mod kyber; // (and change the visibility of the exported functions to pub(crate)) the // moment we have an implementation of one. This is tracked by: // https://github.com/cryspen/libcrux/issues/36 -pub use kyber::kyber1024::decapsulate_1024 as kyber1024_decapsulate_derand; -pub use kyber::kyber1024::encapsulate_1024 as kyber1024_encapsulate_derand; -pub use kyber::kyber1024::generate_key_pair_1024 as kyber1024_generate_keypair_derand; -pub use kyber::kyber512::decapsulate_512 as kyber512_decapsulate_derand; -pub use kyber::kyber512::encapsulate_512 as kyber512_encapsulate_derand; -pub use kyber::kyber512::generate_key_pair_512 as kyber512_generate_keypair_derand; -pub use kyber::kyber768::decapsulate_768 as kyber768_decapsulate_derand; -pub use kyber::kyber768::encapsulate_768 as kyber768_encapsulate_derand; -pub use kyber::kyber768::generate_key_pair_768 as kyber768_generate_keypair_derand; +#[cfg(feature = "tests")] +pub mod deterministic { + pub use super::kyber::kyber1024::decapsulate as kyber1024_decapsulate_derand; + pub use super::kyber::kyber1024::encapsulate as kyber1024_encapsulate_derand; + pub use super::kyber::kyber1024::generate_key_pair as kyber1024_generate_keypair_derand; + pub use super::kyber::kyber512::decapsulate as kyber512_decapsulate_derand; + pub use super::kyber::kyber512::encapsulate as kyber512_encapsulate_derand; + pub use super::kyber::kyber512::generate_key_pair as kyber512_generate_keypair_derand; + pub use super::kyber::kyber768::decapsulate as kyber768_decapsulate_derand; + pub use super::kyber::kyber768::encapsulate as kyber768_encapsulate_derand; + pub use super::kyber::kyber768::generate_key_pair as kyber768_generate_keypair_derand; +} +use self::kyber::{kyber1024, kyber512, kyber768}; use self::kyber::{ - kyber1024::{Kyber1024Ciphertext, Kyber1024PrivateKey, Kyber1024PublicKey}, - kyber512::{Kyber512Ciphertext, Kyber512PrivateKey, Kyber512PublicKey}, - kyber768::{Kyber768Ciphertext, Kyber768PrivateKey, Kyber768PublicKey}, - KyberSharedSecret, + kyber1024::{MlKem1024Ciphertext, MlKem1024PrivateKey, MlKem1024PublicKey}, + kyber512::{MlKem512Ciphertext, MlKem512PrivateKey, MlKem512PublicKey}, + kyber768::{MlKem768Ciphertext, MlKem768PrivateKey, MlKem768PublicKey}, + MlKemSharedSecret, }; -pub use kyber::{KyberCiphertext, KyberKeyPair}; +pub use kyber::{MlKemCiphertext, MlKemKeyPair}; /// KEM Algorithms /// @@ -46,10 +75,10 @@ pub enum Algorithm { Secp256r1, Secp384r1, Secp521r1, - Kyber512, - Kyber768, - Kyber768X25519, - Kyber1024, + MlKem512, + MlKem768, + X25519MlKem768Draft00, + MlKem1024, } #[derive(Debug, PartialEq, Eq)] @@ -74,7 +103,7 @@ impl TryFrom for ecdh::Algorithm { Algorithm::Secp256r1 => Ok(ecdh::Algorithm::P256), Algorithm::Secp384r1 => Ok(ecdh::Algorithm::P384), Algorithm::Secp521r1 => Ok(ecdh::Algorithm::P521), - Algorithm::Kyber768X25519 => Ok(ecdh::Algorithm::X25519), + Algorithm::X25519MlKem768Draft00 => Ok(ecdh::Algorithm::X25519), _ => Err("provided algorithm is not an ECDH algorithm"), } } @@ -86,15 +115,16 @@ impl From for Error { } } -pub struct Kyber768X25519PrivateKey { - pub kyber: Kyber768PrivateKey, +/// An ML-KEM768-x25519 private key. +pub struct X25519MlKem768Draft00PrivateKey { + pub mlkem: MlKem768PrivateKey, pub x25519: x25519::PrivateKey, } -impl Kyber768X25519PrivateKey { +impl X25519MlKem768Draft00PrivateKey { pub fn decode(bytes: &[u8]) -> Result { Ok(Self { - kyber: bytes[32..] + mlkem: bytes[32..] .try_into() .map_err(|_| Error::InvalidPrivateKey)?, x25519: bytes[..32] @@ -105,7 +135,7 @@ impl Kyber768X25519PrivateKey { pub fn encode(&self) -> Vec { let mut out = self.x25519.0.to_vec(); - out.extend_from_slice(self.kyber.as_ref()); + out.extend_from_slice(self.mlkem.as_ref()); out } } @@ -114,23 +144,25 @@ impl Kyber768X25519PrivateKey { pub enum PrivateKey { X25519(x25519::PrivateKey), P256(p256::PrivateKey), - Kyber512(Kyber512PrivateKey), - Kyber768(Kyber768PrivateKey), - Kyber768X25519(Kyber768X25519PrivateKey), - Kyber1024(Kyber1024PrivateKey), + MlKem512(MlKem512PrivateKey), + MlKem768(MlKem768PrivateKey), + X25519MlKem768Draft00(X25519MlKem768Draft00PrivateKey), + MlKem1024(MlKem1024PrivateKey), } -pub struct Kyber768X25519PublicKey { - pub kyber: Kyber768PublicKey, +/// An ML-KEM768-x25519 public key. +pub struct X25519MlKem768Draft00PublicKey { + pub mlkem: MlKem768PublicKey, pub x25519: x25519::PublicKey, } -impl Kyber768X25519PublicKey { +impl X25519MlKem768Draft00PublicKey { pub fn decode(bytes: &[u8]) -> Result { Ok(Self { - kyber: bytes[32..] - .try_into() - .map_err(|_| Error::InvalidPublicKey)?, + mlkem: MlKem768PublicKey::try_from(&bytes[32..]) + .ok() + .and_then(kyber768::validate_public_key) + .ok_or(Error::InvalidPublicKey)?, x25519: bytes[0..32] .try_into() .map_err(|_| Error::InvalidPublicKey)?, @@ -139,7 +171,7 @@ impl Kyber768X25519PublicKey { pub fn encode(&self) -> Vec { let mut out = self.x25519.0.to_vec(); - out.extend_from_slice(self.kyber.as_ref()); + out.extend_from_slice(self.mlkem.as_ref()); out } } @@ -148,30 +180,101 @@ impl Kyber768X25519PublicKey { pub enum PublicKey { X25519(x25519::PublicKey), P256(p256::PublicKey), - Kyber512(Kyber512PublicKey), - Kyber768(Kyber768PublicKey), - Kyber768X25519(Kyber768X25519PublicKey), - Kyber1024(Kyber1024PublicKey), + MlKem512(MlKem512PublicKey), + MlKem768(MlKem768PublicKey), + X25519MlKem768Draft00(X25519MlKem768Draft00PublicKey), + MlKem1024(MlKem1024PublicKey), } /// A KEM ciphertext pub enum Ct { X25519(x25519::PublicKey), P256(p256::PublicKey), - Kyber512(Kyber512Ciphertext), - Kyber768(Kyber768Ciphertext), - Kyber768X25519(Kyber768Ciphertext, x25519::PublicKey), - Kyber1024(Kyber1024Ciphertext), + MlKem512(MlKem512Ciphertext), + MlKem768(MlKem768Ciphertext), + X25519MlKem768Draft00(MlKem768Ciphertext, x25519::PublicKey), + MlKem1024(MlKem1024Ciphertext), +} + +impl Ct { + /// Decapsulate the shared secret in `ct` using the private key `sk`. + pub fn decapsulate(&self, sk: &PrivateKey) -> Result { + match self { + Ct::X25519(ct) => { + let sk = if let PrivateKey::X25519(k) = sk { + k + } else { + return Err(Error::InvalidPrivateKey); + }; + x25519::derive(ct, sk).map_err(|e| e.into()).map(Ss::X25519) + } + Ct::P256(ct) => { + let sk = if let PrivateKey::P256(k) = sk { + k + } else { + return Err(Error::InvalidPrivateKey); + }; + p256_derive(ct, sk).map_err(|e| e.into()).map(Ss::P256) + } + Ct::MlKem512(ct) => { + let sk = if let PrivateKey::MlKem512(k) = sk { + k + } else { + return Err(Error::InvalidPrivateKey); + }; + let ss = kyber::kyber512::decapsulate(sk, ct); + + Ok(Ss::MlKem768(ss)) + } + Ct::MlKem768(ct) => { + let sk = if let PrivateKey::MlKem768(k) = sk { + k + } else { + return Err(Error::InvalidPrivateKey); + }; + let ss = kyber768::decapsulate(sk, ct); + + Ok(Ss::MlKem768(ss)) + } + Ct::X25519MlKem768Draft00(kct, xct) => { + let (ksk, xsk) = + if let PrivateKey::X25519MlKem768Draft00(X25519MlKem768Draft00PrivateKey { + mlkem: kk, + x25519: xk, + }) = sk + { + (kk, xk) + } else { + return Err(Error::InvalidPrivateKey); + }; + let kss = kyber768::decapsulate(ksk, kct); + let xss = x25519::derive(xct, xsk)?; + + Ok(Ss::X25519MlKem768Draft00(kss, xss)) + } + + Ct::MlKem1024(ct) => { + let sk = if let PrivateKey::MlKem1024(k) = sk { + k + } else { + return Err(Error::InvalidPrivateKey); + }; + let ss = kyber::kyber1024::decapsulate(sk, ct); + + Ok(Ss::MlKem1024(ss)) + } + } + } } /// A KEM shared secret pub enum Ss { X25519(x25519::PublicKey), P256(p256::PublicKey), - Kyber512(KyberSharedSecret), - Kyber768(KyberSharedSecret), - Kyber768X25519(KyberSharedSecret, x25519::PublicKey), - Kyber1024(KyberSharedSecret), + MlKem512(MlKemSharedSecret), + MlKem768(MlKemSharedSecret), + X25519MlKem768Draft00(MlKemSharedSecret, x25519::PublicKey), + MlKem1024(MlKemSharedSecret), } impl PrivateKey { @@ -180,10 +283,10 @@ impl PrivateKey { match self { PrivateKey::X25519(k) => k.0.to_vec(), PrivateKey::P256(k) => k.0.to_vec(), - PrivateKey::Kyber512(k) => k.as_slice().to_vec(), - PrivateKey::Kyber768(k) => k.as_slice().to_vec(), - PrivateKey::Kyber768X25519(k) => k.encode(), - PrivateKey::Kyber1024(k) => k.as_slice().to_vec(), + PrivateKey::MlKem512(k) => k.as_slice().to_vec(), + PrivateKey::MlKem768(k) => k.as_slice().to_vec(), + PrivateKey::X25519MlKem768Draft00(k) => k.encode(), + PrivateKey::MlKem1024(k) => k.as_slice().to_vec(), } } @@ -198,42 +301,93 @@ impl PrivateKey { .try_into() .map_err(|_| Error::InvalidPrivateKey) .map(Self::P256), - Algorithm::Kyber512 => bytes + Algorithm::MlKem512 => bytes .try_into() .map_err(|_| Error::InvalidPrivateKey) - .map(Self::Kyber512), - Algorithm::Kyber768 => bytes + .map(Self::MlKem512), + Algorithm::MlKem768 => bytes .try_into() .map_err(|_| Error::InvalidPrivateKey) - .map(Self::Kyber768), - Algorithm::Kyber768X25519 => { - let key: [u8; kyber::kyber768::SECRET_KEY_SIZE_768 + 32] = + .map(Self::MlKem768), + Algorithm::X25519MlKem768Draft00 => { + let key: [u8; kyber768::SECRET_KEY_SIZE_768 + 32] = bytes.try_into().map_err(|_| Error::InvalidPrivateKey)?; - let (ksk, xsk) = key.split_at(kyber::kyber768::SECRET_KEY_SIZE_768); - Ok(Self::Kyber768X25519(Kyber768X25519PrivateKey { - kyber: ksk.try_into().map_err(|_| Error::InvalidPrivateKey)?, - x25519: xsk.try_into().map_err(|_| Error::InvalidPrivateKey)?, - })) + let (ksk, xsk) = key.split_at(kyber768::SECRET_KEY_SIZE_768); + Ok(Self::X25519MlKem768Draft00( + X25519MlKem768Draft00PrivateKey { + mlkem: ksk.try_into().map_err(|_| Error::InvalidPrivateKey)?, + x25519: xsk.try_into().map_err(|_| Error::InvalidPrivateKey)?, + }, + )) } - Algorithm::Kyber1024 => bytes + Algorithm::MlKem1024 => bytes .try_into() .map_err(|_| Error::InvalidPrivateKey) - .map(Self::Kyber1024), + .map(Self::MlKem1024), _ => Err(Error::UnsupportedAlgorithm), } } } impl PublicKey { + /// Encapsulate a shared secret to the provided `pk` and return the `(Key, Enc)` tuple. + pub fn encapsulate(&self, rng: &mut (impl CryptoRng + Rng)) -> Result<(Ss, Ct), Error> { + match self { + PublicKey::X25519(pk) => { + let (new_sk, new_pk) = ecdh::x25519_key_gen(rng)?; + let gxy = x25519::derive(pk, &new_sk)?; + Ok((Ss::X25519(gxy), Ct::X25519(new_pk))) + } + PublicKey::P256(pk) => { + let (new_sk, new_pk) = ecdh::p256_key_gen(rng)?; + let gxy = p256_derive(pk, &new_sk)?; + Ok((Ss::P256(gxy), Ct::P256(new_pk))) + } + + PublicKey::MlKem512(pk) => { + let seed = kyber_rand(rng)?; + let (ct, ss) = kyber::kyber512::encapsulate(pk, seed); + Ok((Ss::MlKem512(ss), Ct::MlKem512(ct))) + } + + PublicKey::MlKem768(pk) => { + let seed = kyber_rand(rng)?; + let (ct, ss) = kyber768::encapsulate(pk, seed); + Ok((Ss::MlKem768(ss), Ct::MlKem768(ct))) + } + + PublicKey::MlKem1024(pk) => { + let seed = kyber_rand(rng)?; + let (ct, ss) = kyber1024::encapsulate(pk, seed); + Ok((Ss::MlKem1024(ss), Ct::MlKem1024(ct))) + } + + PublicKey::X25519MlKem768Draft00(X25519MlKem768Draft00PublicKey { + mlkem: kpk, + x25519: xpk, + }) => { + let seed = kyber_rand(rng)?; + let (kyber_ct, kyber_ss) = kyber768::encapsulate(kpk, seed); + let (x_sk, x_pk) = ecdh::x25519_key_gen(rng)?; + let x_ss = x25519::derive(xpk, &x_sk)?; + + Ok(( + Ss::X25519MlKem768Draft00(kyber_ss, x_ss), + Ct::X25519MlKem768Draft00(kyber_ct, x_pk), + )) + } + } + } + /// Encode public key. pub fn encode(&self) -> Vec { match self { PublicKey::X25519(k) => k.0.to_vec(), PublicKey::P256(k) => k.0.to_vec(), - PublicKey::Kyber512(k) => k.as_ref().to_vec(), - PublicKey::Kyber768(k) => k.as_ref().to_vec(), - PublicKey::Kyber768X25519(k) => k.encode(), - PublicKey::Kyber1024(k) => k.as_ref().to_vec(), + PublicKey::MlKem512(k) => k.as_ref().to_vec(), + PublicKey::MlKem768(k) => k.as_ref().to_vec(), + PublicKey::X25519MlKem768Draft00(k) => k.encode(), + PublicKey::MlKem1024(k) => k.as_ref().to_vec(), } } @@ -242,23 +396,30 @@ impl PublicKey { match alg { Algorithm::X25519 => bytes .try_into() - .map_err(|_| Error::InvalidPublicKey) - .map(Self::X25519), + .map(Self::X25519) + .map_err(|_| Error::InvalidPublicKey), Algorithm::Secp256r1 => bytes .try_into() - .map_err(|_| Error::InvalidPublicKey) - .map(Self::P256), - Algorithm::Kyber768 => bytes - .try_into() - .map_err(|_| Error::InvalidPublicKey) - .map(Self::Kyber768), - Algorithm::Kyber768X25519 => { - Kyber768X25519PublicKey::decode(bytes).map(Self::Kyber768X25519) + .map(Self::P256) + .map_err(|_| Error::InvalidPublicKey), + Algorithm::MlKem512 => MlKem512PublicKey::try_from(bytes) + .ok() + .and_then(kyber512::validate_public_key) + .map(Self::MlKem512) + .ok_or(Error::InvalidPublicKey), + Algorithm::MlKem768 => MlKem768PublicKey::try_from(bytes) + .ok() + .and_then(kyber768::validate_public_key) + .map(Self::MlKem768) + .ok_or(Error::InvalidPublicKey), + Algorithm::X25519MlKem768Draft00 => { + X25519MlKem768Draft00PublicKey::decode(bytes).map(Self::X25519MlKem768Draft00) } - Algorithm::Kyber1024 => bytes - .try_into() - .map_err(|_| Error::InvalidPublicKey) - .map(Self::Kyber1024), + Algorithm::MlKem1024 => MlKem1024PublicKey::try_from(bytes) + .ok() + .and_then(kyber1024::validate_public_key) + .map(Self::MlKem1024) + .ok_or(Error::InvalidPublicKey), _ => Err(Error::UnsupportedAlgorithm), } } @@ -270,14 +431,14 @@ impl Ss { match self { Ss::X25519(k) => k.0.to_vec(), Ss::P256(k) => k.0.to_vec(), - Ss::Kyber512(k) => k.as_ref().to_vec(), - Ss::Kyber768(k) => k.as_ref().to_vec(), - Ss::Kyber768X25519(kk, xk) => { + Ss::MlKem512(k) => k.as_ref().to_vec(), + Ss::MlKem768(k) => k.as_ref().to_vec(), + Ss::X25519MlKem768Draft00(kk, xk) => { let mut out = xk.0.to_vec(); out.extend_from_slice(kk.as_ref()); out } - Ss::Kyber1024(k) => k.as_ref().to_vec(), + Ss::MlKem1024(k) => k.as_ref().to_vec(), } } } @@ -288,14 +449,14 @@ impl Ct { match self { Ct::X25519(k) => k.0.to_vec(), Ct::P256(k) => k.0.to_vec(), - Ct::Kyber512(k) => k.as_ref().to_vec(), - Ct::Kyber768(k) => k.as_ref().to_vec(), - Ct::Kyber768X25519(kk, xk) => { + Ct::MlKem512(k) => k.as_ref().to_vec(), + Ct::MlKem768(k) => k.as_ref().to_vec(), + Ct::X25519MlKem768Draft00(kk, xk) => { let mut out = xk.0.to_vec(); out.extend_from_slice(kk.as_ref()); out } - Ct::Kyber1024(k) => k.as_ref().to_vec(), + Ct::MlKem1024(k) => k.as_ref().to_vec(), } } @@ -310,23 +471,27 @@ impl Ct { .try_into() .map_err(|_| Error::InvalidCiphertext) .map(Self::P256), - Algorithm::Kyber768 => bytes + Algorithm::MlKem512 => bytes .try_into() .map_err(|_| Error::InvalidCiphertext) - .map(Self::Kyber768), - Algorithm::Kyber768X25519 => { - let key: [u8; kyber::kyber768::CPA_PKE_CIPHERTEXT_SIZE_768 + 32] = + .map(Self::MlKem512), + Algorithm::MlKem768 => bytes + .try_into() + .map_err(|_| Error::InvalidCiphertext) + .map(Self::MlKem768), + Algorithm::X25519MlKem768Draft00 => { + let key: [u8; kyber768::CPA_PKE_CIPHERTEXT_SIZE_768 + 32] = bytes.try_into().map_err(|_| Error::InvalidCiphertext)?; - let (kct, xct) = key.split_at(kyber::kyber768::CPA_PKE_CIPHERTEXT_SIZE_768); - Ok(Self::Kyber768X25519( + let (kct, xct) = key.split_at(kyber768::CPA_PKE_CIPHERTEXT_SIZE_768); + Ok(Self::X25519MlKem768Draft00( kct.try_into().map_err(|_| Error::InvalidCiphertext)?, xct.try_into().map_err(|_| Error::InvalidCiphertext)?, )) } - Algorithm::Kyber1024 => bytes + Algorithm::MlKem1024 => bytes .try_into() .map_err(|_| Error::InvalidCiphertext) - .map(Self::Kyber1024), + .map(Self::MlKem1024), _ => Err(Error::UnsupportedAlgorithm), } } @@ -345,15 +510,17 @@ pub fn secret_to_public(alg: Algorithm, sk: impl AsRef<[u8]>) -> Result, fn gen_kyber768( rng: &mut (impl CryptoRng + Rng), -) -> Result<(Kyber768PrivateKey, Kyber768PublicKey), Error> { - let mut seed = [0; kyber::KEY_GENERATION_SEED_SIZE]; - rng.try_fill_bytes(&mut seed).map_err(|_| Error::KeyGen)?; - - let KyberKeyPair { sk, pk } = kyber768_generate_keypair_derand(seed); - +) -> Result<(MlKem768PrivateKey, MlKem768PublicKey), Error> { + let MlKemKeyPair { sk, pk } = kyber768::generate_key_pair(random_array(rng)?); Ok((sk, pk)) } +fn random_array(rng: &mut (impl CryptoRng + Rng)) -> Result<[u8; L], Error> { + let mut seed = [0; L]; + rng.try_fill_bytes(&mut seed).map_err(|_| Error::KeyGen)?; + Ok(seed) +} + /// Generate a key pair for the [`Algorithm`] using the provided rng. /// /// The function returns a fresh key or a [`Error::KeyGen`] error if @@ -370,18 +537,28 @@ pub fn key_gen( Algorithm::Secp256r1 => ecdh::p256_key_gen(rng) .map_err(|e| e.into()) .map(|(private, public)| (PrivateKey::P256(private), PublicKey::P256(public))), - Algorithm::Kyber768 => gen_kyber768(rng) - .map(|(private, public)| (PrivateKey::Kyber768(private), PublicKey::Kyber768(public))), - Algorithm::Kyber768X25519 => { + Algorithm::MlKem512 => { + let MlKemKeyPair { sk, pk } = kyber512::generate_key_pair(random_array(rng)?); + Ok((PrivateKey::MlKem512(sk), PublicKey::MlKem512(pk))) + } + Algorithm::MlKem768 => { + let MlKemKeyPair { sk, pk } = kyber768::generate_key_pair(random_array(rng)?); + Ok((PrivateKey::MlKem768(sk), PublicKey::MlKem768(pk))) + } + Algorithm::MlKem1024 => { + let MlKemKeyPair { sk, pk } = kyber1024::generate_key_pair(random_array(rng)?); + Ok((PrivateKey::MlKem1024(sk), PublicKey::MlKem1024(pk))) + } + Algorithm::X25519MlKem768Draft00 => { let (kyber_private, kyber_public) = gen_kyber768(rng)?; let (x25519_private, x25519_public) = ecdh::x25519_key_gen(rng)?; Ok(( - PrivateKey::Kyber768X25519(Kyber768X25519PrivateKey { - kyber: kyber_private, + PrivateKey::X25519MlKem768Draft00(X25519MlKem768Draft00PrivateKey { + mlkem: kyber_private, x25519: x25519_private, }), - PublicKey::Kyber768X25519(Kyber768X25519PublicKey { - kyber: kyber_public, + PublicKey::X25519MlKem768Draft00(X25519MlKem768Draft00PublicKey { + mlkem: kyber_public, x25519: x25519_public, }), )) @@ -390,50 +567,6 @@ pub fn key_gen( } } -/// Encapsulate a shared secret to the provided `pk` and return the `(Key, Enc)` tuple. -pub fn encapsulate(pk: &PublicKey, rng: &mut (impl CryptoRng + Rng)) -> Result<(Ss, Ct), Error> { - match pk { - PublicKey::X25519(pk) => { - let (new_sk, new_pk) = ecdh::x25519_key_gen(rng)?; - let gxy = x25519::derive(pk, &new_sk)?; - Ok((Ss::X25519(gxy), Ct::X25519(new_pk))) - } - PublicKey::P256(pk) => { - let (new_sk, new_pk) = ecdh::p256_key_gen(rng)?; - let gxy = p256_derive(pk, &new_sk)?; - Ok((Ss::P256(gxy), Ct::P256(new_pk))) - } - - PublicKey::Kyber512(pk) => { - let seed = kyber_rand(rng)?; - let (ct, ss) = kyber::kyber512::encapsulate_512(pk, seed); - Ok((Ss::Kyber512(ss), Ct::Kyber512(ct))) - } - - PublicKey::Kyber768(pk) => { - let seed = kyber_rand(rng)?; - let (ct, ss) = kyber::kyber768::encapsulate_768(pk, seed); - Ok((Ss::Kyber768(ss), Ct::Kyber768(ct))) - } - - PublicKey::Kyber768X25519(Kyber768X25519PublicKey { - kyber: kpk, - x25519: xpk, - }) => { - let seed = kyber_rand(rng)?; - let (kyber_ct, kyber_ss) = kyber::kyber768::encapsulate_768(kpk, seed); - let (x_sk, x_pk) = ecdh::x25519_key_gen(rng)?; - let x_ss = x25519::derive(xpk, &x_sk)?; - - Ok(( - Ss::Kyber768X25519(kyber_ss, x_ss), - Ct::Kyber768X25519(kyber_ct, x_pk), - )) - } - _ => Err(Error::UnsupportedAlgorithm), - } -} - fn kyber_rand( rng: &mut (impl CryptoRng + Rng), ) -> Result<[u8; kyber::constants::SHARED_SECRET_SIZE], Error> { @@ -441,71 +574,3 @@ fn kyber_rand( rng.try_fill_bytes(&mut seed).map_err(|_| Error::KeyGen)?; Ok(seed) } - -/// Decapsulate the shared secret in `ct` using the private key `sk`. -pub fn decapsulate(ct: &Ct, sk: &PrivateKey) -> Result { - match ct { - Ct::X25519(ct) => { - let sk = if let PrivateKey::X25519(k) = sk { - k - } else { - return Err(Error::InvalidPrivateKey); - }; - x25519::derive(ct, sk).map_err(|e| e.into()).map(Ss::X25519) - } - Ct::P256(ct) => { - let sk = if let PrivateKey::P256(k) = sk { - k - } else { - return Err(Error::InvalidPrivateKey); - }; - p256_derive(ct, sk).map_err(|e| e.into()).map(Ss::P256) - } - Ct::Kyber512(ct) => { - let sk = if let PrivateKey::Kyber512(k) = sk { - k - } else { - return Err(Error::InvalidPrivateKey); - }; - let ss = kyber::kyber512::decapsulate_512(sk, ct); - - Ok(Ss::Kyber768(ss)) - } - Ct::Kyber768(ct) => { - let sk = if let PrivateKey::Kyber768(k) = sk { - k - } else { - return Err(Error::InvalidPrivateKey); - }; - let ss = kyber::kyber768::decapsulate_768(sk, ct); - - Ok(Ss::Kyber768(ss)) - } - Ct::Kyber768X25519(kct, xct) => { - let (ksk, xsk) = if let PrivateKey::Kyber768X25519(Kyber768X25519PrivateKey { - kyber: kk, - x25519: xk, - }) = sk - { - (kk, xk) - } else { - return Err(Error::InvalidPrivateKey); - }; - let kss = kyber::kyber768::decapsulate_768(ksk, kct); - let xss = x25519::derive(xct, xsk)?; - - Ok(Ss::Kyber768X25519(kss, xss)) - } - - Ct::Kyber1024(ct) => { - let sk = if let PrivateKey::Kyber1024(k) = sk { - k - } else { - return Err(Error::InvalidPrivateKey); - }; - let ss = kyber::kyber1024::decapsulate_1024(sk, ct); - - Ok(Ss::Kyber1024(ss)) - } - } -} diff --git a/src/kem/kyber.rs b/src/kem/kyber.rs index 0e984dc38..c8b46d4e5 100644 --- a/src/kem/kyber.rs +++ b/src/kem/kyber.rs @@ -26,12 +26,14 @@ pub mod kyber1024; pub mod kyber512; pub mod kyber768; -pub use types::{KyberCiphertext, KyberKeyPair, KyberPrivateKey, KyberPublicKey}; +pub use types::{MlKemCiphertext, MlKemKeyPair, MlKemPrivateKey, MlKemPublicKey}; // TODO: We should make this an actual type as opposed to alias so we can enforce // some checks at the type level. This is being tracked in: // https://github.com/cryspen/libcrux/issues/123 -pub type KyberSharedSecret = [u8; constants::SHARED_SECRET_SIZE]; +pub type MlKemSharedSecret = [u8; constants::SHARED_SECRET_SIZE]; + +use crate::kem::kyber::ind_cpa::{deserialize_public_key, serialize_public_key}; use self::{ constant_time_ops::{ @@ -66,6 +68,24 @@ fn serialize_kem_secret_key( out } +pub(super) fn validate_public_key< + const K: usize, + const RANKED_BYTES_PER_RING_ELEMENT: usize, + const PUBLIC_KEY_SIZE: usize, +>( + public_key: &[u8; PUBLIC_KEY_SIZE], +) -> bool { + // public_key == + let pk = deserialize_public_key::(public_key); + let public_key_serialized = serialize_public_key::< + K, + RANKED_BYTES_PER_RING_ELEMENT, + PUBLIC_KEY_SIZE, + >(pk, &public_key[RANKED_BYTES_PER_RING_ELEMENT..]); + + public_key == &public_key_serialized +} + pub(super) fn generate_keypair< const K: usize, const CPA_PRIVATE_KEY_SIZE: usize, @@ -76,7 +96,7 @@ pub(super) fn generate_keypair< const ETA1_RANDOMNESS_SIZE: usize, >( randomness: [u8; KEY_GENERATION_SEED_SIZE], -) -> KyberKeyPair { +) -> MlKemKeyPair { let ind_cpa_keypair_randomness = &randomness[0..CPA_PKE_KEY_GENERATION_SEED_SIZE]; let implicit_rejection_value = &randomness[CPA_PKE_KEY_GENERATION_SEED_SIZE..]; @@ -91,10 +111,10 @@ pub(super) fn generate_keypair< let secret_key_serialized = serialize_kem_secret_key(&ind_cpa_private_key, &public_key, implicit_rejection_value); - let private_key: KyberPrivateKey = - KyberPrivateKey::from(secret_key_serialized); + let private_key: MlKemPrivateKey = + MlKemPrivateKey::from(secret_key_serialized); - KyberKeyPair::from(private_key, public_key.into()) + MlKemKeyPair::from(private_key, public_key.into()) } pub(super) fn encapsulate< @@ -112,9 +132,9 @@ pub(super) fn encapsulate< const ETA2: usize, const ETA2_RANDOMNESS_SIZE: usize, >( - public_key: &KyberPublicKey, + public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], -) -> (KyberCiphertext, KyberSharedSecret) { +) -> (MlKemCiphertext, MlKemSharedSecret) { let mut to_hash: [u8; 2 * H_DIGEST_SIZE] = into_padded_array(&randomness); to_hash[H_DIGEST_SIZE..].copy_from_slice(&H(public_key.as_slice())); @@ -161,9 +181,9 @@ pub(super) fn decapsulate< const ETA2_RANDOMNESS_SIZE: usize, const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize, >( - secret_key: &KyberPrivateKey, - ciphertext: &KyberCiphertext, -) -> KyberSharedSecret { + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, +) -> MlKemSharedSecret { let (ind_cpa_secret_key, secret_key) = secret_key.split_at(CPA_SECRET_KEY_SIZE); let (ind_cpa_public_key, secret_key) = secret_key.split_at(PUBLIC_KEY_SIZE); let (ind_cpa_public_key_hash, implicit_rejection_value) = secret_key.split_at(H_DIGEST_SIZE); diff --git a/src/kem/kyber/constant_time_ops.rs b/src/kem/kyber/constant_time_ops.rs index 649244d86..5577493c4 100644 --- a/src/kem/kyber/constant_time_ops.rs +++ b/src/kem/kyber/constant_time_ops.rs @@ -1,6 +1,6 @@ use crate::{hax_utils::hax_debug_assert, kem::kyber::constants::SHARED_SECRET_SIZE}; -// TODO: Examine the output that LLVM produces for this code to ensure +// Examine the output that LLVM produces for this code from time to time to ensure // operations are not being optimized away/constant-timedness is not being broken. /// Return 1 if `value` is not zero and 0 otherwise. @@ -8,7 +8,7 @@ use crate::{hax_utils::hax_debug_assert, kem::kyber::constants::SHARED_SECRET_SI hax_lib::implies(value == 0, || result == 0) && hax_lib::implies(value != 0, || result == 1) ))] -#[inline] +#[inline(never)] // Don't inline this to avoid that the compiler optimizes this out. fn is_non_zero(value: u8) -> u8 { let value = value as u16; diff --git a/src/kem/kyber/ind_cpa.rs b/src/kem/kyber/ind_cpa.rs index 0bddbce54..215fda7aa 100644 --- a/src/kem/kyber/ind_cpa.rs +++ b/src/kem/kyber/ind_cpa.rs @@ -27,7 +27,7 @@ pub(super) fn into_padded_array(slice: &[u8]) -> [u8; LEN] { /// Concatenate `t` and `ρ` into the public key. #[inline(always)] -fn serialize_public_key< +pub(super) fn serialize_public_key< const K: usize, const RANKED_BYTES_PER_RING_ELEMENT: usize, const PUBLIC_KEY_SIZE: usize, @@ -45,7 +45,9 @@ fn serialize_public_key< /// Call [`deserialize_to_uncompressed_ring_element`] on each ring element. #[inline(always)] -fn deserialize_public_key(public_key: &[u8]) -> [PolynomialRingElement; K] { +pub(super) fn deserialize_public_key( + public_key: &[u8], +) -> [PolynomialRingElement; K] { let mut t_as_ntt = [PolynomialRingElement::ZERO; K]; cloop! { for (i, t_as_ntt_bytes) in public_key diff --git a/src/kem/kyber/kyber1024.rs b/src/kem/kyber/kyber1024.rs index a2639c984..ef6b81876 100644 --- a/src/kem/kyber/kyber1024.rs +++ b/src/kem/kyber/kyber1024.rs @@ -34,15 +34,31 @@ const ETA2_RANDOMNESS_SIZE: usize = ETA2 * 64; const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = SHARED_SECRET_SIZE + CPA_PKE_CIPHERTEXT_SIZE_1024; // Kyber 1024 types -pub type Kyber1024Ciphertext = KyberCiphertext; -pub type Kyber1024PrivateKey = KyberPrivateKey; -pub type Kyber1024PublicKey = KyberPublicKey; +pub type MlKem1024Ciphertext = MlKemCiphertext; +pub type MlKem1024PrivateKey = MlKemPrivateKey; +pub type MlKem1024PublicKey = MlKemPublicKey; -/// Generate Kyber 1024 Key Pair -pub fn generate_key_pair_1024( +/// Validate a public key. +/// +/// Returns `Some(public_key)` if valid, and `None` otherwise. +pub(crate) fn validate_public_key(public_key: MlKem1024PublicKey) -> Option { + if super::validate_public_key::< + RANK_1024, + RANKED_BYTES_PER_RING_ELEMENT_1024, + CPA_PKE_PUBLIC_KEY_SIZE_1024, + >(&public_key.value) + { + Some(public_key) + } else { + None + } +} + +/// Generate ML-KEM 1024 Key Pair +pub fn generate_key_pair( randomness: [u8; KEY_GENERATION_SEED_SIZE], -) -> KyberKeyPair { - generate_keypair::< +) -> MlKemKeyPair { + super::generate_keypair::< RANK_1024, CPA_PKE_SECRET_KEY_SIZE_1024, SECRET_KEY_SIZE_1024, @@ -53,15 +69,15 @@ pub fn generate_key_pair_1024( >(randomness) } -/// Encapsulate Kyber 1024 -pub fn encapsulate_1024( - public_key: &KyberPublicKey, +/// Encapsulate ML-KEM 1024 +pub fn encapsulate( + public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], ) -> ( - KyberCiphertext, - KyberSharedSecret, + MlKemCiphertext, + MlKemSharedSecret, ) { - encapsulate::< + super::encapsulate::< RANK_1024, CPA_PKE_CIPHERTEXT_SIZE_1024, CPA_PKE_PUBLIC_KEY_SIZE_1024, @@ -78,12 +94,12 @@ pub fn encapsulate_1024( >(public_key, randomness) } -/// Decapsulate Kyber 1024 -pub fn decapsulate_1024( - secret_key: &KyberPrivateKey, - ciphertext: &KyberCiphertext, +/// Decapsulate ML-KEM 1024 +pub fn decapsulate( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, ) -> [u8; SHARED_SECRET_SIZE] { - decapsulate::< + super::decapsulate::< RANK_1024, SECRET_KEY_SIZE_1024, CPA_PKE_SECRET_KEY_SIZE_1024, diff --git a/src/kem/kyber/kyber512.rs b/src/kem/kyber/kyber512.rs index 9440c77a4..9b309a5dd 100644 --- a/src/kem/kyber/kyber512.rs +++ b/src/kem/kyber/kyber512.rs @@ -32,14 +32,30 @@ const ETA2_RANDOMNESS_SIZE: usize = ETA2 * 64; const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = SHARED_SECRET_SIZE + CPA_PKE_CIPHERTEXT_SIZE_512; // Kyber 512 types -pub type Kyber512Ciphertext = KyberCiphertext; -pub type Kyber512PrivateKey = KyberPrivateKey; -pub type Kyber512PublicKey = KyberPublicKey; +pub type MlKem512Ciphertext = MlKemCiphertext; +pub type MlKem512PrivateKey = MlKemPrivateKey; +pub type MlKem512PublicKey = MlKemPublicKey; -/// Generate Kyber 512 Key Pair -pub fn generate_key_pair_512( +/// Validate a public key. +/// +/// Returns `Some(public_key)` if valid, and `None` otherwise. +pub(crate) fn validate_public_key(public_key: MlKem512PublicKey) -> Option { + if super::validate_public_key::< + RANK_512, + RANKED_BYTES_PER_RING_ELEMENT_512, + CPA_PKE_PUBLIC_KEY_SIZE_512, + >(&public_key.value) + { + Some(public_key) + } else { + None + } +} + +/// Generate ML-KEM 512 Key Pair +pub fn generate_key_pair( randomness: [u8; KEY_GENERATION_SEED_SIZE], -) -> KyberKeyPair { +) -> MlKemKeyPair { generate_keypair::< RANK_512, CPA_PKE_SECRET_KEY_SIZE_512, @@ -51,15 +67,15 @@ pub fn generate_key_pair_512( >(randomness) } -/// Encapsulate Kyber 512 -pub fn encapsulate_512( - public_key: &KyberPublicKey, +/// Encapsulate ML-KEM 512 +pub fn encapsulate( + public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], ) -> ( - KyberCiphertext, - KyberSharedSecret, + MlKemCiphertext, + MlKemSharedSecret, ) { - encapsulate::< + super::encapsulate::< RANK_512, CPA_PKE_CIPHERTEXT_SIZE_512, CPA_PKE_PUBLIC_KEY_SIZE_512, @@ -76,12 +92,12 @@ pub fn encapsulate_512( >(public_key, randomness) } -/// Decapsulate Kyber 512 -pub fn decapsulate_512( - secret_key: &KyberPrivateKey, - ciphertext: &KyberCiphertext, +/// Decapsulate ML-KEM 512 +pub fn decapsulate( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, ) -> [u8; SHARED_SECRET_SIZE] { - decapsulate::< + super::decapsulate::< RANK_512, SECRET_KEY_SIZE_512, CPA_PKE_SECRET_KEY_SIZE_512, diff --git a/src/kem/kyber/kyber768.rs b/src/kem/kyber/kyber768.rs index 773fb5a63..9d35dbb8c 100644 --- a/src/kem/kyber/kyber768.rs +++ b/src/kem/kyber/kyber768.rs @@ -33,14 +33,30 @@ const ETA2_RANDOMNESS_SIZE: usize = ETA2 * 64; const IMPLICIT_REJECTION_HASH_INPUT_SIZE: usize = SHARED_SECRET_SIZE + CPA_PKE_CIPHERTEXT_SIZE_768; // Kyber 768 types -pub type Kyber768Ciphertext = KyberCiphertext; -pub type Kyber768PrivateKey = KyberPrivateKey; -pub type Kyber768PublicKey = KyberPublicKey; +pub type MlKem768Ciphertext = MlKemCiphertext; +pub type MlKem768PrivateKey = MlKemPrivateKey; +pub type MlKem768PublicKey = MlKemPublicKey; -/// Generate Kyber 768 Key Pair -pub fn generate_key_pair_768( +/// Validate a public key. +/// +/// Returns `Some(public_key)` if valid, and `None` otherwise. +pub(crate) fn validate_public_key(public_key: MlKem768PublicKey) -> Option { + if super::validate_public_key::< + RANK_768, + RANKED_BYTES_PER_RING_ELEMENT_768, + CPA_PKE_PUBLIC_KEY_SIZE_768, + >(&public_key.value) + { + Some(public_key) + } else { + None + } +} + +/// Generate ML-KEM 768 Key Pair +pub fn generate_key_pair( randomness: [u8; KEY_GENERATION_SEED_SIZE], -) -> KyberKeyPair { +) -> MlKemKeyPair { generate_keypair::< RANK_768, CPA_PKE_SECRET_KEY_SIZE_768, @@ -52,15 +68,15 @@ pub fn generate_key_pair_768( >(randomness) } -/// Encapsulate Kyber 768 -pub fn encapsulate_768( - public_key: &KyberPublicKey, +/// Encapsulate ML-KEM 768 +pub fn encapsulate( + public_key: &MlKemPublicKey, randomness: [u8; SHARED_SECRET_SIZE], ) -> ( - KyberCiphertext, - KyberSharedSecret, + MlKemCiphertext, + MlKemSharedSecret, ) { - encapsulate::< + super::encapsulate::< RANK_768, CPA_PKE_CIPHERTEXT_SIZE_768, CPA_PKE_PUBLIC_KEY_SIZE_768, @@ -77,12 +93,12 @@ pub fn encapsulate_768( >(public_key, randomness) } -/// Decapsulate Kyber 768 -pub fn decapsulate_768( - secret_key: &KyberPrivateKey, - ciphertext: &KyberCiphertext, +/// Decapsulate ML-KEM 768 +pub fn decapsulate( + secret_key: &MlKemPrivateKey, + ciphertext: &MlKemCiphertext, ) -> [u8; SHARED_SECRET_SIZE] { - decapsulate::< + super::decapsulate::< RANK_768, SECRET_KEY_SIZE_768, CPA_PKE_SECRET_KEY_SIZE_768, @@ -101,3 +117,21 @@ pub fn decapsulate_768( IMPLICIT_REJECTION_HASH_INPUT_SIZE, >(secret_key, ciphertext) } + +#[cfg(test)] +mod tests { + use rand_core::{OsRng, RngCore}; + + use crate::kem::kyber::kyber768::validate_public_key; + + use super::{kyber768::generate_key_pair, KEY_GENERATION_SEED_SIZE}; + + #[test] + fn pk_validation() { + let mut randomness = [0u8; KEY_GENERATION_SEED_SIZE]; + OsRng.fill_bytes(&mut randomness); + + let key_pair = generate_key_pair(randomness); + assert!(validate_public_key(key_pair.pk).is_some()); + } +} diff --git a/src/kem/kyber/types.rs b/src/kem/kyber/types.rs index d05609359..0179bcd07 100644 --- a/src/kem/kyber/types.rs +++ b/src/kem/kyber/types.rs @@ -92,28 +92,28 @@ macro_rules! impl_index_impls_for_generic_struct { }; } -impl_generic_struct!(KyberCiphertext); -impl_generic_struct!(KyberPrivateKey); -impl_generic_struct!(KyberPublicKey); +impl_generic_struct!(MlKemCiphertext); +impl_generic_struct!(MlKemPrivateKey); +impl_generic_struct!(MlKemPublicKey); // These traits are used only in `ind_cpa` for kyber cipher text. mod index_impls { use super::*; - impl_index_impls_for_generic_struct!(KyberCiphertext); - impl_index_impls_for_generic_struct!(KyberPrivateKey); - impl_index_impls_for_generic_struct!(KyberPublicKey); + impl_index_impls_for_generic_struct!(MlKemCiphertext); + impl_index_impls_for_generic_struct!(MlKemPrivateKey); + impl_index_impls_for_generic_struct!(MlKemPublicKey); } -/// A Kyber key pair -pub struct KyberKeyPair { - pub(crate) sk: KyberPrivateKey, - pub(crate) pk: KyberPublicKey, +/// An ML-KEM key pair +pub struct MlKemKeyPair { + pub(crate) sk: MlKemPrivateKey, + pub(crate) pk: MlKemPublicKey, } impl - KyberKeyPair + MlKemKeyPair { - /// Creates a new [`KyberKeyPair`]. + /// Creates a new [`MlKemKeyPair`]. pub fn new(sk: [u8; PRIVATE_KEY_SIZE], pk: [u8; PUBLIC_KEY_SIZE]) -> Self { Self { sk: sk.into(), @@ -122,17 +122,17 @@ impl } pub fn from( - sk: KyberPrivateKey, - pk: KyberPublicKey, + sk: MlKemPrivateKey, + pk: MlKemPublicKey, ) -> Self { Self { sk, pk } } - pub fn public_key(&self) -> &KyberPublicKey { + pub fn public_key(&self) -> &MlKemPublicKey { &self.pk } - pub fn private_key(&self) -> &KyberPrivateKey { + pub fn private_key(&self) -> &MlKemPrivateKey { &self.sk } diff --git a/src/signature.rs b/src/signature.rs index 0dde6f2be..bd48e38f0 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -86,7 +86,7 @@ pub mod rsa_pss { use super::{DigestAlgorithm, Error}; - /// A [`Algorithm::RsaPss`] Signature + /// A [`Algorithm::RsaPss`](super::Algorithm::RsaPss) Signature #[derive(Debug, Clone, PartialEq, Eq)] pub struct RsaPssSignature { pub(super) value: Vec, @@ -121,7 +121,7 @@ pub mod rsa_pss { } } - /// A [`Algorithm::RsaPss`] public key. + /// A [`Algorithm::RsaPss`](super::Algorithm::RsaPss) public key. #[derive(Debug, Clone, PartialEq, Eq)] pub struct RsaPssPublicKey { n: Vec, @@ -211,7 +211,7 @@ pub mod rsa_pss { /// An RSA-PSS private key. /// The private key holds a [`RsaPssPublicKey`] with the public modulus. - /// A [`Algorithm::RsaPss`] private key. + /// A [`Algorithm::RsaPss`](super::Algorithm::RsaPss) private key. pub struct RsaPssPrivateKey<'a> { pk: &'a RsaPssPublicKey, d: Vec, diff --git a/tests/kyber.rs b/tests/kyber.rs index 5c33dc7c5..7f5bfa1d1 100644 --- a/tests/kyber.rs +++ b/tests/kyber.rs @@ -23,9 +23,8 @@ macro_rules! impl_consistency { let mut rng = OsRng; if let Ok((secret_key, public_key)) = kem::key_gen($alg, &mut rng) { - if let Ok((shared_secret, ciphertext)) = kem::encapsulate(&public_key, &mut rng) { - let shared_secret_decapsulated = - kem::decapsulate(&ciphertext, &secret_key).unwrap(); + if let Ok((shared_secret, ciphertext)) = public_key.encapsulate(&mut rng) { + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); assert_eq!(shared_secret.encode(), shared_secret_decapsulated.encode()); } } @@ -65,10 +64,9 @@ macro_rules! impl_modified_ciphertext { let mut rng = OsRng; if let Ok((secret_key, public_key)) = kem::key_gen($alg, &mut rng) { - if let Ok((shared_secret, ciphertext)) = kem::encapsulate(&public_key, &mut rng) { + if let Ok((shared_secret, ciphertext)) = public_key.encapsulate(&mut rng) { let ciphertext = modify_ciphertext($alg, &mut rng, ciphertext); - let shared_secret_decapsulated = - kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); assert_ne!(shared_secret.encode(), shared_secret_decapsulated.encode()); } @@ -130,15 +128,13 @@ macro_rules! impl_modified_secret_key { let mut rng = OsRng; if let Ok((secret_key, public_key)) = kem::key_gen($alg, &mut rng) { - if let Ok((shared_secret, ciphertext)) = kem::encapsulate(&public_key, &mut rng) { + if let Ok((shared_secret, ciphertext)) = public_key.encapsulate(&mut rng) { let secret_key = modify_secret_key($alg, &mut rng, secret_key, false); - let shared_secret_decapsulated = - kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); assert_ne!(shared_secret.encode(), shared_secret_decapsulated.encode()); let secret_key = modify_secret_key($alg, &mut rng, secret_key, true); - let shared_secret_decapsulated = - kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); assert_eq!( shared_secret_decapsulated.encode(), @@ -165,14 +161,12 @@ macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { let mut rng = OsRng; if let Ok((secret_key, public_key)) = kem::key_gen($alg, &mut rng) { - if let Ok((_, ciphertext)) = kem::encapsulate(&public_key, &mut rng) { + if let Ok((_, ciphertext)) = public_key.encapsulate(&mut rng) { let ciphertext = modify_ciphertext($alg, &mut rng, ciphertext); - let shared_secret_decapsulated = - kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let shared_secret_decapsulated = ciphertext.decapsulate(&secret_key).unwrap(); let secret_key = modify_secret_key($alg, &mut rng, secret_key, true); - let shared_secret_decapsulated_1 = - kem::decapsulate(&ciphertext, &secret_key).unwrap(); + let shared_secret_decapsulated_1 = ciphertext.decapsulate(&secret_key).unwrap(); assert_ne!( shared_secret_decapsulated.encode(), @@ -193,27 +187,27 @@ macro_rules! impl_modified_ciphertext_and_implicit_rejection_value { }; } -impl_consistency!(consistency_512, Algorithm::Kyber512); -impl_consistency!(consistency_768, Algorithm::Kyber768); -impl_consistency!(consistency_1024, Algorithm::Kyber1024); +impl_consistency!(consistency_512, Algorithm::MlKem512); +impl_consistency!(consistency_768, Algorithm::MlKem768); +impl_consistency!(consistency_1024, Algorithm::MlKem1024); -impl_modified_ciphertext!(modified_ciphertext_512, Algorithm::Kyber512); -impl_modified_ciphertext!(modified_ciphertext_768, Algorithm::Kyber768); -impl_modified_ciphertext!(modified_ciphertext_1024, Algorithm::Kyber1024); +impl_modified_ciphertext!(modified_ciphertext_512, Algorithm::MlKem512); +impl_modified_ciphertext!(modified_ciphertext_768, Algorithm::MlKem768); +impl_modified_ciphertext!(modified_ciphertext_1024, Algorithm::MlKem1024); -impl_modified_secret_key!(modified_secret_key_512, Algorithm::Kyber512); -impl_modified_secret_key!(modified_secret_key_768, Algorithm::Kyber768); -impl_modified_secret_key!(modified_secret_key_1024, Algorithm::Kyber1024); +impl_modified_secret_key!(modified_secret_key_512, Algorithm::MlKem512); +impl_modified_secret_key!(modified_secret_key_768, Algorithm::MlKem768); +impl_modified_secret_key!(modified_secret_key_1024, Algorithm::MlKem1024); impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_512, - Algorithm::Kyber512 + Algorithm::MlKem512 ); impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_768, - Algorithm::Kyber768 + Algorithm::MlKem768 ); impl_modified_ciphertext_and_implicit_rejection_value!( modified_ciphertext_and_implicit_rejection_value_1024, - Algorithm::Kyber1024 + Algorithm::MlKem1024 ); diff --git a/tests/kyber_nistkats.rs b/tests/kyber_nistkats.rs index 7631e43b0..307ec2d28 100644 --- a/tests/kyber_nistkats.rs +++ b/tests/kyber_nistkats.rs @@ -69,21 +69,21 @@ macro_rules! impl_nist_known_answer_tests { impl_nist_known_answer_tests!( kyber512_nist_known_answer_tests, 512, - kem::kyber512_generate_keypair_derand, - kem::kyber512_encapsulate_derand, - kem::kyber512_decapsulate_derand + kem::deterministic::kyber512_generate_keypair_derand, + kem::deterministic::kyber512_encapsulate_derand, + kem::deterministic::kyber512_decapsulate_derand ); impl_nist_known_answer_tests!( kyber768_nist_known_answer_tests, 768, - kem::kyber768_generate_keypair_derand, - kem::kyber768_encapsulate_derand, - kem::kyber768_decapsulate_derand + kem::deterministic::kyber768_generate_keypair_derand, + kem::deterministic::kyber768_encapsulate_derand, + kem::deterministic::kyber768_decapsulate_derand ); impl_nist_known_answer_tests!( kyber1024_nist_known_answer_tests, 1024, - kem::kyber1024_generate_keypair_derand, - kem::kyber1024_encapsulate_derand, - kem::kyber1024_decapsulate_derand + kem::deterministic::kyber1024_generate_keypair_derand, + kem::deterministic::kyber1024_encapsulate_derand, + kem::deterministic::kyber1024_decapsulate_derand ); diff --git a/tests/xkyber_kem.rs b/tests/xkyber_kem.rs index 618b36f99..1fec45f1c 100644 --- a/tests/xkyber_kem.rs +++ b/tests/xkyber_kem.rs @@ -27,10 +27,10 @@ fn xkyber_selftest() { #[cfg(target_arch = "wasm32")] let mut rng = OsRng; - let (skr, pkr) = kem::key_gen(Algorithm::Kyber768X25519, &mut rng).unwrap(); + let (skr, pkr) = kem::key_gen(Algorithm::X25519MlKem768Draft00, &mut rng).unwrap(); - let (ss, ct) = kem::encapsulate(&pkr, &mut rng).unwrap(); - let rss = kem::decapsulate(&ct, &skr).unwrap(); + let (ss, ct) = pkr.encapsulate(&mut rng).unwrap(); + let rss = ct.decapsulate(&skr).unwrap(); assert_eq!(rss.encode(), ss.encode()); }