rustls/crypto/
cipher.rs

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