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 #[cfg(unstable_api_not_supported)] pub fn fips(&self) -> bool {
71 self.common.fips() && self.prf_provider.fips() && self.aead_alg.fips()
72 }
73}
74
75impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
76 fn from(s: &'static Tls12CipherSuite) -> Self {
77 Self::Tls12(s)
78 }
79}
80
81impl PartialEq for Tls12CipherSuite {
82 fn eq(&self, other: &Self) -> bool {
83 self.common.suite == other.common.suite
84 }
85}
86
87impl fmt::Debug for Tls12CipherSuite {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.debug_struct("Tls12CipherSuite")
90 .field("suite", &self.common.suite)
91 .finish()
92 }
93}
94
95pub(crate) struct ConnectionSecrets {
97 pub(crate) randoms: ConnectionRandoms,
98 suite: &'static Tls12CipherSuite,
99 pub(crate) master_secret: [u8; 48],
100}
101
102impl ConnectionSecrets {
103 pub(crate) fn from_key_exchange(
104 kx: Box<dyn crypto::ActiveKeyExchange>,
105 peer_pub_key: &[u8],
106 ems_seed: Option<hash::Output>,
107 randoms: ConnectionRandoms,
108 suite: &'static Tls12CipherSuite,
109 ) -> Result<Self, Error> {
110 let mut ret = Self {
111 randoms,
112 suite,
113 master_secret: [0u8; 48],
114 };
115
116 let (label, seed) = match ems_seed {
117 Some(seed) => ("extended master secret", Seed::Ems(seed)),
118 None => (
119 "master secret",
120 Seed::Randoms(join_randoms(&ret.randoms.client, &ret.randoms.server)),
121 ),
122 };
123
124 ret.suite
129 .prf_provider
130 .for_key_exchange(
131 &mut ret.master_secret,
132 kx,
133 peer_pub_key,
134 label.as_bytes(),
135 seed.as_ref(),
136 )?;
137
138 Ok(ret)
139 }
140
141 pub(crate) fn new_resume(
142 randoms: ConnectionRandoms,
143 suite: &'static Tls12CipherSuite,
144 master_secret: &[u8],
145 ) -> Self {
146 let mut ret = Self {
147 randoms,
148 suite,
149 master_secret: [0u8; 48],
150 };
151 ret.master_secret
152 .copy_from_slice(master_secret);
153 ret
154 }
155
156 pub(crate) fn make_cipher_pair(&self, side: Side) -> MessageCipherPair {
159 let key_block = self.make_key_block();
162 let shape = self.suite.aead_alg.key_block_shape();
163
164 let (client_write_key, key_block) = key_block.split_at(shape.enc_key_len);
165 let (server_write_key, key_block) = key_block.split_at(shape.enc_key_len);
166 let (client_write_iv, key_block) = key_block.split_at(shape.fixed_iv_len);
167 let (server_write_iv, extra) = key_block.split_at(shape.fixed_iv_len);
168
169 let (write_key, write_iv, read_key, read_iv) = match side {
170 Side::Client => (
171 client_write_key,
172 client_write_iv,
173 server_write_key,
174 server_write_iv,
175 ),
176 Side::Server => (
177 server_write_key,
178 server_write_iv,
179 client_write_key,
180 client_write_iv,
181 ),
182 };
183
184 (
185 self.suite
186 .aead_alg
187 .decrypter(AeadKey::new(read_key), read_iv),
188 self.suite
189 .aead_alg
190 .encrypter(AeadKey::new(write_key), write_iv, extra),
191 )
192 }
193
194 fn make_key_block(&self) -> Vec<u8> {
195 let shape = self.suite.aead_alg.key_block_shape();
196
197 let len = (shape.enc_key_len + shape.fixed_iv_len) * 2 + shape.explicit_nonce_len;
198
199 let mut out = vec![0u8; len];
200
201 let randoms = join_randoms(&self.randoms.server, &self.randoms.client);
204 self.suite.prf_provider.for_secret(
205 &mut out,
206 &self.master_secret,
207 b"key expansion",
208 &randoms,
209 );
210
211 out
212 }
213
214 pub(crate) fn suite(&self) -> &'static Tls12CipherSuite {
215 self.suite
216 }
217
218 pub(crate) fn master_secret(&self) -> &[u8] {
219 &self.master_secret[..]
220 }
221
222 fn make_verify_data(&self, handshake_hash: &hash::Output, label: &[u8]) -> Vec<u8> {
223 let mut out = vec![0u8; 12];
224
225 self.suite.prf_provider.for_secret(
226 &mut out,
227 &self.master_secret,
228 label,
229 handshake_hash.as_ref(),
230 );
231
232 out
233 }
234
235 pub(crate) fn client_verify_data(&self, handshake_hash: &hash::Output) -> Vec<u8> {
236 self.make_verify_data(handshake_hash, b"client finished")
237 }
238
239 pub(crate) fn server_verify_data(&self, handshake_hash: &hash::Output) -> Vec<u8> {
240 self.make_verify_data(handshake_hash, b"server finished")
241 }
242
243 pub(crate) fn export_keying_material(
244 &self,
245 output: &mut [u8],
246 label: &[u8],
247 context: Option<&[u8]>,
248 ) {
249 let mut randoms = Vec::new();
250 randoms.extend_from_slice(&self.randoms.client);
251 randoms.extend_from_slice(&self.randoms.server);
252 if let Some(context) = context {
253 assert!(context.len() <= 0xffff);
254 (context.len() as u16).encode(&mut randoms);
255 randoms.extend_from_slice(context);
256 }
257
258 self.suite
259 .prf_provider
260 .for_secret(output, &self.master_secret, label, &randoms);
261 }
262
263 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
264 let key_block = self.make_key_block();
266 let shape = self.suite.aead_alg.key_block_shape();
267
268 let (client_key, key_block) = key_block.split_at(shape.enc_key_len);
269 let (server_key, key_block) = key_block.split_at(shape.enc_key_len);
270 let (client_iv, key_block) = key_block.split_at(shape.fixed_iv_len);
271 let (server_iv, explicit_nonce) = key_block.split_at(shape.fixed_iv_len);
272
273 let client_secrets = self.suite.aead_alg.extract_keys(
274 AeadKey::new(client_key),
275 client_iv,
276 explicit_nonce,
277 )?;
278 let server_secrets = self.suite.aead_alg.extract_keys(
279 AeadKey::new(server_key),
280 server_iv,
281 explicit_nonce,
282 )?;
283
284 let (tx, rx) = match side {
285 Side::Client => (client_secrets, server_secrets),
286 Side::Server => (server_secrets, client_secrets),
287 };
288 Ok(PartiallyExtractedSecrets { tx, rx })
289 }
290}
291
292impl Drop for ConnectionSecrets {
293 fn drop(&mut self) {
294 self.master_secret.zeroize();
295 }
296}
297
298enum Seed {
299 Ems(hash::Output),
300 Randoms([u8; 64]),
301}
302
303impl AsRef<[u8]> for Seed {
304 fn as_ref(&self) -> &[u8] {
306 match self {
307 Self::Ems(seed) => seed.as_ref(),
309 Self::Randoms(randoms) => randoms.as_ref(),
311 }
312 }
313}
314
315fn join_randoms(first: &[u8; 32], second: &[u8; 32]) -> [u8; 64] {
316 let mut randoms = [0u8; 64];
317 randoms[..32].copy_from_slice(first);
318 randoms[32..].copy_from_slice(second);
319 randoms
320}
321
322type MessageCipherPair = (Box<dyn MessageDecrypter>, Box<dyn MessageEncrypter>);
323
324pub(crate) fn decode_kx_params<'a, T: KxDecode<'a>>(
325 kx_algorithm: KeyExchangeAlgorithm,
326 common: &mut CommonState,
327 kx_params: &'a [u8],
328) -> Result<T, Error> {
329 let mut rd = Reader::init(kx_params);
330 let kx_params = T::decode(&mut rd, kx_algorithm)?;
331 match rd.any_left() {
332 false => Ok(kx_params),
333 true => Err(common.send_fatal_alert(
334 AlertDescription::DecodeError,
335 InvalidMessage::InvalidDhParams,
336 )),
337 }
338}
339
340pub(crate) const DOWNGRADE_SENTINEL: [u8; 8] = [0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01];
341
342#[cfg(test)]
343#[macro_rules_attribute::apply(test_for_each_provider)]
344mod tests {
345 use super::provider::kx_group::X25519;
346 use super::*;
347 use crate::common_state::{CommonState, Side};
348 use crate::msgs::handshake::{ServerEcdhParams, ServerKeyExchangeParams};
349
350 #[test]
351 fn server_ecdhe_remaining_bytes() {
352 let key = X25519.start().unwrap();
353 let server_params = ServerEcdhParams::new(&*key);
354 let mut server_buf = Vec::new();
355 server_params.encode(&mut server_buf);
356 server_buf.push(34);
357
358 let mut common = CommonState::new(Side::Client);
359 assert!(decode_kx_params::<ServerKeyExchangeParams>(
360 KeyExchangeAlgorithm::ECDHE,
361 &mut common,
362 &server_buf
363 )
364 .is_err());
365 }
366
367 #[test]
368 fn client_ecdhe_invalid() {
369 let mut common = CommonState::new(Side::Server);
370 assert!(decode_kx_params::<ServerKeyExchangeParams>(
371 KeyExchangeAlgorithm::ECDHE,
372 &mut common,
373 &[34],
374 )
375 .is_err());
376 }
377}