1use crate::aead;
2use crate::hash::{SHA256, SHA384};
3use crate::hkdf::Hkdf;
4use crate::quic;
5use rustls::crypto::CipherSuiteCommon;
6use rustls::crypto::cipher::{
7 AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, MessageEncrypter,
8 Nonce, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, Tls13AeadAlgorithm,
9 UnsupportedOperationError, make_tls13_aad,
10};
11use rustls::{
12 CipherSuite, ConnectionTrafficSecrets, Error, SupportedCipherSuite, Tls13CipherSuite,
13};
14
15#[cfg(all(chacha, not(feature = "fips")))]
17pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
18 SupportedCipherSuite::Tls13(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
19
20#[cfg(all(chacha, not(feature = "fips")))]
21pub static TLS13_CHACHA20_POLY1305_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
22 common: CipherSuiteCommon {
23 suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
24 hash_provider: &SHA256,
25 confidentiality_limit: u64::MAX,
26 },
27 hkdf_provider: &Hkdf(SHA256),
28 aead_alg: &aead::Algorithm::ChaCha20Poly1305,
29 quic: Some(&quic::KeyBuilder {
30 packet_algo: aead::Algorithm::ChaCha20Poly1305,
31 header_algo: quic::HeaderProtectionAlgorithm::ChaCha20,
32 confidentiality_limit: u64::MAX,
34 integrity_limit: 1 << 36,
36 }),
37};
38
39pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
41 SupportedCipherSuite::Tls13(&Tls13CipherSuite {
42 common: CipherSuiteCommon {
43 suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
44 hash_provider: &SHA384,
45 confidentiality_limit: 1 << 23,
46 },
47 hkdf_provider: &Hkdf(SHA384),
48 aead_alg: &aead::Algorithm::Aes256Gcm,
49 quic: Some(&quic::KeyBuilder {
50 packet_algo: aead::Algorithm::Aes256Gcm,
51 header_algo: quic::HeaderProtectionAlgorithm::Aes256,
52 confidentiality_limit: 1 << 23,
54 integrity_limit: 1 << 52,
56 }),
57 });
58
59pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
61 SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL);
62
63pub static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
64 common: CipherSuiteCommon {
65 suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
66 hash_provider: &SHA256,
67 confidentiality_limit: 1 << 23,
68 },
69 hkdf_provider: &Hkdf(SHA256),
70 aead_alg: &aead::Algorithm::Aes128Gcm,
71 quic: Some(&quic::KeyBuilder {
72 packet_algo: aead::Algorithm::Aes128Gcm,
73 header_algo: quic::HeaderProtectionAlgorithm::Aes128,
74 confidentiality_limit: 1 << 23,
76 integrity_limit: 1 << 52,
78 }),
79};
80
81struct Tls13Crypter {
82 algo: aead::Algorithm,
83 key: AeadKey,
84 iv: Iv,
85}
86
87impl Tls13AeadAlgorithm for aead::Algorithm {
88 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
89 Box::new(Tls13Crypter {
90 algo: *self,
91 key,
92 iv,
93 })
94 }
95
96 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
97 Box::new(Tls13Crypter {
98 algo: *self,
99 key,
100 iv,
101 })
102 }
103
104 fn key_len(&self) -> usize {
105 self.key_size()
106 }
107
108 fn extract_keys(
109 &self,
110 key: AeadKey,
111 iv: Iv,
112 ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
113 Ok(match self {
114 aead::Algorithm::Aes128Gcm => ConnectionTrafficSecrets::Aes128Gcm { key, iv },
115 aead::Algorithm::Aes256Gcm => ConnectionTrafficSecrets::Aes256Gcm { key, iv },
116 #[cfg(all(chacha, not(feature = "fips")))]
117 aead::Algorithm::ChaCha20Poly1305 => {
118 ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }
119 }
120 })
121 }
122
123 fn fips(&self) -> bool {
124 crate::fips::enabled()
125 }
126}
127
128impl MessageEncrypter for Tls13Crypter {
129 fn encrypt(
130 &mut self,
131 msg: OutboundPlainMessage,
132 seq: u64,
133 ) -> Result<OutboundOpaqueMessage, Error> {
134 let total_len = self.encrypted_payload_len(msg.payload.len());
135 let mut payload = PrefixedPayload::with_capacity(total_len);
136 let aad = make_tls13_aad(total_len);
137 payload.extend_from_chunks(&msg.payload);
138 payload.extend_from_slice(&msg.typ.to_array());
139 let tag = self.algo.encrypt_in_place(
140 self.key.as_ref(),
141 &Nonce::new(&self.iv, seq).0,
142 &aad,
143 payload.as_mut(),
144 )?;
145 payload.extend_from_slice(&tag);
146 Ok(OutboundOpaqueMessage::new(
147 rustls::ContentType::ApplicationData,
148 rustls::ProtocolVersion::TLSv1_2,
151 payload,
152 ))
153 }
154
155 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
156 payload_len + 1 + aead::TAG_LEN
157 }
158}
159
160impl MessageDecrypter for Tls13Crypter {
161 fn decrypt<'a>(
162 &mut self,
163 mut msg: InboundOpaqueMessage<'a>,
164 seq: u64,
165 ) -> Result<InboundPlainMessage<'a>, Error> {
166 let payload = &mut msg.payload;
167 let aad = make_tls13_aad(payload.len());
168 let plaintext_len = self.algo.decrypt_in_place(
169 self.key.as_ref(),
170 &Nonce::new(&self.iv, seq).0,
171 &aad,
172 payload.as_mut(),
173 )?;
174 payload.truncate(plaintext_len);
176 msg.into_tls13_unpadded_message()
177 }
178}