From 4b83bfcad25c8d8e36fe210a76faa5797f9c5aaf Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 4 Sep 2025 21:47:55 +0200 Subject: add benchmarks for primitives --- Cargo.toml | 6 ++++++ benches/primitives.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 benches/primitives.rs diff --git a/Cargo.toml b/Cargo.toml index 237972e..2bb1e9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ categories = ["algorithms", "cryptography"] default = ["std"] simd = [] std = ["constant_time_eq/std", "blake2/std"] +primitives = [] [dependencies] aes = { version = "0.8.4", features = ["hazmat"] } @@ -27,3 +28,8 @@ criterion = "0.5.1" [[bench]] name = "zears" harness = false + +[[bench]] +name = "primitives" +required-features = ["primitives"] +harness = false diff --git a/benches/primitives.rs b/benches/primitives.rs new file mode 100644 index 0000000..09f926a --- /dev/null +++ b/benches/primitives.rs @@ -0,0 +1,60 @@ +use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; + +use zears::{Aez, primitives}; + +fn bench(c: &mut Criterion) { + let mut group = c.benchmark_group("primitives"); + + const KB: usize = 1024; + let aez = Aez::new(&[0u8; 48]); + + for size in [0, 16, 32, 64, KB].into_iter() { + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_function(BenchmarkId::new("aez_hash", size), |b| { + let tweak = vec![0u8; size]; + b.iter(|| primitives::aez_hash(&aez, [&tweak])) + }); + + // Make sure we also hit the path for tweaks that are not exactly block sized + let size = size + 8; + + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_function(BenchmarkId::new("aez_hash", size), |b| { + let tweak = vec![0u8; size]; + b.iter(|| primitives::aez_hash(&aez, [&tweak])) + }); + } + + for size in [KB, 2 * KB, 4 * KB, 8 * KB, 16 * KB].into_iter() { + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_function(BenchmarkId::new("aez_prf", size), |b| { + let mut buffer = vec![0u8; size]; + let tweak: [&[u8]; 0] = []; + b.iter(|| primitives::aez_prf(&aez, tweak, &mut buffer)) + }); + + group.bench_function(BenchmarkId::new("encipher", size), |b| { + let mut buffer = vec![0u8; size]; + let tweak: [&[u8]; 0] = []; + b.iter(|| primitives::encipher(&aez, tweak, &mut buffer)) + }); + + group.bench_function(BenchmarkId::new("decipher", size), |b| { + let mut buffer = vec![0u8; size]; + let tweak: [&[u8]; 0] = []; + b.iter(|| primitives::decipher(&aez, tweak, &mut buffer)) + }); + } + + group.finish(); + + c.bench_function("primitives/e", |b| { + b.iter(|| primitives::e(1, 1, &aez, [0; 16])) + }); +} + +criterion_group!(benches, bench); +criterion_main!(benches); diff --git a/src/lib.rs b/src/lib.rs index 531705c..95c1622 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -891,6 +891,48 @@ fn split_key(key: &Key) -> (Block, Block, Block) { ) } +/// Access to the primitive AEZ functions `aez_prf`, `aez_hash`, `encipher`, `decipher` and `e`. +/// +/// Note that this is a low-level API, not intended for general use. +/// +/// Note further that this API is exempt from semver guarantees and might break. +#[cfg(feature = "primitives")] +pub mod primitives { + use super::{Aez, Block}; + + pub fn encipher, T: IntoIterator>( + aez: &Aez, + tweaks: T, + message: &mut [u8], + ) { + super::encipher(aez, tweaks, message) + } + + pub fn decipher, T: IntoIterator>( + aez: &Aez, + tweaks: T, + message: &mut [u8], + ) { + super::decipher(aez, tweaks, message) + } + + pub fn aez_hash, T: IntoIterator>(aez: &Aez, tweaks: T) -> [u8; 16] { + super::aez_hash(aez, tweaks).bytes() + } + + pub fn aez_prf, T: IntoIterator>( + aez: &Aez, + tweaks: T, + buffer: &mut [u8], + ) { + super::aez_prf(aez, tweaks, buffer) + } + + pub fn e(j: i32, i: u32, aez: &Aez, block: [u8; 16]) -> [u8; 16] { + super::e(j, i, aez, Block::from(block)).bytes() + } +} + #[cfg(all(test, feature = "std"))] mod test { use super::*; -- cgit v1.2.3