Skip to main content

reqtls/suite/
suite.rs

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