summaryrefslogtreecommitdiff
path: root/crates/tor-proto/benches/client_decrypt.rs
blob: ab68a3b5bce414cf585ed117f9d5efd781f4c88b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use criterion::{criterion_group, criterion_main, measurement::Measurement, Criterion, Throughput};
use criterion_cycles_per_byte::CyclesPerByte;
use rand::Rng;

#[cfg(feature = "counter-galois-onion")]
use aes::{Aes128Dec, Aes128Enc, Aes256Dec, Aes256Enc};
use tor_bytes::SecretBuf;
use tor_llcrypto::{
    cipher::aes::{Aes128Ctr, Aes256Ctr},
    d::{Sha1, Sha3_256},
};
#[cfg(feature = "counter-galois-onion")]
use tor_proto::bench_utils::cgo;
use tor_proto::bench_utils::{
    circuit_encrypt_inbound, tor1, CryptInit, InboundClientCrypt, KGen, RelayCellBody,
    BENCH_CHAN_CMD,
};

// Helper macro to set up a client decryption benchmark.
macro_rules! client_decrypt_setup {
    ($client_state_construct: path, $relay_state_construct: path) => {{
        let seed1: SecretBuf = b"hidden we are free".to_vec().into();
        let seed2: SecretBuf = b"free to speak, to free ourselves".to_vec().into();
        let seed3: SecretBuf = b"free to hide no more".to_vec().into();

        let circuit_states = vec![
            $relay_state_construct(KGen::new(seed1.clone())).unwrap(),
            $relay_state_construct(KGen::new(seed2.clone())).unwrap(),
            $relay_state_construct(KGen::new(seed3.clone())).unwrap(),
        ];

        let mut cc_in = InboundClientCrypt::new();
        let state1 = $client_state_construct(KGen::new(seed1)).unwrap();
        cc_in.add_layer_from_pair(state1);
        let state2 = $client_state_construct(KGen::new(seed2)).unwrap();
        cc_in.add_layer_from_pair(state2);
        let state3 = $client_state_construct(KGen::new(seed3)).unwrap();
        cc_in.add_layer_from_pair(state3);

        let mut rng = rand::rng();
        let mut cell = [0u8; 509];
        rng.fill(&mut cell[..]);
        let mut cell: RelayCellBody = Box::new(cell).into();
        circuit_encrypt_inbound(BENCH_CHAN_CMD, &mut cell, circuit_states);
        (cell, cc_in)
    }};
}

/// Benchmark a client decrypting a relay cell coming from a circuit.
pub fn client_decrypt_benchmark(c: &mut Criterion<impl Measurement>) {
    // Group for the Tor1 relay crypto with 498 bytes of data per relay cell.
    let mut group = c.benchmark_group("client_decrypt");
    group.throughput(Throughput::Bytes(tor1::TOR1_THROUGHPUT));

    group.bench_function("Tor1RelayCrypto", |b| {
        b.iter_batched_ref(
            || {
                client_decrypt_setup!(
                    tor1::CryptStatePair::<Aes128Ctr, Sha1>::construct,
                    tor1::CryptStatePair::<Aes128Ctr, Sha1>::construct
                )
            },
            |(cell, cc_in)| {
                cc_in.decrypt(BENCH_CHAN_CMD, cell).unwrap();
            },
            criterion::BatchSize::SmallInput,
        );
    });

    group.bench_function("Tor1Hsv3RelayCrypto", |b| {
        b.iter_batched_ref(
            || {
                client_decrypt_setup!(
                    tor1::CryptStatePair::<Aes256Ctr, Sha3_256>::construct,
                    tor1::CryptStatePair::<Aes256Ctr, Sha3_256>::construct
                )
            },
            |(cell, cc_in)| {
                cc_in.decrypt(BENCH_CHAN_CMD, cell).unwrap();
            },
            criterion::BatchSize::SmallInput,
        );
    });

    group.finish();

    #[cfg(feature = "counter-galois-onion")]
    {
        // Group for the Counter-Galois-Onion relay crypto with ~488 bytes of data per relay cell.
        let mut group = c.benchmark_group("client_decrypt");
        group.throughput(Throughput::Bytes(cgo::CGO_THROUGHPUT));

        group.bench_function("CGO_Aes128", |b| {
            b.iter_batched_ref(
                || {
                    client_decrypt_setup!(
                        cgo::CryptStatePair::<Aes128Dec, Aes128Enc>::construct,
                        cgo::CryptStatePair::<Aes128Enc, Aes128Enc>::construct
                    )
                },
                |(cell, cc_in)| {
                    cc_in.decrypt(BENCH_CHAN_CMD, cell).unwrap();
                },
                criterion::BatchSize::SmallInput,
            );
        });

        group.bench_function("CGO_Aes256", |b| {
            b.iter_batched_ref(
                || {
                    client_decrypt_setup!(
                        cgo::CryptStatePair::<Aes256Dec, Aes256Enc>::construct,
                        cgo::CryptStatePair::<Aes256Enc, Aes256Enc>::construct
                    )
                },
                |(cell, cc_in)| {
                    cc_in.decrypt(BENCH_CHAN_CMD, cell).unwrap();
                },
                criterion::BatchSize::SmallInput,
            );
        });

        group.finish();
    }
}

criterion_group!(
   name = client_decrypt;
   config = Criterion::default()
      .with_measurement(CyclesPerByte)
      .sample_size(5000);
   targets = client_decrypt_benchmark);
criterion_main!(client_decrypt);