1 use crate::cipher::{MessageDecrypter, MessageEncrypter};
2 use crate::conn::CommonState;
3 use crate::conn::ConnectionRandoms;
4 use crate::kx;
5 use crate::msgs::codec::{Codec, Reader};
6 use crate::msgs::enums::{AlertDescription, ContentType};
7 use crate::msgs::enums::{CipherSuite, SignatureScheme};
8 use crate::msgs::handshake::KeyExchangeAlgorithm;
9 use crate::suites::{BulkAlgorithm, CipherSuiteCommon, SupportedCipherSuite};
10 use crate::Error;
11
12 use ring::aead;
13 use ring::digest::Digest;
14
15 use std::fmt;
16
17 mod cipher;
18 pub(crate) use cipher::{AesGcm, ChaCha20Poly1305, Tls12AeadAlgorithm};
19
20 mod prf;
21
22 /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
23 #[cfg(feature = "tls12")]
24 pub 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
39 /// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
40 #[cfg(feature = "tls12")]
41 pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
42 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
43 common: CipherSuiteCommon {
44 suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
45 bulk: BulkAlgorithm::Chacha20Poly1305,
46 aead_algorithm: &ring::aead::CHACHA20_POLY1305,
47 },
48 kx: KeyExchangeAlgorithm::ECDHE,
49 sign: TLS12_RSA_SCHEMES,
50 fixed_iv_len: 12,
51 explicit_nonce_len: 0,
52 aead_alg: &ChaCha20Poly1305,
53 hmac_algorithm: ring::hmac::HMAC_SHA256,
54 });
55
56 /// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
57 #[cfg(feature = "tls12")]
58 pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
59 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
60 common: CipherSuiteCommon {
61 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
62 bulk: BulkAlgorithm::Aes128Gcm,
63 aead_algorithm: &ring::aead::AES_128_GCM,
64 },
65 kx: KeyExchangeAlgorithm::ECDHE,
66 sign: TLS12_RSA_SCHEMES,
67 fixed_iv_len: 4,
68 explicit_nonce_len: 8,
69 aead_alg: &AesGcm,
70 hmac_algorithm: ring::hmac::HMAC_SHA256,
71 });
72
73 /// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
74 #[cfg(feature = "tls12")]
75 pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
76 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
77 common: CipherSuiteCommon {
78 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
79 bulk: BulkAlgorithm::Aes256Gcm,
80 aead_algorithm: &ring::aead::AES_256_GCM,
81 },
82 kx: KeyExchangeAlgorithm::ECDHE,
83 sign: TLS12_RSA_SCHEMES,
84 fixed_iv_len: 4,
85 explicit_nonce_len: 8,
86 aead_alg: &AesGcm,
87 hmac_algorithm: ring::hmac::HMAC_SHA384,
88 });
89
90 /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
91 #[cfg(feature = "tls12")]
92 pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
93 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
94 common: CipherSuiteCommon {
95 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
96 bulk: BulkAlgorithm::Aes128Gcm,
97 aead_algorithm: &ring::aead::AES_128_GCM,
98 },
99 kx: KeyExchangeAlgorithm::ECDHE,
100 sign: TLS12_ECDSA_SCHEMES,
101 fixed_iv_len: 4,
102 explicit_nonce_len: 8,
103 aead_alg: &AesGcm,
104 hmac_algorithm: ring::hmac::HMAC_SHA256,
105 });
106
107 /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
108 #[cfg(feature = "tls12")]
109 pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
110 SupportedCipherSuite::Tls12(&Tls12CipherSuite {
111 common: CipherSuiteCommon {
112 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
113 bulk: BulkAlgorithm::Aes256Gcm,
114 aead_algorithm: &ring::aead::AES_256_GCM,
115 },
116 kx: KeyExchangeAlgorithm::ECDHE,
117 sign: TLS12_ECDSA_SCHEMES,
118 fixed_iv_len: 4,
119 explicit_nonce_len: 8,
120 aead_alg: &AesGcm,
121 hmac_algorithm: ring::hmac::HMAC_SHA384,
122 });
123
124 #[cfg(feature = "tls12")]
125 static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
126 SignatureScheme::ED25519,
127 SignatureScheme::ECDSA_NISTP521_SHA512,
128 SignatureScheme::ECDSA_NISTP384_SHA384,
129 SignatureScheme::ECDSA_NISTP256_SHA256,
130 ];
131
132 #[cfg(feature = "tls12")]
133 static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[
134 SignatureScheme::RSA_PSS_SHA512,
135 SignatureScheme::RSA_PSS_SHA384,
136 SignatureScheme::RSA_PSS_SHA256,
137 SignatureScheme::RSA_PKCS1_SHA512,
138 SignatureScheme::RSA_PKCS1_SHA384,
139 SignatureScheme::RSA_PKCS1_SHA256,
140 ];
141
142 /// A TLS 1.2 cipher suite supported by rustls.
143 #[cfg(feature = "tls12")]
144 pub struct Tls12CipherSuite {
145 /// Common cipher suite fields.
146 pub common: CipherSuiteCommon,
147 pub(crate) hmac_algorithm: ring::hmac::Algorithm,
148 /// How to exchange/agree keys.
149 pub kx: KeyExchangeAlgorithm,
150
151 /// How to sign messages for authentication.
152 pub sign: &'static [SignatureScheme],
153
154 /// How long the fixed part of the 'IV' is.
155 ///
156 /// This isn't usually an IV, but we continue the
157 /// terminology misuse to match the standard.
158 pub fixed_iv_len: usize,
159
160 /// This is a non-standard extension which extends the
161 /// key block to provide an initial explicit nonce offset,
162 /// in a deterministic and safe way. GCM needs this,
163 /// chacha20poly1305 works this way by design.
164 pub explicit_nonce_len: usize,
165
166 pub(crate) aead_alg: &'static dyn Tls12AeadAlgorithm,
167 }
168
169 #[cfg(feature = "tls12")]
170 impl Tls12CipherSuite {
171 /// Resolve the set of supported `SignatureScheme`s from the
172 /// offered `SupportedSignatureSchemes`. If we return an empty
173 /// set, the handshake terminates.
resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme>174 pub fn resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme> {
175 self.sign
176 .iter()
177 .filter(|pref| offered.contains(pref))
178 .cloned()
179 .collect()
180 }
181
182 /// Which hash function to use with this suite.
hash_algorithm(&self) -> &'static ring::digest::Algorithm183 pub fn hash_algorithm(&self) -> &'static ring::digest::Algorithm {
184 self.hmac_algorithm.digest_algorithm()
185 }
186 }
187
188 #[cfg(feature = "tls12")]
189 impl From<&'static Tls12CipherSuite> for SupportedCipherSuite {
from(s: &'static Tls12CipherSuite) -> Self190 fn from(s: &'static Tls12CipherSuite) -> Self {
191 Self::Tls12(s)
192 }
193 }
194
195 #[cfg(feature = "tls12")]
196 impl PartialEq for Tls12CipherSuite {
eq(&self, other: &Self) -> bool197 fn eq(&self, other: &Self) -> bool {
198 self.common.suite == other.common.suite
199 }
200 }
201
202 #[cfg(feature = "tls12")]
203 impl fmt::Debug for Tls12CipherSuite {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 f.debug_struct("Tls12CipherSuite")
206 .field("suite", &self.common.suite)
207 .field("bulk", &self.common.bulk)
208 .finish()
209 }
210 }
211
212 /// TLS1.2 per-connection keying material
213 pub(crate) struct ConnectionSecrets {
214 pub(crate) randoms: ConnectionRandoms,
215 suite: &'static Tls12CipherSuite,
216 pub(crate) master_secret: [u8; 48],
217 }
218
219 impl ConnectionSecrets {
new( randoms: &ConnectionRandoms, suite: &'static Tls12CipherSuite, pms: &[u8], ) -> Self220 pub(crate) fn new(
221 randoms: &ConnectionRandoms,
222 suite: &'static Tls12CipherSuite,
223 pms: &[u8],
224 ) -> Self {
225 let mut ret = Self {
226 randoms: randoms.clone(),
227 suite,
228 master_secret: [0u8; 48],
229 };
230
231 let randoms = join_randoms(&ret.randoms.client, &ret.randoms.server);
232 prf::prf(
233 &mut ret.master_secret,
234 suite.hmac_algorithm,
235 pms,
236 b"master secret",
237 &randoms,
238 );
239 ret
240 }
241
new_ems( randoms: &ConnectionRandoms, hs_hash: &Digest, suite: &'static Tls12CipherSuite, pms: &[u8], ) -> Self242 pub(crate) fn new_ems(
243 randoms: &ConnectionRandoms,
244 hs_hash: &Digest,
245 suite: &'static Tls12CipherSuite,
246 pms: &[u8],
247 ) -> Self {
248 let mut ret = Self {
249 randoms: randoms.clone(),
250 master_secret: [0u8; 48],
251 suite,
252 };
253
254 prf::prf(
255 &mut ret.master_secret,
256 suite.hmac_algorithm,
257 pms,
258 b"extended master secret",
259 hs_hash.as_ref(),
260 );
261 ret
262 }
263
new_resume( randoms: &ConnectionRandoms, suite: &'static Tls12CipherSuite, master_secret: &[u8], ) -> Self264 pub(crate) fn new_resume(
265 randoms: &ConnectionRandoms,
266 suite: &'static Tls12CipherSuite,
267 master_secret: &[u8],
268 ) -> Self {
269 let mut ret = Self {
270 randoms: randoms.clone(),
271 suite,
272 master_secret: [0u8; 48],
273 };
274 ret.master_secret
275 .copy_from_slice(master_secret);
276 ret
277 }
278
279 /// Make a `MessageCipherPair` based on the given supported ciphersuite `scs`,
280 /// and the session's `secrets`.
make_cipher_pair(&self) -> MessageCipherPair281 pub(crate) fn make_cipher_pair(&self) -> MessageCipherPair {
282 fn split_key<'a>(
283 key_block: &'a [u8],
284 alg: &'static aead::Algorithm,
285 ) -> (aead::LessSafeKey, &'a [u8]) {
286 // Might panic if the key block is too small.
287 let (key, rest) = key_block.split_at(alg.key_len());
288 // Won't panic because its only prerequisite is that `key` is `alg.key_len()` bytes long.
289 let key = aead::UnboundKey::new(alg, key).unwrap();
290 (aead::LessSafeKey::new(key), rest)
291 }
292
293 // Make a key block, and chop it up.
294 // nb. we don't implement any ciphersuites with nonzero mac_key_len.
295 let key_block = self.make_key_block();
296
297 let suite = self.suite;
298 let scs = &suite.common;
299
300 let (client_write_key, key_block) = split_key(&key_block, scs.aead_algorithm);
301 let (server_write_key, key_block) = split_key(key_block, scs.aead_algorithm);
302 let (client_write_iv, key_block) = key_block.split_at(suite.fixed_iv_len);
303 let (server_write_iv, extra) = key_block.split_at(suite.fixed_iv_len);
304
305 let (write_key, write_iv, read_key, read_iv) = if self.randoms.we_are_client {
306 (
307 client_write_key,
308 client_write_iv,
309 server_write_key,
310 server_write_iv,
311 )
312 } else {
313 (
314 server_write_key,
315 server_write_iv,
316 client_write_key,
317 client_write_iv,
318 )
319 };
320
321 (
322 suite
323 .aead_alg
324 .decrypter(read_key, read_iv),
325 suite
326 .aead_alg
327 .encrypter(write_key, write_iv, extra),
328 )
329 }
330
make_key_block(&self) -> Vec<u8>331 fn make_key_block(&self) -> Vec<u8> {
332 let suite = &self.suite;
333 let common = &self.suite.common;
334
335 let len =
336 (common.aead_algorithm.key_len() + suite.fixed_iv_len) * 2 + suite.explicit_nonce_len;
337
338 let mut out = Vec::new();
339 out.resize(len, 0u8);
340
341 // NOTE: opposite order to above for no good reason.
342 // Don't design security protocols on drugs, kids.
343 let randoms = join_randoms(&self.randoms.server, &self.randoms.client);
344 prf::prf(
345 &mut out,
346 self.suite.hmac_algorithm,
347 &self.master_secret,
348 b"key expansion",
349 &randoms,
350 );
351
352 out
353 }
354
suite(&self) -> &'static Tls12CipherSuite355 pub(crate) fn suite(&self) -> &'static Tls12CipherSuite {
356 self.suite
357 }
358
get_master_secret(&self) -> Vec<u8>359 pub(crate) fn get_master_secret(&self) -> Vec<u8> {
360 let mut ret = Vec::new();
361 ret.extend_from_slice(&self.master_secret);
362 ret
363 }
364
make_verify_data(&self, handshake_hash: &Digest, label: &[u8]) -> Vec<u8>365 fn make_verify_data(&self, handshake_hash: &Digest, label: &[u8]) -> Vec<u8> {
366 let mut out = Vec::new();
367 out.resize(12, 0u8);
368
369 prf::prf(
370 &mut out,
371 self.suite.hmac_algorithm,
372 &self.master_secret,
373 label,
374 handshake_hash.as_ref(),
375 );
376 out
377 }
378
client_verify_data(&self, handshake_hash: &Digest) -> Vec<u8>379 pub(crate) fn client_verify_data(&self, handshake_hash: &Digest) -> Vec<u8> {
380 self.make_verify_data(handshake_hash, b"client finished")
381 }
382
server_verify_data(&self, handshake_hash: &Digest) -> Vec<u8>383 pub(crate) fn server_verify_data(&self, handshake_hash: &Digest) -> Vec<u8> {
384 self.make_verify_data(handshake_hash, b"server finished")
385 }
386
export_keying_material( &self, output: &mut [u8], label: &[u8], context: Option<&[u8]>, )387 pub(crate) fn export_keying_material(
388 &self,
389 output: &mut [u8],
390 label: &[u8],
391 context: Option<&[u8]>,
392 ) {
393 let mut randoms = Vec::new();
394 randoms.extend_from_slice(&self.randoms.client);
395 randoms.extend_from_slice(&self.randoms.server);
396 if let Some(context) = context {
397 assert!(context.len() <= 0xffff);
398 (context.len() as u16).encode(&mut randoms);
399 randoms.extend_from_slice(context);
400 }
401
402 prf::prf(
403 output,
404 self.suite.hmac_algorithm,
405 &self.master_secret,
406 label,
407 &randoms,
408 )
409 }
410 }
411
join_randoms(first: &[u8; 32], second: &[u8; 32]) -> [u8; 64]412 fn join_randoms(first: &[u8; 32], second: &[u8; 32]) -> [u8; 64] {
413 let mut randoms = [0u8; 64];
414 randoms[..32].copy_from_slice(first);
415 randoms[32..].copy_from_slice(second);
416 randoms
417 }
418
419 type MessageCipherPair = (Box<dyn MessageDecrypter>, Box<dyn MessageEncrypter>);
420
decode_ecdh_params<T: Codec>( common: &mut CommonState, kx_params: &[u8], ) -> Result<T, Error>421 pub(crate) fn decode_ecdh_params<T: Codec>(
422 common: &mut CommonState,
423 kx_params: &[u8],
424 ) -> Result<T, Error> {
425 decode_ecdh_params_::<T>(kx_params).ok_or_else(|| {
426 common.send_fatal_alert(AlertDescription::DecodeError);
427 Error::CorruptMessagePayload(ContentType::Handshake)
428 })
429 }
430
decode_ecdh_params_<T: Codec>(kx_params: &[u8]) -> Option<T>431 fn decode_ecdh_params_<T: Codec>(kx_params: &[u8]) -> Option<T> {
432 let mut rd = Reader::init(kx_params);
433 let ecdh_params = T::read(&mut rd)?;
434 match rd.any_left() {
435 false => Some(ecdh_params),
436 true => None,
437 }
438 }
439
complete_ecdh( mine: kx::KeyExchange, peer_pub_key: &[u8], ) -> Result<kx::KeyExchangeResult, Error>440 pub(crate) fn complete_ecdh(
441 mine: kx::KeyExchange,
442 peer_pub_key: &[u8],
443 ) -> Result<kx::KeyExchangeResult, Error> {
444 mine.complete(peer_pub_key)
445 .ok_or_else(|| Error::PeerMisbehavedError("key agreement failed".to_string()))
446 }
447
448 #[cfg(test)]
449 mod tests {
450 use super::*;
451 use crate::msgs::handshake::{ClientECDHParams, ServerECDHParams};
452
453 #[test]
server_ecdhe_remaining_bytes()454 fn server_ecdhe_remaining_bytes() {
455 let key = kx::KeyExchange::start(&kx::X25519).unwrap();
456 let server_params = ServerECDHParams::new(key.group(), key.pubkey.as_ref());
457 let mut server_buf = Vec::new();
458 server_params.encode(&mut server_buf);
459 server_buf.push(34);
460 assert!(decode_ecdh_params_::<ServerECDHParams>(&server_buf).is_none());
461 }
462
463 #[test]
client_ecdhe_invalid()464 fn client_ecdhe_invalid() {
465 assert!(decode_ecdh_params_::<ClientECDHParams>(&[34]).is_none());
466 }
467 }
468