rustls/tls12/
mod.rs

1use alloc::boxed::Box;
2use alloc::vec;
3use alloc::vec::Vec;
4use core::fmt;
5
6use zeroize::Zeroize;
7
8use crate::common_state::{CommonState, Side};
9use crate::conn::ConnectionRandoms;
10use crate::crypto;
11use crate::crypto::cipher::{AeadKey, MessageDecrypter, MessageEncrypter, Tls12AeadAlgorithm};
12use crate::crypto::hash;
13use crate::enums::{AlertDescription, SignatureScheme};
14use crate::error::{Error, InvalidMessage};
15use crate::msgs::codec::{Codec, Reader};
16use crate::msgs::handshake::{KeyExchangeAlgorithm, KxDecode};
17use crate::suites::{CipherSuiteCommon, PartiallyExtractedSecrets, SupportedCipherSuite};
18
19/// A TLS 1.2 cipher suite supported by rustls.
20pub struct Tls12CipherSuite {
21    /// Common cipher suite fields.
22    pub common: CipherSuiteCommon,
23
24    /// How to compute the TLS1.2 PRF for the suite's hash function.
25    ///
26    /// If you have a TLS1.2 PRF implementation, you should directly implement the [`crypto::tls12::Prf`] trait.
27    ///
28    /// If not, you can implement the [`crypto::hmac::Hmac`] trait (and associated), and then use
29    /// [`crypto::tls12::PrfUsingHmac`].
30    pub prf_provider: &'static dyn crypto::tls12::Prf,
31
32    /// How to exchange/agree keys.
33    ///
34    /// In TLS1.2, the key exchange method (eg, Elliptic Curve Diffie-Hellman with Ephemeral keys -- ECDHE)
35    /// is baked into the cipher suite, but the details to achieve it are negotiated separately.
36    ///
37    /// This controls how protocol messages (like the `ClientKeyExchange` message) are interpreted
38    /// once this cipher suite has been negotiated.
39    pub kx: KeyExchangeAlgorithm,
40
41    /// How to sign messages for authentication.
42    ///
43    /// This is a set of [`SignatureScheme`]s that are usable once this cipher suite has been
44    /// negotiated.
45    ///
46    /// The precise scheme used is then chosen from this set by the selected authentication key.
47    pub sign: &'static [SignatureScheme],
48
49    /// How to produce a [`MessageDecrypter`] or [`MessageEncrypter`]
50    /// from raw key material.
51    pub aead_alg: &'static dyn Tls12AeadAlgorithm,
52}
53
54impl Tls12CipherSuite {
55    /// Resolve the set of supported [`SignatureScheme`]s from the
56    /// offered signature schemes.  If we return an empty
57    /// set, the handshake terminates.
58    pub fn resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme> {
59        self.sign
60            .iter()
61            .filter(|pref| offered.contains(pref))
62            .cloned()
63            .collect()
64    }
65
66    /// Return `true` if this is backed by a FIPS-approved implementation.
67    ///
68    /// This means all the constituent parts that do cryptography return `true` for `fips()`.
69    pub fn fips(&self) -> bool {
70        self.common.fips() && self.prf_provider.fips() && self.aead_alg.fips()
71    }
72}
73
74impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
75    fn from(s: &'static Tls12CipherSuite) -> Self {
76        Self::Tls12(s)
77    }
78}
79
80impl PartialEq for Tls12CipherSuite {
81    fn eq(&self, other: &Self) -> bool {
82        self.common.suite == other.common.suite
83    }
84}
85
86impl fmt::Debug for Tls12CipherSuite {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        f.debug_struct("Tls12CipherSuite")
89            .field("suite", &self.common.suite)
90            .finish()
91    }
92}
93
94/// TLS1.2 per-connection keying material
95pub(crate) struct ConnectionSecrets {
96    pub(crate) randoms: ConnectionRandoms,
97    suite: &'static Tls12CipherSuite,
98    pub(crate) master_secret: [u8; 48],
99}
100
101impl ConnectionSecrets {
102    pub(crate) fn from_key_exchange(
103        kx: Box<dyn crypto::ActiveKeyExchange>,
104        peer_pub_key: &[u8],
105        ems_seed: Option<hash::Output>,
106        randoms: ConnectionRandoms,
107        suite: &'static Tls12CipherSuite,
108    ) -> Result<Self, Error> {
109        let mut ret = Self {
110            randoms,
111            suite,
112            master_secret: [0u8; 48],
113        };
114
115        let (label, seed) = match ems_seed {
116            Some(seed) => ("extended master secret", Seed::Ems(seed)),
117            None => (
118                "master secret",
119                Seed::Randoms(join_randoms(&ret.randoms.client, &ret.randoms.server)),
120            ),
121        };
122
123        // The API contract for for_key_exchange is that the caller guarantees `label` and `seed`
124        // slice parameters are non-empty.
125        // `label` is guaranteed non-empty because it's assigned from a `&str` above.
126        // `seed.as_ref()` is guaranteed non-empty by documentation on the AsRef impl.
127        ret.suite
128            .prf_provider
129            .for_key_exchange(
130                &mut ret.master_secret,
131                kx,
132                peer_pub_key,
133                label.as_bytes(),
134                seed.as_ref(),
135            )?;
136
137        Ok(ret)
138    }
139
140    pub(crate) fn new_resume(
141        randoms: ConnectionRandoms,
142        suite: &'static Tls12CipherSuite,
143        master_secret: &[u8],
144    ) -> Self {
145        let mut ret = Self {
146            randoms,
147            suite,
148            master_secret: [0u8; 48],
149        };
150        ret.master_secret
151            .copy_from_slice(master_secret);
152        ret
153    }
154
155    /// Make a `MessageCipherPair` based on the given supported ciphersuite `self.suite`,
156    /// and the session's `secrets`.
157    pub(crate) fn make_cipher_pair(&self, side: Side) -> MessageCipherPair {
158        // Make a key block, and chop it up.
159        // Note: we don't implement any ciphersuites with nonzero mac_key_len.
160        let key_block = self.make_key_block();
161        let shape = self.suite.aead_alg.key_block_shape();
162
163        let (client_write_key, key_block) = key_block.split_at(shape.enc_key_len);
164        let (server_write_key, key_block) = key_block.split_at(shape.enc_key_len);
165        let (client_write_iv, key_block) = key_block.split_at(shape.fixed_iv_len);
166        let (server_write_iv, extra) = key_block.split_at(shape.fixed_iv_len);
167
168        let (write_key, write_iv, read_key, read_iv) = match side {
169            Side::Client => (
170                client_write_key,
171                client_write_iv,
172                server_write_key,
173                server_write_iv,
174            ),
175            Side::Server => (
176                server_write_key,
177                server_write_iv,
178                client_write_key,
179                client_write_iv,
180            ),
181        };
182
183        (
184            self.suite
185                .aead_alg
186                .decrypter(AeadKey::new(read_key), read_iv),
187            self.suite
188                .aead_alg
189                .encrypter(AeadKey::new(write_key), write_iv, extra),
190        )
191    }
192
193    fn make_key_block(&self) -> Vec<u8> {
194        let shape = self.suite.aead_alg.key_block_shape();
195
196        let len = (shape.enc_key_len + shape.fixed_iv_len) * 2 + shape.explicit_nonce_len;
197
198        let mut out = vec![0u8; len];
199
200        // NOTE: opposite order to above for no good reason.
201        // Don't design security protocols on drugs, kids.
202        let randoms = join_randoms(&self.randoms.server, &self.randoms.client);
203        self.suite.prf_provider.for_secret(
204            &mut out,
205            &self.master_secret,
206            b"key expansion",
207            &randoms,
208        );
209
210        out
211    }
212
213    pub(crate) fn suite(&self) -> &'static Tls12CipherSuite {
214        self.suite
215    }
216
217    pub(crate) fn master_secret(&self) -> &[u8] {
218        &self.master_secret[..]
219    }
220
221    fn make_verify_data(&self, handshake_hash: &hash::Output, label: &[u8]) -> Vec<u8> {
222        let mut out = vec![0u8; 12];
223
224        self.suite.prf_provider.for_secret(
225            &mut out,
226            &self.master_secret,
227            label,
228            handshake_hash.as_ref(),
229        );
230
231        out
232    }
233
234    pub(crate) fn client_verify_data(&self, handshake_hash: &hash::Output) -> Vec<u8> {
235        self.make_verify_data(handshake_hash, b"client finished")
236    }
237
238    pub(crate) fn server_verify_data(&self, handshake_hash: &hash::Output) -> Vec<u8> {
239        self.make_verify_data(handshake_hash, b"server finished")
240    }
241
242    pub(crate) fn export_keying_material(
243        &self,
244        output: &mut [u8],
245        label: &[u8],
246        context: Option<&[u8]>,
247    ) {
248        let mut randoms = Vec::new();
249        randoms.extend_from_slice(&self.randoms.client);
250        randoms.extend_from_slice(&self.randoms.server);
251        if let Some(context) = context {
252            assert!(context.len() <= 0xffff);
253            (context.len() as u16).encode(&mut randoms);
254            randoms.extend_from_slice(context);
255        }
256
257        self.suite
258            .prf_provider
259            .for_secret(output, &self.master_secret, label, &randoms);
260    }
261
262    pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
263        // Make a key block, and chop it up
264        let key_block = self.make_key_block();
265        let shape = self.suite.aead_alg.key_block_shape();
266
267        let (client_key, key_block) = key_block.split_at(shape.enc_key_len);
268        let (server_key, key_block) = key_block.split_at(shape.enc_key_len);
269        let (client_iv, key_block) = key_block.split_at(shape.fixed_iv_len);
270        let (server_iv, explicit_nonce) = key_block.split_at(shape.fixed_iv_len);
271
272        let client_secrets = self.suite.aead_alg.extract_keys(
273            AeadKey::new(client_key),
274            client_iv,
275            explicit_nonce,
276        )?;
277        let server_secrets = self.suite.aead_alg.extract_keys(
278            AeadKey::new(server_key),
279            server_iv,
280            explicit_nonce,
281        )?;
282
283        let (tx, rx) = match side {
284            Side::Client => (client_secrets, server_secrets),
285            Side::Server => (server_secrets, client_secrets),
286        };
287        Ok(PartiallyExtractedSecrets { tx, rx })
288    }
289}
290
291impl Drop for ConnectionSecrets {
292    fn drop(&mut self) {
293        self.master_secret.zeroize();
294    }
295}
296
297enum Seed {
298    Ems(hash::Output),
299    Randoms([u8; 64]),
300}
301
302impl AsRef<[u8]> for Seed {
303    /// This is guaranteed to return a non-empty slice.
304    fn as_ref(&self) -> &[u8] {
305        match self {
306            // seed is a hash::Output, which is a fixed, non-zero length array.
307            Self::Ems(seed) => seed.as_ref(),
308            // randoms is a fixed, non-zero length array.
309            Self::Randoms(randoms) => randoms.as_ref(),
310        }
311    }
312}
313
314fn join_randoms(first: &[u8; 32], second: &[u8; 32]) -> [u8; 64] {
315    let mut randoms = [0u8; 64];
316    randoms[..32].copy_from_slice(first);
317    randoms[32..].copy_from_slice(second);
318    randoms
319}
320
321type MessageCipherPair = (Box<dyn MessageDecrypter>, Box<dyn MessageEncrypter>);
322
323pub(crate) fn decode_kx_params<'a, T: KxDecode<'a>>(
324    kx_algorithm: KeyExchangeAlgorithm,
325    common: &mut CommonState,
326    kx_params: &'a [u8],
327) -> Result<T, Error> {
328    let mut rd = Reader::init(kx_params);
329    let kx_params = T::decode(&mut rd, kx_algorithm)?;
330    match rd.any_left() {
331        false => Ok(kx_params),
332        true => Err(common.send_fatal_alert(
333            AlertDescription::DecodeError,
334            InvalidMessage::InvalidDhParams,
335        )),
336    }
337}
338
339pub(crate) const DOWNGRADE_SENTINEL: [u8; 8] = [0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01];
340
341#[cfg(test)]
342#[macro_rules_attribute::apply(test_for_each_provider)]
343mod tests {
344    use super::provider::kx_group::X25519;
345    use super::*;
346    use crate::common_state::{CommonState, Side};
347    use crate::msgs::handshake::{ServerEcdhParams, ServerKeyExchangeParams};
348
349    #[test]
350    fn server_ecdhe_remaining_bytes() {
351        let key = X25519.start().unwrap();
352        let server_params = ServerEcdhParams::new(&*key);
353        let mut server_buf = Vec::new();
354        server_params.encode(&mut server_buf);
355        server_buf.push(34);
356
357        let mut common = CommonState::new(Side::Client);
358        assert!(
359            decode_kx_params::<ServerKeyExchangeParams>(
360                KeyExchangeAlgorithm::ECDHE,
361                &mut common,
362                &server_buf
363            )
364            .is_err()
365        );
366    }
367
368    #[test]
369    fn client_ecdhe_invalid() {
370        let mut common = CommonState::new(Side::Server);
371        assert!(
372            decode_kx_params::<ServerKeyExchangeParams>(
373                KeyExchangeAlgorithm::ECDHE,
374                &mut common,
375                &[34],
376            )
377            .is_err()
378        );
379    }
380}