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
19pub struct Tls12CipherSuite {
21 pub common: CipherSuiteCommon,
23
24 pub prf_provider: &'static dyn crypto::tls12::Prf,
31
32 pub kx: KeyExchangeAlgorithm,
40
41 pub sign: &'static [SignatureScheme],
48
49 pub aead_alg: &'static dyn Tls12AeadAlgorithm,
52}
53
54impl Tls12CipherSuite {
55 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 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
94pub(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 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 pub(crate) fn make_cipher_pair(&self, side: Side) -> MessageCipherPair {
158 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 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 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 fn as_ref(&self) -> &[u8] {
305 match self {
306 Self::Ems(seed) => seed.as_ref(),
308 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}