1use alloc::boxed::Box;
4use alloc::string::ToString;
5use core::ops::Deref;
6
7use crate::common_state::{CommonState, Side};
8use crate::crypto::cipher::{AeadKey, Iv, MessageDecrypter, Tls13AeadAlgorithm};
9use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError, expand};
10use crate::crypto::{SharedSecret, hash, hmac};
11use crate::error::Error;
12use crate::msgs::message::Message;
13use crate::suites::PartiallyExtractedSecrets;
14use crate::{ConnectionTrafficSecrets, KeyLog, Tls13CipherSuite, quic};
15
16pub(crate) struct KeyScheduleEarly {
30 ks: KeySchedule,
31}
32
33impl KeyScheduleEarly {
34 pub(crate) fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
35 Self {
36 ks: KeySchedule::new(suite, secret),
37 }
38 }
39
40 pub(crate) fn client_early_traffic_secret(
50 &self,
51 hs_hash: &hash::Output,
52 key_log: &dyn KeyLog,
53 client_random: &[u8; 32],
54 common: &mut CommonState,
55 ) {
56 let client_early_traffic_secret = self.ks.derive_logged_secret(
57 SecretKind::ClientEarlyTrafficSecret,
58 hs_hash.as_ref(),
59 key_log,
60 client_random,
61 );
62
63 match common.side {
64 Side::Client => self
65 .ks
66 .set_encrypter(&client_early_traffic_secret, common),
67 Side::Server => self
68 .ks
69 .set_decrypter(&client_early_traffic_secret, common),
70 }
71
72 if common.is_quic() {
73 common.quic.early_secret = Some(client_early_traffic_secret);
76 }
77 }
78
79 pub(crate) fn resumption_psk_binder_key_and_sign_verify_data(
80 &self,
81 hs_hash: &hash::Output,
82 ) -> hmac::Tag {
83 let resumption_psk_binder_key = self
84 .ks
85 .derive_for_empty_hash(SecretKind::ResumptionPskBinderKey);
86 self.ks
87 .sign_verify_data(&resumption_psk_binder_key, hs_hash)
88 }
89}
90
91pub(crate) struct KeySchedulePreHandshake {
115 ks: KeySchedule,
116}
117
118impl KeySchedulePreHandshake {
119 pub(crate) fn new(suite: &'static Tls13CipherSuite) -> Self {
121 Self {
122 ks: KeySchedule::new_with_empty_secret(suite),
123 }
124 }
125
126 pub(crate) fn into_handshake(
133 mut self,
134 shared_secret: SharedSecret,
135 ) -> KeyScheduleHandshakeStart {
136 self.ks
137 .input_secret(shared_secret.secret_bytes());
138 KeyScheduleHandshakeStart { ks: self.ks }
139 }
140}
141
142impl From<KeyScheduleEarly> for KeySchedulePreHandshake {
144 fn from(KeyScheduleEarly { ks }: KeyScheduleEarly) -> Self {
145 Self { ks }
146 }
147}
148
149pub(crate) struct KeyScheduleHandshakeStart {
153 ks: KeySchedule,
154}
155
156impl KeyScheduleHandshakeStart {
157 pub(crate) fn derive_client_handshake_secrets(
158 mut self,
159 early_data_enabled: bool,
160 hs_hash: hash::Output,
161 suite: &'static Tls13CipherSuite,
162 key_log: &dyn KeyLog,
163 client_random: &[u8; 32],
164 common: &mut CommonState,
165 ) -> KeyScheduleHandshake {
166 debug_assert_eq!(common.side, Side::Client);
167 self.ks.inner = suite.into();
169 let new = self.into_handshake(hs_hash, key_log, client_random, common);
170
171 new.ks
173 .set_decrypter(&new.server_handshake_traffic_secret, common);
174
175 if !early_data_enabled {
176 new.ks
178 .set_encrypter(&new.client_handshake_traffic_secret, common);
179 }
180
181 new
182 }
183
184 pub(crate) fn derive_server_handshake_secrets(
185 self,
186 hs_hash: hash::Output,
187 key_log: &dyn KeyLog,
188 client_random: &[u8; 32],
189 common: &mut CommonState,
190 ) -> KeyScheduleHandshake {
191 debug_assert_eq!(common.side, Side::Server);
192 let new = self.into_handshake(hs_hash, key_log, client_random, common);
193
194 new.ks
198 .set_encrypter(&new.server_handshake_traffic_secret, common);
199 new
200 }
201
202 pub(crate) fn server_ech_confirmation_secret(
203 &mut self,
204 client_hello_inner_random: &[u8],
205 hs_hash: hash::Output,
206 ) -> [u8; 8] {
207 hkdf_expand_label(
216 self.ks
217 .suite
218 .hkdf_provider
219 .extract_from_secret(None, client_hello_inner_random)
220 .as_ref(),
221 SecretKind::ServerEchConfirmationSecret.to_bytes(),
222 hs_hash.as_ref(),
223 )
224 }
225
226 fn into_handshake(
227 self,
228 hs_hash: hash::Output,
229 key_log: &dyn KeyLog,
230 client_random: &[u8; 32],
231 common: &mut CommonState,
232 ) -> KeyScheduleHandshake {
233 let client_secret = self.ks.derive_logged_secret(
235 SecretKind::ClientHandshakeTrafficSecret,
236 hs_hash.as_ref(),
237 key_log,
238 client_random,
239 );
240
241 let server_secret = self.ks.derive_logged_secret(
242 SecretKind::ServerHandshakeTrafficSecret,
243 hs_hash.as_ref(),
244 key_log,
245 client_random,
246 );
247
248 if common.is_quic() {
249 common.quic.hs_secrets = Some(quic::Secrets::new(
250 client_secret.clone(),
251 server_secret.clone(),
252 self.ks.suite,
253 self.ks.suite.quic.unwrap(),
254 common.side,
255 common.quic.version,
256 ));
257 }
258
259 KeyScheduleHandshake {
260 ks: self.ks,
261 client_handshake_traffic_secret: client_secret,
262 server_handshake_traffic_secret: server_secret,
263 }
264 }
265}
266
267pub(crate) struct KeyScheduleHandshake {
268 ks: KeySchedule,
269 client_handshake_traffic_secret: OkmBlock,
270 server_handshake_traffic_secret: OkmBlock,
271}
272
273impl KeyScheduleHandshake {
274 pub(crate) fn sign_server_finish(&self, hs_hash: &hash::Output) -> hmac::Tag {
275 self.ks
276 .sign_finish(&self.server_handshake_traffic_secret, hs_hash)
277 }
278
279 pub(crate) fn set_handshake_encrypter(&self, common: &mut CommonState) {
280 debug_assert_eq!(common.side, Side::Client);
281 self.ks
282 .set_encrypter(&self.client_handshake_traffic_secret, common);
283 }
284
285 pub(crate) fn set_handshake_decrypter(
286 &self,
287 skip_requested: Option<usize>,
288 common: &mut CommonState,
289 ) {
290 debug_assert_eq!(common.side, Side::Server);
291 let secret = &self.client_handshake_traffic_secret;
292 match skip_requested {
293 None => self.ks.set_decrypter(secret, common),
294 Some(max_early_data_size) => common
295 .record_layer
296 .set_message_decrypter_with_trial_decryption(
297 self.ks
298 .derive_decrypter(&self.client_handshake_traffic_secret),
299 max_early_data_size,
300 ),
301 }
302 }
303
304 pub(crate) fn into_traffic_with_client_finished_pending(
305 self,
306 hs_hash: hash::Output,
307 key_log: &dyn KeyLog,
308 client_random: &[u8; 32],
309 common: &mut CommonState,
310 ) -> KeyScheduleTrafficWithClientFinishedPending {
311 debug_assert_eq!(common.side, Side::Server);
312
313 let before_finished =
314 KeyScheduleBeforeFinished::new(self.ks, hs_hash, key_log, client_random);
315 let (_client_secret, server_secret) = (
316 &before_finished.current_client_traffic_secret,
317 &before_finished.current_server_traffic_secret,
318 );
319
320 before_finished
321 .ks
322 .set_encrypter(server_secret, common);
323
324 if common.is_quic() {
325 common.quic.traffic_secrets = Some(quic::Secrets::new(
326 _client_secret.clone(),
327 server_secret.clone(),
328 before_finished.ks.suite,
329 before_finished.ks.suite.quic.unwrap(),
330 common.side,
331 common.quic.version,
332 ));
333 }
334
335 KeyScheduleTrafficWithClientFinishedPending {
336 handshake_client_traffic_secret: self.client_handshake_traffic_secret,
337 before_finished,
338 }
339 }
340
341 pub(crate) fn into_pre_finished_client_traffic(
342 self,
343 pre_finished_hash: hash::Output,
344 handshake_hash: hash::Output,
345 key_log: &dyn KeyLog,
346 client_random: &[u8; 32],
347 ) -> (KeyScheduleClientBeforeFinished, hmac::Tag) {
348 let before_finished =
349 KeyScheduleBeforeFinished::new(self.ks, pre_finished_hash, key_log, client_random);
350 let tag = before_finished
351 .ks
352 .sign_finish(&self.client_handshake_traffic_secret, &handshake_hash);
353 (KeyScheduleClientBeforeFinished(before_finished), tag)
354 }
355}
356
357pub(crate) struct KeyScheduleBeforeFinished {
359 ks: KeySchedule,
360 current_client_traffic_secret: OkmBlock,
361 current_server_traffic_secret: OkmBlock,
362 current_exporter_secret: OkmBlock,
363}
364
365impl KeyScheduleBeforeFinished {
366 fn new(
367 mut ks: KeySchedule,
368 hs_hash: hash::Output,
369 key_log: &dyn KeyLog,
370 client_random: &[u8; 32],
371 ) -> Self {
372 ks.input_empty();
373
374 let current_client_traffic_secret = ks.derive_logged_secret(
375 SecretKind::ClientApplicationTrafficSecret,
376 hs_hash.as_ref(),
377 key_log,
378 client_random,
379 );
380
381 let current_server_traffic_secret = ks.derive_logged_secret(
382 SecretKind::ServerApplicationTrafficSecret,
383 hs_hash.as_ref(),
384 key_log,
385 client_random,
386 );
387
388 let current_exporter_secret = ks.derive_logged_secret(
389 SecretKind::ExporterMasterSecret,
390 hs_hash.as_ref(),
391 key_log,
392 client_random,
393 );
394
395 Self {
396 ks,
397 current_client_traffic_secret,
398 current_server_traffic_secret,
399 current_exporter_secret,
400 }
401 }
402
403 pub(crate) fn into_traffic(
404 self,
405 hs_hash: hash::Output,
406 ) -> (KeyScheduleTraffic, KeyScheduleResumption) {
407 let Self {
408 ks,
409 current_client_traffic_secret,
410 current_server_traffic_secret,
411 current_exporter_secret,
412 } = self;
413
414 let resumption_master_secret =
415 ks.derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref());
416
417 (
418 KeyScheduleTraffic {
419 ks: ks.inner,
420 current_client_traffic_secret,
421 current_server_traffic_secret,
422 current_exporter_secret,
423 },
424 KeyScheduleResumption {
425 ks: ks.inner,
426 resumption_master_secret,
427 },
428 )
429 }
430}
431
432pub(crate) struct KeyScheduleClientBeforeFinished(KeyScheduleBeforeFinished);
438
439impl KeyScheduleClientBeforeFinished {
440 pub(crate) fn into_traffic(
441 self,
442 common: &mut CommonState,
443 hs_hash: hash::Output,
444 ) -> (KeyScheduleTraffic, KeyScheduleResumption) {
445 let next = self.0;
446
447 debug_assert_eq!(common.side, Side::Client);
448 let (client_secret, server_secret) = (
449 &next.current_client_traffic_secret,
450 &next.current_server_traffic_secret,
451 );
452
453 next.ks
454 .set_decrypter(server_secret, common);
455 next.ks
456 .set_encrypter(client_secret, common);
457
458 if common.is_quic() {
459 common.quic.traffic_secrets = Some(quic::Secrets::new(
460 client_secret.clone(),
461 server_secret.clone(),
462 next.ks.suite,
463 next.ks.suite.quic.unwrap(),
464 common.side,
465 common.quic.version,
466 ));
467 }
468
469 next.into_traffic(hs_hash)
470 }
471}
472
473pub(crate) struct KeyScheduleTrafficWithClientFinishedPending {
477 handshake_client_traffic_secret: OkmBlock,
478 before_finished: KeyScheduleBeforeFinished,
479}
480
481impl KeyScheduleTrafficWithClientFinishedPending {
482 pub(crate) fn update_decrypter(&self, common: &mut CommonState) {
483 debug_assert_eq!(common.side, Side::Server);
484 self.before_finished
485 .ks
486 .set_decrypter(&self.handshake_client_traffic_secret, common);
487 }
488
489 pub(crate) fn sign_client_finish(
490 self,
491 hs_hash: &hash::Output,
492 common: &mut CommonState,
493 ) -> (KeyScheduleBeforeFinished, hmac::Tag) {
494 debug_assert_eq!(common.side, Side::Server);
495 let tag = self
496 .before_finished
497 .ks
498 .sign_finish(&self.handshake_client_traffic_secret, hs_hash);
499
500 self.before_finished.ks.set_decrypter(
502 &self
503 .before_finished
504 .current_client_traffic_secret,
505 common,
506 );
507
508 (self.before_finished, tag)
509 }
510}
511
512pub(crate) struct KeyScheduleTraffic {
515 ks: KeyScheduleSuite,
516 current_client_traffic_secret: OkmBlock,
517 current_server_traffic_secret: OkmBlock,
518 current_exporter_secret: OkmBlock,
519}
520
521impl KeyScheduleTraffic {
522 pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) {
523 let secret = self.next_application_traffic_secret(common.side);
524 common.enqueue_key_update_notification();
525 self.ks.set_encrypter(&secret, common);
526 }
527
528 pub(crate) fn request_key_update_and_update_encrypter(
529 &mut self,
530 common: &mut CommonState,
531 ) -> Result<(), Error> {
532 common.check_aligned_handshake()?;
533 common.send_msg_encrypt(Message::build_key_update_request().into());
534 let secret = self.next_application_traffic_secret(common.side);
535 self.ks.set_encrypter(&secret, common);
536 common.refresh_traffic_keys_pending = false;
539 Ok(())
540 }
541
542 pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
543 let secret = self.next_application_traffic_secret(common.side.peer());
544 self.ks.set_decrypter(&secret, common);
545 }
546
547 pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> OkmBlock {
548 let current = match side {
549 Side::Client => &mut self.current_client_traffic_secret,
550 Side::Server => &mut self.current_server_traffic_secret,
551 };
552
553 let secret = self.ks.derive_next(current);
554 *current = secret.clone();
555 secret
556 }
557
558 pub(crate) fn export_keying_material(
559 &self,
560 out: &mut [u8],
561 label: &[u8],
562 context: Option<&[u8]>,
563 ) -> Result<(), Error> {
564 self.ks
565 .export_keying_material(&self.current_exporter_secret, out, label, context)
566 }
567
568 pub(crate) fn refresh_traffic_secret(
569 &mut self,
570 side: Side,
571 ) -> Result<ConnectionTrafficSecrets, Error> {
572 let secret = self.next_application_traffic_secret(side);
573 let (key, iv) = expand_secret(
574 &secret,
575 self.ks.suite.hkdf_provider,
576 self.ks.suite.aead_alg.key_len(),
577 );
578 Ok(self
579 .ks
580 .suite
581 .aead_alg
582 .extract_keys(key, iv)?)
583 }
584
585 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
586 let (client_key, client_iv) = expand_secret(
587 &self.current_client_traffic_secret,
588 self.ks.suite.hkdf_provider,
589 self.ks.suite.aead_alg.key_len(),
590 );
591 let (server_key, server_iv) = expand_secret(
592 &self.current_server_traffic_secret,
593 self.ks.suite.hkdf_provider,
594 self.ks.suite.aead_alg.key_len(),
595 );
596 let client_secrets = self
597 .ks
598 .suite
599 .aead_alg
600 .extract_keys(client_key, client_iv)?;
601 let server_secrets = self
602 .ks
603 .suite
604 .aead_alg
605 .extract_keys(server_key, server_iv)?;
606
607 let (tx, rx) = match side {
608 Side::Client => (client_secrets, server_secrets),
609 Side::Server => (server_secrets, client_secrets),
610 };
611 Ok(PartiallyExtractedSecrets { tx, rx })
612 }
613}
614
615pub(crate) struct KeyScheduleResumption {
616 ks: KeyScheduleSuite,
617 resumption_master_secret: OkmBlock,
618}
619
620impl KeyScheduleResumption {
621 pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock {
622 self.ks
623 .derive_ticket_psk(&self.resumption_master_secret, nonce)
624 }
625}
626
627fn expand_secret(secret: &OkmBlock, hkdf: &'static dyn Hkdf, aead_key_len: usize) -> (AeadKey, Iv) {
628 let expander = hkdf.expander_for_okm(secret);
629
630 (
631 hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
632 hkdf_expand_label(expander.as_ref(), b"iv", &[]),
633 )
634}
635
636struct KeySchedule {
640 current: Box<dyn HkdfExpander>,
641 inner: KeyScheduleSuite,
642}
643
644impl KeySchedule {
645 fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
646 Self {
647 current: suite
648 .hkdf_provider
649 .extract_from_secret(None, secret),
650 inner: suite.into(),
651 }
652 }
653
654 fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
656 Self {
657 current: suite
658 .hkdf_provider
659 .extract_from_zero_ikm(None),
660 inner: suite.into(),
661 }
662 }
663
664 fn input_empty(&mut self) {
670 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
671 self.current = self
672 .suite
673 .hkdf_provider
674 .extract_from_zero_ikm(Some(salt.as_ref()));
675 }
676
677 fn input_secret(&mut self, secret: &[u8]) {
679 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
680 self.current = self
681 .suite
682 .hkdf_provider
683 .extract_from_secret(Some(salt.as_ref()), secret);
684 }
685
686 fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
694 hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
695 }
696
697 fn derive_logged_secret(
698 &self,
699 kind: SecretKind,
700 hs_hash: &[u8],
701 key_log: &dyn KeyLog,
702 client_random: &[u8; 32],
703 ) -> OkmBlock {
704 let output = self.derive(kind, hs_hash);
705
706 let log_label = kind
707 .log_label()
708 .expect("not a loggable secret");
709 if key_log.will_log(log_label) {
710 key_log.log(log_label, client_random, output.as_ref());
711 }
712 output
713 }
714
715 fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
729 let hp = self.suite.common.hash_provider;
730 let empty_hash = hp
731 .algorithm()
732 .hash_for_empty_input()
733 .unwrap_or_else(|| hp.start().finish());
734 self.derive(kind, empty_hash.as_ref())
735 }
736}
737
738impl Deref for KeySchedule {
739 type Target = KeyScheduleSuite;
740
741 fn deref(&self) -> &Self::Target {
742 &self.inner
743 }
744}
745
746#[derive(Clone, Copy)]
749struct KeyScheduleSuite {
750 suite: &'static Tls13CipherSuite,
751}
752
753impl KeyScheduleSuite {
754 fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
755 let expander = self
756 .suite
757 .hkdf_provider
758 .expander_for_okm(secret);
759 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
760 let iv = derive_traffic_iv(expander.as_ref());
761
762 common
763 .record_layer
764 .set_message_encrypter(
765 self.suite.aead_alg.encrypter(key, iv),
766 self.suite.common.confidentiality_limit,
767 );
768 }
769
770 fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
771 common
772 .record_layer
773 .set_message_decrypter(self.derive_decrypter(secret));
774 }
775
776 fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
777 let expander = self
778 .suite
779 .hkdf_provider
780 .expander_for_okm(secret);
781 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
782 let iv = derive_traffic_iv(expander.as_ref());
783 self.suite.aead_alg.decrypter(key, iv)
784 }
785
786 fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
791 self.sign_verify_data(base_key, hs_hash)
792 }
793
794 fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
799 let expander = self
800 .suite
801 .hkdf_provider
802 .expander_for_okm(base_key);
803 let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
804
805 self.suite
806 .hkdf_provider
807 .hmac_sign(&hmac_key, hs_hash.as_ref())
808 }
809
810 fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
812 let expander = self
813 .suite
814 .hkdf_provider
815 .expander_for_okm(base_key);
816 hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
817 }
818
819 fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
822 let expander = self
823 .suite
824 .hkdf_provider
825 .expander_for_okm(rms);
826 hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
827 }
828
829 fn export_keying_material(
830 &self,
831 current_exporter_secret: &OkmBlock,
832 out: &mut [u8],
833 label: &[u8],
834 context: Option<&[u8]>,
835 ) -> Result<(), Error> {
836 let secret = {
837 let h_empty = self
838 .suite
839 .common
840 .hash_provider
841 .hash(&[]);
842
843 let expander = self
844 .suite
845 .hkdf_provider
846 .expander_for_okm(current_exporter_secret);
847 hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
848 };
849
850 let h_context = self
851 .suite
852 .common
853 .hash_provider
854 .hash(context.unwrap_or(&[]));
855
856 let expander = self
857 .suite
858 .hkdf_provider
859 .expander_for_okm(&secret);
860 hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
861 .map_err(|_| Error::General("exporting too much".to_string()))
862 }
863}
864
865impl From<&'static Tls13CipherSuite> for KeyScheduleSuite {
866 fn from(suite: &'static Tls13CipherSuite) -> Self {
867 Self { suite }
868 }
869}
870
871pub fn derive_traffic_key(
875 expander: &dyn HkdfExpander,
876 aead_alg: &dyn Tls13AeadAlgorithm,
877) -> AeadKey {
878 hkdf_expand_label_aead_key(expander, aead_alg.key_len(), b"key", &[])
879}
880
881pub fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
885 hkdf_expand_label(expander, b"iv", &[])
886}
887
888pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
893 expander: &dyn HkdfExpander,
894 label: &[u8],
895 context: &[u8],
896) -> T {
897 hkdf_expand_label_inner(expander, label, context, N, |e, info| expand(e, info))
898}
899
900pub(crate) fn hkdf_expand_label_block(
902 expander: &dyn HkdfExpander,
903 label: &[u8],
904 context: &[u8],
905) -> OkmBlock {
906 hkdf_expand_label_inner(expander, label, context, expander.hash_len(), |e, info| {
907 e.expand_block(info)
908 })
909}
910
911pub(crate) fn hkdf_expand_label_aead_key(
913 expander: &dyn HkdfExpander,
914 key_len: usize,
915 label: &[u8],
916 context: &[u8],
917) -> AeadKey {
918 hkdf_expand_label_inner(expander, label, context, key_len, |e, info| {
919 let key: AeadKey = expand(e, info);
920 key.with_length(key_len)
921 })
922}
923
924fn hkdf_expand_label_slice(
928 expander: &dyn HkdfExpander,
929 label: &[u8],
930 context: &[u8],
931 output: &mut [u8],
932) -> Result<(), OutputLengthError> {
933 hkdf_expand_label_inner(expander, label, context, output.len(), |e, info| {
934 e.expand_slice(info, output)
935 })
936}
937
938pub(crate) fn server_ech_hrr_confirmation_secret(
939 hkdf_provider: &'static dyn Hkdf,
940 client_hello_inner_random: &[u8],
941 hs_hash: hash::Output,
942) -> [u8; 8] {
943 hkdf_expand_label(
953 hkdf_provider
954 .extract_from_secret(None, client_hello_inner_random)
955 .as_ref(),
956 SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
957 hs_hash.as_ref(),
958 )
959}
960
961fn hkdf_expand_label_inner<F, T>(
962 expander: &dyn HkdfExpander,
963 label: &[u8],
964 context: &[u8],
965 n: usize,
966 f: F,
967) -> T
968where
969 F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
970{
971 const LABEL_PREFIX: &[u8] = b"tls13 ";
972
973 let output_len = u16::to_be_bytes(n as u16);
974 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
975 let context_len = u8::to_be_bytes(context.len() as u8);
976
977 let info = &[
978 &output_len[..],
979 &label_len[..],
980 LABEL_PREFIX,
981 label,
982 &context_len[..],
983 context,
984 ];
985
986 f(expander, info)
987}
988
989#[derive(Debug, Clone, Copy, PartialEq)]
991enum SecretKind {
992 ResumptionPskBinderKey,
993 ClientEarlyTrafficSecret,
994 ClientHandshakeTrafficSecret,
995 ServerHandshakeTrafficSecret,
996 ClientApplicationTrafficSecret,
997 ServerApplicationTrafficSecret,
998 ExporterMasterSecret,
999 ResumptionMasterSecret,
1000 DerivedSecret,
1001 ServerEchConfirmationSecret,
1002 ServerEchHrrConfirmationSecret,
1003}
1004
1005impl SecretKind {
1006 fn to_bytes(self) -> &'static [u8] {
1007 use self::SecretKind::*;
1008 match self {
1009 ResumptionPskBinderKey => b"res binder",
1010 ClientEarlyTrafficSecret => b"c e traffic",
1011 ClientHandshakeTrafficSecret => b"c hs traffic",
1012 ServerHandshakeTrafficSecret => b"s hs traffic",
1013 ClientApplicationTrafficSecret => b"c ap traffic",
1014 ServerApplicationTrafficSecret => b"s ap traffic",
1015 ExporterMasterSecret => b"exp master",
1016 ResumptionMasterSecret => b"res master",
1017 DerivedSecret => b"derived",
1018 ServerEchConfirmationSecret => b"ech accept confirmation",
1020 ServerEchHrrConfirmationSecret => b"hrr ech accept confirmation",
1022 }
1023 }
1024
1025 fn log_label(self) -> Option<&'static str> {
1026 use self::SecretKind::*;
1027 Some(match self {
1028 ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
1029 ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
1030 ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
1031 ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
1032 ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
1033 ExporterMasterSecret => "EXPORTER_SECRET",
1034 _ => {
1035 return None;
1036 }
1037 })
1038 }
1039}
1040
1041#[cfg(test)]
1042#[macro_rules_attribute::apply(test_for_each_provider)]
1043mod tests {
1044 use core::fmt::Debug;
1045 use std::prelude::v1::*;
1046 use std::vec;
1047
1048 use super::provider::ring_like::aead;
1049 use super::provider::tls13::{
1050 TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
1051 };
1052 use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
1053 use crate::KeyLog;
1054 use crate::msgs::enums::HashAlgorithm;
1055
1056 #[test]
1057 fn empty_hash() {
1058 let sha256 = super::provider::tls13::TLS13_AES_128_GCM_SHA256
1059 .tls13()
1060 .unwrap()
1061 .common
1062 .hash_provider;
1063 let sha384 = super::provider::tls13::TLS13_AES_256_GCM_SHA384
1064 .tls13()
1065 .unwrap()
1066 .common
1067 .hash_provider;
1068
1069 assert!(
1070 sha256.start().finish().as_ref()
1071 == HashAlgorithm::SHA256
1072 .hash_for_empty_input()
1073 .unwrap()
1074 .as_ref()
1075 );
1076 assert!(
1077 sha384.start().finish().as_ref()
1078 == HashAlgorithm::SHA384
1079 .hash_for_empty_input()
1080 .unwrap()
1081 .as_ref()
1082 );
1083
1084 assert!(
1086 HashAlgorithm::SHA1
1087 .hash_for_empty_input()
1088 .is_none()
1089 );
1090 }
1091
1092 #[test]
1093 fn test_vectors() {
1094 let hs_start_hash = [
1096 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
1097 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
1098 0x75, 0x88, 0x1c, 0x0a,
1099 ];
1100
1101 let hs_full_hash = [
1102 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
1103 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
1104 0xbb, 0xeb, 0x23, 0xe2,
1105 ];
1106
1107 let ecdhe_secret = [
1108 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
1109 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
1110 0x71, 0xdf, 0x4b, 0x40,
1111 ];
1112
1113 let client_hts = [
1114 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
1115 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
1116 0x35, 0xcf, 0x46, 0xab,
1117 ];
1118
1119 let client_hts_key = [
1120 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
1121 0x85, 0xa7,
1122 ];
1123
1124 let client_hts_iv = [
1125 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
1126 ];
1127
1128 let server_hts = [
1129 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
1130 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
1131 0x29, 0xa8, 0x87, 0x59,
1132 ];
1133
1134 let server_hts_key = [
1135 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
1136 0xbc, 0x54,
1137 ];
1138
1139 let server_hts_iv = [
1140 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
1141 ];
1142
1143 let client_ats = [
1144 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
1145 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
1146 0x20, 0x6d, 0xbd, 0xa5,
1147 ];
1148
1149 let client_ats_key = [
1150 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
1151 0x57, 0x2e,
1152 ];
1153
1154 let client_ats_iv = [
1155 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
1156 ];
1157
1158 let server_ats = [
1159 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
1160 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
1161 0x4c, 0x23, 0x21, 0x92,
1162 ];
1163
1164 let server_ats_key = [
1165 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
1166 0x2b, 0xb3,
1167 ];
1168
1169 let server_ats_iv = [
1170 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
1171 ];
1172
1173 let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1174 ks.input_secret(&ecdhe_secret);
1175
1176 assert_traffic_secret(
1177 &ks,
1178 SecretKind::ClientHandshakeTrafficSecret,
1179 &hs_start_hash,
1180 &client_hts,
1181 &client_hts_key,
1182 &client_hts_iv,
1183 );
1184
1185 assert_traffic_secret(
1186 &ks,
1187 SecretKind::ServerHandshakeTrafficSecret,
1188 &hs_start_hash,
1189 &server_hts,
1190 &server_hts_key,
1191 &server_hts_iv,
1192 );
1193
1194 ks.input_empty();
1195
1196 assert_traffic_secret(
1197 &ks,
1198 SecretKind::ClientApplicationTrafficSecret,
1199 &hs_full_hash,
1200 &client_ats,
1201 &client_ats_key,
1202 &client_ats_iv,
1203 );
1204
1205 assert_traffic_secret(
1206 &ks,
1207 SecretKind::ServerApplicationTrafficSecret,
1208 &hs_full_hash,
1209 &server_ats,
1210 &server_ats_key,
1211 &server_ats_iv,
1212 );
1213 }
1214
1215 fn assert_traffic_secret(
1216 ks: &KeySchedule,
1217 kind: SecretKind,
1218 hash: &[u8],
1219 expected_traffic_secret: &[u8],
1220 expected_key: &[u8],
1221 expected_iv: &[u8],
1222 ) {
1223 #[derive(Debug)]
1224 struct Log<'a>(&'a [u8]);
1225 impl KeyLog for Log<'_> {
1226 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
1227 assert_eq!(self.0, secret);
1228 }
1229 }
1230 let log = Log(expected_traffic_secret);
1231 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
1232
1233 let aead_alg = &aead::AES_128_GCM;
1235 let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
1236 .hkdf_provider
1237 .expander_for_okm(&traffic_secret);
1238 let key = derive_traffic_key(
1239 expander.as_ref(),
1240 TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg,
1241 );
1242 let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
1243 let seal_output = seal_zeroes(key);
1244 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
1245 let expected_seal_output = seal_zeroes(expected_key);
1246 assert_eq!(seal_output, expected_seal_output);
1247 assert!(seal_output.len() >= 48); let iv = derive_traffic_iv(expander.as_ref());
1250 assert_eq!(iv.as_ref(), expected_iv);
1251 }
1252
1253 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
1254 let key = aead::LessSafeKey::new(key);
1255 let mut seal_output = vec![0; 32];
1256 key.seal_in_place_append_tag(
1257 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
1258 aead::Aad::empty(),
1259 &mut seal_output,
1260 )
1261 .unwrap();
1262 seal_output
1263 }
1264}
1265
1266#[cfg(all(test, bench))]
1267#[macro_rules_attribute::apply(bench_for_each_provider)]
1268mod benchmarks {
1269 #[bench]
1270 fn bench_sha256(b: &mut test::Bencher) {
1271 use core::fmt::Debug;
1272
1273 use super::provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1274 use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
1275 use crate::KeyLog;
1276
1277 fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1278 #[derive(Debug)]
1279 struct Log;
1280
1281 impl KeyLog for Log {
1282 fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1283 }
1284
1285 let hash = [0u8; 32];
1286 let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1287 let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1288 .hkdf_provider
1289 .expander_for_okm(&traffic_secret);
1290 test::black_box(derive_traffic_key(
1291 traffic_secret_expander.as_ref(),
1292 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.aead_alg,
1293 ));
1294 test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
1295 }
1296
1297 b.iter(|| {
1298 let mut ks =
1299 KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1300 ks.input_secret(&[0u8; 32]);
1301
1302 extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1303 extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1304
1305 ks.input_empty();
1306
1307 extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1308 extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1309 });
1310 }
1311}