1//! Key schedule maintenance for TLS1.3
2
3use 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::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError, expand};
9use crate::crypto::{SharedSecret, hash, hmac};
10use crate::error::Error;
11use crate::msgs::message::Message;
12use crate::suites::PartiallyExtractedSecrets;
13use crate::{KeyLog, Tls13CipherSuite, quic};
14
15/// The kinds of secret we can extract from `KeySchedule`.
16#[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 // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-7.2
45 ServerEchConfirmationSecret => b"ech accept confirmation",
46 // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-7.2.1
47 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
67/// This is the TLS1.3 key schedule. It stores the current secret and
68/// the type of hash. This isn't used directly; but only through the
69/// typestates.
70struct KeySchedule {
71 current: Box<dyn HkdfExpander>,
72 suite: &'static Tls13CipherSuite,
73}
74
75// We express the state of a contained KeySchedule using these
76// typestates. This means we can write code that cannot accidentally
77// (e.g.) encrypt application data using a KeySchedule solely constructed
78// with an empty or trivial secret, or extract the wrong kind of secrets
79// at a given point.
80
81/// KeySchedule for early data stage.
82pub(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 // If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing
118 // before the application can see.
119 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
135/// Pre-handshake key schedule
136///
137/// The inner `KeySchedule` is either constructed without any secrets based on the HKDF algorithm
138/// or is extracted from a `KeyScheduleEarly`. This can then be used to derive the `KeyScheduleHandshakeStart`.
139pub(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: KeySchedule }: KeyScheduleEarly) -> Self {
162 Self { ks }
163 }
164}
165
166/// KeySchedule during handshake.
167pub(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 // Suite might have changed due to resumption
183 self.ks.suite = suite;
184 let new = self.into_handshake(hs_hash, key_log, client_random, common);
185
186 // Decrypt with the peer's key, encrypt with our own key
187 new.ks
188 .set_decrypter(&new.server_handshake_traffic_secret, common);
189
190 if !early_data_enabled {
191 // Set the client encryption key for handshakes if early data is not used
192 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 // Set up to encrypt with handshake secrets, but decrypt with early_data keys.
210 // If not doing early_data after all, this is corrected later to the handshake
211 // keys (now stored in key_schedule).
212 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 /*
223 Per ietf-tls-esni-17 section 7.2:
224 <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-7.2>
225 accept_confirmation = HKDF-Expand-Label(
226 HKDF-Extract(0, ClientHelloInner.random),
227 "ech accept confirmation",
228 transcript_ech_conf,8)
229 */
230 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 // Use an empty handshake hash for the initial handshake.
249 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
408/// KeySchedule during traffic stage, retaining the ability to calculate the client's
409/// finished verify_data. The traffic stage key schedule can be extracted from it
410/// through signing the client finished hash.
411pub(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 // Install keying to read future messages.
436 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
447/// KeySchedule during traffic stage. All traffic & exporter keys are guaranteed
448/// to be available.
449pub(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(kind: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 /// Input the empty secret.
654 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 /// Input the given secret.
663 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 /// Derive a secret of given `kind`, using current handshake hash `hs_hash`.
672 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 /// Derive a secret of given `kind` using the hash of the empty string
695 /// for the handshake hash. Useful only for
696 /// `SecretKind::ResumptionPSKBinderKey` and
697 /// `SecretKind::DerivedSecret`.
698 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 /// Sign the finished message consisting of `hs_hash` using a current
709 /// traffic secret.
710 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 /// Sign the finished message consisting of `hs_hash` using the key material
715 /// `base_key`.
716 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 /// Derive the next application traffic secret, returning it.
729 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 /// Derive the PSK to use given a resumption_master_secret and
738 /// ticket_nonce.
739 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
783/// [HKDF-Expand-Label] where the output is an AEAD key.
784///
785/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
786pub 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(), label:b"key", &[])
791}
792
793/// [HKDF-Expand-Label] where the output is an IV.
794///
795/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
796pub fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
797 hkdf_expand_label(expander, label:b"iv", &[])
798}
799
800/// [HKDF-Expand-Label] where the output length is a compile-time constant, and therefore
801/// it is infallible.
802///
803/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
804pub(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: &dyn HkdfExpander, info: &[&[u8]]| expand(expander:e, info))
810}
811
812/// [HKDF-Expand-Label] where the output is one block in size.
813pub(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, n:expander.hash_len(), |e: &dyn HkdfExpander, info: &[&[u8]]| {
819 e.expand_block(info)
820 })
821}
822
823/// [HKDF-Expand-Label] where the output is an AEAD key.
824pub(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, n:key_len, |e: &dyn HkdfExpander, info: &[&[u8]]| {
831 let key: AeadKey = expand(expander:e, info);
832 key.with_length(key_len)
833 })
834}
835
836/// [HKDF-Expand-Label] where the output is a slice.
837///
838/// This can fail because HKDF-Expand is limited in its maximum output length.
839fn 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, n:output.len(), |e: &dyn HkdfExpander, info: &[&[u8]]| {
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 /*
856 Per ietf-tls-esni-17 section 7.2.1:
857 <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-7.2.1>
858 hrr_accept_confirmation = HKDF-Expand-Label(
859 HKDF-Extract(0, ClientHelloInner1.random),
860 "hrr ech accept confirmation",
861 transcript_hrr_ech_conf,
862 8)
863 */
864 hkdf_expand_label(
865 expander:hkdf_provider
866 .extract_from_secret(None, client_hello_inner_random)
867 .as_ref(),
868 label:SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
869 context: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: [u8; _] = u16::to_be_bytes(self:n as u16);
886 let label_len: [u8; _] = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
887 let context_len: [u8; _] = u8::to_be_bytes(self:context.len() as u8);
888
889 let info: &[&[u8]; 6] = &[
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::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
913 use crate::KeyLog;
914
915 #[test]
916 fn test_vectors() {
917 /* These test vectors generated with OpenSSL. */
918 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 // Since we can't test key equality, we test the output of sealing with the key instead.
1057 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); // Sanity check.
1071
1072 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::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
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}
1135