1use alloc::boxed::Box;
2use alloc::string::ToString;
3use core::fmt;
4
5use zeroize::Zeroize;
6
7use crate::enums::{ContentType, ProtocolVersion};
8use crate::error::Error;
9use crate::msgs::codec;
10pub use crate::msgs::message::{
11 BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage, OutboundChunks,
12 OutboundOpaqueMessage, OutboundPlainMessage, PlainMessage, PrefixedPayload,
13};
14use crate::suites::ConnectionTrafficSecrets;
15
16pub trait Tls13AeadAlgorithm: Send + Sync {
18 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter>;
20
21 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter>;
23
24 fn key_len(&self) -> usize;
26
27 fn extract_keys(
32 &self,
33 key: AeadKey,
34 iv: Iv,
35 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
36
37 fn fips(&self) -> bool {
39 false
40 }
41}
42
43pub trait Tls12AeadAlgorithm: Send + Sync + 'static {
45 fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter>;
54
55 fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter>;
61
62 fn key_block_shape(&self) -> KeyBlockShape;
65
66 fn extract_keys(
77 &self,
78 key: AeadKey,
79 iv: &[u8],
80 explicit: &[u8],
81 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
82
83 fn fips(&self) -> bool {
85 false
86 }
87}
88
89#[allow(clippy::exhaustive_structs)]
91#[derive(Debug, Eq, PartialEq, Clone, Copy)]
92pub struct UnsupportedOperationError;
93
94impl From<UnsupportedOperationError> for Error {
95 fn from(value: UnsupportedOperationError) -> Self {
96 Self::General(value.to_string())
97 }
98}
99
100impl fmt::Display for UnsupportedOperationError {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "operation not supported")
103 }
104}
105
106#[cfg(feature = "std")]
107impl std::error::Error for UnsupportedOperationError {}
108
109#[allow(clippy::exhaustive_structs)]
113pub struct KeyBlockShape {
114 pub enc_key_len: usize,
120
121 pub fixed_iv_len: usize,
130
131 pub explicit_nonce_len: usize,
136}
137
138pub trait MessageDecrypter: Send + Sync {
140 fn decrypt<'a>(
143 &mut self,
144 msg: InboundOpaqueMessage<'a>,
145 seq: u64,
146 ) -> Result<InboundPlainMessage<'a>, Error>;
147}
148
149pub trait MessageEncrypter: Send + Sync {
151 fn encrypt(
154 &mut self,
155 msg: OutboundPlainMessage<'_>,
156 seq: u64,
157 ) -> Result<OutboundOpaqueMessage, Error>;
158
159 fn encrypted_payload_len(&self, payload_len: usize) -> usize;
162}
163
164impl dyn MessageEncrypter {
165 pub(crate) fn invalid() -> Box<dyn MessageEncrypter> {
166 Box::new(InvalidMessageEncrypter {})
167 }
168}
169
170impl dyn MessageDecrypter {
171 pub(crate) fn invalid() -> Box<dyn MessageDecrypter> {
172 Box::new(InvalidMessageDecrypter {})
173 }
174}
175
176#[derive(Default)]
178pub struct Iv([u8; NONCE_LEN]);
179
180impl Iv {
181 pub fn new(value: [u8; NONCE_LEN]) -> Self {
183 Self(value)
184 }
185
186 pub fn copy(value: &[u8]) -> Self {
188 debug_assert_eq!(value.len(), NONCE_LEN);
189 let mut iv = Self::new(Default::default());
190 iv.0.copy_from_slice(value);
191 iv
192 }
193}
194
195impl From<[u8; NONCE_LEN]> for Iv {
196 fn from(bytes: [u8; NONCE_LEN]) -> Self {
197 Self(bytes)
198 }
199}
200
201impl AsRef<[u8]> for Iv {
202 fn as_ref(&self) -> &[u8] {
203 self.0.as_ref()
204 }
205}
206
207#[allow(clippy::exhaustive_structs)]
209pub struct Nonce(pub [u8; NONCE_LEN]);
210
211impl Nonce {
212 #[inline]
216 pub fn new(iv: &Iv, seq: u64) -> Self {
217 Self::new_inner(None, iv, seq)
218 }
219
220 pub fn quic(path_id: Option<u32>, iv: &Iv, pn: u64) -> Self {
225 Self::new_inner(path_id, iv, pn)
226 }
227
228 #[inline]
230 fn new_inner(path_id: Option<u32>, iv: &Iv, seq: u64) -> Self {
231 let mut seq_bytes = [0u8; NONCE_LEN];
232 codec::put_u64(seq, &mut seq_bytes[4..]);
233 if let Some(path_id) = path_id {
234 seq_bytes[0..4].copy_from_slice(&path_id.to_be_bytes());
235 }
236
237 seq_bytes
238 .iter_mut()
239 .zip(iv.0.iter())
240 .for_each(|(s, iv)| {
241 *s ^= *iv;
242 });
243
244 Self(seq_bytes)
245 }
246}
247
248pub const NONCE_LEN: usize = 12;
251
252#[inline]
256pub fn make_tls13_aad(payload_len: usize) -> [u8; 5] {
257 let version = ProtocolVersion::TLSv1_2.to_array();
258 [
259 ContentType::ApplicationData.into(),
260 version[0],
262 version[1],
263 (payload_len >> 8) as u8,
264 (payload_len & 0xff) as u8,
265 ]
266}
267
268#[inline]
272pub fn make_tls12_aad(
273 seq: u64,
274 typ: ContentType,
275 vers: ProtocolVersion,
276 len: usize,
277) -> [u8; TLS12_AAD_SIZE] {
278 let mut out = [0; TLS12_AAD_SIZE];
279 codec::put_u64(seq, &mut out[0..]);
280 out[8] = typ.into();
281 codec::put_u16(vers.into(), &mut out[9..]);
282 codec::put_u16(len as u16, &mut out[11..]);
283 out
284}
285
286const TLS12_AAD_SIZE: usize = 8 + 1 + 2 + 2;
287
288pub struct AeadKey {
292 buf: [u8; Self::MAX_LEN],
293 used: usize,
294}
295
296impl AeadKey {
297 pub(crate) fn new(buf: &[u8]) -> Self {
298 debug_assert!(buf.len() <= Self::MAX_LEN);
299 let mut key = Self::from([0u8; Self::MAX_LEN]);
300 key.buf[..buf.len()].copy_from_slice(buf);
301 key.used = buf.len();
302 key
303 }
304
305 pub(crate) fn with_length(self, len: usize) -> Self {
306 assert!(len <= self.used);
307 Self {
308 buf: self.buf,
309 used: len,
310 }
311 }
312
313 pub(crate) const MAX_LEN: usize = 32;
315}
316
317impl Drop for AeadKey {
318 fn drop(&mut self) {
319 self.buf.zeroize();
320 }
321}
322
323impl AsRef<[u8]> for AeadKey {
324 fn as_ref(&self) -> &[u8] {
325 &self.buf[..self.used]
326 }
327}
328
329impl From<[u8; Self::MAX_LEN]> for AeadKey {
330 fn from(bytes: [u8; Self::MAX_LEN]) -> Self {
331 Self {
332 buf: bytes,
333 used: Self::MAX_LEN,
334 }
335 }
336}
337
338struct InvalidMessageEncrypter {}
340
341impl MessageEncrypter for InvalidMessageEncrypter {
342 fn encrypt(
343 &mut self,
344 _m: OutboundPlainMessage<'_>,
345 _seq: u64,
346 ) -> Result<OutboundOpaqueMessage, Error> {
347 Err(Error::EncryptError)
348 }
349
350 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
351 payload_len
352 }
353}
354
355struct InvalidMessageDecrypter {}
357
358impl MessageDecrypter for InvalidMessageDecrypter {
359 fn decrypt<'a>(
360 &mut self,
361 _m: InboundOpaqueMessage<'a>,
362 _seq: u64,
363 ) -> Result<InboundPlainMessage<'a>, Error> {
364 Err(Error::DecryptError)
365 }
366}
367#[cfg(test)]
368mod tests {
369 use super::*;
370
371 #[test]
374 fn multipath_nonce() {
375 const PATH_ID: u32 = 3;
376 const PN: u64 = 54321;
377 const IV: [u8; 16] = 0x6b26114b9cba2b63a9e8dd4fu128.to_be_bytes();
378 const EXPECTED_NONCE: [u8; 16] = 0x6b2611489cba2b63a9e8097eu128.to_be_bytes();
379 let nonce = Nonce::quic(Some(PATH_ID), &Iv::copy(&IV[4..]), PN).0;
380 assert_eq!(EXPECTED_NONCE[4..], nonce);
381 }
382}