@@ -11,14 +11,93 @@ use self::openssl::ssl::{
1111 SslVerifyMode ,
1212} ;
1313use self :: openssl:: x509:: { X509 , store:: X509StoreBuilder , X509VerifyResult } ;
14+ use std:: borrow;
1415use std:: error;
1516use std:: fmt;
1617use std:: io;
1718use std:: sync:: Once ;
1819
19- use { Protocol , TlsAcceptorBuilder , TlsConnectorBuilder } ;
20+ use {
21+ CipherSuiteSet , Protocol , TlsAcceptorBuilder , TlsBulkEncryptionAlgorithm , TlsConnectorBuilder ,
22+ TlsHashAlgorithm , TlsKeyExchangeAlgorithm , TlsSignatureAlgorithm ,
23+ } ;
2024use self :: openssl:: pkey:: Private ;
2125
26+ const CIPHER_STRING_SUFFIX : & [ & str ] = & [
27+ "!aNULL" ,
28+ "!eNULL" ,
29+ "!IDEA" ,
30+ "!SEED" ,
31+ "!SRP" ,
32+ "!PSK" ,
33+ "@STRENGTH" ,
34+ ] ;
35+
36+ fn cartesian_product (
37+ xs : impl IntoIterator < Item = Vec < & ' static str > > ,
38+ ys : impl IntoIterator < Item = & ' static str > + Clone ,
39+ ) -> Vec < Vec < & ' static str > > {
40+ xs. into_iter ( )
41+ . flat_map ( move |x| ys. clone ( ) . into_iter ( ) . map ( move |y| [ & x, & [ y] [ ..] ] . concat ( ) ) )
42+ . collect ( )
43+ }
44+
45+ fn expand_algorithms ( cipher_suites : & CipherSuiteSet ) -> String {
46+ let mut cipher_suite_strings: Vec < Vec < & ' static str > > = vec ! [ ] ;
47+
48+ cipher_suite_strings. extend ( cipher_suites. key_exchange . iter ( ) . map ( |alg| {
49+ vec ! [ match alg {
50+ TlsKeyExchangeAlgorithm :: Dhe => "DHE" ,
51+ TlsKeyExchangeAlgorithm :: Ecdhe => "ECDHE" ,
52+ TlsKeyExchangeAlgorithm :: Rsa => "kRSA" ,
53+ TlsKeyExchangeAlgorithm :: __NonExhaustive => unreachable!( ) ,
54+ } ]
55+ } ) ) ;
56+
57+ cipher_suite_strings = cartesian_product (
58+ cipher_suite_strings,
59+ cipher_suites. signature . iter ( ) . map ( |alg| match alg {
60+ TlsSignatureAlgorithm :: Dss => "aDSS" ,
61+ TlsSignatureAlgorithm :: Ecdsa => "aECDSA" ,
62+ TlsSignatureAlgorithm :: Rsa => "aRSA" ,
63+ TlsSignatureAlgorithm :: __NonExhaustive => unreachable ! ( ) ,
64+ } ) ,
65+ ) ;
66+ cipher_suite_strings = cartesian_product (
67+ cipher_suite_strings,
68+ cipher_suites. bulk_encryption . iter ( ) . map ( |alg| match alg {
69+ TlsBulkEncryptionAlgorithm :: Aes128 => "AES128" ,
70+ TlsBulkEncryptionAlgorithm :: Aes256 => "AES256" ,
71+ TlsBulkEncryptionAlgorithm :: Des => "DES" ,
72+ TlsBulkEncryptionAlgorithm :: Rc2 => "RC2" ,
73+ TlsBulkEncryptionAlgorithm :: Rc4 => "RC4" ,
74+ TlsBulkEncryptionAlgorithm :: TripleDes => "3DES" ,
75+ TlsBulkEncryptionAlgorithm :: __NonExhaustive => unreachable ! ( ) ,
76+ } ) ,
77+ ) ;
78+ cipher_suite_strings = cartesian_product (
79+ cipher_suite_strings,
80+ cipher_suites. hash . iter ( ) . map ( |alg| match alg {
81+ TlsHashAlgorithm :: Md5 => "MD5" ,
82+ TlsHashAlgorithm :: Sha1 => "SHA1" ,
83+ TlsHashAlgorithm :: Sha256 => "SHA256" ,
84+ TlsHashAlgorithm :: Sha384 => "SHA384" ,
85+ TlsHashAlgorithm :: __NonExhaustive => unreachable ! ( ) ,
86+ } ) ,
87+ ) ;
88+
89+ cipher_suite_strings
90+ . into_iter ( )
91+ . map ( move |parts| borrow:: Cow :: Owned ( parts. join ( "+" ) ) )
92+ . chain (
93+ CIPHER_STRING_SUFFIX
94+ . iter ( )
95+ . map ( |s| borrow:: Cow :: Borrowed ( * s) ) ,
96+ )
97+ . collect :: < Vec < _ > > ( )
98+ . join ( ":" )
99+ }
100+
22101#[ cfg( have_min_max_version) ]
23102fn supported_protocols (
24103 min : Option < Protocol > ,
@@ -262,6 +341,9 @@ impl TlsConnector {
262341 connector. add_extra_chain_cert ( cert. to_owned ( ) ) ?;
263342 }
264343 }
344+ if let Some ( ref cipher_suites) = builder. cipher_suites {
345+ connector. set_cipher_list ( & expand_algorithms ( cipher_suites) ) ?;
346+ }
265347 supported_protocols ( builder. min_protocol , builder. max_protocol , & mut connector) ?;
266348
267349 if builder. disable_built_in_roots {
@@ -412,3 +494,34 @@ impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
412494 self . 0 . flush ( )
413495 }
414496}
497+
498+ #[ cfg( test) ]
499+ mod tests {
500+ use super :: * ;
501+
502+ #[ test]
503+ fn expand_algorithms_basic ( ) {
504+ assert_eq ! (
505+ expand_algorithms( & CipherSuiteSet {
506+ key_exchange: vec![ TlsKeyExchangeAlgorithm :: Dhe , TlsKeyExchangeAlgorithm :: Ecdhe ] ,
507+ signature: vec![ TlsSignatureAlgorithm :: Rsa ] ,
508+ bulk_encryption: vec![
509+ TlsBulkEncryptionAlgorithm :: Aes128 ,
510+ TlsBulkEncryptionAlgorithm :: Aes256
511+ ] ,
512+ hash: vec![ TlsHashAlgorithm :: Sha256 , TlsHashAlgorithm :: Sha384 ] ,
513+ } ) ,
514+ "\
515+ DHE+aRSA+AES128+SHA256:\
516+ DHE+aRSA+AES128+SHA384:\
517+ DHE+aRSA+AES256+SHA256:\
518+ DHE+aRSA+AES256+SHA384:\
519+ ECDHE+aRSA+AES128+SHA256:\
520+ ECDHE+aRSA+AES128+SHA384:\
521+ ECDHE+aRSA+AES256+SHA256:\
522+ ECDHE+aRSA+AES256+SHA384:\
523+ !aNULL:!eNULL:!IDEA:!SEED:!SRP:!PSK:@STRENGTH\
524+ ",
525+ ) ;
526+ }
527+ }
0 commit comments