1use pki_types::ServerName;
2
3use super::CredentialRequest;
4use crate::crypto::{Credentials, SelectedCredential};
5use crate::enums::CertificateType;
6use crate::msgs::persist;
7use crate::{NamedGroup, client};
8
9#[derive(Debug)]
11pub(super) struct NoClientSessionStorage;
12
13impl client::ClientSessionStore for NoClientSessionStorage {
14 fn set_kx_hint(&self, _: ServerName<'static>, _: NamedGroup) {}
15
16 fn kx_hint(&self, _: &ServerName<'_>) -> Option<NamedGroup> {
17 None
18 }
19
20 fn set_tls12_session(&self, _: ServerName<'static>, _: persist::Tls12ClientSessionValue) {}
21
22 fn tls12_session(&self, _: &ServerName<'_>) -> Option<persist::Tls12ClientSessionValue> {
23 None
24 }
25
26 fn remove_tls12_session(&self, _: &ServerName<'_>) {}
27
28 fn insert_tls13_ticket(&self, _: ServerName<'static>, _: persist::Tls13ClientSessionValue) {}
29
30 fn take_tls13_ticket(&self, _: &ServerName<'_>) -> Option<persist::Tls13ClientSessionValue> {
31 None
32 }
33}
34
35#[cfg(any(feature = "std", feature = "hashbrown"))]
36mod cache {
37 use alloc::collections::VecDeque;
38 use core::fmt;
39
40 use pki_types::ServerName;
41
42 use crate::lock::Mutex;
43 use crate::msgs::persist;
44 use crate::{NamedGroup, limited_cache};
45
46 const MAX_TLS13_TICKETS_PER_SERVER: usize = 8;
47
48 struct ServerData {
49 kx_hint: Option<NamedGroup>,
50
51 tls12: Option<persist::Tls12ClientSessionValue>,
53
54 tls13: VecDeque<persist::Tls13ClientSessionValue>,
56 }
57
58 impl Default for ServerData {
59 fn default() -> Self {
60 Self {
61 kx_hint: None,
62 tls12: None,
63 tls13: VecDeque::with_capacity(MAX_TLS13_TICKETS_PER_SERVER),
64 }
65 }
66 }
67
68 pub struct ClientSessionMemoryCache {
73 servers: Mutex<limited_cache::LimitedCache<ServerName<'static>, ServerData>>,
74 }
75
76 impl ClientSessionMemoryCache {
77 #[cfg(feature = "std")]
80 pub fn new(size: usize) -> Self {
81 let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
82 / MAX_TLS13_TICKETS_PER_SERVER;
83 Self {
84 servers: Mutex::new(limited_cache::LimitedCache::new(max_servers)),
85 }
86 }
87
88 #[cfg(not(feature = "std"))]
91 pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Self {
92 let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1)
93 / MAX_TLS13_TICKETS_PER_SERVER;
94 Self {
95 servers: Mutex::new::<M>(limited_cache::LimitedCache::new(max_servers)),
96 }
97 }
98 }
99
100 impl super::client::ClientSessionStore for ClientSessionMemoryCache {
101 fn set_kx_hint(&self, server_name: ServerName<'static>, group: NamedGroup) {
102 self.servers
103 .lock()
104 .unwrap()
105 .get_or_insert_default_and_edit(server_name, |data| data.kx_hint = Some(group));
106 }
107
108 fn kx_hint(&self, server_name: &ServerName<'_>) -> Option<NamedGroup> {
109 self.servers
110 .lock()
111 .unwrap()
112 .get(server_name)
113 .and_then(|sd| sd.kx_hint)
114 }
115
116 fn set_tls12_session(
117 &self,
118 server_name: ServerName<'static>,
119 value: persist::Tls12ClientSessionValue,
120 ) {
121 self.servers
122 .lock()
123 .unwrap()
124 .get_or_insert_default_and_edit(server_name.clone(), |data| {
125 data.tls12 = Some(value)
126 });
127 }
128
129 fn tls12_session(
130 &self,
131 server_name: &ServerName<'_>,
132 ) -> Option<persist::Tls12ClientSessionValue> {
133 self.servers
134 .lock()
135 .unwrap()
136 .get(server_name)
137 .and_then(|sd| sd.tls12.as_ref().cloned())
138 }
139
140 fn remove_tls12_session(&self, server_name: &ServerName<'static>) {
141 self.servers
142 .lock()
143 .unwrap()
144 .get_mut(server_name)
145 .and_then(|data| data.tls12.take());
146 }
147
148 fn insert_tls13_ticket(
149 &self,
150 server_name: ServerName<'static>,
151 value: persist::Tls13ClientSessionValue,
152 ) {
153 self.servers
154 .lock()
155 .unwrap()
156 .get_or_insert_default_and_edit(server_name.clone(), |data| {
157 if data.tls13.len() == data.tls13.capacity() {
158 data.tls13.pop_front();
159 }
160 data.tls13.push_back(value);
161 });
162 }
163
164 fn take_tls13_ticket(
165 &self,
166 server_name: &ServerName<'static>,
167 ) -> Option<persist::Tls13ClientSessionValue> {
168 self.servers
169 .lock()
170 .unwrap()
171 .get_mut(server_name)
172 .and_then(|data| data.tls13.pop_back())
173 }
174 }
175
176 impl fmt::Debug for ClientSessionMemoryCache {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 f.debug_struct("ClientSessionMemoryCache")
180 .finish()
181 }
182 }
183}
184
185#[cfg(any(feature = "std", feature = "hashbrown"))]
186pub use cache::ClientSessionMemoryCache;
187
188#[derive(Debug)]
189pub(super) struct FailResolveClientCert {}
190
191impl client::ClientCredentialResolver for FailResolveClientCert {
192 fn resolve(&self, _: &CredentialRequest<'_>) -> Option<SelectedCredential> {
193 None
194 }
195
196 fn supported_certificate_types(&self) -> &'static [CertificateType] {
197 &[]
198 }
199}
200
201#[derive(Debug)]
206pub struct AlwaysResolvesClientRawPublicKeys(Credentials);
207
208impl AlwaysResolvesClientRawPublicKeys {
209 pub fn new(credentials: Credentials) -> Self {
211 Self(credentials)
212 }
213}
214
215impl client::ClientCredentialResolver for AlwaysResolvesClientRawPublicKeys {
216 fn resolve(&self, request: &CredentialRequest<'_>) -> Option<SelectedCredential> {
217 match request.negotiated_type() {
218 CertificateType::RawPublicKey => self
219 .0
220 .signer(request.signature_schemes()),
221 _ => None,
222 }
223 }
224
225 fn supported_certificate_types(&self) -> &'static [CertificateType] {
226 &[CertificateType::RawPublicKey]
227 }
228}
229
230#[cfg(test)]
231#[macro_rules_attribute::apply(test_for_each_provider)]
232mod tests {
233 use std::prelude::v1::*;
234
235 use pki_types::{CertificateDer, ServerName, UnixTime};
236
237 use super::NoClientSessionStorage;
238 use super::provider::cipher_suite;
239 use crate::client::danger::{HandshakeSignatureValid, PeerVerified, ServerVerifier};
240 use crate::client::{ClientCredentialResolver, ClientSessionStore, CredentialRequest};
241 use crate::crypto::{CertificateIdentity, Identity, SelectedCredential};
242 use crate::enums::{CertificateType, SignatureScheme};
243 use crate::error::Error;
244 use crate::msgs::base::PayloadU16;
245 use crate::msgs::enums::NamedGroup;
246 use crate::msgs::handshake::SessionId;
247 use crate::msgs::persist::Tls13ClientSessionValue;
248 use crate::sync::Arc;
249 use crate::verify::{ServerIdentity, SignatureVerificationInput};
250
251 #[test]
252 fn test_noclientsessionstorage_does_nothing() {
253 let c = NoClientSessionStorage {};
254 let name = ServerName::try_from("example.com").unwrap();
255 let now = UnixTime::now();
256 let server_cert_verifier: Arc<dyn ServerVerifier> = Arc::new(DummyServerVerifier);
257 let resolves_client_cert: Arc<dyn ClientCredentialResolver> =
258 Arc::new(DummyClientCredentialResolver);
259
260 c.set_kx_hint(name.clone(), NamedGroup::X25519);
261 assert_eq!(None, c.kx_hint(&name));
262
263 {
264 use crate::msgs::persist::Tls12ClientSessionValue;
265
266 c.set_tls12_session(
267 name.clone(),
268 Tls12ClientSessionValue::new(
269 cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
270 SessionId::empty(),
271 Arc::new(PayloadU16::empty()),
272 &[0u8; 48],
273 Identity::X509(CertificateIdentity {
274 end_entity: CertificateDer::from(&[][..]),
275 intermediates: Vec::new(),
276 }),
277 &server_cert_verifier,
278 &resolves_client_cert,
279 now,
280 0,
281 true,
282 ),
283 );
284 assert!(c.tls12_session(&name).is_none());
285 c.remove_tls12_session(&name);
286 }
287
288 c.insert_tls13_ticket(
289 name.clone(),
290 Tls13ClientSessionValue::new(
291 cipher_suite::TLS13_AES_256_GCM_SHA384,
292 Arc::new(PayloadU16::empty()),
293 &[],
294 Identity::X509(CertificateIdentity {
295 end_entity: CertificateDer::from(&[][..]),
296 intermediates: Vec::new(),
297 }),
298 &server_cert_verifier,
299 &resolves_client_cert,
300 now,
301 0,
302 0,
303 0,
304 ),
305 );
306 assert!(c.take_tls13_ticket(&name).is_none());
307 }
308
309 #[derive(Debug)]
310 struct DummyServerVerifier;
311
312 impl ServerVerifier for DummyServerVerifier {
313 #[cfg_attr(coverage_nightly, coverage(off))]
314 fn verify_identity(&self, _identity: &ServerIdentity<'_>) -> Result<PeerVerified, Error> {
315 unreachable!()
316 }
317
318 #[cfg_attr(coverage_nightly, coverage(off))]
319 fn verify_tls12_signature(
320 &self,
321 _input: &SignatureVerificationInput<'_>,
322 ) -> Result<HandshakeSignatureValid, Error> {
323 unreachable!()
324 }
325
326 #[cfg_attr(coverage_nightly, coverage(off))]
327 fn verify_tls13_signature(
328 &self,
329 _input: &SignatureVerificationInput<'_>,
330 ) -> Result<HandshakeSignatureValid, Error> {
331 unreachable!()
332 }
333
334 #[cfg_attr(coverage_nightly, coverage(off))]
335 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
336 unreachable!()
337 }
338
339 #[cfg_attr(coverage_nightly, coverage(off))]
340 fn request_ocsp_response(&self) -> bool {
341 unreachable!()
342 }
343 }
344
345 #[derive(Debug)]
346 struct DummyClientCredentialResolver;
347
348 impl ClientCredentialResolver for DummyClientCredentialResolver {
349 #[cfg_attr(coverage_nightly, coverage(off))]
350 fn resolve(&self, _: &CredentialRequest<'_>) -> Option<SelectedCredential> {
351 unreachable!()
352 }
353
354 #[cfg_attr(coverage_nightly, coverage(off))]
355 fn supported_certificate_types(&self) -> &'static [CertificateType] {
356 unreachable!()
357 }
358 }
359}