Coverage Report

Created: 2025-12-08 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quiche/quiche/src/crypto/mod.rs
Line
Count
Source
1
// Copyright (C) 2018-2019, Cloudflare, Inc.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
//     * Redistributions of source code must retain the above copyright notice,
9
//       this list of conditions and the following disclaimer.
10
//
11
//     * Redistributions in binary form must reproduce the above copyright
12
//       notice, this list of conditions and the following disclaimer in the
13
//       documentation and/or other materials provided with the distribution.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27
use libc::c_int;
28
use libc::c_void;
29
30
use crate::Error;
31
use crate::Result;
32
33
use crate::packet;
34
35
// All the AEAD algorithms we support use 96-bit nonces.
36
pub const MAX_NONCE_LEN: usize = 12;
37
38
// Length of header protection mask.
39
pub const HP_MASK_LEN: usize = 5;
40
41
#[repr(C)]
42
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43
pub enum Level {
44
    Initial   = 0,
45
    ZeroRTT   = 1,
46
    Handshake = 2,
47
    OneRTT    = 3,
48
}
49
50
impl Level {
51
869k
    pub fn from_epoch(e: packet::Epoch) -> Level {
52
869k
        match e {
53
600k
            packet::Epoch::Initial => Level::Initial,
54
55
35.9k
            packet::Epoch::Handshake => Level::Handshake,
56
57
232k
            packet::Epoch::Application => Level::OneRTT,
58
        }
59
869k
    }
60
}
61
62
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
63
pub 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
74
// Note: some vendor-specific methods are implemented by each vendor's submodule
75
// (openssl-quictls / boringssl).
76
impl Algorithm {
77
917k
    fn get_evp_digest(self) -> *const EVP_MD {
78
917k
        match self {
79
865k
            Algorithm::AES128_GCM => unsafe { EVP_sha256() },
80
27.7k
            Algorithm::AES256_GCM => unsafe { EVP_sha384() },
81
24.4k
            Algorithm::ChaCha20_Poly1305 => unsafe { EVP_sha256() },
82
        }
83
917k
    }
84
85
1.21M
    pub const fn key_len(self) -> usize {
86
1.21M
        match self {
87
1.13M
            Algorithm::AES128_GCM => 16,
88
43.2k
            Algorithm::AES256_GCM => 32,
89
32.6k
            Algorithm::ChaCha20_Poly1305 => 32,
90
        }
91
1.21M
    }
92
93
14.2M
    pub const fn tag_len(self) -> usize {
94
14.2M
        if cfg!(feature = "fuzzing") {
95
14.2M
            return 16;
96
0
        }
97
98
0
        match self {
99
0
            Algorithm::AES128_GCM => 16,
100
0
            Algorithm::AES256_GCM => 16,
101
0
            Algorithm::ChaCha20_Poly1305 => 16,
102
        }
103
14.2M
    }
104
105
492k
    pub const fn nonce_len(self) -> usize {
106
492k
        match self {
107
457k
            Algorithm::AES128_GCM => 12,
108
18.5k
            Algorithm::AES256_GCM => 12,
109
16.3k
            Algorithm::ChaCha20_Poly1305 => 12,
110
        }
111
492k
    }
112
}
113
114
#[allow(non_camel_case_types)]
115
#[repr(transparent)]
116
pub struct EVP_AEAD {
117
    _unused: c_void,
118
}
119
120
#[allow(non_camel_case_types)]
121
#[repr(transparent)]
122
struct EVP_MD {
123
    _unused: c_void,
124
}
125
126
type HeaderProtectionMask = [u8; HP_MASK_LEN];
127
128
pub struct Open {
129
    alg: Algorithm,
130
131
    secret: Vec<u8>,
132
133
    header: HeaderProtectionKey,
134
135
    packet: PacketKey,
136
}
137
138
impl Open {
139
    // Note: some vendor-specific methods are implemented by each vendor's
140
    // submodule (openssl-quictls / boringssl).
141
142
    pub const DECRYPT: u32 = 0;
143
144
39.7k
    pub fn new(
145
39.7k
        alg: Algorithm, key: Vec<u8>, iv: Vec<u8>, hp_key: Vec<u8>,
146
39.7k
        secret: Vec<u8>,
147
39.7k
    ) -> Result<Open> {
148
        Ok(Open {
149
39.7k
            alg,
150
151
39.7k
            secret,
152
153
39.7k
            header: HeaderProtectionKey::new(alg, hp_key)?,
154
155
39.7k
            packet: PacketKey::new(alg, key, iv, Self::DECRYPT)?,
156
        })
157
39.7k
    }
158
159
48.7k
    pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open> {
160
        Ok(Open {
161
48.7k
            alg: aead,
162
163
48.7k
            secret: secret.to_vec(),
164
165
48.7k
            header: HeaderProtectionKey::from_secret(aead, secret)?,
166
167
48.7k
            packet: PacketKey::from_secret(aead, secret, Self::DECRYPT)?,
168
        })
169
48.7k
    }
170
171
2.44M
    pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
172
2.44M
        if cfg!(feature = "fuzzing") {
173
2.44M
            return Ok(<[u8; 5]>::default());
174
0
        }
175
176
0
        self.header.new_mask(sample)
177
2.44M
    }
178
179
2.52M
    pub fn alg(&self) -> Algorithm {
180
2.52M
        self.alg
181
2.52M
    }
182
183
43.4k
    pub fn derive_next_packet_key(&self) -> Result<Open> {
184
43.4k
        let next_secret = derive_next_secret(self.alg, &self.secret)?;
185
186
43.4k
        let next_packet_key =
187
43.4k
            PacketKey::from_secret(self.alg, &next_secret, Self::DECRYPT)?;
188
189
43.4k
        Ok(Open {
190
43.4k
            alg: self.alg,
191
43.4k
192
43.4k
            secret: next_secret,
193
43.4k
194
43.4k
            header: self.header.clone(),
195
43.4k
196
43.4k
            packet: next_packet_key,
197
43.4k
        })
198
43.4k
    }
199
200
2.42M
    pub fn open_with_u64_counter(
201
2.42M
        &self, counter: u64, ad: &[u8], buf: &mut [u8],
202
2.42M
    ) -> Result<usize> {
203
2.42M
        if cfg!(feature = "fuzzing") {
204
2.42M
            let tag_len = self.alg.tag_len();
205
2.42M
            let out_len = match buf.len().checked_sub(tag_len) {
206
2.42M
                Some(n) => n,
207
923
                None => return Err(Error::CryptoFail),
208
            };
209
2.42M
            if ad.len() > tag_len && buf[out_len..] == ad[..tag_len] {
210
29.3k
                return Err(Error::CryptoFail);
211
2.39M
            }
212
2.39M
            return Ok(out_len);
213
0
        }
214
215
0
        self.packet.open_with_u64_counter(counter, ad, buf)
216
2.42M
    }
217
}
218
219
pub struct Seal {
220
    alg: Algorithm,
221
222
    secret: Vec<u8>,
223
224
    header: HeaderProtectionKey,
225
226
    packet: PacketKey,
227
}
228
229
impl Seal {
230
    // Note: some vendor-specific methods are implemented by each vendor's
231
    // submodule (openssl-quictls / boringssl).
232
233
    pub const ENCRYPT: u32 = 1;
234
235
39.7k
    pub fn new(
236
39.7k
        alg: Algorithm, key: Vec<u8>, iv: Vec<u8>, hp_key: Vec<u8>,
237
39.7k
        secret: Vec<u8>,
238
39.7k
    ) -> Result<Seal> {
239
        Ok(Seal {
240
39.7k
            alg,
241
242
39.7k
            secret,
243
244
39.7k
            header: HeaderProtectionKey::new(alg, hp_key)?,
245
246
39.7k
            packet: PacketKey::new(alg, key, iv, Self::ENCRYPT)?,
247
        })
248
39.7k
    }
249
250
50.8k
    pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal> {
251
        Ok(Seal {
252
50.8k
            alg: aead,
253
254
50.8k
            secret: secret.to_vec(),
255
256
50.8k
            header: HeaderProtectionKey::from_secret(aead, secret)?,
257
258
50.8k
            packet: PacketKey::from_secret(aead, secret, Self::ENCRYPT)?,
259
        })
260
50.8k
    }
261
262
1.41M
    pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
263
1.41M
        if cfg!(feature = "fuzzing") {
264
1.41M
            return Ok(<[u8; 5]>::default());
265
0
        }
266
267
0
        self.header.new_mask(sample)
268
1.41M
    }
269
270
7.40M
    pub fn alg(&self) -> Algorithm {
271
7.40M
        self.alg
272
7.40M
    }
273
274
43.4k
    pub fn derive_next_packet_key(&self) -> Result<Seal> {
275
43.4k
        let next_secret = derive_next_secret(self.alg, &self.secret)?;
276
277
43.4k
        let next_packet_key =
278
43.4k
            PacketKey::from_secret(self.alg, &next_secret, Self::ENCRYPT)?;
279
280
43.4k
        Ok(Seal {
281
43.4k
            alg: self.alg,
282
43.4k
283
43.4k
            secret: next_secret,
284
43.4k
285
43.4k
            header: self.header.clone(),
286
43.4k
287
43.4k
            packet: next_packet_key,
288
43.4k
        })
289
43.4k
    }
290
291
1.41M
    pub fn seal_with_u64_counter(
292
1.41M
        &self, counter: u64, ad: &[u8], buf: &mut [u8], in_len: usize,
293
1.41M
        extra_in: Option<&[u8]>,
294
1.41M
    ) -> Result<usize> {
295
1.41M
        if cfg!(feature = "fuzzing") {
296
1.41M
            let tag_len = self.alg.tag_len();
297
298
1.41M
            if let Some(extra) = extra_in {
299
0
                if in_len + tag_len + extra.len() > buf.len() {
300
0
                    return Err(Error::CryptoFail);
301
0
                }
302
0
                buf[in_len..in_len + extra.len()].copy_from_slice(extra);
303
0
                return Ok(in_len + extra.len());
304
1.41M
            }
305
1.41M
            if in_len + tag_len > buf.len() {
306
0
                return Err(Error::CryptoFail);
307
1.41M
            }
308
309
1.41M
            return Ok(in_len + tag_len);
310
0
        }
311
312
0
        self.packet
313
0
            .seal_with_u64_counter(counter, ad, buf, in_len, extra_in)
314
1.41M
    }
315
}
316
317
impl HeaderProtectionKey {
318
99.6k
    pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
319
99.6k
        let key_len = aead.key_len();
320
321
99.6k
        let mut hp_key = vec![0; key_len];
322
323
99.6k
        derive_hdr_key(aead, secret, &mut hp_key)?;
324
325
99.6k
        Self::new(aead, hp_key)
326
99.6k
    }
327
}
328
329
39.7k
pub fn derive_initial_key_material(
330
39.7k
    cid: &[u8], version: u32, is_server: bool, did_reset: bool,
331
39.7k
) -> Result<(Open, Seal)> {
332
39.7k
    let mut initial_secret = [0; 32];
333
39.7k
    let mut client_secret = vec![0; 32];
334
39.7k
    let mut server_secret = vec![0; 32];
335
336
39.7k
    let aead = Algorithm::AES128_GCM;
337
338
39.7k
    let key_len = aead.key_len();
339
39.7k
    let nonce_len = aead.nonce_len();
340
341
39.7k
    derive_initial_secret(cid, version, &mut initial_secret)?;
342
343
39.7k
    derive_client_initial_secret(aead, &initial_secret, &mut client_secret)?;
344
345
39.7k
    derive_server_initial_secret(aead, &initial_secret, &mut server_secret)?;
346
347
    // When the initial key material has been reset (e.g. due to retry or
348
    // version negotiation), we need to prime the AEAD context as well, as the
349
    // following packet will not start from 0 again. This is done through the
350
    // `Open/Seal::from_secret()` path, rather than `Open/Seal::new()`.
351
39.7k
    if did_reset {
352
0
        let (open, seal) = if is_server {
353
            (
354
0
                Open::from_secret(aead, &client_secret)?,
355
0
                Seal::from_secret(aead, &server_secret)?,
356
            )
357
        } else {
358
            (
359
0
                Open::from_secret(aead, &server_secret)?,
360
0
                Seal::from_secret(aead, &client_secret)?,
361
            )
362
        };
363
364
0
        return Ok((open, seal));
365
39.7k
    }
366
367
    // Client.
368
39.7k
    let mut client_key = vec![0; key_len];
369
39.7k
    let mut client_iv = vec![0; nonce_len];
370
39.7k
    let mut client_hp_key = vec![0; key_len];
371
372
39.7k
    derive_pkt_key(aead, &client_secret, &mut client_key)?;
373
39.7k
    derive_pkt_iv(aead, &client_secret, &mut client_iv)?;
374
39.7k
    derive_hdr_key(aead, &client_secret, &mut client_hp_key)?;
375
376
    // Server.
377
39.7k
    let mut server_key = vec![0; key_len];
378
39.7k
    let mut server_iv = vec![0; nonce_len];
379
39.7k
    let mut server_hp_key = vec![0; key_len];
380
381
39.7k
    derive_pkt_key(aead, &server_secret, &mut server_key)?;
382
39.7k
    derive_pkt_iv(aead, &server_secret, &mut server_iv)?;
383
39.7k
    derive_hdr_key(aead, &server_secret, &mut server_hp_key)?;
384
385
39.7k
    let (open, seal) = if is_server {
386
        (
387
24.6k
            Open::new(aead, client_key, client_iv, client_hp_key, client_secret)?,
388
24.6k
            Seal::new(aead, server_key, server_iv, server_hp_key, server_secret)?,
389
        )
390
    } else {
391
        (
392
15.0k
            Open::new(aead, server_key, server_iv, server_hp_key, server_secret)?,
393
15.0k
            Seal::new(aead, client_key, client_iv, client_hp_key, client_secret)?,
394
        )
395
    };
396
397
39.7k
    Ok((open, seal))
398
39.7k
}
399
400
39.7k
fn derive_initial_secret(
401
39.7k
    secret: &[u8], version: u32, out_prk: &mut [u8],
402
39.7k
) -> 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
39.7k
    let salt = match version {
409
39.7k
        crate::PROTOCOL_VERSION_V1 => &INITIAL_SALT_V1,
410
411
0
        _ => &INITIAL_SALT_V1,
412
    };
413
414
39.7k
    hkdf_extract(Algorithm::AES128_GCM, out_prk, secret, salt)
415
39.7k
}
416
417
39.7k
fn derive_client_initial_secret(
418
39.7k
    aead: Algorithm, prk: &[u8], out: &mut [u8],
419
39.7k
) -> Result<()> {
420
    const LABEL: &[u8] = b"client in";
421
39.7k
    hkdf_expand_label(aead, prk, LABEL, out)
422
39.7k
}
423
424
39.7k
fn derive_server_initial_secret(
425
39.7k
    aead: Algorithm, prk: &[u8], out: &mut [u8],
426
39.7k
) -> Result<()> {
427
    const LABEL: &[u8] = b"server in";
428
39.7k
    hkdf_expand_label(aead, prk, LABEL, out)
429
39.7k
}
430
431
86.9k
fn derive_next_secret(aead: Algorithm, secret: &[u8]) -> Result<Vec<u8>> {
432
    const LABEL: &[u8] = b"quic ku";
433
434
86.9k
    let mut next_secret = vec![0u8; secret.len()];
435
436
86.9k
    hkdf_expand_label(aead, secret, LABEL, &mut next_secret)?;
437
438
86.9k
    Ok(next_secret)
439
86.9k
}
440
441
179k
pub fn derive_hdr_key(
442
179k
    aead: Algorithm, secret: &[u8], out: &mut [u8],
443
179k
) -> Result<()> {
444
    const LABEL: &[u8] = b"quic hp";
445
446
179k
    let key_len = aead.key_len();
447
448
179k
    if key_len > out.len() {
449
0
        return Err(Error::CryptoFail);
450
179k
    }
451
452
179k
    hkdf_expand_label(aead, secret, LABEL, &mut out[..key_len])
453
179k
}
454
455
266k
pub fn derive_pkt_key(aead: Algorithm, prk: &[u8], out: &mut [u8]) -> Result<()> {
456
    const LABEL: &[u8] = b"quic key";
457
458
266k
    let key_len: usize = aead.key_len();
459
460
266k
    if key_len > out.len() {
461
0
        return Err(Error::CryptoFail);
462
266k
    }
463
464
266k
    hkdf_expand_label(aead, prk, LABEL, &mut out[..key_len])
465
266k
}
466
467
266k
pub fn derive_pkt_iv(aead: Algorithm, prk: &[u8], out: &mut [u8]) -> Result<()> {
468
    const LABEL: &[u8] = b"quic iv";
469
470
266k
    let nonce_len = aead.nonce_len();
471
472
266k
    if nonce_len > out.len() {
473
0
        return Err(Error::CryptoFail);
474
266k
    }
475
476
266k
    hkdf_expand_label(aead, prk, LABEL, &mut out[..nonce_len])
477
266k
}
478
479
877k
fn hkdf_expand_label(
480
877k
    alg: Algorithm, prk: &[u8], label: &[u8], out: &mut [u8],
481
877k
) -> Result<()> {
482
    const LABEL_PREFIX: &[u8] = b"tls13 ";
483
484
877k
    let out_len = (out.len() as u16).to_be_bytes();
485
877k
    let label_len = (LABEL_PREFIX.len() + label.len()) as u8;
486
487
877k
    let info = [&out_len, &[label_len][..], LABEL_PREFIX, label, &[0][..]];
488
877k
    let info = info.concat();
489
490
877k
    hkdf_expand(alg, out, prk, &info)?;
491
492
877k
    Ok(())
493
877k
}
494
495
186k
fn make_nonce(iv: &[u8], counter: u64) -> [u8; MAX_NONCE_LEN] {
496
186k
    let mut nonce = [0; MAX_NONCE_LEN];
497
186k
    nonce.copy_from_slice(iv);
498
499
    // XOR the last bytes of the IV with the counter. This is equivalent to
500
    // left-padding the counter with zero bytes.
501
1.49M
    for (a, b) in nonce[4..].iter_mut().zip(counter.to_be_bytes().iter()) {
502
1.49M
        *a ^= b;
503
1.49M
    }
504
505
186k
    nonce
506
186k
}
507
508
227
pub fn verify_slices_are_equal(a: &[u8], b: &[u8]) -> Result<()> {
509
227
    if a.len() != b.len() {
510
0
        return Err(Error::CryptoFail);
511
227
    }
512
513
227
    let rc = unsafe { CRYPTO_memcmp(a.as_ptr(), b.as_ptr(), a.len()) };
514
515
227
    if rc == 0 {
516
0
        return Ok(());
517
227
    }
518
519
227
    Err(Error::CryptoFail)
520
227
}
521
522
extern "C" {
523
    fn EVP_sha256() -> *const EVP_MD;
524
525
    fn EVP_sha384() -> *const EVP_MD;
526
527
    // CRYPTO
528
    fn CRYPTO_memcmp(a: *const u8, b: *const u8, len: usize) -> c_int;
529
}
530
531
#[cfg(test)]
532
mod 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
        // Client.
556
        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
        // Server.
589
        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
670
#[cfg(not(feature = "openssl"))]
671
mod boringssl;
672
#[cfg(not(feature = "openssl"))]
673
pub(crate) use boringssl::*;
674
675
#[cfg(feature = "openssl")]
676
mod openssl_quictls;
677
#[cfg(feature = "openssl")]
678
pub(crate) use openssl_quictls::*;