1#![allow(clippy::duplicate_mod)]
2
3use alloc::boxed::Box;
4
5use super::ring_like::aead;
6use crate::crypto::cipher::{AeadKey, Iv, Nonce};
7use crate::error::Error;
8use crate::quic;
9
10pub(crate) struct HeaderProtectionKey(aead::quic::HeaderProtectionKey);
11
12impl HeaderProtectionKey {
13 pub(crate) fn new(key: AeadKey, alg: &'static aead::quic::Algorithm) -> Self {
14 Self(aead::quic::HeaderProtectionKey::new(alg, key.as_ref()).unwrap())
15 }
16
17 fn xor_in_place(
18 &self,
19 sample: &[u8],
20 first: &mut u8,
21 packet_number: &mut [u8],
22 masked: bool,
23 ) -> Result<(), Error> {
24 let mask = self
28 .0
29 .new_mask(sample)
30 .map_err(|_| Error::General("sample of invalid length".into()))?;
31
32 let (first_mask, pn_mask) = mask.split_first().unwrap();
35
36 if packet_number.len() > pn_mask.len() {
39 return Err(Error::General("packet number too long".into()));
40 }
41
42 const LONG_HEADER_FORM: u8 = 0x80;
46 let bits = match *first & LONG_HEADER_FORM == LONG_HEADER_FORM {
47 true => 0x0f, false => 0x1f, };
50
51 let first_plain = match masked {
52 true => *first ^ (first_mask & bits),
54 false => *first,
56 };
57 let pn_len = (first_plain & 0x03) as usize + 1;
58
59 *first ^= first_mask & bits;
60 for (dst, m) in packet_number
61 .iter_mut()
62 .zip(pn_mask)
63 .take(pn_len)
64 {
65 *dst ^= m;
66 }
67
68 Ok(())
69 }
70}
71
72impl quic::HeaderProtectionKey for HeaderProtectionKey {
73 fn encrypt_in_place(
74 &self,
75 sample: &[u8],
76 first: &mut u8,
77 packet_number: &mut [u8],
78 ) -> Result<(), Error> {
79 self.xor_in_place(sample, first, packet_number, false)
80 }
81
82 fn decrypt_in_place(
83 &self,
84 sample: &[u8],
85 first: &mut u8,
86 packet_number: &mut [u8],
87 ) -> Result<(), Error> {
88 self.xor_in_place(sample, first, packet_number, true)
89 }
90
91 #[inline]
92 fn sample_len(&self) -> usize {
93 self.0.algorithm().sample_len()
94 }
95}
96
97pub(crate) struct PacketKey {
98 key: aead::LessSafeKey,
100 iv: Iv,
102 confidentiality_limit: u64,
104 integrity_limit: u64,
106}
107
108impl PacketKey {
109 pub(crate) fn new(
110 key: AeadKey,
111 iv: Iv,
112 confidentiality_limit: u64,
113 integrity_limit: u64,
114 aead_algorithm: &'static aead::Algorithm,
115 ) -> Self {
116 Self {
117 key: aead::LessSafeKey::new(
118 aead::UnboundKey::new(aead_algorithm, key.as_ref()).unwrap(),
119 ),
120 iv,
121 confidentiality_limit,
122 integrity_limit,
123 }
124 }
125}
126
127impl quic::PacketKey for PacketKey {
128 fn encrypt_in_place(
129 &self,
130 packet_number: u64,
131 header: &[u8],
132 payload: &mut [u8],
133 ) -> Result<quic::Tag, Error> {
134 let aad = aead::Aad::from(header);
135 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, packet_number).0);
136 let tag = self
137 .key
138 .seal_in_place_separate_tag(nonce, aad, payload)
139 .map_err(|_| Error::EncryptError)?;
140 Ok(quic::Tag::from(tag.as_ref()))
141 }
142
143 fn decrypt_in_place<'a>(
151 &self,
152 packet_number: u64,
153 header: &[u8],
154 payload: &'a mut [u8],
155 ) -> Result<&'a [u8], Error> {
156 let payload_len = payload.len();
157 let aad = aead::Aad::from(header);
158 let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, packet_number).0);
159 self.key
160 .open_in_place(nonce, aad, payload)
161 .map_err(|_| Error::DecryptError)?;
162
163 let plain_len = payload_len - self.key.algorithm().tag_len();
164 Ok(&payload[..plain_len])
165 }
166
167 #[inline]
169 fn tag_len(&self) -> usize {
170 self.key.algorithm().tag_len()
171 }
172
173 fn confidentiality_limit(&self) -> u64 {
175 self.confidentiality_limit
176 }
177
178 fn integrity_limit(&self) -> u64 {
180 self.integrity_limit
181 }
182}
183
184pub(crate) struct KeyBuilder {
185 pub(crate) packet_alg: &'static aead::Algorithm,
186 pub(crate) header_alg: &'static aead::quic::Algorithm,
187 pub(crate) confidentiality_limit: u64,
188 pub(crate) integrity_limit: u64,
189}
190
191impl quic::Algorithm for KeyBuilder {
192 fn packet_key(&self, key: AeadKey, iv: Iv) -> Box<dyn quic::PacketKey> {
193 Box::new(PacketKey::new(
194 key,
195 iv,
196 self.confidentiality_limit,
197 self.integrity_limit,
198 self.packet_alg,
199 ))
200 }
201
202 fn header_protection_key(&self, key: AeadKey) -> Box<dyn quic::HeaderProtectionKey> {
203 Box::new(HeaderProtectionKey::new(key, self.header_alg))
204 }
205
206 fn aead_key_len(&self) -> usize {
207 self.packet_alg.key_len()
208 }
209
210 fn fips(&self) -> bool {
211 super::fips()
212 }
213}
214
215test_for_each_provider! {
216 use std::dbg;
217 use crate::common_state::Side;
218 use crate::crypto::tls13::OkmBlock;
219 use crate::quic::*;
220 use provider::tls13::{
221 TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
222 };
223
224 fn test_short_packet(version: Version, expected: &[u8]) {
225 const PN: u64 = 654360564;
226 const SECRET: &[u8] = &[
227 0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42, 0x27, 0x48, 0xad,
228 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0, 0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3,
229 0x0f, 0x21, 0x63, 0x2b,
230 ];
231
232 let secret = OkmBlock::new(SECRET);
233 let builder = KeyBuilder::new(
234 &secret,
235 version,
236 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
237 .quic
238 .unwrap(),
239 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.hkdf_provider,
240 );
241 let packet = builder.packet_key();
242 let hpk = builder.header_protection_key();
243
244 const PLAIN: &[u8] = &[0x42, 0x00, 0xbf, 0xf4, 0x01];
245
246 let mut buf = PLAIN.to_vec();
247 let (header, payload) = buf.split_at_mut(4);
248 let tag = packet
249 .encrypt_in_place(PN, header, payload)
250 .unwrap();
251 buf.extend(tag.as_ref());
252
253 let pn_offset = 1;
254 let (header, sample) = buf.split_at_mut(pn_offset + 4);
255 let (first, rest) = header.split_at_mut(1);
256 let sample = &sample[..hpk.sample_len()];
257 hpk.encrypt_in_place(sample, &mut first[0], dbg!(rest))
258 .unwrap();
259
260 assert_eq!(&buf, expected);
261
262 let (header, sample) = buf.split_at_mut(pn_offset + 4);
263 let (first, rest) = header.split_at_mut(1);
264 let sample = &sample[..hpk.sample_len()];
265 hpk.decrypt_in_place(sample, &mut first[0], rest)
266 .unwrap();
267
268 let (header, payload_tag) = buf.split_at_mut(4);
269 let plain = packet
270 .decrypt_in_place(PN, header, payload_tag)
271 .unwrap();
272
273 assert_eq!(plain, &PLAIN[4..]);
274 }
275
276 #[test]
277 fn short_packet_header_protection() {
278 test_short_packet(
280 Version::V1,
281 &[
282 0x4c, 0xfe, 0x41, 0x89, 0x65, 0x5e, 0x5c, 0xd5, 0x5c, 0x41, 0xf6, 0x90, 0x80, 0x57,
283 0x5d, 0x79, 0x99, 0xc2, 0x5a, 0x5b, 0xfb,
284 ],
285 );
286 }
287
288 #[test]
289 fn key_update_test_vector() {
290 fn equal_okm(x: &OkmBlock, y: &OkmBlock) -> bool {
291 x.as_ref() == y.as_ref()
292 }
293
294 let mut secrets = Secrets::new(
295 OkmBlock::new(
297 &[
298 0xb8, 0x76, 0x77, 0x08, 0xf8, 0x77, 0x23, 0x58, 0xa6, 0xea, 0x9f, 0xc4, 0x3e,
299 0x4a, 0xdd, 0x2c, 0x96, 0x1b, 0x3f, 0x52, 0x87, 0xa6, 0xd1, 0x46, 0x7e, 0xe0,
300 0xae, 0xab, 0x33, 0x72, 0x4d, 0xbf,
301 ][..],
302 ),
303 OkmBlock::new(
304 &[
305 0x42, 0xdc, 0x97, 0x21, 0x40, 0xe0, 0xf2, 0xe3, 0x98, 0x45, 0xb7, 0x67, 0x61,
306 0x34, 0x39, 0xdc, 0x67, 0x58, 0xca, 0x43, 0x25, 0x9b, 0x87, 0x85, 0x06, 0x82,
307 0x4e, 0xb1, 0xe4, 0x38, 0xd8, 0x55,
308 ][..],
309 ),
310 TLS13_AES_128_GCM_SHA256_INTERNAL,
311 TLS13_AES_128_GCM_SHA256_INTERNAL
312 .quic
313 .unwrap(),
314 Side::Client,
315 Version::V1,
316 );
317 secrets.update();
318
319 assert!(equal_okm(
320 &secrets.client,
321 &OkmBlock::new(
322 &[
323 0x42, 0xca, 0xc8, 0xc9, 0x1c, 0xd5, 0xeb, 0x40, 0x68, 0x2e, 0x43, 0x2e, 0xdf,
324 0x2d, 0x2b, 0xe9, 0xf4, 0x1a, 0x52, 0xca, 0x6b, 0x22, 0xd8, 0xe6, 0xcd, 0xb1,
325 0xe8, 0xac, 0xa9, 0x6, 0x1f, 0xce
326 ][..]
327 )
328 ));
329 assert!(equal_okm(
330 &secrets.server,
331 &OkmBlock::new(
332 &[
333 0xeb, 0x7f, 0x5e, 0x2a, 0x12, 0x3f, 0x40, 0x7d, 0xb4, 0x99, 0xe3, 0x61, 0xca,
334 0xe5, 0x90, 0xd4, 0xd9, 0x92, 0xe1, 0x4b, 0x7a, 0xce, 0x3, 0xc2, 0x44, 0xe0,
335 0x42, 0x21, 0x15, 0xb6, 0xd3, 0x8a
336 ][..]
337 )
338 ));
339 }
340
341 #[test]
342 fn short_packet_header_protection_v2() {
343 test_short_packet(
345 Version::V2,
346 &[
347 0x55, 0x58, 0xb1, 0xc6, 0x0a, 0xe7, 0xb6, 0xb9, 0x32, 0xbc, 0x27, 0xd7, 0x86, 0xf4,
348 0xbc, 0x2b, 0xb2, 0x0f, 0x21, 0x62, 0xba,
349 ],
350 );
351 }
352
353 #[test]
354 fn initial_test_vector_v2() {
355 let icid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
357 let server = Keys::initial(
358 Version::V2,
359 TLS13_AES_128_GCM_SHA256_INTERNAL,
360 TLS13_AES_128_GCM_SHA256_INTERNAL
361 .quic
362 .unwrap(),
363 &icid,
364 Side::Server,
365 );
366 let mut server_payload = [
367 0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x5a, 0x02, 0x00, 0x00, 0x56, 0x03,
368 0x03, 0xee, 0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1, 0xd1, 0x63, 0x2e, 0x96, 0x67, 0x78,
369 0x25, 0xdd, 0xf7, 0x39, 0x88, 0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, 0x6d, 0xc5, 0x43,
370 0x0b, 0x9a, 0x04, 0x5a, 0x12, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33, 0x00,
371 0x24, 0x00, 0x1d, 0x00, 0x20, 0x9d, 0x3c, 0x94, 0x0d, 0x89, 0x69, 0x0b, 0x84, 0xd0,
372 0x8a, 0x60, 0x99, 0x3c, 0x14, 0x4e, 0xca, 0x68, 0x4d, 0x10, 0x81, 0x28, 0x7c, 0x83,
373 0x4d, 0x53, 0x11, 0xbc, 0xf3, 0x2b, 0xb9, 0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03,
374 0x04,
375 ];
376 let mut server_header = [
377 0xd1, 0x6b, 0x33, 0x43, 0xcf, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62,
378 0xb5, 0x00, 0x40, 0x75, 0x00, 0x01,
379 ];
380 let tag = server
381 .local
382 .packet
383 .encrypt_in_place(1, &server_header, &mut server_payload)
384 .unwrap();
385 let (first, rest) = server_header.split_at_mut(1);
386 let rest_len = rest.len();
387 server
388 .local
389 .header
390 .encrypt_in_place(
391 &server_payload[2..18],
392 &mut first[0],
393 &mut rest[rest_len - 2..],
394 )
395 .unwrap();
396 let mut server_packet = server_header.to_vec();
397 server_packet.extend(server_payload);
398 server_packet.extend(tag.as_ref());
399 let expected_server_packet = [
400 0xdc, 0x6b, 0x33, 0x43, 0xcf, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62,
401 0xb5, 0x00, 0x40, 0x75, 0xd9, 0x2f, 0xaa, 0xf1, 0x6f, 0x05, 0xd8, 0xa4, 0x39, 0x8c,
402 0x47, 0x08, 0x96, 0x98, 0xba, 0xee, 0xa2, 0x6b, 0x91, 0xeb, 0x76, 0x1d, 0x9b, 0x89,
403 0x23, 0x7b, 0xbf, 0x87, 0x26, 0x30, 0x17, 0x91, 0x53, 0x58, 0x23, 0x00, 0x35, 0xf7,
404 0xfd, 0x39, 0x45, 0xd8, 0x89, 0x65, 0xcf, 0x17, 0xf9, 0xaf, 0x6e, 0x16, 0x88, 0x6c,
405 0x61, 0xbf, 0xc7, 0x03, 0x10, 0x6f, 0xba, 0xf3, 0xcb, 0x4c, 0xfa, 0x52, 0x38, 0x2d,
406 0xd1, 0x6a, 0x39, 0x3e, 0x42, 0x75, 0x75, 0x07, 0x69, 0x80, 0x75, 0xb2, 0xc9, 0x84,
407 0xc7, 0x07, 0xf0, 0xa0, 0x81, 0x2d, 0x8c, 0xd5, 0xa6, 0x88, 0x1e, 0xaf, 0x21, 0xce,
408 0xda, 0x98, 0xf4, 0xbd, 0x23, 0xf6, 0xfe, 0x1a, 0x3e, 0x2c, 0x43, 0xed, 0xd9, 0xce,
409 0x7c, 0xa8, 0x4b, 0xed, 0x85, 0x21, 0xe2, 0xe1, 0x40,
410 ];
411 assert_eq!(server_packet[..], expected_server_packet[..]);
412 }
413}