Skip to main content

rustls/tls13/
key_schedule.rs

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