tor_proto/crypto/
bench_utils.rs

1//! Collection of benchmarking utilities for the `crypto` module.
2
3use crate::crypto::handshake::ShakeKeyGenerator as KGen;
4use crate::Result;
5use cipher::{KeyIvInit, StreamCipher};
6use digest::Digest;
7use tor_bytes::SecretBuf;
8use tor_cell::relaycell::RelayCellFormatTrait;
9
10pub use super::cell::tor1::bench_utils::*;
11use super::cell::{
12    tor1::CryptStatePair, ClientLayer, CryptInit, InboundClientCrypt, OutboundClientCrypt,
13    RelayCrypt,
14};
15
16/// Public wrapper around the `CryptStatePair` struct.
17#[repr(transparent)]
18pub struct HopCryptState<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait>(
19    CryptStatePair<SC, D, RCF>,
20);
21
22/// Public wrapper around the `InboundClientCrypt` struct.
23#[repr(transparent)]
24pub struct InboundCryptWrapper(InboundClientCrypt);
25
26/// Public wrapper around the `OutboundClientCrypt` struct.
27#[repr(transparent)]
28pub struct OutboundCryptWrapper(OutboundClientCrypt);
29
30impl<SC: StreamCipher + KeyIvInit, D: Digest + Clone, RCF: RelayCellFormatTrait>
31    HopCryptState<SC, D, RCF>
32{
33    /// Return a new `HopCryptState` based on a seed.
34    pub fn construct(seed: SecretBuf) -> Result<Self> {
35        Ok(Self(CryptStatePair::construct(KGen::new(seed))?))
36    }
37}
38
39impl InboundCryptWrapper {
40    /// Create a new `InboundClientCryptState`.
41    pub fn new() -> Self {
42        Default::default()
43    }
44
45    /// Add a new layer to the `InboundClientCrypt` based on a seed.
46    pub fn add_layer_from_seed<
47        SC: StreamCipher + KeyIvInit + Send + 'static,
48        D: Digest + Clone + Send + 'static,
49        RCF: RelayCellFormatTrait + Send + 'static,
50    >(
51        &mut self,
52        seed: SecretBuf,
53    ) -> Result<()> {
54        let layer: CryptStatePair<SC, D, RCF> = CryptStatePair::construct(KGen::new(seed))?;
55        let (_outbound, inbound, _binding) = layer.split();
56        self.0.add_layer(Box::new(inbound));
57
58        Ok(())
59    }
60}
61
62impl Default for InboundCryptWrapper {
63    fn default() -> Self {
64        Self(InboundClientCrypt::new())
65    }
66}
67
68impl OutboundCryptWrapper {
69    /// Create a new `OutboundClientCryptState`.
70    pub fn new() -> Self {
71        Default::default()
72    }
73
74    /// Add a new layer to the `OutboundClientCrypt` based on a seed.
75    pub fn add_layer_from_seed<
76        SC: StreamCipher + KeyIvInit + Send + 'static,
77        D: Digest + Clone + Send + 'static,
78        RCF: RelayCellFormatTrait + Send + 'static,
79    >(
80        &mut self,
81        seed: SecretBuf,
82    ) -> Result<()> {
83        let layer: CryptStatePair<SC, D, RCF> = CryptStatePair::construct(KGen::new(seed))?;
84        let (outbound, _inbound, _binding) = layer.split();
85        self.0.add_layer(Box::new(outbound));
86
87        Ok(())
88    }
89}
90
91impl Default for OutboundCryptWrapper {
92    fn default() -> Self {
93        Self(OutboundClientCrypt::new())
94    }
95}
96
97/// Encrypts the given `RelayCell` in the inbound direction.
98pub fn encrypt_inbound<SC: StreamCipher, D: Digest + Clone, RCF: RelayCellFormatTrait>(
99    cell: &mut RelayBody,
100    router_states: &mut [HopCryptState<SC, D, RCF>],
101) {
102    let cell = &mut cell.0;
103
104    for (i, pair) in router_states.iter_mut().rev().enumerate() {
105        let pair = &mut pair.0;
106        if i == 0 {
107            pair.originate(cell);
108        }
109        pair.encrypt_inbound(cell);
110    }
111}
112
113/// Public wrapper around the `InboundClientCrypt::decrypt` method
114/// for benchmarking purposes.
115pub fn client_decrypt(cell: &mut RelayBody, cc_in: &mut InboundCryptWrapper) -> Result<()> {
116    let cell = &mut cell.0;
117    cc_in.0.decrypt(cell)?;
118
119    Ok(())
120}
121
122/// Public wrapper around the `OutboundClientCrypt::encrypt` method
123/// for benchmarking purposes.
124pub fn client_encrypt(
125    cell: &mut RelayBody,
126    cc_out: &mut OutboundCryptWrapper,
127    hop_num: u8,
128) -> Result<()> {
129    let cell = &mut cell.0;
130    cc_out.0.encrypt(cell, hop_num.into())?;
131
132    Ok(())
133}