1use core::marker::PhantomData;
2
3use crate::TlsError;
4use crate::cipher_suites::CipherSuite;
5use crate::extensions::extension_data::signature_algorithms::SignatureScheme;
6use crate::extensions::extension_data::supported_groups::NamedGroup;
7pub use crate::handshake::certificate::{CertificateEntryRef, CertificateRef};
8pub use crate::handshake::certificate_verify::CertificateVerifyRef;
9use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, KeyInit};
10use digest::core_api::BlockSizeUser;
11use digest::{Digest, FixedOutput, OutputSizeUser, Reset};
12use ecdsa::elliptic_curve::SecretKey;
13use generic_array::ArrayLength;
14use heapless::Vec;
15use p256::ecdsa::SigningKey;
16use rand_core::CryptoRngCore;
17pub use sha2::{Sha256, Sha384};
18use typenum::{Sum, U10, U12, U16, U32};
19
20pub use crate::extensions::extension_data::max_fragment_length::MaxFragmentLength;
21
22pub const TLS_RECORD_OVERHEAD: usize = 128;
23
24type LongestLabel = U12;
26type LabelOverhead = U10;
27type LabelBuffer<CipherSuite> = Sum<
28 <<CipherSuite as TlsCipherSuite>::Hash as OutputSizeUser>::OutputSize,
29 Sum<LongestLabel, LabelOverhead>,
30>;
31
32pub trait TlsCipherSuite {
34 const CODE_POINT: u16;
35 type Cipher: KeyInit<KeySize = Self::KeyLen> + AeadInPlace<NonceSize = Self::IvLen>;
36 type KeyLen: ArrayLength<u8>;
37 type IvLen: ArrayLength<u8>;
38
39 type Hash: Digest + Reset + Clone + OutputSizeUser + BlockSizeUser + FixedOutput;
40 type LabelBufferSize: ArrayLength<u8>;
41}
42
43pub struct Aes128GcmSha256;
44impl TlsCipherSuite for Aes128GcmSha256 {
45 const CODE_POINT: u16 = CipherSuite::TlsAes128GcmSha256 as u16;
46 type Cipher = Aes128Gcm;
47 type KeyLen = U16;
48 type IvLen = U12;
49
50 type Hash = Sha256;
51 type LabelBufferSize = LabelBuffer<Self>;
52}
53
54pub struct Aes256GcmSha384;
55impl TlsCipherSuite for Aes256GcmSha384 {
56 const CODE_POINT: u16 = CipherSuite::TlsAes256GcmSha384 as u16;
57 type Cipher = Aes256Gcm;
58 type KeyLen = U32;
59 type IvLen = U12;
60
61 type Hash = Sha384;
62 type LabelBufferSize = LabelBuffer<Self>;
63}
64
65pub trait TlsVerifier<CipherSuite>
71where
72 CipherSuite: TlsCipherSuite,
73{
74 fn set_hostname_verification(&mut self, hostname: &str) -> Result<(), crate::TlsError>;
76
77 fn verify_certificate(
83 &mut self,
84 transcript: &CipherSuite::Hash,
85 cert: CertificateRef,
86 ) -> Result<(), TlsError>;
87
88 fn verify_signature(&mut self, verify: CertificateVerifyRef) -> Result<(), crate::TlsError>;
92}
93
94pub struct NoVerify;
95
96impl<CipherSuite> TlsVerifier<CipherSuite> for NoVerify
97where
98 CipherSuite: TlsCipherSuite,
99{
100 fn set_hostname_verification(&mut self, _hostname: &str) -> Result<(), crate::TlsError> {
101 Ok(())
102 }
103
104 fn verify_certificate(
105 &mut self,
106 _transcript: &CipherSuite::Hash,
107 _cert: CertificateRef,
108 ) -> Result<(), TlsError> {
109 Ok(())
110 }
111
112 fn verify_signature(&mut self, _verify: CertificateVerifyRef) -> Result<(), crate::TlsError> {
113 Ok(())
114 }
115}
116
117#[derive(Debug, Clone)]
118#[cfg_attr(feature = "defmt", derive(defmt::Format))]
119#[must_use = "TlsConfig does nothing unless consumed"]
120pub struct TlsConfig<'a> {
121 pub(crate) server_name: Option<&'a str>,
122 pub(crate) alpn_protocols: Option<&'a [&'a [u8]]>,
123 pub(crate) psk: Option<(&'a [u8], Vec<&'a [u8], 4>)>,
124 pub(crate) signature_schemes: Vec<SignatureScheme, 25>,
125 pub(crate) named_groups: Vec<NamedGroup, 13>,
126 pub(crate) max_fragment_length: Option<MaxFragmentLength>,
127}
128
129pub trait TlsClock {
130 fn now() -> Option<u64>;
131}
132
133pub struct NoClock;
134
135impl TlsClock for NoClock {
136 fn now() -> Option<u64> {
137 None
138 }
139}
140
141pub trait CryptoProvider {
142 type CipherSuite: TlsCipherSuite;
143 type Signature: AsRef<[u8]>;
144
145 fn rng(&mut self) -> impl CryptoRngCore;
146
147 fn verifier(&mut self) -> Result<&mut impl TlsVerifier<Self::CipherSuite>, crate::TlsError> {
148 Err::<&mut NoVerify, _>(crate::TlsError::Unimplemented)
149 }
150
151 fn signer(
156 &mut self,
157 ) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
158 {
159 Err::<(NoSign, _), crate::TlsError>(crate::TlsError::Unimplemented)
160 }
161
162 fn client_cert(&mut self) -> Option<Certificate<impl AsRef<[u8]>>> {
169 None::<Certificate<&[u8]>>
170 }
171}
172
173impl<T: CryptoProvider> CryptoProvider for &mut T {
174 type CipherSuite = T::CipherSuite;
175
176 type Signature = T::Signature;
177
178 fn rng(&mut self) -> impl CryptoRngCore {
179 T::rng(self)
180 }
181
182 fn verifier(&mut self) -> Result<&mut impl TlsVerifier<Self::CipherSuite>, crate::TlsError> {
183 T::verifier(self)
184 }
185
186 fn signer(
187 &mut self,
188 ) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
189 {
190 T::signer(self)
191 }
192
193 fn client_cert(&mut self) -> Option<Certificate<impl AsRef<[u8]>>> {
194 T::client_cert(self)
195 }
196}
197
198pub struct NoSign;
199
200impl<S> signature::Signer<S> for NoSign {
201 fn try_sign(&self, _msg: &[u8]) -> Result<S, signature::Error> {
202 unimplemented!()
203 }
204}
205
206pub struct UnsecureProvider<'a, CipherSuite, RNG> {
207 rng: RNG,
208 priv_key: Option<&'a [u8]>,
209 client_cert: Option<Certificate<&'a [u8]>>,
210 _marker: PhantomData<CipherSuite>,
211}
212
213impl<RNG: CryptoRngCore> UnsecureProvider<'_, (), RNG> {
214 pub fn new<CipherSuite: TlsCipherSuite>(
215 rng: RNG,
216 ) -> UnsecureProvider<'static, CipherSuite, RNG> {
217 UnsecureProvider {
218 rng,
219 priv_key: None,
220 client_cert: None,
221 _marker: PhantomData,
222 }
223 }
224}
225
226impl<'a, CipherSuite: TlsCipherSuite, RNG: CryptoRngCore> UnsecureProvider<'a, CipherSuite, RNG> {
227 pub fn with_priv_key(mut self, priv_key: &'a [u8]) -> Self {
228 self.priv_key = Some(priv_key);
229 self
230 }
231
232 pub fn with_cert(mut self, cert: Certificate<&'a [u8]>) -> Self {
233 self.client_cert = Some(cert);
234 self
235 }
236}
237
238impl<CipherSuite: TlsCipherSuite, RNG: CryptoRngCore> CryptoProvider
239 for UnsecureProvider<'_, CipherSuite, RNG>
240{
241 type CipherSuite = CipherSuite;
242 type Signature = p256::ecdsa::DerSignature;
243
244 fn rng(&mut self) -> impl CryptoRngCore {
245 &mut self.rng
246 }
247
248 fn signer(
249 &mut self,
250 ) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
251 {
252 let key_der = self.priv_key.ok_or(TlsError::InvalidPrivateKey)?;
253 let secret_key =
254 SecretKey::from_sec1_der(key_der).map_err(|_| TlsError::InvalidPrivateKey)?;
255
256 Ok((
257 SigningKey::from(&secret_key),
258 SignatureScheme::EcdsaSecp256r1Sha256,
259 ))
260 }
261
262 fn client_cert(&mut self) -> Option<Certificate<impl AsRef<[u8]>>> {
263 self.client_cert.clone()
264 }
265}
266
267#[derive(Debug)]
268#[cfg_attr(feature = "defmt", derive(defmt::Format))]
269pub struct TlsContext<'a, Provider>
270where
271 Provider: CryptoProvider,
272{
273 pub(crate) config: &'a TlsConfig<'a>,
274 pub(crate) crypto_provider: Provider,
275}
276
277impl<'a, Provider> TlsContext<'a, Provider>
278where
279 Provider: CryptoProvider,
280{
281 pub fn new(config: &'a TlsConfig<'a>, crypto_provider: Provider) -> Self {
283 Self {
284 config,
285 crypto_provider,
286 }
287 }
288}
289
290impl<'a> TlsConfig<'a> {
291 pub fn new() -> Self {
292 let mut config = Self {
293 signature_schemes: Vec::new(),
294 named_groups: Vec::new(),
295 max_fragment_length: None,
296 psk: None,
297 server_name: None,
298 alpn_protocols: None,
299 };
300
301 if cfg!(feature = "alloc") {
302 config = config.enable_rsa_signatures();
303 }
304
305 unwrap!(
306 config
307 .signature_schemes
308 .push(SignatureScheme::EcdsaSecp256r1Sha256)
309 .ok()
310 );
311 unwrap!(
312 config
313 .signature_schemes
314 .push(SignatureScheme::EcdsaSecp384r1Sha384)
315 .ok()
316 );
317 unwrap!(config.signature_schemes.push(SignatureScheme::Ed25519).ok());
318
319 unwrap!(config.named_groups.push(NamedGroup::Secp256r1));
320
321 config
322 }
323
324 pub fn enable_rsa_signatures(mut self) -> Self {
326 unwrap!(
327 self.signature_schemes
328 .push(SignatureScheme::RsaPkcs1Sha256)
329 .ok()
330 );
331 unwrap!(
332 self.signature_schemes
333 .push(SignatureScheme::RsaPkcs1Sha384)
334 .ok()
335 );
336 unwrap!(
337 self.signature_schemes
338 .push(SignatureScheme::RsaPkcs1Sha512)
339 .ok()
340 );
341 unwrap!(
342 self.signature_schemes
343 .push(SignatureScheme::RsaPssRsaeSha256)
344 .ok()
345 );
346 unwrap!(
347 self.signature_schemes
348 .push(SignatureScheme::RsaPssRsaeSha384)
349 .ok()
350 );
351 unwrap!(
352 self.signature_schemes
353 .push(SignatureScheme::RsaPssRsaeSha512)
354 .ok()
355 );
356 self
357 }
358
359 pub fn with_server_name(mut self, server_name: &'a str) -> Self {
360 self.server_name = Some(server_name);
361 self
362 }
363
364 pub fn with_alpn(mut self, protocols: &'a [&'a [u8]]) -> Self {
370 self.alpn_protocols = Some(protocols);
371 self
372 }
373
374 pub fn with_max_fragment_length(mut self, max_fragment_length: MaxFragmentLength) -> Self {
393 self.max_fragment_length = Some(max_fragment_length);
394 self
395 }
396
397 pub fn reset_max_fragment_length(mut self) -> Self {
399 self.max_fragment_length = None;
400 self
401 }
402
403 pub fn with_psk(mut self, psk: &'a [u8], identities: &[&'a [u8]]) -> Self {
404 self.psk = Some((psk, unwrap!(Vec::from_slice(identities).ok())));
406 self
407 }
408}
409
410impl Default for TlsConfig<'_> {
411 fn default() -> Self {
412 TlsConfig::new()
413 }
414}
415
416#[derive(Debug, Copy, Clone, PartialEq)]
417#[cfg_attr(feature = "defmt", derive(defmt::Format))]
418pub enum Certificate<D> {
419 X509(D),
420 RawPublicKey(D),
421}