1 | use alloc::boxed::Box; |
2 | use alloc::vec::Vec; |
3 | |
4 | use crate::crypto; |
5 | use crate::crypto::cipher::{ |
6 | make_tls13_aad, AeadKey, Iv, MessageDecrypter, MessageEncrypter, Nonce, Tls13AeadAlgorithm, |
7 | UnsupportedOperationError, |
8 | }; |
9 | use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError}; |
10 | use crate::enums::{CipherSuite, ContentType, ProtocolVersion}; |
11 | use crate::error::Error; |
12 | use crate::msgs::codec::Codec; |
13 | use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage}; |
14 | use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite}; |
15 | use crate::tls13::Tls13CipherSuite; |
16 | |
17 | use super::ring_like::hkdf::KeyType; |
18 | use super::ring_like::{aead, hkdf, hmac}; |
19 | |
20 | /// The TLS1.3 ciphersuite TLS_CHACHA20_POLY1305_SHA256 |
21 | pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = |
22 | SupportedCipherSuite::Tls13(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL); |
23 | |
24 | pub(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, |
29 | integrity_limit: 1 << 36, |
30 | }, |
31 | hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256), |
32 | aead_alg: &Chacha20Poly1305Aead(AeadAlgorithm(&aead::CHACHA20_POLY1305)), |
33 | quic: Some(&super::quic::KeyBuilder( |
34 | &aead::CHACHA20_POLY1305, |
35 | &aead::quic::CHACHA20, |
36 | )), |
37 | }; |
38 | |
39 | /// The TLS1.3 ciphersuite TLS_AES_256_GCM_SHA384 |
40 | pub 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: &super::hash::SHA384, |
45 | confidentiality_limit: 1 << 23, |
46 | integrity_limit: 1 << 52, |
47 | }, |
48 | hkdf_provider: &RingHkdf(hkdf::HKDF_SHA384, hmac::HMAC_SHA384), |
49 | aead_alg: &Aes256GcmAead(AeadAlgorithm(&aead::AES_256_GCM)), |
50 | quic: Some(&super::quic::KeyBuilder( |
51 | &aead::AES_256_GCM, |
52 | &aead::quic::AES_256, |
53 | )), |
54 | }); |
55 | |
56 | /// The TLS1.3 ciphersuite TLS_AES_128_GCM_SHA256 |
57 | pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = |
58 | SupportedCipherSuite::Tls13(TLS13_AES_128_GCM_SHA256_INTERNAL); |
59 | |
60 | pub(crate) static TLS13_AES_128_GCM_SHA256_INTERNAL: &Tls13CipherSuite = &Tls13CipherSuite { |
61 | common: CipherSuiteCommon { |
62 | suite: CipherSuite::TLS13_AES_128_GCM_SHA256, |
63 | hash_provider: &super::hash::SHA256, |
64 | confidentiality_limit: 1 << 23, |
65 | integrity_limit: 1 << 52, |
66 | }, |
67 | hkdf_provider: &RingHkdf(hkdf::HKDF_SHA256, hmac::HMAC_SHA256), |
68 | aead_alg: &Aes128GcmAead(AeadAlgorithm(&aead::AES_128_GCM)), |
69 | quic: Some(&super::quic::KeyBuilder( |
70 | &aead::AES_128_GCM, |
71 | &aead::quic::AES_128, |
72 | )), |
73 | }; |
74 | |
75 | struct Chacha20Poly1305Aead(AeadAlgorithm); |
76 | |
77 | impl Tls13AeadAlgorithm for Chacha20Poly1305Aead { |
78 | fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> { |
79 | self.0.encrypter(key, iv) |
80 | } |
81 | |
82 | fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> { |
83 | self.0.decrypter(key, iv) |
84 | } |
85 | |
86 | fn key_len(&self) -> usize { |
87 | self.0.key_len() |
88 | } |
89 | |
90 | fn extract_keys( |
91 | &self, |
92 | key: AeadKey, |
93 | iv: Iv, |
94 | ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> { |
95 | Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }) |
96 | } |
97 | } |
98 | |
99 | struct Aes256GcmAead(AeadAlgorithm); |
100 | |
101 | impl Tls13AeadAlgorithm for Aes256GcmAead { |
102 | fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> { |
103 | self.0.encrypter(key, iv) |
104 | } |
105 | |
106 | fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> { |
107 | self.0.decrypter(key, iv) |
108 | } |
109 | |
110 | fn key_len(&self) -> usize { |
111 | self.0.key_len() |
112 | } |
113 | |
114 | fn extract_keys( |
115 | &self, |
116 | key: AeadKey, |
117 | iv: Iv, |
118 | ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> { |
119 | Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv }) |
120 | } |
121 | } |
122 | |
123 | struct Aes128GcmAead(AeadAlgorithm); |
124 | |
125 | impl Tls13AeadAlgorithm for Aes128GcmAead { |
126 | fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> { |
127 | self.0.encrypter(key, iv) |
128 | } |
129 | |
130 | fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> { |
131 | self.0.decrypter(key, iv) |
132 | } |
133 | |
134 | fn key_len(&self) -> usize { |
135 | self.0.key_len() |
136 | } |
137 | |
138 | fn extract_keys( |
139 | &self, |
140 | key: AeadKey, |
141 | iv: Iv, |
142 | ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> { |
143 | Ok(ConnectionTrafficSecrets::Aes128Gcm { key, iv }) |
144 | } |
145 | } |
146 | |
147 | // common encrypter/decrypter/key_len items for above Tls13AeadAlgorithm impls |
148 | struct AeadAlgorithm(&'static aead::Algorithm); |
149 | |
150 | impl AeadAlgorithm { |
151 | fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> { |
152 | // safety: the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe. |
153 | Box::new(Tls13MessageEncrypter { |
154 | enc_key: aead::LessSafeKey::new(key:aead::UnboundKey::new(self.0, key_bytes:key.as_ref()).unwrap()), |
155 | iv, |
156 | }) |
157 | } |
158 | |
159 | fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> { |
160 | // safety: the caller arranges that `key` is `key_len()` in bytes, so this unwrap is safe. |
161 | Box::new(Tls13MessageDecrypter { |
162 | dec_key: aead::LessSafeKey::new(key:aead::UnboundKey::new(self.0, key_bytes:key.as_ref()).unwrap()), |
163 | iv, |
164 | }) |
165 | } |
166 | |
167 | fn key_len(&self) -> usize { |
168 | self.0.key_len() |
169 | } |
170 | } |
171 | |
172 | struct Tls13MessageEncrypter { |
173 | enc_key: aead::LessSafeKey, |
174 | iv: Iv, |
175 | } |
176 | |
177 | struct Tls13MessageDecrypter { |
178 | dec_key: aead::LessSafeKey, |
179 | iv: Iv, |
180 | } |
181 | |
182 | impl MessageEncrypter for Tls13MessageEncrypter { |
183 | fn encrypt(&mut self, msg: BorrowedPlainMessage, seq: u64) -> Result<OpaqueMessage, Error> { |
184 | let total_len = self.encrypted_payload_len(msg.payload.len()); |
185 | let mut payload = Vec::with_capacity(total_len); |
186 | payload.extend_from_slice(msg.payload); |
187 | msg.typ.encode(&mut payload); |
188 | |
189 | let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0); |
190 | let aad = aead::Aad::from(make_tls13_aad(total_len)); |
191 | self.enc_key |
192 | .seal_in_place_append_tag(nonce, aad, &mut payload) |
193 | .map_err(|_| Error::EncryptError)?; |
194 | |
195 | Ok(OpaqueMessage::new( |
196 | ContentType::ApplicationData, |
197 | // Note: all TLS 1.3 application data records use TLSv1_2 (0x0303) as the legacy record |
198 | // protocol version, see https://www.rfc-editor.org/rfc/rfc8446#section-5.1 |
199 | ProtocolVersion::TLSv1_2, |
200 | payload, |
201 | )) |
202 | } |
203 | |
204 | fn encrypted_payload_len(&self, payload_len: usize) -> usize { |
205 | payload_len + 1 + self.enc_key.algorithm().tag_len() |
206 | } |
207 | } |
208 | |
209 | impl MessageDecrypter for Tls13MessageDecrypter { |
210 | fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> { |
211 | let payload: &mut Vec = msg.payload_mut(); |
212 | if payload.len() < self.dec_key.algorithm().tag_len() { |
213 | return Err(Error::DecryptError); |
214 | } |
215 | |
216 | let nonce: Nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0); |
217 | let aad: Aad<[u8; 5]> = aead::Aad::from(aad:make_tls13_aad(payload_len:payload.len())); |
218 | let plain_len: usize = self |
219 | .dec_key |
220 | .open_in_place(nonce, aad, payload) |
221 | .map_err(|_| Error::DecryptError)? |
222 | .len(); |
223 | |
224 | payload.truncate(plain_len); |
225 | msg.into_tls13_unpadded_message() |
226 | } |
227 | } |
228 | |
229 | struct RingHkdf(hkdf::Algorithm, hmac::Algorithm); |
230 | |
231 | impl Hkdf for RingHkdf { |
232 | fn extract_from_zero_ikm(&self, salt: Option<&[u8]>) -> Box<dyn HkdfExpander> { |
233 | let zeroes = [0u8; OkmBlock::MAX_LEN]; |
234 | let salt = match salt { |
235 | Some(salt) => salt, |
236 | None => &zeroes[..self.0.len()], |
237 | }; |
238 | Box::new(RingHkdfExpander { |
239 | alg: self.0, |
240 | prk: hkdf::Salt::new(self.0, salt).extract(&zeroes[..self.0.len()]), |
241 | }) |
242 | } |
243 | |
244 | fn extract_from_secret(&self, salt: Option<&[u8]>, secret: &[u8]) -> Box<dyn HkdfExpander> { |
245 | let zeroes = [0u8; OkmBlock::MAX_LEN]; |
246 | let salt = match salt { |
247 | Some(salt) => salt, |
248 | None => &zeroes[..self.0.len()], |
249 | }; |
250 | Box::new(RingHkdfExpander { |
251 | alg: self.0, |
252 | prk: hkdf::Salt::new(self.0, salt).extract(secret), |
253 | }) |
254 | } |
255 | |
256 | fn expander_for_okm(&self, okm: &OkmBlock) -> Box<dyn HkdfExpander> { |
257 | Box::new(RingHkdfExpander { |
258 | alg: self.0, |
259 | prk: hkdf::Prk::new_less_safe(self.0, okm.as_ref()), |
260 | }) |
261 | } |
262 | |
263 | fn hmac_sign(&self, key: &OkmBlock, message: &[u8]) -> crypto::hmac::Tag { |
264 | crypto::hmac::Tag::new(hmac::sign(&hmac::Key::new(self.1, key.as_ref()), message).as_ref()) |
265 | } |
266 | } |
267 | |
268 | struct RingHkdfExpander { |
269 | alg: hkdf::Algorithm, |
270 | prk: hkdf::Prk, |
271 | } |
272 | |
273 | impl HkdfExpander for RingHkdfExpander { |
274 | fn expand_slice(&self, info: &[&[u8]], output: &mut [u8]) -> Result<(), OutputLengthError> { |
275 | self.prk |
276 | .expand(info, Len(output.len())) |
277 | .and_then(|okm| okm.fill(output)) |
278 | .map_err(|_| OutputLengthError) |
279 | } |
280 | |
281 | fn expand_block(&self, info: &[&[u8]]) -> OkmBlock { |
282 | let mut buf: [u8; 64] = [0u8; OkmBlock::MAX_LEN]; |
283 | let output: &mut [u8] = &mut buf[..self.hash_len()]; |
284 | self.prk |
285 | .expand(info, Len(output.len())) |
286 | .and_then(|okm: Okm<'_, Len>| okm.fill(out:output)) |
287 | .unwrap(); |
288 | OkmBlock::new(bytes:output) |
289 | } |
290 | |
291 | fn hash_len(&self) -> usize { |
292 | self.alg.len() |
293 | } |
294 | } |
295 | |
296 | struct Len(usize); |
297 | |
298 | impl KeyType for Len { |
299 | fn len(&self) -> usize { |
300 | self.0 |
301 | } |
302 | } |
303 | |