xref: /webrtc/dtls/src/cipher_suite/mod.rs (revision 630c46fe)
1 pub mod cipher_suite_aes_128_ccm;
2 pub mod cipher_suite_aes_128_gcm_sha256;
3 pub mod cipher_suite_aes_256_cbc_sha;
4 pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm;
5 pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
6 pub mod cipher_suite_tls_psk_with_aes_128_ccm;
7 pub mod cipher_suite_tls_psk_with_aes_128_ccm8;
8 pub mod cipher_suite_tls_psk_with_aes_128_gcm_sha256;
9 
10 use std::fmt;
11 use std::marker::{Send, Sync};
12 
13 use super::client_certificate_type::*;
14 use super::error::*;
15 use super::record_layer::record_layer_header::*;
16 
17 use cipher_suite_aes_128_gcm_sha256::*;
18 use cipher_suite_aes_256_cbc_sha::*;
19 use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
20 use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
21 use cipher_suite_tls_psk_with_aes_128_ccm::*;
22 use cipher_suite_tls_psk_with_aes_128_ccm8::*;
23 use cipher_suite_tls_psk_with_aes_128_gcm_sha256::*;
24 
25 // CipherSuiteID is an ID for our supported CipherSuites
26 // Supported Cipher Suites
27 #[allow(non_camel_case_types)]
28 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
29 pub enum CipherSuiteId {
30     // AES-128-CCM
31     Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm = 0xc0ac,
32     Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 = 0xc0ae,
33 
34     // AES-128-GCM-SHA256
35     Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 = 0xc02b,
36     Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 = 0xc02f,
37 
38     // AES-256-CBC-SHA
39     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 
49 impl fmt::Display for CipherSuiteId {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result50     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 
80 impl From<u16> for CipherSuiteId {
from(val: u16) -> Self81     fn from(val: u16) -> Self {
82         match val {
83             // AES-128-CCM
84             0xc0ac => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
85             0xc0ae => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
86 
87             // AES-128-GCM-SHA256
88             0xc02b => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256,
89             0xc02f => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256,
90 
91             // AES-256-CBC-SHA
92             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)]
105 pub enum CipherSuiteHash {
106     Sha256,
107 }
108 
109 impl CipherSuiteHash {
size(&self) -> usize110     pub(crate) fn size(&self) -> usize {
111         match *self {
112             CipherSuiteHash::Sha256 => 32,
113         }
114     }
115 }
116 
117 pub trait CipherSuite {
to_string(&self) -> String118     fn to_string(&self) -> String;
id(&self) -> CipherSuiteId119     fn id(&self) -> CipherSuiteId;
certificate_type(&self) -> ClientCertificateType120     fn certificate_type(&self) -> ClientCertificateType;
hash_func(&self) -> CipherSuiteHash121     fn hash_func(&self) -> CipherSuiteHash;
is_psk(&self) -> bool122     fn is_psk(&self) -> bool;
is_initialized(&self) -> bool123     fn is_initialized(&self) -> bool;
124 
125     // Generate the internal encryption state
init( &mut self, master_secret: &[u8], client_random: &[u8], server_random: &[u8], is_client: bool, ) -> Result<()>126     fn init(
127         &mut self,
128         master_secret: &[u8],
129         client_random: &[u8],
130         server_random: &[u8],
131         is_client: bool,
132     ) -> Result<()>;
133 
encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>134     fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>;
decrypt(&self, input: &[u8]) -> Result<Vec<u8>>135     fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>>;
136 }
137 
138 // Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml
139 // A cipher_suite is a specific combination of key agreement, cipher and MAC
140 // function.
cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite + Send + Sync>>141 pub 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 
174 // CipherSuites we support in order of preference
default_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>>175 pub(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 
all_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>>184 fn 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 
cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>>198 fn 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 
parse_cipher_suites( user_selected_suites: &[CipherSuiteId], exclude_psk: bool, exclude_non_psk: bool, ) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>>206 pub(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 }
228