1use alloc::boxed::Box;
2
3use aws_lc_rs::{aead, tls_prf};
4use zeroize::Zeroizing;
5
6use crate::crypto::cipher::{
7 AeadKey, InboundOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter,
8 NONCE_LEN, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, make_tls12_aad,
9};
10use crate::crypto::tls12::{Prf, PrfSecret};
11use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm, SharedSecret};
12use crate::enums::{CipherSuite, SignatureScheme};
13use crate::error::Error;
14use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
15use crate::msgs::message::{
16 InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
17};
18use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
19use crate::tls12::Tls12CipherSuite;
20use crate::version::{TLS12, TLS12_VERSION};
21
22pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
24 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
25 common: CipherSuiteCommon {
26 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
27 hash_provider: &super::hash::SHA256,
28 confidentiality_limit: u64::MAX,
29 },
30 protocol_version: TLS12_VERSION,
31 kx: KeyExchangeAlgorithm::ECDHE,
32 sign: TLS12_ECDSA_SCHEMES,
33 aead_alg: &ChaCha20Poly1305,
34 prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
35 });
36
37pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
39 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
40 common: CipherSuiteCommon {
41 suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
42 hash_provider: &super::hash::SHA256,
43 confidentiality_limit: u64::MAX,
44 },
45 protocol_version: TLS12_VERSION,
46 kx: KeyExchangeAlgorithm::ECDHE,
47 sign: TLS12_RSA_SCHEMES,
48 aead_alg: &ChaCha20Poly1305,
49 prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
50 });
51
52pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
54 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
55 common: CipherSuiteCommon {
56 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
57 hash_provider: &super::hash::SHA256,
58 confidentiality_limit: 1 << 24,
59 },
60 protocol_version: TLS12_VERSION,
61 kx: KeyExchangeAlgorithm::ECDHE,
62 sign: TLS12_RSA_SCHEMES,
63 aead_alg: &AES128_GCM,
64 prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
65 });
66
67pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
69 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
70 common: CipherSuiteCommon {
71 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
72 hash_provider: &super::hash::SHA384,
73 confidentiality_limit: 1 << 24,
74 },
75 protocol_version: TLS12_VERSION,
76 kx: KeyExchangeAlgorithm::ECDHE,
77 sign: TLS12_RSA_SCHEMES,
78 aead_alg: &AES256_GCM,
79 prf_provider: &Tls12Prf(&tls_prf::P_SHA384),
80 });
81
82pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
84 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
85 common: CipherSuiteCommon {
86 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
87 hash_provider: &super::hash::SHA256,
88 confidentiality_limit: 1 << 24,
89 },
90 protocol_version: TLS12_VERSION,
91 kx: KeyExchangeAlgorithm::ECDHE,
92 sign: TLS12_ECDSA_SCHEMES,
93 aead_alg: &AES128_GCM,
94 prf_provider: &Tls12Prf(&tls_prf::P_SHA256),
95 });
96
97pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
99 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
100 common: CipherSuiteCommon {
101 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
102 hash_provider: &super::hash::SHA384,
103 confidentiality_limit: 1 << 24,
104 },
105 protocol_version: TLS12_VERSION,
106 kx: KeyExchangeAlgorithm::ECDHE,
107 sign: TLS12_ECDSA_SCHEMES,
108 aead_alg: &AES256_GCM,
109 prf_provider: &Tls12Prf(&tls_prf::P_SHA384),
110 });
111
112static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
113 SignatureScheme::ED25519,
114 SignatureScheme::ECDSA_NISTP521_SHA512,
115 SignatureScheme::ECDSA_NISTP384_SHA384,
116 SignatureScheme::ECDSA_NISTP256_SHA256,
117];
118
119static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[
120 SignatureScheme::RSA_PSS_SHA512,
121 SignatureScheme::RSA_PSS_SHA384,
122 SignatureScheme::RSA_PSS_SHA256,
123 SignatureScheme::RSA_PKCS1_SHA512,
124 SignatureScheme::RSA_PKCS1_SHA384,
125 SignatureScheme::RSA_PKCS1_SHA256,
126];
127
128pub(crate) static AES128_GCM: GcmAlgorithm = GcmAlgorithm(&aead::AES_128_GCM);
129pub(crate) static AES256_GCM: GcmAlgorithm = GcmAlgorithm(&aead::AES_256_GCM);
130
131pub(crate) struct GcmAlgorithm(&'static aead::Algorithm);
132
133impl Tls12AeadAlgorithm for GcmAlgorithm {
134 fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box<dyn MessageDecrypter> {
135 let dec_key =
137 aead::TlsRecordOpeningKey::new(self.0, aead::TlsProtocolId::TLS12, dec_key.as_ref())
138 .unwrap();
139
140 let mut ret = GcmMessageDecrypter {
141 dec_key,
142 dec_salt: [0u8; 4],
143 };
144
145 debug_assert_eq!(dec_iv.len(), 4);
146 ret.dec_salt.copy_from_slice(dec_iv);
147 Box::new(ret)
148 }
149
150 fn encrypter(
151 &self,
152 enc_key: AeadKey,
153 write_iv: &[u8],
154 explicit: &[u8],
155 ) -> Box<dyn MessageEncrypter> {
156 let enc_key =
169 aead::TlsRecordSealingKey::new(self.0, aead::TlsProtocolId::TLS13, enc_key.as_ref())
170 .unwrap();
171 let iv = gcm_iv(write_iv, explicit);
172 Box::new(GcmMessageEncrypter { enc_key, iv })
173 }
174
175 fn key_block_shape(&self) -> KeyBlockShape {
176 KeyBlockShape {
177 enc_key_len: self.0.key_len(),
178 fixed_iv_len: 4,
179 explicit_nonce_len: 8,
180 }
181 }
182
183 fn extract_keys(
184 &self,
185 key: AeadKey,
186 write_iv: &[u8],
187 explicit: &[u8],
188 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
189 let iv = gcm_iv(write_iv, explicit);
190 Ok(match self.0.key_len() {
191 16 => ConnectionTrafficSecrets::Aes128Gcm { key, iv },
192 32 => ConnectionTrafficSecrets::Aes256Gcm { key, iv },
193 _ => unreachable!(),
194 })
195 }
196
197 fn fips(&self) -> bool {
198 super::fips()
199 }
200}
201
202pub(crate) struct ChaCha20Poly1305;
203
204impl Tls12AeadAlgorithm for ChaCha20Poly1305 {
205 fn decrypter(&self, dec_key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> {
206 let dec_key = aead::LessSafeKey::new(
207 aead::UnboundKey::new(&aead::CHACHA20_POLY1305, dec_key.as_ref()).unwrap(),
208 );
209 Box::new(ChaCha20Poly1305MessageDecrypter {
210 dec_key,
211 dec_offset: Iv::copy(iv),
212 })
213 }
214
215 fn encrypter(&self, enc_key: AeadKey, enc_iv: &[u8], _: &[u8]) -> Box<dyn MessageEncrypter> {
216 let enc_key = aead::LessSafeKey::new(
217 aead::UnboundKey::new(&aead::CHACHA20_POLY1305, enc_key.as_ref()).unwrap(),
218 );
219 Box::new(ChaCha20Poly1305MessageEncrypter {
220 enc_key,
221 enc_offset: Iv::copy(enc_iv),
222 })
223 }
224
225 fn key_block_shape(&self) -> KeyBlockShape {
226 KeyBlockShape {
227 enc_key_len: 32,
228 fixed_iv_len: 12,
229 explicit_nonce_len: 0,
230 }
231 }
232
233 fn extract_keys(
234 &self,
235 key: AeadKey,
236 iv: &[u8],
237 _explicit: &[u8],
238 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
239 debug_assert_eq!(aead::NONCE_LEN, iv.len());
241 Ok(ConnectionTrafficSecrets::Chacha20Poly1305 {
242 key,
243 iv: Iv::new(iv[..].try_into().unwrap()),
244 })
245 }
246
247 fn fips(&self) -> bool {
248 false }
250}
251
252struct GcmMessageEncrypter {
254 enc_key: aead::TlsRecordSealingKey,
255 iv: Iv,
256}
257
258struct GcmMessageDecrypter {
260 dec_key: aead::TlsRecordOpeningKey,
261 dec_salt: [u8; 4],
262}
263
264const GCM_EXPLICIT_NONCE_LEN: usize = 8;
265const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
266
267impl MessageDecrypter for GcmMessageDecrypter {
268 fn decrypt<'a>(
269 &mut self,
270 mut msg: InboundOpaqueMessage<'a>,
271 seq: u64,
272 ) -> Result<InboundPlainMessage<'a>, Error> {
273 let payload = &msg.payload;
274 if payload.len() < GCM_OVERHEAD {
275 return Err(Error::DecryptError);
276 }
277
278 let nonce = {
279 let mut nonce = [0u8; 12];
280 nonce[..4].copy_from_slice(&self.dec_salt);
281 nonce[4..].copy_from_slice(&payload[..8]);
282 aead::Nonce::assume_unique_for_key(nonce)
283 };
284
285 let aad = aead::Aad::from(make_tls12_aad(
286 seq,
287 msg.typ,
288 msg.version,
289 payload.len() - GCM_OVERHEAD,
290 ));
291
292 let payload = &mut msg.payload;
293 let plain_len = self
294 .dec_key
295 .open_in_place(nonce, aad, &mut payload[GCM_EXPLICIT_NONCE_LEN..])
296 .map_err(|_| Error::DecryptError)?
297 .len();
298
299 if plain_len > MAX_FRAGMENT_LEN {
300 return Err(Error::PeerSentOversizedRecord);
301 }
302
303 Ok(
304 msg.into_plain_message_range(
305 GCM_EXPLICIT_NONCE_LEN..GCM_EXPLICIT_NONCE_LEN + plain_len,
306 ),
307 )
308 }
309}
310
311impl MessageEncrypter for GcmMessageEncrypter {
312 fn encrypt(
313 &mut self,
314 msg: OutboundPlainMessage<'_>,
315 seq: u64,
316 ) -> Result<OutboundOpaqueMessage, Error> {
317 let total_len = self.encrypted_payload_len(msg.payload.len());
318 let mut payload = PrefixedPayload::with_capacity(total_len);
319
320 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
321 let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
322 payload.extend_from_slice(&nonce.as_ref()[4..]);
323 payload.extend_from_chunks(&msg.payload);
324
325 self.enc_key
326 .seal_in_place_separate_tag(nonce, aad, &mut payload.as_mut()[GCM_EXPLICIT_NONCE_LEN..])
327 .map(|tag| payload.extend_from_slice(tag.as_ref()))
328 .map_err(|_| Error::EncryptError)?;
329
330 Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
331 }
332
333 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
334 payload_len + GCM_EXPLICIT_NONCE_LEN + self.enc_key.algorithm().tag_len()
335 }
336}
337
338struct ChaCha20Poly1305MessageEncrypter {
342 enc_key: aead::LessSafeKey,
343 enc_offset: Iv,
344}
345
346struct ChaCha20Poly1305MessageDecrypter {
350 dec_key: aead::LessSafeKey,
351 dec_offset: Iv,
352}
353
354const CHACHAPOLY1305_OVERHEAD: usize = 16;
355
356impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
357 fn decrypt<'a>(
358 &mut self,
359 mut msg: InboundOpaqueMessage<'a>,
360 seq: u64,
361 ) -> Result<InboundPlainMessage<'a>, Error> {
362 let payload = &msg.payload;
363
364 if payload.len() < CHACHAPOLY1305_OVERHEAD {
365 return Err(Error::DecryptError);
366 }
367
368 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.dec_offset, seq).0);
369 let aad = aead::Aad::from(make_tls12_aad(
370 seq,
371 msg.typ,
372 msg.version,
373 payload.len() - CHACHAPOLY1305_OVERHEAD,
374 ));
375
376 let payload = &mut msg.payload;
377 let plain_len = self
378 .dec_key
379 .open_in_place(nonce, aad, payload)
380 .map_err(|_| Error::DecryptError)?
381 .len();
382
383 if plain_len > MAX_FRAGMENT_LEN {
384 return Err(Error::PeerSentOversizedRecord);
385 }
386
387 payload.truncate(plain_len);
388 Ok(msg.into_plain_message())
389 }
390}
391
392impl MessageEncrypter for ChaCha20Poly1305MessageEncrypter {
393 fn encrypt(
394 &mut self,
395 msg: OutboundPlainMessage<'_>,
396 seq: u64,
397 ) -> Result<OutboundOpaqueMessage, Error> {
398 let total_len = self.encrypted_payload_len(msg.payload.len());
399 let mut payload = PrefixedPayload::with_capacity(total_len);
400
401 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.enc_offset, seq).0);
402 let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
403 payload.extend_from_chunks(&msg.payload);
404
405 self.enc_key
406 .seal_in_place_append_tag(nonce, aad, &mut payload)
407 .map_err(|_| Error::EncryptError)?;
408
409 Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
410 }
411
412 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
413 payload_len + self.enc_key.algorithm().tag_len()
414 }
415}
416
417fn gcm_iv(write_iv: &[u8], explicit: &[u8]) -> Iv {
418 debug_assert_eq!(write_iv.len(), 4);
419 debug_assert_eq!(explicit.len(), 8);
420
421 let mut iv = [0; NONCE_LEN];
429 iv[..4].copy_from_slice(write_iv);
430 iv[4..].copy_from_slice(explicit);
431
432 Iv::new(iv)
433}
434
435struct Tls12Prf(&'static tls_prf::Algorithm);
436
437impl Prf for Tls12Prf {
438 fn for_key_exchange(
439 &self,
440 output: &mut [u8; 48],
441 kx: Box<dyn ActiveKeyExchange>,
442 peer_pub_key: &[u8],
443 label: &[u8],
444 seed: &[u8],
445 ) -> Result<(), Error> {
446 Tls12PrfSecret {
447 alg: self.0,
448 secret: Secret::KeyExchange(kx.complete_for_tls_version(peer_pub_key, &TLS12)?),
449 }
450 .prf(output, label, seed);
451 Ok(())
452 }
453
454 fn new_secret(&self, secret: &[u8; 48]) -> Box<dyn PrfSecret> {
455 Box::new(Tls12PrfSecret {
456 alg: self.0,
457 secret: Secret::Master(Zeroizing::new(*secret)),
458 })
459 }
460
461 fn fips(&self) -> bool {
462 super::fips()
463 }
464}
465
466struct Tls12PrfSecret {
469 alg: &'static tls_prf::Algorithm,
470 secret: Secret,
471}
472
473impl PrfSecret for Tls12PrfSecret {
474 fn prf(&self, output: &mut [u8], label: &[u8], seed: &[u8]) {
475 let derived = tls_prf::Secret::new(self.alg, self.secret.as_ref())
481 .unwrap() .derive(label, seed, output.len())
483 .unwrap(); output.copy_from_slice(derived.as_ref());
485 }
486}
487
488enum Secret {
489 Master(Zeroizing<[u8; 48]>),
490 KeyExchange(SharedSecret),
491}
492
493impl AsRef<[u8]> for Secret {
494 fn as_ref(&self) -> &[u8] {
495 match self {
496 Self::Master(ms) => ms.as_ref(),
497 Self::KeyExchange(kx) => kx.secret_bytes(),
498 }
499 }
500}