1 use super::Cipher; 2 use crate::error::Result; 3 use crate::{error::Error, key_derivation::*, protection_profile::*}; 4 use util::marshal::*; 5 6 use aes::cipher::generic_array::GenericArray; 7 use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; 8 use bytes::{BufMut, Bytes, BytesMut}; 9 use ctr::cipher::{NewCipher, StreamCipher, StreamCipherSeek}; 10 use hmac::{Hmac, Mac}; 11 use sha1::Sha1; 12 use std::io::BufWriter; 13 use subtle::ConstantTimeEq; 14 15 type HmacSha1 = Hmac<Sha1>; 16 type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>; 17 18 pub const CIPHER_AES_CM_HMAC_SHA1AUTH_TAG_LEN: usize = 10; 19 20 pub(crate) struct CipherAesCmHmacSha1 { 21 srtp_session_key: Vec<u8>, 22 srtp_session_salt: Vec<u8>, 23 srtp_session_auth: HmacSha1, 24 //srtp_session_auth_tag: Vec<u8>, 25 srtcp_session_key: Vec<u8>, 26 srtcp_session_salt: Vec<u8>, 27 srtcp_session_auth: HmacSha1, 28 //srtcp_session_auth_tag: Vec<u8>, 29 } 30 31 impl CipherAesCmHmacSha1 { new(master_key: &[u8], master_salt: &[u8]) -> Result<Self>32 pub fn new(master_key: &[u8], master_salt: &[u8]) -> Result<Self> { 33 let srtp_session_key = aes_cm_key_derivation( 34 LABEL_SRTP_ENCRYPTION, 35 master_key, 36 master_salt, 37 0, 38 master_key.len(), 39 )?; 40 let srtcp_session_key = aes_cm_key_derivation( 41 LABEL_SRTCP_ENCRYPTION, 42 master_key, 43 master_salt, 44 0, 45 master_key.len(), 46 )?; 47 48 let srtp_session_salt = aes_cm_key_derivation( 49 LABEL_SRTP_SALT, 50 master_key, 51 master_salt, 52 0, 53 master_salt.len(), 54 )?; 55 let srtcp_session_salt = aes_cm_key_derivation( 56 LABEL_SRTCP_SALT, 57 master_key, 58 master_salt, 59 0, 60 master_salt.len(), 61 )?; 62 63 let auth_key_len = ProtectionProfile::Aes128CmHmacSha1_80.auth_key_len(); 64 65 let srtp_session_auth_tag = aes_cm_key_derivation( 66 LABEL_SRTP_AUTHENTICATION_TAG, 67 master_key, 68 master_salt, 69 0, 70 auth_key_len, 71 )?; 72 let srtcp_session_auth_tag = aes_cm_key_derivation( 73 LABEL_SRTCP_AUTHENTICATION_TAG, 74 master_key, 75 master_salt, 76 0, 77 auth_key_len, 78 )?; 79 80 let srtp_session_auth = HmacSha1::new_from_slice(&srtp_session_auth_tag) 81 .map_err(|e| Error::Other(e.to_string()))?; 82 let srtcp_session_auth = HmacSha1::new_from_slice(&srtcp_session_auth_tag) 83 .map_err(|e| Error::Other(e.to_string()))?; 84 85 Ok(CipherAesCmHmacSha1 { 86 srtp_session_key, 87 srtp_session_salt, 88 srtp_session_auth, 89 //srtp_session_auth_tag, 90 srtcp_session_key, 91 srtcp_session_salt, 92 srtcp_session_auth, 93 //srtcp_session_auth_tag, 94 }) 95 } 96 97 /// https://tools.ietf.org/html/rfc3711#section-4.2 98 /// In the case of SRTP, M SHALL consist of the Authenticated 99 /// Portion of the packet (as specified in Figure 1) concatenated with 100 /// the roc, M = Authenticated Portion || roc; 101 /// 102 /// The pre-defined authentication transform for SRTP is HMAC-SHA1 103 /// [RFC2104]. With HMAC-SHA1, the SRTP_PREFIX_LENGTH (Figure 3) SHALL 104 /// be 0. For SRTP (respectively SRTCP), the HMAC SHALL be applied to 105 /// the session authentication key and M as specified above, i.e., 106 /// HMAC(k_a, M). The HMAC output SHALL then be truncated to the n_tag 107 /// left-most bits. 108 /// - Authenticated portion of the packet is everything BEFORE MKI 109 /// - k_a is the session message authentication key 110 /// - n_tag is the bit-length of the output authentication tag generate_srtp_auth_tag(&mut self, buf: &[u8], roc: u32) -> Result<Vec<u8>>111 fn generate_srtp_auth_tag(&mut self, buf: &[u8], roc: u32) -> Result<Vec<u8>> { 112 self.srtp_session_auth.reset(); 113 114 self.srtp_session_auth.update(buf); 115 116 // For SRTP only, we need to hash the rollover counter as well. 117 let mut roc_buf: Vec<u8> = vec![]; 118 { 119 let mut writer = BufWriter::<&mut Vec<u8>>::new(roc_buf.as_mut()); 120 writer.write_u32::<BigEndian>(roc)?; 121 } 122 123 self.srtp_session_auth.update(&roc_buf); 124 125 let result = self.srtp_session_auth.clone().finalize(); 126 let code_bytes = result.into_bytes(); 127 128 // Truncate the hash to the first AUTH_TAG_SIZE bytes. 129 Ok(code_bytes[0..self.auth_tag_len()].to_vec()) 130 } 131 132 /// https://tools.ietf.org/html/rfc3711#section-4.2 133 /// 134 /// The pre-defined authentication transform for SRTP is HMAC-SHA1 135 /// [RFC2104]. With HMAC-SHA1, the SRTP_PREFIX_LENGTH (Figure 3) SHALL 136 /// be 0. For SRTP (respectively SRTCP), the HMAC SHALL be applied to 137 /// the session authentication key and M as specified above, i.e., 138 /// HMAC(k_a, M). The HMAC output SHALL then be truncated to the n_tag 139 /// left-most bits. 140 /// - Authenticated portion of the packet is everything BEFORE MKI 141 /// - k_a is the session message authentication key 142 /// - n_tag is the bit-length of the output authentication tag generate_srtcp_auth_tag(&mut self, buf: &[u8]) -> Vec<u8>143 fn generate_srtcp_auth_tag(&mut self, buf: &[u8]) -> Vec<u8> { 144 self.srtcp_session_auth.reset(); 145 146 self.srtcp_session_auth.update(buf); 147 148 let result = self.srtcp_session_auth.clone().finalize(); 149 let code_bytes = result.into_bytes(); 150 151 // Truncate the hash to the first AUTH_TAG_SIZE bytes. 152 code_bytes[0..self.auth_tag_len()].to_vec() 153 } 154 } 155 156 impl Cipher for CipherAesCmHmacSha1 { auth_tag_len(&self) -> usize157 fn auth_tag_len(&self) -> usize { 158 CIPHER_AES_CM_HMAC_SHA1AUTH_TAG_LEN 159 } 160 get_rtcp_index(&self, input: &[u8]) -> usize161 fn get_rtcp_index(&self, input: &[u8]) -> usize { 162 let tail_offset = input.len() - (self.auth_tag_len() + SRTCP_INDEX_SIZE); 163 (BigEndian::read_u32(&input[tail_offset..tail_offset + SRTCP_INDEX_SIZE]) & !(1 << 31)) 164 as usize 165 } 166 encrypt_rtp( &mut self, payload: &[u8], header: &rtp::header::Header, roc: u32, ) -> Result<Bytes>167 fn encrypt_rtp( 168 &mut self, 169 payload: &[u8], 170 header: &rtp::header::Header, 171 roc: u32, 172 ) -> Result<Bytes> { 173 let mut writer = 174 BytesMut::with_capacity(header.marshal_size() + payload.len() + self.auth_tag_len()); 175 176 // Copy the header unencrypted. 177 let data = header.marshal()?; 178 writer.extend(data); 179 180 // Write the plaintext header to the destination buffer. 181 writer.extend_from_slice(payload); 182 183 // Encrypt the payload 184 let counter = generate_counter( 185 header.sequence_number, 186 roc, 187 header.ssrc, 188 &self.srtp_session_salt, 189 )?; 190 let key = GenericArray::from_slice(&self.srtp_session_key); 191 let nonce = GenericArray::from_slice(&counter); 192 let mut stream = Aes128Ctr::new(key, nonce); 193 let payload_offset = header.marshal_size(); 194 stream.apply_keystream(&mut writer[payload_offset..]); 195 196 // Generate the auth tag. 197 let auth_tag = self.generate_srtp_auth_tag(&writer, roc)?; 198 writer.extend(auth_tag); 199 200 Ok(writer.freeze()) 201 } 202 decrypt_rtp( &mut self, encrypted: &[u8], header: &rtp::header::Header, roc: u32, ) -> Result<Bytes>203 fn decrypt_rtp( 204 &mut self, 205 encrypted: &[u8], 206 header: &rtp::header::Header, 207 roc: u32, 208 ) -> Result<Bytes> { 209 if encrypted.len() < self.auth_tag_len() { 210 return Err(Error::SrtpTooSmall(encrypted.len(), self.auth_tag_len())); 211 } 212 213 let mut writer = BytesMut::with_capacity(encrypted.len() - self.auth_tag_len()); 214 215 // Split the auth tag and the cipher text into two parts. 216 let actual_tag = &encrypted[encrypted.len() - self.auth_tag_len()..]; 217 let cipher_text = &encrypted[..encrypted.len() - self.auth_tag_len()]; 218 219 // Generate the auth tag we expect to see from the ciphertext. 220 let expected_tag = self.generate_srtp_auth_tag(cipher_text, roc)?; 221 222 // See if the auth tag actually matches. 223 // We use a constant time comparison to prevent timing attacks. 224 if actual_tag.ct_eq(&expected_tag).unwrap_u8() != 1 { 225 return Err(Error::RtpFailedToVerifyAuthTag); 226 } 227 228 // Write cipher_text to the destination buffer. 229 writer.extend_from_slice(cipher_text); 230 231 // Decrypt the ciphertext for the payload. 232 let counter = generate_counter( 233 header.sequence_number, 234 roc, 235 header.ssrc, 236 &self.srtp_session_salt, 237 )?; 238 239 let key = GenericArray::from_slice(&self.srtp_session_key); 240 let nonce = GenericArray::from_slice(&counter); 241 let mut stream = Aes128Ctr::new(key, nonce); 242 let payload_offset = header.marshal_size(); 243 stream.seek(0); 244 stream.apply_keystream(&mut writer[payload_offset..]); 245 246 Ok(writer.freeze()) 247 } 248 encrypt_rtcp(&mut self, decrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes>249 fn encrypt_rtcp(&mut self, decrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes> { 250 let mut writer = 251 BytesMut::with_capacity(decrypted.len() + SRTCP_INDEX_SIZE + self.auth_tag_len()); 252 253 // Write the decrypted to the destination buffer. 254 writer.extend_from_slice(decrypted); 255 256 // Encrypt everything after header 257 let counter = generate_counter( 258 (srtcp_index & 0xFFFF) as u16, 259 (srtcp_index >> 16) as u32, 260 ssrc, 261 &self.srtcp_session_salt, 262 )?; 263 264 let key = GenericArray::from_slice(&self.srtcp_session_key); 265 let nonce = GenericArray::from_slice(&counter); 266 let mut stream = Aes128Ctr::new(key, nonce); 267 268 stream.apply_keystream( 269 &mut writer[rtcp::header::HEADER_LENGTH + rtcp::header::SSRC_LENGTH..], 270 ); 271 272 // Add SRTCP index and set Encryption bit 273 writer.put_u32(srtcp_index as u32 | (1u32 << 31)); 274 275 // Generate the auth tag. 276 let auth_tag = self.generate_srtcp_auth_tag(&writer); 277 writer.extend(auth_tag); 278 279 Ok(writer.freeze()) 280 } 281 decrypt_rtcp(&mut self, encrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes>282 fn decrypt_rtcp(&mut self, encrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes> { 283 if encrypted.len() < self.auth_tag_len() + SRTCP_INDEX_SIZE { 284 return Err(Error::SrtcpTooSmall( 285 encrypted.len(), 286 self.auth_tag_len() + SRTCP_INDEX_SIZE, 287 )); 288 } 289 290 let tail_offset = encrypted.len() - (self.auth_tag_len() + SRTCP_INDEX_SIZE); 291 292 let mut writer = BytesMut::with_capacity(tail_offset); 293 294 writer.extend_from_slice(&encrypted[0..tail_offset]); 295 296 let is_encrypted = encrypted[tail_offset] >> 7; 297 if is_encrypted == 0 { 298 return Ok(writer.freeze()); 299 } 300 301 // Split the auth tag and the cipher text into two parts. 302 let actual_tag = &encrypted[encrypted.len() - self.auth_tag_len()..]; 303 let cipher_text = &encrypted[..encrypted.len() - self.auth_tag_len()]; 304 305 // Generate the auth tag we expect to see from the ciphertext. 306 let expected_tag = self.generate_srtcp_auth_tag(cipher_text); 307 308 // See if the auth tag actually matches. 309 // We use a constant time comparison to prevent timing attacks. 310 if actual_tag.ct_eq(&expected_tag).unwrap_u8() != 1 { 311 return Err(Error::RtcpFailedToVerifyAuthTag); 312 } 313 314 let counter = generate_counter( 315 (srtcp_index & 0xFFFF) as u16, 316 (srtcp_index >> 16) as u32, 317 ssrc, 318 &self.srtcp_session_salt, 319 )?; 320 321 let key = GenericArray::from_slice(&self.srtcp_session_key); 322 let nonce = GenericArray::from_slice(&counter); 323 let mut stream = Aes128Ctr::new(key, nonce); 324 325 stream.seek(0); 326 stream.apply_keystream( 327 &mut writer[rtcp::header::HEADER_LENGTH + rtcp::header::SSRC_LENGTH..], 328 ); 329 330 Ok(writer.freeze()) 331 } 332 } 333