1use alloc::vec::Vec;
2use core::fmt::Debug;
3
4use crate::crypto::{Credentials, SelectedCredential};
5use crate::enums::CertificateType;
6use crate::error::{Error, PeerIncompatible};
7use crate::server;
8use crate::server::ClientHello;
9
10#[allow(clippy::exhaustive_structs)]
12#[derive(Debug)]
13pub struct NoServerSessionStorage {}
14
15impl server::StoresServerSessions for NoServerSessionStorage {
16 fn put(&self, _id: Vec<u8>, _sec: Vec<u8>) -> bool {
17 false
18 }
19 fn get(&self, _id: &[u8]) -> Option<Vec<u8>> {
20 None
21 }
22 fn take(&self, _id: &[u8]) -> Option<Vec<u8>> {
23 None
24 }
25 fn can_cache(&self) -> bool {
26 false
27 }
28}
29
30#[cfg(any(feature = "std", feature = "hashbrown"))]
31mod cache {
32 use alloc::vec::Vec;
33 use core::fmt::{Debug, Formatter};
34
35 use crate::lock::Mutex;
36 use crate::sync::Arc;
37 use crate::{limited_cache, server};
38
39 pub struct ServerSessionMemoryCache {
43 cache: Mutex<limited_cache::LimitedCache<Vec<u8>, Vec<u8>>>,
44 }
45
46 impl ServerSessionMemoryCache {
47 #[cfg(feature = "std")]
51 pub fn new(size: usize) -> Arc<Self> {
52 Arc::new(Self {
53 cache: Mutex::new(limited_cache::LimitedCache::new(size)),
54 })
55 }
56
57 #[cfg(not(feature = "std"))]
61 pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Arc<Self> {
62 Arc::new(Self {
63 cache: Mutex::new::<M>(limited_cache::LimitedCache::new(size)),
64 })
65 }
66 }
67
68 impl server::StoresServerSessions for ServerSessionMemoryCache {
69 fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
70 self.cache
71 .lock()
72 .unwrap()
73 .insert(key, value);
74 true
75 }
76
77 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
78 self.cache
79 .lock()
80 .unwrap()
81 .get(key)
82 .cloned()
83 }
84
85 fn take(&self, key: &[u8]) -> Option<Vec<u8>> {
86 self.cache.lock().unwrap().remove(key)
87 }
88
89 fn can_cache(&self) -> bool {
90 true
91 }
92 }
93
94 impl Debug for ServerSessionMemoryCache {
95 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
96 f.debug_struct("ServerSessionMemoryCache")
97 .finish()
98 }
99 }
100
101 #[cfg(test)]
102 mod tests {
103 use std::vec;
104
105 use super::*;
106 use crate::server::StoresServerSessions;
107
108 #[test]
109 fn test_serversessionmemorycache_accepts_put() {
110 let c = ServerSessionMemoryCache::new(4);
111 assert!(c.put(vec![0x01], vec![0x02]));
112 }
113
114 #[test]
115 fn test_serversessionmemorycache_persists_put() {
116 let c = ServerSessionMemoryCache::new(4);
117 assert!(c.put(vec![0x01], vec![0x02]));
118 assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
119 assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
120 }
121
122 #[test]
123 fn test_serversessionmemorycache_overwrites_put() {
124 let c = ServerSessionMemoryCache::new(4);
125 assert!(c.put(vec![0x01], vec![0x02]));
126 assert!(c.put(vec![0x01], vec![0x04]));
127 assert_eq!(c.get(&[0x01]), Some(vec![0x04]));
128 }
129
130 #[test]
131 fn test_serversessionmemorycache_drops_to_maintain_size_invariant() {
132 let c = ServerSessionMemoryCache::new(2);
133 assert!(c.put(vec![0x01], vec![0x02]));
134 assert!(c.put(vec![0x03], vec![0x04]));
135 assert!(c.put(vec![0x05], vec![0x06]));
136 assert!(c.put(vec![0x07], vec![0x08]));
137 assert!(c.put(vec![0x09], vec![0x0a]));
138
139 let count = c.get(&[0x01]).iter().count()
140 + c.get(&[0x03]).iter().count()
141 + c.get(&[0x05]).iter().count()
142 + c.get(&[0x07]).iter().count()
143 + c.get(&[0x09]).iter().count();
144
145 assert!(count < 5);
146 }
147 }
148}
149
150#[cfg(any(feature = "std", feature = "hashbrown"))]
151pub use cache::ServerSessionMemoryCache;
152
153#[derive(Debug)]
155pub(super) struct NeverProducesTickets {}
156
157impl server::ProducesTickets for NeverProducesTickets {
158 fn enabled(&self) -> bool {
159 false
160 }
161 fn lifetime(&self) -> u32 {
162 0
163 }
164 fn encrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
165 None
166 }
167 fn decrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
168 None
169 }
170}
171
172#[derive(Debug)]
177pub struct SingleRawPublicKeyResolver(Credentials);
178
179impl SingleRawPublicKeyResolver {
180 pub fn new(credentials: Credentials) -> Self {
182 Self(credentials)
183 }
184}
185
186impl server::ServerCredentialResolver for SingleRawPublicKeyResolver {
187 fn resolve(&self, client_hello: &ClientHello<'_>) -> Result<SelectedCredential, Error> {
188 self.0
189 .signer(client_hello.signature_schemes)
190 .ok_or(Error::PeerIncompatible(
191 PeerIncompatible::NoSignatureSchemesInCommon,
192 ))
193 }
194
195 fn supported_certificate_types(&self) -> &'static [CertificateType] {
196 &[CertificateType::RawPublicKey]
197 }
198}
199
200#[cfg(any(feature = "std", feature = "hashbrown"))]
201mod sni_resolver {
202 use core::fmt::Debug;
203
204 use pki_types::{DnsName, ServerName};
205
206 use crate::crypto::{CertificateIdentity, Credentials, Identity, SelectedCredential};
207 use crate::error::{Error, PeerIncompatible};
208 use crate::hash_map::HashMap;
209 use crate::server::{self, ClientHello};
210 use crate::sync::Arc;
211 use crate::webpki::{ParsedCertificate, verify_server_name};
212
213 #[derive(Debug)]
216 pub struct ServerNameResolver {
217 by_name: HashMap<DnsName<'static>, Arc<Credentials>>,
218 }
219
220 impl ServerNameResolver {
221 pub fn new() -> Self {
223 Self {
224 by_name: HashMap::new(),
225 }
226 }
227
228 pub fn add(&mut self, name: DnsName<'static>, ck: Credentials) -> Result<(), Error> {
233 let wrapped = ServerName::DnsName(name);
243 if let Identity::X509(CertificateIdentity { end_entity, .. }) = &*ck.identity {
244 let parsed = ParsedCertificate::try_from(end_entity)?;
245 verify_server_name(&parsed, &wrapped)?;
246 }
247
248 let ServerName::DnsName(name) = wrapped else {
249 unreachable!()
250 };
251
252 self.by_name.insert(name, Arc::new(ck));
253 Ok(())
254 }
255 }
256
257 impl server::ServerCredentialResolver for ServerNameResolver {
258 fn resolve(&self, client_hello: &ClientHello<'_>) -> Result<SelectedCredential, Error> {
259 let Some(name) = client_hello.server_name() else {
260 return Err(PeerIncompatible::NoServerNameProvided.into());
261 };
262
263 let Some(credentials) = self.by_name.get(name) else {
264 return Err(Error::NoSuitableCertificate);
265 };
266
267 match credentials.signer(client_hello.signature_schemes) {
268 Some(signer) => Ok(signer),
269 None => Err(PeerIncompatible::NoSignatureSchemesInCommon.into()),
270 }
271 }
272 }
273
274 #[cfg(test)]
275 mod tests {
276 use alloc::borrow::Cow;
277
278 use super::*;
279 use crate::server::ServerCredentialResolver;
280
281 #[test]
282 fn test_server_name_resolver_requires_sni() {
283 let rscsni = ServerNameResolver::new();
284 assert!(
285 rscsni
286 .resolve(&ClientHello {
287 server_name: None,
288 signature_schemes: &[],
289 alpn: None,
290 server_cert_types: None,
291 client_cert_types: None,
292 cipher_suites: &[],
293 certificate_authorities: None,
294 named_groups: None,
295 })
296 .is_err()
297 );
298 }
299
300 #[test]
301 fn test_server_name_resolver_handles_unknown_name() {
302 let rscsni = ServerNameResolver::new();
303 let name = DnsName::try_from("hello.com")
304 .unwrap()
305 .to_owned();
306 assert!(
307 rscsni
308 .resolve(&ClientHello {
309 server_name: Some(Cow::Borrowed(&name)),
310 signature_schemes: &[],
311 alpn: None,
312 server_cert_types: None,
313 client_cert_types: None,
314 cipher_suites: &[],
315 certificate_authorities: None,
316 named_groups: None,
317 })
318 .is_err()
319 );
320 }
321 }
322}
323
324#[cfg(any(feature = "std", feature = "hashbrown"))]
325pub use sni_resolver::ServerNameResolver;
326
327#[cfg(test)]
328mod tests {
329 use std::vec;
330
331 use super::*;
332 use crate::server::{ProducesTickets, StoresServerSessions};
333
334 #[test]
335 fn test_noserversessionstorage_drops_put() {
336 let c = NoServerSessionStorage {};
337 assert!(!c.put(vec![0x01], vec![0x02]));
338 }
339
340 #[test]
341 fn test_noserversessionstorage_denies_gets() {
342 let c = NoServerSessionStorage {};
343 c.put(vec![0x01], vec![0x02]);
344 assert_eq!(c.get(&[]), None);
345 assert_eq!(c.get(&[0x01]), None);
346 assert_eq!(c.get(&[0x02]), None);
347 }
348
349 #[test]
350 fn test_noserversessionstorage_denies_takes() {
351 let c = NoServerSessionStorage {};
352 assert_eq!(c.take(&[]), None);
353 assert_eq!(c.take(&[0x01]), None);
354 assert_eq!(c.take(&[0x02]), None);
355 }
356
357 #[test]
358 fn test_neverproducestickets_does_nothing() {
359 let npt = NeverProducesTickets {};
360 assert!(!npt.enabled());
361 assert_eq!(0, npt.lifetime());
362 assert_eq!(None, npt.encrypt(&[]));
363 assert_eq!(None, npt.decrypt(&[]));
364 }
365}