1use alloc::boxed::Box;
2use alloc::string::ToString;
3
4use crate::common_state::{CommonState, Side};
5use crate::crypto::cipher::{AeadKey, Iv, MessageDecrypter};
6use crate::crypto::tls13::{expand, Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
7use crate::crypto::{hash, hmac, SharedSecret};
8use crate::error::Error;
9use crate::msgs::message::Message;
10use crate::suites::PartiallyExtractedSecrets;
11use crate::{quic, KeyLog, Tls13CipherSuite};
12
13#[derive(Debug, Clone, Copy, PartialEq)]
17enum SecretKind {
18 ResumptionPskBinderKey,
19 ClientEarlyTrafficSecret,
20 ClientHandshakeTrafficSecret,
21 ServerHandshakeTrafficSecret,
22 ClientApplicationTrafficSecret,
23 ServerApplicationTrafficSecret,
24 ExporterMasterSecret,
25 ResumptionMasterSecret,
26 DerivedSecret,
27 ServerEchConfirmationSecret,
28 ServerEchHrrConfirmationSecret,
29}
30
31impl SecretKind {
32 fn to_bytes(self) -> &'static [u8] {
33 use self::SecretKind::*;
34 match self {
35 ResumptionPskBinderKey => b"res binder",
36 ClientEarlyTrafficSecret => b"c e traffic",
37 ClientHandshakeTrafficSecret => b"c hs traffic",
38 ServerHandshakeTrafficSecret => b"s hs traffic",
39 ClientApplicationTrafficSecret => b"c ap traffic",
40 ServerApplicationTrafficSecret => b"s ap traffic",
41 ExporterMasterSecret => b"exp master",
42 ResumptionMasterSecret => b"res master",
43 DerivedSecret => b"derived",
44 ServerEchConfirmationSecret => b"ech accept confirmation",
46 ServerEchHrrConfirmationSecret => b"hrr ech accept confirmation",
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: Box<dyn HkdfExpander>,
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: &hash::Output,
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 if common.is_quic() {
117 common.quic.early_secret = Some(client_early_traffic_secret);
120 }
121 }
122
123 pub(crate) fn resumption_psk_binder_key_and_sign_verify_data(
124 &self,
125 hs_hash: &hash::Output,
126 ) -> hmac::Tag {
127 let resumption_psk_binder_key = self
128 .ks
129 .derive_for_empty_hash(SecretKind::ResumptionPskBinderKey);
130 self.ks
131 .sign_verify_data(&resumption_psk_binder_key, hs_hash)
132 }
133}
134
135pub(crate) struct KeySchedulePreHandshake {
140 ks: KeySchedule,
141}
142
143impl KeySchedulePreHandshake {
144 pub(crate) fn new(suite: &'static Tls13CipherSuite) -> Self {
145 Self {
146 ks: KeySchedule::new_with_empty_secret(suite),
147 }
148 }
149
150 pub(crate) fn into_handshake(
151 mut self,
152 shared_secret: SharedSecret,
153 ) -> KeyScheduleHandshakeStart {
154 self.ks
155 .input_secret(shared_secret.secret_bytes());
156 KeyScheduleHandshakeStart { ks: self.ks }
157 }
158}
159
160impl From<KeyScheduleEarly> for KeySchedulePreHandshake {
161 fn from(KeyScheduleEarly { ks }: KeyScheduleEarly) -> Self {
162 Self { ks }
163 }
164}
165
166pub(crate) struct KeyScheduleHandshakeStart {
168 ks: KeySchedule,
169}
170
171impl KeyScheduleHandshakeStart {
172 pub(crate) fn derive_client_handshake_secrets(
173 mut self,
174 early_data_enabled: bool,
175 hs_hash: hash::Output,
176 suite: &'static Tls13CipherSuite,
177 key_log: &dyn KeyLog,
178 client_random: &[u8; 32],
179 common: &mut CommonState,
180 ) -> KeyScheduleHandshake {
181 debug_assert_eq!(common.side, Side::Client);
182 self.ks.suite = suite;
184 let new = self.into_handshake(hs_hash, key_log, client_random, common);
185
186 new.ks
188 .set_decrypter(&new.server_handshake_traffic_secret, common);
189
190 if !early_data_enabled {
191 new.ks
193 .set_encrypter(&new.client_handshake_traffic_secret, common);
194 }
195
196 new
197 }
198
199 pub(crate) fn derive_server_handshake_secrets(
200 self,
201 hs_hash: hash::Output,
202 key_log: &dyn KeyLog,
203 client_random: &[u8; 32],
204 common: &mut CommonState,
205 ) -> KeyScheduleHandshake {
206 debug_assert_eq!(common.side, Side::Server);
207 let new = self.into_handshake(hs_hash, key_log, client_random, common);
208
209 new.ks
213 .set_encrypter(&new.server_handshake_traffic_secret, common);
214 new
215 }
216
217 pub(crate) fn server_ech_confirmation_secret(
218 &mut self,
219 client_hello_inner_random: &[u8],
220 hs_hash: hash::Output,
221 ) -> [u8; 8] {
222 hkdf_expand_label(
231 self.ks
232 .suite
233 .hkdf_provider
234 .extract_from_secret(None, client_hello_inner_random)
235 .as_ref(),
236 SecretKind::ServerEchConfirmationSecret.to_bytes(),
237 hs_hash.as_ref(),
238 )
239 }
240
241 fn into_handshake(
242 self,
243 hs_hash: hash::Output,
244 key_log: &dyn KeyLog,
245 client_random: &[u8; 32],
246 common: &mut CommonState,
247 ) -> KeyScheduleHandshake {
248 let client_secret = self.ks.derive_logged_secret(
250 SecretKind::ClientHandshakeTrafficSecret,
251 hs_hash.as_ref(),
252 key_log,
253 client_random,
254 );
255
256 let server_secret = self.ks.derive_logged_secret(
257 SecretKind::ServerHandshakeTrafficSecret,
258 hs_hash.as_ref(),
259 key_log,
260 client_random,
261 );
262
263 if common.is_quic() {
264 common.quic.hs_secrets = Some(quic::Secrets::new(
265 client_secret.clone(),
266 server_secret.clone(),
267 self.ks.suite,
268 self.ks.suite.quic.unwrap(),
269 common.side,
270 common.quic.version,
271 ));
272 }
273
274 KeyScheduleHandshake {
275 ks: self.ks,
276 client_handshake_traffic_secret: client_secret,
277 server_handshake_traffic_secret: server_secret,
278 }
279 }
280}
281
282pub(crate) struct KeyScheduleHandshake {
283 ks: KeySchedule,
284 client_handshake_traffic_secret: OkmBlock,
285 server_handshake_traffic_secret: OkmBlock,
286}
287
288impl KeyScheduleHandshake {
289 pub(crate) fn sign_server_finish(&self, hs_hash: &hash::Output) -> hmac::Tag {
290 self.ks
291 .sign_finish(&self.server_handshake_traffic_secret, hs_hash)
292 }
293
294 pub(crate) fn set_handshake_encrypter(&self, common: &mut CommonState) {
295 debug_assert_eq!(common.side, Side::Client);
296 self.ks
297 .set_encrypter(&self.client_handshake_traffic_secret, common);
298 }
299
300 pub(crate) fn set_handshake_decrypter(
301 &self,
302 skip_requested: Option<usize>,
303 common: &mut CommonState,
304 ) {
305 debug_assert_eq!(common.side, Side::Server);
306 let secret = &self.client_handshake_traffic_secret;
307 match skip_requested {
308 None => self.ks.set_decrypter(secret, common),
309 Some(max_early_data_size) => common
310 .record_layer
311 .set_message_decrypter_with_trial_decryption(
312 self.ks
313 .derive_decrypter(&self.client_handshake_traffic_secret),
314 max_early_data_size,
315 ),
316 }
317 }
318
319 pub(crate) fn into_traffic_with_client_finished_pending(
320 self,
321 hs_hash: hash::Output,
322 key_log: &dyn KeyLog,
323 client_random: &[u8; 32],
324 common: &mut CommonState,
325 ) -> KeyScheduleTrafficWithClientFinishedPending {
326 debug_assert_eq!(common.side, Side::Server);
327
328 let traffic = KeyScheduleTraffic::new(self.ks, hs_hash, key_log, client_random);
329 let (_client_secret, server_secret) = (
330 &traffic.current_client_traffic_secret,
331 &traffic.current_server_traffic_secret,
332 );
333
334 traffic
335 .ks
336 .set_encrypter(server_secret, common);
337
338 if common.is_quic() {
339 common.quic.traffic_secrets = Some(quic::Secrets::new(
340 _client_secret.clone(),
341 server_secret.clone(),
342 traffic.ks.suite,
343 traffic.ks.suite.quic.unwrap(),
344 common.side,
345 common.quic.version,
346 ));
347 }
348
349 KeyScheduleTrafficWithClientFinishedPending {
350 handshake_client_traffic_secret: self.client_handshake_traffic_secret,
351 traffic,
352 }
353 }
354
355 pub(crate) fn into_pre_finished_client_traffic(
356 self,
357 pre_finished_hash: hash::Output,
358 handshake_hash: hash::Output,
359 key_log: &dyn KeyLog,
360 client_random: &[u8; 32],
361 ) -> (KeyScheduleClientBeforeFinished, hmac::Tag) {
362 let traffic = KeyScheduleTraffic::new(self.ks, pre_finished_hash, key_log, client_random);
363 let tag = traffic
364 .ks
365 .sign_finish(&self.client_handshake_traffic_secret, &handshake_hash);
366 (KeyScheduleClientBeforeFinished { traffic }, tag)
367 }
368}
369
370pub(crate) struct KeyScheduleClientBeforeFinished {
371 traffic: KeyScheduleTraffic,
372}
373
374impl KeyScheduleClientBeforeFinished {
375 pub(crate) fn into_traffic(self, common: &mut CommonState) -> KeyScheduleTraffic {
376 debug_assert_eq!(common.side, Side::Client);
377 let (client_secret, server_secret) = (
378 &self
379 .traffic
380 .current_client_traffic_secret,
381 &self
382 .traffic
383 .current_server_traffic_secret,
384 );
385
386 self.traffic
387 .ks
388 .set_decrypter(server_secret, common);
389 self.traffic
390 .ks
391 .set_encrypter(client_secret, common);
392
393 if common.is_quic() {
394 common.quic.traffic_secrets = Some(quic::Secrets::new(
395 client_secret.clone(),
396 server_secret.clone(),
397 self.traffic.ks.suite,
398 self.traffic.ks.suite.quic.unwrap(),
399 common.side,
400 common.quic.version,
401 ));
402 }
403
404 self.traffic
405 }
406}
407
408pub(crate) struct KeyScheduleTrafficWithClientFinishedPending {
412 handshake_client_traffic_secret: OkmBlock,
413 traffic: KeyScheduleTraffic,
414}
415
416impl KeyScheduleTrafficWithClientFinishedPending {
417 pub(crate) fn update_decrypter(&self, common: &mut CommonState) {
418 debug_assert_eq!(common.side, Side::Server);
419 self.traffic
420 .ks
421 .set_decrypter(&self.handshake_client_traffic_secret, common);
422 }
423
424 pub(crate) fn sign_client_finish(
425 self,
426 hs_hash: &hash::Output,
427 common: &mut CommonState,
428 ) -> (KeyScheduleTraffic, hmac::Tag) {
429 debug_assert_eq!(common.side, Side::Server);
430 let tag = self
431 .traffic
432 .ks
433 .sign_finish(&self.handshake_client_traffic_secret, hs_hash);
434
435 self.traffic.ks.set_decrypter(
437 &self
438 .traffic
439 .current_client_traffic_secret,
440 common,
441 );
442
443 (self.traffic, tag)
444 }
445}
446
447pub(crate) struct KeyScheduleTraffic {
450 ks: KeySchedule,
451 current_client_traffic_secret: OkmBlock,
452 current_server_traffic_secret: OkmBlock,
453 current_exporter_secret: OkmBlock,
454}
455
456impl KeyScheduleTraffic {
457 fn new(
458 mut ks: KeySchedule,
459 hs_hash: hash::Output,
460 key_log: &dyn KeyLog,
461 client_random: &[u8; 32],
462 ) -> Self {
463 ks.input_empty();
464
465 let current_client_traffic_secret = ks.derive_logged_secret(
466 SecretKind::ClientApplicationTrafficSecret,
467 hs_hash.as_ref(),
468 key_log,
469 client_random,
470 );
471
472 let current_server_traffic_secret = ks.derive_logged_secret(
473 SecretKind::ServerApplicationTrafficSecret,
474 hs_hash.as_ref(),
475 key_log,
476 client_random,
477 );
478
479 let current_exporter_secret = ks.derive_logged_secret(
480 SecretKind::ExporterMasterSecret,
481 hs_hash.as_ref(),
482 key_log,
483 client_random,
484 );
485
486 Self {
487 ks,
488 current_client_traffic_secret,
489 current_server_traffic_secret,
490 current_exporter_secret,
491 }
492 }
493
494 pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) {
495 let secret = self.next_application_traffic_secret(common.side);
496 common.enqueue_key_update_notification();
497 self.ks.set_encrypter(&secret, common);
498 }
499
500 pub(crate) fn request_key_update_and_update_encrypter(
501 &mut self,
502 common: &mut CommonState,
503 ) -> Result<(), Error> {
504 common.check_aligned_handshake()?;
505 common.send_msg_encrypt(Message::build_key_update_request().into());
506 let secret = self.next_application_traffic_secret(common.side);
507 self.ks.set_encrypter(&secret, common);
508 Ok(())
509 }
510
511 pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
512 let secret = self.next_application_traffic_secret(common.side.peer());
513 self.ks.set_decrypter(&secret, common);
514 }
515
516 pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> OkmBlock {
517 let current = match side {
518 Side::Client => &mut self.current_client_traffic_secret,
519 Side::Server => &mut self.current_server_traffic_secret,
520 };
521
522 let secret = self.ks.derive_next(current);
523 *current = secret.clone();
524 secret
525 }
526
527 pub(crate) fn resumption_master_secret_and_derive_ticket_psk(
528 &self,
529 hs_hash: &hash::Output,
530 nonce: &[u8],
531 ) -> OkmBlock {
532 let resumption_master_secret = self
533 .ks
534 .derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref());
535 self.ks
536 .derive_ticket_psk(&resumption_master_secret, nonce)
537 }
538
539 pub(crate) fn export_keying_material(
540 &self,
541 out: &mut [u8],
542 label: &[u8],
543 context: Option<&[u8]>,
544 ) -> Result<(), Error> {
545 self.ks
546 .export_keying_material(&self.current_exporter_secret, out, label, context)
547 }
548
549 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
550 fn expand(
551 secret: &OkmBlock,
552 hkdf: &'static dyn Hkdf,
553 aead_key_len: usize,
554 ) -> (AeadKey, Iv) {
555 let expander = hkdf.expander_for_okm(secret);
556
557 (
558 hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
559 hkdf_expand_label(expander.as_ref(), b"iv", &[]),
560 )
561 }
562
563 let (client_key, client_iv) = expand(
564 &self.current_client_traffic_secret,
565 self.ks.suite.hkdf_provider,
566 self.ks.suite.aead_alg.key_len(),
567 );
568 let (server_key, server_iv) = expand(
569 &self.current_server_traffic_secret,
570 self.ks.suite.hkdf_provider,
571 self.ks.suite.aead_alg.key_len(),
572 );
573 let client_secrets = self
574 .ks
575 .suite
576 .aead_alg
577 .extract_keys(client_key, client_iv)?;
578 let server_secrets = self
579 .ks
580 .suite
581 .aead_alg
582 .extract_keys(server_key, server_iv)?;
583
584 let (tx, rx) = match side {
585 Side::Client => (client_secrets, server_secrets),
586 Side::Server => (server_secrets, client_secrets),
587 };
588 Ok(PartiallyExtractedSecrets { tx, rx })
589 }
590}
591
592impl KeySchedule {
593 fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
594 Self {
595 current: suite
596 .hkdf_provider
597 .extract_from_secret(None, secret),
598 suite,
599 }
600 }
601
602 fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
603 let expander = self
604 .suite
605 .hkdf_provider
606 .expander_for_okm(secret);
607 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg.key_len());
608 let iv = derive_traffic_iv(expander.as_ref());
609
610 common
611 .record_layer
612 .set_message_encrypter(
613 self.suite.aead_alg.encrypter(key, iv),
614 self.suite.common.confidentiality_limit,
615 );
616 }
617
618 fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
619 common
620 .record_layer
621 .set_message_decrypter(self.derive_decrypter(secret));
622 }
623
624 fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
625 let expander = self
626 .suite
627 .hkdf_provider
628 .expander_for_okm(secret);
629 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg.key_len());
630 let iv = derive_traffic_iv(expander.as_ref());
631 self.suite.aead_alg.decrypter(key, iv)
632 }
633
634 fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
635 Self {
636 current: suite
637 .hkdf_provider
638 .extract_from_zero_ikm(None),
639 suite,
640 }
641 }
642
643 fn input_empty(&mut self) {
645 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
646 self.current = self
647 .suite
648 .hkdf_provider
649 .extract_from_zero_ikm(Some(salt.as_ref()));
650 }
651
652 fn input_secret(&mut self, secret: &[u8]) {
654 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
655 self.current = self
656 .suite
657 .hkdf_provider
658 .extract_from_secret(Some(salt.as_ref()), secret);
659 }
660
661 fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
663 hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
664 }
665
666 fn derive_logged_secret(
667 &self,
668 kind: SecretKind,
669 hs_hash: &[u8],
670 key_log: &dyn KeyLog,
671 client_random: &[u8; 32],
672 ) -> OkmBlock {
673 let output = self.derive(kind, hs_hash);
674
675 let log_label = kind
676 .log_label()
677 .expect("not a loggable secret");
678 if key_log.will_log(log_label) {
679 key_log.log(log_label, client_random, output.as_ref());
680 }
681 output
682 }
683
684 fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
689 let empty_hash = self
690 .suite
691 .common
692 .hash_provider
693 .start()
694 .finish();
695 self.derive(kind, empty_hash.as_ref())
696 }
697
698 fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
701 self.sign_verify_data(base_key, hs_hash)
702 }
703
704 fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
707 let expander = self
708 .suite
709 .hkdf_provider
710 .expander_for_okm(base_key);
711 let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
712
713 self.suite
714 .hkdf_provider
715 .hmac_sign(&hmac_key, hs_hash.as_ref())
716 }
717
718 fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
720 let expander = self
721 .suite
722 .hkdf_provider
723 .expander_for_okm(base_key);
724 hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
725 }
726
727 fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
730 let expander = self
731 .suite
732 .hkdf_provider
733 .expander_for_okm(rms);
734 hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
735 }
736
737 fn export_keying_material(
738 &self,
739 current_exporter_secret: &OkmBlock,
740 out: &mut [u8],
741 label: &[u8],
742 context: Option<&[u8]>,
743 ) -> Result<(), Error> {
744 let secret = {
745 let h_empty = self
746 .suite
747 .common
748 .hash_provider
749 .hash(&[]);
750
751 let expander = self
752 .suite
753 .hkdf_provider
754 .expander_for_okm(current_exporter_secret);
755 hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
756 };
757
758 let h_context = self
759 .suite
760 .common
761 .hash_provider
762 .hash(context.unwrap_or(&[]));
763
764 let expander = self
765 .suite
766 .hkdf_provider
767 .expander_for_okm(&secret);
768 hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
769 .map_err(|_| Error::General("exporting too much".to_string()))
770 }
771}
772
773pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
778 expander: &dyn HkdfExpander,
779 label: &[u8],
780 context: &[u8],
781) -> T {
782 hkdf_expand_label_inner(expander, label, context, N, |e, info| expand(e, info))
783}
784
785pub(crate) fn hkdf_expand_label_block(
787 expander: &dyn HkdfExpander,
788 label: &[u8],
789 context: &[u8],
790) -> OkmBlock {
791 hkdf_expand_label_inner(expander, label, context, expander.hash_len(), |e, info| {
792 e.expand_block(info)
793 })
794}
795
796pub(crate) fn hkdf_expand_label_aead_key(
798 expander: &dyn HkdfExpander,
799 key_len: usize,
800 label: &[u8],
801 context: &[u8],
802) -> AeadKey {
803 hkdf_expand_label_inner(expander, label, context, key_len, |e, info| {
804 let key: AeadKey = expand(e, info);
805 key.with_length(key_len)
806 })
807}
808
809fn hkdf_expand_label_slice(
813 expander: &dyn HkdfExpander,
814 label: &[u8],
815 context: &[u8],
816 output: &mut [u8],
817) -> Result<(), OutputLengthError> {
818 hkdf_expand_label_inner(expander, label, context, output.len(), |e, info| {
819 e.expand_slice(info, output)
820 })
821}
822
823pub(crate) fn server_ech_hrr_confirmation_secret(
824 hkdf_provider: &'static dyn Hkdf,
825 client_hello_inner_random: &[u8],
826 hs_hash: hash::Output,
827) -> [u8; 8] {
828 hkdf_expand_label(
838 hkdf_provider
839 .extract_from_secret(None, client_hello_inner_random)
840 .as_ref(),
841 SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
842 hs_hash.as_ref(),
843 )
844}
845
846pub(crate) fn derive_traffic_key(expander: &dyn HkdfExpander, aead_key_len: usize) -> AeadKey {
847 hkdf_expand_label_aead_key(expander, aead_key_len, b"key", &[])
848}
849
850pub(crate) fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
851 hkdf_expand_label(expander, b"iv", &[])
852}
853
854fn hkdf_expand_label_inner<F, T>(
855 expander: &dyn HkdfExpander,
856 label: &[u8],
857 context: &[u8],
858 n: usize,
859 f: F,
860) -> T
861where
862 F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
863{
864 const LABEL_PREFIX: &[u8] = b"tls13 ";
865
866 let output_len = u16::to_be_bytes(n as u16);
867 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
868 let context_len = u8::to_be_bytes(context.len() as u8);
869
870 let info = &[
871 &output_len[..],
872 &label_len[..],
873 LABEL_PREFIX,
874 label,
875 &context_len[..],
876 context,
877 ];
878
879 f(expander, info)
880}
881
882test_for_each_provider! {
883 use core::fmt::Debug;
884 use std::vec;
885 use std::prelude::v1::*;
886
887 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
888 use provider::ring_like::aead;
889 use provider::tls13::{
890 TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
891 };
892 use crate::KeyLog;
893
894 #[test]
895 fn test_vectors() {
896 let hs_start_hash = [
898 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
899 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
900 0x75, 0x88, 0x1c, 0x0a,
901 ];
902
903 let hs_full_hash = [
904 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
905 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
906 0xbb, 0xeb, 0x23, 0xe2,
907 ];
908
909 let ecdhe_secret = [
910 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
911 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
912 0x71, 0xdf, 0x4b, 0x40,
913 ];
914
915 let client_hts = [
916 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
917 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
918 0x35, 0xcf, 0x46, 0xab,
919 ];
920
921 let client_hts_key = [
922 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
923 0x85, 0xa7,
924 ];
925
926 let client_hts_iv = [
927 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
928 ];
929
930 let server_hts = [
931 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
932 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
933 0x29, 0xa8, 0x87, 0x59,
934 ];
935
936 let server_hts_key = [
937 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
938 0xbc, 0x54,
939 ];
940
941 let server_hts_iv = [
942 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
943 ];
944
945 let client_ats = [
946 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
947 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
948 0x20, 0x6d, 0xbd, 0xa5,
949 ];
950
951 let client_ats_key = [
952 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
953 0x57, 0x2e,
954 ];
955
956 let client_ats_iv = [
957 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
958 ];
959
960 let server_ats = [
961 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
962 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
963 0x4c, 0x23, 0x21, 0x92,
964 ];
965
966 let server_ats_key = [
967 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
968 0x2b, 0xb3,
969 ];
970
971 let server_ats_iv = [
972 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
973 ];
974
975 let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
976 ks.input_secret(&ecdhe_secret);
977
978 assert_traffic_secret(
979 &ks,
980 SecretKind::ClientHandshakeTrafficSecret,
981 &hs_start_hash,
982 &client_hts,
983 &client_hts_key,
984 &client_hts_iv,
985 );
986
987 assert_traffic_secret(
988 &ks,
989 SecretKind::ServerHandshakeTrafficSecret,
990 &hs_start_hash,
991 &server_hts,
992 &server_hts_key,
993 &server_hts_iv,
994 );
995
996 ks.input_empty();
997
998 assert_traffic_secret(
999 &ks,
1000 SecretKind::ClientApplicationTrafficSecret,
1001 &hs_full_hash,
1002 &client_ats,
1003 &client_ats_key,
1004 &client_ats_iv,
1005 );
1006
1007 assert_traffic_secret(
1008 &ks,
1009 SecretKind::ServerApplicationTrafficSecret,
1010 &hs_full_hash,
1011 &server_ats,
1012 &server_ats_key,
1013 &server_ats_iv,
1014 );
1015 }
1016
1017 fn assert_traffic_secret(
1018 ks: &KeySchedule,
1019 kind: SecretKind,
1020 hash: &[u8],
1021 expected_traffic_secret: &[u8],
1022 expected_key: &[u8],
1023 expected_iv: &[u8],
1024 ) {
1025 #[derive(Debug)]
1026 struct Log<'a>(&'a [u8]);
1027 impl KeyLog for Log<'_> {
1028 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
1029 assert_eq!(self.0, secret);
1030 }
1031 }
1032 let log = Log(expected_traffic_secret);
1033 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
1034
1035 let aead_alg = &aead::AES_128_GCM;
1037 let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
1038 .hkdf_provider
1039 .expander_for_okm(&traffic_secret);
1040 let key = derive_traffic_key(expander.as_ref(), aead_alg.key_len());
1041 let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
1042 let seal_output = seal_zeroes(key);
1043 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
1044 let expected_seal_output = seal_zeroes(expected_key);
1045 assert_eq!(seal_output, expected_seal_output);
1046 assert!(seal_output.len() >= 48); let iv = derive_traffic_iv(expander.as_ref());
1049 assert_eq!(iv.as_ref(), expected_iv);
1050 }
1051
1052 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
1053 let key = aead::LessSafeKey::new(key);
1054 let mut seal_output = vec![0; 32];
1055 key.seal_in_place_append_tag(
1056 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
1057 aead::Aad::empty(),
1058 &mut seal_output,
1059 )
1060 .unwrap();
1061 seal_output
1062 }
1063}
1064
1065bench_for_each_provider! {
1066 #[bench]
1067 fn bench_sha256(b: &mut test::Bencher) {
1068 use core::fmt::Debug;
1069
1070 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
1071 use provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1072 use crate::KeyLog;
1073
1074 fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1075 #[derive(Debug)]
1076 struct Log;
1077
1078 impl KeyLog for Log {
1079 fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1080 }
1081
1082 let hash = [0u8; 32];
1083 let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1084 let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1085 .hkdf_provider
1086 .expander_for_okm(&traffic_secret);
1087 test::black_box(derive_traffic_key(
1088 traffic_secret_expander.as_ref(),
1089 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1090 .aead_alg
1091 .key_len(),
1092 ));
1093 test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
1094 }
1095
1096 b.iter(|| {
1097 let mut ks =
1098 KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1099 ks.input_secret(&[0u8; 32]);
1100
1101 extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1102 extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1103
1104 ks.input_empty();
1105
1106 extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1107 extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1108 });
1109 }
1110}