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        Ok(())
537    }
538
539    pub(crate) fn update_decrypter(&mut self, common: &mut CommonState) {
540        let secret = self.next_application_traffic_secret(common.side.peer());
541        self.ks.set_decrypter(&secret, common);
542    }
543
544    pub(crate) fn next_application_traffic_secret(&mut self, side: Side) -> OkmBlock {
545        let current = match side {
546            Side::Client => &mut self.current_client_traffic_secret,
547            Side::Server => &mut self.current_server_traffic_secret,
548        };
549
550        let secret = self.ks.derive_next(current);
551        *current = secret.clone();
552        secret
553    }
554
555    pub(crate) fn export_keying_material(
556        &self,
557        out: &mut [u8],
558        label: &[u8],
559        context: Option<&[u8]>,
560    ) -> Result<(), Error> {
561        self.ks
562            .export_keying_material(&self.current_exporter_secret, out, label, context)
563    }
564
565    pub(crate) fn refresh_traffic_secret(
566        &mut self,
567        side: Side,
568    ) -> Result<ConnectionTrafficSecrets, Error> {
569        let secret = self.next_application_traffic_secret(side);
570        let (key, iv) = expand_secret(
571            &secret,
572            self.ks.suite.hkdf_provider,
573            self.ks.suite.aead_alg.key_len(),
574        );
575        Ok(self
576            .ks
577            .suite
578            .aead_alg
579            .extract_keys(key, iv)?)
580    }
581
582    pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
583        let (client_key, client_iv) = expand_secret(
584            &self.current_client_traffic_secret,
585            self.ks.suite.hkdf_provider,
586            self.ks.suite.aead_alg.key_len(),
587        );
588        let (server_key, server_iv) = expand_secret(
589            &self.current_server_traffic_secret,
590            self.ks.suite.hkdf_provider,
591            self.ks.suite.aead_alg.key_len(),
592        );
593        let client_secrets = self
594            .ks
595            .suite
596            .aead_alg
597            .extract_keys(client_key, client_iv)?;
598        let server_secrets = self
599            .ks
600            .suite
601            .aead_alg
602            .extract_keys(server_key, server_iv)?;
603
604        let (tx, rx) = match side {
605            Side::Client => (client_secrets, server_secrets),
606            Side::Server => (server_secrets, client_secrets),
607        };
608        Ok(PartiallyExtractedSecrets { tx, rx })
609    }
610}
611
612pub(crate) struct KeyScheduleResumption {
613    ks: KeyScheduleSuite,
614    resumption_master_secret: OkmBlock,
615}
616
617impl KeyScheduleResumption {
618    pub(crate) fn derive_ticket_psk(&self, nonce: &[u8]) -> OkmBlock {
619        self.ks
620            .derive_ticket_psk(&self.resumption_master_secret, nonce)
621    }
622}
623
624fn expand_secret(secret: &OkmBlock, hkdf: &'static dyn Hkdf, aead_key_len: usize) -> (AeadKey, Iv) {
625    let expander = hkdf.expander_for_okm(secret);
626
627    (
628        hkdf_expand_label_aead_key(expander.as_ref(), aead_key_len, b"key", &[]),
629        hkdf_expand_label(expander.as_ref(), b"iv", &[]),
630    )
631}
632
633/// This is the TLS1.3 key schedule.  It stores the current secret and
634/// the type of hash.  This isn't used directly; but only through the
635/// typestates.
636struct KeySchedule {
637    current: Box<dyn HkdfExpander>,
638    inner: KeyScheduleSuite,
639}
640
641impl KeySchedule {
642    fn new(suite: &'static Tls13CipherSuite, secret: &[u8]) -> Self {
643        Self {
644            current: suite
645                .hkdf_provider
646                .extract_from_secret(None, secret),
647            inner: suite.into(),
648        }
649    }
650
651    /// Creates a key schedule without a PSK.
652    fn new_with_empty_secret(suite: &'static Tls13CipherSuite) -> Self {
653        Self {
654            current: suite
655                .hkdf_provider
656                .extract_from_zero_ikm(None),
657            inner: suite.into(),
658        }
659    }
660
661    /// Input the empty secret.
662    ///
663    /// RFC 8446: "If a given secret is not available, then the
664    /// 0-value consisting of a string of Hash.length bytes set
665    /// to zeros is used."
666    fn input_empty(&mut self) {
667        let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
668        self.current = self
669            .suite
670            .hkdf_provider
671            .extract_from_zero_ikm(Some(salt.as_ref()));
672    }
673
674    /// Input the given secret.
675    fn input_secret(&mut self, secret: &[u8]) {
676        let salt = self.derive_for_empty_hash(SecretKind::DerivedSecret);
677        self.current = self
678            .suite
679            .hkdf_provider
680            .extract_from_secret(Some(salt.as_ref()), secret);
681    }
682
683    /// Derive a secret of given `kind`, using current handshake hash `hs_hash`.
684    ///
685    /// More specifically
686    /// ```text
687    ///    Derive-Secret(., "derived", Messages)
688    /// ```
689    /// where `hs_hash` is `Messages`.
690    fn derive(&self, kind: SecretKind, hs_hash: &[u8]) -> OkmBlock {
691        hkdf_expand_label_block(self.current.as_ref(), kind.to_bytes(), hs_hash)
692    }
693
694    fn derive_logged_secret(
695        &self,
696        kind: SecretKind,
697        hs_hash: &[u8],
698        key_log: &dyn KeyLog,
699        client_random: &[u8; 32],
700    ) -> OkmBlock {
701        let output = self.derive(kind, hs_hash);
702
703        let log_label = kind
704            .log_label()
705            .expect("not a loggable secret");
706        if key_log.will_log(log_label) {
707            key_log.log(log_label, client_random, output.as_ref());
708        }
709        output
710    }
711
712    /// Derive a secret of given `kind` using the hash of the empty string
713    /// for the handshake hash.
714    ///
715    /// More specifically:
716    /// ```text
717    /// Derive-Secret(., Label, "")
718    /// ```
719    /// where `kind` is `Label`.
720    ///
721    /// Useful only for the following `SecretKind`s:
722    /// - `SecretKind::ExternalPskBinderKey`
723    /// - `SecretKind::ResumptionPSKBinderKey`
724    /// - `SecretKind::DerivedSecret`
725    fn derive_for_empty_hash(&self, kind: SecretKind) -> OkmBlock {
726        let hp = self.suite.common.hash_provider;
727        let empty_hash = hp
728            .algorithm()
729            .hash_for_empty_input()
730            .unwrap_or_else(|| hp.start().finish());
731        self.derive(kind, empty_hash.as_ref())
732    }
733}
734
735impl Deref for KeySchedule {
736    type Target = KeyScheduleSuite;
737
738    fn deref(&self) -> &Self::Target {
739        &self.inner
740    }
741}
742
743/// This is a component part of `KeySchedule`, and groups operations
744/// that do not depend on the root key schedule secret.
745#[derive(Clone, Copy)]
746struct KeyScheduleSuite {
747    suite: &'static Tls13CipherSuite,
748}
749
750impl KeyScheduleSuite {
751    fn set_encrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
752        let expander = self
753            .suite
754            .hkdf_provider
755            .expander_for_okm(secret);
756        let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
757        let iv = derive_traffic_iv(expander.as_ref());
758
759        common
760            .record_layer
761            .set_message_encrypter(
762                self.suite.aead_alg.encrypter(key, iv),
763                self.suite.common.confidentiality_limit,
764            );
765    }
766
767    fn set_decrypter(&self, secret: &OkmBlock, common: &mut CommonState) {
768        common
769            .record_layer
770            .set_message_decrypter(self.derive_decrypter(secret));
771    }
772
773    fn derive_decrypter(&self, secret: &OkmBlock) -> Box<dyn MessageDecrypter> {
774        let expander = self
775            .suite
776            .hkdf_provider
777            .expander_for_okm(secret);
778        let key = derive_traffic_key(expander.as_ref(), self.suite.aead_alg);
779        let iv = derive_traffic_iv(expander.as_ref());
780        self.suite.aead_alg.decrypter(key, iv)
781    }
782
783    /// Sign the finished message consisting of `hs_hash` using a current
784    /// traffic secret.
785    ///
786    /// See RFC 8446 section 4.4.4.
787    fn sign_finish(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
788        self.sign_verify_data(base_key, hs_hash)
789    }
790
791    /// Sign the finished message consisting of `hs_hash` using the key material
792    /// `base_key`.
793    ///
794    /// See RFC 8446 section 4.4.4.
795    fn sign_verify_data(&self, base_key: &OkmBlock, hs_hash: &hash::Output) -> hmac::Tag {
796        let expander = self
797            .suite
798            .hkdf_provider
799            .expander_for_okm(base_key);
800        let hmac_key = hkdf_expand_label_block(expander.as_ref(), b"finished", &[]);
801
802        self.suite
803            .hkdf_provider
804            .hmac_sign(&hmac_key, hs_hash.as_ref())
805    }
806
807    /// Derive the next application traffic secret, returning it.
808    fn derive_next(&self, base_key: &OkmBlock) -> OkmBlock {
809        let expander = self
810            .suite
811            .hkdf_provider
812            .expander_for_okm(base_key);
813        hkdf_expand_label_block(expander.as_ref(), b"traffic upd", &[])
814    }
815
816    /// Derive the PSK to use given a resumption_master_secret and
817    /// ticket_nonce.
818    fn derive_ticket_psk(&self, rms: &OkmBlock, nonce: &[u8]) -> OkmBlock {
819        let expander = self
820            .suite
821            .hkdf_provider
822            .expander_for_okm(rms);
823        hkdf_expand_label_block(expander.as_ref(), b"resumption", nonce)
824    }
825
826    fn export_keying_material(
827        &self,
828        current_exporter_secret: &OkmBlock,
829        out: &mut [u8],
830        label: &[u8],
831        context: Option<&[u8]>,
832    ) -> Result<(), Error> {
833        let secret = {
834            let h_empty = self
835                .suite
836                .common
837                .hash_provider
838                .hash(&[]);
839
840            let expander = self
841                .suite
842                .hkdf_provider
843                .expander_for_okm(current_exporter_secret);
844            hkdf_expand_label_block(expander.as_ref(), label, h_empty.as_ref())
845        };
846
847        let h_context = self
848            .suite
849            .common
850            .hash_provider
851            .hash(context.unwrap_or(&[]));
852
853        let expander = self
854            .suite
855            .hkdf_provider
856            .expander_for_okm(&secret);
857        hkdf_expand_label_slice(expander.as_ref(), b"exporter", h_context.as_ref(), out)
858            .map_err(|_| Error::General("exporting too much".to_string()))
859    }
860}
861
862impl From<&'static Tls13CipherSuite> for KeyScheduleSuite {
863    fn from(suite: &'static Tls13CipherSuite) -> Self {
864        Self { suite }
865    }
866}
867
868/// [HKDF-Expand-Label] where the output is an AEAD key.
869///
870/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
871pub fn derive_traffic_key(
872    expander: &dyn HkdfExpander,
873    aead_alg: &dyn Tls13AeadAlgorithm,
874) -> AeadKey {
875    hkdf_expand_label_aead_key(expander, aead_alg.key_len(), b"key", &[])
876}
877
878/// [HKDF-Expand-Label] where the output is an IV.
879///
880/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
881pub fn derive_traffic_iv(expander: &dyn HkdfExpander) -> Iv {
882    hkdf_expand_label(expander, b"iv", &[])
883}
884
885/// [HKDF-Expand-Label] where the output length is a compile-time constant, and therefore
886/// it is infallible.
887///
888/// [HKDF-Expand-Label]: <https://www.rfc-editor.org/rfc/rfc8446#section-7.1>
889pub(crate) fn hkdf_expand_label<T: From<[u8; N]>, const N: usize>(
890    expander: &dyn HkdfExpander,
891    label: &[u8],
892    context: &[u8],
893) -> T {
894    hkdf_expand_label_inner(expander, label, context, N, |e, info| expand(e, info))
895}
896
897/// [HKDF-Expand-Label] where the output is one block in size.
898pub(crate) fn hkdf_expand_label_block(
899    expander: &dyn HkdfExpander,
900    label: &[u8],
901    context: &[u8],
902) -> OkmBlock {
903    hkdf_expand_label_inner(expander, label, context, expander.hash_len(), |e, info| {
904        e.expand_block(info)
905    })
906}
907
908/// [HKDF-Expand-Label] where the output is an AEAD key.
909pub(crate) fn hkdf_expand_label_aead_key(
910    expander: &dyn HkdfExpander,
911    key_len: usize,
912    label: &[u8],
913    context: &[u8],
914) -> AeadKey {
915    hkdf_expand_label_inner(expander, label, context, key_len, |e, info| {
916        let key: AeadKey = expand(e, info);
917        key.with_length(key_len)
918    })
919}
920
921/// [HKDF-Expand-Label] where the output is a slice.
922///
923/// This can fail because HKDF-Expand is limited in its maximum output length.
924fn hkdf_expand_label_slice(
925    expander: &dyn HkdfExpander,
926    label: &[u8],
927    context: &[u8],
928    output: &mut [u8],
929) -> Result<(), OutputLengthError> {
930    hkdf_expand_label_inner(expander, label, context, output.len(), |e, info| {
931        e.expand_slice(info, output)
932    })
933}
934
935pub(crate) fn server_ech_hrr_confirmation_secret(
936    hkdf_provider: &'static dyn Hkdf,
937    client_hello_inner_random: &[u8],
938    hs_hash: hash::Output,
939) -> [u8; 8] {
940    /*
941    Per ietf-tls-esni-17 section 7.2.1:
942    <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-7.2.1>
943    hrr_accept_confirmation = HKDF-Expand-Label(
944      HKDF-Extract(0, ClientHelloInner1.random),
945      "hrr ech accept confirmation",
946      transcript_hrr_ech_conf,
947      8)
948     */
949    hkdf_expand_label(
950        hkdf_provider
951            .extract_from_secret(None, client_hello_inner_random)
952            .as_ref(),
953        SecretKind::ServerEchHrrConfirmationSecret.to_bytes(),
954        hs_hash.as_ref(),
955    )
956}
957
958fn hkdf_expand_label_inner<F, T>(
959    expander: &dyn HkdfExpander,
960    label: &[u8],
961    context: &[u8],
962    n: usize,
963    f: F,
964) -> T
965where
966    F: FnOnce(&dyn HkdfExpander, &[&[u8]]) -> T,
967{
968    const LABEL_PREFIX: &[u8] = b"tls13 ";
969
970    let output_len = u16::to_be_bytes(n as u16);
971    let label_len = u8::to_be_bytes((LABEL_PREFIX.len() + label.len()) as u8);
972    let context_len = u8::to_be_bytes(context.len() as u8);
973
974    let info = &[
975        &output_len[..],
976        &label_len[..],
977        LABEL_PREFIX,
978        label,
979        &context_len[..],
980        context,
981    ];
982
983    f(expander, info)
984}
985
986/// The kinds of secret we can extract from `KeySchedule`.
987#[derive(Debug, Clone, Copy, PartialEq)]
988enum SecretKind {
989    ResumptionPskBinderKey,
990    ClientEarlyTrafficSecret,
991    ClientHandshakeTrafficSecret,
992    ServerHandshakeTrafficSecret,
993    ClientApplicationTrafficSecret,
994    ServerApplicationTrafficSecret,
995    ExporterMasterSecret,
996    ResumptionMasterSecret,
997    DerivedSecret,
998    ServerEchConfirmationSecret,
999    ServerEchHrrConfirmationSecret,
1000}
1001
1002impl SecretKind {
1003    fn to_bytes(self) -> &'static [u8] {
1004        use self::SecretKind::*;
1005        match self {
1006            ResumptionPskBinderKey => b"res binder",
1007            ClientEarlyTrafficSecret => b"c e traffic",
1008            ClientHandshakeTrafficSecret => b"c hs traffic",
1009            ServerHandshakeTrafficSecret => b"s hs traffic",
1010            ClientApplicationTrafficSecret => b"c ap traffic",
1011            ServerApplicationTrafficSecret => b"s ap traffic",
1012            ExporterMasterSecret => b"exp master",
1013            ResumptionMasterSecret => b"res master",
1014            DerivedSecret => b"derived",
1015            // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-7.2
1016            ServerEchConfirmationSecret => b"ech accept confirmation",
1017            // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#section-7.2.1
1018            ServerEchHrrConfirmationSecret => b"hrr ech accept confirmation",
1019        }
1020    }
1021
1022    fn log_label(self) -> Option<&'static str> {
1023        use self::SecretKind::*;
1024        Some(match self {
1025            ClientEarlyTrafficSecret => "CLIENT_EARLY_TRAFFIC_SECRET",
1026            ClientHandshakeTrafficSecret => "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
1027            ServerHandshakeTrafficSecret => "SERVER_HANDSHAKE_TRAFFIC_SECRET",
1028            ClientApplicationTrafficSecret => "CLIENT_TRAFFIC_SECRET_0",
1029            ServerApplicationTrafficSecret => "SERVER_TRAFFIC_SECRET_0",
1030            ExporterMasterSecret => "EXPORTER_SECRET",
1031            _ => {
1032                return None;
1033            }
1034        })
1035    }
1036}
1037
1038#[cfg(test)]
1039#[macro_rules_attribute::apply(test_for_each_provider)]
1040mod tests {
1041    use core::fmt::Debug;
1042    use std::prelude::v1::*;
1043    use std::vec;
1044
1045    use super::provider::ring_like::aead;
1046    use super::provider::tls13::{
1047        TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
1048    };
1049    use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
1050    use crate::KeyLog;
1051    use crate::msgs::enums::HashAlgorithm;
1052
1053    #[test]
1054    fn empty_hash() {
1055        let sha256 = super::provider::tls13::TLS13_AES_128_GCM_SHA256
1056            .tls13()
1057            .unwrap()
1058            .common
1059            .hash_provider;
1060        let sha384 = super::provider::tls13::TLS13_AES_256_GCM_SHA384
1061            .tls13()
1062            .unwrap()
1063            .common
1064            .hash_provider;
1065
1066        assert!(
1067            sha256.start().finish().as_ref()
1068                == HashAlgorithm::SHA256
1069                    .hash_for_empty_input()
1070                    .unwrap()
1071                    .as_ref()
1072        );
1073        assert!(
1074            sha384.start().finish().as_ref()
1075                == HashAlgorithm::SHA384
1076                    .hash_for_empty_input()
1077                    .unwrap()
1078                    .as_ref()
1079        );
1080
1081        // a theoretical example of unsupported hash
1082        assert!(
1083            HashAlgorithm::SHA1
1084                .hash_for_empty_input()
1085                .is_none()
1086        );
1087    }
1088
1089    #[test]
1090    fn test_vectors() {
1091        /* These test vectors generated with OpenSSL. */
1092        let hs_start_hash = [
1093            0xec, 0x14, 0x7a, 0x06, 0xde, 0xa3, 0xc8, 0x84, 0x6c, 0x02, 0xb2, 0x23, 0x8e, 0x41,
1094            0xbd, 0xdc, 0x9d, 0x89, 0xf9, 0xae, 0xa1, 0x7b, 0x5e, 0xfd, 0x4d, 0x74, 0x82, 0xaf,
1095            0x75, 0x88, 0x1c, 0x0a,
1096        ];
1097
1098        let hs_full_hash = [
1099            0x75, 0x1a, 0x3d, 0x4a, 0x14, 0xdf, 0xab, 0xeb, 0x68, 0xe9, 0x2c, 0xa5, 0x91, 0x8e,
1100            0x24, 0x08, 0xb9, 0xbc, 0xb0, 0x74, 0x89, 0x82, 0xec, 0x9c, 0x32, 0x30, 0xac, 0x30,
1101            0xbb, 0xeb, 0x23, 0xe2,
1102        ];
1103
1104        let ecdhe_secret = [
1105            0xe7, 0xb8, 0xfe, 0xf8, 0x90, 0x3b, 0x52, 0x0c, 0xb9, 0xa1, 0x89, 0x71, 0xb6, 0x9d,
1106            0xd4, 0x5d, 0xca, 0x53, 0xce, 0x2f, 0x12, 0xbf, 0x3b, 0xef, 0x93, 0x15, 0xe3, 0x12,
1107            0x71, 0xdf, 0x4b, 0x40,
1108        ];
1109
1110        let client_hts = [
1111            0x61, 0x7b, 0x35, 0x07, 0x6b, 0x9d, 0x0e, 0x08, 0xcf, 0x73, 0x1d, 0x94, 0xa8, 0x66,
1112            0x14, 0x78, 0x41, 0x09, 0xef, 0x25, 0x55, 0x51, 0x92, 0x1d, 0xd4, 0x6e, 0x04, 0x01,
1113            0x35, 0xcf, 0x46, 0xab,
1114        ];
1115
1116        let client_hts_key = [
1117            0x62, 0xd0, 0xdd, 0x00, 0xf6, 0x96, 0x19, 0xd3, 0xb8, 0x19, 0x3a, 0xb4, 0xa0, 0x95,
1118            0x85, 0xa7,
1119        ];
1120
1121        let client_hts_iv = [
1122            0xff, 0xf7, 0x5d, 0xf5, 0xad, 0x35, 0xd5, 0xcb, 0x3c, 0x53, 0xf3, 0xa9,
1123        ];
1124
1125        let server_hts = [
1126            0xfc, 0xf7, 0xdf, 0xe6, 0x4f, 0xa2, 0xc0, 0x4f, 0x62, 0x35, 0x38, 0x7f, 0x43, 0x4e,
1127            0x01, 0x42, 0x23, 0x36, 0xd9, 0xc0, 0x39, 0xde, 0x68, 0x47, 0xa0, 0xb9, 0xdd, 0xcf,
1128            0x29, 0xa8, 0x87, 0x59,
1129        ];
1130
1131        let server_hts_key = [
1132            0x04, 0x67, 0xf3, 0x16, 0xa8, 0x05, 0xb8, 0xc4, 0x97, 0xee, 0x67, 0x04, 0x7b, 0xbc,
1133            0xbc, 0x54,
1134        ];
1135
1136        let server_hts_iv = [
1137            0xde, 0x83, 0xa7, 0x3e, 0x9d, 0x81, 0x4b, 0x04, 0xc4, 0x8b, 0x78, 0x09,
1138        ];
1139
1140        let client_ats = [
1141            0xc1, 0x4a, 0x6d, 0x79, 0x76, 0xd8, 0x10, 0x2b, 0x5a, 0x0c, 0x99, 0x51, 0x49, 0x3f,
1142            0xee, 0x87, 0xdc, 0xaf, 0xf8, 0x2c, 0x24, 0xca, 0xb2, 0x14, 0xe8, 0xbe, 0x71, 0xa8,
1143            0x20, 0x6d, 0xbd, 0xa5,
1144        ];
1145
1146        let client_ats_key = [
1147            0xcc, 0x9f, 0x5f, 0x98, 0x0b, 0x5f, 0x10, 0x30, 0x6c, 0xba, 0xd7, 0xbe, 0x98, 0xd7,
1148            0x57, 0x2e,
1149        ];
1150
1151        let client_ats_iv = [
1152            0xb8, 0x09, 0x29, 0xe8, 0xd0, 0x2c, 0x70, 0xf6, 0x11, 0x62, 0xed, 0x6b,
1153        ];
1154
1155        let server_ats = [
1156            0x2c, 0x90, 0x77, 0x38, 0xd3, 0xf8, 0x37, 0x02, 0xd1, 0xe4, 0x59, 0x8f, 0x48, 0x48,
1157            0x53, 0x1d, 0x9f, 0x93, 0x65, 0x49, 0x1b, 0x9f, 0x7f, 0x52, 0xc8, 0x22, 0x29, 0x0d,
1158            0x4c, 0x23, 0x21, 0x92,
1159        ];
1160
1161        let server_ats_key = [
1162            0x0c, 0xb2, 0x95, 0x62, 0xd8, 0xd8, 0x8f, 0x48, 0xb0, 0x2c, 0xbf, 0xbe, 0xd7, 0xe6,
1163            0x2b, 0xb3,
1164        ];
1165
1166        let server_ats_iv = [
1167            0x0d, 0xb2, 0x8f, 0x98, 0x85, 0x86, 0xa1, 0xb7, 0xe4, 0xd5, 0xc6, 0x9c,
1168        ];
1169
1170        let mut ks = KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1171        ks.input_secret(&ecdhe_secret);
1172
1173        assert_traffic_secret(
1174            &ks,
1175            SecretKind::ClientHandshakeTrafficSecret,
1176            &hs_start_hash,
1177            &client_hts,
1178            &client_hts_key,
1179            &client_hts_iv,
1180        );
1181
1182        assert_traffic_secret(
1183            &ks,
1184            SecretKind::ServerHandshakeTrafficSecret,
1185            &hs_start_hash,
1186            &server_hts,
1187            &server_hts_key,
1188            &server_hts_iv,
1189        );
1190
1191        ks.input_empty();
1192
1193        assert_traffic_secret(
1194            &ks,
1195            SecretKind::ClientApplicationTrafficSecret,
1196            &hs_full_hash,
1197            &client_ats,
1198            &client_ats_key,
1199            &client_ats_iv,
1200        );
1201
1202        assert_traffic_secret(
1203            &ks,
1204            SecretKind::ServerApplicationTrafficSecret,
1205            &hs_full_hash,
1206            &server_ats,
1207            &server_ats_key,
1208            &server_ats_iv,
1209        );
1210    }
1211
1212    fn assert_traffic_secret(
1213        ks: &KeySchedule,
1214        kind: SecretKind,
1215        hash: &[u8],
1216        expected_traffic_secret: &[u8],
1217        expected_key: &[u8],
1218        expected_iv: &[u8],
1219    ) {
1220        #[derive(Debug)]
1221        struct Log<'a>(&'a [u8]);
1222        impl KeyLog for Log<'_> {
1223            fn log(&self, _label: &str, _client_random: &[u8], secret: &[u8]) {
1224                assert_eq!(self.0, secret);
1225            }
1226        }
1227        let log = Log(expected_traffic_secret);
1228        let traffic_secret = ks.derive_logged_secret(kind, hash, &log, &[0; 32]);
1229
1230        // Since we can't test key equality, we test the output of sealing with the key instead.
1231        let aead_alg = &aead::AES_128_GCM;
1232        let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
1233            .hkdf_provider
1234            .expander_for_okm(&traffic_secret);
1235        let key = derive_traffic_key(
1236            expander.as_ref(),
1237            TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg,
1238        );
1239        let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
1240        let seal_output = seal_zeroes(key);
1241        let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
1242        let expected_seal_output = seal_zeroes(expected_key);
1243        assert_eq!(seal_output, expected_seal_output);
1244        assert!(seal_output.len() >= 48); // Sanity check.
1245
1246        let iv = derive_traffic_iv(expander.as_ref());
1247        assert_eq!(iv.as_ref(), expected_iv);
1248    }
1249
1250    fn seal_zeroes(key: aead::UnboundKey) -> Vec<u8> {
1251        let key = aead::LessSafeKey::new(key);
1252        let mut seal_output = vec![0; 32];
1253        key.seal_in_place_append_tag(
1254            aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]),
1255            aead::Aad::empty(),
1256            &mut seal_output,
1257        )
1258        .unwrap();
1259        seal_output
1260    }
1261}
1262
1263#[cfg(all(test, bench))]
1264#[macro_rules_attribute::apply(bench_for_each_provider)]
1265mod benchmarks {
1266    #[bench]
1267    fn bench_sha256(b: &mut test::Bencher) {
1268        use core::fmt::Debug;
1269
1270        use super::provider::tls13::TLS13_CHACHA20_POLY1305_SHA256_INTERNAL;
1271        use super::{KeySchedule, SecretKind, derive_traffic_iv, derive_traffic_key};
1272        use crate::KeyLog;
1273
1274        fn extract_traffic_secret(ks: &KeySchedule, kind: SecretKind) {
1275            #[derive(Debug)]
1276            struct Log;
1277
1278            impl KeyLog for Log {
1279                fn log(&self, _label: &str, _client_random: &[u8], _secret: &[u8]) {}
1280            }
1281
1282            let hash = [0u8; 32];
1283            let traffic_secret = ks.derive_logged_secret(kind, &hash, &Log, &[0u8; 32]);
1284            let traffic_secret_expander = TLS13_CHACHA20_POLY1305_SHA256_INTERNAL
1285                .hkdf_provider
1286                .expander_for_okm(&traffic_secret);
1287            test::black_box(derive_traffic_key(
1288                traffic_secret_expander.as_ref(),
1289                TLS13_CHACHA20_POLY1305_SHA256_INTERNAL.aead_alg,
1290            ));
1291            test::black_box(derive_traffic_iv(traffic_secret_expander.as_ref()));
1292        }
1293
1294        b.iter(|| {
1295            let mut ks =
1296                KeySchedule::new_with_empty_secret(TLS13_CHACHA20_POLY1305_SHA256_INTERNAL);
1297            ks.input_secret(&[0u8; 32]);
1298
1299            extract_traffic_secret(&ks, SecretKind::ClientHandshakeTrafficSecret);
1300            extract_traffic_secret(&ks, SecretKind::ServerHandshakeTrafficSecret);
1301
1302            ks.input_empty();
1303
1304            extract_traffic_secret(&ks, SecretKind::ClientApplicationTrafficSecret);
1305            extract_traffic_secret(&ks, SecretKind::ServerApplicationTrafficSecret);
1306        });
1307    }
1308}