1use alloc::boxed::Box;
2use alloc::string::ToString;
3use core::fmt;
45use zeroize::Zeroize;
67use 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;
1516/// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.3 cipher suite.
17pub trait Tls13AeadAlgorithm: Send + Sync {
18/// Build a `MessageEncrypter` for the given key/iv.
19fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter>;
2021/// Build a `MessageDecrypter` for the given key/iv.
22fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter>;
2324/// The length of key in bytes required by `encrypter()` and `decrypter()`.
25fn key_len(&self) -> usize;
2627/// 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`.
31fn extract_keys(
32&self,
33 key: AeadKey,
34 iv: Iv,
35 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
3637/// Return `true` if this is backed by a FIPS-approved implementation.
38fn fips(&self) -> bool {
39false
40}
41}
4243/// Factory trait for building `MessageEncrypter` and `MessageDecrypter` for a TLS1.2 cipher suite.
44pub 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`].
53fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter>;
5455/// 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`].
60fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter>;
6162/// 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()`.
64fn key_block_shape(&self) -> KeyBlockShape;
6566/// 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`.
76fn extract_keys(
77&self,
78 key: AeadKey,
79 iv: &[u8],
80 explicit: &[u8],
81 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
8283/// Return `true` if this is backed by a FIPS-approved implementation.
84fn fips(&self) -> bool {
85false
86}
87}
8889/// An error indicating that the AEAD algorithm does not support the requested operation.
90#[derive(Debug, Eq, PartialEq, Clone, Copy)]
91pub struct UnsupportedOperationError;
9293impl From<UnsupportedOperationError> for Error {
94fn from(value: UnsupportedOperationError) -> Self {
95Self::General(value.to_string())
96 }
97}
9899impl fmt::Display for UnsupportedOperationError {
100fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101write!(f, "operation not supported")
102 }
103}
104105#[cfg(feature = "std")]
106impl std::error::Error for UnsupportedOperationError {}
107108/// How a TLS1.2 `key_block` is partitioned.
109///
110/// Note: ciphersuites with non-zero `mac_key_length` are not currently supported.
111pub 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>
117pub enc_key_len: usize,
118119/// 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>
127pub fixed_iv_len: usize,
128129/// 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.
133pub explicit_nonce_len: usize,
134}
135136/// Objects with this trait can decrypt TLS messages.
137pub 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`].
140fn decrypt<'a>(
141&mut self,
142 msg: InboundOpaqueMessage<'a>,
143 seq: u64,
144 ) -> Result<InboundPlainMessage<'a>, Error>;
145}
146147/// Objects with this trait can encrypt TLS messages.
148pub 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`].
151fn encrypt(
152&mut self,
153 msg: OutboundPlainMessage<'_>,
154 seq: u64,
155 ) -> Result<OutboundOpaqueMessage, Error>;
156157/// Return the length of the ciphertext that results from encrypting plaintext of
158 /// length `payload_len`
159fn encrypted_payload_len(&self, payload_len: usize) -> usize;
160}
161162impl dyn MessageEncrypter {
163pub(crate) fn invalid() -> Box<dyn MessageEncrypter> {
164 Box::new(InvalidMessageEncrypter {})
165 }
166}
167168impl dyn MessageDecrypter {
169pub(crate) fn invalid() -> Box<dyn MessageDecrypter> {
170 Box::new(InvalidMessageDecrypter {})
171 }
172}
173174/// A write or read IV.
175#[derive(Default)]
176pub struct Iv([u8; NONCE_LEN]);
177178impl Iv {
179/// Create a new `Iv` from a byte array, of precisely `NONCE_LEN` bytes.
180#[cfg(feature = "tls12")]
181pub fn new(value: [u8; NONCE_LEN]) -> Self {
182Self(value)
183 }
184185/// Create a new `Iv` from a byte slice, of precisely `NONCE_LEN` bytes.
186#[cfg(feature = "tls12")]
187pub fn copy(value: &[u8]) -> Self {
188debug_assert_eq!(value.len(), NONCE_LEN);
189let mut iv = Self::new(Default::default());
190 iv.0.copy_from_slice(value);
191 iv
192 }
193}
194195impl From<[u8; NONCE_LEN]> for Iv {
196fn from(bytes: [u8; NONCE_LEN]) -> Self {
197Self(bytes)
198 }
199}
200201impl AsRef<[u8]> for Iv {
202fn as_ref(&self) -> &[u8] {
203self.0.as_ref()
204 }
205}
206207/// A nonce. This is unique for all messages on a connection.
208pub struct Nonce(pub [u8; NONCE_LEN]);
209210impl 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]
215pub fn new(iv: &Iv, seq: u64) -> Self {
216let mut nonce = Self([0u8; NONCE_LEN]);
217 codec::put_u64(seq, &mut nonce.0[4..]);
218219 nonce
220 .0
221.iter_mut()
222 .zip(iv.0.iter())
223 .for_each(|(nonce, iv)| {
224*nonce ^= *iv;
225 });
226227 nonce
228 }
229}
230231/// Size of TLS nonces (incorrectly termed "IV" in standard) for all supported ciphersuites
232/// (AES-GCM, Chacha20Poly1305)
233pub const NONCE_LEN: usize = 12;
234235/// Returns a TLS1.3 `additional_data` encoding.
236///
237/// See RFC8446 s5.2 for the `additional_data` definition.
238#[inline]
239pub fn make_tls13_aad(payload_len: usize) -> [u8; 5] {
240let version = 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.
244version[0],
245 version[1],
246 (payload_len >> 8) as u8,
247 (payload_len & 0xff) as u8,
248 ]
249}
250251/// Returns a TLS1.2 `additional_data` encoding.
252///
253/// See RFC5246 s6.2.3.3 for the `additional_data` definition.
254#[inline]
255pub fn make_tls12_aad(
256 seq: u64,
257 typ: ContentType,
258 vers: ProtocolVersion,
259 len: usize,
260) -> [u8; TLS12_AAD_SIZE] {
261let mut out = [0; TLS12_AAD_SIZE];
262 codec::put_u64(seq, &mut out[0..]);
263 out[8] = typ.into();
264 codec::put_u16(vers.into(), &mut out[9..]);
265 codec::put_u16(len as u16, &mut out[11..]);
266 out
267}
268269const TLS12_AAD_SIZE: usize = 8 + 1 + 2 + 2;
270271/// 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.
274pub struct AeadKey {
275 buf: [u8; Self::MAX_LEN],
276 used: usize,
277}
278279impl AeadKey {
280#[cfg(feature = "tls12")]
281pub(crate) fn new(buf: &[u8]) -> Self {
282debug_assert!(buf.len() <= Self::MAX_LEN);
283let mut key = Self::from([0u8; Self::MAX_LEN]);
284 key.buf[..buf.len()].copy_from_slice(buf);
285 key.used = buf.len();
286 key
287 }
288289pub(crate) fn with_length(self, len: usize) -> Self {
290assert!(len <= self.used);
291Self {
292 buf: self.buf,
293 used: len,
294 }
295 }
296297/// Largest possible AEAD key in the ciphersuites we support.
298pub(crate) const MAX_LEN: usize = 32;
299}
300301impl Drop for AeadKey {
302fn drop(&mut self) {
303self.buf.zeroize();
304 }
305}
306307impl AsRef<[u8]> for AeadKey {
308fn as_ref(&self) -> &[u8] {
309&self.buf[..self.used]
310 }
311}
312313impl From<[u8; Self::MAX_LEN]> for AeadKey {
314fn from(bytes: [u8; Self::MAX_LEN]) -> Self {
315Self {
316 buf: bytes,
317 used: Self::MAX_LEN,
318 }
319 }
320}
321322/// A `MessageEncrypter` which doesn't work.
323struct InvalidMessageEncrypter {}
324325impl MessageEncrypter for InvalidMessageEncrypter {
326fn encrypt(
327&mut self,
328 _m: OutboundPlainMessage<'_>,
329 _seq: u64,
330 ) -> Result<OutboundOpaqueMessage, Error> {
331Err(Error::EncryptError)
332 }
333334fn encrypted_payload_len(&self, payload_len: usize) -> usize {
335 payload_len
336 }
337}
338339/// A `MessageDecrypter` which doesn't work.
340struct InvalidMessageDecrypter {}
341342impl MessageDecrypter for InvalidMessageDecrypter {
343fn decrypt<'a>(
344&mut self,
345 _m: InboundOpaqueMessage<'a>,
346 _seq: u64,
347 ) -> Result<InboundPlainMessage<'a>, Error> {
348Err(Error::DecryptError)
349 }
350}