1use libc::c_int;
28use libc::c_void;
29
30use crate::Error;
31use crate::Result;
32
33use crate::packet;
34
35pub const MAX_NONCE_LEN: usize = 12;
37
38pub const HP_MASK_LEN: usize = 5;
40
41#[repr(C)]
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum Level {
44 Initial = 0,
45 ZeroRTT = 1,
46 Handshake = 2,
47 OneRTT = 3,
48}
49
50impl Level {
51 pub fn from_epoch(e: packet::Epoch) -> Level {
52 match e {
53 packet::Epoch::Initial => Level::Initial,
54
55 packet::Epoch::Handshake => Level::Handshake,
56
57 packet::Epoch::Application => Level::OneRTT,
58 }
59 }
60}
61
62#[derive(Clone, Copy, Debug, PartialEq, Eq)]
63pub enum Algorithm {
64 #[allow(non_camel_case_types)]
65 AES128_GCM,
66
67 #[allow(non_camel_case_types)]
68 AES256_GCM,
69
70 #[allow(non_camel_case_types)]
71 ChaCha20_Poly1305,
72}
73
74impl Algorithm {
77 fn get_evp_digest(self) -> *const EVP_MD {
78 match self {
79 Algorithm::AES128_GCM => unsafe { EVP_sha256() },
80 Algorithm::AES256_GCM => unsafe { EVP_sha384() },
81 Algorithm::ChaCha20_Poly1305 => unsafe { EVP_sha256() },
82 }
83 }
84
85 pub const fn key_len(self) -> usize {
86 match self {
87 Algorithm::AES128_GCM => 16,
88 Algorithm::AES256_GCM => 32,
89 Algorithm::ChaCha20_Poly1305 => 32,
90 }
91 }
92
93 pub const fn tag_len(self) -> usize {
94 if cfg!(feature = "fuzzing") {
95 return 16;
96 }
97
98 match self {
99 Algorithm::AES128_GCM => 16,
100 Algorithm::AES256_GCM => 16,
101 Algorithm::ChaCha20_Poly1305 => 16,
102 }
103 }
104
105 pub const fn nonce_len(self) -> usize {
106 match self {
107 Algorithm::AES128_GCM => 12,
108 Algorithm::AES256_GCM => 12,
109 Algorithm::ChaCha20_Poly1305 => 12,
110 }
111 }
112}
113
114#[allow(non_camel_case_types)]
115#[repr(transparent)]
116pub struct EVP_AEAD {
117 _unused: c_void,
118}
119
120#[allow(non_camel_case_types)]
121#[repr(transparent)]
122struct EVP_MD {
123 _unused: c_void,
124}
125
126type HeaderProtectionMask = [u8; HP_MASK_LEN];
127
128pub struct Open {
129 alg: Algorithm,
130
131 secret: Vec<u8>,
132
133 header: HeaderProtectionKey,
134
135 packet: PacketKey,
136}
137
138impl Open {
139 pub const DECRYPT: u32 = 0;
143
144 pub fn new(
145 alg: Algorithm, key: Vec<u8>, iv: Vec<u8>, hp_key: Vec<u8>,
146 secret: Vec<u8>,
147 ) -> Result<Open> {
148 Ok(Open {
149 alg,
150
151 secret,
152
153 header: HeaderProtectionKey::new(alg, hp_key)?,
154
155 packet: PacketKey::new(alg, key, iv, Self::DECRYPT)?,
156 })
157 }
158
159 pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open> {
160 Ok(Open {
161 alg: aead,
162
163 secret: secret.to_vec(),
164
165 header: HeaderProtectionKey::from_secret(aead, secret)?,
166
167 packet: PacketKey::from_secret(aead, secret, Self::DECRYPT)?,
168 })
169 }
170
171 pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
172 if cfg!(feature = "fuzzing") {
173 return Ok(<[u8; 5]>::default());
174 }
175
176 self.header.new_mask(sample)
177 }
178
179 pub fn alg(&self) -> Algorithm {
180 self.alg
181 }
182
183 pub fn derive_next_packet_key(&self) -> Result<Open> {
184 let next_secret = derive_next_secret(self.alg, &self.secret)?;
185
186 let next_packet_key =
187 PacketKey::from_secret(self.alg, &next_secret, Self::DECRYPT)?;
188
189 Ok(Open {
190 alg: self.alg,
191
192 secret: next_secret,
193
194 header: self.header.clone(),
195
196 packet: next_packet_key,
197 })
198 }
199
200 pub fn open_with_u64_counter(
201 &self, counter: u64, ad: &[u8], buf: &mut [u8],
202 ) -> Result<usize> {
203 if cfg!(feature = "fuzzing") {
204 let tag_len = self.alg.tag_len();
205 let out_len = match buf.len().checked_sub(tag_len) {
206 Some(n) => n,
207 None => return Err(Error::CryptoFail),
208 };
209 if ad.len() > tag_len && buf[out_len..] == ad[..tag_len] {
210 return Err(Error::CryptoFail);
211 }
212 return Ok(out_len);
213 }
214
215 self.packet.open_with_u64_counter(counter, ad, buf)
216 }
217}
218
219pub struct Seal {
220 alg: Algorithm,
221
222 secret: Vec<u8>,
223
224 header: HeaderProtectionKey,
225
226 packet: PacketKey,
227}
228
229impl Seal {
230 pub const ENCRYPT: u32 = 1;
234
235 pub fn new(
236 alg: Algorithm, key: Vec<u8>, iv: Vec<u8>, hp_key: Vec<u8>,
237 secret: Vec<u8>,
238 ) -> Result<Seal> {
239 Ok(Seal {
240 alg,
241
242 secret,
243
244 header: HeaderProtectionKey::new(alg, hp_key)?,
245
246 packet: PacketKey::new(alg, key, iv, Self::ENCRYPT)?,
247 })
248 }
249
250 pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal> {
251 Ok(Seal {
252 alg: aead,
253
254 secret: secret.to_vec(),
255
256 header: HeaderProtectionKey::from_secret(aead, secret)?,
257
258 packet: PacketKey::from_secret(aead, secret, Self::ENCRYPT)?,
259 })
260 }
261
262 pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
263 if cfg!(feature = "fuzzing") {
264 return Ok(<[u8; 5]>::default());
265 }
266
267 self.header.new_mask(sample)
268 }
269
270 pub fn alg(&self) -> Algorithm {
271 self.alg
272 }
273
274 pub fn derive_next_packet_key(&self) -> Result<Seal> {
275 let next_secret = derive_next_secret(self.alg, &self.secret)?;
276
277 let next_packet_key =
278 PacketKey::from_secret(self.alg, &next_secret, Self::ENCRYPT)?;
279
280 Ok(Seal {
281 alg: self.alg,
282
283 secret: next_secret,
284
285 header: self.header.clone(),
286
287 packet: next_packet_key,
288 })
289 }
290
291 pub fn seal_with_u64_counter(
292 &mut self, counter: u64, ad: &[u8], buf: &mut [u8], in_len: usize,
293 extra_in: Option<&[u8]>,
294 ) -> Result<usize> {
295 if cfg!(feature = "fuzzing") {
296 let tag_len = self.alg.tag_len();
297
298 if let Some(extra) = extra_in {
299 if in_len + tag_len + extra.len() > buf.len() {
300 return Err(Error::CryptoFail);
301 }
302 buf[in_len..in_len + extra.len()].copy_from_slice(extra);
303 return Ok(in_len + extra.len());
304 }
305 if in_len + tag_len > buf.len() {
306 return Err(Error::CryptoFail);
307 }
308
309 return Ok(in_len + tag_len);
310 }
311
312 self.packet
313 .seal_with_u64_counter(counter, ad, buf, in_len, extra_in)
314 }
315}
316
317impl HeaderProtectionKey {
318 pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
319 let key_len = aead.key_len();
320
321 let mut hp_key = vec![0; key_len];
322
323 derive_hdr_key(aead, secret, &mut hp_key)?;
324
325 Self::new(aead, hp_key)
326 }
327}
328
329pub fn derive_initial_key_material(
330 cid: &[u8], version: u32, is_server: bool, did_reset: bool,
331) -> Result<(Open, Seal)> {
332 let mut initial_secret = [0; 32];
333 let mut client_secret = vec![0; 32];
334 let mut server_secret = vec![0; 32];
335
336 let aead = Algorithm::AES128_GCM;
337
338 let key_len = aead.key_len();
339 let nonce_len = aead.nonce_len();
340
341 derive_initial_secret(cid, version, &mut initial_secret)?;
342
343 derive_client_initial_secret(aead, &initial_secret, &mut client_secret)?;
344
345 derive_server_initial_secret(aead, &initial_secret, &mut server_secret)?;
346
347 if did_reset {
352 let (open, seal) = if is_server {
353 (
354 Open::from_secret(aead, &client_secret)?,
355 Seal::from_secret(aead, &server_secret)?,
356 )
357 } else {
358 (
359 Open::from_secret(aead, &server_secret)?,
360 Seal::from_secret(aead, &client_secret)?,
361 )
362 };
363
364 return Ok((open, seal));
365 }
366
367 let mut client_key = vec![0; key_len];
369 let mut client_iv = vec![0; nonce_len];
370 let mut client_hp_key = vec![0; key_len];
371
372 derive_pkt_key(aead, &client_secret, &mut client_key)?;
373 derive_pkt_iv(aead, &client_secret, &mut client_iv)?;
374 derive_hdr_key(aead, &client_secret, &mut client_hp_key)?;
375
376 let mut server_key = vec![0; key_len];
378 let mut server_iv = vec![0; nonce_len];
379 let mut server_hp_key = vec![0; key_len];
380
381 derive_pkt_key(aead, &server_secret, &mut server_key)?;
382 derive_pkt_iv(aead, &server_secret, &mut server_iv)?;
383 derive_hdr_key(aead, &server_secret, &mut server_hp_key)?;
384
385 let (open, seal) = if is_server {
386 (
387 Open::new(aead, client_key, client_iv, client_hp_key, client_secret)?,
388 Seal::new(aead, server_key, server_iv, server_hp_key, server_secret)?,
389 )
390 } else {
391 (
392 Open::new(aead, server_key, server_iv, server_hp_key, server_secret)?,
393 Seal::new(aead, client_key, client_iv, client_hp_key, client_secret)?,
394 )
395 };
396
397 Ok((open, seal))
398}
399
400fn derive_initial_secret(
401 secret: &[u8], version: u32, out_prk: &mut [u8],
402) -> Result<()> {
403 const INITIAL_SALT_V1: [u8; 20] = [
404 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6,
405 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
406 ];
407
408 let salt = match version {
409 crate::PROTOCOL_VERSION_V1 => &INITIAL_SALT_V1,
410
411 _ => &INITIAL_SALT_V1,
412 };
413
414 hkdf_extract(Algorithm::AES128_GCM, out_prk, secret, salt)
415}
416
417fn derive_client_initial_secret(
418 aead: Algorithm, prk: &[u8], out: &mut [u8],
419) -> Result<()> {
420 const LABEL: &[u8] = b"client in";
421 hkdf_expand_label(aead, prk, LABEL, out)
422}
423
424fn derive_server_initial_secret(
425 aead: Algorithm, prk: &[u8], out: &mut [u8],
426) -> Result<()> {
427 const LABEL: &[u8] = b"server in";
428 hkdf_expand_label(aead, prk, LABEL, out)
429}
430
431fn derive_next_secret(aead: Algorithm, secret: &[u8]) -> Result<Vec<u8>> {
432 const LABEL: &[u8] = b"quic ku";
433
434 let mut next_secret = vec![0u8; secret.len()];
435
436 hkdf_expand_label(aead, secret, LABEL, &mut next_secret)?;
437
438 Ok(next_secret)
439}
440
441pub fn derive_hdr_key(
442 aead: Algorithm, secret: &[u8], out: &mut [u8],
443) -> Result<()> {
444 const LABEL: &[u8] = b"quic hp";
445
446 let key_len = aead.key_len();
447
448 if key_len > out.len() {
449 return Err(Error::CryptoFail);
450 }
451
452 hkdf_expand_label(aead, secret, LABEL, &mut out[..key_len])
453}
454
455pub fn derive_pkt_key(aead: Algorithm, prk: &[u8], out: &mut [u8]) -> Result<()> {
456 const LABEL: &[u8] = b"quic key";
457
458 let key_len: usize = aead.key_len();
459
460 if key_len > out.len() {
461 return Err(Error::CryptoFail);
462 }
463
464 hkdf_expand_label(aead, prk, LABEL, &mut out[..key_len])
465}
466
467pub fn derive_pkt_iv(aead: Algorithm, prk: &[u8], out: &mut [u8]) -> Result<()> {
468 const LABEL: &[u8] = b"quic iv";
469
470 let nonce_len = aead.nonce_len();
471
472 if nonce_len > out.len() {
473 return Err(Error::CryptoFail);
474 }
475
476 hkdf_expand_label(aead, prk, LABEL, &mut out[..nonce_len])
477}
478
479fn hkdf_expand_label(
480 alg: Algorithm, prk: &[u8], label: &[u8], out: &mut [u8],
481) -> Result<()> {
482 const LABEL_PREFIX: &[u8] = b"tls13 ";
483
484 let out_len = (out.len() as u16).to_be_bytes();
485 let label_len = (LABEL_PREFIX.len() + label.len()) as u8;
486
487 let info = [&out_len, &[label_len][..], LABEL_PREFIX, label, &[0][..]];
488 let info = info.concat();
489
490 hkdf_expand(alg, out, prk, &info)?;
491
492 Ok(())
493}
494
495fn make_nonce(iv: &[u8], counter: u64) -> [u8; MAX_NONCE_LEN] {
496 let mut nonce = [0; MAX_NONCE_LEN];
497 nonce.copy_from_slice(iv);
498
499 for (a, b) in nonce[4..].iter_mut().zip(counter.to_be_bytes().iter()) {
502 *a ^= b;
503 }
504
505 nonce
506}
507
508pub fn verify_slices_are_equal(a: &[u8], b: &[u8]) -> Result<()> {
509 if a.len() != b.len() {
510 return Err(Error::CryptoFail);
511 }
512
513 let rc = unsafe { CRYPTO_memcmp(a.as_ptr(), b.as_ptr(), a.len()) };
514
515 if rc == 0 {
516 return Ok(());
517 }
518
519 Err(Error::CryptoFail)
520}
521
522extern "C" {
523 fn EVP_sha256() -> *const EVP_MD;
524
525 fn EVP_sha384() -> *const EVP_MD;
526
527 fn CRYPTO_memcmp(a: *const u8, b: *const u8, len: usize) -> c_int;
529}
530
531#[cfg(test)]
532mod tests {
533 use super::*;
534
535 #[test]
536 fn derive_initial_secrets_v1() {
537 let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
538
539 let mut initial_secret = [0; 32];
540
541 let mut secret = [0; 32];
542 let mut pkt_key = [0; 16];
543 let mut pkt_iv = [0; 12];
544 let mut hdr_key = [0; 16];
545
546 let aead = Algorithm::AES128_GCM;
547
548 assert!(derive_initial_secret(
549 &dcid,
550 crate::PROTOCOL_VERSION_V1,
551 &mut initial_secret,
552 )
553 .is_ok());
554
555 assert!(
557 derive_client_initial_secret(aead, &initial_secret, &mut secret)
558 .is_ok()
559 );
560 let expected_client_initial_secret = [
561 0xc0, 0x0c, 0xf1, 0x51, 0xca, 0x5b, 0xe0, 0x75, 0xed, 0x0e, 0xbf,
562 0xb5, 0xc8, 0x03, 0x23, 0xc4, 0x2d, 0x6b, 0x7d, 0xb6, 0x78, 0x81,
563 0x28, 0x9a, 0xf4, 0x00, 0x8f, 0x1f, 0x6c, 0x35, 0x7a, 0xea,
564 ];
565 assert_eq!(&secret, &expected_client_initial_secret);
566
567 assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
568 let expected_client_pkt_key = [
569 0x1f, 0x36, 0x96, 0x13, 0xdd, 0x76, 0xd5, 0x46, 0x77, 0x30, 0xef,
570 0xcb, 0xe3, 0xb1, 0xa2, 0x2d,
571 ];
572 assert_eq!(&pkt_key, &expected_client_pkt_key);
573
574 assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
575 let expected_client_pkt_iv = [
576 0xfa, 0x04, 0x4b, 0x2f, 0x42, 0xa3, 0xfd, 0x3b, 0x46, 0xfb, 0x25,
577 0x5c,
578 ];
579 assert_eq!(&pkt_iv, &expected_client_pkt_iv);
580
581 assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
582 let expected_client_hdr_key = [
583 0x9f, 0x50, 0x44, 0x9e, 0x04, 0xa0, 0xe8, 0x10, 0x28, 0x3a, 0x1e,
584 0x99, 0x33, 0xad, 0xed, 0xd2,
585 ];
586 assert_eq!(&hdr_key, &expected_client_hdr_key);
587
588 assert!(
590 derive_server_initial_secret(aead, &initial_secret, &mut secret)
591 .is_ok()
592 );
593
594 let expected_server_initial_secret = [
595 0x3c, 0x19, 0x98, 0x28, 0xfd, 0x13, 0x9e, 0xfd, 0x21, 0x6c, 0x15,
596 0x5a, 0xd8, 0x44, 0xcc, 0x81, 0xfb, 0x82, 0xfa, 0x8d, 0x74, 0x46,
597 0xfa, 0x7d, 0x78, 0xbe, 0x80, 0x3a, 0xcd, 0xda, 0x95, 0x1b,
598 ];
599 assert_eq!(&secret, &expected_server_initial_secret);
600
601 assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
602 let expected_server_pkt_key = [
603 0xcf, 0x3a, 0x53, 0x31, 0x65, 0x3c, 0x36, 0x4c, 0x88, 0xf0, 0xf3,
604 0x79, 0xb6, 0x06, 0x7e, 0x37,
605 ];
606 assert_eq!(&pkt_key, &expected_server_pkt_key);
607
608 assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
609 let expected_server_pkt_iv = [
610 0x0a, 0xc1, 0x49, 0x3c, 0xa1, 0x90, 0x58, 0x53, 0xb0, 0xbb, 0xa0,
611 0x3e,
612 ];
613 assert_eq!(&pkt_iv, &expected_server_pkt_iv);
614
615 assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
616 let expected_server_hdr_key = [
617 0xc2, 0x06, 0xb8, 0xd9, 0xb9, 0xf0, 0xf3, 0x76, 0x44, 0x43, 0x0b,
618 0x49, 0x0e, 0xea, 0xa3, 0x14,
619 ];
620 assert_eq!(&hdr_key, &expected_server_hdr_key);
621 }
622
623 #[test]
624 fn derive_chacha20_secrets() {
625 let secret = [
626 0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42,
627 0x27, 0x48, 0xad, 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0,
628 0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3, 0x0f, 0x21, 0x63, 0x2b,
629 ];
630
631 let aead = Algorithm::ChaCha20_Poly1305;
632
633 let mut pkt_key = [0; 32];
634 let mut pkt_iv = [0; 12];
635 let mut hdr_key = [0; 32];
636
637 assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
638 let expected_pkt_key = [
639 0xc6, 0xd9, 0x8f, 0xf3, 0x44, 0x1c, 0x3f, 0xe1, 0xb2, 0x18, 0x20,
640 0x94, 0xf6, 0x9c, 0xaa, 0x2e, 0xd4, 0xb7, 0x16, 0xb6, 0x54, 0x88,
641 0x96, 0x0a, 0x7a, 0x98, 0x49, 0x79, 0xfb, 0x23, 0xe1, 0xc8,
642 ];
643 assert_eq!(&pkt_key, &expected_pkt_key);
644
645 assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
646 let expected_pkt_iv = [
647 0xe0, 0x45, 0x9b, 0x34, 0x74, 0xbd, 0xd0, 0xe4, 0x4a, 0x41, 0xc1,
648 0x44,
649 ];
650 assert_eq!(&pkt_iv, &expected_pkt_iv);
651
652 assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
653 let expected_hdr_key = [
654 0x25, 0xa2, 0x82, 0xb9, 0xe8, 0x2f, 0x06, 0xf2, 0x1f, 0x48, 0x89,
655 0x17, 0xa4, 0xfc, 0x8f, 0x1b, 0x73, 0x57, 0x36, 0x85, 0x60, 0x85,
656 0x97, 0xd0, 0xef, 0xcb, 0x07, 0x6b, 0x0a, 0xb7, 0xa7, 0xa4,
657 ];
658 assert_eq!(&hdr_key, &expected_hdr_key);
659
660 let next_secret = derive_next_secret(aead, &secret).unwrap();
661 let expected_secret = [
662 0x12, 0x23, 0x50, 0x47, 0x55, 0x03, 0x6d, 0x55, 0x63, 0x42, 0xee,
663 0x93, 0x61, 0xd2, 0x53, 0x42, 0x1a, 0x82, 0x6c, 0x9e, 0xcd, 0xf3,
664 0xc7, 0x14, 0x86, 0x84, 0xb3, 0x6b, 0x71, 0x48, 0x81, 0xf9,
665 ];
666 assert_eq!(&next_secret, &expected_secret);
667 }
668}
669
670mod boringssl;
671pub(crate) use boringssl::*;