tlspuffin/tls/
key_schedule.rs

1use puffin::algebra::error::FnError;
2use ring::digest;
3use ring::hkdf::Prk;
4
5use super::rustls::msgs::handshake::Random;
6use crate::tls::key_exchange::tls13_key_exchange;
7use crate::tls::rustls::hash_hs::HandshakeHash;
8use crate::tls::rustls::key_log::NoKeyLog;
9use crate::tls::rustls::msgs::enums::NamedGroup;
10use crate::tls::rustls::suites::SupportedCipherSuite;
11use crate::tls::rustls::tls13::key_schedule::{
12    KeyScheduleEarly, KeyScheduleHandshake, KeyScheduleHandshakeStart, KeySchedulePreHandshake,
13    KeyScheduleTrafficWithClientFinishedPending,
14};
15
16pub fn tls13_handshake_traffic_secret(
17    server_hello: &HandshakeHash,
18    server_key_share: &Option<Vec<u8>>,
19    psk: &Option<Vec<u8>>,
20    client: bool,
21    group: &NamedGroup,
22    client_random: &Random,
23    suite: &SupportedCipherSuite,
24) -> Result<(Prk, KeyScheduleHandshake), FnError> {
25    let key_schedule = dhe_key_schedule(suite, group, server_key_share, psk)?;
26
27    let (hs, client_secret, server_secret) = key_schedule.derive_handshake_secrets(
28        &server_hello.get_current_hash_raw(),
29        &NoKeyLog {},
30        &client_random.0,
31    );
32
33    Ok((if client { client_secret } else { server_secret }, hs))
34}
35
36/// Compute the client/server secret from a raw shared secret
37/// This function is used to decrypt knowledges using the secret extracted
38/// through the Finished claim
39pub fn tls13_handshake_traffic_secret_from_shared_secret(
40    server_hello_transcript: &HandshakeHash,
41    client_random: &Random,
42    client: bool,
43    suite: &SupportedCipherSuite,
44    extracted_shared_secret: &Vec<u8>,
45) -> Result<(Prk, KeyScheduleHandshake), FnError> {
46    let hkdf_algorithm = suite
47        .tls13()
48        .ok_or_else(|| FnError::Crypto("No tls 1.3 suite".to_owned()))?
49        .hkdf_algorithm;
50    let key_schedule =
51        KeyScheduleHandshakeStart::new_with_secret(hkdf_algorithm, extracted_shared_secret);
52    let (hs, client_secret, server_secret) = key_schedule.derive_handshake_secrets(
53        &server_hello_transcript.get_current_hash_raw(),
54        &NoKeyLog {},
55        &client_random.0,
56    );
57
58    Ok((if client { client_secret } else { server_secret }, hs))
59}
60
61pub fn tls13_application_traffic_secret(
62    server_hello: &HandshakeHash,
63    server_finished: &HandshakeHash,
64    server_key_share: &Option<Vec<u8>>,
65    psk: &Option<Vec<u8>>,
66    group: &NamedGroup,
67    client: bool,
68    client_random: &Random,
69    suite: &SupportedCipherSuite,
70) -> Result<(Prk, KeyScheduleTrafficWithClientFinishedPending), FnError> {
71    let (_key, key_schedule) = tls13_handshake_traffic_secret(
72        server_hello,
73        server_key_share,
74        psk,
75        client,
76        group,
77        client_random,
78        suite,
79    )?;
80
81    let (pending, client_secret, server_secret) = key_schedule
82        .into_traffic_with_client_finished_pending_raw(
83            &server_finished.get_current_hash_raw(),
84            &NoKeyLog {},
85            &client_random.0,
86        );
87    Ok((if client { client_secret } else { server_secret }, pending))
88}
89
90pub fn tls13_derive_psk(
91    server_hello: &HandshakeHash,
92    server_finished: &HandshakeHash,
93    client_finished: &HandshakeHash,
94    server_key_share: &Option<Vec<u8>>,
95    new_ticket_nonce: &[u8],
96    group: &NamedGroup,
97    client_random: &Random,
98    suite: &SupportedCipherSuite,
99) -> Result<Vec<u8>, FnError> {
100    let (_, pending) = tls13_application_traffic_secret(
101        server_hello,
102        server_finished,
103        server_key_share,
104        &None,
105        group,
106        true,
107        client_random,
108        suite,
109    )?;
110
111    let (traffic, _tag, _client_secret) =
112        pending.sign_client_finish_raw(&server_finished.get_current_hash_raw());
113    let psk = traffic.resumption_master_secret_and_derive_ticket_psk_raw(
114        &client_finished.get_current_hash_raw(),
115        new_ticket_nonce,
116    );
117
118    Ok(psk)
119}
120
121pub fn dhe_key_schedule(
122    suite: &SupportedCipherSuite,
123    group: &NamedGroup,
124    server_key_share: &Option<Vec<u8>>,
125    psk: &Option<Vec<u8>>,
126) -> Result<KeyScheduleHandshakeStart, FnError> {
127    let hkdf_algorithm = suite
128        .tls13()
129        .ok_or_else(|| FnError::Crypto("No tls 1.3 suite".to_owned()))?
130        .hkdf_algorithm;
131
132    // Key Schedule with or without PSK
133    let key_schedule = match (server_key_share, psk) {
134        (Some(server_key_share), Some(psk)) => {
135            let shared_secret = tls13_key_exchange(server_key_share, group)?;
136            let early = KeyScheduleEarly::new(hkdf_algorithm, psk.as_slice());
137            let pre: KeySchedulePreHandshake = early.into();
138            Ok(pre.into_handshake(&shared_secret))
139        }
140        (Some(server_key_share), None) => {
141            let shared_secret = tls13_key_exchange(server_key_share, group)?;
142            Ok(KeySchedulePreHandshake::new(hkdf_algorithm).into_handshake(&shared_secret))
143        }
144        (None, Some(psk)) => {
145            // Note: his empty secret is not specified in the RFC 8446
146            let zeroes = [0u8; digest::MAX_OUTPUT_LEN];
147            let early = KeyScheduleEarly::new(hkdf_algorithm, psk.as_slice());
148            let pre: KeySchedulePreHandshake = early.into();
149            Ok(pre.into_handshake(
150                &zeroes[..hkdf_algorithm
151                    .hmac_algorithm()
152                    .digest_algorithm()
153                    .output_len],
154            ))
155        }
156        (None, None) => Err(FnError::Malformed(
157            "Need at least a key share or a psk".to_owned(),
158        )),
159    };
160
161    key_schedule
162}