1use crate::common_state::{CommonState, Side};
2use crate::crypto::cipher::{AeadKey, Iv, MessageDecrypter};
3use crate::crypto::tls13::{expand, Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
4use crate::crypto::{hash, hmac, ActiveKeyExchange};
5use crate::error::Error;
6use crate::quic;
7use crate::suites::PartiallyExtractedSecrets;
8use crate::{KeyLog, Tls13CipherSuite};
9
10use alloc::boxed::Box;
11use alloc::string::ToString;
12
13/// Key schedule maintenance for TLS1.3
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}
28
29impl SecretKind {
30 fn to_bytes(self) -> &'static [u8] {
31 use self::SecretKind::*;
32 match self {
33 ResumptionPskBinderKey => b"res binder",
34 ClientEarlyTrafficSecret => b"c e traffic",
35 ClientHandshakeTrafficSecret => b"c hs traffic",
36 ServerHandshakeTrafficSecret => b"s hs traffic",
37 ClientApplicationTrafficSecret => b"c ap traffic",
38 ServerApplicationTrafficSecret => b"s ap traffic",
39 ExporterMasterSecret => b"exp master",
40 ResumptionMasterSecret => b"res master",
41 DerivedSecret => b"derived",
42 }
43 }
44
45 fn log_label(self) -> Option<&'static str> {
46 use self::SecretKind::*;
47 Some(match self {
48 ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
49 ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
50 ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
51 ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
52 ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
53 ExporterMasterSecret => "EXPORTER_SECRET",
54 _ => {
55 return None;
56 }
57 })
58 }
59}
60
61/// This is the TLS1.3 key schedule. It stores the current secret and
62/// the type of hash. This isn't used directly; but only through the
63/// typestates.
64struct KeySchedule {
65 current: Box<dyn HkdfExpander>,
66 suite: &'static Tls13CipherSuite,
67}
68
69// We express the state of a contained KeySchedule using these
70// typestates. This means we can write code that cannot accidentally
71// (e.g.) encrypt application data using a KeySchedule solely constructed
72// with an empty or trivial secret, or extract the wrong kind of secrets
73// at a given point.
74
75/// KeySchedule for early data stage.
76pub(crate) struct KeyScheduleEarly {
77 ks: KeySchedule,
78}
79
80impl KeyScheduleEarly {
81 pub(crate) fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
82 Self {
83 ks: KeySchedule::new(suite, secret),
84 }
85 }
86
87 pub(crate) fn client_early_traffic_secret(
88 &self,
89 hs_hash: &hash::Output,
90 key_log: &dyn KeyLog,
91 client_random: &[u8; 32],
92 common: &mut CommonState,
93 ) {
94 let client_early_traffic_secret = self.ks.derive_logged_secret(
95 SecretKind::ClientEarlyTrafficSecret,
96 hs_hash.as_ref(),
97 key_log,
98 client_random,
99 );
100
101 match common.side {
102 Side::Client => self
103 .ks
104 .set_encrypter(&client_early_traffic_secret, common),
105 Side::Server => self
106 .ks
107 .set_decrypter(&client_early_traffic_secret, common),
108 }
109
110 if common.is_quic() {
111 // If 0-RTT should be rejected, this will be clobbered by ExtensionProcessing
112 // before the application can see.
113 common.quic.early_secret = Some(client_early_traffic_secret);
114 }
115 }
116
117 pub(crate) fn resumption_psk_binder_key_and_sign_verify_data(
118 &self,
119 hs_hash: &hash::Output,
120 ) -> hmac::Tag {
121 let resumption_psk_binder_key = self
122 .ks
123 .derive_for_empty_hash(SecretKind::ResumptionPskBinderKey);
124 self.ks
125 .sign_verify_data(&resumption_psk_binder_key, hs_hash)
126 }
127}
128
129/// Pre-handshake key schedule
130///
131/// The inner `KeySchedule` is either constructed without any secrets based on ths HKDF algorithm
132/// or is extracted from a `KeyScheduleEarly`. This can then be used to derive the `KeyScheduleHandshakeStart`.
133pub(crate) struct KeySchedulePreHandshake {
134 ks: KeySchedule,
135}
136
137impl KeySchedulePreHandshake {
138 pub(crate) fn new(suite: &'static Tls13CipherSuite) -> Self {
139 Self {
140 ks: KeySchedule::new_with_empty_secret(suite),
141 }
142 }
143
144 pub(crate) fn into_handshake(
145 mut self,
146 kx: Box<dyn ActiveKeyExchange>,
147 peer_public_key: &[u8],
148 ) -> Result<KeyScheduleHandshakeStart, Error> {
149 self.ks
150 .input_from_key_exchange(kx, peer_public_key)?;
151 Ok(KeyScheduleHandshakeStart { ks: self.ks })
152 }
153}
154
155impl From<KeyScheduleEarly> for KeySchedulePreHandshake {
156 fn from(KeyScheduleEarly { ks: KeySchedule }: KeyScheduleEarly) -> Self {
157 Self { ks }
158 }
159}
160
161/// KeySchedule during handshake.
162pub(crate) struct KeyScheduleHandshakeStart {
163 ks: KeySchedule,
164}
165
166impl KeyScheduleHandshakeStart {
167 pub(crate) fn derive_client_handshake_secrets(
168 mut self,
169 early_data_enabled: bool,
170 hs_hash: hash::Output,
171 suite: &'static Tls13CipherSuite,
172 key_log: &dyn KeyLog,
173 client_random: &[u8; 32],
174 common: &mut CommonState,
175 ) -> KeyScheduleHandshake {
176 debug_assert_eq!(common.side, Side::Client);
177 // Suite might have changed due to resumption
178 self.ks.suite = suite;
179 let new = self.into_handshake(hs_hash, key_log, client_random, common);
180
181 // Decrypt with the peer's key, encrypt with our own key
182 new.ks
183 .set_decrypter(&new.server_handshake_traffic_secret, common);
184
185 if !early_data_enabled {
186 // Set the client encryption key for handshakes if early data is not used
187 new.ks
188 .set_encrypter(&new.client_handshake_traffic_secret, common);
189 }
190
191 new
192 }
193
194 pub(crate) fn derive_server_handshake_secrets(
195 self,
196 hs_hash: hash::Output,
197 key_log: &dyn KeyLog,
198 client_random: &[u8; 32],
199 common: &mut CommonState,
200 ) -> KeyScheduleHandshake {
201 debug_assert_eq!(common.side, Side::Server);
202 let new = self.into_handshake(hs_hash, key_log, client_random, common);
203
204 // Set up to encrypt with handshake secrets, but decrypt with early_data keys.
205 // If not doing early_data after all, this is corrected later to the handshake
206 // keys (now stored in key_schedule).
207 new.ks
208 .set_encrypter(&new.server_handshake_traffic_secret, common);
209 new
210 }
211
212 fn into_handshake(
213 self,
214 hs_hash: hash::Output,
215 key_log: &dyn KeyLog,
216 client_random: &[u8; 32],
217 common: &mut CommonState,
218 ) -> KeyScheduleHandshake {
219 // Use an empty handshake hash for the initial handshake.
220 let client_secret = self.ks.derive_logged_secret(
221 SecretKind::ClientHandshakeTrafficSecret,
222 hs_hash.as_ref(),
223 key_log,
224 client_random,
225 );
226
227 let server_secret = self.ks.derive_logged_secret(
228 SecretKind::ServerHandshakeTrafficSecret,
229 hs_hash.as_ref(),
230 key_log,
231 client_random,
232 );
233
234 if common.is_quic() {
235 common.quic.hs_secrets = Some(quic::Secrets::new(
236 client_secret.clone(),
237 server_secret.clone(),
238 self.ks.suite,
239 self.ks.suite.quic.unwrap(),
240 common.side,
241 common.quic.version,
242 ));
243 }
244
245 KeyScheduleHandshake {
246 ks: self.ks,
247 client_handshake_traffic_secret: client_secret,
248 server_handshake_traffic_secret: server_secret,
249 }
250 }
251}
252
253pub(crate) struct KeyScheduleHandshake {
254 ks: KeySchedule,
255 client_handshake_traffic_secret: OkmBlock,
256 server_handshake_traffic_secret: OkmBlock,
257}
258
259impl KeyScheduleHandshake {
260 pub(crate) fn sign_server_finish(&self, hs_hash: &hash::Output) -> hmac::Tag {
261 self.ks
262 .sign_finish(&self.server_handshake_traffic_secret, hs_hash)
263 }
264
265 pub(crate) fn set_handshake_encrypter(&self, common: &mut CommonState) {
266 debug_assert_eq!(common.side, Side::Client);
267 self.ks
268 .set_encrypter(&self.client_handshake_traffic_secret, common);
269 }
270
271 pub(crate) fn set_handshake_decrypter(
272 &self,
273 skip_requested: Option<usize>,
274 common: &mut CommonState,
275 ) {
276 debug_assert_eq!(common.side, Side::Server);
277 let secret = &self.client_handshake_traffic_secret;
278 match skip_requested {
279 None => self.ks.set_decrypter(secret, common),
280 Some(max_early_data_size) => common
281 .record_layer
282 .set_message_decrypter_with_trial_decryption(
283 self.ks
284 .derive_decrypter(&self.client_handshake_traffic_secret),
285 max_early_data_size,
286 ),
287 }
288 }
289
290 pub(crate) fn into_traffic_with_client_finished_pending(
291 self,
292 hs_hash: hash::Output,
293 key_log: &dyn KeyLog,
294 client_random: &[u8; 32],
295 common: &mut CommonState,
296 ) -> KeyScheduleTrafficWithClientFinishedPending {
297 debug_assert_eq!(common.side, Side::Server);
298
299 let traffic = KeyScheduleTraffic::new(self.ks, hs_hash, key_log, client_random);
300 let (_client_secret, server_secret) = (
301 &traffic.current_client_traffic_secret,
302 &traffic.current_server_traffic_secret,
303 );
304
305 traffic
306 .ks
307 .set_encrypter(server_secret, common);
308
309 if common.is_quic() {
310 common.quic.traffic_secrets = Some(quic::Secrets::new(
311 _client_secret.clone(),
312 server_secret.clone(),
313 traffic.ks.suite,
314 traffic.ks.suite.quic.unwrap(),
315 common.side,
316 common.quic.version,
317 ));
318 }
319
320 KeyScheduleTrafficWithClientFinishedPending {
321 handshake_client_traffic_secret: self.client_handshake_traffic_secret,
322 traffic,
323 }
324 }
325
326 pub(crate) fn into_pre_finished_client_traffic(
327 self,
328 pre_finished_hash: hash::Output,
329 handshake_hash: hash::Output,
330 key_log: &dyn KeyLog,
331 client_random: &[u8; 32],
332 ) -> (KeyScheduleClientBeforeFinished, hmac::Tag) {
333 let traffic = KeyScheduleTraffic::new(self.ks, pre_finished_hash, key_log, client_random);
334 let tag = traffic
335 .ks
336 .sign_finish(&self.client_handshake_traffic_secret, &handshake_hash);
337 (KeyScheduleClientBeforeFinished { traffic }, tag)
338 }
339}
340
341pub(crate) struct KeyScheduleClientBeforeFinished {
342 traffic: KeyScheduleTraffic,
343}
344
345impl KeyScheduleClientBeforeFinished {
346 pub(crate) fn into_traffic(self, common: &mut CommonState) -> KeyScheduleTraffic {
347 debug_assert_eq!(common.side, Side::Client);
348 let (client_secret, server_secret) = (
349 &self
350 .traffic
351 .current_client_traffic_secret,
352 &self
353 .traffic
354 .current_server_traffic_secret,
355 );
356
357 self.traffic
358 .ks
359 .set_decrypter(server_secret, common);
360 self.traffic
361 .ks
362 .set_encrypter(client_secret, common);
363
364 if common.is_quic() {
365 common.quic.traffic_secrets = Some(quic::Secrets::new(
366 client_secret.clone(),
367 server_secret.clone(),
368 self.traffic.ks.suite,
369 self.traffic.ks.suite.quic.unwrap(),
370 common.side,
371 common.quic.version,
372 ));
373 }
374
375 self.traffic
376 }
377}
378
379/// KeySchedule during traffic stage, retaining the ability to calculate the client's
380/// finished verify_data. The traffic stage key schedule can be extracted from it
381/// through signing the client finished hash.
382pub(crate) struct KeyScheduleTrafficWithClientFinishedPending {
383 handshake_client_traffic_secret: OkmBlock,
384 traffic: KeyScheduleTraffic,
385}
386
387impl KeyScheduleTrafficWithClientFinishedPending {
388 pub(crate) fn update_decrypter(&self, common: &mut CommonState) {
389 debug_assert_eq!(common.side, Side::Server);
390 self.traffic
391 .ks
392 .set_decrypter(&self.handshake_client_traffic_secret, common);
393 }
394
395 pub(crate) fn sign_client_finish(
396 self,
397 hs_hash: &hash::Output,
398 common: &mut CommonState,
399 ) -> (KeyScheduleTraffic, hmac::Tag) {
400 debug_assert_eq!(common.side, Side::Server);
401 let tag = self
402 .traffic
403 .ks
404 .sign_finish(&self.handshake_client_traffic_secret, hs_hash);
405
406 // Install keying to read future messages.
407 self.traffic.ks.set_decrypter(
408 &self
409 .traffic
410 .current_client_traffic_secret,
411 common,
412 );
413
414 (self.traffic, tag)
415 }
416}
417
418/// KeySchedule during traffic stage. All traffic & exporter keys are guaranteed
419/// to be available.
420pub(crate) struct KeyScheduleTraffic {
421 ks: KeySchedule,
422 current_client_traffic_secret: OkmBlock,
423 current_server_traffic_secret: OkmBlock,
424 current_exporter_secret: OkmBlock,
425}
426
427impl KeyScheduleTraffic {
428 fn new(
429 mut ks: KeySchedule,
430 hs_hash: hash::Output,
431 key_log: &dyn KeyLog,
432 client_random: &[u8; 32],
433 ) -> Self {
434 ks.input_empty();
435
436 let current_client_traffic_secret = ks.derive_logged_secret(
437 SecretKind::ClientApplicationTrafficSecret,
438 hs_hash.as_ref(),
439 key_log,
440 client_random,
441 );
442
443 let current_server_traffic_secret = ks.derive_logged_secret(
444 SecretKind::ServerApplicationTrafficSecret,
445 hs_hash.as_ref(),
446 key_log,
447 client_random,
448 );
449
450 let current_exporter_secret = ks.derive_logged_secret(
451 SecretKind::ExporterMasterSecret,
452 hs_hash.as_ref(),
453 key_log,
454 client_random,
455 );
456
457 Self {
458 ks,
459 current_client_traffic_secret,
460 current_server_traffic_secret,
461 current_exporter_secret,
462 }
463 }
464
465 pub(crate) fn update_encrypter_and_notify(&mut self, common: &mut CommonState) {
466 let secret = self.next_application_traffic_secret(common.side);
467 common.enqueue_key_update_notification();
468 self.ks.set_encrypter(&secret, common);
469 }
470
471 pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
472 let secret = self.next_application_traffic_secret(common.side.peer());
473 self.ks.set_decrypter(&secret, common);
474 }
475
476 pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> OkmBlock {
477 let current = match side {
478 Side::Client => &mut self.current_client_traffic_secret,
479 Side::Server => &mut self.current_server_traffic_secret,
480 };
481
482 let secret = self.ks.derive_next(current);
483 *current = secret.clone();
484 secret
485 }
486
487 pub(crate) fn resumption_master_secret_and_derive_ticket_psk(
488 &self,
489 hs_hash: &hash::Output,
490 nonce: &[u8],
491 ) -> OkmBlock {
492 let resumption_master_secret = self
493 .ks
494 .derive(SecretKind::ResumptionMasterSecret, hs_hash.as_ref());
495 self.ks
496 .derive_ticket_psk(&resumption_master_secret, nonce)
497 }
498
499 pub(crate) fn export_keying_material(
500 &self,
501 out: &mut [u8],
502 label: &[u8],
503 context: Option<&[u8]>,
504 ) -> Result<(), Error> {
505 self.ks
506 .export_keying_material(&self.current_exporter_secret, out, label, context)
507 }
508
509 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
510 fn expand(
511 secret: &OkmBlock,
512 hkdf: &'static dyn Hkdf,
513 aead_key_len: usize,
514 ) -> (AeadKey, Iv) {
515 let expander = hkdf.expander_for_okm(secret);
516
517 (
518 hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
519 hkdf_expand_label(expander.as_ref(), b"iv", &[]),
520 )
521 }
522
523 let (client_key, client_iv) = expand(
524 &self.current_client_traffic_secret,
525 self.ks.suite.hkdf_provider,
526 self.ks.suite.aead_alg.key_len(),
527 );
528 let (server_key, server_iv) = expand(
529 &self.current_server_traffic_secret,
530 self.ks.suite.hkdf_provider,
531 self.ks.suite.aead_alg.key_len(),
532 );
533 let client_secrets = self
534 .ks
535 .suite
536 .aead_alg
537 .extract_keys(client_key, client_iv)?;
538 let server_secrets = self
539 .ks
540 .suite
541 .aead_alg
542 .extract_keys(server_key, server_iv)?;
543
544 let (tx, rx) = match side {
545 Side::Client => (client_secrets, server_secrets),
546 Side::Server => (server_secrets, client_secrets),
547 };
548 Ok(PartiallyExtractedSecrets { tx, rx })
549 }
550}
551
552impl KeySchedule {
553 fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
554 Self {
555 current: suite
556 .hkdf_provider
557 .extract_from_secret(None, secret),
558 suite,
559 }
560 }
561
562 fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
563 let expander = self
564 .suite
565 .hkdf_provider
566 .expander_for_okm(secret);
567 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg.key_len());
568 let iv = derive_traffic_iv(expander.as_ref());
569
570 common
571 .record_layer
572 .set_message_encrypter(self.suite.aead_alg.encrypter(key, iv));
573 }
574
575 fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
576 common
577 .record_layer
578 .set_message_decrypter(self.derive_decrypter(secret));
579 }
580
581 fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
582 let expander = self
583 .suite
584 .hkdf_provider
585 .expander_for_okm(secret);
586 let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg.key_len());
587 let iv = derive_traffic_iv(expander.as_ref());
588 self.suite.aead_alg.decrypter(key, iv)
589 }
590
591 fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
592 Self {
593 current: suite
594 .hkdf_provider
595 .extract_from_zero_ikm(None),
596 suite,
597 }
598 }
599
600 /// Input the empty secret.
601 fn input_empty(&mut self) {
602 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
603 self.current = self
604 .suite
605 .hkdf_provider
606 .extract_from_zero_ikm(Some(salt.as_ref()));
607 }
608
609 /// Input the given secret.
610 #[cfg(all(test, any(feature = "ring", feature = "aws_lc_rs")))]
611 fn input_secret(&mut self, secret: &[u8]) {
612 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
613 self.current = self
614 .suite
615 .hkdf_provider
616 .extract_from_secret(Some(salt.as_ref()), secret);
617 }
618
619 /// Input the shared secret resulting from completing the given key exchange.
620 fn input_from_key_exchange(
621 &mut self,
622 kx: Box<dyn ActiveKeyExchange>,
623 peer_public_key: &[u8],
624 ) -> Result<(), Error> {
625 let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
626 self.current = self
627 .suite
628 .hkdf_provider
629 .extract_from_kx_shared_secret(Some(salt.as_ref()), kx, peer_public_key)?;
630 Ok(())
631 }
632
633 /// Derive a secret of given `kind`, using current handshake hash `hs_hash`.
634 fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
635 hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
636 }
637
638 fn derive_logged_secret(
639 &self,
640 kind: SecretKind,
641 hs_hash: &[u8],
642 key_log: &dyn KeyLog,
643 client_random: &[u8; 32],
644 ) -> OkmBlock {
645 let output = self.derive(kind, hs_hash);
646
647 let log_label = kind
648 .log_label()
649 .expect("not a loggable secret");
650 if key_log.will_log(log_label) {
651 key_log.log(log_label, client_random, output.as_ref());
652 }
653 output
654 }
655
656 /// Derive a secret of given `kind` using the hash of the empty string
657 /// for the handshake hash. Useful only for
658 /// `SecretKind::ResumptionPSKBinderKey` and
659 /// `SecretKind::DerivedSecret`.
660 fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
661 let empty_hash = self
662 .suite
663 .common
664 .hash_provider
665 .start()
666 .finish();
667 self.derive(kind, empty_hash.as_ref())
668 }
669
670 /// Sign the finished message consisting of `hs_hash` using a current
671 /// traffic secret.
672 fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
673 self.sign_verify_data(base_key, hs_hash)
674 }
675
676 /// Sign the finished message consisting of `hs_hash` using the key material
677 /// `base_key`.
678 fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
679 let expander = self
680 .suite
681 .hkdf_provider
682 .expander_for_okm(base_key);
683 let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
684
685 self.suite
686 .hkdf_provider
687 .hmac_sign(&hmac_key, hs_hash.as_ref())
688 }
689
690 /// Derive the next application traffic secret, returning it.
691 fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
692 let expander = self
693 .suite
694 .hkdf_provider
695 .expander_for_okm(base_key);
696 hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
697 }
698
699 /// Derive the PSK to use given a resumption_master_secret and
700 /// ticket_nonce.
701 fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
702 let expander = self
703 .suite
704 .hkdf_provider
705 .expander_for_okm(rms);
706 hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
707 }
708
709 fn export_keying_material(
710 &self,
711 current_exporter_secret: &OkmBlock,
712 out: &mut [u8],
713 label: &[u8],
714 context: Option<&[u8]>,
715 ) -> Result<(), Error> {
716 let secret = {
717 let h_empty = self
718 .suite
719 .common
720 .hash_provider
721 .hash(&[]);
722
723 let expander = self
724 .suite
725 .hkdf_provider
726 .expander_for_okm(current_exporter_secret);
727 hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
728 };
729
730 let h_context = self
731 .suite
732 .common
733 .hash_provider
734 .hash(context.unwrap_or(&[]));
735
736 let expander = self
737 .suite
738 .hkdf_provider
739 .expander_for_okm(&secret);
740 hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
741 .map_err(|_| Error::General("exporting too much".to_string()))
742 }
743}
744
745/// [HKDF-Expand-Label] where the output length is a compile-time constant, and therefore
746/// it is infallible.
747///
748/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
749pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
750 expander: &dyn HkdfExpander,
751 label: &[u8],
752 context: &[u8],
753) -> T {
754 hkdf_expand_label_inner(expander, label, context, N, |e: &dyn HkdfExpander, info: &[&[u8]]| expand(expander:e, info))
755}
756
757/// [HKDF-Expand-Label] where the output is one block in size.
758pub(crate) fn hkdf_expand_label_block(
759 expander: &dyn HkdfExpander,
760 label: &[u8],
761 context: &[u8],
762) -> OkmBlock {
763 hkdf_expand_label_inner(expander, label, context, n:expander.hash_len(), |e: &dyn HkdfExpander, info: &[&[u8]]| {
764 e.expand_block(info)
765 })
766}
767
768/// [HKDF-Expand-Label] where the output is an AEAD key.
769pub(crate) fn hkdf_expand_label_aead_key(
770 expander: &dyn HkdfExpander,
771 key_len: usize,
772 label: &[u8],
773 context: &[u8],
774) -> AeadKey {
775 hkdf_expand_label_inner(expander, label, context, n:key_len, |e: &dyn HkdfExpander, info: &[&[u8]]| {
776 let key: AeadKey = expand(expander:e, info);
777 key.with_length(key_len)
778 })
779}
780
781/// [HKDF-Expand-Label] where the output is a slice.
782///
783/// This can fail because HKDF-Expand is limited in its maximum output length.
784fn hkdf_expand_label_slice(
785 expander: &dyn HkdfExpander,
786 label: &[u8],
787 context: &[u8],
788 output: &mut [u8],
789) -> Result<(), OutputLengthError> {
790 hkdf_expand_label_inner(expander, label, context, n:output.len(), |e: &dyn HkdfExpander, info: &[&[u8]]| {
791 e.expand_slice(info, output)
792 })
793}
794
795pub(crate) fn derive_traffic_key(expander: &dyn HkdfExpander, aead_key_len: usize) -> AeadKey {
796 hkdf_expand_label_aead_key(expander, aead_key_len, label:b"key", &[])
797}
798
799pub(crate) fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
800 hkdf_expand_label(expander, label:b"iv", &[])
801}
802
803fn hkdf_expand_label_inner<F, T>(
804 expander: &dyn HkdfExpander,
805 label: &[u8],
806 context: &[u8],
807 n: usize,
808 f: F,
809) -> T
810where
811 F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
812{
813 const LABEL_PREFIX: &[u8] = b"tls13 ";
814
815 let output_len: [u8; 2] = u16::to_be_bytes(self:n as u16);
816 let label_len: [u8; 1] = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
817 let context_len: [u8; 1] = u8::to_be_bytes(self:context.len() as u8);
818
819 let info: &[&[u8]; 6] = &[
820 &output_len[..],
821 &label_len[..],
822 LABEL_PREFIX,
823 label,
824 &context_len[..],
825 context,
826 ];
827
828 f(expander, info)
829}
830
831#[cfg(all(test, any(feature = "ring", feature = "aws_lc_rs")))]
832mod tests {
833 use core::fmt::Debug;
834
835 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
836 use crate::test_provider::ring_like::aead;
837 use crate::test_provider::tls13::{
838 TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
839 };
840 use crate::KeyLog;
841
842 #[test]
843 fn test_vectors() {
844 /* These test vectors generated with OpenSSL. */
845 let hs_start_hash = [
846 0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
847 0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
848 0x75, 0x88, 0x1c, 0x0a,
849 ];
850
851 let hs_full_hash = [
852 0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
853 0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
854 0xbb, 0xeb, 0x23, 0xe2,
855 ];
856
857 let ecdhe_secret = [
858 0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
859 0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
860 0x71, 0xdf, 0x4b, 0x40,
861 ];
862
863 let client_hts = [
864 0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
865 0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
866 0x35, 0xcf, 0x46, 0xab,
867 ];
868
869 let client_hts_key = [
870 0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
871 0x85, 0xa7,
872 ];
873
874 let client_hts_iv = [
875 0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
876 ];
877
878 let server_hts = [
879 0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
880 0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
881 0x29, 0xa8, 0x87, 0x59,
882 ];
883
884 let server_hts_key = [
885 0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
886 0xbc, 0x54,
887 ];
888
889 let server_hts_iv = [
890 0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
891 ];
892
893 let client_ats = [
894 0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
895 0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
896 0x20, 0x6d, 0xbd, 0xa5,
897 ];
898
899 let client_ats_key = [
900 0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
901 0x57, 0x2e,
902 ];
903
904 let client_ats_iv = [
905 0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
906 ];
907
908 let server_ats = [
909 0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
910 0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
911 0x4c, 0x23, 0x21, 0x92,
912 ];
913
914 let server_ats_key = [
915 0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
916 0x2b, 0xb3,
917 ];
918
919 let server_ats_iv = [
920 0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
921 ];
922
923 let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
924 ks.input_secret(&ecdhe_secret);
925
926 assert_traffic_secret(
927 &ks,
928 SecretKind::ClientHandshakeTrafficSecret,
929 &hs_start_hash,
930 &client_hts,
931 &client_hts_key,
932 &client_hts_iv,
933 );
934
935 assert_traffic_secret(
936 &ks,
937 SecretKind::ServerHandshakeTrafficSecret,
938 &hs_start_hash,
939 &server_hts,
940 &server_hts_key,
941 &server_hts_iv,
942 );
943
944 ks.input_empty();
945
946 assert_traffic_secret(
947 &ks,
948 SecretKind::ClientApplicationTrafficSecret,
949 &hs_full_hash,
950 &client_ats,
951 &client_ats_key,
952 &client_ats_iv,
953 );
954
955 assert_traffic_secret(
956 &ks,
957 SecretKind::ServerApplicationTrafficSecret,
958 &hs_full_hash,
959 &server_ats,
960 &server_ats_key,
961 &server_ats_iv,
962 );
963 }
964
965 fn assert_traffic_secret(
966 ks: &KeySchedule,
967 kind: SecretKind,
968 hash: &[u8],
969 expected_traffic_secret: &[u8],
970 expected_key: &[u8],
971 expected_iv: &[u8],
972 ) {
973 #[derive(Debug)]
974 struct Log<'a>(&'a [u8]);
975 impl KeyLog for Log<'_> {
976 fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
977 assert_eq!(self.0, secret);
978 }
979 }
980 let log = Log(expected_traffic_secret);
981 let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
982
983 // Since we can't test key equality, we test the output of sealing with the key instead.
984 let aead_alg = &aead::AES_128_GCM;
985 let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
986 .hkdf_provider
987 .expander_for_okm(&traffic_secret);
988 let key = derive_traffic_key(expander.as_ref(), aead_alg.key_len());
989 let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
990 let seal_output = seal_zeroes(key);
991 let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
992 let expected_seal_output = seal_zeroes(expected_key);
993 assert_eq!(seal_output, expected_seal_output);
994 assert!(seal_output.len() >= 48); // Sanity check.
995
996 let iv = derive_traffic_iv(expander.as_ref());
997 assert_eq!(iv.as_ref(), expected_iv);
998 }
999
1000 fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
1001 let key = aead::LessSafeKey::new(key);
1002 let mut seal_output = vec![0; 32];
1003 key.seal_in_place_append_tag(
1004 aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
1005 aead::Aad::empty(),
1006 &mut seal_output,
1007 )
1008 .unwrap();
1009 seal_output
1010 }
1011}
1012
1013#[cfg(bench)]
1014mod benchmarks {
1015 #[cfg(any(feature = "ring", feature = "aws_lc_rs"))]
1016 #[bench]
1017 fn bench_sha256(b: &mut test::Bencher) {
1018 use core::fmt::Debug;
1019
1020 use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
1021 use crate::test_provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1022 use crate::KeyLog;
1023
1024 fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1025 #[derive(Debug)]
1026 struct Log;
1027
1028 impl KeyLog for Log {
1029 fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1030 }
1031
1032 let hash = [0u8; 32];
1033 let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1034 let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1035 .hkdf_provider
1036 .expander_for_okm(&traffic_secret);
1037 test::black_box(derive_traffic_key(
1038 traffic_secret_expander.as_ref(),
1039 TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1040 .aead_alg
1041 .key_len(),
1042 ));
1043 test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
1044 }
1045
1046 b.iter(|| {
1047 let mut ks =
1048 KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1049 ks.input_secret(&[0u8; 32]);
1050
1051 extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1052 extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1053
1054 ks.input_empty();
1055
1056 extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1057 extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1058 });
1059 }
1060}
1061