1 #[cfg(test)] 2 mod prf_test; 3 4 use std::convert::TryInto; 5 use std::fmt; 6 7 use hmac::{Hmac, Mac}; 8 use sha1::Sha1; 9 use sha2::Digest; 10 use sha2::Sha256; 11 12 type HmacSha256 = Hmac<Sha256>; 13 type HmacSha1 = Hmac<Sha1>; 14 15 use crate::cipher_suite::CipherSuiteHash; 16 use crate::content::ContentType; 17 use crate::curve::named_curve::*; 18 use crate::error::*; 19 use crate::record_layer::record_layer_header::ProtocolVersion; 20 21 pub(crate) const PRF_MASTER_SECRET_LABEL: &str = "master secret"; 22 pub(crate) const PRF_EXTENDED_MASTER_SECRET_LABEL: &str = "extended master secret"; 23 pub(crate) const PRF_KEY_EXPANSION_LABEL: &str = "key expansion"; 24 pub(crate) const PRF_VERIFY_DATA_CLIENT_LABEL: &str = "client finished"; 25 pub(crate) const PRF_VERIFY_DATA_SERVER_LABEL: &str = "server finished"; 26 27 #[derive(PartialEq, Debug, Clone)] 28 pub(crate) struct EncryptionKeys { 29 pub(crate) master_secret: Vec<u8>, 30 pub(crate) client_mac_key: Vec<u8>, 31 pub(crate) server_mac_key: Vec<u8>, 32 pub(crate) client_write_key: Vec<u8>, 33 pub(crate) server_write_key: Vec<u8>, 34 pub(crate) client_write_iv: Vec<u8>, 35 pub(crate) server_write_iv: Vec<u8>, 36 } 37 38 impl fmt::Display for EncryptionKeys { 39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 40 let mut out = "EncryptionKeys:\n".to_string(); 41 42 out += format!("- master_secret: {:?}\n", self.master_secret).as_str(); 43 out += format!("- client_mackey: {:?}\n", self.client_mac_key).as_str(); 44 out += format!("- server_mackey: {:?}\n", self.server_mac_key).as_str(); 45 out += format!("- client_write_key: {:?}\n", self.client_write_key).as_str(); 46 out += format!("- server_write_key: {:?}\n", self.server_write_key).as_str(); 47 out += format!("- client_write_iv: {:?}\n", self.client_write_iv).as_str(); 48 out += format!("- server_write_iv: {:?}\n", self.server_write_iv).as_str(); 49 50 write!(f, "{}", out) 51 } 52 } 53 54 // The premaster secret is formed as follows: if the PSK is N octets 55 // long, concatenate a uint16 with the value N, N zero octets, a second 56 // uint16 with the value N, and the PSK itself. 57 // 58 // https://tools.ietf.org/html/rfc4279#section-2 59 pub(crate) fn prf_psk_pre_master_secret(psk: &[u8]) -> Vec<u8> { 60 let psk_len = psk.len(); 61 62 let mut out = vec![0u8; 2 + psk_len + 2]; 63 64 out.extend_from_slice(psk); 65 let be = (psk_len as u16).to_be_bytes(); 66 out[..2].copy_from_slice(&be); 67 out[2 + psk_len..2 + psk_len + 2].copy_from_slice(&be); 68 69 out 70 } 71 72 pub(crate) fn prf_pre_master_secret( 73 public_key: &[u8], 74 private_key: &NamedCurvePrivateKey, 75 curve: NamedCurve, 76 ) -> Result<Vec<u8>> { 77 match curve { 78 NamedCurve::P256 => elliptic_curve_pre_master_secret(public_key, private_key, curve), 79 NamedCurve::P384 => elliptic_curve_pre_master_secret(public_key, private_key, curve), 80 NamedCurve::X25519 => elliptic_curve_pre_master_secret(public_key, private_key, curve), 81 _ => Err(Error::ErrInvalidNamedCurve), 82 } 83 } 84 85 fn elliptic_curve_pre_master_secret( 86 public_key: &[u8], 87 private_key: &NamedCurvePrivateKey, 88 curve: NamedCurve, 89 ) -> Result<Vec<u8>> { 90 match curve { 91 NamedCurve::P256 => { 92 let pub_key = p256::EncodedPoint::from_bytes(public_key)?; 93 let public = p256::PublicKey::from_sec1_bytes(pub_key.as_ref())?; 94 if let NamedCurvePrivateKey::EphemeralSecretP256(secret) = private_key { 95 return Ok(secret.diffie_hellman(&public).raw_secret_bytes().to_vec()); 96 } 97 } 98 NamedCurve::P384 => { 99 let pub_key = p384::EncodedPoint::from_bytes(public_key)?; 100 let public = p384::PublicKey::from_sec1_bytes(pub_key.as_ref())?; 101 if let NamedCurvePrivateKey::EphemeralSecretP384(secret) = private_key { 102 return Ok(secret.diffie_hellman(&public).raw_secret_bytes().to_vec()); 103 } 104 } 105 NamedCurve::X25519 => { 106 if public_key.len() != 32 { 107 return Err(Error::Other("Public key is not 32 len".into())); 108 } 109 let pub_key: [u8; 32] = public_key.try_into().unwrap(); 110 let public = x25519_dalek::PublicKey::from(pub_key); 111 if let NamedCurvePrivateKey::StaticSecretX25519(secret) = private_key { 112 return Ok(secret.diffie_hellman(&public).as_bytes().to_vec()); 113 } 114 } 115 _ => return Err(Error::ErrInvalidNamedCurve), 116 } 117 Err(Error::ErrNamedCurveAndPrivateKeyMismatch) 118 } 119 120 // This PRF with the SHA-256 hash function is used for all cipher suites 121 // defined in this document and in TLS documents published prior to this 122 // document when TLS 1.2 is negotiated. New cipher suites MUST explicitly 123 // specify a PRF and, in general, SHOULD use the TLS PRF with SHA-256 or a 124 // stronger standard hash function. 125 // 126 // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + 127 // HMAC_hash(secret, A(2) + seed) + 128 // HMAC_hash(secret, A(3) + seed) + ... 129 // 130 // A() is defined as: 131 // 132 // A(0) = seed 133 // A(i) = HMAC_hash(secret, A(i-1)) 134 // 135 // P_hash can be iterated as many times as necessary to produce the 136 // required quantity of data. For example, if P_SHA256 is being used to 137 // create 80 bytes of data, it will have to be iterated three times 138 // (through A(3)), creating 96 bytes of output data; the last 16 bytes 139 // of the final iteration will then be discarded, leaving 80 bytes of 140 // output data. 141 // 142 // https://tools.ietf.org/html/rfc4346w 143 fn hmac_sha(h: CipherSuiteHash, key: &[u8], data: &[u8]) -> Result<Vec<u8>> { 144 let mut mac = match h { 145 CipherSuiteHash::Sha256 => { 146 HmacSha256::new_from_slice(key).map_err(|e| Error::Other(e.to_string()))? 147 } 148 }; 149 mac.update(data); 150 let result = mac.finalize(); 151 let code_bytes = result.into_bytes(); 152 Ok(code_bytes.to_vec()) 153 } 154 155 pub(crate) fn prf_p_hash( 156 secret: &[u8], 157 seed: &[u8], 158 requested_length: usize, 159 h: CipherSuiteHash, 160 ) -> Result<Vec<u8>> { 161 let mut last_round = seed.to_vec(); 162 let mut out = vec![]; 163 164 let iterations = ((requested_length as f64) / (h.size() as f64)).ceil() as usize; 165 for _ in 0..iterations { 166 last_round = hmac_sha(h, secret, &last_round)?; 167 168 let mut last_round_seed = last_round.clone(); 169 last_round_seed.extend_from_slice(seed); 170 let with_secret = hmac_sha(h, secret, &last_round_seed)?; 171 172 out.extend_from_slice(&with_secret); 173 } 174 175 Ok(out[..requested_length].to_vec()) 176 } 177 178 pub(crate) fn prf_extended_master_secret( 179 pre_master_secret: &[u8], 180 session_hash: &[u8], 181 h: CipherSuiteHash, 182 ) -> Result<Vec<u8>> { 183 let mut seed = PRF_EXTENDED_MASTER_SECRET_LABEL.as_bytes().to_vec(); 184 seed.extend_from_slice(session_hash); 185 prf_p_hash(pre_master_secret, &seed, 48, h) 186 } 187 188 pub(crate) fn prf_master_secret( 189 pre_master_secret: &[u8], 190 client_random: &[u8], 191 server_random: &[u8], 192 h: CipherSuiteHash, 193 ) -> Result<Vec<u8>> { 194 let mut seed = PRF_MASTER_SECRET_LABEL.as_bytes().to_vec(); 195 seed.extend_from_slice(client_random); 196 seed.extend_from_slice(server_random); 197 prf_p_hash(pre_master_secret, &seed, 48, h) 198 } 199 200 pub(crate) fn prf_encryption_keys( 201 master_secret: &[u8], 202 client_random: &[u8], 203 server_random: &[u8], 204 prf_mac_len: usize, 205 prf_key_len: usize, 206 prf_iv_len: usize, 207 h: CipherSuiteHash, 208 ) -> Result<EncryptionKeys> { 209 let mut seed = PRF_KEY_EXPANSION_LABEL.as_bytes().to_vec(); 210 seed.extend_from_slice(server_random); 211 seed.extend_from_slice(client_random); 212 213 let material = prf_p_hash( 214 master_secret, 215 &seed, 216 (2 * prf_mac_len) + (2 * prf_key_len) + (2 * prf_iv_len), 217 h, 218 )?; 219 let mut key_material = &material[..]; 220 221 let client_mac_key = key_material[..prf_mac_len].to_vec(); 222 key_material = &key_material[prf_mac_len..]; 223 224 let server_mac_key = key_material[..prf_mac_len].to_vec(); 225 key_material = &key_material[prf_mac_len..]; 226 227 let client_write_key = key_material[..prf_key_len].to_vec(); 228 key_material = &key_material[prf_key_len..]; 229 230 let server_write_key = key_material[..prf_key_len].to_vec(); 231 key_material = &key_material[prf_key_len..]; 232 233 let client_write_iv = key_material[..prf_iv_len].to_vec(); 234 key_material = &key_material[prf_iv_len..]; 235 236 let server_write_iv = key_material[..prf_iv_len].to_vec(); 237 238 Ok(EncryptionKeys { 239 master_secret: master_secret.to_vec(), 240 client_mac_key, 241 server_mac_key, 242 client_write_key, 243 server_write_key, 244 client_write_iv, 245 server_write_iv, 246 }) 247 } 248 249 pub(crate) fn prf_verify_data( 250 master_secret: &[u8], 251 handshake_bodies: &[u8], 252 label: &str, 253 h: CipherSuiteHash, 254 ) -> Result<Vec<u8>> { 255 let mut hasher = match h { 256 CipherSuiteHash::Sha256 => Sha256::new(), 257 }; 258 hasher.update(handshake_bodies); 259 let result = hasher.finalize(); 260 let mut seed = label.as_bytes().to_vec(); 261 seed.extend_from_slice(&result); 262 263 prf_p_hash(master_secret, &seed, 12, h) 264 } 265 266 pub(crate) fn prf_verify_data_client( 267 master_secret: &[u8], 268 handshake_bodies: &[u8], 269 h: CipherSuiteHash, 270 ) -> Result<Vec<u8>> { 271 prf_verify_data( 272 master_secret, 273 handshake_bodies, 274 PRF_VERIFY_DATA_CLIENT_LABEL, 275 h, 276 ) 277 } 278 279 pub(crate) fn prf_verify_data_server( 280 master_secret: &[u8], 281 handshake_bodies: &[u8], 282 h: CipherSuiteHash, 283 ) -> Result<Vec<u8>> { 284 prf_verify_data( 285 master_secret, 286 handshake_bodies, 287 PRF_VERIFY_DATA_SERVER_LABEL, 288 h, 289 ) 290 } 291 292 // compute the MAC using HMAC-SHA1 293 pub(crate) fn prf_mac( 294 epoch: u16, 295 sequence_number: u64, 296 content_type: ContentType, 297 protocol_version: ProtocolVersion, 298 payload: &[u8], 299 key: &[u8], 300 ) -> Result<Vec<u8>> { 301 let mut hmac = HmacSha1::new_from_slice(key).map_err(|e| Error::Other(e.to_string()))?; 302 303 let mut msg = vec![0u8; 13]; 304 msg[..2].copy_from_slice(&epoch.to_be_bytes()); 305 msg[2..8].copy_from_slice(&sequence_number.to_be_bytes()[2..]); 306 msg[8] = content_type as u8; 307 msg[9] = protocol_version.major; 308 msg[10] = protocol_version.minor; 309 msg[11..].copy_from_slice(&(payload.len() as u16).to_be_bytes()); 310 311 hmac.update(&msg); 312 hmac.update(payload); 313 let result = hmac.finalize(); 314 315 Ok(result.into_bytes().to_vec()) 316 } 317