aws-lc-rs-testing/benches/hmac_benchmark.rs (170 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC
use criterion::{criterion_group, criterion_main, Criterion};
#[derive(Debug)]
pub enum HMACAlgorithm {
SHA1,
SHA256,
SHA384,
SHA512,
}
pub struct HMACConfig {
algorithm: HMACAlgorithm,
}
impl HMACConfig {
#[must_use]
pub fn new(algorithm: HMACAlgorithm) -> HMACConfig {
HMACConfig { algorithm }
}
}
macro_rules! benchmark_hmac {
( $pkg:ident ) => {
paste::item! {
mod [<$pkg _benchmarks>] {
use $pkg::{hmac, digest};
use criterion::black_box;
use crate::HMACConfig;
pub fn algorithm(config: &crate::HMACConfig) -> hmac::Algorithm {
black_box(match &config.algorithm {
crate::HMACAlgorithm::SHA1 => hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
crate::HMACAlgorithm::SHA256 => hmac::HMAC_SHA256,
crate::HMACAlgorithm::SHA384 => hmac::HMAC_SHA384,
crate::HMACAlgorithm::SHA512 => hmac::HMAC_SHA512,
})
}
pub fn create_hmac_key(config: &HMACConfig) -> hmac::Key {
let key_val = vec![1u8; get_digest_length(&config)];
hmac::Key::new(algorithm(&config), &key_val)
}
// A HMAC key longer than the corresponding digest length will be hashed once
// before being processed.
pub fn create_longer_hmac_key(config: &HMACConfig) -> hmac::Key {
let key_val = vec![1u8; get_digest_length(&config) + 1];
hmac::Key::new(algorithm(&config), &key_val)
}
#[allow(unused_must_use)]
pub fn run_hmac_incremental(key: &hmac::Key, chunk: &[u8]) {
let mut s_ctx = hmac::Context::with_key(&key);
s_ctx.update(chunk);
s_ctx.sign();
}
#[allow(unused_must_use)]
pub fn run_hmac_one_shot(key: &hmac::Key, chunk: &[u8]) {
hmac::sign(&key, chunk);
}
fn get_digest_length(config: &HMACConfig) -> usize {
match &config.algorithm {
crate::HMACAlgorithm::SHA1 => digest::SHA1_OUTPUT_LEN,
crate::HMACAlgorithm::SHA256 => digest::SHA256_OUTPUT_LEN,
crate::HMACAlgorithm::SHA384 => digest::SHA384_OUTPUT_LEN,
crate::HMACAlgorithm::SHA512 => digest::SHA512_OUTPUT_LEN,
}
}
}
}
};
}
benchmark_hmac!(aws_lc_rs);
#[cfg(feature = "ring-benchmarks")]
benchmark_hmac!(ring);
fn bench_hmac_sha1(c: &mut Criterion) {
let config = HMACConfig::new(HMACAlgorithm::SHA1);
bench_hmac_one_shot(c, &config);
bench_hmac_incremental(c, &config);
bench_hmac_longer_key(c, &config);
}
fn bench_hmac_sha256(c: &mut Criterion) {
let config = HMACConfig::new(HMACAlgorithm::SHA256);
bench_hmac_one_shot(c, &config);
bench_hmac_incremental(c, &config);
bench_hmac_longer_key(c, &config);
}
fn bench_hmac_sha384(c: &mut Criterion) {
let config = HMACConfig::new(HMACAlgorithm::SHA384);
bench_hmac_one_shot(c, &config);
bench_hmac_incremental(c, &config);
bench_hmac_longer_key(c, &config);
}
fn bench_hmac_sha512(c: &mut Criterion) {
let config = HMACConfig::new(HMACAlgorithm::SHA512);
bench_hmac_one_shot(c, &config);
bench_hmac_incremental(c, &config);
bench_hmac_longer_key(c, &config);
}
const G_CHUNK_LENGTHS: [usize; 5] = [16, 256, 1350, 8192, 16384];
// Benchmark hmac::sign one-shot API.
fn bench_hmac_one_shot(c: &mut Criterion, config: &HMACConfig) {
for &chunk_len in &G_CHUNK_LENGTHS {
let chunk = vec![1u8; chunk_len];
let bench_group_name = format!("HMAC-{:?}-one-shot-{}-bytes", config.algorithm, chunk_len);
let mut group = c.benchmark_group(bench_group_name);
group.bench_function("AWS-LC", |b| {
b.iter(|| {
let aws_key = aws_lc_rs_benchmarks::create_hmac_key(config);
aws_lc_rs_benchmarks::run_hmac_one_shot(&aws_key, &chunk);
});
});
#[cfg(feature = "ring-benchmarks")]
{
group.bench_function("Ring", |b| {
b.iter(|| {
let ring_key = ring_benchmarks::create_hmac_key(config);
ring_benchmarks::run_hmac_one_shot(&ring_key, &chunk);
});
});
}
}
}
// Benchmark hmac::sign with keys longer than the block size. If a key is longer than the block
// length then it will be compressed using the digest algorithm.
fn bench_hmac_longer_key(c: &mut Criterion, config: &HMACConfig) {
for &chunk_len in &G_CHUNK_LENGTHS {
let chunk = vec![1u8; chunk_len];
let bench_group_name = format!(
"HMAC-{:?}-one-shot-long-key-{}-bytes",
config.algorithm, chunk_len
);
let mut group = c.benchmark_group(bench_group_name);
group.bench_function("AWS-LC", |b| {
b.iter(|| {
let aws_key = aws_lc_rs_benchmarks::create_longer_hmac_key(config);
aws_lc_rs_benchmarks::run_hmac_one_shot(&aws_key, &chunk);
});
});
#[cfg(feature = "ring-benchmarks")]
{
group.bench_function("Ring", |b| {
b.iter(|| {
let ring_key = ring_benchmarks::create_longer_hmac_key(config);
ring_benchmarks::run_hmac_one_shot(&ring_key, &chunk);
});
});
}
}
}
// Benchmark incremental hmac update/sign.
fn bench_hmac_incremental(c: &mut Criterion, config: &HMACConfig) {
for &chunk_len in &G_CHUNK_LENGTHS {
let chunk = vec![123u8; chunk_len];
let bench_group_name = format!(
"HMAC-{:?}-incremental-{}-bytes",
config.algorithm, chunk_len
);
let mut group = c.benchmark_group(bench_group_name);
group.bench_function("AWS-LC", |b| {
b.iter(|| {
let aws_key = aws_lc_rs_benchmarks::create_hmac_key(config);
aws_lc_rs_benchmarks::run_hmac_incremental(&aws_key, &chunk);
});
});
#[cfg(feature = "ring-benchmarks")]
{
group.bench_function("Ring", |b| {
b.iter(|| {
let ring_key = ring_benchmarks::create_hmac_key(config);
ring_benchmarks::run_hmac_incremental(&ring_key, &chunk);
});
});
}
}
}
criterion_group!(
benches,
bench_hmac_sha1,
bench_hmac_sha256,
bench_hmac_sha384,
bench_hmac_sha512,
);
criterion_main!(benches);