1 | use alloc::boxed::Box; |
2 | use alloc::string::ToString; |
3 | use core::fmt; |
4 | |
5 | use zeroize::Zeroize; |
6 | |
7 | use crate::enums::{ContentType, ProtocolVersion}; |
8 | use crate::error::Error; |
9 | use crate::msgs::codec; |
10 | pub use crate::msgs::message::{ |
11 | BorrowedPayload, InboundOpaqueMessage, InboundPlainMessage, OutboundChunks, |
12 | OutboundOpaqueMessage, OutboundPlainMessage, PlainMessage, PrefixedPayload, |
13 | }; |
14 | use crate::suites::ConnectionTrafficSecrets; |
15 | |
16 | /// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.3 cipher suite. |
17 | pub trait Tls13AeadAlgorithm: Send + Sync { |
18 | /// Build a `MessageEncrypter` for the given key/iv. |
19 | fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter>; |
20 | |
21 | /// Build a `MessageDecrypter` for the given key/iv. |
22 | fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter>; |
23 | |
24 | /// The length of key in bytes required by `encrypter()` and `decrypter()`. |
25 | fn key_len(&self) -> usize; |
26 | |
27 | /// Convert the key material from `key`/`iv`, into a `ConnectionTrafficSecrets` item. |
28 | /// |
29 | /// May return [`UnsupportedOperationError`] if the AEAD algorithm is not a supported |
30 | /// variant of `ConnectionTrafficSecrets`. |
31 | fn extract_keys( |
32 | &self, |
33 | key: AeadKey, |
34 | iv: Iv, |
35 | ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>; |
36 | |
37 | /// Return `true` if this is backed by a FIPS-approved implementation. |
38 | fn fips(&self) -> bool { |
39 | false |
40 | } |
41 | } |
42 | |
43 | /// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.2 cipher suite. |
44 | pub trait Tls12AeadAlgorithm: Send + Sync + 'static { |
45 | /// Build a `MessageEncrypter` for the given key/iv and extra key block (which can be used for |
46 | /// improving explicit nonce size security, if needed). |
47 | /// |
48 | /// The length of `key` is set by [`KeyBlockShape::enc_key_len`]. |
49 | /// |
50 | /// The length of `iv` is set by [`KeyBlockShape::fixed_iv_len`]. |
51 | /// |
52 | /// The length of `extra` is set by [`KeyBlockShape::explicit_nonce_len`]. |
53 | fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter>; |
54 | |
55 | /// Build a `MessageDecrypter` for the given key/iv. |
56 | /// |
57 | /// The length of `key` is set by [`KeyBlockShape::enc_key_len`]. |
58 | /// |
59 | /// The length of `iv` is set by [`KeyBlockShape::fixed_iv_len`]. |
60 | fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter>; |
61 | |
62 | /// Return a `KeyBlockShape` that defines how large the `key_block` is and how it |
63 | /// is split up prior to calling `encrypter()`, `decrypter()` and/or `extract_keys()`. |
64 | fn key_block_shape(&self) -> KeyBlockShape; |
65 | |
66 | /// Convert the key material from `key`/`iv`, into a `ConnectionTrafficSecrets` item. |
67 | /// |
68 | /// The length of `key` is set by [`KeyBlockShape::enc_key_len`]. |
69 | /// |
70 | /// The length of `iv` is set by [`KeyBlockShape::fixed_iv_len`]. |
71 | /// |
72 | /// The length of `extra` is set by [`KeyBlockShape::explicit_nonce_len`]. |
73 | /// |
74 | /// May return [`UnsupportedOperationError`] if the AEAD algorithm is not a supported |
75 | /// variant of `ConnectionTrafficSecrets`. |
76 | fn extract_keys( |
77 | &self, |
78 | key: AeadKey, |
79 | iv: &[u8], |
80 | explicit: &[u8], |
81 | ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>; |
82 | |
83 | /// Return `true` if this is backed by a FIPS-approved implementation. |
84 | fn fips(&self) -> bool { |
85 | false |
86 | } |
87 | } |
88 | |
89 | /// An error indicating that the AEAD algorithm does not support the requested operation. |
90 | #[derive (Debug, Eq, PartialEq, Clone, Copy)] |
91 | pub struct UnsupportedOperationError; |
92 | |
93 | impl From<UnsupportedOperationError> for Error { |
94 | fn from(value: UnsupportedOperationError) -> Self { |
95 | Self::General(value.to_string()) |
96 | } |
97 | } |
98 | |
99 | impl fmt::Display for UnsupportedOperationError { |
100 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
101 | write!(f, "operation not supported" ) |
102 | } |
103 | } |
104 | |
105 | #[cfg (feature = "std" )] |
106 | impl std::error::Error for UnsupportedOperationError {} |
107 | |
108 | /// How a TLS1.2 `key_block` is partitioned. |
109 | /// |
110 | /// Note: ciphersuites with non-zero `mac_key_length` are not currently supported. |
111 | pub struct KeyBlockShape { |
112 | /// How long keys are. |
113 | /// |
114 | /// `enc_key_length` terminology is from the standard ([RFC5246 A.6]). |
115 | /// |
116 | /// [RFC5246 A.6]: <https://www.rfc-editor.org/rfc/rfc5246#appendix-A.6> |
117 | pub enc_key_len: usize, |
118 | |
119 | /// How long the fixed part of the 'IV' is. |
120 | /// |
121 | /// `fixed_iv_length` terminology is from the standard ([RFC5246 A.6]). |
122 | /// |
123 | /// This isn't usually an IV, but we continue the |
124 | /// terminology misuse to match the standard. |
125 | /// |
126 | /// [RFC5246 A.6]: <https://www.rfc-editor.org/rfc/rfc5246#appendix-A.6> |
127 | pub fixed_iv_len: usize, |
128 | |
129 | /// This is a non-standard extension which extends the |
130 | /// key block to provide an initial explicit nonce offset, |
131 | /// in a deterministic and safe way. GCM needs this, |
132 | /// chacha20poly1305 works this way by design. |
133 | pub explicit_nonce_len: usize, |
134 | } |
135 | |
136 | /// Objects with this trait can decrypt TLS messages. |
137 | pub trait MessageDecrypter: Send + Sync { |
138 | /// Decrypt the given TLS message `msg`, using the sequence number |
139 | /// `seq` which can be used to derive a unique [`Nonce`]. |
140 | fn decrypt<'a>( |
141 | &mut self, |
142 | msg: InboundOpaqueMessage<'a>, |
143 | seq: u64, |
144 | ) -> Result<InboundPlainMessage<'a>, Error>; |
145 | } |
146 | |
147 | /// Objects with this trait can encrypt TLS messages. |
148 | pub trait MessageEncrypter: Send + Sync { |
149 | /// Encrypt the given TLS message `msg`, using the sequence number |
150 | /// `seq` which can be used to derive a unique [`Nonce`]. |
151 | fn encrypt( |
152 | &mut self, |
153 | msg: OutboundPlainMessage<'_>, |
154 | seq: u64, |
155 | ) -> Result<OutboundOpaqueMessage, Error>; |
156 | |
157 | /// Return the length of the ciphertext that results from encrypting plaintext of |
158 | /// length `payload_len` |
159 | fn encrypted_payload_len(&self, payload_len: usize) -> usize; |
160 | } |
161 | |
162 | impl dyn MessageEncrypter { |
163 | pub(crate) fn invalid() -> Box<dyn MessageEncrypter> { |
164 | Box::new(InvalidMessageEncrypter {}) |
165 | } |
166 | } |
167 | |
168 | impl dyn MessageDecrypter { |
169 | pub(crate) fn invalid() -> Box<dyn MessageDecrypter> { |
170 | Box::new(InvalidMessageDecrypter {}) |
171 | } |
172 | } |
173 | |
174 | /// A write or read IV. |
175 | #[derive (Default)] |
176 | pub struct Iv([u8; NONCE_LEN]); |
177 | |
178 | impl Iv { |
179 | /// Create a new `Iv` from a byte array, of precisely `NONCE_LEN` bytes. |
180 | #[cfg (feature = "tls12" )] |
181 | pub fn new(value: [u8; NONCE_LEN]) -> Self { |
182 | Self(value) |
183 | } |
184 | |
185 | /// Create a new `Iv` from a byte slice, of precisely `NONCE_LEN` bytes. |
186 | #[cfg (feature = "tls12" )] |
187 | pub fn copy(value: &[u8]) -> Self { |
188 | debug_assert_eq!(value.len(), NONCE_LEN); |
189 | let mut iv: Iv = Self::new(Default::default()); |
190 | iv.0.copy_from_slice(src:value); |
191 | iv |
192 | } |
193 | } |
194 | |
195 | impl From<[u8; NONCE_LEN]> for Iv { |
196 | fn from(bytes: [u8; NONCE_LEN]) -> Self { |
197 | Self(bytes) |
198 | } |
199 | } |
200 | |
201 | impl AsRef<[u8]> for Iv { |
202 | fn as_ref(&self) -> &[u8] { |
203 | self.0.as_ref() |
204 | } |
205 | } |
206 | |
207 | /// A nonce. This is unique for all messages on a connection. |
208 | pub struct Nonce(pub [u8; NONCE_LEN]); |
209 | |
210 | impl Nonce { |
211 | /// Combine an `Iv` and sequence number to produce a unique nonce. |
212 | /// |
213 | /// This is `iv ^ seq` where `seq` is encoded as a 96-bit big-endian integer. |
214 | #[inline ] |
215 | pub fn new(iv: &Iv, seq: u64) -> Self { |
216 | let mut nonce: Nonce = Self([0u8; NONCE_LEN]); |
217 | codec::put_u64(v:seq, &mut nonce.0[4..]); |
218 | |
219 | nonceimpl Iterator |
220 | .0 |
221 | .iter_mut() |
222 | .zip(iv.0.iter()) |
223 | .for_each(|(nonce: &mut u8, iv: &u8)| { |
224 | *nonce ^= *iv; |
225 | }); |
226 | |
227 | nonce |
228 | } |
229 | } |
230 | |
231 | /// Size of TLS nonces (incorrectly termed "IV" in standard) for all supported ciphersuites |
232 | /// (AES-GCM, Chacha20Poly1305) |
233 | pub const NONCE_LEN: usize = 12; |
234 | |
235 | /// Returns a TLS1.3 `additional_data` encoding. |
236 | /// |
237 | /// See RFC8446 s5.2 for the `additional_data` definition. |
238 | #[inline ] |
239 | pub fn make_tls13_aad(payload_len: usize) -> [u8; 5] { |
240 | let version: [u8; _] = ProtocolVersion::TLSv1_2.to_array(); |
241 | [ |
242 | ContentType::ApplicationData.into(), |
243 | // Note: this is `legacy_record_version`, i.e. TLS1.2 even for TLS1.3. |
244 | version[0], |
245 | version[1], |
246 | (payload_len >> 8) as u8, |
247 | (payload_len & 0xff) as u8, |
248 | ] |
249 | } |
250 | |
251 | /// Returns a TLS1.2 `additional_data` encoding. |
252 | /// |
253 | /// See RFC5246 s6.2.3.3 for the `additional_data` definition. |
254 | #[inline ] |
255 | pub fn make_tls12_aad( |
256 | seq: u64, |
257 | typ: ContentType, |
258 | vers: ProtocolVersion, |
259 | len: usize, |
260 | ) -> [u8; TLS12_AAD_SIZE] { |
261 | let mut out: [u8; 13] = [0; TLS12_AAD_SIZE]; |
262 | codec::put_u64(v:seq, &mut out[0..]); |
263 | out[8] = typ.into(); |
264 | codec::put_u16(v:vers.into(), &mut out[9..]); |
265 | codec::put_u16(v:len as u16, &mut out[11..]); |
266 | out |
267 | } |
268 | |
269 | const TLS12_AAD_SIZE: usize = 8 + 1 + 2 + 2; |
270 | |
271 | /// A key for an AEAD algorithm. |
272 | /// |
273 | /// This is a value type for a byte string up to `AeadKey::MAX_LEN` bytes in length. |
274 | pub struct AeadKey { |
275 | buf: [u8; Self::MAX_LEN], |
276 | used: usize, |
277 | } |
278 | |
279 | impl AeadKey { |
280 | #[cfg (feature = "tls12" )] |
281 | pub(crate) fn new(buf: &[u8]) -> Self { |
282 | debug_assert!(buf.len() <= Self::MAX_LEN); |
283 | let mut key: AeadKey = Self::from([0u8; Self::MAX_LEN]); |
284 | key.buf[..buf.len()].copy_from_slice(src:buf); |
285 | key.used = buf.len(); |
286 | key |
287 | } |
288 | |
289 | pub(crate) fn with_length(self, len: usize) -> Self { |
290 | assert!(len <= self.used); |
291 | Self { |
292 | buf: self.buf, |
293 | used: len, |
294 | } |
295 | } |
296 | |
297 | /// Largest possible AEAD key in the ciphersuites we support. |
298 | pub(crate) const MAX_LEN: usize = 32; |
299 | } |
300 | |
301 | impl Drop for AeadKey { |
302 | fn drop(&mut self) { |
303 | self.buf.zeroize(); |
304 | } |
305 | } |
306 | |
307 | impl AsRef<[u8]> for AeadKey { |
308 | fn as_ref(&self) -> &[u8] { |
309 | &self.buf[..self.used] |
310 | } |
311 | } |
312 | |
313 | impl From<[u8; Self::MAX_LEN]> for AeadKey { |
314 | fn from(bytes: [u8; Self::MAX_LEN]) -> Self { |
315 | Self { |
316 | buf: bytes, |
317 | used: Self::MAX_LEN, |
318 | } |
319 | } |
320 | } |
321 | |
322 | /// A `MessageEncrypter` which doesn't work. |
323 | struct InvalidMessageEncrypter {} |
324 | |
325 | impl MessageEncrypter for InvalidMessageEncrypter { |
326 | fn encrypt( |
327 | &mut self, |
328 | _m: OutboundPlainMessage<'_>, |
329 | _seq: u64, |
330 | ) -> Result<OutboundOpaqueMessage, Error> { |
331 | Err(Error::EncryptError) |
332 | } |
333 | |
334 | fn encrypted_payload_len(&self, payload_len: usize) -> usize { |
335 | payload_len |
336 | } |
337 | } |
338 | |
339 | /// A `MessageDecrypter` which doesn't work. |
340 | struct InvalidMessageDecrypter {} |
341 | |
342 | impl MessageDecrypter for InvalidMessageDecrypter { |
343 | fn decrypt<'a>( |
344 | &mut self, |
345 | _m: InboundOpaqueMessage<'a>, |
346 | _seq: u64, |
347 | ) -> Result<InboundPlainMessage<'a>, Error> { |
348 | Err(Error::DecryptError) |
349 | } |
350 | } |
351 | |