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