1use super::{
5 size_of::SizeOf,
6 status::{Dedup, IsRetired},
7 Map,
8};
9use crate::{
10 credentials::{self, Credentials},
11 packet::{secret_control as control, WireVersion},
12 path::secret::{
13 map::Epoch,
14 open, receiver,
15 schedule::{self, Initiator},
16 seal, sender,
17 },
18 stream::TransportFeatures,
19};
20use s2n_codec::EncoderBuffer;
21use s2n_quic_core::{dc, varint::VarInt};
22use std::{
23 any::Any,
24 fmt,
25 net::SocketAddr,
26 sync::{
27 atomic::{AtomicU32, AtomicU64, AtomicU8, Ordering},
28 Arc,
29 },
30 time::{Duration, Instant},
31};
32
33#[cfg(test)]
34mod tests;
35
36pub type ApplicationData = Arc<dyn Any + Send + Sync>;
37
38#[derive(Debug, thiserror::Error)]
39#[error("{inner}")]
40pub struct ApplicationDataError {
41 pub msg: &'static str,
42 #[source]
43 pub inner: Box<dyn std::error::Error + Send + Sync>,
44}
45
46#[derive(Debug)]
47pub struct Entry {
48 creation_time: Instant,
49 peer: SocketAddr,
50 secret: schedule::Secret,
51 retired: IsRetired,
52 accessed_at: AccessedAt,
53 sender: sender::State,
54 receiver: receiver::State,
55 parameters: dc::ApplicationParams,
56 accessed: AtomicU8,
59 application_data: Option<ApplicationData>,
60}
61
62impl SizeOf for Entry {
63 fn size(&self) -> usize {
64 let Entry {
65 creation_time,
66 peer,
67 secret,
68 retired,
69 sender,
70 receiver,
71 parameters,
72 accessed,
73 application_data,
74 accessed_at,
75 } = self;
76 creation_time.size()
77 + peer.size()
78 + secret.size()
79 + retired.size()
80 + sender.size()
81 + receiver.size()
82 + parameters.size()
83 + accessed.size()
84 + application_data.size()
85 + accessed_at.size()
86 }
87}
88
89impl SizeOf for Option<ApplicationData> {
90 fn size(&self) -> usize {
91 std::mem::size_of::<ApplicationData>()
92 }
93}
94
95impl SizeOf for ApplicationData {
96 fn size(&self) -> usize {
97 std::mem::size_of_val(self)
98 }
99}
100
101impl SizeOf for AtomicU8 {}
102impl SizeOf for AtomicU32 {}
103
104impl Entry {
105 pub fn new(
106 peer: SocketAddr,
107 secret: schedule::Secret,
108 sender: sender::State,
109 receiver: receiver::State,
110 parameters: dc::ApplicationParams,
111 _: Duration,
113 application_data: Option<ApplicationData>,
114 ) -> Self {
115 parameters
117 .max_datagram_size
118 .fetch_min(crate::stream::MAX_DATAGRAM_SIZE as _, Ordering::Relaxed);
119
120 Self {
121 creation_time: Instant::now(),
122 peer,
123 secret,
124 retired: Default::default(),
125 sender,
126 receiver,
127 parameters,
128 accessed: AtomicU8::new(0),
129 accessed_at: AccessedAt(AtomicU64::new(0)),
130 application_data,
131 }
132 }
133
134 #[cfg(any(test, feature = "testing"))]
135 #[allow(
136 clippy::unwrap_used,
137 reason = "test-support helper may panic to surface setup failures"
138 )]
139 pub fn fake(peer: SocketAddr, receiver: Option<receiver::State>) -> Arc<Entry> {
140 let receiver = receiver.unwrap_or_default();
141
142 let mut secret = [0; 32];
143 aws_lc_rs::rand::fill(&mut secret).unwrap();
144
145 Arc::new(Entry::new(
146 peer,
147 schedule::Secret::new(
148 schedule::Ciphersuite::AES_GCM_128_SHA256,
149 dc::SUPPORTED_VERSIONS[0],
150 s2n_quic_core::endpoint::Type::Client,
151 &secret,
152 ),
153 sender::State::new([0; control::TAG_LEN]),
154 receiver,
155 dc::testing::TEST_APPLICATION_PARAMS,
156 dc::testing::TEST_REHANDSHAKE_PERIOD,
157 None,
158 ))
159 }
160
161 pub fn peer(&self) -> &SocketAddr {
162 &self.peer
163 }
164
165 pub fn id(&self) -> &credentials::Id {
166 self.secret.id()
167 }
168
169 pub fn secret(&self) -> &schedule::Secret {
170 &self.secret
171 }
172
173 pub fn accessed_at_epoch(&self) -> Epoch {
177 Epoch(self.accessed_at.accessed_at_epoch())
178 }
179
180 pub fn set_accessed_id(&self, epoch: Epoch) {
181 self.accessed_at.set_accessed(epoch);
182 self.accessed.fetch_or(0b10, Ordering::Relaxed);
183 }
184
185 pub fn set_accessed_addr(&self, epoch: Epoch) {
186 self.accessed_at.set_accessed(epoch);
187 self.accessed.fetch_or(0b01, Ordering::Relaxed);
188 }
189
190 pub fn take_accessed_id(&self) -> bool {
191 self.accessed.fetch_and(!0b10, Ordering::Relaxed) & 0b10 != 0
192 }
193
194 pub fn take_accessed_addr(&self) -> bool {
195 self.accessed.fetch_and(!0b01, Ordering::Relaxed) & 0b01 != 0
196 }
197
198 pub fn retire(&self, at_epoch: Epoch) {
199 self.retired.retire(at_epoch);
200 }
201
202 pub fn retired_at(&self) -> Option<Epoch> {
203 self.retired.retired_at()
204 }
205
206 pub fn uni_sealer(&self) -> (seal::Once, Credentials) {
207 let key_id = self.sender.next_key_id();
208 let credentials = Credentials {
209 id: *self.secret.id(),
210 key_id,
211 };
212 let sealer = self.secret.application_sealer(key_id);
213 let sealer = seal::Once::new(sealer);
214
215 (sealer, credentials)
216 }
217
218 pub fn uni_opener(
219 self: Arc<Self>,
220 map: Map,
221 credentials: &Credentials,
222 queue_id: Option<VarInt>,
223 ) -> open::Once {
224 let key_id = credentials.key_id;
225 let opener = self.secret.application_opener(key_id);
226 let dedup = Dedup::new(self, key_id, queue_id, map);
227 open::Once::new(opener, dedup)
228 }
229
230 pub fn bidi_local(&self, features: &TransportFeatures) -> Bidirectional {
231 let key_id = self.sender.next_key_id();
232 let initiator = Initiator::Local;
233
234 let application = ApplicationPair::new(
235 &self.secret,
236 key_id,
237 initiator,
238 Dedup::disabled(),
240 );
241
242 let control = if features.is_reliable() {
243 None
244 } else {
245 Some(ControlPair::new(&self.secret, key_id, initiator))
246 };
247
248 Bidirectional {
249 credentials: Credentials {
250 id: *self.secret.id(),
251 key_id,
252 },
253 application,
254 control,
255 }
256 }
257
258 pub fn bidi_remote(
259 self: &Arc<Self>,
260 map: Map,
261 credentials: &Credentials,
262 queue_id: Option<VarInt>,
263 features: &TransportFeatures,
264 ) -> Bidirectional {
265 let key_id = credentials.key_id;
266 let initiator = Initiator::Remote;
267
268 let application = ApplicationPair::new(
269 &self.secret,
270 key_id,
271 initiator,
272 Dedup::new(self.clone(), key_id, queue_id, map),
274 );
275
276 let control = if features.is_reliable() {
277 None
278 } else {
279 Some(ControlPair::new(&self.secret, key_id, initiator))
280 };
281
282 Bidirectional {
283 credentials: *credentials,
284 application,
285 control,
286 }
287 }
288
289 pub fn parameters(&self) -> dc::ApplicationParams {
290 self.parameters.clone()
291 }
292
293 pub fn update_max_datagram_size(&self, mtu: u16) {
294 self.parameters
295 .max_datagram_size
296 .store(mtu, Ordering::Relaxed);
297 }
298
299 pub fn age(&self) -> Duration {
300 self.creation_time.elapsed()
301 }
302
303 pub fn creation_time(&self) -> Instant {
304 self.creation_time
305 }
306
307 pub fn receiver(&self) -> &receiver::State {
308 &self.receiver
309 }
310
311 pub fn sender(&self) -> &sender::State {
312 &self.sender
313 }
314
315 pub fn control_opener(&self) -> crate::crypto::awslc::open::control::Secret {
316 self.sender.control_secret(&self.secret)
317 }
318
319 pub fn control_sealer(&self) -> crate::crypto::awslc::seal::control::Secret {
320 self.secret.control_sealer()
321 }
322
323 pub fn application_data(&self) -> &Option<ApplicationData> {
324 &self.application_data
325 }
326
327 #[cfg(test)]
328 pub fn reset_sender_counter(&self) {
329 self.sender.reset_counter();
330 }
331}
332
333impl receiver::Error {
334 pub(super) fn to_packet<'buffer>(
335 self,
336 entry: &Entry,
337 credentials: &Credentials,
338 queue_id: Option<VarInt>,
339 buffer: &'buffer mut [u8; control::MAX_PACKET_SIZE],
340 ) -> &'buffer [u8] {
341 debug_assert_eq!(entry.secret.id(), &credentials.id);
342 let encoder = EncoderBuffer::new(&mut buffer[..]);
343 let length = match self {
344 receiver::Error::AlreadyExists => control::ReplayDetected {
345 wire_version: WireVersion::ZERO,
346 credential_id: credentials.id,
347 rejected_key_id: credentials.key_id,
348 queue_id,
349 }
350 .encode(encoder, &entry.control_sealer()),
351 receiver::Error::Unknown => control::StaleKey {
352 wire_version: WireVersion::ZERO,
353 credential_id: credentials.id,
354 min_key_id: entry.receiver.minimum_unseen_key_id(),
355 queue_id,
356 }
357 .encode(encoder, &entry.control_sealer()),
358 };
359 &buffer[..length]
360 }
361}
362
363pub struct Bidirectional {
364 pub credentials: Credentials,
365 pub application: ApplicationPair,
366 pub control: Option<ControlPair>,
367}
368
369pub struct ApplicationPair {
370 pub sealer: seal::Application,
371 pub opener: open::Application,
372}
373
374impl ApplicationPair {
375 pub fn new(
376 secret: &schedule::Secret,
377 key_id: VarInt,
378 initiator: Initiator,
379 dedup: Dedup,
380 ) -> Self {
381 let (sealer, sealer_ku, opener, opener_ku) = secret.application_pair(key_id, initiator);
382
383 let sealer = seal::Application::new(sealer, sealer_ku);
384
385 let opener = open::Application::new(opener, opener_ku, dedup);
386
387 Self { sealer, opener }
388 }
389}
390
391pub struct ControlPair {
392 pub sealer: seal::control::Stream,
393 pub opener: open::control::Stream,
394}
395
396impl ControlPair {
397 fn new(secret: &schedule::Secret, key_id: VarInt, initiator: Initiator) -> Self {
398 let (sealer, opener) = secret.control_pair(key_id, initiator);
399
400 Self { sealer, opener }
401 }
402}
403
404#[derive(Default)]
409struct AccessedAt(AtomicU64);
410
411impl fmt::Debug for AccessedAt {
412 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413 f.debug_tuple("AccessedAt")
414 .field(&self.accessed_at_epoch())
415 .finish()
416 }
417}
418
419impl AccessedAt {
420 pub fn set_accessed(&self, at_epoch: Epoch) {
421 if self.0.load(Ordering::Relaxed) < at_epoch.get() {
425 self.0.store(at_epoch.get(), Ordering::Relaxed);
428 }
429 }
430
431 pub fn accessed_at_epoch(&self) -> u64 {
432 self.0.load(Ordering::Relaxed)
433 }
434}
435
436impl SizeOf for AccessedAt {}