rustls/
suites.rs

1use crate::cipher;
2use crate::msgs::codec::{Codec, Reader};
3use crate::msgs::enums::{CipherSuite, HashAlgorithm, SignatureAlgorithm, SignatureScheme};
4use crate::msgs::enums::{NamedGroup, ProtocolVersion};
5use crate::msgs::handshake::DecomposedSignatureScheme;
6use crate::msgs::handshake::KeyExchangeAlgorithm;
7use crate::msgs::handshake::{ClientECDHParams, ServerECDHParams};
8
9use ring;
10use std::fmt;
11
12/// Bulk symmetric encryption scheme used by a cipher suite.
13#[allow(non_camel_case_types)]
14#[derive(Debug, PartialEq)]
15pub 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).
29pub 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.
36pub 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
43impl KeyExchange {
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
55    pub fn supported_groups() -> &'static [NamedGroup] {
56        // in preference order
57        &[
58            NamedGroup::X25519,
59            NamedGroup::secp384r1,
60            NamedGroup::secp256r1,
61        ]
62    }
63
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
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
87    pub fn check_client_params(&self, kx_params: &[u8]) -> bool {
88        self.decode_client_params(kx_params)
89            .is_some()
90    }
91
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
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
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.
130pub 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
170impl PartialEq for SupportedCipherSuite {
171    fn eq(&self, other: &SupportedCipherSuite) -> bool {
172        self.suite == other.suite
173    }
174}
175
176impl fmt::Debug for SupportedCipherSuite {
177    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
191impl SupportedCipherSuite {
192    /// Which hash function to use with this suite.
193    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`.
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.
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.
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.
235    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`.
240    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.
250    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?
260    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
280static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[
281    SignatureScheme::ED25519,
282    SignatureScheme::ECDSA_NISTP521_SHA512,
283    SignatureScheme::ECDSA_NISTP384_SHA384,
284    SignatureScheme::ECDSA_NISTP256_SHA256,
285];
286
287static 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.
297pub 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
314pub 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
331pub 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
347pub 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
363pub 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
379pub 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
395pub 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
411pub 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
427pub 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.
443pub 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)!
458pub 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
474pub 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.
490pub 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.
502pub 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.
513pub 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)]
524mod test {
525    use super::*;
526    use crate::msgs::enums::CipherSuite;
527
528    #[test]
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]
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]
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]
577    fn test_scs_is_debug() {
578        println!("{:?}", ALL_CIPHERSUITES);
579    }
580
581    #[test]
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]
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}