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