use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use dcrypt_algorithms::block::{Aes128, Aes192, Aes256, BlockCipher};
use dcrypt_algorithms::types::SecretBytes;
use dcrypt_internal::random::{ChaCha20Rng, RngCore};
fn bench_key_expansion(c: &mut Criterion) {
let mut group = c.benchmark_group("aes_key_expansion");
let mut rng = ChaCha20Rng::from_seed([42u8; 32]);
group.bench_function("aes128", |b| {
let mut key_bytes = [0u8; 16];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
b.iter(|| {
let cipher = Aes128::new(black_box(&key));
black_box(cipher);
});
});
group.bench_function("aes192", |b| {
let mut key_bytes = [0u8; 24];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
b.iter(|| {
let cipher = Aes192::new(black_box(&key));
black_box(cipher);
});
});
group.bench_function("aes256", |b| {
let mut key_bytes = [0u8; 32];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
b.iter(|| {
let cipher = Aes256::new(black_box(&key));
black_box(cipher);
});
});
group.finish();
}
fn bench_block_encrypt(c: &mut Criterion) {
let mut group = c.benchmark_group("aes_block_encrypt");
group.throughput(Throughput::Bytes(16));
let mut rng = ChaCha20Rng::from_seed([42u8; 32]);
{
let mut key_bytes = [0u8; 16];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes128::new(&key);
group.bench_function("aes128", |b| {
let mut block = [0u8; 16];
rng.fill_bytes(&mut block);
b.iter(|| {
let mut data = block;
cipher.encrypt_block(black_box(&mut data)).unwrap();
black_box(data);
});
});
}
{
let mut key_bytes = [0u8; 24];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes192::new(&key);
group.bench_function("aes192", |b| {
let mut block = [0u8; 16];
rng.fill_bytes(&mut block);
b.iter(|| {
let mut data = block;
cipher.encrypt_block(black_box(&mut data)).unwrap();
black_box(data);
});
});
}
{
let mut key_bytes = [0u8; 32];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes256::new(&key);
group.bench_function("aes256", |b| {
let mut block = [0u8; 16];
rng.fill_bytes(&mut block);
b.iter(|| {
let mut data = block;
cipher.encrypt_block(black_box(&mut data)).unwrap();
black_box(data);
});
});
}
group.finish();
}
fn bench_block_decrypt(c: &mut Criterion) {
let mut group = c.benchmark_group("aes_block_decrypt");
group.throughput(Throughput::Bytes(16));
let mut rng = ChaCha20Rng::from_seed([42u8; 32]);
{
let mut key_bytes = [0u8; 16];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes128::new(&key);
group.bench_function("aes128", |b| {
let mut block = [0u8; 16];
rng.fill_bytes(&mut block);
cipher.encrypt_block(&mut block).unwrap();
b.iter(|| {
let mut data = block;
cipher.decrypt_block(black_box(&mut data)).unwrap();
black_box(data);
});
});
}
{
let mut key_bytes = [0u8; 24];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes192::new(&key);
group.bench_function("aes192", |b| {
let mut block = [0u8; 16];
rng.fill_bytes(&mut block);
cipher.encrypt_block(&mut block).unwrap();
b.iter(|| {
let mut data = block;
cipher.decrypt_block(black_box(&mut data)).unwrap();
black_box(data);
});
});
}
{
let mut key_bytes = [0u8; 32];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes256::new(&key);
group.bench_function("aes256", |b| {
let mut block = [0u8; 16];
rng.fill_bytes(&mut block);
cipher.encrypt_block(&mut block).unwrap();
b.iter(|| {
let mut data = block;
cipher.decrypt_block(black_box(&mut data)).unwrap();
black_box(data);
});
});
}
group.finish();
}
fn bench_multi_block_encrypt(c: &mut Criterion) {
let mut group = c.benchmark_group("aes_multi_block_encrypt");
let mut rng = ChaCha20Rng::from_seed([42u8; 32]);
let sizes = [64, 256, 1024, 4096, 16384];
for size in &sizes {
group.throughput(Throughput::Bytes(*size as u64));
{
let mut key_bytes = [0u8; 16];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes128::new(&key);
group.bench_with_input(BenchmarkId::new("aes128", size), size, |b, &size| {
let mut data = vec![0u8; size];
rng.fill_bytes(&mut data[..]);
b.iter(|| {
let mut work_data = data.clone();
for chunk in work_data.chunks_exact_mut(16) {
cipher.encrypt_block(chunk).unwrap();
}
black_box(work_data);
});
});
}
{
let mut key_bytes = [0u8; 32];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes256::new(&key);
group.bench_with_input(BenchmarkId::new("aes256", size), size, |b, &size| {
let mut data = vec![0u8; size];
rng.fill_bytes(&mut data[..]);
b.iter(|| {
let mut work_data = data.clone();
for chunk in work_data.chunks_exact_mut(16) {
cipher.encrypt_block(chunk).unwrap();
}
black_box(work_data);
});
});
}
}
group.finish();
}
fn bench_parallel_blocks(c: &mut Criterion) {
let mut group = c.benchmark_group("aes_parallel_blocks");
let mut rng = ChaCha20Rng::from_seed([42u8; 32]);
let block_count = 8;
group.throughput(Throughput::Bytes((block_count * 16) as u64));
{
let mut key_bytes = [0u8; 16];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes128::new(&key);
group.bench_function("aes128_8_blocks", |b| {
let mut blocks = [[0u8; 16]; 8];
for block in &mut blocks {
rng.fill_bytes(block);
}
b.iter(|| {
let mut work_blocks = blocks;
for block in &mut work_blocks {
cipher.encrypt_block(block).unwrap();
}
black_box(work_blocks);
});
});
}
{
let mut key_bytes = [0u8; 32];
rng.fill_bytes(&mut key_bytes);
let key = SecretBytes::new(key_bytes);
let cipher = Aes256::new(&key);
group.bench_function("aes256_8_blocks", |b| {
let mut blocks = [[0u8; 16]; 8];
for block in &mut blocks {
rng.fill_bytes(block);
}
b.iter(|| {
let mut work_blocks = blocks;
for block in &mut work_blocks {
cipher.encrypt_block(block).unwrap();
}
black_box(work_blocks);
});
});
}
group.finish();
}
criterion_group!(
benches,
bench_key_expansion,
bench_block_encrypt,
bench_block_decrypt,
bench_multi_block_encrypt,
bench_parallel_blocks
);
criterion_main!(benches);