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