1use alloc::boxed::Box;
2
3use super::ring_like::hkdf::KeyType;
4use super::ring_like::{aead, hkdf, hmac};
5use crate::crypto;
6use crate::crypto::cipher::{
7 AeadKey, InboundOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
8 Tls13AeadAlgorithm, UnsupportedOperationError, make_tls13_aad,
9};
10use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
11use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
12use crate::error::Error;
13use crate::msgs::message::{
14 InboundPlainMessage, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload,
15};
16use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
17use crate::tls13::Tls13CipherSuite;
18use crate::version::TLS13_VERSION;
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 protocol_version: TLS13_VERSION,
32 hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
33 aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)),
34 quic: Some(&super::quic::KeyBuilder {
35 packet_alg: &aead::CHACHA20_POLY1305,
36 header_alg: &aead::quic::CHACHA20,
37 confidentiality_limit: u64::MAX,
39 integrity_limit: 1 << 36,
41 }),
42};
43
44pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite =
46 SupportedCipherSuite::Tls13(&Tls13CipherSuite {
47 common: CipherSuiteCommon {
48 suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
49 hash_provider: &super::hash::SHA384,
50 confidentiality_limit: 1 << 24,
51 },
52 protocol_version: TLS13_VERSION,
53 hkdf_provider: &RingHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384),
54 aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)),
55 quic: Some(&super::quic::KeyBuilder {
56 packet_alg: &aead::AES_256_GCM,
57 header_alg: &aead::quic::AES_256,
58 confidentiality_limit: 1 << 23,
60 integrity_limit: 1 << 52,
62 }),
63 });
64
65pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite =
67 SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL);
68
69pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite {
70 common: CipherSuiteCommon {
71 suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
72 hash_provider: &super::hash::SHA256,
73 confidentiality_limit: 1 << 24,
74 },
75 protocol_version: TLS13_VERSION,
76 hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256),
77 aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)),
78 quic: Some(&super::quic::KeyBuilder {
79 packet_alg: &aead::AES_128_GCM,
80 header_alg: &aead::quic::AES_128,
81 confidentiality_limit: 1 << 23,
83 integrity_limit: 1 << 52,
85 }),
86};
87
88struct Chacha20Poly1305Aead(AeadAlgorithm);
89
90impl Tls13AeadAlgorithm for Chacha20Poly1305Aead {
91 fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
92 self.0.encrypter(key, iv)
93 }
94
95 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
96 self.0.decrypter(key, iv)
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> {
177 Box::new(Tls13MessageEncrypter {
179 enc_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0, key.as_ref()).unwrap()),
180 iv,
181 })
182 }
183
184 fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
185 Box::new(Tls13MessageDecrypter {
187 dec_key: aead::LessSafeKey::new(aead::UnboundKey::new(self.0, key.as_ref()).unwrap()),
188 iv,
189 })
190 }
191
192 fn key_len(&self) -> usize {
193 self.0.key_len()
194 }
195}
196
197struct Tls13MessageEncrypter {
198 enc_key: aead::LessSafeKey,
199 iv: Iv,
200}
201
202struct Tls13MessageDecrypter {
203 dec_key: aead::LessSafeKey,
204 iv: Iv,
205}
206
207impl MessageEncrypter for Tls13MessageEncrypter {
208 fn encrypt(
209 &mut self,
210 msg: OutboundPlainMessage<'_>,
211 seq: u64,
212 ) -> Result<OutboundOpaqueMessage, Error> {
213 let total_len = self.encrypted_payload_len(msg.payload.len());
214 let mut payload = PrefixedPayload::with_capacity(total_len);
215
216 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
217 let aad = aead::Aad::from(make_tls13_aad(total_len));
218 payload.extend_from_chunks(&msg.payload);
219 payload.extend_from_slice(&msg.typ.to_array());
220
221 self.enc_key
222 .seal_in_place_append_tag(nonce, aad, &mut payload)
223 .map_err(|_| Error::EncryptError)?;
224
225 Ok(OutboundOpaqueMessage::new(
226 ContentType::ApplicationData,
227 ProtocolVersion::TLSv1_2,
230 payload,
231 ))
232 }
233
234 fn encrypted_payload_len(&self, payload_len: usize) -> usize {
235 payload_len + 1 + self.enc_key.algorithm().tag_len()
236 }
237}
238
239impl MessageDecrypter for Tls13MessageDecrypter {
240 fn decrypt<'a>(
241 &mut self,
242 mut msg: InboundOpaqueMessage<'a>,
243 seq: u64,
244 ) -> Result<InboundPlainMessage<'a>, Error> {
245 let payload = &mut msg.payload;
246 if payload.len() < self.dec_key.algorithm().tag_len() {
247 return Err(Error::DecryptError);
248 }
249
250 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
251 let aad = aead::Aad::from(make_tls13_aad(payload.len()));
252 let plain_len = self
253 .dec_key
254 .open_in_place(nonce, aad, payload)
255 .map_err(|_| Error::DecryptError)?
256 .len();
257
258 payload.truncate(plain_len);
259 msg.into_tls13_unpadded_message()
260 }
261}
262
263struct RingHkdf(hkdf::Algorithm, hmac::Algorithm);
264
265impl Hkdf for RingHkdf {
266 fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander> {
267 let zeroes = [0u8; OkmBlock::MAX_LEN];
268 let salt = match salt {
269 Some(salt) => salt,
270 None => &zeroes[..self.0.len()],
271 };
272 Box::new(RingHkdfExpander {
273 alg: self.0,
274 prk: hkdf::Salt::new(self.0, salt).extract(&zeroes[..self.0.len()]),
275 })
276 }
277
278 fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander> {
279 let zeroes = [0u8; OkmBlock::MAX_LEN];
280 let salt = match salt {
281 Some(salt) => salt,
282 None => &zeroes[..self.0.len()],
283 };
284 Box::new(RingHkdfExpander {
285 alg: self.0,
286 prk: hkdf::Salt::new(self.0, salt).extract(secret),
287 })
288 }
289
290 fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander> {
291 Box::new(RingHkdfExpander {
292 alg: self.0,
293 prk: hkdf::Prk::new_less_safe(self.0, okm.as_ref()),
294 })
295 }
296
297 fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag {
298 crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref())
299 }
300
301 fn fips(&self) -> bool {
302 super::fips()
303 }
304}
305
306struct RingHkdfExpander {
307 alg: hkdf::Algorithm,
308 prk: hkdf::Prk,
309}
310
311impl HkdfExpander for RingHkdfExpander {
312 fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError> {
313 self.prk
314 .expand(info, Len(output.len()))
315 .and_then(|okm| okm.fill(output))
316 .map_err(|_| OutputLengthError)
317 }
318
319 fn expand_block(&self, info: &[&[u8]]) -> OkmBlock {
320 let mut buf = [0u8; OkmBlock::MAX_LEN];
321 let output = &mut buf[..self.hash_len()];
322 self.prk
323 .expand(info, Len(output.len()))
324 .and_then(|okm| okm.fill(output))
325 .unwrap();
326 OkmBlock::new(output)
327 }
328
329 fn hash_len(&self) -> usize {
330 self.alg.len()
331 }
332}
333
334struct Len(usize);
335
336impl KeyType for Len {
337 fn len(&self) -> usize {
338 self.0
339 }
340}