wolfcrypt-ring-testing 0.2.1

Tests and benchmarks for wolfcrypt-ring-compat
use criterion::{criterion_group, criterion_main, Criterion};
use wolfcrypt_ring_compat::{test, test_file};

#[derive(Debug)]
pub enum AeadAlgorithm {
    Aes128Gcm,
    Aes256Gcm,
    Chacha20Poly1305,
}

pub struct AeadConfig {
    algorithm: AeadAlgorithm,
    key: Vec<u8>,
    nonce: Vec<u8>,
    aad: String,
    in_out: Vec<u8>,
}

impl AeadConfig {
    #[must_use]
    pub fn new(
        algorithm: AeadAlgorithm,
        key: &[u8],
        nonce: &[u8],
        aad: &str,
        in_out: &[u8],
    ) -> AeadConfig {
        AeadConfig {
            algorithm,
            key: Vec::from(key),
            nonce: Vec::from(nonce),
            aad: String::from(aad),
            in_out: Vec::from(in_out),
        }
    }
}
macro_rules! benchmark_aead
{( $pkg:ident ) =>
{
    paste::item! {
mod [<$pkg _benchmarks>]  {

    use $pkg::{aead, error};

    use std::hint::black_box;
    use crate::AeadConfig;
    use aead::{
        Aad, BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey, Tag, UnboundKey,
    };
    use error::Unspecified;


    struct NotANonce(Vec<u8>);

    impl NotANonce {
        fn from(value: Vec<u8>) -> Self {
            NotANonce(value)
        }
    }

    impl NonceSequence for NotANonce {
        fn advance(&mut self) -> Result<Nonce, Unspecified> {
            let mut nonce = [0u8; aead::NONCE_LEN];
            nonce.copy_from_slice(&self.0[0..aead::NONCE_LEN]);
            Ok(Nonce::assume_unique_for_key(nonce))
        }
    }

    fn algorithm(config: &crate::AeadConfig) ->  &'static aead::Algorithm {
        black_box(match &config.algorithm {
            crate::AeadAlgorithm::Aes128Gcm => &aead::AES_128_GCM,
            crate::AeadAlgorithm::Aes256Gcm => &aead::AES_256_GCM,
            crate::AeadAlgorithm::Chacha20Poly1305 => &aead::CHACHA20_POLY1305,
        })
    }

    fn key(config: &crate::AeadConfig) -> UnboundKey {
       black_box(UnboundKey::new(algorithm(config), &config.key).unwrap())
    }

    fn nonce(config: &crate::AeadConfig) -> impl NonceSequence {
       black_box(NotANonce::from(config.nonce.clone()))
    }

    pub fn aad(config: &crate::AeadConfig) -> Aad<String> {
        black_box(Aad::from(config.aad.clone()))
    }

    pub fn create_sealing_key(config: &AeadConfig) -> SealingKey<impl NonceSequence> {
        SealingKey::new(key(&config), nonce(&config))
    }

    pub fn create_opening_key(config: &AeadConfig) -> OpeningKey<impl NonceSequence> {
        OpeningKey::new(key(&config), nonce(&config))
    }


    pub fn seal_separate(sealing_key: &mut SealingKey<impl NonceSequence>, aad: Aad<String>, in_out: &mut [u8]) -> Tag {
       sealing_key
            .seal_in_place_separate_tag(aad, in_out)
            .map_err(|x| x.to_string()).unwrap()
    }

    pub fn seal_append(sealing_key: &mut SealingKey<impl NonceSequence>, aad: Aad<String>, in_out: &mut Vec<u8>) {
       sealing_key
            .seal_in_place_append_tag(aad, in_out)
            .map_err(|x| x.to_string()).unwrap()
    }

    pub fn open(opening_key: &mut OpeningKey<impl NonceSequence>, aad: Aad<String>, in_out: &mut [u8]) {
       opening_key
            .open_in_place(aad, in_out)
            .map_err(|x| x.to_string()).unwrap();
    }

}
}}}

benchmark_aead!(wolfcrypt_ring_compat);
#[cfg(feature = "ring-benchmarks")]
benchmark_aead!(ring);

fn test_aes_128_gcm(c: &mut Criterion) {
    test::run(
        test_file!("data/aead_aes_128_gcm_benchmarks.txt"),
        |_section, test_case| {
            let config = AeadConfig::new(
                AeadAlgorithm::Aes128Gcm,
                test_case.consume_bytes("KEY").as_slice(),
                test_case.consume_bytes("NONCE").as_slice(),
                test_case.consume_string("AD").as_str(),
                test_case.consume_bytes("IN").as_slice(),
            );
            test_aead_separate(c, &config);
            test_aead_append(c, &config);
            test_aead_open(c, &config);
            Ok(())
        },
    );
}

fn test_aes_256_gcm(c: &mut Criterion) {
    test::run(
        test_file!("data/aead_aes_256_gcm_benchmarks.txt"),
        |_section, test_case| {
            let config = AeadConfig::new(
                AeadAlgorithm::Aes256Gcm,
                test_case.consume_bytes("KEY").as_slice(),
                test_case.consume_bytes("NONCE").as_slice(),
                test_case.consume_string("AD").as_str(),
                test_case.consume_bytes("IN").as_slice(),
            );
            test_aead_separate(c, &config);
            test_aead_append(c, &config);
            test_aead_open(c, &config);
            Ok(())
        },
    );
}

fn test_chacha20(c: &mut Criterion) {
    test::run(
        test_file!("data/aead_chacha20_poly1305_benchmarks.txt"),
        |_section, test_case| {
            let config = AeadConfig::new(
                AeadAlgorithm::Chacha20Poly1305,
                test_case.consume_bytes("KEY").as_slice(),
                test_case.consume_bytes("NONCE").as_slice(),
                test_case.consume_string("AD").as_str(),
                test_case.consume_bytes("IN").as_slice(),
            );
            test_aead_separate(c, &config);
            test_aead_append(c, &config);
            test_aead_open(c, &config);
            Ok(())
        },
    );
}

fn test_aead_separate(c: &mut Criterion, config: &AeadConfig) {
    let mut in_out = config.in_out.clone();

    let bench_group_name = format!(
        "AEAD-{:?}-separate-{}-bytes",
        config.algorithm,
        in_out.len()
    );
    let mut group = c.benchmark_group(bench_group_name);

    let mut wc_sealing_key = wolfcrypt_ring_compat_benchmarks::create_sealing_key(config);
    group.bench_function("wolfcrypt-ring-compat", |b| {
        b.iter(|| {
            let wc_aad = wolfcrypt_ring_compat_benchmarks::aad(config);
            let _tag = wolfcrypt_ring_compat_benchmarks::seal_separate(
                &mut wc_sealing_key,
                wc_aad,
                &mut in_out,
            );
        });
    });

    #[cfg(feature = "ring-benchmarks")]
    {
        let mut ring_sealing_key = ring_benchmarks::create_sealing_key(config);
        group.bench_function("Ring", |b| {
            b.iter(|| {
                let ring_aad = ring_benchmarks::aad(config);
                let _tag =
                    ring_benchmarks::seal_separate(&mut ring_sealing_key, ring_aad, &mut in_out);
            });
        });
    }
}

fn test_aead_append(c: &mut Criterion, config: &AeadConfig) {
    let in_out = config.in_out.clone();

    let bench_group_name = format!("AEAD-{:?}-append-{}-bytes", config.algorithm, in_out.len());
    let mut group = c.benchmark_group(bench_group_name);

    let mut wc_sealing_key = wolfcrypt_ring_compat_benchmarks::create_sealing_key(config);
    group.bench_function("wolfcrypt-ring-compat", |b| {
        b.iter(|| {
            let mut wc_in_out = in_out.clone();
            let wc_aad = wolfcrypt_ring_compat_benchmarks::aad(config);
            wolfcrypt_ring_compat_benchmarks::seal_append(
                &mut wc_sealing_key,
                wc_aad,
                &mut wc_in_out,
            );
        });
    });

    #[cfg(feature = "ring-benchmarks")]
    {
        let mut ring_sealing_key = ring_benchmarks::create_sealing_key(config);
        group.bench_function("Ring", |b| {
            b.iter(|| {
                let mut ring_in_out = in_out.clone();
                let ring_aad = ring_benchmarks::aad(config);
                ring_benchmarks::seal_append(&mut ring_sealing_key, ring_aad, &mut ring_in_out);
            });
        });
    }
}

fn test_aead_open(c: &mut Criterion, config: &AeadConfig) {
    let mut in_out = config.in_out.clone();

    let wc_aad = wolfcrypt_ring_compat_benchmarks::aad(config);
    let mut wc_sealing_key = wolfcrypt_ring_compat_benchmarks::create_sealing_key(config);
    wolfcrypt_ring_compat_benchmarks::seal_append(&mut wc_sealing_key, wc_aad, &mut in_out);

    let bench_group_name = format!("AEAD-{:?}-open-{}-bytes", config.algorithm, in_out.len());
    let mut group = c.benchmark_group(bench_group_name);

    let mut wc_opening_key = wolfcrypt_ring_compat_benchmarks::create_opening_key(config);
    group.bench_function("wolfcrypt-ring-compat", |b| {
        b.iter(|| {
            let mut wc_in_out = in_out.clone();
            let wc_aad = wolfcrypt_ring_compat_benchmarks::aad(config);
            wolfcrypt_ring_compat_benchmarks::open(&mut wc_opening_key, wc_aad, &mut wc_in_out);
        });
    });

    #[cfg(feature = "ring-benchmarks")]
    {
        let mut ring_opening_key = ring_benchmarks::create_opening_key(config);
        group.bench_function("Ring", |b| {
            b.iter(|| {
                let mut ring_in_out = in_out.clone();
                let ring_aad = ring_benchmarks::aad(config);
                ring_benchmarks::open(&mut ring_opening_key, ring_aad, &mut ring_in_out);
            });
        });
    }
}

criterion_group!(benches, test_aes_128_gcm, test_aes_256_gcm, test_chacha20,);
criterion_main!(benches);