• 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 std::mem::MaybeUninit;
28 
29 use ring::aead;
30 use ring::hkdf;
31 
32 use libc::c_int;
33 use libc::c_void;
34 
35 use crate::Error;
36 use crate::Result;
37 
38 use crate::packet;
39 
40 #[repr(C)]
41 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
42 pub enum Level {
43     Initial   = 0,
44     ZeroRTT   = 1,
45     Handshake = 2,
46     OneRTT    = 3,
47 }
48 
49 impl Level {
from_epoch(e: packet::Epoch) -> Level50     pub fn from_epoch(e: packet::Epoch) -> Level {
51         match e {
52             packet::Epoch::Initial => Level::Initial,
53 
54             packet::Epoch::Handshake => Level::Handshake,
55 
56             packet::Epoch::Application => Level::OneRTT,
57         }
58     }
59 }
60 
61 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
62 pub enum Algorithm {
63     #[allow(non_camel_case_types)]
64     AES128_GCM,
65 
66     #[allow(non_camel_case_types)]
67     AES256_GCM,
68 
69     #[allow(non_camel_case_types)]
70     ChaCha20_Poly1305,
71 }
72 
73 impl Algorithm {
get_evp_aead(self) -> *const EVP_AEAD74     fn get_evp_aead(self) -> *const EVP_AEAD {
75         match self {
76             Algorithm::AES128_GCM => unsafe { EVP_aead_aes_128_gcm() },
77             Algorithm::AES256_GCM => unsafe { EVP_aead_aes_256_gcm() },
78             Algorithm::ChaCha20_Poly1305 => unsafe {
79                 EVP_aead_chacha20_poly1305()
80             },
81         }
82     }
83 
get_ring_hp(self) -> &'static aead::quic::Algorithm84     fn get_ring_hp(self) -> &'static aead::quic::Algorithm {
85         match self {
86             Algorithm::AES128_GCM => &aead::quic::AES_128,
87             Algorithm::AES256_GCM => &aead::quic::AES_256,
88             Algorithm::ChaCha20_Poly1305 => &aead::quic::CHACHA20,
89         }
90     }
91 
get_ring_digest(self) -> hkdf::Algorithm92     fn get_ring_digest(self) -> hkdf::Algorithm {
93         match self {
94             Algorithm::AES128_GCM => hkdf::HKDF_SHA256,
95             Algorithm::AES256_GCM => hkdf::HKDF_SHA384,
96             Algorithm::ChaCha20_Poly1305 => hkdf::HKDF_SHA256,
97         }
98     }
99 
key_len(self) -> usize100     pub fn key_len(self) -> usize {
101         match self {
102             Algorithm::AES128_GCM => 16,
103             Algorithm::AES256_GCM => 32,
104             Algorithm::ChaCha20_Poly1305 => 32,
105         }
106     }
107 
tag_len(self) -> usize108     pub fn tag_len(self) -> usize {
109         if cfg!(feature = "fuzzing") {
110             return 0;
111         }
112 
113         match self {
114             Algorithm::AES128_GCM => 16,
115             Algorithm::AES256_GCM => 16,
116             Algorithm::ChaCha20_Poly1305 => 16,
117         }
118     }
119 
nonce_len(self) -> usize120     pub fn nonce_len(self) -> usize {
121         match self {
122             Algorithm::AES128_GCM => 12,
123             Algorithm::AES256_GCM => 12,
124             Algorithm::ChaCha20_Poly1305 => 12,
125         }
126     }
127 }
128 
129 pub struct Open {
130     alg: Algorithm,
131 
132     secret: Vec<u8>,
133 
134     header: HeaderProtectionKey,
135 
136     packet: PacketKey,
137 }
138 
139 impl Open {
new( alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], secret: &[u8], ) -> Result<Open>140     pub fn new(
141         alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], secret: &[u8],
142     ) -> Result<Open> {
143         Ok(Open {
144             alg,
145 
146             secret: Vec::from(secret),
147 
148             header: HeaderProtectionKey::new(alg, hp_key)?,
149 
150             packet: PacketKey::new(alg, key, iv)?,
151         })
152     }
153 
from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open>154     pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Open> {
155         Ok(Open {
156             alg: aead,
157 
158             secret: Vec::from(secret),
159 
160             header: HeaderProtectionKey::from_secret(aead, secret)?,
161 
162             packet: PacketKey::from_secret(aead, secret)?,
163         })
164     }
165 
open_with_u64_counter( &self, counter: u64, ad: &[u8], buf: &mut [u8], ) -> Result<usize>166     pub fn open_with_u64_counter(
167         &self, counter: u64, ad: &[u8], buf: &mut [u8],
168     ) -> Result<usize> {
169         if cfg!(feature = "fuzzing") {
170             return Ok(buf.len());
171         }
172 
173         let tag_len = self.alg().tag_len();
174 
175         let mut out_len = match buf.len().checked_sub(tag_len) {
176             Some(n) => n,
177             None => return Err(Error::CryptoFail),
178         };
179 
180         let max_out_len = out_len;
181 
182         let nonce = make_nonce(&self.packet.nonce, counter);
183 
184         let rc = unsafe {
185             EVP_AEAD_CTX_open(
186                 &self.packet.ctx,   // ctx
187                 buf.as_mut_ptr(),   // out
188                 &mut out_len,       // out_len
189                 max_out_len,        // max_out_len
190                 nonce[..].as_ptr(), // nonce
191                 nonce.len(),        // nonce_len
192                 buf.as_ptr(),       // inp
193                 buf.len(),          // in_len
194                 ad.as_ptr(),        // ad
195                 ad.len(),           // ad_len
196             )
197         };
198 
199         if rc != 1 {
200             return Err(Error::CryptoFail);
201         }
202 
203         Ok(out_len)
204     }
205 
new_mask(&self, sample: &[u8]) -> Result<[u8; 5]>206     pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
207         if cfg!(feature = "fuzzing") {
208             return Ok(<[u8; 5]>::default());
209         }
210 
211         let mask = self
212             .header
213             .hpk
214             .new_mask(sample)
215             .map_err(|_| Error::CryptoFail)?;
216 
217         Ok(mask)
218     }
219 
alg(&self) -> Algorithm220     pub fn alg(&self) -> Algorithm {
221         self.alg
222     }
223 
derive_next_packet_key(&self) -> Result<Open>224     pub fn derive_next_packet_key(&self) -> Result<Open> {
225         let next_secret = derive_next_secret(self.alg, &self.secret)?;
226 
227         let next_packet_key = PacketKey::from_secret(self.alg, &next_secret)?;
228 
229         Ok(Open {
230             alg: self.alg,
231 
232             secret: next_secret,
233 
234             header: HeaderProtectionKey::new(self.alg, &self.header.hp_key)?,
235 
236             packet: next_packet_key,
237         })
238     }
239 }
240 
241 pub struct Seal {
242     alg: Algorithm,
243 
244     secret: Vec<u8>,
245 
246     header: HeaderProtectionKey,
247 
248     packet: PacketKey,
249 }
250 
251 impl Seal {
new( alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], secret: &[u8], ) -> Result<Seal>252     pub fn new(
253         alg: Algorithm, key: &[u8], iv: &[u8], hp_key: &[u8], secret: &[u8],
254     ) -> Result<Seal> {
255         Ok(Seal {
256             alg,
257 
258             secret: Vec::from(secret),
259 
260             header: HeaderProtectionKey::new(alg, hp_key)?,
261 
262             packet: PacketKey::new(alg, key, iv)?,
263         })
264     }
265 
from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal>266     pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Seal> {
267         Ok(Seal {
268             alg: aead,
269 
270             secret: Vec::from(secret),
271 
272             header: HeaderProtectionKey::from_secret(aead, secret)?,
273 
274             packet: PacketKey::from_secret(aead, secret)?,
275         })
276     }
277 
seal_with_u64_counter( &self, counter: u64, ad: &[u8], buf: &mut [u8], in_len: usize, extra_in: Option<&[u8]>, ) -> Result<usize>278     pub fn seal_with_u64_counter(
279         &self, counter: u64, ad: &[u8], buf: &mut [u8], in_len: usize,
280         extra_in: Option<&[u8]>,
281     ) -> Result<usize> {
282         if cfg!(feature = "fuzzing") {
283             if let Some(extra) = extra_in {
284                 buf[in_len..in_len + extra.len()].copy_from_slice(extra);
285                 return Ok(in_len + extra.len());
286             }
287 
288             return Ok(in_len);
289         }
290 
291         let tag_len = self.alg().tag_len();
292 
293         let mut out_tag_len = tag_len;
294 
295         let (extra_in_ptr, extra_in_len) = match extra_in {
296             Some(v) => (v.as_ptr(), v.len()),
297 
298             None => (std::ptr::null(), 0),
299         };
300 
301         // Make sure all the outputs combined fit in the buffer.
302         if in_len + tag_len + extra_in_len > buf.len() {
303             return Err(Error::CryptoFail);
304         }
305 
306         let nonce = make_nonce(&self.packet.nonce, counter);
307 
308         let rc = unsafe {
309             EVP_AEAD_CTX_seal_scatter(
310                 &self.packet.ctx,           // ctx
311                 buf.as_mut_ptr(),           // out
312                 buf[in_len..].as_mut_ptr(), // out_tag
313                 &mut out_tag_len,           // out_tag_len
314                 tag_len + extra_in_len,     // max_out_tag_len
315                 nonce[..].as_ptr(),         // nonce
316                 nonce.len(),                // nonce_len
317                 buf.as_ptr(),               // inp
318                 in_len,                     // in_len
319                 extra_in_ptr,               // extra_in
320                 extra_in_len,               // extra_in_len
321                 ad.as_ptr(),                // ad
322                 ad.len(),                   // ad_len
323             )
324         };
325 
326         if rc != 1 {
327             return Err(Error::CryptoFail);
328         }
329 
330         Ok(in_len + out_tag_len)
331     }
332 
new_mask(&self, sample: &[u8]) -> Result<[u8; 5]>333     pub fn new_mask(&self, sample: &[u8]) -> Result<[u8; 5]> {
334         if cfg!(feature = "fuzzing") {
335             return Ok(<[u8; 5]>::default());
336         }
337 
338         let mask = self
339             .header
340             .hpk
341             .new_mask(sample)
342             .map_err(|_| Error::CryptoFail)?;
343 
344         Ok(mask)
345     }
346 
alg(&self) -> Algorithm347     pub fn alg(&self) -> Algorithm {
348         self.alg
349     }
350 
derive_next_packet_key(&self) -> Result<Seal>351     pub fn derive_next_packet_key(&self) -> Result<Seal> {
352         let next_secret = derive_next_secret(self.alg, &self.secret)?;
353 
354         let next_packet_key = PacketKey::from_secret(self.alg, &next_secret)?;
355 
356         Ok(Seal {
357             alg: self.alg,
358 
359             secret: next_secret,
360 
361             header: HeaderProtectionKey::new(self.alg, &self.header.hp_key)?,
362 
363             packet: next_packet_key,
364         })
365     }
366 }
367 
368 pub struct HeaderProtectionKey {
369     hpk: aead::quic::HeaderProtectionKey,
370 
371     hp_key: Vec<u8>,
372 }
373 
374 impl HeaderProtectionKey {
new(alg: Algorithm, hp_key: &[u8]) -> Result<Self>375     pub fn new(alg: Algorithm, hp_key: &[u8]) -> Result<Self> {
376         aead::quic::HeaderProtectionKey::new(alg.get_ring_hp(), hp_key)
377             .map(|hpk| Self {
378                 hpk,
379                 hp_key: Vec::from(hp_key),
380             })
381             .map_err(|_| Error::CryptoFail)
382     }
383 
from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self>384     pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
385         let key_len = aead.key_len();
386 
387         let mut hp_key = vec![0; key_len];
388 
389         derive_hdr_key(aead, secret, &mut hp_key)?;
390 
391         Self::new(aead, &hp_key)
392     }
393 }
394 
395 pub struct PacketKey {
396     ctx: EVP_AEAD_CTX,
397 
398     nonce: Vec<u8>,
399 }
400 
401 impl PacketKey {
new(alg: Algorithm, key: &[u8], iv: &[u8]) -> Result<Self>402     pub fn new(alg: Algorithm, key: &[u8], iv: &[u8]) -> Result<Self> {
403         Ok(Self {
404             ctx: make_aead_ctx(alg, key)?,
405 
406             nonce: Vec::from(iv),
407         })
408     }
409 
from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self>410     pub fn from_secret(aead: Algorithm, secret: &[u8]) -> Result<Self> {
411         let key_len = aead.key_len();
412         let nonce_len = aead.nonce_len();
413 
414         let mut key = vec![0; key_len];
415         let mut iv = vec![0; nonce_len];
416 
417         derive_pkt_key(aead, secret, &mut key)?;
418         derive_pkt_iv(aead, secret, &mut iv)?;
419 
420         Self::new(aead, &key, &iv)
421     }
422 }
423 
derive_initial_key_material( cid: &[u8], version: u32, is_server: bool, ) -> Result<(Open, Seal)>424 pub fn derive_initial_key_material(
425     cid: &[u8], version: u32, is_server: bool,
426 ) -> Result<(Open, Seal)> {
427     let mut client_secret = [0; 32];
428     let mut server_secret = [0; 32];
429 
430     let aead = Algorithm::AES128_GCM;
431 
432     let key_len = aead.key_len();
433     let nonce_len = aead.nonce_len();
434 
435     let initial_secret = derive_initial_secret(cid, version);
436 
437     // Client.
438     let mut client_key = vec![0; key_len];
439     let mut client_iv = vec![0; nonce_len];
440     let mut client_hp_key = vec![0; key_len];
441 
442     derive_client_initial_secret(&initial_secret, &mut client_secret)?;
443     derive_pkt_key(aead, &client_secret, &mut client_key)?;
444     derive_pkt_iv(aead, &client_secret, &mut client_iv)?;
445     derive_hdr_key(aead, &client_secret, &mut client_hp_key)?;
446 
447     // Server.
448     let mut server_key = vec![0; key_len];
449     let mut server_iv = vec![0; nonce_len];
450     let mut server_hp_key = vec![0; key_len];
451 
452     derive_server_initial_secret(&initial_secret, &mut server_secret)?;
453     derive_pkt_key(aead, &server_secret, &mut server_key)?;
454     derive_pkt_iv(aead, &server_secret, &mut server_iv)?;
455     derive_hdr_key(aead, &server_secret, &mut server_hp_key)?;
456 
457     let (open, seal) = if is_server {
458         (
459             Open::new(
460                 aead,
461                 &client_key,
462                 &client_iv,
463                 &client_hp_key,
464                 &client_secret,
465             )?,
466             Seal::new(
467                 aead,
468                 &server_key,
469                 &server_iv,
470                 &server_hp_key,
471                 &server_secret,
472             )?,
473         )
474     } else {
475         (
476             Open::new(
477                 aead,
478                 &server_key,
479                 &server_iv,
480                 &server_hp_key,
481                 &server_secret,
482             )?,
483             Seal::new(
484                 aead,
485                 &client_key,
486                 &client_iv,
487                 &client_hp_key,
488                 &client_secret,
489             )?,
490         )
491     };
492 
493     Ok((open, seal))
494 }
495 
derive_initial_secret(secret: &[u8], version: u32) -> hkdf::Prk496 fn derive_initial_secret(secret: &[u8], version: u32) -> hkdf::Prk {
497     const INITIAL_SALT: [u8; 20] = [
498         0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6,
499         0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
500     ];
501 
502     const INITIAL_SALT_DRAFT29: [u8; 20] = [
503         0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97, 0x86, 0xf1,
504         0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99,
505     ];
506 
507     const INITIAL_SALT_DRAFT27: [u8; 20] = [
508         0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7, 0xd2, 0x43,
509         0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
510     ];
511 
512     let salt = match version {
513         crate::PROTOCOL_VERSION_DRAFT27 | crate::PROTOCOL_VERSION_DRAFT28 =>
514             &INITIAL_SALT_DRAFT27,
515 
516         crate::PROTOCOL_VERSION_DRAFT29 => &INITIAL_SALT_DRAFT29,
517 
518         _ => &INITIAL_SALT,
519     };
520 
521     let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, salt);
522     salt.extract(secret)
523 }
524 
derive_client_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()>525 fn derive_client_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()> {
526     const LABEL: &[u8] = b"client in";
527     hkdf_expand_label(prk, LABEL, out)
528 }
529 
derive_server_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()>530 fn derive_server_initial_secret(prk: &hkdf::Prk, out: &mut [u8]) -> Result<()> {
531     const LABEL: &[u8] = b"server in";
532     hkdf_expand_label(prk, LABEL, out)
533 }
534 
derive_next_secret(aead: Algorithm, secret: &[u8]) -> Result<Vec<u8>>535 fn derive_next_secret(aead: Algorithm, secret: &[u8]) -> Result<Vec<u8>> {
536     const LABEL: &[u8] = b"quic ku";
537 
538     let mut next_secret = vec![0; secret.len()];
539 
540     let secret_prk = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
541     hkdf_expand_label(&secret_prk, LABEL, &mut next_secret)?;
542 
543     Ok(next_secret)
544 }
545 
derive_hdr_key( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()>546 pub fn derive_hdr_key(
547     aead: Algorithm, secret: &[u8], out: &mut [u8],
548 ) -> Result<()> {
549     const LABEL: &[u8] = b"quic hp";
550 
551     let key_len = aead.key_len();
552 
553     if key_len > out.len() {
554         return Err(Error::CryptoFail);
555     }
556 
557     let secret = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
558     hkdf_expand_label(&secret, LABEL, &mut out[..key_len])
559 }
560 
derive_pkt_key( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()>561 pub fn derive_pkt_key(
562     aead: Algorithm, secret: &[u8], out: &mut [u8],
563 ) -> Result<()> {
564     const LABEL: &[u8] = b"quic key";
565 
566     let key_len = aead.key_len();
567 
568     if key_len > out.len() {
569         return Err(Error::CryptoFail);
570     }
571 
572     let secret = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
573     hkdf_expand_label(&secret, LABEL, &mut out[..key_len])
574 }
575 
derive_pkt_iv( aead: Algorithm, secret: &[u8], out: &mut [u8], ) -> Result<()>576 pub fn derive_pkt_iv(
577     aead: Algorithm, secret: &[u8], out: &mut [u8],
578 ) -> Result<()> {
579     const LABEL: &[u8] = b"quic iv";
580 
581     let nonce_len = aead.nonce_len();
582 
583     if nonce_len > out.len() {
584         return Err(Error::CryptoFail);
585     }
586 
587     let secret = hkdf::Prk::new_less_safe(aead.get_ring_digest(), secret);
588     hkdf_expand_label(&secret, LABEL, &mut out[..nonce_len])
589 }
590 
make_aead_ctx(alg: Algorithm, key: &[u8]) -> Result<EVP_AEAD_CTX>591 fn make_aead_ctx(alg: Algorithm, key: &[u8]) -> Result<EVP_AEAD_CTX> {
592     let mut ctx = MaybeUninit::uninit();
593 
594     let ctx = unsafe {
595         let aead = alg.get_evp_aead();
596 
597         let rc = EVP_AEAD_CTX_init(
598             ctx.as_mut_ptr(),
599             aead,
600             key.as_ptr(),
601             alg.key_len(),
602             alg.tag_len(),
603             std::ptr::null_mut(),
604         );
605 
606         if rc != 1 {
607             return Err(Error::CryptoFail);
608         }
609 
610         ctx.assume_init()
611     };
612 
613     Ok(ctx)
614 }
615 
hkdf_expand_label( prk: &hkdf::Prk, label: &[u8], out: &mut [u8], ) -> Result<()>616 fn hkdf_expand_label(
617     prk: &hkdf::Prk, label: &[u8], out: &mut [u8],
618 ) -> Result<()> {
619     const LABEL_PREFIX: &[u8] = b"tls13 ";
620 
621     let out_len = (out.len() as u16).to_be_bytes();
622     let label_len = (LABEL_PREFIX.len() + label.len()) as u8;
623 
624     let info = [&out_len, &[label_len][..], LABEL_PREFIX, label, &[0][..]];
625 
626     prk.expand(&info, ArbitraryOutputLen(out.len()))
627         .map_err(|_| Error::CryptoFail)?
628         .fill(out)
629         .map_err(|_| Error::CryptoFail)?;
630 
631     Ok(())
632 }
633 
make_nonce(iv: &[u8], counter: u64) -> [u8; aead::NONCE_LEN]634 fn make_nonce(iv: &[u8], counter: u64) -> [u8; aead::NONCE_LEN] {
635     let mut nonce = [0; aead::NONCE_LEN];
636     nonce.copy_from_slice(iv);
637 
638     // XOR the last bytes of the IV with the counter. This is equivalent to
639     // left-padding the counter with zero bytes.
640     for (a, b) in nonce[4..].iter_mut().zip(counter.to_be_bytes().iter()) {
641         *a ^= b;
642     }
643 
644     nonce
645 }
646 
647 // The ring HKDF expand() API does not accept an arbitrary output length, so we
648 // need to hide the `usize` length as part of a type that implements the trait
649 // `ring::hkdf::KeyType` in order to trick ring into accepting it.
650 struct ArbitraryOutputLen(usize);
651 
652 impl hkdf::KeyType for ArbitraryOutputLen {
len(&self) -> usize653     fn len(&self) -> usize {
654         self.0
655     }
656 }
657 
658 #[allow(non_camel_case_types)]
659 #[repr(transparent)]
660 struct EVP_AEAD(c_void);
661 
662 // NOTE: This structure is copied from <openssl/aead.h> in order to be able to
663 // statically allocate it. While it is not often modified upstream, it needs to
664 // be kept in sync.
665 #[repr(C)]
666 struct EVP_AEAD_CTX {
667     aead: libc::uintptr_t,
668     opaque: [u8; 580],
669     alignment: u64,
670     tag_len: u8,
671 }
672 
673 extern {
674     // EVP_AEAD
EVP_aead_aes_128_gcm() -> *const EVP_AEAD675     fn EVP_aead_aes_128_gcm() -> *const EVP_AEAD;
676 
EVP_aead_aes_256_gcm() -> *const EVP_AEAD677     fn EVP_aead_aes_256_gcm() -> *const EVP_AEAD;
678 
EVP_aead_chacha20_poly1305() -> *const EVP_AEAD679     fn EVP_aead_chacha20_poly1305() -> *const EVP_AEAD;
680 
681     // EVP_AEAD_CTX
EVP_AEAD_CTX_init( ctx: *mut EVP_AEAD_CTX, aead: *const EVP_AEAD, key: *const u8, key_len: usize, tag_len: usize, engine: *mut c_void, ) -> c_int682     fn EVP_AEAD_CTX_init(
683         ctx: *mut EVP_AEAD_CTX, aead: *const EVP_AEAD, key: *const u8,
684         key_len: usize, tag_len: usize, engine: *mut c_void,
685     ) -> c_int;
686 
EVP_AEAD_CTX_open( ctx: *const EVP_AEAD_CTX, out: *mut u8, out_len: *mut usize, max_out_len: usize, nonce: *const u8, nonce_len: usize, inp: *const u8, in_len: usize, ad: *const u8, ad_len: usize, ) -> c_int687     fn EVP_AEAD_CTX_open(
688         ctx: *const EVP_AEAD_CTX, out: *mut u8, out_len: *mut usize,
689         max_out_len: usize, nonce: *const u8, nonce_len: usize, inp: *const u8,
690         in_len: usize, ad: *const u8, ad_len: usize,
691     ) -> c_int;
692 
EVP_AEAD_CTX_seal_scatter( ctx: *const EVP_AEAD_CTX, out: *mut u8, out_tag: *mut u8, out_tag_len: *mut usize, max_out_tag_len: usize, nonce: *const u8, nonce_len: usize, inp: *const u8, in_len: usize, extra_in: *const u8, extra_in_len: usize, ad: *const u8, ad_len: usize, ) -> c_int693     fn EVP_AEAD_CTX_seal_scatter(
694         ctx: *const EVP_AEAD_CTX, out: *mut u8, out_tag: *mut u8,
695         out_tag_len: *mut usize, max_out_tag_len: usize, nonce: *const u8,
696         nonce_len: usize, inp: *const u8, in_len: usize, extra_in: *const u8,
697         extra_in_len: usize, ad: *const u8, ad_len: usize,
698     ) -> c_int;
699 }
700 
701 #[cfg(test)]
702 mod tests {
703     use super::*;
704 
705     #[test]
derive_initial_secrets_v1()706     fn derive_initial_secrets_v1() {
707         let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
708 
709         let mut secret = [0; 32];
710         let mut pkt_key = [0; 16];
711         let mut pkt_iv = [0; 12];
712         let mut hdr_key = [0; 16];
713 
714         let aead = Algorithm::AES128_GCM;
715 
716         let initial_secret =
717             derive_initial_secret(&dcid, crate::PROTOCOL_VERSION_V1);
718 
719         // Client.
720         assert!(
721             derive_client_initial_secret(&initial_secret, &mut secret).is_ok()
722         );
723         let expected_client_initial_secret = [
724             0xc0, 0x0c, 0xf1, 0x51, 0xca, 0x5b, 0xe0, 0x75, 0xed, 0x0e, 0xbf,
725             0xb5, 0xc8, 0x03, 0x23, 0xc4, 0x2d, 0x6b, 0x7d, 0xb6, 0x78, 0x81,
726             0x28, 0x9a, 0xf4, 0x00, 0x8f, 0x1f, 0x6c, 0x35, 0x7a, 0xea,
727         ];
728         assert_eq!(&secret, &expected_client_initial_secret);
729 
730         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
731         let expected_client_pkt_key = [
732             0x1f, 0x36, 0x96, 0x13, 0xdd, 0x76, 0xd5, 0x46, 0x77, 0x30, 0xef,
733             0xcb, 0xe3, 0xb1, 0xa2, 0x2d,
734         ];
735         assert_eq!(&pkt_key, &expected_client_pkt_key);
736 
737         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
738         let expected_client_pkt_iv = [
739             0xfa, 0x04, 0x4b, 0x2f, 0x42, 0xa3, 0xfd, 0x3b, 0x46, 0xfb, 0x25,
740             0x5c,
741         ];
742         assert_eq!(&pkt_iv, &expected_client_pkt_iv);
743 
744         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
745         let expected_client_hdr_key = [
746             0x9f, 0x50, 0x44, 0x9e, 0x04, 0xa0, 0xe8, 0x10, 0x28, 0x3a, 0x1e,
747             0x99, 0x33, 0xad, 0xed, 0xd2,
748         ];
749         assert_eq!(&hdr_key, &expected_client_hdr_key);
750 
751         // Server.
752         assert!(
753             derive_server_initial_secret(&initial_secret, &mut secret).is_ok()
754         );
755         let expected_server_initial_secret = [
756             0x3c, 0x19, 0x98, 0x28, 0xfd, 0x13, 0x9e, 0xfd, 0x21, 0x6c, 0x15,
757             0x5a, 0xd8, 0x44, 0xcc, 0x81, 0xfb, 0x82, 0xfa, 0x8d, 0x74, 0x46,
758             0xfa, 0x7d, 0x78, 0xbe, 0x80, 0x3a, 0xcd, 0xda, 0x95, 0x1b,
759         ];
760         assert_eq!(&secret, &expected_server_initial_secret);
761 
762         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
763         let expected_server_pkt_key = [
764             0xcf, 0x3a, 0x53, 0x31, 0x65, 0x3c, 0x36, 0x4c, 0x88, 0xf0, 0xf3,
765             0x79, 0xb6, 0x06, 0x7e, 0x37,
766         ];
767         assert_eq!(&pkt_key, &expected_server_pkt_key);
768 
769         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
770         let expected_server_pkt_iv = [
771             0x0a, 0xc1, 0x49, 0x3c, 0xa1, 0x90, 0x58, 0x53, 0xb0, 0xbb, 0xa0,
772             0x3e,
773         ];
774         assert_eq!(&pkt_iv, &expected_server_pkt_iv);
775 
776         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
777         let expected_server_hdr_key = [
778             0xc2, 0x06, 0xb8, 0xd9, 0xb9, 0xf0, 0xf3, 0x76, 0x44, 0x43, 0x0b,
779             0x49, 0x0e, 0xea, 0xa3, 0x14,
780         ];
781         assert_eq!(&hdr_key, &expected_server_hdr_key);
782     }
783 
784     #[test]
derive_initial_secrets_draft29()785     fn derive_initial_secrets_draft29() {
786         let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
787 
788         let mut secret = [0; 32];
789         let mut pkt_key = [0; 16];
790         let mut pkt_iv = [0; 12];
791         let mut hdr_key = [0; 16];
792 
793         let aead = Algorithm::AES128_GCM;
794 
795         let initial_secret =
796             derive_initial_secret(&dcid, crate::PROTOCOL_VERSION_DRAFT29);
797 
798         // Client.
799         assert!(
800             derive_client_initial_secret(&initial_secret, &mut secret).is_ok()
801         );
802         let expected_client_initial_secret = [
803             0x00, 0x88, 0x11, 0x92, 0x88, 0xf1, 0xd8, 0x66, 0x73, 0x3c, 0xee,
804             0xed, 0x15, 0xff, 0x9d, 0x50, 0x90, 0x2c, 0xf8, 0x29, 0x52, 0xee,
805             0xe2, 0x7e, 0x9d, 0x4d, 0x49, 0x18, 0xea, 0x37, 0x1d, 0x87,
806         ];
807         assert_eq!(&secret, &expected_client_initial_secret);
808 
809         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
810         let expected_client_pkt_key = [
811             0x17, 0x52, 0x57, 0xa3, 0x1e, 0xb0, 0x9d, 0xea, 0x93, 0x66, 0xd8,
812             0xbb, 0x79, 0xad, 0x80, 0xba,
813         ];
814         assert_eq!(&pkt_key, &expected_client_pkt_key);
815 
816         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
817         let expected_client_pkt_iv = [
818             0x6b, 0x26, 0x11, 0x4b, 0x9c, 0xba, 0x2b, 0x63, 0xa9, 0xe8, 0xdd,
819             0x4f,
820         ];
821         assert_eq!(&pkt_iv, &expected_client_pkt_iv);
822 
823         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
824         let expected_client_hdr_key = [
825             0x9d, 0xdd, 0x12, 0xc9, 0x94, 0xc0, 0x69, 0x8b, 0x89, 0x37, 0x4a,
826             0x9c, 0x07, 0x7a, 0x30, 0x77,
827         ];
828         assert_eq!(&hdr_key, &expected_client_hdr_key);
829 
830         // Server.
831         assert!(
832             derive_server_initial_secret(&initial_secret, &mut secret).is_ok()
833         );
834         let expected_server_initial_secret = [
835             0x00, 0x6f, 0x88, 0x13, 0x59, 0x24, 0x4d, 0xd9, 0xad, 0x1a, 0xcf,
836             0x85, 0xf5, 0x95, 0xba, 0xd6, 0x7c, 0x13, 0xf9, 0xf5, 0x58, 0x6f,
837             0x5e, 0x64, 0xe1, 0xac, 0xae, 0x1d, 0x9e, 0xa8, 0xf6, 0x16,
838         ];
839         assert_eq!(&secret, &expected_server_initial_secret);
840 
841         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
842         let expected_server_pkt_key = [
843             0x14, 0x9d, 0x0b, 0x16, 0x62, 0xab, 0x87, 0x1f, 0xbe, 0x63, 0xc4,
844             0x9b, 0x5e, 0x65, 0x5a, 0x5d,
845         ];
846         assert_eq!(&pkt_key, &expected_server_pkt_key);
847 
848         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
849         let expected_server_pkt_iv = [
850             0xba, 0xb2, 0xb1, 0x2a, 0x4c, 0x76, 0x01, 0x6a, 0xce, 0x47, 0x85,
851             0x6d,
852         ];
853         assert_eq!(&pkt_iv, &expected_server_pkt_iv);
854 
855         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
856         let expected_server_hdr_key = [
857             0xc0, 0xc4, 0x99, 0xa6, 0x5a, 0x60, 0x02, 0x4a, 0x18, 0xa2, 0x50,
858             0x97, 0x4e, 0xa0, 0x1d, 0xfa,
859         ];
860         assert_eq!(&hdr_key, &expected_server_hdr_key);
861     }
862 
863     #[test]
derive_initial_secrets_draft27()864     fn derive_initial_secrets_draft27() {
865         let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
866 
867         let mut secret = [0; 32];
868         let mut pkt_key = [0; 16];
869         let mut pkt_iv = [0; 12];
870         let mut hdr_key = [0; 16];
871 
872         let aead = Algorithm::AES128_GCM;
873 
874         let initial_secret =
875             derive_initial_secret(&dcid, crate::PROTOCOL_VERSION_DRAFT27);
876 
877         // Client.
878         assert!(
879             derive_client_initial_secret(&initial_secret, &mut secret).is_ok()
880         );
881         let expected_client_initial_secret = [
882             0xfd, 0xa3, 0x95, 0x3a, 0xec, 0xc0, 0x40, 0xe4, 0x8b, 0x34, 0xe2,
883             0x7e, 0xf8, 0x7d, 0xe3, 0xa6, 0x09, 0x8e, 0xcf, 0x0e, 0x38, 0xb7,
884             0xe0, 0x32, 0xc5, 0xc5, 0x7b, 0xcb, 0xd5, 0x97, 0x5b, 0x84,
885         ];
886         assert_eq!(&secret, &expected_client_initial_secret);
887 
888         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
889         let expected_client_pkt_key = [
890             0xaf, 0x7f, 0xd7, 0xef, 0xeb, 0xd2, 0x18, 0x78, 0xff, 0x66, 0x81,
891             0x12, 0x48, 0x98, 0x36, 0x94,
892         ];
893         assert_eq!(&pkt_key, &expected_client_pkt_key);
894 
895         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
896         let expected_client_pkt_iv = [
897             0x86, 0x81, 0x35, 0x94, 0x10, 0xa7, 0x0b, 0xb9, 0xc9, 0x2f, 0x04,
898             0x20,
899         ];
900         assert_eq!(&pkt_iv, &expected_client_pkt_iv);
901 
902         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
903         let expected_client_hdr_key = [
904             0xa9, 0x80, 0xb8, 0xb4, 0xfb, 0x7d, 0x9f, 0xbc, 0x13, 0xe8, 0x14,
905             0xc2, 0x31, 0x64, 0x25, 0x3d,
906         ];
907         assert_eq!(&hdr_key, &expected_client_hdr_key);
908 
909         // Server.
910         assert!(
911             derive_server_initial_secret(&initial_secret, &mut secret).is_ok()
912         );
913         let expected_server_initial_secret = [
914             0x55, 0x43, 0x66, 0xb8, 0x19, 0x12, 0xff, 0x90, 0xbe, 0x41, 0xf1,
915             0x7e, 0x80, 0x22, 0x21, 0x30, 0x90, 0xab, 0x17, 0xd8, 0x14, 0x91,
916             0x79, 0xbc, 0xad, 0xf2, 0x22, 0xf2, 0x9f, 0xf2, 0xdd, 0xd5,
917         ];
918         assert_eq!(&secret, &expected_server_initial_secret);
919 
920         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
921         let expected_server_pkt_key = [
922             0x5d, 0x51, 0xda, 0x9e, 0xe8, 0x97, 0xa2, 0x1b, 0x26, 0x59, 0xcc,
923             0xc7, 0xe5, 0xbf, 0xa5, 0x77,
924         ];
925         assert_eq!(&pkt_key, &expected_server_pkt_key);
926 
927         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
928         let expected_server_pkt_iv = [
929             0x5e, 0x5a, 0xe6, 0x51, 0xfd, 0x1e, 0x84, 0x95, 0xaf, 0x13, 0x50,
930             0x8b,
931         ];
932         assert_eq!(&pkt_iv, &expected_server_pkt_iv);
933 
934         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
935         let expected_server_hdr_key = [
936             0xa8, 0xed, 0x82, 0xe6, 0x66, 0x4f, 0x86, 0x5a, 0xed, 0xf6, 0x10,
937             0x69, 0x43, 0xf9, 0x5f, 0xb8,
938         ];
939         assert_eq!(&hdr_key, &expected_server_hdr_key);
940     }
941 
942     #[test]
derive_chacha20_secrets()943     fn derive_chacha20_secrets() {
944         let secret = [
945             0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42,
946             0x27, 0x48, 0xad, 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0,
947             0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3, 0x0f, 0x21, 0x63, 0x2b,
948         ];
949 
950         let aead = Algorithm::ChaCha20_Poly1305;
951 
952         let mut pkt_key = [0; 32];
953         let mut pkt_iv = [0; 12];
954         let mut hdr_key = [0; 32];
955 
956         assert!(derive_pkt_key(aead, &secret, &mut pkt_key).is_ok());
957         let expected_pkt_key = [
958             0xc6, 0xd9, 0x8f, 0xf3, 0x44, 0x1c, 0x3f, 0xe1, 0xb2, 0x18, 0x20,
959             0x94, 0xf6, 0x9c, 0xaa, 0x2e, 0xd4, 0xb7, 0x16, 0xb6, 0x54, 0x88,
960             0x96, 0x0a, 0x7a, 0x98, 0x49, 0x79, 0xfb, 0x23, 0xe1, 0xc8,
961         ];
962         assert_eq!(&pkt_key, &expected_pkt_key);
963 
964         assert!(derive_pkt_iv(aead, &secret, &mut pkt_iv).is_ok());
965         let expected_pkt_iv = [
966             0xe0, 0x45, 0x9b, 0x34, 0x74, 0xbd, 0xd0, 0xe4, 0x4a, 0x41, 0xc1,
967             0x44,
968         ];
969         assert_eq!(&pkt_iv, &expected_pkt_iv);
970 
971         assert!(derive_hdr_key(aead, &secret, &mut hdr_key).is_ok());
972         let expected_hdr_key = [
973             0x25, 0xa2, 0x82, 0xb9, 0xe8, 0x2f, 0x06, 0xf2, 0x1f, 0x48, 0x89,
974             0x17, 0xa4, 0xfc, 0x8f, 0x1b, 0x73, 0x57, 0x36, 0x85, 0x60, 0x85,
975             0x97, 0xd0, 0xef, 0xcb, 0x07, 0x6b, 0x0a, 0xb7, 0xa7, 0xa4,
976         ];
977         assert_eq!(&hdr_key, &expected_hdr_key);
978     }
979 }
980