perf/
noprotection.rs

1use bytes::BytesMut;
2
3use noq_proto::{
4    ConnectionId, PathId, Side, TransportError,
5    crypto::{
6        self, CryptoError,
7        rustls::{QuicClientConfig, QuicServerConfig},
8    },
9    transport_parameters,
10};
11
12/// A rustls TLS session which does not perform packet encryption/decryption (for debugging purpose)
13struct NoProtectionSession {
14    inner: Box<dyn crypto::Session>,
15}
16
17impl NoProtectionSession {
18    fn new(tls: Box<dyn crypto::Session>) -> Self {
19        Self { inner: tls }
20    }
21
22    /// Wraps the provided keys in `NoProtectionPacketKey` to disable packet encryption / decryption
23    fn wrap_packet_keys(
24        keys: crypto::KeyPair<Box<dyn crypto::PacketKey>>,
25    ) -> crypto::KeyPair<Box<dyn crypto::PacketKey>> {
26        crypto::KeyPair {
27            local: Box::new(NoProtectionPacketKey::new(keys.local)),
28            remote: Box::new(NoProtectionPacketKey::new(keys.remote)),
29        }
30    }
31}
32
33struct NoProtectionPacketKey {
34    inner: Box<dyn crypto::PacketKey>,
35}
36
37impl NoProtectionPacketKey {
38    fn new(key: Box<dyn crypto::PacketKey>) -> Self {
39        Self { inner: key }
40    }
41}
42
43#[derive(Clone)]
44pub struct NoProtectionClientConfig {
45    inner: QuicClientConfig,
46}
47
48impl NoProtectionClientConfig {
49    pub fn new(config: QuicClientConfig) -> Self {
50        Self { inner: config }
51    }
52}
53
54#[derive(Clone)]
55pub struct NoProtectionServerConfig {
56    inner: QuicServerConfig,
57}
58
59impl NoProtectionServerConfig {
60    pub fn new(config: QuicServerConfig) -> Self {
61        Self { inner: config }
62    }
63}
64
65// forward all calls to inner except those related to packet encryption/decryption
66impl crypto::Session for NoProtectionSession {
67    fn initial_keys(&self, dst_cid: ConnectionId, side: Side) -> crypto::Keys {
68        self.inner.initial_keys(dst_cid, side)
69    }
70
71    fn handshake_data(&self) -> Option<Box<dyn std::any::Any>> {
72        self.inner.handshake_data()
73    }
74
75    fn peer_identity(&self) -> Option<Box<dyn std::any::Any>> {
76        self.inner.peer_identity()
77    }
78
79    fn early_crypto(&self) -> Option<(Box<dyn crypto::HeaderKey>, Box<dyn crypto::PacketKey>)> {
80        let (hkey, pkey) = self.inner.early_crypto()?;
81
82        // use wrapper type to disable packet encryption/decryption
83        Some((hkey, Box::new(NoProtectionPacketKey::new(pkey))))
84    }
85
86    fn early_data_accepted(&self) -> Option<bool> {
87        self.inner.early_data_accepted()
88    }
89
90    fn is_handshaking(&self) -> bool {
91        self.inner.is_handshaking()
92    }
93
94    fn read_handshake(&mut self, buf: &[u8]) -> Result<bool, TransportError> {
95        self.inner.read_handshake(buf)
96    }
97
98    fn transport_parameters(
99        &self,
100    ) -> Result<Option<transport_parameters::TransportParameters>, TransportError> {
101        self.inner.transport_parameters()
102    }
103
104    fn write_handshake(&mut self, buf: &mut Vec<u8>) -> Option<crypto::Keys> {
105        let keys = self.inner.write_handshake(buf)?;
106
107        Some(crypto::Keys {
108            header: keys.header,
109            packet: Self::wrap_packet_keys(keys.packet),
110        })
111    }
112
113    fn next_1rtt_keys(&mut self) -> Option<crypto::KeyPair<Box<dyn crypto::PacketKey>>> {
114        let keys = self.inner.next_1rtt_keys()?;
115        Some(Self::wrap_packet_keys(keys))
116    }
117
118    fn is_valid_retry(&self, orig_dst_cid: ConnectionId, header: &[u8], payload: &[u8]) -> bool {
119        self.inner.is_valid_retry(orig_dst_cid, header, payload)
120    }
121
122    fn export_keying_material(
123        &self,
124        output: &mut [u8],
125        label: &[u8],
126        context: &[u8],
127    ) -> Result<(), crypto::ExportKeyingMaterialError> {
128        self.inner.export_keying_material(output, label, context)
129    }
130}
131
132impl crypto::ClientConfig for NoProtectionClientConfig {
133    fn start_session(
134        &self,
135        version: u32,
136        server_name: &str,
137        params: &transport_parameters::TransportParameters,
138    ) -> Result<Box<dyn crypto::Session>, noq::ConnectError> {
139        let tls = self
140            .inner
141            .clone()
142            .start_session(version, server_name, params)?;
143
144        Ok(Box::new(NoProtectionSession::new(tls)))
145    }
146}
147
148impl crypto::ServerConfig for NoProtectionServerConfig {
149    fn initial_keys(
150        &self,
151        version: u32,
152        dst_cid: ConnectionId,
153    ) -> Result<crypto::Keys, crypto::UnsupportedVersion> {
154        self.inner.initial_keys(version, dst_cid)
155    }
156
157    fn retry_tag(&self, version: u32, orig_dst_cid: ConnectionId, packet: &[u8]) -> [u8; 16] {
158        self.inner.retry_tag(version, orig_dst_cid, packet)
159    }
160
161    fn start_session(
162        &self,
163        version: u32,
164        params: &transport_parameters::TransportParameters,
165    ) -> Box<dyn crypto::Session> {
166        let tls = self.inner.start_session(version, params);
167
168        Box::new(NoProtectionSession::new(tls))
169    }
170}
171
172// forward all calls to inner except those related to packet encryption/decryption
173impl crypto::PacketKey for NoProtectionPacketKey {
174    fn encrypt(&self, _path_id: PathId, _packet: u64, buf: &mut [u8], header_len: usize) {
175        let (_header, payload_tag) = buf.split_at_mut(header_len);
176        let (_payload, tag_storage) =
177            payload_tag.split_at_mut(payload_tag.len() - self.inner.tag_len());
178        // packet = identity(packet)
179        tag_storage.fill(42);
180    }
181
182    fn decrypt(
183        &self,
184        _path_id: PathId,
185        _packet: u64,
186        _header: &[u8],
187        payload: &mut BytesMut,
188    ) -> Result<(), CryptoError> {
189        let plain_len = payload.len() - self.inner.tag_len();
190        payload.truncate(plain_len);
191        Ok(())
192    }
193
194    fn tag_len(&self) -> usize {
195        self.inner.tag_len()
196    }
197
198    fn confidentiality_limit(&self) -> u64 {
199        self.inner.confidentiality_limit()
200    }
201
202    fn integrity_limit(&self) -> u64 {
203        self.inner.integrity_limit()
204    }
205}