1use crate::cipher::{Iv, IvLen, MessageDecrypter};
2use crate::common_state::{CommonState, Side};
3use crate::error::Error;
4use crate::msgs::base::PayloadU8;
5#[cfg(feature = "quic")]
6use crate::quic;
7#[cfg(feature = "secret_extraction")]
8use crate::suites::{ConnectionTrafficSecrets, PartiallyExtractedSecrets};
9use crate::{KeyLog, Tls13CipherSuite};
10
11use ring::{
13 aead,
14 digest::{self, Digest},
15 hkdf::{self, KeyType as _},
16 hmac,
17};
18
19use super::{Tls13MessageDecrypter, Tls13MessageEncrypter};
20
21#[derive(Debug, Clone, Copy, PartialEq)]
23enum SecretKind {
24 ResumptionPskBinderKey,
25 ClientEarlyTrafficSecret,
26 ClientHandshakeTrafficSecret,
27 ServerHandshakeTrafficSecret,
28 ClientApplicationTrafficSecret,
29 ServerApplicationTrafficSecret,
30 ExporterMasterSecret,
31 ResumptionMasterSecret,
32 DerivedSecret,
33}
34
35impl SecretKind {
36 fn to_bytes(self) -> &'static [u8] {
37 use self::SecretKind::*;
38 match self {
39 ResumptionPskBinderKey => b"res binder",
40 ClientEarlyTrafficSecret => b"c e traffic",
41 ClientHandshakeTrafficSecret => b"c hs traffic",
42 ServerHandshakeTrafficSecret => b"s hs traffic",
43 ClientApplicationTrafficSecret => b"c ap traffic",
44 ServerApplicationTrafficSecret => b"s ap traffic",
45 ExporterMasterSecret => b"exp master",
46 ResumptionMasterSecret => b"res master",
47 DerivedSecret => b"derived",
48 }
49 }
50
51 fn log_label(self) -> Option<&'static str> {
52 use self::SecretKind::*;
53 Some(match self {
54 ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
55 ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
56 ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
57 ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
58 ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
59 ExporterMasterSecret => "EXPORTER_SECRET",
60 _ => {
61 return None;
62 }
63 })
64 }
65}
66
67struct KeySchedule {
71 current: hkdf::Prk,
72 suite: &'static Tls13CipherSuite,
73}
74
75pub(crate) struct KeyScheduleEarly {
83 ks: KeySchedule,
84}
85
86impl KeyScheduleEarly {
87 pub(crate) fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
88 Self {
89 ks: KeySchedule::new(suite, secret),
90 }
91 }
92
93 pub(crate) fn client_early_traffic_secret(
94 &self,
95 hs_hash: &Digest,
96 key_log: &dyn KeyLog,
97 client_random: &[u8; 32],
98 common: &mut CommonState,
99 ) {
100 let client_early_traffic_secret = self.ks.derive_logged_secret(
101 SecretKind::ClientEarlyTrafficSecret,
102 hs_hash.as_ref(),
103 key_log,
104 client_random,
105 );
106
107 match common.side {
108 Side::Client => self
109 .ks
110 .set_encrypter(&client_early_traffic_secret, common),
111 Side::Server => self
112 .ks
113 .set_decrypter(&client_early_traffic_secret, common),
114 }
115
116 #[cfg(feature = "quic")]
117 if common.is_quic() {
118 common.quic.early_secret = Some(client_early_traffic_secret);
121 }
122 }
123
124 pub(crate) fn resumption_psk_binder_key_and_sign_verify_data(
125 &self,
126 hs_hash: &Digest,
127 ) -> hmac::Tag {
128 let resumption_psk_binder_key = self
129 .ks
130 .derive_for_empty_hash(SecretKind::ResumptionPskBinderKey);
131 self.ks
132 .sign_verify_data(&resumption_psk_binder_key, hs_hash)
133 }
134}
135
136pub(crate) struct KeySchedulePreHandshake {
141 ks: KeySchedule,
142}
143
144impl KeySchedulePreHandshake {
145 pub(crate) fn new(suite: &'static Tls13CipherSuite) -> Self {
146 Self {
147 ks: KeySchedule::new_with_empty_secret(suite),
148 }
149 }
150
151 pub(crate) fn into_handshake(mut self, secret: &[u8]) -> KeyScheduleHandshakeStart {
152 self.ks.input_secret(secret);
153 KeyScheduleHandshakeStart { ks: self.ks }
154 }
155}
156
157impl From<KeyScheduleEarly> for KeySchedulePreHandshake {
158 fn from(KeyScheduleEarly { ks }: KeyScheduleEarly) -> Self {
159 Self { ks }
160 }
161}
162
163pub(crate) struct KeyScheduleHandshakeStart {
165 ks: KeySchedule,
166}
167
168impl KeyScheduleHandshakeStart {
169 pub(crate) fn derive_client_handshake_secrets(
170 mut self,
171 early_data_enabled: bool,
172 hs_hash: Digest,
173 suite: &'static Tls13CipherSuite,
174 key_log: &dyn KeyLog,
175 client_random: &[u8; 32],
176 common: &mut CommonState,
177 ) -> KeyScheduleHandshake {
178 debug_assert_eq!(common.side, Side::Client);
179 self.ks.suite = suite;
181 let new = self.into_handshake(hs_hash, key_log, client_random, common);
182
183 new.ks
185 .set_decrypter(&new.server_handshake_traffic_secret, common);
186
187 if !early_data_enabled {
188 new.ks
190 .set_encrypter(&new.client_handshake_traffic_secret, common);
191 }
192
193 new
194 }
195
196 pub(crate) fn derive_server_handshake_secrets(
197 self,
198 hs_hash: Digest,
199 key_log: &dyn KeyLog,
200 client_random: &[u8; 32],
201 common: &mut CommonState,
202 ) -> KeyScheduleHandshake {
203 debug_assert_eq!(common.side, Side::Server);
204 let new = self.into_handshake(hs_hash, key_log, client_random, common);
205
206 new.ks
210 .set_encrypter(&new.server_handshake_traffic_secret, common);
211 new
212 }
213
214 fn into_handshake(
215 self,
216 hs_hash: Digest,
217 key_log: &dyn KeyLog,
218 client_random: &[u8; 32],
219 _common: &mut CommonState,
220 ) -> KeyScheduleHandshake {
221 let client_secret = self.ks.derive_logged_secret(
223 SecretKind::ClientHandshakeTrafficSecret,
224 hs_hash.as_ref(),
225 key_log,
226 client_random,
227 );
228
229 let server_secret = self.ks.derive_logged_secret(
230 SecretKind::ServerHandshakeTrafficSecret,
231 hs_hash.as_ref(),
232 key_log,
233 client_random,
234 );
235
236 #[cfg(feature = "quic")]
237 if _common.is_quic() {
238 _common.quic.hs_secrets = Some(quic::Secrets::new(
239 client_secret.clone(),
240 server_secret.clone(),
241 self.ks.suite,
242 _common.side,
243 _common.quic.version,
244 ));
245 }
246
247 KeyScheduleHandshake {
248 ks: self.ks,
249 client_handshake_traffic_secret: client_secret,
250 server_handshake_traffic_secret: server_secret,
251 }
252 }
253}
254
255pub(crate) struct KeyScheduleHandshake {
256 ks: KeySchedule,
257 client_handshake_traffic_secret: hkdf::Prk,
258 server_handshake_traffic_secret: hkdf::Prk,
259}
260
261impl KeyScheduleHandshake {
262 pub(crate) fn sign_server_finish(&self, hs_hash: &Digest) -> hmac::Tag {
263 self.ks
264 .sign_finish(&self.server_handshake_traffic_secret, hs_hash)
265 }
266
267 pub(crate) fn set_handshake_encrypter(&self, common: &mut CommonState) {
268 debug_assert_eq!(common.side, Side::Client);
269 self.ks
270 .set_encrypter(&self.client_handshake_traffic_secret, common);
271 }
272
273 pub(crate) fn set_handshake_decrypter(
274 &self,
275 skip_requested: Option<usize>,
276 common: &mut CommonState,
277 ) {
278 debug_assert_eq!(common.side, Side::Server);
279 let secret = &self.client_handshake_traffic_secret;
280 match skip_requested {
281 None => self.ks.set_decrypter(secret, common),
282 Some(max_early_data_size) => common
283 .record_layer
284 .set_message_decrypter_with_trial_decryption(
285 self.ks
286 .derive_decrypter(&self.client_handshake_traffic_secret),
287 max_early_data_size,
288 ),
289 }
290 }
291
292 pub(crate) fn into_traffic_with_client_finished_pending(
293 self,
294 hs_hash: Digest,
295 key_log: &dyn KeyLog,
296 client_random: &[u8; 32],
297 common: &mut CommonState,
298 ) -> KeyScheduleTrafficWithClientFinishedPending {
299 debug_assert_eq!(common.side, Side::Server);
300
301 let traffic = KeyScheduleTraffic::new(self.ks, hs_hash, key_log, client_random);
302 let (_client_secret, server_secret) = (
303 &traffic.current_client_traffic_secret,
304 &traffic.current_server_traffic_secret,
305 );
306
307 traffic
308 .ks
309 .set_encrypter(server_secret, common);
310
311 #[cfg(feature = "quic")]
312 if common.is_quic() {
313 common.quic.traffic_secrets = Some(quic::Secrets::new(
314 _client_secret.clone(),
315 server_secret.clone(),
316 traffic.ks.suite,
317 common.side,
318 common.quic.version,
319 ));
320 }
321
322 KeyScheduleTrafficWithClientFinishedPending {
323 handshake_client_traffic_secret: self.client_handshake_traffic_secret,
324 traffic,
325 }
326 }
327
328 pub(crate) fn into_pre_finished_client_traffic(
329 self,
330 pre_finished_hash: Digest,
331 handshake_hash: Digest,
332 key_log: &dyn KeyLog,
333 client_random: &[u8; 32],
334 ) -> (KeyScheduleClientBeforeFinished, hmac::Tag) {
335 let traffic = KeyScheduleTraffic::new(self.ks, pre_finished_hash, key_log, client_random);
336 let tag = traffic
337 .ks
338 .sign_finish(&self.client_handshake_traffic_secret, &handshake_hash);
339 (KeyScheduleClientBeforeFinished { traffic }, tag)
340 }
341}
342
343pub(crate) struct KeyScheduleClientBeforeFinished {
344 traffic: KeyScheduleTraffic,
345}
346
347impl KeyScheduleClientBeforeFinished {
348 pub(crate) fn into_traffic(self, common: &mut CommonState) -> KeyScheduleTraffic {
349 debug_assert_eq!(common.side, Side::Client);
350 let (client_secret, server_secret) = (
351 &self
352 .traffic
353 .current_client_traffic_secret,
354 &self
355 .traffic
356 .current_server_traffic_secret,
357 );
358
359 self.traffic
360 .ks
361 .set_decrypter(server_secret, common);
362 self.traffic
363 .ks
364 .set_encrypter(client_secret, common);
365
366 #[cfg(feature = "quic")]
367 if common.is_quic() {
368 common.quic.traffic_secrets = Some(quic::Secrets::new(
369 client_secret.clone(),
370 server_secret.clone(),
371 self.traffic.ks.suite,
372 common.side,
373 common.quic.version,
374 ));
375 }
376
377 self.traffic
378 }
379}
380
381pub(crate) struct KeyScheduleTrafficWithClientFinishedPending {
385 handshake_client_traffic_secret: hkdf::Prk,
386 traffic: KeyScheduleTraffic,
387}
388
389impl KeyScheduleTrafficWithClientFinishedPending {
390 pub(crate) fn update_decrypter(&self, common: &mut CommonState) {
391 debug_assert_eq!(common.side, Side::Server);
392 self.traffic
393 .ks
394 .set_decrypter(&self.handshake_client_traffic_secret, common);
395 }
396
397 pub(crate) fn sign_client_finish(
398 self,
399 hs_hash: &Digest,
400 common: &mut CommonState,
401 ) -> (KeyScheduleTraffic, hmac::Tag) {
402 debug_assert_eq!(common.side, Side::Server);
403 let tag = self
404 .traffic
405 .ks
406 .sign_finish(&self.handshake_client_traffic_secret, hs_hash);
407
408 self.traffic.ks.set_decrypter(
410 &self
411 .traffic
412 .current_client_traffic_secret,
413 common,
414 );
415
416 (self.traffic, tag)
417 }
418}
419
420pub(crate) struct KeyScheduleTraffic {
423 ks: KeySchedule,
424 current_client_traffic_secret: hkdf::Prk,
425 current_server_traffic_secret: hkdf::Prk,
426 current_exporter_secret: hkdf::Prk,
427}
428
429impl KeyScheduleTraffic {
430 fn new(
431 mut ks: KeySchedule,
432 hs_hash: Digest,
433 key_log: &dyn KeyLog,
434 client_random: &[u8; 32],
435 ) -> Self {
436 ks.input_empty();
437
438 let current_client_traffic_secret = ks.derive_logged_secret(
439 SecretKind::ClientApplicationTrafficSecret,
440 hs_hash.as_ref(),
441 key_log,
442 client_random,
443 );
444
445 let current_server_traffic_secret = ks.derive_logged_secret(
446 SecretKind::ServerApplicationTrafficSecret,
447 hs_hash.as_ref(),
448 key_log,
449 client_random,
450 );
451
452 let current_exporter_secret = ks.derive_logged_secret(
453 SecretKind::ExporterMasterSecret,
454 hs_hash.as_ref(),
455 key_log,
456 client_random,
457 );
458
459 Self {
460 ks,
461 current_client_traffic_secret,
462 current_server_traffic_secret,
463 current_exporter_secret,
464 }
465 }
466
467 pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) {
468 let secret = self.next_application_traffic_secret(common.side);
469 common.enqueue_key_update_notification();
470 self.ks.set_encrypter(&secret, common);
471 }
472
473 pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
474 let secret = self.next_application_traffic_secret(common.side.peer());
475 self.ks.set_decrypter(&secret, common);
476 }
477
478 pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> hkdf::Prk {
479 let current = match side {
480 Side::Client => &mut self.current_client_traffic_secret,
481 Side::Server => &mut self.current_server_traffic_secret,
482 };
483
484 let secret = self.ks.derive_next(current);
485 *current = secret.clone();
486 secret
487 }
488
489 pub(crate) fn resumption_master_secret_and_derive_ticket_psk(
490 &self,
491 hs_hash: &Digest,
492 nonce: &[u8],
493 ) -> Vec<u8> {
494 let resumption_master_secret = self.ks.derive(
495 self.ks.algorithm(),
496 SecretKind::ResumptionMasterSecret,
497 hs_hash.as_ref(),
498 );
499 self.ks
500 .derive_ticket_psk(&resumption_master_secret, nonce)
501 }
502
503 pub(crate) fn export_keying_material(
504 &self,
505 out: &mut [u8],
506 label: &[u8],
507 context: Option<&[u8]>,
508 ) -> Result<(), Error> {
509 self.ks
510 .export_keying_material(&self.current_exporter_secret, out, label, context)
511 }
512
513 #[cfg(feature = "secret_extraction")]
514 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
515 fn expand<const KEY_LEN: usize, const IV_LEN: usize>(
516 secret: &hkdf::Prk,
517 ) -> Result<([u8; KEY_LEN], [u8; IV_LEN]), Error> {
518 let mut key = [0u8; KEY_LEN];
519 let mut iv = [0u8; IV_LEN];
520
521 hkdf_expand_info(secret, PayloadU8Len(key.len()), b"key", &[], |okm| {
522 okm.fill(&mut key)
523 })
524 .map_err(|_| Error::General("hkdf_expand_info failed".to_string()))?;
525
526 hkdf_expand_info(secret, PayloadU8Len(iv.len()), b"iv", &[], |okm| {
527 okm.fill(&mut iv)
528 })
529 .map_err(|_| Error::General("hkdf_expand_info failed".to_string()))?;
530
531 Ok((key, iv))
532 }
533
534 let client_secrets;
535 let server_secrets;
536
537 let algo = self.ks.suite.common.aead_algorithm;
538 if algo == &aead::AES_128_GCM {
539 let extract = |secret: &hkdf::Prk| -> Result<ConnectionTrafficSecrets, Error> {
540 let (key, iv_in) = expand::<16, 12>(secret)?;
541
542 let mut salt = [0u8; 4];
543 salt.copy_from_slice(&iv_in[..4]);
544
545 let mut iv = [0u8; 8];
546 iv.copy_from_slice(&iv_in[4..]);
547
548 Ok(ConnectionTrafficSecrets::Aes128Gcm { key, salt, iv })
549 };
550
551 client_secrets = extract(&self.current_client_traffic_secret)?;
552 server_secrets = extract(&self.current_server_traffic_secret)?;
553 } else if algo == &aead::AES_256_GCM {
554 let extract = |secret: &hkdf::Prk| -> Result<ConnectionTrafficSecrets, Error> {
555 let (key, iv_in) = expand::<32, 12>(secret)?;
556
557 let mut salt = [0u8; 4];
558 salt.copy_from_slice(&iv_in[..4]);
559
560 let mut iv = [0u8; 8];
561 iv.copy_from_slice(&iv_in[4..]);
562
563 Ok(ConnectionTrafficSecrets::Aes256Gcm { key, salt, iv })
564 };
565
566 client_secrets = extract(&self.current_client_traffic_secret)?;
567 server_secrets = extract(&self.current_server_traffic_secret)?;
568 } else if algo == &aead::CHACHA20_POLY1305 {
569 let extract = |secret: &hkdf::Prk| -> Result<ConnectionTrafficSecrets, Error> {
570 let (key, iv) = expand::<32, 12>(secret)?;
571 Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
572 };
573
574 client_secrets = extract(&self.current_client_traffic_secret)?;
575 server_secrets = extract(&self.current_server_traffic_secret)?;
576 } else {
577 return Err(Error::General(format!(
578 "exporting secrets for {:?}: unimplemented",
579 algo
580 )));
581 }
582
583 let (tx, rx) = match side {
584 Side::Client => (client_secrets, server_secrets),
585 Side::Server => (server_secrets, client_secrets),
586 };
587 Ok(PartiallyExtractedSecrets { tx, rx })
588 }
589}
590
591impl KeySchedule {
592 fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
593 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
594 let salt = hkdf::Salt::new(suite.hkdf_algorithm, &zeroes[..suite.hkdf_algorithm.len()]);
595 Self {
596 current: salt.extract(secret),
597 suite,
598 }
599 }
600
601 fn set_encrypter(&self, secret: &hkdf::Prk, common: &mut CommonState) {
602 let key = derive_traffic_key(secret, self.suite.common.aead_algorithm);
603 let iv = derive_traffic_iv(secret);
604
605 common
606 .record_layer
607 .set_message_encrypter(Box::new(Tls13MessageEncrypter {
608 enc_key: aead::LessSafeKey::new(key),
609 iv,
610 }));
611 }
612
613 fn set_decrypter(&self, secret: &hkdf::Prk, common: &mut CommonState) {
614 common
615 .record_layer
616 .set_message_decrypter(self.derive_decrypter(secret));
617 }
618
619 fn derive_decrypter(&self, secret: &hkdf::Prk) -> Box<dyn MessageDecrypter> {
620 let key = derive_traffic_key(secret, self.suite.common.aead_algorithm);
621 let iv = derive_traffic_iv(secret);
622 Box::new(Tls13MessageDecrypter {
623 dec_key: aead::LessSafeKey::new(key),
624 iv,
625 })
626 }
627
628 #[inline]
629 fn algorithm(&self) -> hkdf::Algorithm {
630 self.suite.hkdf_algorithm
631 }
632
633 fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
634 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
635 Self::new(suite, &zeroes[..suite.hkdf_algorithm.len()])
636 }
637
638 fn input_empty(&mut self) {
640 let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
641 self.input_secret(&zeroes[..self.suite.hkdf_algorithm.len()]);
642 }
643
644 fn input_secret(&mut self, secret: &[u8]) {
646 let salt: hkdf::Salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
647 self.current = salt.extract(secret);
648 }
649
650 fn derive<T, L>(&self, key_type: L, kind: SecretKind, hs_hash: &[u8]) -> T
652 where
653 T: for<'a> From<hkdf::Okm<'a, L>>,
654 L: hkdf::KeyType,
655 {
656 hkdf_expand(&self.current, key_type, kind.to_bytes(), hs_hash)
657 }
658
659 fn derive_logged_secret(
660 &self,
661 kind: SecretKind,
662 hs_hash: &[u8],
663 key_log: &dyn KeyLog,
664 client_random: &[u8; 32],
665 ) -> hkdf::Prk {
666 let log_label = kind
667 .log_label()
668 .expect("not a loggable secret");
669 if key_log.will_log(log_label) {
670 let secret = self
671 .derive::<PayloadU8, _>(
672 PayloadU8Len(self.suite.hkdf_algorithm.len()),
673 kind,
674 hs_hash,
675 )
676 .into_inner();
677 key_log.log(log_label, client_random, &secret);
678 }
679 self.derive(self.suite.hkdf_algorithm, kind, hs_hash)
680 }
681
682 fn derive_for_empty_hash<T>(&self, kind: SecretKind) -> T
687 where
688 T: for<'a> From<hkdf::Okm<'a, hkdf::Algorithm>>,
689 {
690 let digest_alg = self
691 .suite
692 .hkdf_algorithm
693 .hmac_algorithm()
694 .digest_algorithm();
695 let empty_hash = digest::digest(digest_alg, &[]);
696 self.derive(self.suite.hkdf_algorithm, kind, empty_hash.as_ref())
697 }
698
699 fn sign_finish(&self, base_key: &hkdf::Prk, hs_hash: &Digest) -> hmac::Tag {
702 self.sign_verify_data(base_key, hs_hash)
703 }
704
705 fn sign_verify_data(&self, base_key: &hkdf::Prk, hs_hash: &Digest) -> hmac::Tag {
708 let hmac_alg = self
709 .suite
710 .hkdf_algorithm
711 .hmac_algorithm();
712 let hmac_key = hkdf_expand(base_key, hmac_alg, b"finished", &[]);
713 hmac::sign(&hmac_key, hs_hash.as_ref())
714 }
715
716 fn derive_next(&self, base_key: &hkdf::Prk) -> hkdf::Prk {
718 hkdf_expand(base_key, self.suite.hkdf_algorithm, b"traffic upd", &[])
719 }
720
721 fn derive_ticket_psk(&self, rms: &hkdf::Prk, nonce: &[u8]) -> Vec<u8> {
724 let payload: PayloadU8 = hkdf_expand(
725 rms,
726 PayloadU8Len(self.suite.hkdf_algorithm.len()),
727 b"resumption",
728 nonce,
729 );
730 payload.into_inner()
731 }
732
733 fn export_keying_material(
734 &self,
735 current_exporter_secret: &hkdf::Prk,
736 out: &mut [u8],
737 label: &[u8],
738 context: Option<&[u8]>,
739 ) -> Result<(), Error> {
740 let digest_alg = self
741 .suite
742 .hkdf_algorithm
743 .hmac_algorithm()
744 .digest_algorithm();
745
746 let h_empty = digest::digest(digest_alg, &[]);
747 let secret: hkdf::Prk = hkdf_expand(
748 current_exporter_secret,
749 self.suite.hkdf_algorithm,
750 label,
751 h_empty.as_ref(),
752 );
753
754 let h_context = digest::digest(digest_alg, context.unwrap_or(&[]));
755
756 hkdf_expand_info(
758 &secret,
759 PayloadU8Len(out.len()),
760 b"exporter",
761 h_context.as_ref(),
762 |okm| okm.fill(out),
763 )
764 .map_err(|_| Error::General("exporting too much".to_string()))
765 }
766}
767
768pub(crate) fn hkdf_expand<T, L>(secret: &hkdf::Prk, key_type: L, label: &[u8], context: &[u8]) -> T
769where
770 T: for<'a> From<hkdf::Okm<'a, L>>,
771 L: hkdf::KeyType,
772{
773 hkdf_expand_info(secret, key_type, label, context, |okm| okm.into())
774}
775
776fn hkdf_expand_info<F, T, L>(
777 secret: &hkdf::Prk,
778 key_type: L,
779 label: &[u8],
780 context: &[u8],
781 f: F,
782) -> T
783where
784 F: for<'b> FnOnce(hkdf::Okm<'b, L>) -> T,
785 L: hkdf::KeyType,
786{
787 const LABEL_PREFIX: &[u8] = b"tls13 ";
788
789 let output_len = u16::to_be_bytes(key_type.len() as u16);
790 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
791 let context_len = u8::to_be_bytes(context.len() as u8);
792
793 let info = &[
794 &output_len[..],
795 &label_len[..],
796 LABEL_PREFIX,
797 label,
798 &context_len[..],
799 context,
800 ];
801 let okm = secret.expand(info, key_type).unwrap();
802
803 f(okm)
804}
805
806pub(crate) struct PayloadU8Len(pub(crate) usize);
807impl hkdf::KeyType for PayloadU8Len {
808 fn len(&self) -> usize {
809 self.0
810 }
811}
812
813impl From<hkdf::Okm<'_, PayloadU8Len>> for PayloadU8 {
814 fn from(okm: hkdf::Okm<PayloadU8Len>) -> Self {
815 let mut r = vec![0u8; okm.len().0];
816 okm.fill(&mut r[..]).unwrap();
817 Self::new(r)
818 }
819}
820
821pub(crate) fn derive_traffic_key(
822 secret: &hkdf::Prk,
823 aead_algorithm: &'static aead::Algorithm,
824) -> aead::UnboundKey {
825 hkdf_expand(secret, aead_algorithm, b"key", &[])
826}
827
828pub(crate) fn derive_traffic_iv(secret: &hkdf::Prk) -> Iv {
829 hkdf_expand(secret, IvLen, b"iv", &[])
830}
831
832#[cfg(test)]
833mod test {
834 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
835 use crate::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
836 use crate::KeyLog;
837 use ring::aead;
838
839 #[test]
840 fn test_vectors() {
841 let hs_start_hash = [
843 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
844 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
845 0x75, 0x88, 0x1c, 0x0a,
846 ];
847
848 let hs_full_hash = [
849 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
850 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
851 0xbb, 0xeb, 0x23, 0xe2,
852 ];
853
854 let ecdhe_secret = [
855 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
856 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
857 0x71, 0xdf, 0x4b, 0x40,
858 ];
859
860 let client_hts = [
861 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
862 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
863 0x35, 0xcf, 0x46, 0xab,
864 ];
865
866 let client_hts_key = [
867 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
868 0x85, 0xa7,
869 ];
870
871 let client_hts_iv = [
872 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
873 ];
874
875 let server_hts = [
876 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
877 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
878 0x29, 0xa8, 0x87, 0x59,
879 ];
880
881 let server_hts_key = [
882 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
883 0xbc, 0x54,
884 ];
885
886 let server_hts_iv = [
887 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
888 ];
889
890 let client_ats = [
891 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
892 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
893 0x20, 0x6d, 0xbd, 0xa5,
894 ];
895
896 let client_ats_key = [
897 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
898 0x57, 0x2e,
899 ];
900
901 let client_ats_iv = [
902 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
903 ];
904
905 let server_ats = [
906 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
907 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
908 0x4c, 0x23, 0x21, 0x92,
909 ];
910
911 let server_ats_key = [
912 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
913 0x2b, 0xb3,
914 ];
915
916 let server_ats_iv = [
917 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
918 ];
919
920 let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
921 ks.input_secret(&ecdhe_secret);
922
923 assert_traffic_secret(
924 &ks,
925 SecretKind::ClientHandshakeTrafficSecret,
926 &hs_start_hash,
927 &client_hts,
928 &client_hts_key,
929 &client_hts_iv,
930 );
931
932 assert_traffic_secret(
933 &ks,
934 SecretKind::ServerHandshakeTrafficSecret,
935 &hs_start_hash,
936 &server_hts,
937 &server_hts_key,
938 &server_hts_iv,
939 );
940
941 ks.input_empty();
942
943 assert_traffic_secret(
944 &ks,
945 SecretKind::ClientApplicationTrafficSecret,
946 &hs_full_hash,
947 &client_ats,
948 &client_ats_key,
949 &client_ats_iv,
950 );
951
952 assert_traffic_secret(
953 &ks,
954 SecretKind::ServerApplicationTrafficSecret,
955 &hs_full_hash,
956 &server_ats,
957 &server_ats_key,
958 &server_ats_iv,
959 );
960 }
961
962 fn assert_traffic_secret(
963 ks: &KeySchedule,
964 kind: SecretKind,
965 hash: &[u8],
966 expected_traffic_secret: &[u8],
967 expected_key: &[u8],
968 expected_iv: &[u8],
969 ) {
970 struct Log<'a>(&'a [u8]);
971 impl KeyLog for Log<'_> {
972 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
973 assert_eq!(self.0, secret);
974 }
975 }
976 let log = Log(expected_traffic_secret);
977 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
978
979 let aead_alg = &aead::AES_128_GCM;
981 let key = derive_traffic_key(&traffic_secret, aead_alg);
982 let seal_output = seal_zeroes(key);
983 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
984 let expected_seal_output = seal_zeroes(expected_key);
985 assert_eq!(seal_output, expected_seal_output);
986 assert!(seal_output.len() >= 48); let iv = derive_traffic_iv(&traffic_secret);
989 assert_eq!(iv.value(), expected_iv);
990 }
991
992 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
993 let key = aead::LessSafeKey::new(key);
994 let mut seal_output = vec![0; 32];
995 key.seal_in_place_append_tag(
996 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
997 aead::Aad::empty(),
998 &mut seal_output,
999 )
1000 .unwrap();
1001 seal_output
1002 }
1003}
1004
1005#[cfg(bench)]
1006mod benchmarks {
1007 #[bench]
1008 fn bench_sha256(b: &mut test::Bencher) {
1009 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
1010 use crate::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1011 use crate::KeyLog;
1012 use ring::aead;
1013
1014 fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1015 struct Log;
1016
1017 impl KeyLog for Log {
1018 fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1019 }
1020
1021 let aead_alg = &aead::CHACHA20_POLY1305;
1022 let hash = [0u8; 32];
1023 let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1024 test::black_box(derive_traffic_key(&traffic_secret, aead_alg));
1025 test::black_box(derive_traffic_iv(&traffic_secret));
1026 }
1027
1028 b.iter(|| {
1029 let mut ks =
1030 KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1031 ks.input_secret(&[0u8; 32]);
1032
1033 extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1034 extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1035
1036 ks.input_empty();
1037
1038 extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1039 extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1040 });
1041 }
1042}