1use core::hash::Hasher;
2
3use super::{ClientSessionKey, CredentialRequest};
4use crate::client;
5use crate::crypto::SelectedCredential;
6use crate::crypto::kx::NamedGroup;
7use crate::enums::CertificateType;
8use crate::msgs::persist;
9
10#[derive(Debug)]
12pub(super) struct NoClientSessionStorage;
13
14impl client::ClientSessionStore for NoClientSessionStorage {
15 fn set_kx_hint(&self, _: ClientSessionKey<'static>, _: NamedGroup) {}
16
17 fn kx_hint(&self, _: &ClientSessionKey<'_>) -> Option<NamedGroup> {
18 None
19 }
20
21 fn set_tls12_session(&self, _: ClientSessionKey<'static>, _: persist::Tls12ClientSessionValue) {
22 }
23
24 fn tls12_session(&self, _: &ClientSessionKey<'_>) -> Option<persist::Tls12ClientSessionValue> {
25 None
26 }
27
28 fn remove_tls12_session(&self, _: &ClientSessionKey<'_>) {}
29
30 fn insert_tls13_ticket(
31 &self,
32 _: ClientSessionKey<'static>,
33 _: persist::Tls13ClientSessionValue,
34 ) {
35 }
36
37 fn take_tls13_ticket(
38 &self,
39 _: &ClientSessionKey<'_>,
40 ) -> Option<persist::Tls13ClientSessionValue> {
41 None
42 }
43}
44
45#[cfg(any(feature = "std", feature = "hashbrown"))]
46mod cache {
47 use alloc::collections::VecDeque;
48 use core::fmt;
49
50 use super::ClientSessionKey;
51 use crate::crypto::kx::NamedGroup;
52 use crate::limited_cache;
53 use crate::lock::Mutex;
54 use crate::msgs::persist;
55
56 const MAX_TLS13_TICKETS_PER_SERVER: usize = 8;
57
58 struct ServerData {
59 kx_hint: Option<NamedGroup>,
60
61 tls12: Option<persist::Tls12ClientSessionValue>,
63
64 tls13: VecDeque<persist::Tls13ClientSessionValue>,
66 }
67
68 impl Default for ServerData {
69 fn default() -> Self {
70 Self {
71 kx_hint: None,
72 tls12: None,
73 tls13: VecDeque::with_capacity(MAX_TLS13_TICKETS_PER_SERVER),
74 }
75 }
76 }
77
78 pub struct ClientSessionMemoryCache {
83 servers: Mutex<limited_cache::LimitedCache<ClientSessionKey<'static>, ServerData>>,
84 }
85
86 impl ClientSessionMemoryCache {
87 #[cfg(feature = "std")]
90 pub fn new(size: usize) -> Self {
91 let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
92 / MAX_TLS13_TICKETS_PER_SERVER;
93 Self {
94 servers: Mutex::new(limited_cache::LimitedCache::new(max_servers)),
95 }
96 }
97
98 #[cfg(not(feature = "std"))]
101 pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Self {
102 let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
103 / MAX_TLS13_TICKETS_PER_SERVER;
104 Self {
105 servers: Mutex::new::<M>(limited_cache::LimitedCache::new(max_servers)),
106 }
107 }
108 }
109
110 impl super::client::ClientSessionStore for ClientSessionMemoryCache {
111 fn set_kx_hint(&self, key: ClientSessionKey<'static>, group: NamedGroup) {
112 self.servers
113 .lock()
114 .unwrap()
115 .get_or_insert_default_and_edit(key, |data| data.kx_hint = Some(group));
116 }
117
118 fn kx_hint(&self, key: &ClientSessionKey<'_>) -> Option<NamedGroup> {
119 self.servers
120 .lock()
121 .unwrap()
122 .get(key)
123 .and_then(|sd| sd.kx_hint)
124 }
125
126 fn set_tls12_session(
127 &self,
128 key: ClientSessionKey<'static>,
129 value: persist::Tls12ClientSessionValue,
130 ) {
131 self.servers
132 .lock()
133 .unwrap()
134 .get_or_insert_default_and_edit(key.clone(), |data| data.tls12 = Some(value));
135 }
136
137 fn tls12_session(
138 &self,
139 key: &ClientSessionKey<'_>,
140 ) -> Option<persist::Tls12ClientSessionValue> {
141 self.servers
142 .lock()
143 .unwrap()
144 .get(key)
145 .and_then(|sd| sd.tls12.as_ref().cloned())
146 }
147
148 fn remove_tls12_session(&self, key: &ClientSessionKey<'static>) {
149 self.servers
150 .lock()
151 .unwrap()
152 .get_mut(key)
153 .and_then(|data| data.tls12.take());
154 }
155
156 fn insert_tls13_ticket(
157 &self,
158 key: ClientSessionKey<'static>,
159 value: persist::Tls13ClientSessionValue,
160 ) {
161 self.servers
162 .lock()
163 .unwrap()
164 .get_or_insert_default_and_edit(key.clone(), |data| {
165 if data.tls13.len() == data.tls13.capacity() {
166 data.tls13.pop_front();
167 }
168 data.tls13.push_back(value);
169 });
170 }
171
172 fn take_tls13_ticket(
173 &self,
174 key: &ClientSessionKey<'static>,
175 ) -> Option<persist::Tls13ClientSessionValue> {
176 self.servers
177 .lock()
178 .unwrap()
179 .get_mut(key)
180 .and_then(|data| data.tls13.pop_back())
181 }
182 }
183
184 impl fmt::Debug for ClientSessionMemoryCache {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 f.debug_struct("ClientSessionMemoryCache")
188 .finish()
189 }
190 }
191}
192
193#[cfg(any(feature = "std", feature = "hashbrown"))]
194pub use cache::ClientSessionMemoryCache;
195
196#[derive(Debug)]
197pub(super) struct FailResolveClientCert {}
198
199impl client::ClientCredentialResolver for FailResolveClientCert {
200 fn resolve(&self, _: &CredentialRequest<'_>) -> Option<SelectedCredential> {
201 None
202 }
203
204 fn supported_certificate_types(&self) -> &'static [CertificateType] {
205 &[]
206 }
207
208 fn hash_config(&self, _: &mut dyn Hasher) {}
209}
210
211#[cfg(test)]
212mod tests {
213 use core::time::Duration;
214 use std::prelude::v1::*;
215
216 use pki_types::{CertificateDer, ServerName, UnixTime};
217
218 use super::NoClientSessionStorage;
219 use crate::TEST_PROVIDERS;
220 use crate::client::{ClientSessionKey, ClientSessionStore};
221 use crate::crypto::kx::NamedGroup;
222 use crate::crypto::{CertificateIdentity, CipherSuite, Identity, tls12_suite, tls13_suite};
223 use crate::msgs::base::PayloadU16;
224 use crate::msgs::handshake::SessionId;
225 use crate::msgs::persist::{Tls12ClientSessionValue, Tls13ClientSessionValue};
226 use crate::sync::Arc;
227
228 #[test]
229 fn test_noclientsessionstorage_does_nothing() {
230 let c = NoClientSessionStorage {};
231 let server_name = ServerName::try_from("example.com").unwrap();
232 let key = ClientSessionKey {
233 config_hash: Default::default(),
234 server_name,
235 };
236 let now = UnixTime::now();
237
238 c.set_kx_hint(key.clone(), NamedGroup::X25519);
239 assert_eq!(None, c.kx_hint(&key));
240
241 for provider in TEST_PROVIDERS {
242 {
243 c.set_tls12_session(
244 key.clone(),
245 Tls12ClientSessionValue::new(
246 tls12_suite(
247 CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
248 provider,
249 ),
250 SessionId::empty(),
251 Arc::new(PayloadU16::empty()),
252 &[0u8; 48],
253 Identity::X509(CertificateIdentity {
254 end_entity: CertificateDer::from(&[][..]),
255 intermediates: Vec::new(),
256 }),
257 now,
258 Duration::ZERO,
259 true,
260 ),
261 );
262 assert!(c.tls12_session(&key).is_none());
263 c.remove_tls12_session(&key);
264 }
265
266 c.insert_tls13_ticket(
267 key.clone(),
268 Tls13ClientSessionValue::new(
269 tls13_suite(CipherSuite::TLS13_AES_256_GCM_SHA384, provider),
270 Arc::new(PayloadU16::empty()),
271 &[],
272 Identity::X509(CertificateIdentity {
273 end_entity: CertificateDer::from(&[][..]),
274 intermediates: Vec::new(),
275 }),
276 now,
277 Duration::ZERO,
278 0,
279 0,
280 ),
281 );
282
283 assert!(c.take_tls13_ticket(&key).is_none());
284 }
285 }
286}