rustls/tls13/
key_schedule.rs

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