1use alloc::boxed::Box;
2
3use aws_lc_rs::hkdf::KeyType;
4use aws_lc_rs::{aead, hkdf, hmac};
5
6use crate::crypto;
7use crate::crypto::cipher::{
8 AeadKey, InboundOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
9 Tls13AeadAlgorithm, UnsupportedOperationError, make_tls13_aad,
10};
11use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
12use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
13use crate::error::Error;
14use crate::msgs::message::{
15 InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
16};
17use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
18use crate::tls13::Tls13CipherSuite;
19
20pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
22 SupportedCipherSuite::Tls13(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
23
24pub(crate) static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
25 common: CipherSuiteCommon {
26 suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
27 hash_provider: &super::hash::SHA256,
28 confidentiality_limit: u64::MAX,
30 },
31 hkdf_provider: &AwsLcHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
32 aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)),
33 quic: Some(&super::quic::KeyBuilder {
34 packet_alg: &aead::CHACHA20_POLY1305,
35 header_alg: &aead::quic::CHACHA20,
36 confidentiality_limit: u64::MAX,
38 integrity_limit: 1 << 36,
40 }),
41};
42
43pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
45 SupportedCipherSuite::Tls13(&Tls13CipherSuite {
46 common: CipherSuiteCommon {
47 suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
48 hash_provider: &super::hash::SHA384,
49 confidentiality_limit: 1 << 24,
50 },
51 hkdf_provider: &AwsLcHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384),
52 aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)),
53 quic: Some(&super::quic::KeyBuilder {
54 packet_alg: &aead::AES_256_GCM,
55 header_alg: &aead::quic::AES_256,
56 confidentiality_limit: 1 << 23,
58 integrity_limit: 1 << 52,
60 }),
61 });
62
63pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
65 SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL);
66
67pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
68 common: CipherSuiteCommon {
69 suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
70 hash_provider: &super::hash::SHA256,
71 confidentiality_limit: 1 << 24,
72 },
73 hkdf_provider: &AwsLcHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
74 aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)),
75 quic: Some(&super::quic::KeyBuilder {
76 packet_alg: &aead::AES_128_GCM,
77 header_alg: &aead::quic::AES_128,
78 confidentiality_limit: 1 << 23,
80 integrity_limit: 1 << 52,
82 }),
83};
84
85struct Chacha20Poly1305Aead(AeadAlgorithm);
86
87impl Tls13AeadAlgorithm for Chacha20Poly1305Aead {
88 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
89 Box::new(AeadMessageEncrypter {
91 enc_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0.0, key.as_ref()).unwrap()),
92 iv,
93 })
94 }
95
96 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
97 Box::new(AeadMessageDecrypter {
99 dec_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0.0, key.as_ref()).unwrap()),
100 iv,
101 })
102 }
103
104 fn key_len(&self) -> usize {
105 self.0.key_len()
106 }
107
108 fn extract_keys(
109 &self,
110 key: AeadKey,
111 iv: Iv,
112 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
113 Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
114 }
115
116 fn fips(&self) -> bool {
117 false }
119}
120
121struct Aes256GcmAead(AeadAlgorithm);
122
123impl Tls13AeadAlgorithm for Aes256GcmAead {
124 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
125 self.0.encrypter(key, iv)
126 }
127
128 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
129 self.0.decrypter(key, iv)
130 }
131
132 fn key_len(&self) -> usize {
133 self.0.key_len()
134 }
135
136 fn extract_keys(
137 &self,
138 key: AeadKey,
139 iv: Iv,
140 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
141 Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv })
142 }
143
144 fn fips(&self) -> bool {
145 super::fips()
146 }
147}
148
149struct Aes128GcmAead(AeadAlgorithm);
150
151impl Tls13AeadAlgorithm for Aes128GcmAead {
152 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
153 self.0.encrypter(key, iv)
154 }
155
156 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
157 self.0.decrypter(key, iv)
158 }
159
160 fn key_len(&self) -> usize {
161 self.0.key_len()
162 }
163
164 fn extract_keys(
165 &self,
166 key: AeadKey,
167 iv: Iv,
168 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
169 Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv })
170 }
171
172 fn fips(&self) -> bool {
173 super::fips()
174 }
175}
176
177struct AeadAlgorithm(&'static aead::Algorithm);
179
180impl AeadAlgorithm {
181 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
183 Box::new(GcmMessageEncrypter {
187 enc_key: aead::TlsRecordSealingKey::new(
188 self.0,
189 aead::TlsProtocolId::TLS13,
190 key.as_ref(),
191 )
192 .unwrap(),
193 iv,
194 })
195 }
196
197 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
199 Box::new(GcmMessageDecrypter {
203 dec_key: aead::TlsRecordOpeningKey::new(
204 self.0,
205 aead::TlsProtocolId::TLS13,
206 key.as_ref(),
207 )
208 .unwrap(),
209 iv,
210 })
211 }
212
213 fn key_len(&self) -> usize {
214 self.0.key_len()
215 }
216}
217
218struct AeadMessageEncrypter {
219 enc_key: aead::LessSafeKey,
220 iv: Iv,
221}
222
223struct AeadMessageDecrypter {
224 dec_key: aead::LessSafeKey,
225 iv: Iv,
226}
227
228impl MessageEncrypter for AeadMessageEncrypter {
229 fn encrypt(
230 &mut self,
231 msg: OutboundPlainMessage<'_>,
232 seq: u64,
233 ) -> Result<OutboundOpaqueMessage, Error> {
234 let total_len = self.encrypted_payload_len(msg.payload.len());
235 let mut payload = PrefixedPayload::with_capacity(total_len);
236
237 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
238 let aad = aead::Aad::from(make_tls13_aad(total_len));
239 payload.extend_from_chunks(&msg.payload);
240 payload.extend_from_slice(&msg.typ.to_array());
241
242 self.enc_key
243 .seal_in_place_append_tag(nonce, aad, &mut payload)
244 .map_err(|_| Error::EncryptError)?;
245
246 Ok(OutboundOpaqueMessage::new(
247 ContentType::ApplicationData,
248 ProtocolVersion::TLSv1_2,
251 payload,
252 ))
253 }
254
255 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
256 payload_len + 1 + self.enc_key.algorithm().tag_len()
257 }
258}
259
260impl MessageDecrypter for AeadMessageDecrypter {
261 fn decrypt<'a>(
262 &mut self,
263 mut msg: InboundOpaqueMessage<'a>,
264 seq: u64,
265 ) -> Result<InboundPlainMessage<'a>, Error> {
266 let payload = &mut msg.payload;
267 if payload.len() < self.dec_key.algorithm().tag_len() {
268 return Err(Error::DecryptError);
269 }
270
271 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
272 let aad = aead::Aad::from(make_tls13_aad(payload.len()));
273 let plain_len = self
274 .dec_key
275 .open_in_place(nonce, aad, payload)
276 .map_err(|_| Error::DecryptError)?
277 .len();
278
279 payload.truncate(plain_len);
280 msg.into_tls13_unpadded_message()
281 }
282}
283
284struct GcmMessageEncrypter {
285 enc_key: aead::TlsRecordSealingKey,
286 iv: Iv,
287}
288
289impl MessageEncrypter for GcmMessageEncrypter {
290 fn encrypt(
291 &mut self,
292 msg: OutboundPlainMessage<'_>,
293 seq: u64,
294 ) -> Result<OutboundOpaqueMessage, Error> {
295 let total_len = self.encrypted_payload_len(msg.payload.len());
296 let mut payload = PrefixedPayload::with_capacity(total_len);
297
298 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
299 let aad = aead::Aad::from(make_tls13_aad(total_len));
300 payload.extend_from_chunks(&msg.payload);
301 payload.extend_from_slice(&msg.typ.to_array());
302
303 self.enc_key
304 .seal_in_place_append_tag(nonce, aad, &mut payload)
305 .map_err(|_| Error::EncryptError)?;
306
307 Ok(OutboundOpaqueMessage::new(
308 ContentType::ApplicationData,
309 ProtocolVersion::TLSv1_2,
310 payload,
311 ))
312 }
313
314 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
315 payload_len + 1 + self.enc_key.algorithm().tag_len()
316 }
317}
318
319struct GcmMessageDecrypter {
320 dec_key: aead::TlsRecordOpeningKey,
321 iv: Iv,
322}
323
324impl MessageDecrypter for GcmMessageDecrypter {
325 fn decrypt<'a>(
326 &mut self,
327 mut msg: InboundOpaqueMessage<'a>,
328 seq: u64,
329 ) -> Result<InboundPlainMessage<'a>, Error> {
330 let payload = &mut msg.payload;
331 if payload.len() < self.dec_key.algorithm().tag_len() {
332 return Err(Error::DecryptError);
333 }
334
335 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
336 let aad = aead::Aad::from(make_tls13_aad(payload.len()));
337 let plain_len = self
338 .dec_key
339 .open_in_place(nonce, aad, payload)
340 .map_err(|_| Error::DecryptError)?
341 .len();
342
343 payload.truncate(plain_len);
344 msg.into_tls13_unpadded_message()
345 }
346}
347
348struct AwsLcHkdf(hkdf::Algorithm, hmac::Algorithm);
349
350impl Hkdf for AwsLcHkdf {
351 fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander> {
352 let zeroes = [0u8; OkmBlock::MAX_LEN];
353 let salt = match salt {
354 Some(salt) => salt,
355 None => &zeroes[..self.0.len()],
356 };
357 Box::new(AwsLcHkdfExpander {
358 alg: self.0,
359 prk: hkdf::Salt::new(self.0, salt).extract(&zeroes[..self.0.len()]),
360 })
361 }
362
363 fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander> {
364 let zeroes = [0u8; OkmBlock::MAX_LEN];
365 let salt = match salt {
366 Some(salt) => salt,
367 None => &zeroes[..self.0.len()],
368 };
369 Box::new(AwsLcHkdfExpander {
370 alg: self.0,
371 prk: hkdf::Salt::new(self.0, salt).extract(secret),
372 })
373 }
374
375 fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander> {
376 Box::new(AwsLcHkdfExpander {
377 alg: self.0,
378 prk: hkdf::Prk::new_less_safe(self.0, okm.as_ref()),
379 })
380 }
381
382 fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
383 crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
384 }
385
386 fn fips(&self) -> bool {
387 super::fips()
388 }
389}
390
391struct AwsLcHkdfExpander {
392 alg: hkdf::Algorithm,
393 prk: hkdf::Prk,
394}
395
396impl HkdfExpander for AwsLcHkdfExpander {
397 fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError> {
398 self.prk
399 .expand(info, Len(output.len()))
400 .and_then(|okm| okm.fill(output))
401 .map_err(|_| OutputLengthError)
402 }
403
404 fn expand_block(&self, info: &[&[u8]]) -> OkmBlock {
405 let mut buf = [0u8; OkmBlock::MAX_LEN];
406 let output = &mut buf[..self.hash_len()];
407 self.prk
408 .expand(info, Len(output.len()))
409 .and_then(|okm| okm.fill(output))
410 .unwrap();
411 OkmBlock::new(output)
412 }
413
414 fn hash_len(&self) -> usize {
415 self.alg.len()
416 }
417}
418
419struct Len(usize);
420
421impl KeyType for Len {
422 fn len(&self) -> usize {
423 self.0
424 }
425}