1 use aes_gcm::{ 2 aead::{generic_array::GenericArray, Aead, Payload}, 3 Aes128Gcm, KeyInit, Nonce, 4 }; 5 use byteorder::{BigEndian, ByteOrder}; 6 use bytes::{Bytes, BytesMut}; 7 8 use super::Cipher; 9 use crate::{ 10 error::{Error, Result}, 11 key_derivation::*, 12 }; 13 use util::marshal::*; 14 15 pub const CIPHER_AEAD_AES_GCM_AUTH_TAG_LEN: usize = 16; 16 17 const RTCP_ENCRYPTION_FLAG: u8 = 0x80; 18 19 /// AEAD Cipher based on AES. 20 pub(crate) struct CipherAeadAesGcm { 21 srtp_cipher: aes_gcm::Aes128Gcm, 22 srtcp_cipher: aes_gcm::Aes128Gcm, 23 srtp_session_salt: Vec<u8>, 24 srtcp_session_salt: Vec<u8>, 25 } 26 27 impl Cipher for CipherAeadAesGcm { auth_tag_len(&self) -> usize28 fn auth_tag_len(&self) -> usize { 29 CIPHER_AEAD_AES_GCM_AUTH_TAG_LEN 30 } 31 encrypt_rtp( &mut self, payload: &[u8], header: &rtp::header::Header, roc: u32, ) -> Result<Bytes>32 fn encrypt_rtp( 33 &mut self, 34 payload: &[u8], 35 header: &rtp::header::Header, 36 roc: u32, 37 ) -> Result<Bytes> { 38 // Grow the given buffer to fit the output. 39 let mut writer = 40 BytesMut::with_capacity(header.marshal_size() + payload.len() + self.auth_tag_len()); 41 42 let data = header.marshal()?; 43 writer.extend(data); 44 45 let nonce = self.rtp_initialization_vector(header, roc); 46 47 let encrypted = self.srtp_cipher.encrypt( 48 Nonce::from_slice(&nonce), 49 Payload { 50 msg: payload, 51 aad: &writer, 52 }, 53 )?; 54 55 writer.extend(encrypted); 56 Ok(writer.freeze()) 57 } 58 decrypt_rtp( &mut self, ciphertext: &[u8], header: &rtp::header::Header, roc: u32, ) -> Result<Bytes>59 fn decrypt_rtp( 60 &mut self, 61 ciphertext: &[u8], 62 header: &rtp::header::Header, 63 roc: u32, 64 ) -> Result<Bytes> { 65 if ciphertext.len() < self.auth_tag_len() { 66 return Err(Error::ErrFailedToVerifyAuthTag); 67 } 68 69 let nonce = self.rtp_initialization_vector(header, roc); 70 let payload_offset = header.marshal_size(); 71 let decrypted_msg: Vec<u8> = self.srtp_cipher.decrypt( 72 Nonce::from_slice(&nonce), 73 Payload { 74 msg: &ciphertext[payload_offset..], 75 aad: &ciphertext[..payload_offset], 76 }, 77 )?; 78 79 let mut writer = BytesMut::with_capacity(payload_offset + decrypted_msg.len()); 80 writer.extend_from_slice(&ciphertext[..payload_offset]); 81 writer.extend(decrypted_msg); 82 83 Ok(writer.freeze()) 84 } 85 encrypt_rtcp(&mut self, decrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes>86 fn encrypt_rtcp(&mut self, decrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes> { 87 let iv = self.rtcp_initialization_vector(srtcp_index, ssrc); 88 let aad = self.rtcp_additional_authenticated_data(decrypted, srtcp_index); 89 90 let encrypted_data = self.srtcp_cipher.encrypt( 91 Nonce::from_slice(&iv), 92 Payload { 93 msg: &decrypted[8..], 94 aad: &aad, 95 }, 96 )?; 97 98 let mut writer = BytesMut::with_capacity(encrypted_data.len() + aad.len()); 99 writer.extend_from_slice(&decrypted[..8]); 100 writer.extend(encrypted_data); 101 writer.extend_from_slice(&aad[8..]); 102 103 Ok(writer.freeze()) 104 } 105 decrypt_rtcp(&mut self, encrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes>106 fn decrypt_rtcp(&mut self, encrypted: &[u8], srtcp_index: usize, ssrc: u32) -> Result<Bytes> { 107 if encrypted.len() < self.auth_tag_len() + SRTCP_INDEX_SIZE { 108 return Err(Error::ErrFailedToVerifyAuthTag); 109 } 110 111 let nonce = self.rtcp_initialization_vector(srtcp_index, ssrc); 112 let aad = self.rtcp_additional_authenticated_data(encrypted, srtcp_index); 113 114 let decrypted_data = self.srtcp_cipher.decrypt( 115 Nonce::from_slice(&nonce), 116 Payload { 117 msg: &encrypted[8..(encrypted.len() - SRTCP_INDEX_SIZE)], 118 aad: &aad, 119 }, 120 )?; 121 122 let mut writer = BytesMut::with_capacity(8 + decrypted_data.len()); 123 writer.extend_from_slice(&encrypted[..8]); 124 writer.extend(decrypted_data); 125 126 Ok(writer.freeze()) 127 } 128 get_rtcp_index(&self, input: &[u8]) -> usize129 fn get_rtcp_index(&self, input: &[u8]) -> usize { 130 let pos = input.len() - 4; 131 let val = BigEndian::read_u32(&input[pos..]); 132 133 (val & !((RTCP_ENCRYPTION_FLAG as u32) << 24)) as usize 134 } 135 } 136 137 impl CipherAeadAesGcm { 138 /// Create a new AEAD instance. new(master_key: &[u8], master_salt: &[u8]) -> Result<CipherAeadAesGcm>139 pub(crate) fn new(master_key: &[u8], master_salt: &[u8]) -> Result<CipherAeadAesGcm> { 140 let srtp_session_key = aes_cm_key_derivation( 141 LABEL_SRTP_ENCRYPTION, 142 master_key, 143 master_salt, 144 0, 145 master_key.len(), 146 )?; 147 148 let srtp_block = GenericArray::from_slice(&srtp_session_key); 149 150 let srtp_cipher = Aes128Gcm::new(srtp_block); 151 152 let srtcp_session_key = aes_cm_key_derivation( 153 LABEL_SRTCP_ENCRYPTION, 154 master_key, 155 master_salt, 156 0, 157 master_key.len(), 158 )?; 159 160 let srtcp_block = GenericArray::from_slice(&srtcp_session_key); 161 162 let srtcp_cipher = Aes128Gcm::new(srtcp_block); 163 164 let srtp_session_salt = aes_cm_key_derivation( 165 LABEL_SRTP_SALT, 166 master_key, 167 master_salt, 168 0, 169 master_key.len(), 170 )?; 171 172 let srtcp_session_salt = aes_cm_key_derivation( 173 LABEL_SRTCP_SALT, 174 master_key, 175 master_salt, 176 0, 177 master_key.len(), 178 )?; 179 180 Ok(CipherAeadAesGcm { 181 srtp_cipher, 182 srtcp_cipher, 183 srtp_session_salt, 184 srtcp_session_salt, 185 }) 186 } 187 188 /// The 12-octet IV used by AES-GCM SRTP is formed by first concatenating 189 /// 2 octets of zeroes, the 4-octet SSRC, the 4-octet rollover counter 190 /// (ROC), and the 2-octet sequence number (SEQ). The resulting 12-octet 191 /// value is then XORed to the 12-octet salt to form the 12-octet IV. 192 /// 193 /// https://tools.ietf.org/html/rfc7714#section-8.1 rtp_initialization_vector( &self, header: &rtp::header::Header, roc: u32, ) -> Vec<u8>194 pub(crate) fn rtp_initialization_vector( 195 &self, 196 header: &rtp::header::Header, 197 roc: u32, 198 ) -> Vec<u8> { 199 let mut iv = vec![0u8; 12]; 200 BigEndian::write_u32(&mut iv[2..], header.ssrc); 201 BigEndian::write_u32(&mut iv[6..], roc); 202 BigEndian::write_u16(&mut iv[10..], header.sequence_number); 203 204 for (i, v) in iv.iter_mut().enumerate() { 205 *v ^= self.srtp_session_salt[i]; 206 } 207 208 iv 209 } 210 211 /// The 12-octet IV used by AES-GCM SRTCP is formed by first 212 /// concatenating 2 octets of zeroes, the 4-octet SSRC identifier, 213 /// 2 octets of zeroes, a single "0" bit, and the 31-bit SRTCP index. 214 /// The resulting 12-octet value is then XORed to the 12-octet salt to 215 /// form the 12-octet IV. 216 /// 217 /// https://tools.ietf.org/html/rfc7714#section-9.1 rtcp_initialization_vector(&self, srtcp_index: usize, ssrc: u32) -> Vec<u8>218 pub(crate) fn rtcp_initialization_vector(&self, srtcp_index: usize, ssrc: u32) -> Vec<u8> { 219 let mut iv = vec![0u8; 12]; 220 221 BigEndian::write_u32(&mut iv[2..], ssrc); 222 BigEndian::write_u32(&mut iv[8..], srtcp_index as u32); 223 224 for (i, v) in iv.iter_mut().enumerate() { 225 *v ^= self.srtcp_session_salt[i]; 226 } 227 228 iv 229 } 230 231 /// In an SRTCP packet, a 1-bit Encryption flag is prepended to the 232 /// 31-bit SRTCP index to form a 32-bit value we shall call the 233 /// "ESRTCP word" 234 /// 235 /// https://tools.ietf.org/html/rfc7714#section-17 rtcp_additional_authenticated_data( &self, rtcp_packet: &[u8], srtcp_index: usize, ) -> Vec<u8>236 pub(crate) fn rtcp_additional_authenticated_data( 237 &self, 238 rtcp_packet: &[u8], 239 srtcp_index: usize, 240 ) -> Vec<u8> { 241 let mut aad = vec![0u8; 12]; 242 243 aad[..8].copy_from_slice(&rtcp_packet[..8]); 244 245 BigEndian::write_u32(&mut aad[8..], srtcp_index as u32); 246 247 aad[8] |= RTCP_ENCRYPTION_FLAG; 248 aad 249 } 250 } 251