1 use crate::cipher;
2 use crate::msgs::codec::{Codec, Reader};
3 use crate::msgs::enums::{CipherSuite, HashAlgorithm, SignatureAlgorithm, SignatureScheme};
4 use crate::msgs::enums::{NamedGroup, ProtocolVersion};
5 use crate::msgs::handshake::DecomposedSignatureScheme;
6 use crate::msgs::handshake::KeyExchangeAlgorithm;
7 use crate::msgs::handshake::{ClientECDHParams, ServerECDHParams};
8
9 use ring;
10 use std::fmt;
11
12 /// Bulk symmetric encryption scheme used by a cipher suite.
13 #[allow(non_camel_case_types)]
14 #[derive(Debug, PartialEq)]
15 pub enum BulkAlgorithm {
16 /// AES with 128-bit keys in Galois counter mode.
17 AES_128_GCM,
18
19 /// AES with 256-bit keys in Galois counter mode.
20 AES_256_GCM,
21
22 /// Chacha20 for confidentiality with poly1305 for authenticity.
23 CHACHA20_POLY1305,
24 }
25
26 /// The result of a key exchange. This has our public key,
27 /// and the agreed shared secret (also known as the "premaster secret"
28 /// in TLS1.0-era protocols, and "Z" in TLS1.3).
29 pub struct KeyExchangeResult {
30 pub pubkey: ring::agreement::PublicKey,
31 pub shared_secret: Vec<u8>,
32 }
33
34 /// An in-progress key exchange. This has the algorithm,
35 /// our private key, and our public key.
36 pub struct KeyExchange {
37 pub group: NamedGroup,
38 alg: &'static ring::agreement::Algorithm,
39 privkey: ring::agreement::EphemeralPrivateKey,
40 pub pubkey: ring::agreement::PublicKey,
41 }
42
43 impl KeyExchange {
named_group_to_ecdh_alg( group: NamedGroup, ) -> Option<&'static ring::agreement::Algorithm>44 pub fn named_group_to_ecdh_alg(
45 group: NamedGroup,
46 ) -> Option<&'static ring::agreement::Algorithm> {
47 match group {
48 NamedGroup::X25519 => Some(&ring::agreement::X25519),
49 NamedGroup::secp256r1 => Some(&ring::agreement::ECDH_P256),
50 NamedGroup::secp384r1 => Some(&ring::agreement::ECDH_P384),
51 _ => None,
52 }
53 }
54
supported_groups() -> &'static [NamedGroup]55 pub fn supported_groups() -> &'static [NamedGroup] {
56 // in preference order
57 &[
58 NamedGroup::X25519,
59 NamedGroup::secp384r1,
60 NamedGroup::secp256r1,
61 ]
62 }
63
client_ecdhe(kx_params: &[u8]) -> Option<KeyExchangeResult>64 pub fn client_ecdhe(kx_params: &[u8]) -> Option<KeyExchangeResult> {
65 let mut rd = Reader::init(kx_params);
66 let ecdh_params = ServerECDHParams::read(&mut rd)?;
67
68 KeyExchange::start_ecdhe(ecdh_params.curve_params.named_group)?
69 .complete(&ecdh_params.public.0)
70 }
71
start_ecdhe(named_group: NamedGroup) -> Option<KeyExchange>72 pub fn start_ecdhe(named_group: NamedGroup) -> Option<KeyExchange> {
73 let alg = KeyExchange::named_group_to_ecdh_alg(named_group)?;
74 let rng = ring::rand::SystemRandom::new();
75 let ours = ring::agreement::EphemeralPrivateKey::generate(alg, &rng).unwrap();
76
77 let pubkey = ours.compute_public_key().unwrap();
78
79 Some(KeyExchange {
80 group: named_group,
81 alg,
82 privkey: ours,
83 pubkey,
84 })
85 }
86
check_client_params(&self, kx_params: &[u8]) -> bool87 pub fn check_client_params(&self, kx_params: &[u8]) -> bool {
88 self.decode_client_params(kx_params)
89 .is_some()
90 }
91
decode_client_params(&self, kx_params: &[u8]) -> Option<ClientECDHParams>92 fn decode_client_params(&self, kx_params: &[u8]) -> Option<ClientECDHParams> {
93 let mut rd = Reader::init(kx_params);
94 let ecdh_params = ClientECDHParams::read(&mut rd)?;
95 if rd.any_left() {
96 None
97 } else {
98 Some(ecdh_params)
99 }
100 }
101
server_complete(self, kx_params: &[u8]) -> Option<KeyExchangeResult>102 pub fn server_complete(self, kx_params: &[u8]) -> Option<KeyExchangeResult> {
103 self.decode_client_params(kx_params)
104 .and_then(|ecdh| self.complete(&ecdh.public.0))
105 }
106
complete(self, peer: &[u8]) -> Option<KeyExchangeResult>107 pub fn complete(self, peer: &[u8]) -> Option<KeyExchangeResult> {
108 let peer_key = ring::agreement::UnparsedPublicKey::new(self.alg, peer);
109 let secret = ring::agreement::agree_ephemeral(self.privkey, &peer_key, (), |v| {
110 let mut r = Vec::new();
111 r.extend_from_slice(v);
112 Ok(r)
113 });
114
115 if secret.is_err() {
116 return None;
117 }
118
119 Some(KeyExchangeResult {
120 pubkey: self.pubkey,
121 shared_secret: secret.unwrap(),
122 })
123 }
124 }
125
126 /// A cipher suite supported by rustls.
127 ///
128 /// All possible instances of this class are provided by the library in
129 /// the `ALL_CIPHERSUITES` array.
130 pub struct SupportedCipherSuite {
131 /// The TLS enumeration naming this cipher suite.
132 pub suite: CipherSuite,
133
134 /// How to exchange/agree keys.
135 pub kx: KeyExchangeAlgorithm,
136
137 /// How to do bulk encryption.
138 pub bulk: BulkAlgorithm,
139
140 /// How to do hashing.
141 pub hash: HashAlgorithm,
142
143 /// How to sign messages for authentication.
144 ///
145 /// This is not present for TLS1.3, because authentication is orthogonal
146 /// to the ciphersuite concept there.
147 pub sign: Option<&'static [SignatureScheme]>,
148
149 /// Encryption key length, for the bulk algorithm.
150 pub enc_key_len: usize,
151
152 /// How long the fixed part of the 'IV' is.
153 ///
154 /// This isn't usually an IV, but we continue the
155 /// terminology misuse to match the standard.
156 pub fixed_iv_len: usize,
157
158 /// This is a non-standard extension which extends the
159 /// key block to provide an initial explicit nonce offset,
160 /// in a deterministic and safe way. GCM needs this,
161 /// chacha20poly1305 works this way by design.
162 pub explicit_nonce_len: usize,
163
164 pub(crate) hkdf_algorithm: ring::hkdf::Algorithm,
165 pub(crate) aead_algorithm: &'static ring::aead::Algorithm,
166 pub(crate) build_tls12_encrypter: Option<cipher::BuildTLS12Encrypter>,
167 pub(crate) build_tls12_decrypter: Option<cipher::BuildTLS12Decrypter>,
168 }
169
170 impl PartialEq for SupportedCipherSuite {
eq(&self, other: &SupportedCipherSuite) -> bool171 fn eq(&self, other: &SupportedCipherSuite) -> bool {
172 self.suite == other.suite
173 }
174 }
175
176 impl fmt::Debug for SupportedCipherSuite {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 f.debug_struct("SupportedCipherSuite")
179 .field("suite", &self.suite)
180 .field("kx", &self.kx)
181 .field("bulk", &self.bulk)
182 .field("hash", &self.hash)
183 .field("sign", &self.sign)
184 .field("enc_key_len", &self.enc_key_len)
185 .field("fixed_iv_len", &self.fixed_iv_len)
186 .field("explicit_nonce_len", &self.explicit_nonce_len)
187 .finish()
188 }
189 }
190
191 impl SupportedCipherSuite {
192 /// Which hash function to use with this suite.
get_hash(&self) -> &'static ring::digest::Algorithm193 pub fn get_hash(&self) -> &'static ring::digest::Algorithm {
194 self.hkdf_algorithm
195 .hmac_algorithm()
196 .digest_algorithm()
197 }
198
199 /// We have parameters and a verified public key in `kx_params`.
200 /// Generate an ephemeral key, generate the shared secret, and
201 /// return it and the public half in a `KeyExchangeResult`.
do_client_kx(&self, kx_params: &[u8]) -> Option<KeyExchangeResult>202 pub fn do_client_kx(&self, kx_params: &[u8]) -> Option<KeyExchangeResult> {
203 match self.kx {
204 KeyExchangeAlgorithm::ECDHE => KeyExchange::client_ecdhe(kx_params),
205 _ => None,
206 }
207 }
208
209 /// Start the KX process with the given group. This generates
210 /// the server's share, but we don't yet have the client's share.
start_server_kx(&self, named_group: NamedGroup) -> Option<KeyExchange>211 pub fn start_server_kx(&self, named_group: NamedGroup) -> Option<KeyExchange> {
212 match self.kx {
213 KeyExchangeAlgorithm::ECDHE => KeyExchange::start_ecdhe(named_group),
214 _ => None,
215 }
216 }
217
218 /// Resolve the set of supported `SignatureScheme`s from the
219 /// offered `SupportedSignatureSchemes`. If we return an empty
220 /// set, the handshake terminates.
resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme>221 pub fn resolve_sig_schemes(&self, offered: &[SignatureScheme]) -> Vec<SignatureScheme> {
222 if let Some(our_preference) = self.sign {
223 our_preference
224 .iter()
225 .filter(|pref| offered.contains(pref))
226 .cloned()
227 .collect()
228 } else {
229 vec![]
230 }
231 }
232
233 /// Length of key block that needs to be output by the key
234 /// derivation phase for this suite.
key_block_len(&self) -> usize235 pub fn key_block_len(&self) -> usize {
236 (self.enc_key_len + self.fixed_iv_len) * 2 + self.explicit_nonce_len
237 }
238
239 /// Return true if this suite is usable for TLS `version`.
usable_for_version(&self, version: ProtocolVersion) -> bool240 pub fn usable_for_version(&self, version: ProtocolVersion) -> bool {
241 match version {
242 ProtocolVersion::TLSv1_3 => self.build_tls12_encrypter.is_none(),
243 ProtocolVersion::TLSv1_2 => self.build_tls12_encrypter.is_some(),
244 _ => false,
245 }
246 }
247
248 /// Return true if this suite is usable for a key only offering `sigalg`
249 /// signatures. This resolves to true for all TLS1.3 suites.
usable_for_sigalg(&self, sigalg: SignatureAlgorithm) -> bool250 pub fn usable_for_sigalg(&self, sigalg: SignatureAlgorithm) -> bool {
251 match self.sign {
252 None => true, // no constraint expressed by ciphersuite (eg, TLS1.3)
253 Some(schemes) => schemes
254 .iter()
255 .any(|scheme| scheme.sign() == sigalg),
256 }
257 }
258
259 /// Can a session using suite self resume using suite new_suite?
can_resume_to(&self, new_suite: &SupportedCipherSuite) -> bool260 pub fn can_resume_to(&self, new_suite: &SupportedCipherSuite) -> bool {
261 if self.usable_for_version(ProtocolVersion::TLSv1_3)
262 && new_suite.usable_for_version(ProtocolVersion::TLSv1_3)
263 {
264 // TLS1.3 actually specifies requirements here: suites are compatible
265 // for resumption if they have the same KDF hash
266 self.hash == new_suite.hash
267 } else if self.usable_for_version(ProtocolVersion::TLSv1_2)
268 && new_suite.usable_for_version(ProtocolVersion::TLSv1_2)
269 {
270 // Previous versions don't specify any constraint, so we don't
271 // resume between suites to avoid bad interactions.
272 self.suite == new_suite.suite
273 } else {
274 // Suites for different versions definitely can't resume!
275 false
276 }
277 }
278 }
279
280 static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
281 SignatureScheme::ED25519,
282 SignatureScheme::ECDSA_NISTP521_SHA512,
283 SignatureScheme::ECDSA_NISTP384_SHA384,
284 SignatureScheme::ECDSA_NISTP256_SHA256,
285 ];
286
287 static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[
288 SignatureScheme::RSA_PSS_SHA512,
289 SignatureScheme::RSA_PSS_SHA384,
290 SignatureScheme::RSA_PSS_SHA256,
291 SignatureScheme::RSA_PKCS1_SHA512,
292 SignatureScheme::RSA_PKCS1_SHA384,
293 SignatureScheme::RSA_PKCS1_SHA256,
294 ];
295
296 /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
297 pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
298 SupportedCipherSuite {
299 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
300 kx: KeyExchangeAlgorithm::ECDHE,
301 sign: Some(TLS12_ECDSA_SCHEMES),
302 bulk: BulkAlgorithm::CHACHA20_POLY1305,
303 hash: HashAlgorithm::SHA256,
304 enc_key_len: 32,
305 fixed_iv_len: 12,
306 explicit_nonce_len: 0,
307 hkdf_algorithm: ring::hkdf::HKDF_SHA256,
308 aead_algorithm: &ring::aead::CHACHA20_POLY1305,
309 build_tls12_encrypter: Some(cipher::build_tls12_chacha_encrypter),
310 build_tls12_decrypter: Some(cipher::build_tls12_chacha_decrypter),
311 };
312
313 /// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
314 pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =
315 SupportedCipherSuite {
316 suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
317 kx: KeyExchangeAlgorithm::ECDHE,
318 sign: Some(TLS12_RSA_SCHEMES),
319 bulk: BulkAlgorithm::CHACHA20_POLY1305,
320 hash: HashAlgorithm::SHA256,
321 enc_key_len: 32,
322 fixed_iv_len: 12,
323 explicit_nonce_len: 0,
324 hkdf_algorithm: ring::hkdf::HKDF_SHA256,
325 aead_algorithm: &ring::aead::CHACHA20_POLY1305,
326 build_tls12_encrypter: Some(cipher::build_tls12_chacha_encrypter),
327 build_tls12_decrypter: Some(cipher::build_tls12_chacha_decrypter),
328 };
329
330 /// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
331 pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite {
332 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
333 kx: KeyExchangeAlgorithm::ECDHE,
334 sign: Some(TLS12_RSA_SCHEMES),
335 bulk: BulkAlgorithm::AES_128_GCM,
336 hash: HashAlgorithm::SHA256,
337 enc_key_len: 16,
338 fixed_iv_len: 4,
339 explicit_nonce_len: 8,
340 hkdf_algorithm: ring::hkdf::HKDF_SHA256,
341 aead_algorithm: &ring::aead::AES_128_GCM,
342 build_tls12_encrypter: Some(cipher::build_tls12_gcm_128_encrypter),
343 build_tls12_decrypter: Some(cipher::build_tls12_gcm_128_decrypter),
344 };
345
346 /// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
347 pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite {
348 suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
349 kx: KeyExchangeAlgorithm::ECDHE,
350 sign: Some(TLS12_RSA_SCHEMES),
351 bulk: BulkAlgorithm::AES_256_GCM,
352 hash: HashAlgorithm::SHA384,
353 enc_key_len: 32,
354 fixed_iv_len: 4,
355 explicit_nonce_len: 8,
356 hkdf_algorithm: ring::hkdf::HKDF_SHA384,
357 aead_algorithm: &ring::aead::AES_256_GCM,
358 build_tls12_encrypter: Some(cipher::build_tls12_gcm_256_encrypter),
359 build_tls12_decrypter: Some(cipher::build_tls12_gcm_256_decrypter),
360 };
361
362 /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
363 pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite {
364 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
365 kx: KeyExchangeAlgorithm::ECDHE,
366 sign: Some(TLS12_ECDSA_SCHEMES),
367 bulk: BulkAlgorithm::AES_128_GCM,
368 hash: HashAlgorithm::SHA256,
369 enc_key_len: 16,
370 fixed_iv_len: 4,
371 explicit_nonce_len: 8,
372 hkdf_algorithm: ring::hkdf::HKDF_SHA256,
373 aead_algorithm: &ring::aead::AES_128_GCM,
374 build_tls12_encrypter: Some(cipher::build_tls12_gcm_128_encrypter),
375 build_tls12_decrypter: Some(cipher::build_tls12_gcm_128_decrypter),
376 };
377
378 /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
379 pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite {
380 suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
381 kx: KeyExchangeAlgorithm::ECDHE,
382 sign: Some(TLS12_ECDSA_SCHEMES),
383 bulk: BulkAlgorithm::AES_256_GCM,
384 hash: HashAlgorithm::SHA384,
385 enc_key_len: 32,
386 fixed_iv_len: 4,
387 explicit_nonce_len: 8,
388 hkdf_algorithm: ring::hkdf::HKDF_SHA384,
389 aead_algorithm: &ring::aead::AES_256_GCM,
390 build_tls12_encrypter: Some(cipher::build_tls12_gcm_256_encrypter),
391 build_tls12_decrypter: Some(cipher::build_tls12_gcm_256_decrypter),
392 };
393
394 /// The TLS1.3 ciphersuite TLS_CHACHA20_POLY1305_SHA256
395 pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = SupportedCipherSuite {
396 suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
397 kx: KeyExchangeAlgorithm::BulkOnly,
398 sign: None,
399 bulk: BulkAlgorithm::CHACHA20_POLY1305,
400 hash: HashAlgorithm::SHA256,
401 enc_key_len: 32,
402 fixed_iv_len: 12,
403 explicit_nonce_len: 0,
404 hkdf_algorithm: ring::hkdf::HKDF_SHA256,
405 aead_algorithm: &ring::aead::CHACHA20_POLY1305,
406 build_tls12_encrypter: None,
407 build_tls12_decrypter: None,
408 };
409
410 /// The TLS1.3 ciphersuite TLS_AES_256_GCM_SHA384
411 pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite {
412 suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
413 kx: KeyExchangeAlgorithm::BulkOnly,
414 sign: None,
415 bulk: BulkAlgorithm::AES_256_GCM,
416 hash: HashAlgorithm::SHA384,
417 enc_key_len: 32,
418 fixed_iv_len: 12,
419 explicit_nonce_len: 0,
420 hkdf_algorithm: ring::hkdf::HKDF_SHA384,
421 aead_algorithm: &ring::aead::AES_256_GCM,
422 build_tls12_encrypter: None,
423 build_tls12_decrypter: None,
424 };
425
426 /// The TLS1.3 ciphersuite TLS_AES_128_GCM_SHA256
427 pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite {
428 suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
429 kx: KeyExchangeAlgorithm::BulkOnly,
430 sign: None,
431 bulk: BulkAlgorithm::AES_128_GCM,
432 hash: HashAlgorithm::SHA256,
433 enc_key_len: 16,
434 fixed_iv_len: 12,
435 explicit_nonce_len: 0,
436 hkdf_algorithm: ring::hkdf::HKDF_SHA256,
437 aead_algorithm: &ring::aead::AES_128_GCM,
438 build_tls12_encrypter: None,
439 build_tls12_decrypter: None,
440 };
441
442 /// A list of all the cipher suites supported by rustls.
443 pub static ALL_CIPHERSUITES: [&SupportedCipherSuite; 9] = [
444 // TLS1.3 suites
445 &TLS13_CHACHA20_POLY1305_SHA256,
446 &TLS13_AES_256_GCM_SHA384,
447 &TLS13_AES_128_GCM_SHA256,
448 // TLS1.2 suites
449 &TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
450 &TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
451 &TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
452 &TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
453 &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
454 &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
455 ];
456
457 // These both O(N^2)!
choose_ciphersuite_preferring_client( client_suites: &[CipherSuite], server_suites: &[&'static SupportedCipherSuite], ) -> Option<&'static SupportedCipherSuite>458 pub fn choose_ciphersuite_preferring_client(
459 client_suites: &[CipherSuite],
460 server_suites: &[&'static SupportedCipherSuite],
461 ) -> Option<&'static SupportedCipherSuite> {
462 for client_suite in client_suites {
463 if let Some(selected) = server_suites
464 .iter()
465 .find(|x| *client_suite == x.suite)
466 {
467 return Some(*selected);
468 }
469 }
470
471 None
472 }
473
choose_ciphersuite_preferring_server( client_suites: &[CipherSuite], server_suites: &[&'static SupportedCipherSuite], ) -> Option<&'static SupportedCipherSuite>474 pub fn choose_ciphersuite_preferring_server(
475 client_suites: &[CipherSuite],
476 server_suites: &[&'static SupportedCipherSuite],
477 ) -> Option<&'static SupportedCipherSuite> {
478 if let Some(selected) = server_suites
479 .iter()
480 .find(|x| client_suites.contains(&x.suite))
481 {
482 return Some(*selected);
483 }
484
485 None
486 }
487
488 /// Return a list of the ciphersuites in `all` with the suites
489 /// incompatible with `SignatureAlgorithm` `sigalg` removed.
reduce_given_sigalg( all: &[&'static SupportedCipherSuite], sigalg: SignatureAlgorithm, ) -> Vec<&'static SupportedCipherSuite>490 pub fn reduce_given_sigalg(
491 all: &[&'static SupportedCipherSuite],
492 sigalg: SignatureAlgorithm,
493 ) -> Vec<&'static SupportedCipherSuite> {
494 all.iter()
495 .filter(|&&suite| suite.usable_for_sigalg(sigalg))
496 .cloned()
497 .collect()
498 }
499
500 /// Return a list of the ciphersuites in `all` with the suites
501 /// incompatible with the chosen `version` removed.
reduce_given_version( all: &[&'static SupportedCipherSuite], version: ProtocolVersion, ) -> Vec<&'static SupportedCipherSuite>502 pub fn reduce_given_version(
503 all: &[&'static SupportedCipherSuite],
504 version: ProtocolVersion,
505 ) -> Vec<&'static SupportedCipherSuite> {
506 all.iter()
507 .filter(|&&suite| suite.usable_for_version(version))
508 .cloned()
509 .collect()
510 }
511
512 /// Return true if `sigscheme` is usable by any of the given suites.
compatible_sigscheme_for_suites( sigscheme: SignatureScheme, common_suites: &[&'static SupportedCipherSuite], ) -> bool513 pub fn compatible_sigscheme_for_suites(
514 sigscheme: SignatureScheme,
515 common_suites: &[&'static SupportedCipherSuite],
516 ) -> bool {
517 let sigalg = sigscheme.sign();
518 common_suites
519 .iter()
520 .any(|&suite| suite.usable_for_sigalg(sigalg))
521 }
522
523 #[cfg(test)]
524 mod test {
525 use super::*;
526 use crate::msgs::enums::CipherSuite;
527
528 #[test]
test_client_pref()529 fn test_client_pref() {
530 let client = vec![
531 CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
532 CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
533 ];
534 let server = vec![
535 &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
536 &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
537 ];
538 let chosen = choose_ciphersuite_preferring_client(&client, &server);
539 assert!(chosen.is_some());
540 assert_eq!(chosen.unwrap(), &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
541 }
542
543 #[test]
test_server_pref()544 fn test_server_pref() {
545 let client = vec![
546 CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
547 CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
548 ];
549 let server = vec![
550 &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
551 &TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
552 ];
553 let chosen = choose_ciphersuite_preferring_server(&client, &server);
554 assert!(chosen.is_some());
555 assert_eq!(chosen.unwrap(), &TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
556 }
557
558 #[test]
test_pref_fails()559 fn test_pref_fails() {
560 assert!(
561 choose_ciphersuite_preferring_client(
562 &[CipherSuite::TLS_NULL_WITH_NULL_NULL],
563 &ALL_CIPHERSUITES
564 )
565 .is_none()
566 );
567 assert!(
568 choose_ciphersuite_preferring_server(
569 &[CipherSuite::TLS_NULL_WITH_NULL_NULL],
570 &ALL_CIPHERSUITES
571 )
572 .is_none()
573 );
574 }
575
576 #[test]
test_scs_is_debug()577 fn test_scs_is_debug() {
578 println!("{:?}", ALL_CIPHERSUITES);
579 }
580
581 #[test]
test_usable_for_version()582 fn test_usable_for_version() {
583 fn ok_tls13(scs: &SupportedCipherSuite) {
584 assert!(!scs.usable_for_version(ProtocolVersion::TLSv1_0));
585 assert!(!scs.usable_for_version(ProtocolVersion::TLSv1_2));
586 assert!(scs.usable_for_version(ProtocolVersion::TLSv1_3));
587 }
588
589 fn ok_tls12(scs: &SupportedCipherSuite) {
590 assert!(!scs.usable_for_version(ProtocolVersion::TLSv1_0));
591 assert!(scs.usable_for_version(ProtocolVersion::TLSv1_2));
592 assert!(!scs.usable_for_version(ProtocolVersion::TLSv1_3));
593 }
594
595 ok_tls13(&TLS13_CHACHA20_POLY1305_SHA256);
596 ok_tls13(&TLS13_AES_256_GCM_SHA384);
597 ok_tls13(&TLS13_AES_128_GCM_SHA256);
598
599 ok_tls12(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
600 ok_tls12(&TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
601 ok_tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384);
602 ok_tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256);
603 ok_tls12(&TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
604 }
605
606 #[test]
test_can_resume_to()607 fn test_can_resume_to() {
608 assert!(TLS13_CHACHA20_POLY1305_SHA256.can_resume_to(&TLS13_AES_128_GCM_SHA256));
609 assert!(!TLS13_CHACHA20_POLY1305_SHA256.can_resume_to(&TLS13_AES_256_GCM_SHA384));
610 assert!(
611 !TLS13_CHACHA20_POLY1305_SHA256
612 .can_resume_to(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
613 );
614 assert!(
615 !TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
616 .can_resume_to(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
617 );
618 assert!(
619 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
620 .can_resume_to(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
621 );
622 }
623 }
624