1 pub mod cipher_suite_aes_128_ccm;
2 pub mod cipher_suite_aes_128_gcm_sha256;
3 pub mod cipher_suite_aes_256_cbc_sha;
4 pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm;
5 pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
6 pub mod cipher_suite_tls_psk_with_aes_128_ccm;
7 pub mod cipher_suite_tls_psk_with_aes_128_ccm8;
8 pub mod cipher_suite_tls_psk_with_aes_128_gcm_sha256;
9
10 use std::fmt;
11 use std::marker::{Send, Sync};
12
13 use super::client_certificate_type::*;
14 use super::error::*;
15 use super::record_layer::record_layer_header::*;
16
17 use cipher_suite_aes_128_gcm_sha256::*;
18 use cipher_suite_aes_256_cbc_sha::*;
19 use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
20 use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
21 use cipher_suite_tls_psk_with_aes_128_ccm::*;
22 use cipher_suite_tls_psk_with_aes_128_ccm8::*;
23 use cipher_suite_tls_psk_with_aes_128_gcm_sha256::*;
24
25 // CipherSuiteID is an ID for our supported CipherSuites
26 // Supported Cipher Suites
27 #[allow(non_camel_case_types)]
28 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
29 pub enum CipherSuiteId {
30 // AES-128-CCM
31 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm = 0xc0ac,
32 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 = 0xc0ae,
33
34 // AES-128-GCM-SHA256
35 Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 = 0xc02b,
36 Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 = 0xc02f,
37
38 // AES-256-CBC-SHA
39 Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha = 0xc00a,
40 Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha = 0xc014,
41
42 Tls_Psk_With_Aes_128_Ccm = 0xc0a4,
43 Tls_Psk_With_Aes_128_Ccm_8 = 0xc0a8,
44 Tls_Psk_With_Aes_128_Gcm_Sha256 = 0x00a8,
45
46 Unsupported,
47 }
48
49 impl fmt::Display for CipherSuiteId {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match *self {
52 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
53 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM")
54 }
55 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => {
56 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8")
57 }
58 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
59 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
60 }
61 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
62 write!(f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
63 }
64 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
65 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
66 }
67 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
68 write!(f, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
69 }
70 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => write!(f, "TLS_PSK_WITH_AES_128_CCM"),
71 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => write!(f, "TLS_PSK_WITH_AES_128_CCM_8"),
72 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
73 write!(f, "TLS_PSK_WITH_AES_128_GCM_SHA256")
74 }
75 _ => write!(f, "Unsupported CipherSuiteID"),
76 }
77 }
78 }
79
80 impl From<u16> for CipherSuiteId {
from(val: u16) -> Self81 fn from(val: u16) -> Self {
82 match val {
83 // AES-128-CCM
84 0xc0ac => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
85 0xc0ae => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
86
87 // AES-128-GCM-SHA256
88 0xc02b => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256,
89 0xc02f => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256,
90
91 // AES-256-CBC-SHA
92 0xc00a => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha,
93 0xc014 => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha,
94
95 0xc0a4 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
96 0xc0a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
97 0x00a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
98
99 _ => CipherSuiteId::Unsupported,
100 }
101 }
102 }
103
104 #[derive(Copy, Clone, Debug)]
105 pub enum CipherSuiteHash {
106 Sha256,
107 }
108
109 impl CipherSuiteHash {
size(&self) -> usize110 pub(crate) fn size(&self) -> usize {
111 match *self {
112 CipherSuiteHash::Sha256 => 32,
113 }
114 }
115 }
116
117 pub trait CipherSuite {
to_string(&self) -> String118 fn to_string(&self) -> String;
id(&self) -> CipherSuiteId119 fn id(&self) -> CipherSuiteId;
certificate_type(&self) -> ClientCertificateType120 fn certificate_type(&self) -> ClientCertificateType;
hash_func(&self) -> CipherSuiteHash121 fn hash_func(&self) -> CipherSuiteHash;
is_psk(&self) -> bool122 fn is_psk(&self) -> bool;
is_initialized(&self) -> bool123 fn is_initialized(&self) -> bool;
124
125 // Generate the internal encryption state
init( &mut self, master_secret: &[u8], client_random: &[u8], server_random: &[u8], is_client: bool, ) -> Result<()>126 fn init(
127 &mut self,
128 master_secret: &[u8],
129 client_random: &[u8],
130 server_random: &[u8],
131 is_client: bool,
132 ) -> Result<()>;
133
encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>134 fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>;
decrypt(&self, input: &[u8]) -> Result<Vec<u8>>135 fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>>;
136 }
137
138 // Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml
139 // A cipher_suite is a specific combination of key agreement, cipher and MAC
140 // function.
cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite + Send + Sync>>141 pub fn cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite + Send + Sync>> {
142 match id {
143 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
144 Ok(Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()))
145 }
146 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => Ok(Box::new(
147 new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8(),
148 )),
149 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
150 Ok(Box::new(CipherSuiteAes128GcmSha256::new(false)))
151 }
152 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
153 Ok(Box::new(CipherSuiteAes128GcmSha256::new(true)))
154 }
155 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
156 Ok(Box::new(CipherSuiteAes256CbcSha::new(true)))
157 }
158 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
159 Ok(Box::new(CipherSuiteAes256CbcSha::new(false)))
160 }
161 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => {
162 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()))
163 }
164 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => {
165 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()))
166 }
167 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
168 Ok(Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default())
169 }
170 _ => Err(Error::ErrInvalidCipherSuite),
171 }
172 }
173
174 // CipherSuites we support in order of preference
default_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>>175 pub(crate) fn default_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
176 vec![
177 Box::new(CipherSuiteAes128GcmSha256::new(false)),
178 Box::new(CipherSuiteAes256CbcSha::new(false)),
179 Box::new(CipherSuiteAes128GcmSha256::new(true)),
180 Box::new(CipherSuiteAes256CbcSha::new(true)),
181 ]
182 }
183
all_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>>184 fn all_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
185 vec![
186 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()),
187 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8()),
188 Box::new(CipherSuiteAes128GcmSha256::new(false)),
189 Box::new(CipherSuiteAes128GcmSha256::new(true)),
190 Box::new(CipherSuiteAes256CbcSha::new(false)),
191 Box::new(CipherSuiteAes256CbcSha::new(true)),
192 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()),
193 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()),
194 Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default(),
195 ]
196 }
197
cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>>198 fn cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>> {
199 let mut cipher_suites = vec![];
200 for id in ids {
201 cipher_suites.push(cipher_suite_for_id(*id)?);
202 }
203 Ok(cipher_suites)
204 }
205
parse_cipher_suites( user_selected_suites: &[CipherSuiteId], exclude_psk: bool, exclude_non_psk: bool, ) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>>206 pub(crate) fn parse_cipher_suites(
207 user_selected_suites: &[CipherSuiteId],
208 exclude_psk: bool,
209 exclude_non_psk: bool,
210 ) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>> {
211 let cipher_suites = if !user_selected_suites.is_empty() {
212 cipher_suites_for_ids(user_selected_suites)?
213 } else {
214 default_cipher_suites()
215 };
216
217 let filtered_cipher_suites: Vec<Box<dyn CipherSuite + Send + Sync>> = cipher_suites
218 .into_iter()
219 .filter(|c| !((exclude_psk && c.is_psk()) || (exclude_non_psk && !c.is_psk())))
220 .collect();
221
222 if filtered_cipher_suites.is_empty() {
223 Err(Error::ErrNoAvailableCipherSuites)
224 } else {
225 Ok(filtered_cipher_suites)
226 }
227 }
228