orbit_rustls/session/
client_v24.rs1use rustls_0_24::client::{ClientSessionKey, ClientSessionStore, Tls12Session, Tls13Session};
4use rustls_0_24::crypto::kx::NamedGroup;
5use rustls_0_24::pki_types::ServerName;
6
7use super::OrbitClientSessionStorage;
8use super::store::CLIENT_TLS13_TICKETS_PER_SERVER;
9
10const KX_HINT: u8 = 1;
11const TLS12_SESSION: u8 = 2;
12const TLS13_TICKET: u8 = 3;
13const DNS_NAME: u8 = 1;
14const IP_ADDRESS: u8 = 2;
15
16impl ClientSessionStore for OrbitClientSessionStorage {
17 fn set_kx_hint(
18 &self,
19 key: ClientSessionKey<'static>,
20 group: NamedGroup
21 ) {
22 let Some((domain, server)) = storage_key(&key, KX_HINT) else {
23 return;
24 };
25 let value = u16::from(group).to_be_bytes();
26 let _ = self.primitive.put(&domain, &server, &value, self.ttl());
27 }
28
29 fn kx_hint(
30 &self,
31 key: &ClientSessionKey<'_>
32 ) -> Option<NamedGroup> {
33 let (domain, server) = storage_key(key, KX_HINT)?;
34 let value = self.primitive.get(&domain, &server).ok()??;
35 let value: [u8; 2] = value.try_into().ok()?;
36 Some(NamedGroup::from(u16::from_be_bytes(value)))
37 }
38
39 fn set_tls12_session(
40 &self,
41 key: ClientSessionKey<'static>,
42 value: Tls12Session
43 ) {
44 let Some((domain, server)) = storage_key(&key, TLS12_SESSION) else {
45 return;
46 };
47 let mut encoded = Vec::new();
48 value.encode(&mut encoded);
49 let _ = self.primitive.put(&domain, &server, &encoded, self.ttl());
50 }
51
52 fn tls12_session(
53 &self,
54 key: &ClientSessionKey<'_>
55 ) -> Option<Tls12Session> {
56 let (domain, server) = storage_key(key, TLS12_SESSION)?;
57 let encoded = self.primitive.get(&domain, &server).ok()??;
58 match Tls12Session::from_slice(&encoded, &self.provider) {
59 Ok(value) => Some(value),
60 Err(error) => {
61 let _ = self.primitive.take(&domain, &server);
62 tracing::trace!(
63 target: "orbit_rustls::client_session_cache",
64 operation = "decode_tls12",
65 %error,
66 "discarding incompatible rustls client session"
67 );
68 None
69 }
70 }
71 }
72
73 fn remove_tls12_session(
74 &self,
75 key: &ClientSessionKey<'static>
76 ) {
77 let Some((domain, server)) = storage_key(key, TLS12_SESSION) else {
78 return;
79 };
80 let _ = self.primitive.take(&domain, &server);
81 }
82
83 fn insert_tls13_ticket(
84 &self,
85 key: ClientSessionKey<'static>,
86 value: Tls13Session
87 ) {
88 let Some((domain, server)) = storage_key(&key, TLS13_TICKET) else {
89 return;
90 };
91 let mut encoded = Vec::new();
92 value.encode(&mut encoded);
93 let _ = self.primitive.push(
94 &domain,
95 &server,
96 &encoded,
97 self.ttl(),
98 CLIENT_TLS13_TICKETS_PER_SERVER
99 );
100 }
101
102 fn take_tls13_ticket(
103 &self,
104 key: &ClientSessionKey<'static>
105 ) -> Option<Tls13Session> {
106 let (domain, server) = storage_key(key, TLS13_TICKET)?;
107 for _ in 0..CLIENT_TLS13_TICKETS_PER_SERVER {
108 let encoded = match self.primitive.take(&domain, &server) {
109 Ok(Some(encoded)) => encoded,
110 Ok(None) | Err(_) => return None
111 };
112 match Tls13Session::from_slice(&encoded, &self.provider) {
113 Ok(value) => return Some(value),
114 Err(error) => {
115 tracing::trace!(
116 target: "orbit_rustls::client_session_cache",
117 operation = "decode_tls13",
118 %error,
119 "discarding incompatible rustls client ticket"
120 );
121 }
122 }
123 }
124 None
125 }
126}
127
128fn storage_key(
129 key: &ClientSessionKey<'_>,
130 record: u8
131) -> Option<([u8; 33], Vec<u8>)> {
132 let mut domain = [0_u8; 33];
133 domain[0] = record;
134 domain[1..].copy_from_slice(&key.config_hash);
135
136 let mut server = Vec::new();
137 server.push(match &key.server_name {
138 ServerName::DnsName(_) => DNS_NAME,
139 ServerName::IpAddress(_) => IP_ADDRESS,
140 _ => return None
141 });
142 server.extend_from_slice(key.server_name.to_str().as_bytes());
143 Some((domain, server))
144}