Skip to main content

reqtls/suite/
mod.rs

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    //ecdhe-ecdhe
19    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    //ecdhe-rsa
56    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    //dhe-rsa
93    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    //rsa
131    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    //empty
163    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        //当hasher为空时需要把这个错误抛出,初始化hasher后一定不能为空
346        self.hasher = Some(self.find_hasher()?);
347        //aead同理
348        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}