1use crate::cipher::{MessageDecrypter, MessageEncrypter};
2use crate::conn::{CommonState, ConnectionRandoms, Side};
3use crate::enums::{CipherSuite, SignatureScheme};
4use crate::kx;
5use crate::msgs::codec::{Codec, Reader};
6use crate::msgs::enums::{AlertDescription, ContentType};
7use crate::msgs::handshake::KeyExchangeAlgorithm;
8use crate::suites::{BulkAlgorithm, CipherSuiteCommon, SupportedCipherSuite};
9#[cfg(feature = "secret_extraction")]
10use crate::suites::{ConnectionTrafficSecrets, PartiallyExtractedSecrets};
11use crate::Error;
12
13use ring::aead;
14use ring::digest::Digest;
15
16use std::fmt;
17
18mod cipher;
19pub(crate) use cipher::{AesGcm, ChaCha20Poly1305, Tls12AeadAlgorithm};
20
21mod prf;
22
23pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
25 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
26 common: CipherSuiteCommon {
27 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
28 bulk: BulkAlgorithm::Chacha20Poly1305,
29 aead_algorithm: &ring::aead::CHACHA20_POLY1305,
30 },
31 kx: KeyExchangeAlgorithm::ECDHE,
32 sign: TLS12_ECDSA_SCHEMES,
33 fixed_iv_len: 12,
34 explicit_nonce_len: 0,
35 aead_alg: &ChaCha20Poly1305,
36 hmac_algorithm: ring::hmac::HMAC_SHA256,
37 });
38
39pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
41 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
42 common: CipherSuiteCommon {
43 suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
44 bulk: BulkAlgorithm::Chacha20Poly1305,
45 aead_algorithm: &ring::aead::CHACHA20_POLY1305,
46 },
47 kx: KeyExchangeAlgorithm::ECDHE,
48 sign: TLS12_RSA_SCHEMES,
49 fixed_iv_len: 12,
50 explicit_nonce_len: 0,
51 aead_alg: &ChaCha20Poly1305,
52 hmac_algorithm: ring::hmac::HMAC_SHA256,
53 });
54
55pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
57 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
58 common: CipherSuiteCommon {
59 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
60 bulk: BulkAlgorithm::Aes128Gcm,
61 aead_algorithm: &ring::aead::AES_128_GCM,
62 },
63 kx: KeyExchangeAlgorithm::ECDHE,
64 sign: TLS12_RSA_SCHEMES,
65 fixed_iv_len: 4,
66 explicit_nonce_len: 8,
67 aead_alg: &AesGcm,
68 hmac_algorithm: ring::hmac::HMAC_SHA256,
69 });
70
71pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
73 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
74 common: CipherSuiteCommon {
75 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
76 bulk: BulkAlgorithm::Aes256Gcm,
77 aead_algorithm: &ring::aead::AES_256_GCM,
78 },
79 kx: KeyExchangeAlgorithm::ECDHE,
80 sign: TLS12_RSA_SCHEMES,
81 fixed_iv_len: 4,
82 explicit_nonce_len: 8,
83 aead_alg: &AesGcm,
84 hmac_algorithm: ring::hmac::HMAC_SHA384,
85 });
86
87pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
89 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
90 common: CipherSuiteCommon {
91 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
92 bulk: BulkAlgorithm::Aes128Gcm,
93 aead_algorithm: &ring::aead::AES_128_GCM,
94 },
95 kx: KeyExchangeAlgorithm::ECDHE,
96 sign: TLS12_ECDSA_SCHEMES,
97 fixed_iv_len: 4,
98 explicit_nonce_len: 8,
99 aead_alg: &AesGcm,
100 hmac_algorithm: ring::hmac::HMAC_SHA256,
101 });
102
103pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
105 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
106 common: CipherSuiteCommon {
107 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
108 bulk: BulkAlgorithm::Aes256Gcm,
109 aead_algorithm: &ring::aead::AES_256_GCM,
110 },
111 kx: KeyExchangeAlgorithm::ECDHE,
112 sign: TLS12_ECDSA_SCHEMES,
113 fixed_iv_len: 4,
114 explicit_nonce_len: 8,
115 aead_alg: &AesGcm,
116 hmac_algorithm: ring::hmac::HMAC_SHA384,
117 });
118
119static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
120 SignatureScheme::ED25519,
121 SignatureScheme::ECDSA_NISTP521_SHA512,
122 SignatureScheme::ECDSA_NISTP384_SHA384,
123 SignatureScheme::ECDSA_NISTP256_SHA256,
124];
125
126static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[
127 SignatureScheme::RSA_PSS_SHA512,
128 SignatureScheme::RSA_PSS_SHA384,
129 SignatureScheme::RSA_PSS_SHA256,
130 SignatureScheme::RSA_PKCS1_SHA512,
131 SignatureScheme::RSA_PKCS1_SHA384,
132 SignatureScheme::RSA_PKCS1_SHA256,
133];
134
135pub struct Tls12CipherSuite {
137 pub common: CipherSuiteCommon,
139 pub(crate) hmac_algorithm: ring::hmac::Algorithm,
140 pub kx: KeyExchangeAlgorithm,
142
143 pub sign: &'static [SignatureScheme],
145
146 pub fixed_iv_len: usize,
151
152 pub explicit_nonce_len: usize,
157
158 pub(crate) aead_alg: &'static dyn Tls12AeadAlgorithm,
159}
160
161impl Tls12CipherSuite {
162 pub fn resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme> {
166 self.sign
167 .iter()
168 .filter(|pref| offered.contains(pref))
169 .cloned()
170 .collect()
171 }
172
173 pub fn hash_algorithm(&self) -> &'static ring::digest::Algorithm {
175 self.hmac_algorithm.digest_algorithm()
176 }
177}
178
179impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
180 fn from(s: &'static Tls12CipherSuite) -> Self {
181 Self::Tls12(s)
182 }
183}
184
185impl PartialEq for Tls12CipherSuite {
186 fn eq(&self, other: &Self) -> bool {
187 self.common.suite == other.common.suite
188 }
189}
190
191impl fmt::Debug for Tls12CipherSuite {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 f.debug_struct("Tls12CipherSuite")
194 .field("suite", &self.common.suite)
195 .field("bulk", &self.common.bulk)
196 .finish()
197 }
198}
199
200pub(crate) struct ConnectionSecrets {
202 pub(crate) randoms: ConnectionRandoms,
203 suite: &'static Tls12CipherSuite,
204 pub(crate) master_secret: [u8; 48],
205}
206
207impl ConnectionSecrets {
208 pub(crate) fn from_key_exchange(
209 kx: kx::KeyExchange,
210 peer_pub_key: &[u8],
211 ems_seed: Option<Digest>,
212 randoms: ConnectionRandoms,
213 suite: &'static Tls12CipherSuite,
214 ) -> Result<Self, Error> {
215 let mut ret = Self {
216 randoms,
217 suite,
218 master_secret: [0u8; 48],
219 };
220
221 let (label, seed) = match ems_seed {
222 Some(seed) => ("extended master secret", Seed::Ems(seed)),
223 None => (
224 "master secret",
225 Seed::Randoms(join_randoms(&ret.randoms.client, &ret.randoms.server)),
226 ),
227 };
228
229 kx.complete(peer_pub_key, |secret| {
230 prf::prf(
231 &mut ret.master_secret,
232 suite.hmac_algorithm,
233 secret,
234 label.as_bytes(),
235 seed.as_ref(),
236 );
237 Ok(())
238 })?;
239
240 Ok(ret)
241 }
242
243 pub(crate) fn new_resume(
244 randoms: ConnectionRandoms,
245 suite: &'static Tls12CipherSuite,
246 master_secret: &[u8],
247 ) -> Self {
248 let mut ret = Self {
249 randoms,
250 suite,
251 master_secret: [0u8; 48],
252 };
253 ret.master_secret
254 .copy_from_slice(master_secret);
255 ret
256 }
257
258 pub(crate) fn make_cipher_pair(&self, side: Side) -> MessageCipherPair {
261 fn split_key<'a>(
262 key_block: &'a [u8],
263 alg: &'static aead::Algorithm,
264 ) -> (aead::LessSafeKey, &'a [u8]) {
265 let (key, rest) = key_block.split_at(alg.key_len());
267 let key = aead::UnboundKey::new(alg, key).unwrap();
269 (aead::LessSafeKey::new(key), rest)
270 }
271
272 let key_block = self.make_key_block();
275
276 let suite = self.suite;
277 let scs = &suite.common;
278
279 let (client_write_key, key_block) = split_key(&key_block, scs.aead_algorithm);
280 let (server_write_key, key_block) = split_key(key_block, scs.aead_algorithm);
281 let (client_write_iv, key_block) = key_block.split_at(suite.fixed_iv_len);
282 let (server_write_iv, extra) = key_block.split_at(suite.fixed_iv_len);
283
284 let (write_key, write_iv, read_key, read_iv) = match side {
285 Side::Client => (
286 client_write_key,
287 client_write_iv,
288 server_write_key,
289 server_write_iv,
290 ),
291 Side::Server => (
292 server_write_key,
293 server_write_iv,
294 client_write_key,
295 client_write_iv,
296 ),
297 };
298
299 (
300 suite
301 .aead_alg
302 .decrypter(read_key, read_iv),
303 suite
304 .aead_alg
305 .encrypter(write_key, write_iv, extra),
306 )
307 }
308
309 fn make_key_block(&self) -> Vec<u8> {
310 let suite = &self.suite;
311 let common = &self.suite.common;
312
313 let len =
314 (common.aead_algorithm.key_len() + suite.fixed_iv_len) * 2 + suite.explicit_nonce_len;
315
316 let mut out = Vec::new();
317 out.resize(len, 0u8);
318
319 let randoms = join_randoms(&self.randoms.server, &self.randoms.client);
322 prf::prf(
323 &mut out,
324 self.suite.hmac_algorithm,
325 &self.master_secret,
326 b"key expansion",
327 &randoms,
328 );
329
330 out
331 }
332
333 pub(crate) fn suite(&self) -> &'static Tls12CipherSuite {
334 self.suite
335 }
336
337 pub(crate) fn get_master_secret(&self) -> Vec<u8> {
338 let mut ret = Vec::new();
339 ret.extend_from_slice(&self.master_secret);
340 ret
341 }
342
343 fn make_verify_data(&self, handshake_hash: &Digest, label: &[u8]) -> Vec<u8> {
344 let mut out = Vec::new();
345 out.resize(12, 0u8);
346
347 prf::prf(
348 &mut out,
349 self.suite.hmac_algorithm,
350 &self.master_secret,
351 label,
352 handshake_hash.as_ref(),
353 );
354 out
355 }
356
357 pub(crate) fn client_verify_data(&self, handshake_hash: &Digest) -> Vec<u8> {
358 self.make_verify_data(handshake_hash, b"client finished")
359 }
360
361 pub(crate) fn server_verify_data(&self, handshake_hash: &Digest) -> Vec<u8> {
362 self.make_verify_data(handshake_hash, b"server finished")
363 }
364
365 pub(crate) fn export_keying_material(
366 &self,
367 output: &mut [u8],
368 label: &[u8],
369 context: Option<&[u8]>,
370 ) {
371 let mut randoms = Vec::new();
372 randoms.extend_from_slice(&self.randoms.client);
373 randoms.extend_from_slice(&self.randoms.server);
374 if let Some(context) = context {
375 assert!(context.len() <= 0xffff);
376 (context.len() as u16).encode(&mut randoms);
377 randoms.extend_from_slice(context);
378 }
379
380 prf::prf(
381 output,
382 self.suite.hmac_algorithm,
383 &self.master_secret,
384 label,
385 &randoms,
386 )
387 }
388
389 #[cfg(feature = "secret_extraction")]
390 pub(crate) fn extract_secrets(&self, side: Side) -> Result<PartiallyExtractedSecrets, Error> {
391 let key_block = self.make_key_block();
393
394 let suite = self.suite;
395 let algo = suite.common.aead_algorithm;
396
397 let (client_key, key_block) = key_block.split_at(algo.key_len());
398 let (server_key, key_block) = key_block.split_at(algo.key_len());
399 let (client_iv, key_block) = key_block.split_at(suite.fixed_iv_len);
400 let (server_iv, extra) = key_block.split_at(suite.fixed_iv_len);
401
402 struct Pair<'a> {
404 key: &'a [u8],
405 iv: &'a [u8],
406 }
407
408 let client_pair = Pair {
409 key: client_key,
410 iv: client_iv,
411 };
412 let server_pair = Pair {
413 key: server_key,
414 iv: server_iv,
415 };
416
417 let (client_secrets, server_secrets) = if algo == &ring::aead::AES_128_GCM {
418 let extract = |pair: Pair| -> ConnectionTrafficSecrets {
419 let mut key = [0u8; 16];
420 key.copy_from_slice(pair.key);
421
422 let mut salt = [0u8; 4];
423 salt.copy_from_slice(pair.iv);
424
425 let mut iv = [0u8; 8];
426 iv.copy_from_slice(&extra[..8]);
427
428 ConnectionTrafficSecrets::Aes128Gcm { key, salt, iv }
429 };
430
431 (extract(client_pair), extract(server_pair))
432 } else if algo == &ring::aead::AES_256_GCM {
433 let extract = |pair: Pair| -> ConnectionTrafficSecrets {
434 let mut key = [0u8; 32];
435 key.copy_from_slice(pair.key);
436
437 let mut salt = [0u8; 4];
438 salt.copy_from_slice(pair.iv);
439
440 let mut iv = [0u8; 8];
441 iv.copy_from_slice(&extra[..8]);
442
443 ConnectionTrafficSecrets::Aes256Gcm { key, salt, iv }
444 };
445
446 (extract(client_pair), extract(server_pair))
447 } else if algo == &ring::aead::CHACHA20_POLY1305 {
448 let extract = |pair: Pair| -> ConnectionTrafficSecrets {
449 let mut key = [0u8; 32];
450 key.copy_from_slice(pair.key);
451
452 let mut iv = [0u8; 12];
453 iv.copy_from_slice(pair.iv);
454
455 ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }
456 };
457
458 (extract(client_pair), extract(server_pair))
459 } else {
460 return Err(Error::General(format!(
461 "exporting secrets for {:?}: unimplemented",
462 algo
463 )));
464 };
465
466 let (tx, rx) = match side {
467 Side::Client => (client_secrets, server_secrets),
468 Side::Server => (server_secrets, client_secrets),
469 };
470 Ok(PartiallyExtractedSecrets { tx, rx })
471 }
472}
473
474enum Seed {
475 Ems(Digest),
476 Randoms([u8; 64]),
477}
478
479impl AsRef<[u8]> for Seed {
480 fn as_ref(&self) -> &[u8] {
481 match self {
482 Self::Ems(seed) => seed.as_ref(),
483 Self::Randoms(randoms) => randoms.as_ref(),
484 }
485 }
486}
487
488fn join_randoms(first: &[u8; 32], second: &[u8; 32]) -> [u8; 64] {
489 let mut randoms = [0u8; 64];
490 randoms[..32].copy_from_slice(first);
491 randoms[32..].copy_from_slice(second);
492 randoms
493}
494
495type MessageCipherPair = (Box<dyn MessageDecrypter>, Box<dyn MessageEncrypter>);
496
497pub(crate) fn decode_ecdh_params<T: Codec>(
498 common: &mut CommonState,
499 kx_params: &[u8],
500) -> Result<T, Error> {
501 decode_ecdh_params_::<T>(kx_params).ok_or_else(|| {
502 common.send_fatal_alert(AlertDescription::DecodeError);
503 Error::CorruptMessagePayload(ContentType::Handshake)
504 })
505}
506
507fn decode_ecdh_params_<T: Codec>(kx_params: &[u8]) -> Option<T> {
508 let mut rd = Reader::init(kx_params);
509 let ecdh_params = T::read(&mut rd)?;
510 match rd.any_left() {
511 false => Some(ecdh_params),
512 true => None,
513 }
514}
515
516pub(crate) const DOWNGRADE_SENTINEL: [u8; 8] = [0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01];
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521 use crate::msgs::handshake::{ClientECDHParams, ServerECDHParams};
522
523 #[test]
524 fn server_ecdhe_remaining_bytes() {
525 let key = kx::KeyExchange::start(&kx::X25519).unwrap();
526 let server_params = ServerECDHParams::new(key.group(), key.pubkey.as_ref());
527 let mut server_buf = Vec::new();
528 server_params.encode(&mut server_buf);
529 server_buf.push(34);
530 assert!(decode_ecdh_params_::<ServerECDHParams>(&server_buf).is_none());
531 }
532
533 #[test]
534 fn client_ecdhe_invalid() {
535 assert!(decode_ecdh_params_::<ClientECDHParams>(&[34]).is_none());
536 }
537}