1use crate::cipher_suites::CipherSuite;
2use crate::extensions::extension_data::signature_algorithms::SignatureScheme;
3use crate::extensions::extension_data::supported_groups::NamedGroup;
4use crate::handshake::certificate::CertificateRef;
5use crate::handshake::certificate_verify::CertificateVerify;
6use crate::TlsError;
7use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, KeyInit};
8use core::marker::PhantomData;
9use digest::core_api::BlockSizeUser;
10use digest::{Digest, FixedOutput, OutputSizeUser, Reset};
11use generic_array::ArrayLength;
12use heapless::Vec;
13use rand_core::{CryptoRng, RngCore};
14pub use sha2::Sha256;
15pub use sha2::Sha384;
16use typenum::{Sum, U10, U12, U16, U32};
17
18pub use crate::extensions::extension_data::max_fragment_length::MaxFragmentLength;
19
20pub(crate) const TLS_RECORD_MAX: usize = 16384;
21pub const TLS_RECORD_OVERHEAD: usize = 128;
22
23type LongestLabel = U12;
25type LabelOverhead = U10;
26type LabelBuffer<CipherSuite> = Sum<
27 <<CipherSuite as TlsCipherSuite>::Hash as OutputSizeUser>::OutputSize,
28 Sum<LongestLabel, LabelOverhead>,
29>;
30
31pub trait TlsCipherSuite {
33 const CODE_POINT: u16;
34 type Cipher: KeyInit<KeySize = Self::KeyLen> + AeadInPlace<NonceSize = Self::IvLen>;
35 type KeyLen: ArrayLength<u8>;
36 type IvLen: ArrayLength<u8>;
37
38 type Hash: Digest + Reset + Clone + OutputSizeUser + BlockSizeUser + FixedOutput;
39 type LabelBufferSize: ArrayLength<u8>;
40}
41
42pub struct Aes128GcmSha256;
43impl TlsCipherSuite for Aes128GcmSha256 {
44 const CODE_POINT: u16 = CipherSuite::TlsAes128GcmSha256 as u16;
45 type Cipher = Aes128Gcm;
46 type KeyLen = U16;
47 type IvLen = U12;
48
49 type Hash = Sha256;
50 type LabelBufferSize = LabelBuffer<Self>;
51}
52
53pub struct Aes256GcmSha384;
54impl TlsCipherSuite for Aes256GcmSha384 {
55 const CODE_POINT: u16 = CipherSuite::TlsAes256GcmSha384 as u16;
56 type Cipher = Aes256Gcm;
57 type KeyLen = U32;
58 type IvLen = U12;
59
60 type Hash = Sha384;
61 type LabelBufferSize = LabelBuffer<Self>;
62}
63
64pub trait TlsVerifier<'a, CipherSuite>
70where
71 CipherSuite: TlsCipherSuite,
72{
73 fn new(host: Option<&'a str>) -> Self;
79
80 fn verify_certificate(
86 &mut self,
87 transcript: &CipherSuite::Hash,
88 ca: &Option<Certificate>,
89 cert: CertificateRef,
90 ) -> Result<(), TlsError>;
91
92 fn verify_signature(&mut self, verify: CertificateVerify) -> Result<(), crate::TlsError>;
96}
97
98pub struct NoVerify;
99
100impl<'a, CipherSuite> TlsVerifier<'a, CipherSuite> for NoVerify
101where
102 CipherSuite: TlsCipherSuite,
103{
104 fn new(_host: Option<&str>) -> Self {
105 Self
106 }
107
108 fn verify_certificate(
109 &mut self,
110 _transcript: &CipherSuite::Hash,
111 _ca: &Option<Certificate>,
112 _cert: CertificateRef,
113 ) -> Result<(), TlsError> {
114 Ok(())
115 }
116
117 fn verify_signature(&mut self, _verify: CertificateVerify) -> Result<(), crate::TlsError> {
118 Ok(())
119 }
120}
121
122#[derive(Debug)]
123#[cfg_attr(feature = "defmt", derive(defmt::Format))]
124pub struct TlsConfig<'a, CipherSuite>
125where
126 CipherSuite: TlsCipherSuite,
127{
128 pub(crate) server_name: Option<&'a str>,
130 pub(crate) psk: Option<(&'a [u8], Vec<&'a [u8], 4>)>,
131 pub(crate) cipher_suite: PhantomData<CipherSuite>,
132 pub(crate) signature_schemes: Vec<SignatureScheme, 16>,
133 pub(crate) named_groups: Vec<NamedGroup, 16>,
134 pub(crate) max_fragment_length: Option<MaxFragmentLength>,
135 pub(crate) ca: Option<Certificate<'a>>,
136 pub(crate) cert: Option<Certificate<'a>>,
137}
138
139pub trait TlsClock {
140 fn now() -> Option<u64>;
141}
142
143pub struct NoClock;
144
145impl TlsClock for NoClock {
146 fn now() -> Option<u64> {
147 None
148 }
149}
150
151#[derive(Debug)]
152#[cfg_attr(feature = "defmt", derive(defmt::Format))]
153pub struct TlsContext<'a, CipherSuite, RNG>
154where
155 CipherSuite: TlsCipherSuite,
156 RNG: CryptoRng + RngCore + 'a,
157{
158 pub(crate) config: &'a TlsConfig<'a, CipherSuite>,
159 pub(crate) rng: &'a mut RNG,
160}
161
162impl<'a, CipherSuite, RNG> TlsContext<'a, CipherSuite, RNG>
163where
164 CipherSuite: TlsCipherSuite,
165 RNG: CryptoRng + RngCore + 'a,
166{
167 pub fn new(config: &'a TlsConfig<'a, CipherSuite>, rng: &'a mut RNG) -> Self {
169 Self { config, rng }
170 }
171}
172
173impl<'a, CipherSuite> TlsConfig<'a, CipherSuite>
174where
175 CipherSuite: TlsCipherSuite,
176{
177 pub fn new() -> Self {
178 let mut config = Self {
179 cipher_suite: PhantomData,
180 signature_schemes: Vec::new(),
181 named_groups: Vec::new(),
182 max_fragment_length: None,
183 psk: None,
184 server_name: None,
185 ca: None,
186 cert: None,
187 };
188
189 if cfg!(feature = "alloc") {
192 config = config.enable_rsa_signatures();
193 }
194
195 unwrap!(config
196 .signature_schemes
197 .push(SignatureScheme::EcdsaSecp256r1Sha256)
198 .ok());
199 unwrap!(config
200 .signature_schemes
201 .push(SignatureScheme::EcdsaSecp384r1Sha384)
202 .ok());
203 unwrap!(config.signature_schemes.push(SignatureScheme::Ed25519).ok());
204
205 unwrap!(config.named_groups.push(NamedGroup::Secp256r1));
206
207 config
208 }
209
210 pub fn enable_rsa_signatures(mut self) -> Self {
212 unwrap!(self
213 .signature_schemes
214 .push(SignatureScheme::RsaPkcs1Sha256)
215 .ok());
216 unwrap!(self
217 .signature_schemes
218 .push(SignatureScheme::RsaPkcs1Sha384)
219 .ok());
220 unwrap!(self
221 .signature_schemes
222 .push(SignatureScheme::RsaPkcs1Sha512)
223 .ok());
224 unwrap!(self
225 .signature_schemes
226 .push(SignatureScheme::RsaPssRsaeSha256)
227 .ok());
228 unwrap!(self
229 .signature_schemes
230 .push(SignatureScheme::RsaPssRsaeSha384)
231 .ok());
232 unwrap!(self
233 .signature_schemes
234 .push(SignatureScheme::RsaPssRsaeSha512)
235 .ok());
236 self
237 }
238
239 pub fn with_server_name(mut self, server_name: &'a str) -> Self {
240 self.server_name = Some(server_name);
241 self
242 }
243
244 pub fn with_max_fragment_length(mut self, max_fragment_length: MaxFragmentLength) -> Self {
263 self.max_fragment_length = Some(max_fragment_length);
264 self
265 }
266
267 pub fn reset_max_fragment_length(mut self) -> Self {
269 self.max_fragment_length = None;
270 self
271 }
272
273 pub fn with_ca(mut self, ca: Certificate<'a>) -> Self {
274 self.ca = Some(ca);
275 self
276 }
277
278 pub fn with_cert(mut self, cert: Certificate<'a>) -> Self {
279 self.cert = Some(cert);
280 self
281 }
282
283 pub fn with_psk(mut self, psk: &'a [u8], identities: &[&'a [u8]]) -> Self {
284 self.psk = Some((psk, unwrap!(Vec::from_slice(identities).ok())));
286 self
287 }
288}
289
290impl<'a, CipherSuite> Default for TlsConfig<'a, CipherSuite>
291where
292 CipherSuite: TlsCipherSuite,
293{
294 fn default() -> Self {
295 TlsConfig::new()
296 }
297}
298
299#[derive(Debug, Clone)]
300#[cfg_attr(feature = "defmt", derive(defmt::Format))]
301pub enum Certificate<'a> {
302 X509(&'a [u8]),
303 RawPublicKey(&'a [u8]),
304}