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