• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ring::aead;
28 use ring::hkdf;
29 
30 use crate::Error;
31 use crate::Result;
32 
33 use crate::packet;
34 
35 #[repr(C)]
36 #[derive(Clone, Copy, Debug, PartialEq)]
37 pub enum Level {
38     Initial   = 0,
39     ZeroRTT   = 1,
40     Handshake = 2,
41     OneRTT    = 3,
42 }
43 
44 impl Level {
from_epoch(e: packet::Epoch) -> Level45     pub fn from_epoch(e: packet::Epoch) -> Level {
46         match e {
47             packet::EPOCH_INITIAL => Level::Initial,
48 
49             packet::EPOCH_HANDSHAKE => Level::Handshake,
50 
51             packet::EPOCH_APPLICATION => Level::OneRTT,
52 
53             _ => unreachable!(),
54         }
55     }
56 }
57 
58 #[derive(Clone, Copy, Debug, PartialEq)]
59 pub enum Algorithm {
60     #[allow(non_camel_case_types)]
61     AES128_GCM,
62 
63     #[allow(non_camel_case_types)]
64     AES256_GCM,
65 
66     #[allow(non_camel_case_types)]
67     ChaCha20_Poly1305,
68 }
69 
70 impl Algorithm {
get_ring_aead(self) -> &'static aead::Algorithm71     fn get_ring_aead(self) -> &'static aead::Algorithm {
72         match self {
73             Algorithm::AES128_GCM => &aead::AES_128_GCM,
74             Algorithm::AES256_GCM => &aead::AES_256_GCM,
75             Algorithm::ChaCha20_Poly1305 => &aead::CHACHA20_POLY1305,
76         }
77     }
78 
get_ring_hp(self) -> &'static aead::quic::Algorithm79     fn get_ring_hp(self) -> &'static aead::quic::Algorithm {
80         match self {
81             Algorithm::AES128_GCM => &aead::quic::AES_128,
82             Algorithm::AES256_GCM => &aead::quic::AES_256,
83             Algorithm::ChaCha20_Poly1305 => &aead::quic::CHACHA20,
84         }
85     }
86 
get_ring_digest(self) -> hkdf::Algorithm87     fn get_ring_digest(self) -> hkdf::Algorithm {
88         match self {
89             Algorithm::AES128_GCM => hkdf::HKDF_SHA256,
90             Algorithm::AES256_GCM => hkdf::HKDF_SHA384,
91             Algorithm::ChaCha20_Poly1305 => hkdf::HKDF_SHA256,
92         }
93     }
94 
key_len(self) -> usize95     pub fn key_len(self) -> usize {
96         self.get_ring_aead().key_len()
97     }
98 
tag_len(self) -> usize99     pub fn tag_len(self) -> usize {
100         if cfg!(feature = "fuzzing") {
101             return 0;
102         }
103 
104         self.get_ring_aead().tag_len()
105     }
106 
nonce_len(self) -> usize107     pub fn nonce_len(self) -> usize {
108         self.get_ring_aead().nonce_len()
109     }
110 }
111 
112 pub struct Open {
113     alg: Algorithm,
114 
115     hp_key: aead::quic::HeaderProtectionKey,
116 
117     key: aead::LessSafeKey,
118 
119     nonce: Vec<u8>,
120 }
121 
122 impl Open {
new( alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], ) -> Result<Open>123     pub fn new(
124         alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8],
125     ) -> Result<Open> {
126         Ok(Open {
127             hp_key: aead::quic::HeaderProtectionKey::new(
128                 alg.get_ring_hp(),
129                 hp_key,
130             )
131             .map_err(|_| Error::CryptoFail)?,
132 
133             key: aead::LessSafeKey::new(
134                 aead::UnboundKey::new(alg.get_ring_aead(), key)
135                     .map_err(|_| Error::CryptoFail)?,
136             ),
137 
138             nonce: Vec::from(iv),
139 
140             alg,
141         })
142     }
143 
from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open>144     pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open> {
145         let key_len = aead.key_len();
146         let nonce_len = aead.nonce_len();
147 
148         let mut key = vec![0; key_len];
149         let mut iv = vec![0; nonce_len];
150         let mut pn_key = vec![0; key_len];
151 
152         derive_pkt_key(aead, &secret, &mut key)?;
153         derive_pkt_iv(aead, &secret, &mut iv)?;
154         derive_hdr_key(aead, &secret, &mut pn_key)?;
155 
156         Open::new(aead, &key, &iv, &pn_key)
157     }
158 
open_with_u64_counter( &self, counter: u64, ad: &[u8], buf: &mut [u8], ) -> Result<usize>159     pub fn open_with_u64_counter(
160         &self, counter: u64, ad: &[u8], buf: &mut [u8],
161     ) -> Result<usize> {
162         if cfg!(feature = "fuzzing") {
163             return Ok(buf.len());
164         }
165 
166         let nonce = make_nonce(&self.nonce, counter);
167 
168         let ad = aead::Aad::from(ad);
169 
170         let plain = self
171             .key
172             .open_in_place(nonce, ad, buf)
173             .map_err(|_| Error::CryptoFail)?;
174 
175         Ok(plain.len())
176     }
177 
new_mask(&self, sample: &[u8]) -> Result<[u8; 5]>178     pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
179         if cfg!(feature = "fuzzing") {
180             return Ok(<[u8; 5]>::default());
181         }
182 
183         let mask = self
184             .hp_key
185             .new_mask(sample)
186             .map_err(|_| Error::CryptoFail)?;
187 
188         Ok(mask)
189     }
190 
alg(&self) -> Algorithm191     pub fn alg(&self) -> Algorithm {
192         self.alg
193     }
194 }
195 
196 pub struct Seal {
197     alg: Algorithm,
198 
199     hp_key: aead::quic::HeaderProtectionKey,
200 
201     key: aead::LessSafeKey,
202 
203     nonce: Vec<u8>,
204 }
205 
206 impl Seal {
new( alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], ) -> Result<Seal>207     pub fn new(
208         alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8],
209     ) -> Result<Seal> {
210         Ok(Seal {
211             hp_key: aead::quic::HeaderProtectionKey::new(
212                 alg.get_ring_hp(),
213                 hp_key,
214             )
215             .map_err(|_| Error::CryptoFail)?,
216 
217             key: aead::LessSafeKey::new(
218                 aead::UnboundKey::new(alg.get_ring_aead(), key)
219                     .map_err(|_| Error::CryptoFail)?,
220             ),
221 
222             nonce: Vec::from(iv),
223 
224             alg,
225         })
226     }
227 
from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal>228     pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal> {
229         let key_len = aead.key_len();
230         let nonce_len = aead.nonce_len();
231 
232         let mut key = vec![0; key_len];
233         let mut iv = vec![0; nonce_len];
234         let mut pn_key = vec![0; key_len];
235 
236         derive_pkt_key(aead, &secret, &mut key)?;
237         derive_pkt_iv(aead, &secret, &mut iv)?;
238         derive_hdr_key(aead, &secret, &mut pn_key)?;
239 
240         Seal::new(aead, &key, &iv, &pn_key)
241     }
242 
seal_with_u64_counter( &self, counter: u64, ad: &[u8], buf: &mut [u8], ) -> Result<()>243     pub fn seal_with_u64_counter(
244         &self, counter: u64, ad: &[u8], buf: &mut [u8],
245     ) -> Result<()> {
246         if cfg!(feature = "fuzzing") {
247             return Ok(());
248         }
249 
250         let nonce = make_nonce(&self.nonce, counter);
251 
252         let ad = aead::Aad::from(ad);
253 
254         let tag_len = self.alg().tag_len();
255 
256         let in_out_len =
257             buf.len().checked_sub(tag_len).ok_or(Error::CryptoFail)?;
258 
259         let (in_out, tag_out) = buf.split_at_mut(in_out_len);
260 
261         let tag = self
262             .key
263             .seal_in_place_separate_tag(nonce, ad, in_out)
264             .map_err(|_| Error::CryptoFail)?;
265 
266         // Append the AEAD tag to the end of the sealed buffer.
267         tag_out.copy_from_slice(tag.as_ref());
268 
269         Ok(())
270     }
271 
new_mask(&self, sample: &[u8]) -> Result<[u8; 5]>272     pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
273         if cfg!(feature = "fuzzing") {
274             return Ok(<[u8; 5]>::default());
275         }
276 
277         let mask = self
278             .hp_key
279             .new_mask(sample)
280             .map_err(|_| Error::CryptoFail)?;
281 
282         Ok(mask)
283     }
284 
alg(&self) -> Algorithm285     pub fn alg(&self) -> Algorithm {
286         self.alg
287     }
288 }
289 
derive_initial_key_material( cid: &[u8], version: u32, is_server: bool, ) -> Result<(Open, Seal)>290 pub fn derive_initial_key_material(
291     cid: &[u8], version: u32, is_server: bool,
292 ) -> Result<(Open, Seal)> {
293     let mut secret = [0; 32];
294 
295     let aead = Algorithm::AES128_GCM;
296 
297     let key_len = aead.key_len();
298     let nonce_len = aead.nonce_len();
299 
300     let initial_secret = derive_initial_secret(&cid, version)?;
301 
302     // Client.
303     let mut client_key = vec![0; key_len];
304     let mut client_iv = vec![0; nonce_len];
305     let mut client_hp_key = vec![0; key_len];
306 
307     derive_client_initial_secret(&initial_secret, &mut secret)?;
308     derive_pkt_key(aead, &secret, &mut client_key)?;
309     derive_pkt_iv(aead, &secret, &mut client_iv)?;
310     derive_hdr_key(aead, &secret, &mut client_hp_key)?;
311 
312     // Server.
313     let mut server_key = vec![0; key_len];
314     let mut server_iv = vec![0; nonce_len];
315     let mut server_hp_key = vec![0; key_len];
316 
317     derive_server_initial_secret(&initial_secret, &mut secret)?;
318     derive_pkt_key(aead, &secret, &mut server_key)?;
319     derive_pkt_iv(aead, &secret, &mut server_iv)?;
320     derive_hdr_key(aead, &secret, &mut server_hp_key)?;
321 
322     let (open, seal) = if is_server {
323         (
324             Open::new(aead, &client_key, &client_iv, &client_hp_key)?,
325             Seal::new(aead, &server_key, &server_iv, &server_hp_key)?,
326         )
327     } else {
328         (
329             Open::new(aead, &server_key, &server_iv, &server_hp_key)?,
330             Seal::new(aead, &client_key, &client_iv, &client_hp_key)?,
331         )
332     };
333 
334     Ok((open, seal))
335 }
336 
derive_initial_secret(secret: &[u8], version: u32) -> Result<hkdf::Prk>337 fn derive_initial_secret(secret: &[u8], version: u32) -> Result<hkdf::Prk> {
338     const INITIAL_SALT: [u8; 20] = [
339         0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1,
340         0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99,
341     ];
342 
343     const INITIAL_SALT_OLD: [u8; 20] = [
344         0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7, 0xd2, 0x43,
345         0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
346     ];
347 
348     let salt = match version {
349         crate::PROTOCOL_VERSION_DRAFT27 | crate::PROTOCOL_VERSION_DRAFT28 =>
350             &INITIAL_SALT_OLD,
351 
352         _ => &INITIAL_SALT,
353     };
354 
355     let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, salt);
356     Ok(salt.extract(secret))
357 }
358 
derive_client_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()>359 fn derive_client_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()> {
360     const LABEL: &[u8] = b"client in";
361     hkdf_expand_label(prk, LABEL, out)
362 }
363 
derive_server_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()>364 fn derive_server_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()> {
365     const LABEL: &[u8] = b"server in";
366     hkdf_expand_label(prk, LABEL, out)
367 }
368 
derive_hdr_key( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()>369 pub fn derive_hdr_key(
370     aead: Algorithm, secret: &[u8], out: &mut [u8],
371 ) -> Result<()> {
372     const LABEL: &[u8] = b"quic hp";
373 
374     let key_len = aead.key_len();
375 
376     if key_len > out.len() {
377         return Err(Error::CryptoFail);
378     }
379 
380     let secret = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
381     hkdf_expand_label(&secret, LABEL, &mut out[..key_len])
382 }
383 
derive_pkt_key( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()>384 pub fn derive_pkt_key(
385     aead: Algorithm, secret: &[u8], out: &mut [u8],
386 ) -> Result<()> {
387     const LABEL: &[u8] = b"quic key";
388 
389     let key_len = aead.key_len();
390 
391     if key_len > out.len() {
392         return Err(Error::CryptoFail);
393     }
394 
395     let secret = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
396     hkdf_expand_label(&secret, LABEL, &mut out[..key_len])
397 }
398 
derive_pkt_iv( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()>399 pub fn derive_pkt_iv(
400     aead: Algorithm, secret: &[u8], out: &mut [u8],
401 ) -> Result<()> {
402     const LABEL: &[u8] = b"quic iv";
403 
404     let nonce_len = aead.nonce_len();
405 
406     if nonce_len > out.len() {
407         return Err(Error::CryptoFail);
408     }
409 
410     let secret = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
411     hkdf_expand_label(&secret, LABEL, &mut out[..nonce_len])
412 }
413 
hkdf_expand_label( prk: &hkdf::Prk, label: &[u8], out: &mut [u8], ) -> Result<()>414 fn hkdf_expand_label(
415     prk: &hkdf::Prk, label: &[u8], out: &mut [u8],
416 ) -> Result<()> {
417     const LABEL_PREFIX: &[u8] = b"tls13 ";
418 
419     let out_len = (out.len() as u16).to_be_bytes();
420     let label_len = (LABEL_PREFIX.len() + label.len()) as u8;
421 
422     let info = [&out_len, &[label_len][..], LABEL_PREFIX, label, &[0][..]];
423 
424     prk.expand(&info, ArbitraryOutputLen(out.len()))
425         .map_err(|_| Error::CryptoFail)?
426         .fill(out)
427         .map_err(|_| Error::CryptoFail)?;
428 
429     Ok(())
430 }
431 
make_nonce(iv: &[u8], counter: u64) -> aead::Nonce432 fn make_nonce(iv: &[u8], counter: u64) -> aead::Nonce {
433     let mut nonce = [0; aead::NONCE_LEN];
434     nonce.copy_from_slice(&iv);
435 
436     // XOR the last bytes of the IV with the counter. This is equivalent to
437     // left-padding the counter with zero bytes.
438     for (a, b) in nonce[4..].iter_mut().zip(counter.to_be_bytes().iter()) {
439         *a ^= b;
440     }
441 
442     aead::Nonce::assume_unique_for_key(nonce)
443 }
444 
445 // The ring HKDF expand() API does not accept an arbitrary output length, so we
446 // need to hide the `usize` length as part of a type that implements the trait
447 // `ring::hkdf::KeyType` in order to trick ring into accepting it.
448 struct ArbitraryOutputLen(usize);
449 
450 impl hkdf::KeyType for ArbitraryOutputLen {
len(&self) -> usize451     fn len(&self) -> usize {
452         self.0
453     }
454 }
455 
456 #[cfg(test)]
457 mod tests {
458     use super::*;
459 
460     #[test]
derive_initial_secrets()461     fn derive_initial_secrets() {
462         let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
463 
464         let mut secret = [0; 32];
465         let mut pkt_key = [0; 16];
466         let mut pkt_iv = [0; 12];
467         let mut hdr_key = [0; 16];
468 
469         let aead = Algorithm::AES128_GCM;
470 
471         let initial_secret =
472             derive_initial_secret(&dcid, crate::PROTOCOL_VERSION).unwrap();
473 
474         // Client.
475         assert!(
476             derive_client_initial_secret(&initial_secret, &mut secret).is_ok()
477         );
478         let expected_client_initial_secret = [
479             0x00, 0x88, 0x11, 0x92, 0x88, 0xf1, 0xd8, 0x66, 0x73, 0x3c, 0xee,
480             0xed, 0x15, 0xff, 0x9d, 0x50, 0x90, 0x2c, 0xf8, 0x29, 0x52, 0xee,
481             0xe2, 0x7e, 0x9d, 0x4d, 0x49, 0x18, 0xea, 0x37, 0x1d, 0x87,
482         ];
483         assert_eq!(&secret, &expected_client_initial_secret);
484 
485         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
486         let expected_client_pkt_key = [
487             0x17, 0x52, 0x57, 0xa3, 0x1e, 0xb0, 0x9d, 0xea, 0x93, 0x66, 0xd8,
488             0xbb, 0x79, 0xad, 0x80, 0xba,
489         ];
490         assert_eq!(&pkt_key, &expected_client_pkt_key);
491 
492         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
493         let expected_client_pkt_iv = [
494             0x6b, 0x26, 0x11, 0x4b, 0x9c, 0xba, 0x2b, 0x63, 0xa9, 0xe8, 0xdd,
495             0x4f,
496         ];
497         assert_eq!(&pkt_iv, &expected_client_pkt_iv);
498 
499         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
500         let expected_client_hdr_key = [
501             0x9d, 0xdd, 0x12, 0xc9, 0x94, 0xc0, 0x69, 0x8b, 0x89, 0x37, 0x4a,
502             0x9c, 0x07, 0x7a, 0x30, 0x77,
503         ];
504         assert_eq!(&hdr_key, &expected_client_hdr_key);
505 
506         // Server.
507         assert!(
508             derive_server_initial_secret(&initial_secret, &mut secret).is_ok()
509         );
510         let expected_server_initial_secret = [
511             0x00, 0x6f, 0x88, 0x13, 0x59, 0x24, 0x4d, 0xd9, 0xad, 0x1a, 0xcf,
512             0x85, 0xf5, 0x95, 0xba, 0xd6, 0x7c, 0x13, 0xf9, 0xf5, 0x58, 0x6f,
513             0x5e, 0x64, 0xe1, 0xac, 0xae, 0x1d, 0x9e, 0xa8, 0xf6, 0x16,
514         ];
515         assert_eq!(&secret, &expected_server_initial_secret);
516 
517         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
518         let expected_server_pkt_key = [
519             0x14, 0x9d, 0x0b, 0x16, 0x62, 0xab, 0x87, 0x1f, 0xbe, 0x63, 0xc4,
520             0x9b, 0x5e, 0x65, 0x5a, 0x5d,
521         ];
522         assert_eq!(&pkt_key, &expected_server_pkt_key);
523 
524         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
525         let expected_server_pkt_iv = [
526             0xba, 0xb2, 0xb1, 0x2a, 0x4c, 0x76, 0x01, 0x6a, 0xce, 0x47, 0x85,
527             0x6d,
528         ];
529         assert_eq!(&pkt_iv, &expected_server_pkt_iv);
530 
531         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
532         let expected_server_hdr_key = [
533             0xc0, 0xc4, 0x99, 0xa6, 0x5a, 0x60, 0x02, 0x4a, 0x18, 0xa2, 0x50,
534             0x97, 0x4e, 0xa0, 0x1d, 0xfa,
535         ];
536         assert_eq!(&hdr_key, &expected_server_hdr_key);
537     }
538 
539     #[test]
derive_initial_secrets_old()540     fn derive_initial_secrets_old() {
541         let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
542 
543         let mut secret = [0; 32];
544         let mut pkt_key = [0; 16];
545         let mut pkt_iv = [0; 12];
546         let mut hdr_key = [0; 16];
547 
548         let aead = Algorithm::AES128_GCM;
549 
550         let initial_secret =
551             derive_initial_secret(&dcid, crate::PROTOCOL_VERSION_DRAFT28)
552                 .unwrap();
553 
554         // Client.
555         assert!(
556             derive_client_initial_secret(&initial_secret, &mut secret).is_ok()
557         );
558         let expected_client_initial_secret = [
559             0xfd, 0xa3, 0x95, 0x3a, 0xec, 0xc0, 0x40, 0xe4, 0x8b, 0x34, 0xe2,
560             0x7e, 0xf8, 0x7d, 0xe3, 0xa6, 0x09, 0x8e, 0xcf, 0x0e, 0x38, 0xb7,
561             0xe0, 0x32, 0xc5, 0xc5, 0x7b, 0xcb, 0xd5, 0x97, 0x5b, 0x84,
562         ];
563         assert_eq!(&secret, &expected_client_initial_secret);
564 
565         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
566         let expected_client_pkt_key = [
567             0xaf, 0x7f, 0xd7, 0xef, 0xeb, 0xd2, 0x18, 0x78, 0xff, 0x66, 0x81,
568             0x12, 0x48, 0x98, 0x36, 0x94,
569         ];
570         assert_eq!(&pkt_key, &expected_client_pkt_key);
571 
572         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
573         let expected_client_pkt_iv = [
574             0x86, 0x81, 0x35, 0x94, 0x10, 0xa7, 0x0b, 0xb9, 0xc9, 0x2f, 0x04,
575             0x20,
576         ];
577         assert_eq!(&pkt_iv, &expected_client_pkt_iv);
578 
579         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
580         let expected_client_hdr_key = [
581             0xa9, 0x80, 0xb8, 0xb4, 0xfb, 0x7d, 0x9f, 0xbc, 0x13, 0xe8, 0x14,
582             0xc2, 0x31, 0x64, 0x25, 0x3d,
583         ];
584         assert_eq!(&hdr_key, &expected_client_hdr_key);
585 
586         // Server.
587         assert!(
588             derive_server_initial_secret(&initial_secret, &mut secret).is_ok()
589         );
590         let expected_server_initial_secret = [
591             0x55, 0x43, 0x66, 0xb8, 0x19, 0x12, 0xff, 0x90, 0xbe, 0x41, 0xf1,
592             0x7e, 0x80, 0x22, 0x21, 0x30, 0x90, 0xab, 0x17, 0xd8, 0x14, 0x91,
593             0x79, 0xbc, 0xad, 0xf2, 0x22, 0xf2, 0x9f, 0xf2, 0xdd, 0xd5,
594         ];
595         assert_eq!(&secret, &expected_server_initial_secret);
596 
597         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
598         let expected_server_pkt_key = [
599             0x5d, 0x51, 0xda, 0x9e, 0xe8, 0x97, 0xa2, 0x1b, 0x26, 0x59, 0xcc,
600             0xc7, 0xe5, 0xbf, 0xa5, 0x77,
601         ];
602         assert_eq!(&pkt_key, &expected_server_pkt_key);
603 
604         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
605         let expected_server_pkt_iv = [
606             0x5e, 0x5a, 0xe6, 0x51, 0xfd, 0x1e, 0x84, 0x95, 0xaf, 0x13, 0x50,
607             0x8b,
608         ];
609         assert_eq!(&pkt_iv, &expected_server_pkt_iv);
610 
611         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
612         let expected_server_hdr_key = [
613             0xa8, 0xed, 0x82, 0xe6, 0x66, 0x4f, 0x86, 0x5a, 0xed, 0xf6, 0x10,
614             0x69, 0x43, 0xf9, 0x5f, 0xb8,
615         ];
616         assert_eq!(&hdr_key, &expected_server_hdr_key);
617     }
618 
619     #[test]
derive_chacha20_secrets()620     fn derive_chacha20_secrets() {
621         let secret = [
622             0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42,
623             0x27, 0x48, 0xad, 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0,
624             0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3, 0x0f, 0x21, 0x63, 0x2b,
625         ];
626 
627         let aead = Algorithm::ChaCha20_Poly1305;
628 
629         let mut pkt_key = [0; 32];
630         let mut pkt_iv = [0; 12];
631         let mut hdr_key = [0; 32];
632 
633         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
634         let expected_pkt_key = [
635             0xc6, 0xd9, 0x8f, 0xf3, 0x44, 0x1c, 0x3f, 0xe1, 0xb2, 0x18, 0x20,
636             0x94, 0xf6, 0x9c, 0xaa, 0x2e, 0xd4, 0xb7, 0x16, 0xb6, 0x54, 0x88,
637             0x96, 0x0a, 0x7a, 0x98, 0x49, 0x79, 0xfb, 0x23, 0xe1, 0xc8,
638         ];
639         assert_eq!(&pkt_key, &expected_pkt_key);
640 
641         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
642         let expected_pkt_iv = [
643             0xe0, 0x45, 0x9b, 0x34, 0x74, 0xbd, 0xd0, 0xe4, 0x4a, 0x41, 0xc1,
644             0x44,
645         ];
646         assert_eq!(&pkt_iv, &expected_pkt_iv);
647 
648         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
649         let expected_hdr_key = [
650             0x25, 0xa2, 0x82, 0xb9, 0xe8, 0x2f, 0x06, 0xf2, 0x1f, 0x48, 0x89,
651             0x17, 0xa4, 0xfc, 0x8f, 0x1b, 0x73, 0x57, 0x36, 0x85, 0x60, 0x85,
652             0x97, 0xd0, 0xef, 0xcb, 0x07, 0x6b, 0x0a, 0xb7, 0xa7, 0xa4,
653         ];
654         assert_eq!(&hdr_key, &expected_hdr_key);
655     }
656 }
657