portable_rustls/crypto/
cipher.rs1use 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 #[cfg(unstable_api_not_supported)] fn fips(&self) -> bool {
40 false
41 }
42}
43
44pub trait Tls12AeadAlgorithm: Send + Sync + 'static {
46 fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter>;
55
56 fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter>;
62
63 fn key_block_shape(&self) -> KeyBlockShape;
66
67 fn extract_keys(
78 &self,
79 key: AeadKey,
80 iv: &[u8],
81 explicit: &[u8],
82 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError>;
83
84 #[cfg(unstable_api_not_supported)] fn fips(&self) -> bool {
87 false
88 }
89}
90
91#[derive(Debug, Eq, PartialEq, Clone, Copy)]
93pub struct UnsupportedOperationError;
94
95impl From<UnsupportedOperationError> for Error {
96 fn from(value: UnsupportedOperationError) -> Self {
97 Self::General(value.to_string())
98 }
99}
100
101impl fmt::Display for UnsupportedOperationError {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(f, "operation not supported")
104 }
105}
106
107#[cfg(feature = "std")]
108impl std::error::Error for UnsupportedOperationError {}
109
110pub 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 #[cfg(feature = "tls12")]
183 pub fn new(value: [u8; NONCE_LEN]) -> Self {
184 Self(value)
185 }
186
187 #[cfg(feature = "tls12")]
189 pub fn copy(value: &[u8]) -> Self {
190 debug_assert_eq!(value.len(), NONCE_LEN);
191 let mut iv = Self::new(Default::default());
192 iv.0.copy_from_slice(value);
193 iv
194 }
195}
196
197impl From<[u8; NONCE_LEN]> for Iv {
198 fn from(bytes: [u8; NONCE_LEN]) -> Self {
199 Self(bytes)
200 }
201}
202
203impl AsRef<[u8]> for Iv {
204 fn as_ref(&self) -> &[u8] {
205 self.0.as_ref()
206 }
207}
208
209pub struct Nonce(pub [u8; NONCE_LEN]);
211
212impl Nonce {
213 #[inline]
217 pub fn new(iv: &Iv, seq: u64) -> Self {
218 let mut nonce = Self([0u8; NONCE_LEN]);
219 codec::put_u64(seq, &mut nonce.0[4..]);
220
221 nonce
222 .0
223 .iter_mut()
224 .zip(iv.0.iter())
225 .for_each(|(nonce, iv)| {
226 *nonce ^= *iv;
227 });
228
229 nonce
230 }
231}
232
233pub const NONCE_LEN: usize = 12;
236
237#[inline]
241pub fn make_tls13_aad(payload_len: usize) -> [u8; 5] {
242 let version = ProtocolVersion::TLSv1_2.to_array();
243 [
244 ContentType::ApplicationData.into(),
245 version[0],
247 version[1],
248 (payload_len >> 8) as u8,
249 (payload_len & 0xff) as u8,
250 ]
251}
252
253#[inline]
257pub fn make_tls12_aad(
258 seq: u64,
259 typ: ContentType,
260 vers: ProtocolVersion,
261 len: usize,
262) -> [u8; TLS12_AAD_SIZE] {
263 let mut out = [0; TLS12_AAD_SIZE];
264 codec::put_u64(seq, &mut out[0..]);
265 out[8] = typ.into();
266 codec::put_u16(vers.into(), &mut out[9..]);
267 codec::put_u16(len as u16, &mut out[11..]);
268 out
269}
270
271const TLS12_AAD_SIZE: usize = 8 + 1 + 2 + 2;
272
273pub struct AeadKey {
277 buf: [u8; Self::MAX_LEN],
278 used: usize,
279}
280
281impl AeadKey {
282 #[cfg(feature = "tls12")]
283 pub(crate) fn new(buf: &[u8]) -> Self {
284 debug_assert!(buf.len() <= Self::MAX_LEN);
285 let mut key = Self::from([0u8; Self::MAX_LEN]);
286 key.buf[..buf.len()].copy_from_slice(buf);
287 key.used = buf.len();
288 key
289 }
290
291 pub(crate) fn with_length(self, len: usize) -> Self {
292 assert!(len <= self.used);
293 Self {
294 buf: self.buf,
295 used: len,
296 }
297 }
298
299 pub(crate) const MAX_LEN: usize = 32;
301}
302
303impl Drop for AeadKey {
304 fn drop(&mut self) {
305 self.buf.zeroize();
306 }
307}
308
309impl AsRef<[u8]> for AeadKey {
310 fn as_ref(&self) -> &[u8] {
311 &self.buf[..self.used]
312 }
313}
314
315impl From<[u8; Self::MAX_LEN]> for AeadKey {
316 fn from(bytes: [u8; Self::MAX_LEN]) -> Self {
317 Self {
318 buf: bytes,
319 used: Self::MAX_LEN,
320 }
321 }
322}
323
324struct InvalidMessageEncrypter {}
326
327impl MessageEncrypter for InvalidMessageEncrypter {
328 fn encrypt(
329 &mut self,
330 _m: OutboundPlainMessage<'_>,
331 _seq: u64,
332 ) -> Result<OutboundOpaqueMessage, Error> {
333 Err(Error::EncryptError)
334 }
335
336 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
337 payload_len
338 }
339}
340
341struct InvalidMessageDecrypter {}
343
344impl MessageDecrypter for InvalidMessageDecrypter {
345 fn decrypt<'a>(
346 &mut self,
347 _m: InboundOpaqueMessage<'a>,
348 _seq: u64,
349 ) -> Result<InboundPlainMessage<'a>, Error> {
350 Err(Error::DecryptError)
351 }
352}