ytls_record/builder/
static_record.rs

1//! Static Record Builder
2
3use crate::error::BuilderError;
4use crate::RecordBuffer;
5use crate::WrappedRecordBuffer;
6
7use ytls_traits::ClientHandshakeFinishedBuilder;
8use ytls_traits::ClientHelloBuilder;
9use ytls_traits::EncryptedExtensionsBuilder;
10use ytls_traits::HandshakeBuilder;
11use ytls_traits::ServerCertificateVerifyBuilder;
12use ytls_traits::ServerCertificatesBuilder;
13use ytls_traits::ServerHandshakeFinishedBuilder;
14use ytls_traits::ServerHelloBuilder;
15use ytls_traits::WrappedApplicationBuilder;
16use ytls_traits::WrappedHandshakeBuilder;
17
18/// Provides statically allocated Record Builder based on worst case
19/// estimation of the maximum size of record.
20/// Typically record sizes need to be also limited based on the record
21/// limit extension but this has to be done in runtime.
22#[derive(Debug, PartialEq)]
23pub struct StaticRecordBuilder<const N: usize> {
24    rec_buf: RecordBuffer<N>,
25}
26
27use crate::builder::b_wrap_application_data::BufStaticAppData;
28use crate::WrappedAppRecordBuffer;
29
30/// Same as [`StaticRecordBuilder`] but in the Application context instead of handshake
31#[derive(Debug, PartialEq)]
32pub struct WrappedAppStaticRecordBuilder<const N: usize> {
33    rec_buf: WrappedAppRecordBuffer<N>,
34}
35
36impl<const N: usize> WrappedApplicationBuilder for WrappedAppStaticRecordBuilder<N> {
37    type Error = BuilderError;
38    /// Construct handshake server finished
39    fn application_data(s: &[u8]) -> Result<Self, Self::Error> {
40        Ok(Self {
41            rec_buf: WrappedAppRecordBuffer::<N>::AppData(
42                BufStaticAppData::<N>::static_from_untyped(s)?,
43            ),
44        })
45    }
46    #[inline]
47    fn as_disjoint_mut_for_aead(&mut self) -> Result<[&mut [u8]; 2], Self::Error> {
48        match self.rec_buf {
49            WrappedAppRecordBuffer::AppData(ref mut s) => s.as_disjoint_mut_for_aead(),
50        }
51    }
52    #[inline]
53    fn set_auth_tag(&mut self, new_tag: &[u8; 16]) {
54        match self.rec_buf {
55            WrappedAppRecordBuffer::AppData(ref mut s) => s.set_auth_tag(new_tag),
56        }
57    }
58    #[inline]
59    fn as_ciphertext_mut(&mut self) -> &mut [u8] {
60        match self.rec_buf {
61            WrappedAppRecordBuffer::AppData(ref mut s) => s.as_ciphertext_mut(),
62        }
63    }
64    #[inline]
65    fn wrapped_hash_header_ref(&self) -> [u8; 5] {
66        match self.rec_buf {
67            WrappedAppRecordBuffer::AppData(ref s) => s.wrapped_hash_header_ref(),
68        }
69    }
70    #[inline]
71    fn as_hashing_context_ref(&self) -> &[u8] {
72        match self.rec_buf {
73            WrappedAppRecordBuffer::AppData(ref s) => &s.as_hashing_context_ref(),
74        }
75    }
76    #[inline]
77    fn as_encoded_bytes(&self) -> &[u8] {
78        match self.rec_buf {
79            WrappedAppRecordBuffer::AppData(ref s) => &s.as_encoded_bytes(),
80        }
81    }
82}
83
84/// Same as [`StaticRecordBuilder`] but provides wrapping into TLS1.2 AppData
85/// which is typically used when the records are AEAD'd to preserve compatibility
86/// with the middleboxes.
87#[derive(Debug, PartialEq)]
88pub struct WrappedStaticRecordBuilder<const N: usize> {
89    rec_buf: WrappedRecordBuffer<N>,
90}
91
92use super::b_dhs_client_handshake_finished::BufStaticClientHandshakeFinished;
93use super::b_dhs_encrypted_extensions::BufStaticEncryptedExtensions;
94use super::b_dhs_server_certificate::BufStaticServerCertificates;
95use super::b_dhs_server_certificate_verify::BufStaticServerCertificateVerify;
96use super::b_dhs_server_handshake_finished::BufStaticServerHandshakeFinished;
97
98impl<const N: usize> WrappedHandshakeBuilder for WrappedStaticRecordBuilder<N> {
99    type Error = BuilderError;
100    /// Construct handshake client finished
101    #[inline]
102    fn client_handshake_finished<S: ClientHandshakeFinishedBuilder>(
103        s: &S,
104    ) -> Result<Self, Self::Error> {
105        Ok(Self {
106            rec_buf: WrappedRecordBuffer::<N>::ClientHandshakeFinished(
107                BufStaticClientHandshakeFinished::<N>::static_from_untyped(s)?,
108            ),
109        })
110    }
111    /// Construct handshake server finished
112    #[inline]
113    fn server_handshake_finished<S: ServerHandshakeFinishedBuilder>(
114        s: &S,
115    ) -> Result<Self, Self::Error> {
116        Ok(Self {
117            rec_buf: WrappedRecordBuffer::<N>::ServerHandshakeFinished(
118                BufStaticServerHandshakeFinished::<N>::static_from_untyped(s)?,
119            ),
120        })
121    }
122    /// Construct handshake server certificate/s.
123    #[inline]
124    fn server_certificates<S: ServerCertificatesBuilder>(s: &S) -> Result<Self, Self::Error> {
125        Ok(Self {
126            rec_buf: WrappedRecordBuffer::<N>::ServerCertificates(
127                BufStaticServerCertificates::<N>::static_from_untyped(s)?,
128            ),
129        })
130    }
131    /// Construct handshake server certificate verify.
132    #[inline]
133    fn server_certificate_verify<S: ServerCertificateVerifyBuilder>(
134        s: &S,
135    ) -> Result<Self, Self::Error> {
136        Ok(Self {
137            rec_buf: WrappedRecordBuffer::<N>::ServerCertificateVerify(
138                BufStaticServerCertificateVerify::<N>::static_from_untyped(s)?,
139            ),
140        })
141    }
142    /// Construct handshake encrypted extensions.
143    #[inline]
144    fn encrypted_extensions<S: EncryptedExtensionsBuilder>(s: &S) -> Result<Self, Self::Error> {
145        Ok(Self {
146            rec_buf: WrappedRecordBuffer::<N>::EncryptedExtensions(BufStaticEncryptedExtensions::<
147                N,
148            >::static_from_untyped(
149                s
150            )?),
151        })
152    }
153    #[inline]
154    fn as_disjoint_mut_for_aead(&mut self) -> Result<[&mut [u8]; 2], Self::Error> {
155        match self.rec_buf {
156            WrappedRecordBuffer::ServerCertificates(ref mut s) => s.as_disjoint_mut_for_aead(),
157            WrappedRecordBuffer::ServerCertificateVerify(ref mut s) => s.as_disjoint_mut_for_aead(),
158            WrappedRecordBuffer::EncryptedExtensions(ref mut s) => s.as_disjoint_mut_for_aead(),
159            WrappedRecordBuffer::ServerHandshakeFinished(ref mut s) => s.as_disjoint_mut_for_aead(),
160            WrappedRecordBuffer::ClientHandshakeFinished(ref mut s) => s.as_disjoint_mut_for_aead(),
161        }
162    }
163    #[inline]
164    fn set_auth_tag(&mut self, new_tag: &[u8; 16]) {
165        match self.rec_buf {
166            WrappedRecordBuffer::ServerCertificates(ref mut s) => s.set_auth_tag(new_tag),
167            WrappedRecordBuffer::ServerCertificateVerify(ref mut s) => s.set_auth_tag(new_tag),
168            WrappedRecordBuffer::EncryptedExtensions(ref mut s) => s.set_auth_tag(new_tag),
169            WrappedRecordBuffer::ServerHandshakeFinished(ref mut s) => s.set_auth_tag(new_tag),
170            WrappedRecordBuffer::ClientHandshakeFinished(ref mut s) => s.set_auth_tag(new_tag),
171        }
172    }
173    #[inline]
174    fn as_ciphertext_mut(&mut self) -> &mut [u8] {
175        match self.rec_buf {
176            WrappedRecordBuffer::ServerCertificates(ref mut s) => s.as_ciphertext_mut(),
177            WrappedRecordBuffer::ServerCertificateVerify(ref mut s) => s.as_ciphertext_mut(),
178            WrappedRecordBuffer::EncryptedExtensions(ref mut s) => s.as_ciphertext_mut(),
179            WrappedRecordBuffer::ServerHandshakeFinished(ref mut s) => s.as_ciphertext_mut(),
180            WrappedRecordBuffer::ClientHandshakeFinished(ref mut s) => s.as_ciphertext_mut(),
181        }
182    }
183    #[inline]
184    fn wrapped_hash_header_ref(&self) -> [u8; 5] {
185        match self.rec_buf {
186            WrappedRecordBuffer::ServerCertificates(ref s) => s.wrapped_hash_header_ref(),
187            WrappedRecordBuffer::ServerCertificateVerify(ref s) => s.wrapped_hash_header_ref(),
188            WrappedRecordBuffer::EncryptedExtensions(ref s) => s.wrapped_hash_header_ref(),
189            WrappedRecordBuffer::ServerHandshakeFinished(ref s) => s.wrapped_hash_header_ref(),
190            WrappedRecordBuffer::ClientHandshakeFinished(ref s) => s.wrapped_hash_header_ref(),
191        }
192    }
193    #[inline]
194    fn as_hashing_context_ref(&self) -> &[u8] {
195        match self.rec_buf {
196            WrappedRecordBuffer::ServerCertificates(ref s) => &s.as_hashing_context_ref(),
197            WrappedRecordBuffer::ServerCertificateVerify(ref s) => &s.as_hashing_context_ref(),
198            WrappedRecordBuffer::EncryptedExtensions(ref s) => &s.as_hashing_context_ref(),
199            WrappedRecordBuffer::ServerHandshakeFinished(ref s) => &s.as_hashing_context_ref(),
200            WrappedRecordBuffer::ClientHandshakeFinished(ref s) => &s.as_hashing_context_ref(),
201        }
202    }
203    #[inline]
204    fn as_encoded_bytes(&self) -> &[u8] {
205        match self.rec_buf {
206            WrappedRecordBuffer::ServerCertificates(ref s) => &s.as_encoded_bytes(),
207            WrappedRecordBuffer::ServerCertificateVerify(ref s) => &s.as_encoded_bytes(),
208            WrappedRecordBuffer::EncryptedExtensions(ref s) => &s.as_encoded_bytes(),
209            WrappedRecordBuffer::ServerHandshakeFinished(ref s) => &s.as_encoded_bytes(),
210            WrappedRecordBuffer::ClientHandshakeFinished(ref s) => &s.as_encoded_bytes(),
211        }
212    }
213}
214
215impl<const N: usize> HandshakeBuilder for StaticRecordBuilder<N> {
216    type Error = BuilderError;
217    /// Construct a handshake record featuring a Client Hello from untyped raw data.
218    #[inline]
219    fn client_hello_untyped<S: ClientHelloBuilder>(s: &S) -> Result<Self, Self::Error> {
220        Ok(Self {
221            rec_buf: RecordBuffer::<N>::ClientHello(super::b_client_hello::BufStaticClientHello::<
222                N,
223            >::static_from_untyped(s)?),
224        })
225    }
226    /// Construct a Handshake record featuring a Server Hello from untyped raw data.
227    #[inline]
228    fn server_hello_untyped<S: ServerHelloBuilder>(s: &S) -> Result<Self, Self::Error> {
229        Ok(Self {
230            rec_buf: RecordBuffer::<N>::ServerHello(super::b_server_hello::BufStaticServerHello::<
231                N,
232            >::static_from_untyped(s)?),
233        })
234    }
235    #[inline]
236    fn as_hashing_context(&self) -> &[u8] {
237        match self.rec_buf {
238            RecordBuffer::ClientHello(ref h) => &h.as_hashing_context(),
239            RecordBuffer::ServerHello(ref h) => &h.as_hashing_context(),
240        }
241    }
242    #[inline]
243    fn as_encoded_bytes(&self) -> &[u8] {
244        match self.rec_buf {
245            RecordBuffer::ClientHello(ref h) => &h.as_encoded_bytes(),
246            RecordBuffer::ServerHello(ref h) => &h.as_encoded_bytes(),
247        }
248    }
249}