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;
7use crate::handshake::certificate::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 ca: &Option<Certificate>,
86 cert: CertificateRef,
87 ) -> Result<(), TlsError>;
88
89 fn verify_signature(&mut self, verify: CertificateVerifyRef) -> Result<(), crate::TlsError>;
93}
94
95pub struct NoVerify;
96
97impl<CipherSuite> TlsVerifier<CipherSuite> for NoVerify
98where
99 CipherSuite: TlsCipherSuite,
100{
101 fn set_hostname_verification(&mut self, _hostname: &str) -> Result<(), crate::TlsError> {
102 Ok(())
103 }
104
105 fn verify_certificate(
106 &mut self,
107 _transcript: &CipherSuite::Hash,
108 _ca: &Option<Certificate>,
109 _cert: CertificateRef,
110 ) -> Result<(), TlsError> {
111 Ok(())
112 }
113
114 fn verify_signature(&mut self, _verify: CertificateVerifyRef) -> Result<(), crate::TlsError> {
115 Ok(())
116 }
117}
118
119#[derive(Debug, Clone)]
120#[cfg_attr(feature = "defmt", derive(defmt::Format))]
121#[must_use = "TlsConfig does nothing unless consumed"]
122pub struct TlsConfig<'a> {
123 pub(crate) server_name: Option<&'a str>,
124 pub(crate) psk: Option<(&'a [u8], Vec<&'a [u8], 4>)>,
125 pub(crate) signature_schemes: Vec<SignatureScheme, 25>,
126 pub(crate) named_groups: Vec<NamedGroup, 13>,
127 pub(crate) max_fragment_length: Option<MaxFragmentLength>,
128 pub(crate) ca: Option<Certificate<'a>>,
129 pub(crate) cert: Option<Certificate<'a>>,
130 pub(crate) priv_key: &'a [u8],
131}
132
133pub trait TlsClock {
134 fn now() -> Option<u64>;
135}
136
137pub struct NoClock;
138
139impl TlsClock for NoClock {
140 fn now() -> Option<u64> {
141 None
142 }
143}
144
145pub trait CryptoProvider {
146 type CipherSuite: TlsCipherSuite;
147 type Signature: AsRef<[u8]>;
148
149 fn rng(&mut self) -> impl CryptoRngCore;
150
151 fn verifier(&mut self) -> Result<&mut impl TlsVerifier<Self::CipherSuite>, crate::TlsError> {
152 Err::<&mut NoVerify, _>(crate::TlsError::Unimplemented)
153 }
154
155 fn signer(
157 &mut self,
158 _key_der: &[u8],
159 ) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
160 {
161 Err::<(NoSign, _), crate::TlsError>(crate::TlsError::Unimplemented)
162 }
163}
164
165impl<T: CryptoProvider> CryptoProvider for &mut T {
166 type CipherSuite = T::CipherSuite;
167
168 type Signature = T::Signature;
169
170 fn rng(&mut self) -> impl CryptoRngCore {
171 T::rng(self)
172 }
173
174 fn verifier(&mut self) -> Result<&mut impl TlsVerifier<Self::CipherSuite>, crate::TlsError> {
175 T::verifier(self)
176 }
177
178 fn signer(
179 &mut self,
180 key_der: &[u8],
181 ) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
182 {
183 T::signer(self, key_der)
184 }
185}
186
187pub struct NoSign;
188
189impl<S> signature::Signer<S> for NoSign {
190 fn try_sign(&self, _msg: &[u8]) -> Result<S, signature::Error> {
191 unimplemented!()
192 }
193}
194
195pub struct UnsecureProvider<CipherSuite, RNG> {
196 rng: RNG,
197 _marker: PhantomData<CipherSuite>,
198}
199
200impl<RNG: CryptoRngCore> UnsecureProvider<(), RNG> {
201 pub fn new<CipherSuite: TlsCipherSuite>(rng: RNG) -> UnsecureProvider<CipherSuite, RNG> {
202 UnsecureProvider {
203 rng,
204 _marker: PhantomData,
205 }
206 }
207}
208
209impl<CipherSuite: TlsCipherSuite, RNG: CryptoRngCore> CryptoProvider
210 for UnsecureProvider<CipherSuite, RNG>
211{
212 type CipherSuite = CipherSuite;
213 type Signature = p256::ecdsa::DerSignature;
214
215 fn rng(&mut self) -> impl CryptoRngCore {
216 &mut self.rng
217 }
218
219 fn signer(
220 &mut self,
221 key_der: &[u8],
222 ) -> Result<(impl signature::SignerMut<Self::Signature>, SignatureScheme), crate::TlsError>
223 {
224 let secret_key =
225 SecretKey::from_sec1_der(key_der).map_err(|_| TlsError::InvalidPrivateKey)?;
226
227 Ok((
228 SigningKey::from(&secret_key),
229 SignatureScheme::EcdsaSecp256r1Sha256,
230 ))
231 }
232}
233
234#[derive(Debug)]
235#[cfg_attr(feature = "defmt", derive(defmt::Format))]
236pub struct TlsContext<'a, Provider>
237where
238 Provider: CryptoProvider,
239{
240 pub(crate) config: &'a TlsConfig<'a>,
241 pub(crate) crypto_provider: Provider,
242}
243
244impl<'a, Provider> TlsContext<'a, Provider>
245where
246 Provider: CryptoProvider,
247{
248 pub fn new(config: &'a TlsConfig<'a>, crypto_provider: Provider) -> Self {
250 Self {
251 config,
252 crypto_provider,
253 }
254 }
255}
256
257impl<'a> TlsConfig<'a> {
258 pub fn new() -> Self {
259 let mut config = Self {
260 signature_schemes: Vec::new(),
261 named_groups: Vec::new(),
262 max_fragment_length: None,
263 psk: None,
264 server_name: None,
265 ca: None,
266 cert: None,
267 priv_key: &[],
268 };
269
270 if cfg!(feature = "alloc") {
271 config = config.enable_rsa_signatures();
272 }
273
274 unwrap!(
275 config
276 .signature_schemes
277 .push(SignatureScheme::EcdsaSecp256r1Sha256)
278 .ok()
279 );
280 unwrap!(
281 config
282 .signature_schemes
283 .push(SignatureScheme::EcdsaSecp384r1Sha384)
284 .ok()
285 );
286 unwrap!(config.signature_schemes.push(SignatureScheme::Ed25519).ok());
287
288 unwrap!(config.named_groups.push(NamedGroup::Secp256r1));
289
290 config
291 }
292
293 pub fn enable_rsa_signatures(mut self) -> Self {
295 unwrap!(
296 self.signature_schemes
297 .push(SignatureScheme::RsaPkcs1Sha256)
298 .ok()
299 );
300 unwrap!(
301 self.signature_schemes
302 .push(SignatureScheme::RsaPkcs1Sha384)
303 .ok()
304 );
305 unwrap!(
306 self.signature_schemes
307 .push(SignatureScheme::RsaPkcs1Sha512)
308 .ok()
309 );
310 unwrap!(
311 self.signature_schemes
312 .push(SignatureScheme::RsaPssRsaeSha256)
313 .ok()
314 );
315 unwrap!(
316 self.signature_schemes
317 .push(SignatureScheme::RsaPssRsaeSha384)
318 .ok()
319 );
320 unwrap!(
321 self.signature_schemes
322 .push(SignatureScheme::RsaPssRsaeSha512)
323 .ok()
324 );
325 self
326 }
327
328 pub fn with_server_name(mut self, server_name: &'a str) -> Self {
329 self.server_name = Some(server_name);
330 self
331 }
332
333 pub fn with_max_fragment_length(mut self, max_fragment_length: MaxFragmentLength) -> Self {
352 self.max_fragment_length = Some(max_fragment_length);
353 self
354 }
355
356 pub fn reset_max_fragment_length(mut self) -> Self {
358 self.max_fragment_length = None;
359 self
360 }
361
362 pub fn with_ca(mut self, ca: Certificate<'a>) -> Self {
363 self.ca = Some(ca);
364 self
365 }
366
367 pub fn with_cert(mut self, cert: Certificate<'a>) -> Self {
368 self.cert = Some(cert);
369 self
370 }
371
372 pub fn with_priv_key(mut self, priv_key: &'a [u8]) -> Self {
373 self.priv_key = priv_key;
374 self
375 }
376
377 pub fn with_psk(mut self, psk: &'a [u8], identities: &[&'a [u8]]) -> Self {
378 self.psk = Some((psk, unwrap!(Vec::from_slice(identities).ok())));
380 self
381 }
382}
383
384impl Default for TlsConfig<'_> {
385 fn default() -> Self {
386 TlsConfig::new()
387 }
388}
389
390#[derive(Debug, Clone)]
391#[cfg_attr(feature = "defmt", derive(defmt::Format))]
392pub enum Certificate<'a> {
393 X509(&'a [u8]),
394 RawPublicKey(&'a [u8]),
395}