webrtc_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_tls_ecdhe_ecdsa_with_aes_128_ccm;
5pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
6pub mod cipher_suite_tls_psk_with_aes_128_ccm;
7pub mod cipher_suite_tls_psk_with_aes_128_ccm8;
8pub mod cipher_suite_tls_psk_with_aes_128_gcm_sha256;
9
10use std::fmt;
11use std::marker::{Send, Sync};
12
13use cipher_suite_aes_128_gcm_sha256::*;
14use cipher_suite_aes_256_cbc_sha::*;
15use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
16use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
17use cipher_suite_tls_psk_with_aes_128_ccm::*;
18use cipher_suite_tls_psk_with_aes_128_ccm8::*;
19use cipher_suite_tls_psk_with_aes_128_gcm_sha256::*;
20
21use super::client_certificate_type::*;
22use super::error::*;
23use super::record_layer::record_layer_header::*;
24
25#[allow(non_camel_case_types)]
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29pub enum CipherSuiteId {
30 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm = 0xc0ac,
32 Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 = 0xc0ae,
33
34 Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 = 0xc02b,
36 Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 = 0xc02f,
37
38 Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha = 0xc00a,
40 Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha = 0xc014,
41
42 Tls_Psk_With_Aes_128_Ccm = 0xc0a4,
43 Tls_Psk_With_Aes_128_Ccm_8 = 0xc0a8,
44 Tls_Psk_With_Aes_128_Gcm_Sha256 = 0x00a8,
45
46 Unsupported,
47}
48
49impl fmt::Display for CipherSuiteId {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match *self {
52 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
53 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM")
54 }
55 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => {
56 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8")
57 }
58 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
59 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
60 }
61 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
62 write!(f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
63 }
64 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
65 write!(f, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
66 }
67 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
68 write!(f, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
69 }
70 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => write!(f, "TLS_PSK_WITH_AES_128_CCM"),
71 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => write!(f, "TLS_PSK_WITH_AES_128_CCM_8"),
72 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
73 write!(f, "TLS_PSK_WITH_AES_128_GCM_SHA256")
74 }
75 _ => write!(f, "Unsupported CipherSuiteID"),
76 }
77 }
78}
79
80impl From<u16> for CipherSuiteId {
81 fn from(val: u16) -> Self {
82 match val {
83 0xc0ac => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
85 0xc0ae => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
86
87 0xc02b => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256,
89 0xc02f => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256,
90
91 0xc00a => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha,
93 0xc014 => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha,
94
95 0xc0a4 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
96 0xc0a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
97 0x00a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
98
99 _ => CipherSuiteId::Unsupported,
100 }
101 }
102}
103
104#[derive(Copy, Clone, Debug)]
105pub enum CipherSuiteHash {
106 Sha256,
107}
108
109impl CipherSuiteHash {
110 pub(crate) fn size(&self) -> usize {
111 match *self {
112 CipherSuiteHash::Sha256 => 32,
113 }
114 }
115}
116
117pub trait CipherSuite {
118 fn to_string(&self) -> String;
119 fn id(&self) -> CipherSuiteId;
120 fn certificate_type(&self) -> ClientCertificateType;
121 fn hash_func(&self) -> CipherSuiteHash;
122 fn is_psk(&self) -> bool;
123 fn is_initialized(&self) -> bool;
124
125 fn init(
127 &mut self,
128 master_secret: &[u8],
129 client_random: &[u8],
130 server_random: &[u8],
131 is_client: bool,
132 ) -> Result<()>;
133
134 fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>;
135 fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>>;
136}
137
138pub fn cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite + Send + Sync>> {
142 match id {
143 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
144 Ok(Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()))
145 }
146 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => Ok(Box::new(
147 new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8(),
148 )),
149 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
150 Ok(Box::new(CipherSuiteAes128GcmSha256::new(false)))
151 }
152 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
153 Ok(Box::new(CipherSuiteAes128GcmSha256::new(true)))
154 }
155 CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
156 Ok(Box::new(CipherSuiteAes256CbcSha::new(true)))
157 }
158 CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
159 Ok(Box::new(CipherSuiteAes256CbcSha::new(false)))
160 }
161 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => {
162 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()))
163 }
164 CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => {
165 Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()))
166 }
167 CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
168 Ok(Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default())
169 }
170 _ => Err(Error::ErrInvalidCipherSuite),
171 }
172}
173
174pub(crate) fn default_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
176 vec![
177 Box::new(CipherSuiteAes128GcmSha256::new(false)),
178 Box::new(CipherSuiteAes256CbcSha::new(false)),
179 Box::new(CipherSuiteAes128GcmSha256::new(true)),
180 Box::new(CipherSuiteAes256CbcSha::new(true)),
181 ]
182}
183
184fn all_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
185 vec![
186 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()),
187 Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8()),
188 Box::new(CipherSuiteAes128GcmSha256::new(false)),
189 Box::new(CipherSuiteAes128GcmSha256::new(true)),
190 Box::new(CipherSuiteAes256CbcSha::new(false)),
191 Box::new(CipherSuiteAes256CbcSha::new(true)),
192 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()),
193 Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()),
194 Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default(),
195 ]
196}
197
198fn cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>> {
199 let mut cipher_suites = vec![];
200 for id in ids {
201 cipher_suites.push(cipher_suite_for_id(*id)?);
202 }
203 Ok(cipher_suites)
204}
205
206pub(crate) fn parse_cipher_suites(
207 user_selected_suites: &[CipherSuiteId],
208 exclude_psk: bool,
209 exclude_non_psk: bool,
210) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>> {
211 let cipher_suites = if !user_selected_suites.is_empty() {
212 cipher_suites_for_ids(user_selected_suites)?
213 } else {
214 default_cipher_suites()
215 };
216
217 let filtered_cipher_suites: Vec<Box<dyn CipherSuite + Send + Sync>> = cipher_suites
218 .into_iter()
219 .filter(|c| !((exclude_psk && c.is_psk()) || (exclude_non_psk && !c.is_psk())))
220 .collect();
221
222 if filtered_cipher_suites.is_empty() {
223 Err(Error::ErrNoAvailableCipherSuites)
224 } else {
225 Ok(filtered_cipher_suites)
226 }
227}