s2n_quic_core/
token.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    connection,
6    event::{api::SocketAddress, IntoEvent},
7    inet, random,
8};
9
10#[non_exhaustive]
11pub struct Context<'a> {
12    pub remote_address: SocketAddress<'a>,
13    pub peer_connection_id: &'a [u8],
14    pub random: &'a mut dyn random::Generator,
15}
16
17impl<'a> Context<'a> {
18    #[inline]
19    #[doc(hidden)]
20    pub fn new(
21        remote_address: &'a inet::SocketAddress,
22        peer_connection_id: &'a connection::PeerId,
23        random: &'a mut dyn random::Generator,
24    ) -> Self {
25        Self {
26            remote_address: remote_address.into_event(),
27            peer_connection_id: peer_connection_id.as_bytes(),
28            random,
29        }
30    }
31}
32
33pub trait Format: 'static + Send {
34    const TOKEN_LEN: usize;
35
36    /// Generate a signed token to be delivered in a NEW_TOKEN frame.
37    /// This function will only be called if the provider support NEW_TOKEN frames.
38    fn generate_new_token(
39        &mut self,
40        context: &mut Context<'_>,
41        source_connection_id: &connection::LocalId,
42        output_buffer: &mut [u8],
43    ) -> Option<()>;
44
45    /// Generate a signed token to be delivered in a Retry Packet
46    fn generate_retry_token(
47        &mut self,
48        context: &mut Context<'_>,
49        original_destination_connection_id: &connection::InitialId,
50        output_buffer: &mut [u8],
51    ) -> Option<()>;
52
53    /// Return the original destination connection id of a valid token.
54    /// If the token is invalid, return None.
55    /// Callers should detect duplicate tokens and treat them as invalid.
56    fn validate_token(
57        &mut self,
58        context: &mut Context<'_>,
59        token: &[u8],
60    ) -> Option<connection::InitialId>;
61}
62
63#[derive(Clone, Copy, Debug, Eq, PartialEq)]
64pub enum Source {
65    RetryPacket,
66    NewTokenFrame,
67}
68
69#[cfg(any(test, feature = "testing"))]
70pub mod testing {
71    use super::*;
72    use crate::crypto::retry;
73
74    #[derive(Debug, Default)]
75    pub struct Format(());
76
77    impl super::Format for Format {
78        const TOKEN_LEN: usize = retry::example::TOKEN_LEN;
79
80        fn generate_new_token(
81            &mut self,
82            _context: &mut Context<'_>,
83            _source_connection_id: &connection::LocalId,
84            _output_buffer: &mut [u8],
85        ) -> Option<()> {
86            // TODO implement one for testing
87            None
88        }
89
90        fn generate_retry_token(
91            &mut self,
92            _context: &mut Context<'_>,
93            _original_destination_connection_id: &connection::InitialId,
94            output_buffer: &mut [u8],
95        ) -> Option<()> {
96            output_buffer.copy_from_slice(&retry::example::TOKEN);
97            Some(())
98        }
99
100        fn validate_token(
101            &mut self,
102            _context: &mut Context<'_>,
103            token: &[u8],
104        ) -> Option<connection::InitialId> {
105            if token == retry::example::TOKEN {
106                return Some(connection::InitialId::TEST_ID);
107            }
108
109            None
110        }
111    }
112
113    impl Format {
114        pub fn new() -> Self {
115            Self(())
116        }
117    }
118}