aranya_internal_rustls/client/
handy.rs

1use alloc::vec::Vec;
2
3use pki_types::ServerName;
4
5use crate::crypto::PresharedKey;
6use crate::enums::SignatureScheme;
7use crate::msgs::persist;
8use crate::sync::Arc;
9use crate::{NamedGroup, client, sign};
10
11/// An implementer of `ClientSessionStore` which does nothing.
12#[derive(Debug)]
13pub(super) struct NoClientSessionStorage;
14
15impl client::ClientSessionStore for NoClientSessionStorage {
16    fn set_kx_hint(&self, _: ServerName<'static>, _: NamedGroup) {}
17
18    fn kx_hint(&self, _: &ServerName<'_>) -> Option<NamedGroup> {
19        None
20    }
21
22    fn set_tls12_session(&self, _: ServerName<'static>, _: persist::Tls12ClientSessionValue) {}
23
24    fn tls12_session(&self, _: &ServerName<'_>) -> Option<persist::Tls12ClientSessionValue> {
25        None
26    }
27
28    fn remove_tls12_session(&self, _: &ServerName<'_>) {}
29
30    fn insert_tls13_ticket(&self, _: ServerName<'static>, _: persist::Tls13ClientSessionValue) {}
31
32    fn take_tls13_ticket(&self, _: &ServerName<'_>) -> Option<persist::Tls13ClientSessionValue> {
33        None
34    }
35}
36
37/// An implementation of `PresharedKeyStore` that does nothing.
38#[derive(Debug)]
39pub(super) struct NoPresharedKeys;
40
41impl client::PresharedKeyStore for NoPresharedKeys {
42    fn psks(&self, _server_name: &ServerName<'_>) -> Vec<Arc<PresharedKey>> {
43        Vec::new()
44    }
45}
46
47#[cfg(any(feature = "std", feature = "hashbrown"))]
48mod cache {
49    use alloc::collections::VecDeque;
50    use core::fmt;
51
52    use pki_types::ServerName;
53
54    use crate::lock::Mutex;
55    use crate::msgs::persist;
56    use crate::{NamedGroup, limited_cache};
57
58    const MAX_TLS13_TICKETS_PER_SERVER: usize = 8;
59
60    struct ServerData {
61        kx_hint: Option<NamedGroup>,
62
63        // Zero or one TLS1.2 sessions.
64        #[cfg(feature = "tls12")]
65        tls12: Option<persist::Tls12ClientSessionValue>,
66
67        // Up to MAX_TLS13_TICKETS_PER_SERVER TLS1.3 tickets, oldest first.
68        tls13: VecDeque<persist::Tls13ClientSessionValue>,
69    }
70
71    impl Default for ServerData {
72        fn default() -> Self {
73            Self {
74                kx_hint: None,
75                #[cfg(feature = "tls12")]
76                tls12: None,
77                tls13: VecDeque::with_capacity(MAX_TLS13_TICKETS_PER_SERVER),
78            }
79        }
80    }
81
82    /// An implementer of `ClientSessionStore` that stores everything
83    /// in memory.
84    ///
85    /// It enforces a limit on the number of entries to bound memory usage.
86    pub struct ClientSessionMemoryCache {
87        servers: Mutex<limited_cache::LimitedCache<ServerName<'static>, ServerData>>,
88    }
89
90    impl ClientSessionMemoryCache {
91        /// Make a new ClientSessionMemoryCache.  `size` is the
92        /// maximum number of stored sessions.
93        #[cfg(feature = "std")]
94        pub fn new(size: usize) -> Self {
95            let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
96                / MAX_TLS13_TICKETS_PER_SERVER;
97            Self {
98                servers: Mutex::new(limited_cache::LimitedCache::new(max_servers)),
99            }
100        }
101
102        /// Make a new ClientSessionMemoryCache.  `size` is the
103        /// maximum number of stored sessions.
104        #[cfg(not(feature = "std"))]
105        pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Self {
106            let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
107                / MAX_TLS13_TICKETS_PER_SERVER;
108            Self {
109                servers: Mutex::new::<M>(limited_cache::LimitedCache::new(max_servers)),
110            }
111        }
112    }
113
114    impl super::client::ClientSessionStore for ClientSessionMemoryCache {
115        fn set_kx_hint(&self, server_name: ServerName<'static>, group: NamedGroup) {
116            self.servers
117                .lock()
118                .unwrap()
119                .get_or_insert_default_and_edit(server_name, |data| data.kx_hint = Some(group));
120        }
121
122        fn kx_hint(&self, server_name: &ServerName<'_>) -> Option<NamedGroup> {
123            self.servers
124                .lock()
125                .unwrap()
126                .get(server_name)
127                .and_then(|sd| sd.kx_hint)
128        }
129
130        fn set_tls12_session(
131            &self,
132            _server_name: ServerName<'static>,
133            _value: persist::Tls12ClientSessionValue,
134        ) {
135            #[cfg(feature = "tls12")]
136            self.servers
137                .lock()
138                .unwrap()
139                .get_or_insert_default_and_edit(_server_name.clone(), |data| {
140                    data.tls12 = Some(_value)
141                });
142        }
143
144        fn tls12_session(
145            &self,
146            _server_name: &ServerName<'_>,
147        ) -> Option<persist::Tls12ClientSessionValue> {
148            #[cfg(not(feature = "tls12"))]
149            return None;
150
151            #[cfg(feature = "tls12")]
152            self.servers
153                .lock()
154                .unwrap()
155                .get(_server_name)
156                .and_then(|sd| sd.tls12.as_ref().cloned())
157        }
158
159        fn remove_tls12_session(&self, _server_name: &ServerName<'static>) {
160            #[cfg(feature = "tls12")]
161            self.servers
162                .lock()
163                .unwrap()
164                .get_mut(_server_name)
165                .and_then(|data| data.tls12.take());
166        }
167
168        fn insert_tls13_ticket(
169            &self,
170            server_name: ServerName<'static>,
171            value: persist::Tls13ClientSessionValue,
172        ) {
173            self.servers
174                .lock()
175                .unwrap()
176                .get_or_insert_default_and_edit(server_name.clone(), |data| {
177                    if data.tls13.len() == data.tls13.capacity() {
178                        data.tls13.pop_front();
179                    }
180                    data.tls13.push_back(value);
181                });
182        }
183
184        fn take_tls13_ticket(
185            &self,
186            server_name: &ServerName<'static>,
187        ) -> Option<persist::Tls13ClientSessionValue> {
188            self.servers
189                .lock()
190                .unwrap()
191                .get_mut(server_name)
192                .and_then(|data| data.tls13.pop_back())
193        }
194    }
195
196    impl fmt::Debug for ClientSessionMemoryCache {
197        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198            // Note: we omit self.servers as it may contain sensitive data.
199            f.debug_struct("ClientSessionMemoryCache")
200                .finish()
201        }
202    }
203}
204
205#[cfg(any(feature = "std", feature = "hashbrown"))]
206pub use cache::ClientSessionMemoryCache;
207
208#[derive(Debug)]
209pub(super) struct FailResolveClientCert {}
210
211impl client::ResolvesClientCert for FailResolveClientCert {
212    fn resolve(
213        &self,
214        _root_hint_subjects: &[&[u8]],
215        _sigschemes: &[SignatureScheme],
216    ) -> Option<Arc<sign::CertifiedKey>> {
217        None
218    }
219
220    fn has_certs(&self) -> bool {
221        false
222    }
223}
224
225/// An exemplar `ResolvesClientCert` implementation that always resolves to a single
226/// [RFC 7250] raw public key.
227///
228/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
229#[derive(Clone, Debug)]
230pub struct AlwaysResolvesClientRawPublicKeys(Arc<sign::CertifiedKey>);
231impl AlwaysResolvesClientRawPublicKeys {
232    /// Create a new `AlwaysResolvesClientRawPublicKeys` instance.
233    pub fn new(certified_key: Arc<sign::CertifiedKey>) -> Self {
234        Self(certified_key)
235    }
236}
237
238impl client::ResolvesClientCert for AlwaysResolvesClientRawPublicKeys {
239    fn resolve(
240        &self,
241        _root_hint_subjects: &[&[u8]],
242        _sigschemes: &[SignatureScheme],
243    ) -> Option<Arc<sign::CertifiedKey>> {
244        Some(Arc::clone(&self.0))
245    }
246
247    fn only_raw_public_keys(&self) -> bool {
248        true
249    }
250
251    /// Returns true if the resolver is ready to present an identity.
252    ///
253    /// Even though the function is called `has_certs`, it returns true
254    /// although only an RPK (Raw Public Key) is available, not an actual certificate.
255    fn has_certs(&self) -> bool {
256        true
257    }
258}
259
260#[cfg(test)]
261#[macro_rules_attribute::apply(test_for_each_provider)]
262mod tests {
263    use std::prelude::v1::*;
264
265    use pki_types::{ServerName, UnixTime};
266
267    use super::NoClientSessionStorage;
268    use super::provider::cipher_suite;
269    use crate::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
270    use crate::client::{ClientSessionStore, ResolvesClientCert};
271    use crate::msgs::base::PayloadU16;
272    use crate::msgs::enums::NamedGroup;
273    use crate::msgs::handshake::CertificateChain;
274    #[cfg(feature = "tls12")]
275    use crate::msgs::handshake::SessionId;
276    use crate::msgs::persist::Tls13ClientSessionValue;
277    use crate::pki_types::CertificateDer;
278    use crate::suites::SupportedCipherSuite;
279    use crate::sync::Arc;
280    use crate::{DigitallySignedStruct, Error, SignatureScheme, sign};
281
282    #[test]
283    fn test_noclientsessionstorage_does_nothing() {
284        let c = NoClientSessionStorage {};
285        let name = ServerName::try_from("example.com").unwrap();
286        let now = UnixTime::now();
287        let server_cert_verifier: Arc<dyn ServerCertVerifier> = Arc::new(DummyServerCertVerifier);
288        let resolves_client_cert: Arc<dyn ResolvesClientCert> = Arc::new(DummyResolvesClientCert);
289
290        c.set_kx_hint(name.clone(), NamedGroup::X25519);
291        assert_eq!(None, c.kx_hint(&name));
292
293        #[cfg(feature = "tls12")]
294        {
295            use crate::msgs::persist::Tls12ClientSessionValue;
296            let SupportedCipherSuite::Tls12(tls12_suite) =
297                cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
298            else {
299                unreachable!()
300            };
301
302            c.set_tls12_session(
303                name.clone(),
304                Tls12ClientSessionValue::new(
305                    tls12_suite,
306                    SessionId::empty(),
307                    Arc::new(PayloadU16::empty()),
308                    &[],
309                    CertificateChain::default(),
310                    &server_cert_verifier,
311                    &resolves_client_cert,
312                    now,
313                    0,
314                    true,
315                ),
316            );
317            assert!(c.tls12_session(&name).is_none());
318            c.remove_tls12_session(&name);
319        }
320
321        let SupportedCipherSuite::Tls13(tls13_suite) = cipher_suite::TLS13_AES_256_GCM_SHA384
322        else {
323            unreachable!();
324        };
325        c.insert_tls13_ticket(
326            name.clone(),
327            Tls13ClientSessionValue::new(
328                tls13_suite,
329                Arc::new(PayloadU16::empty()),
330                &[],
331                CertificateChain::default(),
332                &server_cert_verifier,
333                &resolves_client_cert,
334                now,
335                0,
336                0,
337                0,
338            ),
339        );
340        assert!(c.take_tls13_ticket(&name).is_none());
341    }
342
343    #[derive(Debug)]
344    struct DummyServerCertVerifier;
345
346    impl ServerCertVerifier for DummyServerCertVerifier {
347        #[cfg_attr(coverage_nightly, coverage(off))]
348        fn verify_server_cert(
349            &self,
350            _end_entity: &CertificateDer<'_>,
351            _intermediates: &[CertificateDer<'_>],
352            _server_name: &ServerName<'_>,
353            _ocsp_response: &[u8],
354            _now: UnixTime,
355        ) -> Result<ServerCertVerified, Error> {
356            unreachable!()
357        }
358
359        #[cfg_attr(coverage_nightly, coverage(off))]
360        fn verify_tls12_signature(
361            &self,
362            _message: &[u8],
363            _cert: &CertificateDer<'_>,
364            _dss: &DigitallySignedStruct,
365        ) -> Result<HandshakeSignatureValid, Error> {
366            unreachable!()
367        }
368
369        #[cfg_attr(coverage_nightly, coverage(off))]
370        fn verify_tls13_signature(
371            &self,
372            _message: &[u8],
373            _cert: &CertificateDer<'_>,
374            _dss: &DigitallySignedStruct,
375        ) -> Result<HandshakeSignatureValid, Error> {
376            unreachable!()
377        }
378
379        #[cfg_attr(coverage_nightly, coverage(off))]
380        fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
381            unreachable!()
382        }
383    }
384
385    #[derive(Debug)]
386    struct DummyResolvesClientCert;
387
388    impl ResolvesClientCert for DummyResolvesClientCert {
389        #[cfg_attr(coverage_nightly, coverage(off))]
390        fn resolve(
391            &self,
392            _root_hint_subjects: &[&[u8]],
393            _sigschemes: &[SignatureScheme],
394        ) -> Option<Arc<sign::CertifiedKey>> {
395            unreachable!()
396        }
397
398        #[cfg_attr(coverage_nightly, coverage(off))]
399        fn has_certs(&self) -> bool {
400            unreachable!()
401        }
402    }
403}