rtc_dtls/cipher_suite/
mod.rs1pub mod cipher_suite_aes_128_ccm;
2pub mod cipher_suite_aes_128_gcm_sha256;
3pub mod cipher_suite_aes_256_cbc_sha;
4pub mod cipher_suite_chacha20_poly1305_sha256;
5pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm;
6pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
7pub mod cipher_suite_tls_psk_with_aes_128_ccm;
8pub mod cipher_suite_tls_psk_with_aes_128_ccm8;
9pub mod cipher_suite_tls_psk_with_aes_128_gcm_sha256;
10
11use std::fmt;
12
13use super::client_certificate_type::*;
14use super::record_layer::record_layer_header::*;
15use shared::error::*;
16
17use cipher_suite_aes_128_gcm_sha256::*;
18use cipher_suite_aes_256_cbc_sha::*;
19use cipher_suite_chacha20_poly1305_sha256::*;
20use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
21use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
22use cipher_suite_tls_psk_with_aes_128_ccm::*;
23use cipher_suite_tls_psk_with_aes_128_ccm8::*;
24use cipher_suite_tls_psk_with_aes_128_gcm_sha256::*;
25
26#[allow(non_camel_case_types)]
29#[derive(Copy, Clone, Debug, PartialEq, Eq)]
30pub enum CipherSuiteId {
31 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm = 0xc0ac,
33 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 = 0xc0ae,
34
35 Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 = 0xc02b,
37 Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 = 0xc02f,
38
39 Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha = 0xc00a,
41 Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha = 0xc014,
42
43 Tls_Psk_With_Aes_128_Ccm = 0xc0a4,
44 Tls_Psk_With_Aes_128_Ccm_8 = 0xc0a8,
45 Tls_Psk_With_Aes_128_Gcm_Sha256 = 0x00a8,
46
47 Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 = 0xcca8,
49 Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 = 0xcca9,
50
51 Unsupported,
52}
53
54impl fmt::Display for CipherSuiteId {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match *self {
57 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
58 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM")
59 }
60 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => {
61 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8")
62 }
63 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
64 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
65 }
66 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
67 write!(f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
68 }
69 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
70 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
71 }
72 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
73 write!(f, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
74 }
75 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => write!(f, "TLS_PSK_WITH_AES_128_CCM"),
76 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => write!(f, "TLS_PSK_WITH_AES_128_CCM_8"),
77 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
78 write!(f, "TLS_PSK_WITH_AES_128_GCM_SHA256")
79 }
80 CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
81 write!(f, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
82 }
83 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
84 write!(f, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
85 }
86
87 _ => write!(f, "Unsupported CipherSuiteID"),
88 }
89 }
90}
91
92impl From<u16> for CipherSuiteId {
93 fn from(val: u16) -> Self {
94 match val {
95 0xc0ac => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
97 0xc0ae => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
98
99 0xc02b => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256,
101 0xc02f => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256,
102
103 0xc00a => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha,
105 0xc014 => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha,
106
107 0xc0a4 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
108 0xc0a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
109 0x00a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
110
111 0xcca8 => CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256,
113 0xcca9 => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256,
114
115 _ => CipherSuiteId::Unsupported,
116 }
117 }
118}
119
120impl From<&str> for CipherSuiteId {
121 fn from(val: &str) -> Self {
122 match val {
123 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
124 "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" => {
125 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8
126 }
127 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => {
128 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256
129 }
130 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => {
131 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256
132 }
133 "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" => {
134 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha
135 }
136 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" => {
137 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha
138 }
139 "TLS_PSK_WITH_AES_128_CCM" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
140 "TLS_PSK_WITH_AES_128_CCM_8" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
141 "TLS_PSK_WITH_AES_128_GCM_SHA256" => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
142 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => {
143 CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256
144 }
145 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => {
146 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256
147 }
148 _ => CipherSuiteId::Unsupported,
149 }
150 }
151}
152
153#[derive(Copy, Clone, Debug)]
154pub enum CipherSuiteHash {
155 Sha256,
156}
157
158impl CipherSuiteHash {
159 pub(crate) fn size(&self) -> usize {
160 match *self {
161 CipherSuiteHash::Sha256 => 32,
162 }
163 }
164}
165
166pub trait CipherSuite: Send + Sync {
167 fn to_string(&self) -> String;
168 fn id(&self) -> CipherSuiteId;
169 fn certificate_type(&self) -> ClientCertificateType;
170 fn hash_func(&self) -> CipherSuiteHash;
171 fn is_psk(&self) -> bool;
172 fn is_initialized(&self) -> bool;
173
174 fn init(
176 &mut self,
177 master_secret: &[u8],
178 client_random: &[u8],
179 server_random: &[u8],
180 is_client: bool,
181 ) -> Result<()>;
182
183 fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>;
184 fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>>;
185}
186
187pub fn cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite>> {
191 match id {
192 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
193 Ok(Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()))
194 }
195 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => Ok(Box::new(
196 new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8(),
197 )),
198 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
199 Ok(Box::new(CipherSuiteAes128GcmSha256::new(false)))
200 }
201 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
202 Ok(Box::new(CipherSuiteAes128GcmSha256::new(true)))
203 }
204 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
205 Ok(Box::new(CipherSuiteAes256CbcSha::new(true)))
206 }
207 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
208 Ok(Box::new(CipherSuiteAes256CbcSha::new(false)))
209 }
210 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => {
211 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()))
212 }
213 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => {
214 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()))
215 }
216 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
217 Ok(Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default())
218 }
219 CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
220 Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)))
221 }
222 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
223 Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)))
224 }
225
226 _ => Err(Error::ErrInvalidCipherSuite),
227 }
228}
229
230pub(crate) fn default_cipher_suites() -> Vec<Box<dyn CipherSuite>> {
232 vec![
233 Box::new(CipherSuiteAes128GcmSha256::new(false)),
234 Box::new(CipherSuiteAes256CbcSha::new(false)),
235 Box::new(CipherSuiteAes128GcmSha256::new(true)),
236 Box::new(CipherSuiteAes256CbcSha::new(true)),
237 Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
238 ]
239}
240
241fn all_cipher_suites() -> Vec<Box<dyn CipherSuite>> {
242 vec![
243 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()),
244 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8()),
245 Box::new(CipherSuiteAes128GcmSha256::new(false)),
246 Box::new(CipherSuiteAes128GcmSha256::new(true)),
247 Box::new(CipherSuiteAes256CbcSha::new(false)),
248 Box::new(CipherSuiteAes256CbcSha::new(true)),
249 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()),
250 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()),
251 Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default(),
252 Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
253 Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)),
254 ]
255}
256
257fn cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite>>> {
258 let mut cipher_suites = vec![];
259 for id in ids {
260 cipher_suites.push(cipher_suite_for_id(*id)?);
261 }
262 Ok(cipher_suites)
263}
264
265pub(crate) fn parse_cipher_suites(
266 user_selected_suites: &[CipherSuiteId],
267 exclude_psk: bool,
268 exclude_non_psk: bool,
269) -> Result<Vec<Box<dyn CipherSuite>>> {
270 let cipher_suites = if !user_selected_suites.is_empty() {
271 cipher_suites_for_ids(user_selected_suites)?
272 } else {
273 default_cipher_suites()
274 };
275
276 let filtered_cipher_suites: Vec<Box<dyn CipherSuite>> = cipher_suites
277 .into_iter()
278 .filter(|c| !((exclude_psk && c.is_psk()) || (exclude_non_psk && !c.is_psk())))
279 .collect();
280
281 if filtered_cipher_suites.is_empty() {
282 Err(Error::ErrNoAvailableCipherSuites)
283 } else {
284 Ok(filtered_cipher_suites)
285 }
286}