rustls/tls13/
key_schedule.rs

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::{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/// 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 }: 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(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(), 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, 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, info| expand(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, expander.hash_len(), |e, info| {
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, key_len, |e, info| {
831        let key: AeadKey = expand(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, 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    /*
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        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        /* 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::{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}