1use crate::error::RlsResult;
2use crate::extend::Aead;
3use crate::hash::HashType;
4use crate::{Hasher, RlsError};
5use std::fmt::{Debug, Formatter};
6pub use cipher::TlsCipher;
7
8pub mod iv;
9mod cipher;
10
11pub struct CipherSuite {
12 value: u16,
13 hasher: Option<Hasher>,
14 aead: Option<Aead>,
15}
16
17impl CipherSuite {
18 pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: CipherSuite = CipherSuite {
20 value: 0xc02b,
21 hasher: None,
22 aead: None,
23 };
24 pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: CipherSuite = CipherSuite {
25 value: 0xc02c,
26 hasher: None,
27 aead: None,
28 };
29 pub const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: CipherSuite = CipherSuite {
30 value: 0xc023,
31 hasher: None,
32 aead: None,
33 };
34 pub const TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: CipherSuite = CipherSuite {
35 value: 0xc024,
36 hasher: None,
37 aead: None,
38 };
39 pub const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: CipherSuite = CipherSuite {
40 value: 0xc009,
41 hasher: None,
42 aead: None,
43 };
44 pub const TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: CipherSuite = CipherSuite {
45 value: 0xc00a,
46 hasher: None,
47 aead: None,
48 };
49 pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: CipherSuite = CipherSuite {
50 value: 0xcca9,
51 hasher: None,
52 aead: None,
53 };
54
55 pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: CipherSuite = CipherSuite {
57 value: 0xc02f,
58 hasher: None,
59 aead: None,
60 };
61 pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: CipherSuite = CipherSuite {
62 value: 0xc030,
63 hasher: None,
64 aead: None,
65 };
66 pub const TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: CipherSuite = CipherSuite {
67 value: 0xc027,
68 hasher: None,
69 aead: None,
70 };
71 pub const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: CipherSuite = CipherSuite {
72 value: 0xc028,
73 hasher: None,
74 aead: None,
75 };
76 pub const TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: CipherSuite = CipherSuite {
77 value: 0xc013,
78 hasher: None,
79 aead: None,
80 };
81 pub const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: CipherSuite = CipherSuite {
82 value: 0xc014,
83 hasher: None,
84 aead: None,
85 };
86 pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: CipherSuite = CipherSuite {
87 value: 0xcca8,
88 hasher: None,
89 aead: None,
90 };
91
92 pub const TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: CipherSuite = CipherSuite {
94 value: 0x009e,
95 hasher: None,
96 aead: None,
97 };
98 pub const TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: CipherSuite = CipherSuite {
99 value: 0x009f,
100 hasher: None,
101 aead: None,
102 };
103 pub const TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: CipherSuite = CipherSuite {
104 value: 0x0067,
105 hasher: None,
106 aead: None,
107 };
108 pub const TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: CipherSuite = CipherSuite {
109 value: 0x006b,
110 hasher: None,
111 aead: None,
112 };
113 pub const TLS_DHE_RSA_WITH_AES_128_CBC_SHA: CipherSuite = CipherSuite {
114 value: 0x0033,
115 hasher: None,
116 aead: None,
117 };
118 pub const TLS_DHE_RSA_WITH_AES_256_CBC_SHA: CipherSuite = CipherSuite {
119 value: 0x0039,
120 hasher: None,
121 aead: None,
122 };
123 pub const TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: CipherSuite = CipherSuite {
124 value: 0xccaa,
125 hasher: None,
126 aead: None,
127 };
128
129
130 pub const TLS_RSA_WITH_AES_128_GCM_SHA256: CipherSuite = CipherSuite {
132 value: 0x009c,
133 hasher: None,
134 aead: None,
135 };
136 pub const TLS_RSA_WITH_AES_256_GCM_SHA384: CipherSuite = CipherSuite {
137 value: 0x009d,
138 hasher: None,
139 aead: None,
140 };
141 pub const TLS_RSA_WITH_AES_128_CBC_SHA256: CipherSuite = CipherSuite {
142 value: 0x003c,
143 hasher: None,
144 aead: None,
145 };
146 pub const TLS_RSA_WITH_AES_256_CBC_SHA256: CipherSuite = CipherSuite {
147 value: 0x003d,
148 hasher: None,
149 aead: None,
150 };
151 pub const TLS_RSA_WITH_AES_128_CBC_SHA: CipherSuite = CipherSuite {
152 value: 0x002f,
153 hasher: None,
154 aead: None,
155 };
156 pub const TLS_RSA_WITH_AES_256_CBC_SHA: CipherSuite = CipherSuite {
157 value: 0x0035,
158 hasher: None,
159 aead: None,
160 };
161
162 pub const TLS_AES_128_GCM_SHA256: CipherSuite = CipherSuite {
164 value: 0x1301,
165 hasher: None,
166 aead: None,
167 };
168 pub const TLS_AES_256_GCM_SHA384: CipherSuite = CipherSuite {
169 value: 0x1302,
170 hasher: None,
171 aead: None,
172 };
173 pub const TLS_CHACHA20_POLY1305_SHA256: CipherSuite = CipherSuite {
174 value: 0x1303,
175 hasher: None,
176 aead: None,
177 };
178
179 pub const TLS_EMPTY_RENEGOTIATION_INFO_SCSV: CipherSuite = CipherSuite {
180 value: 0x00ff,
181 hasher: None,
182 aead: None,
183 };
184
185 pub const SUITES: [u16; 31] = [0xc02b, 0xc02c, 0xc023, 0xc024, 0xc009, 0xc00a, 0xcca9, 0xc02f, 0xc030, 0xc027, 0xc028, 0xc013, 0xc014, 0xcca8, 0x009e, 0x009f, 0x0067, 0x006b, 0x0033, 0x0039, 0xccaa, 0x009c, 0x009d, 0x003c, 0x003d, 0x002f, 0x0035, 0x1301, 0x1302, 0x1303, 0x00ff];
186
187 pub fn spec(&self) -> &str {
188 match self.value {
189 0xc02b => "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
190 0xc02c => "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
191 0xc023 => "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
192 0xc024 => "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
193 0xc009 => "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
194 0xc00a => "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
195 0xcca9 => "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
196
197 0xc02f => "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
198 0xc030 => "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
199 0xc027 => "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
200 0xc028 => "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
201 0xc013 => "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
202 0xc014 => "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
203 0xcca8 => "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
204
205 0x009e => "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
206 0x009f => "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
207 0x0067 => "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
208 0x006b => "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
209 0x0033 => "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
210 0x0039 => "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
211 0xccaa => "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
212
213 0x009c => "TLS_RSA_WITH_AES_128_GCM_SHA256",
214 0x009d => "TLS_RSA_WITH_AES_256_GCM_SHA384",
215 0x003c => "TLS_RSA_WITH_AES_128_CBC_SHA256",
216 0x003d => "TLS_RSA_WITH_AES_256_CBC_SHA256",
217 0x002f => "TLS_RSA_WITH_AES_128_CBC_SHA",
218 0x0035 => "TLS_RSA_WITH_AES_256_CBC_SHA",
219
220 0x1301 => "TLS_AES_128_GCM_SHA256",
221 0x1302 => "TLS_AES_256_GCM_SHA384",
222 0x1303 => "TLS_CHACHA20_POLY1305_SHA256",
223
224 0x00ff => "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
225 _ => "Reserved"
226 }
227 }
228
229 pub fn key_size(&self) -> u8 {
230 match self.value {
231 0x009c | 0x009d | 0x003c | 0x003d | 0x002f | 0x0035 => 2,
232 _ => 1,
233 }
234 }
235
236 pub fn is_aead(&self) -> bool {
237 matches!(self.value, 0xc02b | 0xc02c | 0xcca9 | 0xc02f | 0xc030 | 0xcca8 | 0x009e | 0x009f | 0xccaa | 0x009c | 0x009d | 0x1301 | 0x1302 | 0x1303)
238 }
239
240
241 pub fn mac_hash(&self) -> Option<HashType> {
242 match self.value {
243 0xc02b => Some(HashType::Sha256),
244 0xc02c => Some(HashType::Sha384),
245 0xc023 => Some(HashType::Sha256),
246 0xc024 => Some(HashType::Sha384),
247 0xc009 => Some(HashType::Sha1),
248 0xc00a => Some(HashType::Sha1),
249 0xcca9 => Some(HashType::Sha256),
250
251 0xc02f => Some(HashType::Sha256),
252 0xc030 => Some(HashType::Sha384),
253 0xc027 => Some(HashType::Sha256),
254 0xc028 => Some(HashType::Sha384),
255 0xc013 => Some(HashType::Sha1),
256 0xc014 => Some(HashType::Sha1),
257 0xcca8 => Some(HashType::Sha256),
258
259 0x009e => Some(HashType::Sha256),
260 0x009f => Some(HashType::Sha384),
261 0x0067 => Some(HashType::Sha256),
262 0x006b => Some(HashType::Sha256),
263 0x0033 => Some(HashType::Sha1),
264 0x0039 => Some(HashType::Sha1),
265 0xccaa => Some(HashType::Sha256),
266
267 0x009c => Some(HashType::Sha256),
268 0x009d => Some(HashType::Sha384),
269 0x003c => Some(HashType::Sha256),
270 0x003d => Some(HashType::Sha256),
271 0x002f => Some(HashType::Sha1),
272 0x0035 => Some(HashType::Sha1),
273
274 0x1301 => Some(HashType::Sha256),
275 0x1302 => Some(HashType::Sha384),
276 0x1303 => Some(HashType::Sha256),
277 _ => None
278 }
279 }
280}
281
282impl PartialEq for CipherSuite {
283 fn eq(&self, other: &CipherSuite) -> bool {
284 self.value == other.value
285 }
286}
287
288impl CipherSuite {
289 pub fn new(v: u16) -> CipherSuite {
290 CipherSuite {
291 value: v,
292 hasher: None,
293 aead: None,
294 }
295 }
296
297 pub fn from_bytes(bytes: &[u8]) -> RlsResult<Vec<CipherSuite>> {
298 let mut res = vec![];
299 for chuck in bytes.chunks(2) {
300 let v = u16::from_be_bytes(chuck.try_into()?);
301 res.push(CipherSuite::new(v));
302 }
303 Ok(res)
304 }
305
306 pub fn is_reserved(&self) -> bool {
307 !CipherSuite::SUITES.contains(&self.value)
308 }
309
310 pub fn into_inner(self) -> u16 { self.value }
311
312 pub fn as_u16(&self) -> u16 {
313 self.value
314 }
315
316 pub fn update(&mut self, data: impl AsRef<[u8]>) -> RlsResult<()> {
317 match self.hasher.as_mut() {
318 None => Err(RlsError::HasherNone),
319 Some(hasher) => hasher.update(data),
320 }
321 }
322
323 fn find_hasher(&self) -> RlsResult<Hasher> {
324 let text = self.spec().to_lowercase();
325 if text.contains("sha256") {
326 Ok(Hasher::new(HashType::Sha256)?)
327 } else if text.contains("sha384") {
328 Ok(Hasher::new(HashType::Sha384)?)
329 } else if text.ends_with("_sha") {
330 Ok(Hasher::new(HashType::Sha256)?)
331 } else {
332 Err(RlsError::HasherNone)
333 }
334 }
335
336 pub fn current_session_hash(&mut self) -> RlsResult<&[u8]> {
337 self.hasher.as_mut().ok_or(RlsError::HasherNone)?.current_hash()
338 }
339
340 pub fn aead(&self) -> Option<&Aead> {
341 self.aead.as_ref()
342 }
343
344 pub fn init_aead_hasher(&mut self) -> RlsResult<()> {
345 self.hasher = Some(self.find_hasher()?);
347 self.aead = Some(Aead::from_cipher_kind(self.spec()).ok_or(RlsError::AeadNone)?);
349 Ok(())
350 }
351
352 pub fn hasher(&self) -> &Option<Hasher> {
353 &self.hasher
354 }
355}
356
357impl Debug for CipherSuite {
358 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
359 write!(f, "{}(0x{:x})", self.spec(), self.value)
360 }
361}
362
363impl Clone for CipherSuite {
364 fn clone(&self) -> Self {
365 CipherSuite {
366 value: self.value,
367 hasher: None,
368 aead: None,
369 }
370 }
371}