criterion::criterion_main!(keyed_hash::benches, aead::benches, kem::benches); fn benchid(base: KvPairs, last: KvPairs) -> String { format!("{base},{last}") } #[derive(Clone, Copy, Debug)] struct KvPair<'a>(&'a str, &'a str); impl std::fmt::Display for KvPair<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{k}={v}", k = self.0, v = self.1) } } #[derive(Clone, Copy, Debug)] struct KvPairs<'a>(&'a [KvPair<'a>]); impl std::fmt::Display for KvPairs<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.0.len() { 0 => Ok(()), 1 => write!(f, "{}", &self.0[0]), _ => { let mut delim = ""; for pair in self.0 { write!(f, "{delim}{pair}")?; delim = ","; } Ok(()) } } } } mod kem { criterion::criterion_group!( benches, bench_kyber512_libcrux, bench_kyber512_oqs, bench_classicmceliece460896_oqs ); use criterion::Criterion; fn bench_classicmceliece460896_oqs(c: &mut Criterion) { template( c, "classicmceliece460896", "oqs", rosenpass_oqs::ClassicMceliece460896, ); } fn bench_kyber512_libcrux(c: &mut Criterion) { template( c, "kyber512", "libcrux", rosenpass_ciphers::subtle::libcrux::kyber512::Kyber512, ); } fn bench_kyber512_oqs(c: &mut Criterion) { template(c, "kyber512", "oqs", rosenpass_oqs::Kyber512); } use rosenpass_cipher_traits::primitives::Kem; fn template< const SK_LEN: usize, const PK_LEN: usize, const CT_LEN: usize, const SHK_LEN: usize, T: Kem, >( c: &mut Criterion, alg_name: &str, impl_name: &str, scheme: T, ) { use super::{benchid, KvPair, KvPairs}; let base = [ KvPair("primitive", "kem"), KvPair("algorithm", alg_name), KvPair("implementation", impl_name), KvPair("length", "-1"), ]; let kem_benchid = |op| benchid(KvPairs(&base), KvPairs(&[KvPair("operation", op)])); c.bench_function(&kem_benchid("keygen"), |bench| { let mut sk = [0; SK_LEN]; let mut pk = [0; PK_LEN]; bench.iter(|| { scheme.keygen(&mut sk, &mut pk).unwrap(); }); }); c.bench_function(&kem_benchid("encaps"), |bench| { let mut sk = [0; SK_LEN]; let mut pk = [0; PK_LEN]; let mut ct = [0; CT_LEN]; let mut shk = [0; SHK_LEN]; scheme.keygen(&mut sk, &mut pk).unwrap(); bench.iter(|| { scheme.encaps(&mut shk, &mut ct, &pk).unwrap(); }); }); c.bench_function(&kem_benchid("decaps"), |bench| { let mut sk = [0; SK_LEN]; let mut pk = [0; PK_LEN]; let mut ct = [0; CT_LEN]; let mut shk = [0; SHK_LEN]; let mut shk2 = [0; SHK_LEN]; scheme.keygen(&mut sk, &mut pk).unwrap(); scheme.encaps(&mut shk, &mut ct, &pk).unwrap(); bench.iter(|| { scheme.decaps(&mut shk2, &sk, &ct).unwrap(); }); }); } } mod aead { criterion::criterion_group!( benches, bench_chachapoly_libcrux, bench_chachapoly_rustcrypto, bench_xchachapoly_rustcrypto, ); use criterion::Criterion; const KEY_LEN: usize = rosenpass_ciphers::Aead::KEY_LEN; const TAG_LEN: usize = rosenpass_ciphers::Aead::TAG_LEN; fn bench_xchachapoly_rustcrypto(c: &mut Criterion) { template( c, "xchacha20poly1305", "rustcrypto", rosenpass_ciphers::subtle::rust_crypto::xchacha20poly1305_ietf::XChaCha20Poly1305, ); } fn bench_chachapoly_rustcrypto(c: &mut Criterion) { template( c, "chacha20poly1305", "rustcrypto", rosenpass_ciphers::subtle::rust_crypto::chacha20poly1305_ietf::ChaCha20Poly1305, ); } fn bench_chachapoly_libcrux(c: &mut Criterion) { template( c, "chacha20poly1305", "libcrux", rosenpass_ciphers::subtle::libcrux::chacha20poly1305_ietf::ChaCha20Poly1305, ); } use rosenpass_cipher_traits::primitives::Aead; fn template>( c: &mut Criterion, alg_name: &str, impl_name: &str, scheme: T, ) { use crate::{benchid, KvPair, KvPairs}; let base = [ KvPair("primitive", "aead"), KvPair("algorithm", alg_name), KvPair("implementation", impl_name), ]; let aead_benchid = |op, len| { benchid( KvPairs(&base), KvPairs(&[KvPair("operation", op), KvPair("length", len)]), ) }; let key = [12; KEY_LEN]; let nonce = [23; NONCE_LEN]; let ad = []; c.bench_function(&aead_benchid("encrypt", "0byte"), |bench| { const DATA_LEN: usize = 0; let ptxt = []; let mut ctxt = [0; DATA_LEN + TAG_LEN]; bench.iter(|| { scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap(); }); }); c.bench_function(&aead_benchid("decrypt", "0byte"), |bench| { const DATA_LEN: usize = 0; let ptxt = []; let mut ctxt = [0; DATA_LEN + TAG_LEN]; let mut ptxt_out = [0u8; DATA_LEN]; scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap(); bench.iter(|| { scheme .decrypt(&mut ptxt_out, &key, &nonce, &ad, &mut ctxt) .unwrap() }) }); c.bench_function(&aead_benchid("encrypt", "32byte"), |bench| { const DATA_LEN: usize = 32; let ptxt = [34u8; DATA_LEN]; let mut ctxt = [0; DATA_LEN + TAG_LEN]; bench.iter(|| { scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap(); }); }); c.bench_function(&aead_benchid("decrypt", "32byte"), |bench| { const DATA_LEN: usize = 32; let ptxt = [34u8; DATA_LEN]; let mut ctxt = [0; DATA_LEN + TAG_LEN]; let mut ptxt_out = [0u8; DATA_LEN]; scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap(); bench.iter(|| { scheme .decrypt(&mut ptxt_out, &key, &nonce, &ad, &mut ctxt) .unwrap() }) }); c.bench_function(&aead_benchid("encrypt", "1024byte"), |bench| { const DATA_LEN: usize = 1024; let ptxt = [34u8; DATA_LEN]; let mut ctxt = [0; DATA_LEN + TAG_LEN]; bench.iter(|| { scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap(); }); }); c.bench_function(&aead_benchid("decrypt", "1024byte"), |bench| { const DATA_LEN: usize = 1024; let ptxt = [34u8; DATA_LEN]; let mut ctxt = [0; DATA_LEN + TAG_LEN]; let mut ptxt_out = [0u8; DATA_LEN]; scheme.encrypt(&mut ctxt, &key, &nonce, &ad, &ptxt).unwrap(); bench.iter(|| { scheme .decrypt(&mut ptxt_out, &key, &nonce, &ad, &mut ctxt) .unwrap() }) }); } } mod keyed_hash { criterion::criterion_group!( benches, bench_blake2b_rustcrypto, bench_blake2b_libcrux, bench_shake256_rustcrypto, ); const KEY_LEN: usize = 32; const HASH_LEN: usize = 32; use criterion::Criterion; fn bench_shake256_rustcrypto(c: &mut Criterion) { template( c, "shake256", "rustcrypto", &rosenpass_ciphers::subtle::rust_crypto::keyed_shake256::SHAKE256Core, ); } fn bench_blake2b_rustcrypto(c: &mut Criterion) { template( c, "blake2b", "rustcrypto", &rosenpass_ciphers::subtle::rust_crypto::blake2b::Blake2b, ); } fn bench_blake2b_libcrux(c: &mut Criterion) { template( c, "blake2b", "libcrux", &rosenpass_ciphers::subtle::libcrux::blake2b::Blake2b, ); } use rosenpass_cipher_traits::primitives::KeyedHash; fn template>( c: &mut Criterion, alg_name: &str, impl_name: &str, _: &H, ) where H::Error: std::fmt::Debug, { use crate::{benchid, KvPair, KvPairs}; let key = [12u8; KEY_LEN]; let mut out = [0u8; HASH_LEN]; let base = [ KvPair("primitive", "keyedhash"), KvPair("algorithm", alg_name), KvPair("implementation", impl_name), KvPair("operation", "hash"), ]; let keyedhash_benchid = |len| benchid(KvPairs(&base), KvPairs(&[KvPair("length", len)])); c.bench_function(&keyedhash_benchid("0byte"), |bench| { let bytes = []; bench.iter(|| { H::keyed_hash(&key, &bytes, &mut out).unwrap(); }) }) .bench_function(&keyedhash_benchid("32byte"), |bench| { let bytes = [34u8; 32]; bench.iter(|| { H::keyed_hash(&key, &bytes, &mut out).unwrap(); }) }) .bench_function(&keyedhash_benchid("64byte"), |bench| { let bytes = [34u8; 64]; bench.iter(|| { H::keyed_hash(&key, &bytes, &mut out).unwrap(); }) }) .bench_function(&keyedhash_benchid("128byte"), |bench| { let bytes = [34u8; 128]; bench.iter(|| { H::keyed_hash(&key, &bytes, &mut out).unwrap(); }) }) .bench_function(&keyedhash_benchid("1024byte"), |bench| { let bytes = [34u8; 1024]; bench.iter(|| { H::keyed_hash(&key, &bytes, &mut out).unwrap(); }) }); } }