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