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