@@ -11,14 +11,93 @@ use self::openssl::ssl::{
11
11
SslVerifyMode ,
12
12
} ;
13
13
use self :: openssl:: x509:: { X509 , store:: X509StoreBuilder , X509VerifyResult } ;
14
+ use std:: borrow;
14
15
use std:: error;
15
16
use std:: fmt;
16
17
use std:: io;
17
18
use std:: sync:: Once ;
18
19
19
- use { Protocol , TlsAcceptorBuilder , TlsConnectorBuilder } ;
20
+ use {
21
+ CipherSuiteSet , Protocol , TlsAcceptorBuilder , TlsBulkEncryptionAlgorithm , TlsConnectorBuilder ,
22
+ TlsHashAlgorithm , TlsKeyExchangeAlgorithm , TlsSignatureAlgorithm ,
23
+ } ;
20
24
use self :: openssl:: pkey:: Private ;
21
25
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
+
22
101
#[ cfg( have_min_max_version) ]
23
102
fn supported_protocols (
24
103
min : Option < Protocol > ,
@@ -262,6 +341,9 @@ impl TlsConnector {
262
341
connector. add_extra_chain_cert ( cert. to_owned ( ) ) ?;
263
342
}
264
343
}
344
+ if let Some ( ref cipher_suites) = builder. cipher_suites {
345
+ connector. set_cipher_list ( & expand_algorithms ( cipher_suites) ) ?;
346
+ }
265
347
supported_protocols ( builder. min_protocol , builder. max_protocol , & mut connector) ?;
266
348
267
349
if builder. disable_built_in_roots {
@@ -412,3 +494,34 @@ impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
412
494
self . 0 . flush ( )
413
495
}
414
496
}
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