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 Ok(())
537 }
538
539 pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
540 let secret = self.next_application_traffic_secret(common.side.peer());
541 self.ks.set_decrypter(&secret, common);
542 }
543
544 pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> OkmBlock {
545 let current = match side {
546 Side::Client => &mut self.current_client_traffic_secret,
547 Side::Server => &mut self.current_server_traffic_secret,
548 };
549
550 let secret = self.ks.derive_next(current);
551 *current = secret.clone();
552 secret
553 }
554
555 pub(crate) fn export_keying_material(
556 &self,
557 out: &mut [u8],
558 label: &[u8],
559 context: Option<&[u8]>,
560 ) -> Result<(), Error> {
561 self.ks
562 .export_keying_material(&self.current_exporter_secret, out, label, context)
563 }
564
565 pub(crate) fn refresh_traffic_secret(
566 &mut self,
567 side: Side,
568 ) -> Result<ConnectionTrafficSecrets, Error> {
569 let secret = self.next_application_traffic_secret(side);
570 let (key, iv) = expand_secret(
571 &secret,
572 self.ks.suite.hkdf_provider,
573 self.ks.suite.aead_alg.key_len(),
574 );
575 Ok(self
576 .ks
577 .suite
578 .aead_alg
579 .extract_keys(key, iv)?)
580 }
581
582 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
583 let (client_key, client_iv) = expand_secret(
584 &self.current_client_traffic_secret,
585 self.ks.suite.hkdf_provider,
586 self.ks.suite.aead_alg.key_len(),
587 );
588 let (server_key, server_iv) = expand_secret(
589 &self.current_server_traffic_secret,
590 self.ks.suite.hkdf_provider,
591 self.ks.suite.aead_alg.key_len(),
592 );
593 let client_secrets = self
594 .ks
595 .suite
596 .aead_alg
597 .extract_keys(client_key, client_iv)?;
598 let server_secrets = self
599 .ks
600 .suite
601 .aead_alg
602 .extract_keys(server_key, server_iv)?;
603
604 let (tx, rx) = match side {
605 Side::Client => (client_secrets, server_secrets),
606 Side::Server => (server_secrets, client_secrets),
607 };
608 Ok(PartiallyExtractedSecrets { tx, rx })
609 }
610}
611
612pub(crate) struct KeyScheduleResumption {
613 ks: KeyScheduleSuite,
614 resumption_master_secret: OkmBlock,
615}
616
617impl KeyScheduleResumption {
618 pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock {
619 self.ks
620 .derive_ticket_psk(&self.resumption_master_secret, nonce)
621 }
622}
623
624fn expand_secret(secret: &OkmBlock, hkdf: &'static dyn Hkdf, aead_key_len: usize) -> (AeadKey, Iv) {
625 let expander = hkdf.expander_for_okm(secret);
626
627 (
628 hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
629 hkdf_expand_label(expander.as_ref(), b"iv", &[]),
630 )
631}
632
633struct KeySchedule {
637 current: Box<dyn HkdfExpander>,
638 inner: KeyScheduleSuite,
639}
640
641impl KeySchedule {
642 fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
643 Self {
644 current: suite
645 .hkdf_provider
646 .extract_from_secret(None, secret),
647 inner: suite.into(),
648 }
649 }
650
651 fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
653 Self {
654 current: suite
655 .hkdf_provider
656 .extract_from_zero_ikm(None),
657 inner: suite.into(),
658 }
659 }
660
661 fn input_empty(&mut self) {
667 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
668 self.current = self
669 .suite
670 .hkdf_provider
671 .extract_from_zero_ikm(Some(salt.as_ref()));
672 }
673
674 fn input_secret(&mut self, secret: &[u8]) {
676 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
677 self.current = self
678 .suite
679 .hkdf_provider
680 .extract_from_secret(Some(salt.as_ref()), secret);
681 }
682
683 fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
691 hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
692 }
693
694 fn derive_logged_secret(
695 &self,
696 kind: SecretKind,
697 hs_hash: &[u8],
698 key_log: &dyn KeyLog,
699 client_random: &[u8; 32],
700 ) -> OkmBlock {
701 let output = self.derive(kind, hs_hash);
702
703 let log_label = kind
704 .log_label()
705 .expect("not a loggable secret");
706 if key_log.will_log(log_label) {
707 key_log.log(log_label, client_random, output.as_ref());
708 }
709 output
710 }
711
712 fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
726 let hp = self.suite.common.hash_provider;
727 let empty_hash = hp
728 .algorithm()
729 .hash_for_empty_input()
730 .unwrap_or_else(|| hp.start().finish());
731 self.derive(kind, empty_hash.as_ref())
732 }
733}
734
735impl Deref for KeySchedule {
736 type Target = KeyScheduleSuite;
737
738 fn deref(&self) -> &Self::Target {
739 &self.inner
740 }
741}
742
743#[derive(Clone, Copy)]
746struct KeyScheduleSuite {
747 suite: &'static Tls13CipherSuite,
748}
749
750impl KeyScheduleSuite {
751 fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
752 let expander = self
753 .suite
754 .hkdf_provider
755 .expander_for_okm(secret);
756 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
757 let iv = derive_traffic_iv(expander.as_ref());
758
759 common
760 .record_layer
761 .set_message_encrypter(
762 self.suite.aead_alg.encrypter(key, iv),
763 self.suite.common.confidentiality_limit,
764 );
765 }
766
767 fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
768 common
769 .record_layer
770 .set_message_decrypter(self.derive_decrypter(secret));
771 }
772
773 fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
774 let expander = self
775 .suite
776 .hkdf_provider
777 .expander_for_okm(secret);
778 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
779 let iv = derive_traffic_iv(expander.as_ref());
780 self.suite.aead_alg.decrypter(key, iv)
781 }
782
783 fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
788 self.sign_verify_data(base_key, hs_hash)
789 }
790
791 fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
796 let expander = self
797 .suite
798 .hkdf_provider
799 .expander_for_okm(base_key);
800 let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
801
802 self.suite
803 .hkdf_provider
804 .hmac_sign(&hmac_key, hs_hash.as_ref())
805 }
806
807 fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
809 let expander = self
810 .suite
811 .hkdf_provider
812 .expander_for_okm(base_key);
813 hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
814 }
815
816 fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
819 let expander = self
820 .suite
821 .hkdf_provider
822 .expander_for_okm(rms);
823 hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
824 }
825
826 fn export_keying_material(
827 &self,
828 current_exporter_secret: &OkmBlock,
829 out: &mut [u8],
830 label: &[u8],
831 context: Option<&[u8]>,
832 ) -> Result<(), Error> {
833 let secret = {
834 let h_empty = self
835 .suite
836 .common
837 .hash_provider
838 .hash(&[]);
839
840 let expander = self
841 .suite
842 .hkdf_provider
843 .expander_for_okm(current_exporter_secret);
844 hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
845 };
846
847 let h_context = self
848 .suite
849 .common
850 .hash_provider
851 .hash(context.unwrap_or(&[]));
852
853 let expander = self
854 .suite
855 .hkdf_provider
856 .expander_for_okm(&secret);
857 hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
858 .map_err(|_| Error::General("exporting too much".to_string()))
859 }
860}
861
862impl From<&'static Tls13CipherSuite> for KeyScheduleSuite {
863 fn from(suite: &'static Tls13CipherSuite) -> Self {
864 Self { suite }
865 }
866}
867
868pub fn derive_traffic_key(
872 expander: &dyn HkdfExpander,
873 aead_alg: &dyn Tls13AeadAlgorithm,
874) -> AeadKey {
875 hkdf_expand_label_aead_key(expander, aead_alg.key_len(), b"key", &[])
876}
877
878pub fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
882 hkdf_expand_label(expander, b"iv", &[])
883}
884
885pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
890 expander: &dyn HkdfExpander,
891 label: &[u8],
892 context: &[u8],
893) -> T {
894 hkdf_expand_label_inner(expander, label, context, N, |e, info| expand(e, info))
895}
896
897pub(crate) fn hkdf_expand_label_block(
899 expander: &dyn HkdfExpander,
900 label: &[u8],
901 context: &[u8],
902) -> OkmBlock {
903 hkdf_expand_label_inner(expander, label, context, expander.hash_len(), |e, info| {
904 e.expand_block(info)
905 })
906}
907
908pub(crate) fn hkdf_expand_label_aead_key(
910 expander: &dyn HkdfExpander,
911 key_len: usize,
912 label: &[u8],
913 context: &[u8],
914) -> AeadKey {
915 hkdf_expand_label_inner(expander, label, context, key_len, |e, info| {
916 let key: AeadKey = expand(e, info);
917 key.with_length(key_len)
918 })
919}
920
921fn hkdf_expand_label_slice(
925 expander: &dyn HkdfExpander,
926 label: &[u8],
927 context: &[u8],
928 output: &mut [u8],
929) -> Result<(), OutputLengthError> {
930 hkdf_expand_label_inner(expander, label, context, output.len(), |e, info| {
931 e.expand_slice(info, output)
932 })
933}
934
935pub(crate) fn server_ech_hrr_confirmation_secret(
936 hkdf_provider: &'static dyn Hkdf,
937 client_hello_inner_random: &[u8],
938 hs_hash: hash::Output,
939) -> [u8; 8] {
940 hkdf_expand_label(
950 hkdf_provider
951 .extract_from_secret(None, client_hello_inner_random)
952 .as_ref(),
953 SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
954 hs_hash.as_ref(),
955 )
956}
957
958fn hkdf_expand_label_inner<F, T>(
959 expander: &dyn HkdfExpander,
960 label: &[u8],
961 context: &[u8],
962 n: usize,
963 f: F,
964) -> T
965where
966 F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
967{
968 const LABEL_PREFIX: &[u8] = b"tls13 ";
969
970 let output_len = u16::to_be_bytes(n as u16);
971 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
972 let context_len = u8::to_be_bytes(context.len() as u8);
973
974 let info = &[
975 &output_len[..],
976 &label_len[..],
977 LABEL_PREFIX,
978 label,
979 &context_len[..],
980 context,
981 ];
982
983 f(expander, info)
984}
985
986#[derive(Debug, Clone, Copy, PartialEq)]
988enum SecretKind {
989 ResumptionPskBinderKey,
990 ClientEarlyTrafficSecret,
991 ClientHandshakeTrafficSecret,
992 ServerHandshakeTrafficSecret,
993 ClientApplicationTrafficSecret,
994 ServerApplicationTrafficSecret,
995 ExporterMasterSecret,
996 ResumptionMasterSecret,
997 DerivedSecret,
998 ServerEchConfirmationSecret,
999 ServerEchHrrConfirmationSecret,
1000}
1001
1002impl SecretKind {
1003 fn to_bytes(self) -> &'static [u8] {
1004 use self::SecretKind::*;
1005 match self {
1006 ResumptionPskBinderKey => b"res binder",
1007 ClientEarlyTrafficSecret => b"c e traffic",
1008 ClientHandshakeTrafficSecret => b"c hs traffic",
1009 ServerHandshakeTrafficSecret => b"s hs traffic",
1010 ClientApplicationTrafficSecret => b"c ap traffic",
1011 ServerApplicationTrafficSecret => b"s ap traffic",
1012 ExporterMasterSecret => b"exp master",
1013 ResumptionMasterSecret => b"res master",
1014 DerivedSecret => b"derived",
1015 ServerEchConfirmationSecret => b"ech accept confirmation",
1017 ServerEchHrrConfirmationSecret => b"hrr ech accept confirmation",
1019 }
1020 }
1021
1022 fn log_label(self) -> Option<&'static str> {
1023 use self::SecretKind::*;
1024 Some(match self {
1025 ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
1026 ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
1027 ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
1028 ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
1029 ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
1030 ExporterMasterSecret => "EXPORTER_SECRET",
1031 _ => {
1032 return None;
1033 }
1034 })
1035 }
1036}
1037
1038#[cfg(test)]
1039#[macro_rules_attribute::apply(test_for_each_provider)]
1040mod tests {
1041 use core::fmt::Debug;
1042 use std::prelude::v1::*;
1043 use std::vec;
1044
1045 use super::provider::ring_like::aead;
1046 use super::provider::tls13::{
1047 TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
1048 };
1049 use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
1050 use crate::KeyLog;
1051 use crate::msgs::enums::HashAlgorithm;
1052
1053 #[test]
1054 fn empty_hash() {
1055 let sha256 = super::provider::tls13::TLS13_AES_128_GCM_SHA256
1056 .tls13()
1057 .unwrap()
1058 .common
1059 .hash_provider;
1060 let sha384 = super::provider::tls13::TLS13_AES_256_GCM_SHA384
1061 .tls13()
1062 .unwrap()
1063 .common
1064 .hash_provider;
1065
1066 assert!(
1067 sha256.start().finish().as_ref()
1068 == HashAlgorithm::SHA256
1069 .hash_for_empty_input()
1070 .unwrap()
1071 .as_ref()
1072 );
1073 assert!(
1074 sha384.start().finish().as_ref()
1075 == HashAlgorithm::SHA384
1076 .hash_for_empty_input()
1077 .unwrap()
1078 .as_ref()
1079 );
1080
1081 assert!(
1083 HashAlgorithm::SHA1
1084 .hash_for_empty_input()
1085 .is_none()
1086 );
1087 }
1088
1089 #[test]
1090 fn test_vectors() {
1091 let hs_start_hash = [
1093 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
1094 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
1095 0x75, 0x88, 0x1c, 0x0a,
1096 ];
1097
1098 let hs_full_hash = [
1099 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
1100 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
1101 0xbb, 0xeb, 0x23, 0xe2,
1102 ];
1103
1104 let ecdhe_secret = [
1105 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
1106 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
1107 0x71, 0xdf, 0x4b, 0x40,
1108 ];
1109
1110 let client_hts = [
1111 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
1112 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
1113 0x35, 0xcf, 0x46, 0xab,
1114 ];
1115
1116 let client_hts_key = [
1117 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
1118 0x85, 0xa7,
1119 ];
1120
1121 let client_hts_iv = [
1122 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
1123 ];
1124
1125 let server_hts = [
1126 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
1127 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
1128 0x29, 0xa8, 0x87, 0x59,
1129 ];
1130
1131 let server_hts_key = [
1132 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
1133 0xbc, 0x54,
1134 ];
1135
1136 let server_hts_iv = [
1137 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
1138 ];
1139
1140 let client_ats = [
1141 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
1142 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
1143 0x20, 0x6d, 0xbd, 0xa5,
1144 ];
1145
1146 let client_ats_key = [
1147 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
1148 0x57, 0x2e,
1149 ];
1150
1151 let client_ats_iv = [
1152 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
1153 ];
1154
1155 let server_ats = [
1156 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
1157 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
1158 0x4c, 0x23, 0x21, 0x92,
1159 ];
1160
1161 let server_ats_key = [
1162 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
1163 0x2b, 0xb3,
1164 ];
1165
1166 let server_ats_iv = [
1167 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
1168 ];
1169
1170 let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1171 ks.input_secret(&ecdhe_secret);
1172
1173 assert_traffic_secret(
1174 &ks,
1175 SecretKind::ClientHandshakeTrafficSecret,
1176 &hs_start_hash,
1177 &client_hts,
1178 &client_hts_key,
1179 &client_hts_iv,
1180 );
1181
1182 assert_traffic_secret(
1183 &ks,
1184 SecretKind::ServerHandshakeTrafficSecret,
1185 &hs_start_hash,
1186 &server_hts,
1187 &server_hts_key,
1188 &server_hts_iv,
1189 );
1190
1191 ks.input_empty();
1192
1193 assert_traffic_secret(
1194 &ks,
1195 SecretKind::ClientApplicationTrafficSecret,
1196 &hs_full_hash,
1197 &client_ats,
1198 &client_ats_key,
1199 &client_ats_iv,
1200 );
1201
1202 assert_traffic_secret(
1203 &ks,
1204 SecretKind::ServerApplicationTrafficSecret,
1205 &hs_full_hash,
1206 &server_ats,
1207 &server_ats_key,
1208 &server_ats_iv,
1209 );
1210 }
1211
1212 fn assert_traffic_secret(
1213 ks: &KeySchedule,
1214 kind: SecretKind,
1215 hash: &[u8],
1216 expected_traffic_secret: &[u8],
1217 expected_key: &[u8],
1218 expected_iv: &[u8],
1219 ) {
1220 #[derive(Debug)]
1221 struct Log<'a>(&'a [u8]);
1222 impl KeyLog for Log<'_> {
1223 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
1224 assert_eq!(self.0, secret);
1225 }
1226 }
1227 let log = Log(expected_traffic_secret);
1228 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
1229
1230 let aead_alg = &aead::AES_128_GCM;
1232 let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
1233 .hkdf_provider
1234 .expander_for_okm(&traffic_secret);
1235 let key = derive_traffic_key(
1236 expander.as_ref(),
1237 TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg,
1238 );
1239 let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
1240 let seal_output = seal_zeroes(key);
1241 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
1242 let expected_seal_output = seal_zeroes(expected_key);
1243 assert_eq!(seal_output, expected_seal_output);
1244 assert!(seal_output.len() >= 48); let iv = derive_traffic_iv(expander.as_ref());
1247 assert_eq!(iv.as_ref(), expected_iv);
1248 }
1249
1250 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
1251 let key = aead::LessSafeKey::new(key);
1252 let mut seal_output = vec![0; 32];
1253 key.seal_in_place_append_tag(
1254 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
1255 aead::Aad::empty(),
1256 &mut seal_output,
1257 )
1258 .unwrap();
1259 seal_output
1260 }
1261}
1262
1263#[cfg(all(test, bench))]
1264#[macro_rules_attribute::apply(bench_for_each_provider)]
1265mod benchmarks {
1266 #[bench]
1267 fn bench_sha256(b: &mut test::Bencher) {
1268 use core::fmt::Debug;
1269
1270 use super::provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1271 use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
1272 use crate::KeyLog;
1273
1274 fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1275 #[derive(Debug)]
1276 struct Log;
1277
1278 impl KeyLog for Log {
1279 fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1280 }
1281
1282 let hash = [0u8; 32];
1283 let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1284 let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1285 .hkdf_provider
1286 .expander_for_okm(&traffic_secret);
1287 test::black_box(derive_traffic_key(
1288 traffic_secret_expander.as_ref(),
1289 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.aead_alg,
1290 ));
1291 test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
1292 }
1293
1294 b.iter(|| {
1295 let mut ks =
1296 KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1297 ks.input_secret(&[0u8; 32]);
1298
1299 extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1300 extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1301
1302 ks.input_empty();
1303
1304 extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1305 extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1306 });
1307 }
1308}