rtc_dtls/cipher_suite/
mod.rs1pub mod cipher_suite_aes_128_ccm;
3pub mod cipher_suite_aes_128_gcm_sha256;
5pub mod cipher_suite_aes_256_cbc_sha;
7pub mod cipher_suite_chacha20_poly1305_sha256;
9pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm;
12pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
14pub mod cipher_suite_tls_psk_with_aes_128_ccm;
16pub mod cipher_suite_tls_psk_with_aes_128_ccm8;
18pub mod cipher_suite_tls_psk_with_aes_128_gcm_sha256;
20
21use std::fmt;
22
23use super::client_certificate_type::*;
24use super::record_layer::record_layer_header::*;
25use shared::error::*;
26
27use cipher_suite_aes_128_gcm_sha256::*;
28use cipher_suite_aes_256_cbc_sha::*;
29use cipher_suite_chacha20_poly1305_sha256::*;
30use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
31use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
32use cipher_suite_tls_psk_with_aes_128_ccm::*;
33use cipher_suite_tls_psk_with_aes_128_ccm8::*;
34use cipher_suite_tls_psk_with_aes_128_gcm_sha256::*;
35
36#[allow(non_camel_case_types)]
39#[derive(Copy, Clone, Debug, PartialEq, Eq)]
40pub enum CipherSuiteId {
42 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm = 0xc0ac,
45 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 = 0xc0ae,
47
48 Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 = 0xc02b,
51 Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 = 0xc02f,
53
54 Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha = 0xc00a,
57 Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha = 0xc014,
59
60 Tls_Psk_With_Aes_128_Ccm = 0xc0a4,
62 Tls_Psk_With_Aes_128_Ccm_8 = 0xc0a8,
64 Tls_Psk_With_Aes_128_Gcm_Sha256 = 0x00a8,
66
67 Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 = 0xcca8,
70 Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 = 0xcca9,
72
73 Unsupported,
75}
76
77impl fmt::Display for CipherSuiteId {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 match *self {
80 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
81 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM")
82 }
83 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => {
84 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8")
85 }
86 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
87 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
88 }
89 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
90 write!(f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
91 }
92 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
93 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
94 }
95 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
96 write!(f, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
97 }
98 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => write!(f, "TLS_PSK_WITH_AES_128_CCM"),
99 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => write!(f, "TLS_PSK_WITH_AES_128_CCM_8"),
100 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
101 write!(f, "TLS_PSK_WITH_AES_128_GCM_SHA256")
102 }
103 CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
104 write!(f, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
105 }
106 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
107 write!(f, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
108 }
109
110 _ => write!(f, "Unsupported CipherSuiteID"),
111 }
112 }
113}
114
115impl From<u16> for CipherSuiteId {
116 fn from(val: u16) -> Self {
117 match val {
118 0xc0ac => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
120 0xc0ae => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
121
122 0xc02b => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256,
124 0xc02f => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256,
125
126 0xc00a => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha,
128 0xc014 => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha,
129
130 0xc0a4 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
131 0xc0a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
132 0x00a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
133
134 0xcca8 => CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256,
136 0xcca9 => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256,
137
138 _ => CipherSuiteId::Unsupported,
139 }
140 }
141}
142
143impl From<&str> for CipherSuiteId {
144 fn from(val: &str) -> Self {
145 match val {
146 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
147 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" => {
148 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8
149 }
150 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => {
151 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256
152 }
153 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => {
154 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256
155 }
156 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" => {
157 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha
158 }
159 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" => {
160 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha
161 }
162 "TLS_PSK_WITH_AES_128_CCM" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
163 "TLS_PSK_WITH_AES_128_CCM_8" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
164 "TLS_PSK_WITH_AES_128_GCM_SHA256" => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
165 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => {
166 CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256
167 }
168 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => {
169 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256
170 }
171 _ => CipherSuiteId::Unsupported,
172 }
173 }
174}
175
176#[derive(Copy, Clone, Debug)]
177pub enum CipherSuiteHash {
179 Sha256,
181}
182
183impl CipherSuiteHash {
184 pub(crate) fn size(&self) -> usize {
185 match *self {
186 CipherSuiteHash::Sha256 => 32,
187 }
188 }
189}
190
191pub trait CipherSuite: Send + Sync {
194 fn to_string(&self) -> String;
196 fn id(&self) -> CipherSuiteId;
198 fn certificate_type(&self) -> ClientCertificateType;
200 fn hash_func(&self) -> CipherSuiteHash;
202 fn is_psk(&self) -> bool;
204 fn is_initialized(&self) -> bool;
206
207 fn init(
214 &mut self,
215 master_secret: &[u8],
216 client_random: &[u8],
217 server_random: &[u8],
218 is_client: bool,
219 ) -> Result<()>;
220
221 fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>;
227 fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>>;
233}
234
235pub fn cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite>> {
244 match id {
245 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
246 Ok(Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()))
247 }
248 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => Ok(Box::new(
249 new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8(),
250 )),
251 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
252 Ok(Box::new(CipherSuiteAes128GcmSha256::new(false)))
253 }
254 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
255 Ok(Box::new(CipherSuiteAes128GcmSha256::new(true)))
256 }
257 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
258 Ok(Box::new(CipherSuiteAes256CbcSha::new(true)))
259 }
260 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
261 Ok(Box::new(CipherSuiteAes256CbcSha::new(false)))
262 }
263 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => {
264 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()))
265 }
266 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => {
267 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()))
268 }
269 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
270 Ok(Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default())
271 }
272 CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
273 Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)))
274 }
275 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
276 Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)))
277 }
278
279 _ => Err(Error::ErrInvalidCipherSuite),
280 }
281}
282
283pub(crate) fn default_cipher_suites() -> Vec<Box<dyn CipherSuite>> {
285 vec![
286 Box::new(CipherSuiteAes128GcmSha256::new(false)),
287 Box::new(CipherSuiteAes256CbcSha::new(false)),
288 Box::new(CipherSuiteAes128GcmSha256::new(true)),
289 Box::new(CipherSuiteAes256CbcSha::new(true)),
290 Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
291 ]
292}
293
294fn all_cipher_suites() -> Vec<Box<dyn CipherSuite>> {
295 vec![
296 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()),
297 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8()),
298 Box::new(CipherSuiteAes128GcmSha256::new(false)),
299 Box::new(CipherSuiteAes128GcmSha256::new(true)),
300 Box::new(CipherSuiteAes256CbcSha::new(false)),
301 Box::new(CipherSuiteAes256CbcSha::new(true)),
302 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()),
303 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()),
304 Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default(),
305 Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
306 Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)),
307 ]
308}
309
310fn cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite>>> {
311 let mut cipher_suites = vec![];
312 for id in ids {
313 cipher_suites.push(cipher_suite_for_id(*id)?);
314 }
315 Ok(cipher_suites)
316}
317
318pub(crate) fn parse_cipher_suites(
319 user_selected_suites: &[CipherSuiteId],
320 exclude_psk: bool,
321 exclude_non_psk: bool,
322) -> Result<Vec<Box<dyn CipherSuite>>> {
323 let cipher_suites = if !user_selected_suites.is_empty() {
324 cipher_suites_for_ids(user_selected_suites)?
325 } else {
326 default_cipher_suites()
327 };
328
329 let filtered_cipher_suites: Vec<Box<dyn CipherSuite>> = cipher_suites
330 .into_iter()
331 .filter(|c| !((exclude_psk && c.is_psk()) || (exclude_non_psk && !c.is_psk())))
332 .collect();
333
334 if filtered_cipher_suites.is_empty() {
335 Err(Error::ErrNoAvailableCipherSuites)
336 } else {
337 Ok(filtered_cipher_suites)
338 }
339}