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