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 { 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 80 impl From<u16> for CipherSuiteId { 81 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 { 110 pub(crate) fn size(&self) -> usize { 111 match *self { 112 CipherSuiteHash::Sha256 => 32, 113 } 114 } 115 } 116 117 pub 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 // Generate the internal encryption state 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 134 fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[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. 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::new(CipherSuiteTlsPskWithAes128GcmSha256::default())) 169 } 170 _ => Err(Error::ErrInvalidCipherSuite), 171 } 172 } 173 174 // CipherSuites we support in order of preference 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 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::new(CipherSuiteTlsPskWithAes128GcmSha256::default()), 195 ] 196 } 197 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 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