1use alloc::boxed::Box;
4use alloc::string::ToString;
5
6use crate::common_state::{CommonState, Side};
7use crate::crypto::cipher::{AeadKey, Iv, MessageDecrypter, Tls13AeadAlgorithm};
8use crate::crypto::tls13::{expand, Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
9use crate::crypto::{hash, hmac, SharedSecret};
10use crate::error::Error;
11use crate::msgs::message::Message;
12use crate::suites::PartiallyExtractedSecrets;
13use crate::{quic, KeyLog, Tls13CipherSuite};
14
15#[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 export_keying_material(
528 &self,
529 out: &mut [u8],
530 label: &[u8],
531 context: Option<&[u8]>,
532 ) -> Result<(), Error> {
533 self.ks
534 .export_keying_material(&self.current_exporter_secret, out, label, context)
535 }
536
537 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
538 fn expand(
539 secret: &OkmBlock,
540 hkdf: &'static dyn Hkdf,
541 aead_key_len: usize,
542 ) -> (AeadKey, Iv) {
543 let expander = hkdf.expander_for_okm(secret);
544
545 (
546 hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
547 hkdf_expand_label(expander.as_ref(), b"iv", &[]),
548 )
549 }
550
551 let (client_key, client_iv) = expand(
552 &self.current_client_traffic_secret,
553 self.ks.suite.hkdf_provider,
554 self.ks.suite.aead_alg.key_len(),
555 );
556 let (server_key, server_iv) = expand(
557 &self.current_server_traffic_secret,
558 self.ks.suite.hkdf_provider,
559 self.ks.suite.aead_alg.key_len(),
560 );
561 let client_secrets = self
562 .ks
563 .suite
564 .aead_alg
565 .extract_keys(client_key, client_iv)?;
566 let server_secrets = self
567 .ks
568 .suite
569 .aead_alg
570 .extract_keys(server_key, server_iv)?;
571
572 let (tx, rx) = match side {
573 Side::Client => (client_secrets, server_secrets),
574 Side::Server => (server_secrets, client_secrets),
575 };
576 Ok(PartiallyExtractedSecrets { tx, rx })
577 }
578}
579
580pub(crate) struct ResumptionSecret<'a> {
581 kst: &'a KeyScheduleTraffic,
582 resumption_master_secret: OkmBlock,
583}
584
585impl<'a> ResumptionSecret<'a> {
586 pub(crate) fn new(kst: &'a KeyScheduleTraffic, hs_hash: &hash::Output) -> Self {
587 ResumptionSecret {
588 kst,
589 resumption_master_secret: kst
590 .ks
591 .derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref()),
592 }
593 }
594
595 pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock {
596 self.kst
597 .ks
598 .derive_ticket_psk(&self.resumption_master_secret, nonce)
599 }
600}
601
602impl KeySchedule {
603 fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
604 Self {
605 current: suite
606 .hkdf_provider
607 .extract_from_secret(None, secret),
608 suite,
609 }
610 }
611
612 fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
613 let expander = self
614 .suite
615 .hkdf_provider
616 .expander_for_okm(secret);
617 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
618 let iv = derive_traffic_iv(expander.as_ref());
619
620 common
621 .record_layer
622 .set_message_encrypter(
623 self.suite.aead_alg.encrypter(key, iv),
624 self.suite.common.confidentiality_limit,
625 );
626 }
627
628 fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
629 common
630 .record_layer
631 .set_message_decrypter(self.derive_decrypter(secret));
632 }
633
634 fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
635 let expander = self
636 .suite
637 .hkdf_provider
638 .expander_for_okm(secret);
639 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
640 let iv = derive_traffic_iv(expander.as_ref());
641 self.suite.aead_alg.decrypter(key, iv)
642 }
643
644 fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
645 Self {
646 current: suite
647 .hkdf_provider
648 .extract_from_zero_ikm(None),
649 suite,
650 }
651 }
652
653 fn input_empty(&mut self) {
655 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
656 self.current = self
657 .suite
658 .hkdf_provider
659 .extract_from_zero_ikm(Some(salt.as_ref()));
660 }
661
662 fn input_secret(&mut self, secret: &[u8]) {
664 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
665 self.current = self
666 .suite
667 .hkdf_provider
668 .extract_from_secret(Some(salt.as_ref()), secret);
669 }
670
671 fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
673 hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
674 }
675
676 fn derive_logged_secret(
677 &self,
678 kind: SecretKind,
679 hs_hash: &[u8],
680 key_log: &dyn KeyLog,
681 client_random: &[u8; 32],
682 ) -> OkmBlock {
683 let output = self.derive(kind, hs_hash);
684
685 let log_label = kind
686 .log_label()
687 .expect("not a loggable secret");
688 if key_log.will_log(log_label) {
689 key_log.log(log_label, client_random, output.as_ref());
690 }
691 output
692 }
693
694 fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
699 let empty_hash = self
700 .suite
701 .common
702 .hash_provider
703 .start()
704 .finish();
705 self.derive(kind, empty_hash.as_ref())
706 }
707
708 fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
711 self.sign_verify_data(base_key, hs_hash)
712 }
713
714 fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
717 let expander = self
718 .suite
719 .hkdf_provider
720 .expander_for_okm(base_key);
721 let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
722
723 self.suite
724 .hkdf_provider
725 .hmac_sign(&hmac_key, hs_hash.as_ref())
726 }
727
728 fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
730 let expander = self
731 .suite
732 .hkdf_provider
733 .expander_for_okm(base_key);
734 hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
735 }
736
737 fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
740 let expander = self
741 .suite
742 .hkdf_provider
743 .expander_for_okm(rms);
744 hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
745 }
746
747 fn export_keying_material(
748 &self,
749 current_exporter_secret: &OkmBlock,
750 out: &mut [u8],
751 label: &[u8],
752 context: Option<&[u8]>,
753 ) -> Result<(), Error> {
754 let secret = {
755 let h_empty = self
756 .suite
757 .common
758 .hash_provider
759 .hash(&[]);
760
761 let expander = self
762 .suite
763 .hkdf_provider
764 .expander_for_okm(current_exporter_secret);
765 hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
766 };
767
768 let h_context = self
769 .suite
770 .common
771 .hash_provider
772 .hash(context.unwrap_or(&[]));
773
774 let expander = self
775 .suite
776 .hkdf_provider
777 .expander_for_okm(&secret);
778 hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
779 .map_err(|_| Error::General("exporting too much".to_string()))
780 }
781}
782
783pub fn derive_traffic_key(
787 expander: &dyn HkdfExpander,
788 aead_alg: &dyn Tls13AeadAlgorithm,
789) -> AeadKey {
790 hkdf_expand_label_aead_key(expander, aead_alg.key_len(), b"key", &[])
791}
792
793pub fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
797 hkdf_expand_label(expander, b"iv", &[])
798}
799
800pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
805 expander: &dyn HkdfExpander,
806 label: &[u8],
807 context: &[u8],
808) -> T {
809 hkdf_expand_label_inner(expander, label, context, N, |e, info| expand(e, info))
810}
811
812pub(crate) fn hkdf_expand_label_block(
814 expander: &dyn HkdfExpander,
815 label: &[u8],
816 context: &[u8],
817) -> OkmBlock {
818 hkdf_expand_label_inner(expander, label, context, expander.hash_len(), |e, info| {
819 e.expand_block(info)
820 })
821}
822
823pub(crate) fn hkdf_expand_label_aead_key(
825 expander: &dyn HkdfExpander,
826 key_len: usize,
827 label: &[u8],
828 context: &[u8],
829) -> AeadKey {
830 hkdf_expand_label_inner(expander, label, context, key_len, |e, info| {
831 let key: AeadKey = expand(e, info);
832 key.with_length(key_len)
833 })
834}
835
836fn hkdf_expand_label_slice(
840 expander: &dyn HkdfExpander,
841 label: &[u8],
842 context: &[u8],
843 output: &mut [u8],
844) -> Result<(), OutputLengthError> {
845 hkdf_expand_label_inner(expander, label, context, output.len(), |e, info| {
846 e.expand_slice(info, output)
847 })
848}
849
850pub(crate) fn server_ech_hrr_confirmation_secret(
851 hkdf_provider: &'static dyn Hkdf,
852 client_hello_inner_random: &[u8],
853 hs_hash: hash::Output,
854) -> [u8; 8] {
855 hkdf_expand_label(
865 hkdf_provider
866 .extract_from_secret(None, client_hello_inner_random)
867 .as_ref(),
868 SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
869 hs_hash.as_ref(),
870 )
871}
872
873fn hkdf_expand_label_inner<F, T>(
874 expander: &dyn HkdfExpander,
875 label: &[u8],
876 context: &[u8],
877 n: usize,
878 f: F,
879) -> T
880where
881 F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
882{
883 const LABEL_PREFIX: &[u8] = b"tls13 ";
884
885 let output_len = u16::to_be_bytes(n as u16);
886 let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
887 let context_len = u8::to_be_bytes(context.len() as u8);
888
889 let info = &[
890 &output_len[..],
891 &label_len[..],
892 LABEL_PREFIX,
893 label,
894 &context_len[..],
895 context,
896 ];
897
898 f(expander, info)
899}
900
901#[cfg(test)]
902#[macro_rules_attribute::apply(test_for_each_provider)]
903mod tests {
904 use core::fmt::Debug;
905 use std::prelude::v1::*;
906 use std::vec;
907
908 use super::provider::ring_like::aead;
909 use super::provider::tls13::{
910 TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
911 };
912 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
913 use crate::KeyLog;
914
915 #[test]
916 fn test_vectors() {
917 let hs_start_hash = [
919 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
920 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
921 0x75, 0x88, 0x1c, 0x0a,
922 ];
923
924 let hs_full_hash = [
925 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
926 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
927 0xbb, 0xeb, 0x23, 0xe2,
928 ];
929
930 let ecdhe_secret = [
931 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
932 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
933 0x71, 0xdf, 0x4b, 0x40,
934 ];
935
936 let client_hts = [
937 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
938 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
939 0x35, 0xcf, 0x46, 0xab,
940 ];
941
942 let client_hts_key = [
943 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
944 0x85, 0xa7,
945 ];
946
947 let client_hts_iv = [
948 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
949 ];
950
951 let server_hts = [
952 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
953 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
954 0x29, 0xa8, 0x87, 0x59,
955 ];
956
957 let server_hts_key = [
958 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
959 0xbc, 0x54,
960 ];
961
962 let server_hts_iv = [
963 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
964 ];
965
966 let client_ats = [
967 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
968 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
969 0x20, 0x6d, 0xbd, 0xa5,
970 ];
971
972 let client_ats_key = [
973 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
974 0x57, 0x2e,
975 ];
976
977 let client_ats_iv = [
978 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
979 ];
980
981 let server_ats = [
982 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
983 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
984 0x4c, 0x23, 0x21, 0x92,
985 ];
986
987 let server_ats_key = [
988 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
989 0x2b, 0xb3,
990 ];
991
992 let server_ats_iv = [
993 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
994 ];
995
996 let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
997 ks.input_secret(&ecdhe_secret);
998
999 assert_traffic_secret(
1000 &ks,
1001 SecretKind::ClientHandshakeTrafficSecret,
1002 &hs_start_hash,
1003 &client_hts,
1004 &client_hts_key,
1005 &client_hts_iv,
1006 );
1007
1008 assert_traffic_secret(
1009 &ks,
1010 SecretKind::ServerHandshakeTrafficSecret,
1011 &hs_start_hash,
1012 &server_hts,
1013 &server_hts_key,
1014 &server_hts_iv,
1015 );
1016
1017 ks.input_empty();
1018
1019 assert_traffic_secret(
1020 &ks,
1021 SecretKind::ClientApplicationTrafficSecret,
1022 &hs_full_hash,
1023 &client_ats,
1024 &client_ats_key,
1025 &client_ats_iv,
1026 );
1027
1028 assert_traffic_secret(
1029 &ks,
1030 SecretKind::ServerApplicationTrafficSecret,
1031 &hs_full_hash,
1032 &server_ats,
1033 &server_ats_key,
1034 &server_ats_iv,
1035 );
1036 }
1037
1038 fn assert_traffic_secret(
1039 ks: &KeySchedule,
1040 kind: SecretKind,
1041 hash: &[u8],
1042 expected_traffic_secret: &[u8],
1043 expected_key: &[u8],
1044 expected_iv: &[u8],
1045 ) {
1046 #[derive(Debug)]
1047 struct Log<'a>(&'a [u8]);
1048 impl KeyLog for Log<'_> {
1049 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
1050 assert_eq!(self.0, secret);
1051 }
1052 }
1053 let log = Log(expected_traffic_secret);
1054 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
1055
1056 let aead_alg = &aead::AES_128_GCM;
1058 let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
1059 .hkdf_provider
1060 .expander_for_okm(&traffic_secret);
1061 let key = derive_traffic_key(
1062 expander.as_ref(),
1063 TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg,
1064 );
1065 let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
1066 let seal_output = seal_zeroes(key);
1067 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
1068 let expected_seal_output = seal_zeroes(expected_key);
1069 assert_eq!(seal_output, expected_seal_output);
1070 assert!(seal_output.len() >= 48); let iv = derive_traffic_iv(expander.as_ref());
1073 assert_eq!(iv.as_ref(), expected_iv);
1074 }
1075
1076 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
1077 let key = aead::LessSafeKey::new(key);
1078 let mut seal_output = vec![0; 32];
1079 key.seal_in_place_append_tag(
1080 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
1081 aead::Aad::empty(),
1082 &mut seal_output,
1083 )
1084 .unwrap();
1085 seal_output
1086 }
1087}
1088
1089#[cfg(all(test, bench))]
1090#[macro_rules_attribute::apply(bench_for_each_provider)]
1091mod benchmarks {
1092 #[bench]
1093 fn bench_sha256(b: &mut test::Bencher) {
1094 use core::fmt::Debug;
1095
1096 use super::provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1097 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
1098 use crate::KeyLog;
1099
1100 fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1101 #[derive(Debug)]
1102 struct Log;
1103
1104 impl KeyLog for Log {
1105 fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1106 }
1107
1108 let hash = [0u8; 32];
1109 let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1110 let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1111 .hkdf_provider
1112 .expander_for_okm(&traffic_secret);
1113 test::black_box(derive_traffic_key(
1114 traffic_secret_expander.as_ref(),
1115 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.aead_alg,
1116 ));
1117 test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
1118 }
1119
1120 b.iter(|| {
1121 let mut ks =
1122 KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1123 ks.input_secret(&[0u8; 32]);
1124
1125 extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1126 extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1127
1128 ks.input_empty();
1129
1130 extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1131 extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1132 });
1133 }
1134}