| 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 | |