Skip to content

Commit

Permalink
Merge pull request #189 from cryspen/franziskus/mlkem_pk_validation
Browse files Browse the repository at this point in the history
mlkem pk validation
  • Loading branch information
W95Psp authored Jan 29, 2024
2 parents 7d3beb6 + de59648 commit 4f8e208
Show file tree
Hide file tree
Showing 44 changed files with 1,014 additions and 886 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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.
3 changes: 2 additions & 1 deletion benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions benchmarks/benches/boringssl/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
30 changes: 15 additions & 15 deletions benchmarks/benches/kyber768.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
})
});

Expand All @@ -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,
)
Expand All @@ -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,
)
Expand All @@ -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,
)
Expand Down Expand Up @@ -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,
)
Expand Down
4 changes: 2 additions & 2 deletions examples/kyber768_encapsulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
2 changes: 1 addition & 1 deletion examples/kyber768_generate_keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
7 changes: 7 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ rand = { version = "0.8" }

[dependencies.libcrux]
path = "../"
features = ["tests"]

[[bin]]
name = "kyber768_implicit_rejection"
Expand All @@ -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
44 changes: 44 additions & 0 deletions fuzz/fuzz_targets/fuzz_rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use libcrux::digest::shake128;
use rand::CryptoRng;

use rand;

use rand::RngCore;

pub(crate) struct FuzzRng {
pub(crate) data: Vec<u8>,
}

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 {}
73 changes: 73 additions & 0 deletions fuzz/fuzz_targets/implicit_rejection_util.rs
Original file line number Diff line number Diff line change
@@ -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)
}
Loading

0 comments on commit 4f8e208

Please sign in to comment.