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 0;
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 return Ok(buf.len());
205 }
206
207 self.packet.open_with_u64_counter(counter, ad, buf)
208 }
209}
210
211pub struct Seal {
212 alg: Algorithm,
213
214 secret: Vec<u8>,
215
216 header: HeaderProtectionKey,
217
218 packet: PacketKey,
219}
220
221impl Seal {
222 pub const ENCRYPT: u32 = 1;
226
227 pub fn new(
228 alg: Algorithm, key: Vec<u8>, iv: Vec<u8>, hp_key: Vec<u8>,
229 secret: Vec<u8>,
230 ) -> Result<Seal> {
231 Ok(Seal {
232 alg,
233
234 secret,
235
236 header: HeaderProtectionKey::new(alg, hp_key)?,
237
238 packet: PacketKey::new(alg, key, iv, Self::ENCRYPT)?,
239 })
240 }
241
242 pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal> {
243 Ok(Seal {
244 alg: aead,
245
246 secret: secret.to_vec(),
247
248 header: HeaderProtectionKey::from_secret(aead, secret)?,
249
250 packet: PacketKey::from_secret(aead, secret, Self::ENCRYPT)?,
251 })
252 }
253
254 pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
255 if cfg!(feature = "fuzzing") {
256 return Ok(<[u8; 5]>::default());
257 }
258
259 self.header.new_mask(sample)
260 }
261
262 pub fn alg(&self) -> Algorithm {
263 self.alg
264 }
265
266 pub fn derive_next_packet_key(&self) -> Result<Seal> {
267 let next_secret = derive_next_secret(self.alg, &self.secret)?;
268
269 let next_packet_key =
270 PacketKey::from_secret(self.alg, &next_secret, Self::ENCRYPT)?;
271
272 Ok(Seal {
273 alg: self.alg,
274
275 secret: next_secret,
276
277 header: self.header.clone(),
278
279 packet: next_packet_key,
280 })
281 }
282
283 pub fn seal_with_u64_counter(
284 &self, counter: u64, ad: &[u8], buf: &mut [u8], in_len: usize,
285 extra_in: Option<&[u8]>,
286 ) -> Result<usize> {
287 if cfg!(feature = "fuzzing") {
288 if let Some(extra) = extra_in {
289 buf[in_len..in_len + extra.len()].copy_from_slice(extra);
290 return Ok(in_len + extra.len());
291 }
292
293 return Ok(in_len);
294 }
295
296 self.packet
297 .seal_with_u64_counter(counter, ad, buf, in_len, extra_in)
298 }
299}
300
301impl HeaderProtectionKey {
302 pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
303 let key_len = aead.key_len();
304
305 let mut hp_key = vec![0; key_len];
306
307 derive_hdr_key(aead, secret, &mut hp_key)?;
308
309 Self::new(aead, hp_key)
310 }
311}
312
313pub fn derive_initial_key_material(
314 cid: &[u8], version: u32, is_server: bool, did_reset: bool,
315) -> Result<(Open, Seal)> {
316 let mut initial_secret = [0; 32];
317 let mut client_secret = vec![0; 32];
318 let mut server_secret = vec![0; 32];
319
320 let aead = Algorithm::AES128_GCM;
321
322 let key_len = aead.key_len();
323 let nonce_len = aead.nonce_len();
324
325 derive_initial_secret(cid, version, &mut initial_secret)?;
326
327 derive_client_initial_secret(aead, &initial_secret, &mut client_secret)?;
328
329 derive_server_initial_secret(aead, &initial_secret, &mut server_secret)?;
330
331 if did_reset {
336 let (open, seal) = if is_server {
337 (
338 Open::from_secret(aead, &client_secret)?,
339 Seal::from_secret(aead, &server_secret)?,
340 )
341 } else {
342 (
343 Open::from_secret(aead, &server_secret)?,
344 Seal::from_secret(aead, &client_secret)?,
345 )
346 };
347
348 return Ok((open, seal));
349 }
350
351 let mut client_key = vec![0; key_len];
353 let mut client_iv = vec![0; nonce_len];
354 let mut client_hp_key = vec![0; key_len];
355
356 derive_pkt_key(aead, &client_secret, &mut client_key)?;
357 derive_pkt_iv(aead, &client_secret, &mut client_iv)?;
358 derive_hdr_key(aead, &client_secret, &mut client_hp_key)?;
359
360 let mut server_key = vec![0; key_len];
362 let mut server_iv = vec![0; nonce_len];
363 let mut server_hp_key = vec![0; key_len];
364
365 derive_pkt_key(aead, &server_secret, &mut server_key)?;
366 derive_pkt_iv(aead, &server_secret, &mut server_iv)?;
367 derive_hdr_key(aead, &server_secret, &mut server_hp_key)?;
368
369 let (open, seal) = if is_server {
370 (
371 Open::new(aead, client_key, client_iv, client_hp_key, client_secret)?,
372 Seal::new(aead, server_key, server_iv, server_hp_key, server_secret)?,
373 )
374 } else {
375 (
376 Open::new(aead, server_key, server_iv, server_hp_key, server_secret)?,
377 Seal::new(aead, client_key, client_iv, client_hp_key, client_secret)?,
378 )
379 };
380
381 Ok((open, seal))
382}
383
384fn derive_initial_secret(
385 secret: &[u8], version: u32, out_prk: &mut [u8],
386) -> Result<()> {
387 const INITIAL_SALT_V1: [u8; 20] = [
388 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6,
389 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
390 ];
391
392 let salt = match version {
393 crate::PROTOCOL_VERSION_V1 => &INITIAL_SALT_V1,
394
395 _ => &INITIAL_SALT_V1,
396 };
397
398 hkdf_extract(Algorithm::AES128_GCM, out_prk, secret, salt)
399}
400
401fn derive_client_initial_secret(
402 aead: Algorithm, prk: &[u8], out: &mut [u8],
403) -> Result<()> {
404 const LABEL: &[u8] = b"client in";
405 hkdf_expand_label(aead, prk, LABEL, out)
406}
407
408fn derive_server_initial_secret(
409 aead: Algorithm, prk: &[u8], out: &mut [u8],
410) -> Result<()> {
411 const LABEL: &[u8] = b"server in";
412 hkdf_expand_label(aead, prk, LABEL, out)
413}
414
415fn derive_next_secret(aead: Algorithm, secret: &[u8]) -> Result<Vec<u8>> {
416 const LABEL: &[u8] = b"quic ku";
417
418 let mut next_secret = vec![0u8; 32];
419
420 hkdf_expand_label(aead, secret, LABEL, &mut next_secret)?;
421
422 Ok(next_secret)
423}
424
425pub fn derive_hdr_key(
426 aead: Algorithm, secret: &[u8], out: &mut [u8],
427) -> Result<()> {
428 const LABEL: &[u8] = b"quic hp";
429
430 let key_len = aead.key_len();
431
432 if key_len > out.len() {
433 return Err(Error::CryptoFail);
434 }
435
436 hkdf_expand_label(aead, secret, LABEL, &mut out[..key_len])
437}
438
439pub fn derive_pkt_key(aead: Algorithm, prk: &[u8], out: &mut [u8]) -> Result<()> {
440 const LABEL: &[u8] = b"quic key";
441
442 let key_len: usize = aead.key_len();
443
444 if key_len > out.len() {
445 return Err(Error::CryptoFail);
446 }
447
448 hkdf_expand_label(aead, prk, LABEL, &mut out[..key_len])
449}
450
451pub fn derive_pkt_iv(aead: Algorithm, prk: &[u8], out: &mut [u8]) -> Result<()> {
452 const LABEL: &[u8] = b"quic iv";
453
454 let nonce_len = aead.nonce_len();
455
456 if nonce_len > out.len() {
457 return Err(Error::CryptoFail);
458 }
459
460 hkdf_expand_label(aead, prk, LABEL, &mut out[..nonce_len])
461}
462
463fn hkdf_expand_label(
464 alg: Algorithm, prk: &[u8], label: &[u8], out: &mut [u8],
465) -> Result<()> {
466 const LABEL_PREFIX: &[u8] = b"tls13 ";
467
468 let out_len = (out.len() as u16).to_be_bytes();
469 let label_len = (LABEL_PREFIX.len() + label.len()) as u8;
470
471 let info = [&out_len, &[label_len][..], LABEL_PREFIX, label, &[0][..]];
472 let info = info.concat();
473
474 hkdf_expand(alg, out, prk, &info)?;
475
476 Ok(())
477}
478
479fn make_nonce(iv: &[u8], counter: u64) -> [u8; MAX_NONCE_LEN] {
480 let mut nonce = [0; MAX_NONCE_LEN];
481 nonce.copy_from_slice(iv);
482
483 for (a, b) in nonce[4..].iter_mut().zip(counter.to_be_bytes().iter()) {
486 *a ^= b;
487 }
488
489 nonce
490}
491
492pub fn verify_slices_are_equal(a: &[u8], b: &[u8]) -> Result<()> {
493 if a.len() != b.len() {
494 return Err(Error::CryptoFail);
495 }
496
497 let rc = unsafe { CRYPTO_memcmp(a.as_ptr(), b.as_ptr(), a.len()) };
498
499 if rc == 0 {
500 return Ok(());
501 }
502
503 Err(Error::CryptoFail)
504}
505
506extern "C" {
507 fn EVP_sha256() -> *const EVP_MD;
508
509 fn EVP_sha384() -> *const EVP_MD;
510
511 fn CRYPTO_memcmp(a: *const u8, b: *const u8, len: usize) -> c_int;
513}
514
515#[cfg(test)]
516mod tests {
517 use super::*;
518
519 #[test]
520 fn derive_initial_secrets_v1() {
521 let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
522
523 let mut initial_secret = [0; 32];
524
525 let mut secret = [0; 32];
526 let mut pkt_key = [0; 16];
527 let mut pkt_iv = [0; 12];
528 let mut hdr_key = [0; 16];
529
530 let aead = Algorithm::AES128_GCM;
531
532 assert!(derive_initial_secret(
533 &dcid,
534 crate::PROTOCOL_VERSION_V1,
535 &mut initial_secret,
536 )
537 .is_ok());
538
539 assert!(
541 derive_client_initial_secret(aead, &initial_secret, &mut secret)
542 .is_ok()
543 );
544 let expected_client_initial_secret = [
545 0xc0, 0x0c, 0xf1, 0x51, 0xca, 0x5b, 0xe0, 0x75, 0xed, 0x0e, 0xbf,
546 0xb5, 0xc8, 0x03, 0x23, 0xc4, 0x2d, 0x6b, 0x7d, 0xb6, 0x78, 0x81,
547 0x28, 0x9a, 0xf4, 0x00, 0x8f, 0x1f, 0x6c, 0x35, 0x7a, 0xea,
548 ];
549 assert_eq!(&secret, &expected_client_initial_secret);
550
551 assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
552 let expected_client_pkt_key = [
553 0x1f, 0x36, 0x96, 0x13, 0xdd, 0x76, 0xd5, 0x46, 0x77, 0x30, 0xef,
554 0xcb, 0xe3, 0xb1, 0xa2, 0x2d,
555 ];
556 assert_eq!(&pkt_key, &expected_client_pkt_key);
557
558 assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
559 let expected_client_pkt_iv = [
560 0xfa, 0x04, 0x4b, 0x2f, 0x42, 0xa3, 0xfd, 0x3b, 0x46, 0xfb, 0x25,
561 0x5c,
562 ];
563 assert_eq!(&pkt_iv, &expected_client_pkt_iv);
564
565 assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
566 let expected_client_hdr_key = [
567 0x9f, 0x50, 0x44, 0x9e, 0x04, 0xa0, 0xe8, 0x10, 0x28, 0x3a, 0x1e,
568 0x99, 0x33, 0xad, 0xed, 0xd2,
569 ];
570 assert_eq!(&hdr_key, &expected_client_hdr_key);
571
572 assert!(
574 derive_server_initial_secret(aead, &initial_secret, &mut secret)
575 .is_ok()
576 );
577
578 let expected_server_initial_secret = [
579 0x3c, 0x19, 0x98, 0x28, 0xfd, 0x13, 0x9e, 0xfd, 0x21, 0x6c, 0x15,
580 0x5a, 0xd8, 0x44, 0xcc, 0x81, 0xfb, 0x82, 0xfa, 0x8d, 0x74, 0x46,
581 0xfa, 0x7d, 0x78, 0xbe, 0x80, 0x3a, 0xcd, 0xda, 0x95, 0x1b,
582 ];
583 assert_eq!(&secret, &expected_server_initial_secret);
584
585 assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
586 let expected_server_pkt_key = [
587 0xcf, 0x3a, 0x53, 0x31, 0x65, 0x3c, 0x36, 0x4c, 0x88, 0xf0, 0xf3,
588 0x79, 0xb6, 0x06, 0x7e, 0x37,
589 ];
590 assert_eq!(&pkt_key, &expected_server_pkt_key);
591
592 assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
593 let expected_server_pkt_iv = [
594 0x0a, 0xc1, 0x49, 0x3c, 0xa1, 0x90, 0x58, 0x53, 0xb0, 0xbb, 0xa0,
595 0x3e,
596 ];
597 assert_eq!(&pkt_iv, &expected_server_pkt_iv);
598
599 assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
600 let expected_server_hdr_key = [
601 0xc2, 0x06, 0xb8, 0xd9, 0xb9, 0xf0, 0xf3, 0x76, 0x44, 0x43, 0x0b,
602 0x49, 0x0e, 0xea, 0xa3, 0x14,
603 ];
604 assert_eq!(&hdr_key, &expected_server_hdr_key);
605 }
606
607 #[test]
608 fn derive_chacha20_secrets() {
609 let secret = [
610 0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42,
611 0x27, 0x48, 0xad, 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0,
612 0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3, 0x0f, 0x21, 0x63, 0x2b,
613 ];
614
615 let aead = Algorithm::ChaCha20_Poly1305;
616
617 let mut pkt_key = [0; 32];
618 let mut pkt_iv = [0; 12];
619 let mut hdr_key = [0; 32];
620
621 assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
622 let expected_pkt_key = [
623 0xc6, 0xd9, 0x8f, 0xf3, 0x44, 0x1c, 0x3f, 0xe1, 0xb2, 0x18, 0x20,
624 0x94, 0xf6, 0x9c, 0xaa, 0x2e, 0xd4, 0xb7, 0x16, 0xb6, 0x54, 0x88,
625 0x96, 0x0a, 0x7a, 0x98, 0x49, 0x79, 0xfb, 0x23, 0xe1, 0xc8,
626 ];
627 assert_eq!(&pkt_key, &expected_pkt_key);
628
629 assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
630 let expected_pkt_iv = [
631 0xe0, 0x45, 0x9b, 0x34, 0x74, 0xbd, 0xd0, 0xe4, 0x4a, 0x41, 0xc1,
632 0x44,
633 ];
634 assert_eq!(&pkt_iv, &expected_pkt_iv);
635
636 assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
637 let expected_hdr_key = [
638 0x25, 0xa2, 0x82, 0xb9, 0xe8, 0x2f, 0x06, 0xf2, 0x1f, 0x48, 0x89,
639 0x17, 0xa4, 0xfc, 0x8f, 0x1b, 0x73, 0x57, 0x36, 0x85, 0x60, 0x85,
640 0x97, 0xd0, 0xef, 0xcb, 0x07, 0x6b, 0x0a, 0xb7, 0xa7, 0xa4,
641 ];
642 assert_eq!(&hdr_key, &expected_hdr_key);
643 }
644}
645
646#[cfg(not(feature = "openssl"))]
647mod boringssl;
648#[cfg(not(feature = "openssl"))]
649pub(crate) use boringssl::*;
650
651#[cfg(feature = "openssl")]
652mod openssl_quictls;
653#[cfg(feature = "openssl")]
654pub(crate) use openssl_quictls::*;