Skip to content
File

Blob: firmware/vendor/str0m/src/rtp/srtp.rs

rust1544 lines
1use std::fmt;
2use std::panic::{RefUnwindSafe, UnwindSafe};
3 
4use crate::crypto::Aes128CmSha1_80Cipher;
5use crate::crypto::dtls::{KeyingMaterial, SrtpProfile};
6use crate::crypto::{AeadAes128Gcm, AeadAes256Gcm, Aes128CmSha1_80};
7use crate::crypto::{AeadAes128GcmCipher, AeadAes256GcmCipher};
8use crate::crypto::{CryptoProvider, Sha1HmacProvider, SrtpProvider};
9use crate::io::DATAGRAM_MAX_PACKET_SIZE;
10 
11use super::header::RtpHeader;
12 
13// Common among various profiles(defined in RFC3711 Section 4.3)
14const LABEL_RTP_AES: u8 = 0;
15const LABEL_RTP_AUTHENTICATION_KEY: u8 = 1;
16const LABEL_RTP_SALT: u8 = 2;
17 
18const LABEL_RTCP_AES: u8 = 3;
19const LABEL_RTCP_AUTHENTICATION_KEY: u8 = 4;
20const LABEL_RTCP_SALT: u8 = 5;
21 
22// header = 4 bytes
23// ssrc = 4 bytes
24// ssrtcp_index = 4 bytes
25// tag = <T> bytes
26// TOTAL overhead for SRTCP = 12 + T bytes.
27// However, each RTCP packet must be on a 4 byte boundary since length is
28// given in number of 4 bytes - 1 (making 0 valid).
29 
30pub const SRTP_BLOCK_SIZE: usize = 16;
31const SRTCP_INDEX_LEN: usize = 4;
32const SRTCP_HEADER_LEN: usize = 8;
33const MAX_TAG_LEN: usize = AeadAes256Gcm::TAG_LEN;
34pub const SRTCP_OVERHEAD: usize = MAX_TAG_LEN + SRTCP_INDEX_LEN;
35pub const SRTP_OVERHEAD: usize = MAX_TAG_LEN;
36 
37// aws-lc-rs CTR mode requires output buffer to be input.len() + block_len - 1
38// This adds 15 bytes of padding that we truncate after encryption
39const CTR_BUFFER_PADDING: usize = SRTP_BLOCK_SIZE - 1;
40 
41/// Initial capacity for the RTP decryption scratch buffer. Sized to fit the
42/// largest possible received datagram plus the CTR padding the AES-CM cipher
43/// needs, so `unprotect_rtp` never has to grow the buffer in practice.
44const RX_SCRATCH_CAPACITY: usize = DATAGRAM_MAX_PACKET_SIZE + CTR_BUFFER_PADDING;
45 
46impl SrtpContext {
47 /// Create an SRTP context for the relevant profile using the provided keying material.
48 pub fn new(
49 crypto: &CryptoProvider,
50 profile: SrtpProfile,
51 mat: &KeyingMaterial,
52 left: bool,
53 ) -> Self {
54 let sha1_hmac_provider = crypto.sha1_hmac_provider;
55 
56 match profile {
57 SrtpProfile::AES128_CM_SHA1_80 => {
58 let key =
59 SrtpKey::<{ Aes128CmSha1_80::KEY_LEN }, { Aes128CmSha1_80::SALT_LEN }>::new(
60 mat, left,
61 );
62 
63 let (rtp, rtcp) = Derived::aes_128_cm_sha1_80(crypto.srtp_provider, &key);
64 
65 SrtpContext {
66 rtp,
67 rtcp,
68 srtcp_index: 0,
69 sha1_hmac_provider,
70 rx_scratch: Vec::with_capacity(RX_SCRATCH_CAPACITY),
71 }
72 }
73 SrtpProfile::AEAD_AES_128_GCM => {
74 let key = SrtpKey::<{ AeadAes128Gcm::KEY_LEN }, { AeadAes128Gcm::SALT_LEN }>::new(
75 mat, left,
76 );
77 
78 let (rtp, rtcp) = Derived::aead_aes_128_gcm(crypto.srtp_provider, &key);
79 
80 SrtpContext {
81 rtp,
82 rtcp,
83 srtcp_index: 0,
84 sha1_hmac_provider,
85 rx_scratch: Vec::with_capacity(RX_SCRATCH_CAPACITY),
86 }
87 }
88 SrtpProfile::AEAD_AES_256_GCM => {
89 let key = SrtpKey::<{ AeadAes256Gcm::KEY_LEN }, { AeadAes256Gcm::SALT_LEN }>::new(
90 mat, left,
91 );
92 
93 let (rtp, rtcp) = Derived::aead_aes_256_gcm(crypto.srtp_provider, &key);
94 
95 SrtpContext {
96 rtp,
97 rtcp,
98 srtcp_index: 0,
99 sha1_hmac_provider,
100 rx_scratch: Vec::with_capacity(RX_SCRATCH_CAPACITY),
101 }
102 }
103 _ => panic!("Unexpected SRTP profile: {profile:?}"),
104 }
105 }
106 
107 #[cfg(test)]
108 fn new_aead_aes_128_gcm(
109 rtp_key: [u8; AeadAes128Gcm::KEY_LEN],
110 rtp_salt: [u8; AeadAes128Gcm::SALT_LEN],
111 rtcp_key: [u8; AeadAes128Gcm::KEY_LEN],
112 rtcp_salt: [u8; AeadAes128Gcm::SALT_LEN],
113 srtcp_index: u32,
114 ) -> Self {
115 let provider = crate::crypto::test_default_provider();
116 
117 Self {
118 rtp: Derived::AeadAes128Gcm {
119 salt: rtp_salt,
120 enc: provider
121 .srtp_provider
122 .aead_aes_128_gcm()
123 .create_cipher(rtp_key, true),
124 dec: provider
125 .srtp_provider
126 .aead_aes_128_gcm()
127 .create_cipher(rtp_key, false),
128 },
129 rtcp: Derived::AeadAes128Gcm {
130 salt: rtcp_salt,
131 enc: provider
132 .srtp_provider
133 .aead_aes_128_gcm()
134 .create_cipher(rtcp_key, true),
135 dec: provider
136 .srtp_provider
137 .aead_aes_128_gcm()
138 .create_cipher(rtcp_key, false),
139 },
140 srtcp_index,
141 sha1_hmac_provider: provider.sha1_hmac_provider,
142 rx_scratch: Vec::with_capacity(RX_SCRATCH_CAPACITY),
143 }
144 }
145 
146 #[cfg(test)]
147 fn new_aead_aes_256_gcm(
148 rtp_key: [u8; AeadAes256Gcm::KEY_LEN],
149 rtp_salt: [u8; AeadAes256Gcm::SALT_LEN],
150 rtcp_key: [u8; AeadAes256Gcm::KEY_LEN],
151 rtcp_salt: [u8; AeadAes256Gcm::SALT_LEN],
152 srtcp_index: u32,
153 ) -> Self {
154 let provider = crate::crypto::test_default_provider();
155 
156 Self {
157 rtp: Derived::AeadAes256Gcm {
158 salt: rtp_salt,
159 enc: provider
160 .srtp_provider
161 .aead_aes_256_gcm()
162 .create_cipher(rtp_key, true),
163 dec: provider
164 .srtp_provider
165 .aead_aes_256_gcm()
166 .create_cipher(rtp_key, false),
167 },
168 rtcp: Derived::AeadAes256Gcm {
169 salt: rtcp_salt,
170 enc: provider
171 .srtp_provider
172 .aead_aes_256_gcm()
173 .create_cipher(rtcp_key, true),
174 dec: provider
175 .srtp_provider
176 .aead_aes_256_gcm()
177 .create_cipher(rtcp_key, false),
178 },
179 srtcp_index,
180 sha1_hmac_provider: provider.sha1_hmac_provider,
181 rx_scratch: Vec::with_capacity(RX_SCRATCH_CAPACITY),
182 }
183 }
184}
185 
186#[derive(Debug)]
187pub struct SrtpContext {
188 /// Encryption/decryption derived from srtp_key for RTP.
189 rtp: Derived,
190 /// Encryption/decryption derived from srtp_key for RTCP.
191 rtcp: Derived,
192 /// Counter for outgoing SRTCP packets.
193 srtcp_index: u32,
194 /// SHA1-HMAC provider for AES_128_CM_SHA1_80 profile.
195 sha1_hmac_provider: &'static dyn Sha1HmacProvider,
196 /// Reusable scratch buffer for RTP decryption output. Reused across calls
197 /// to `unprotect_rtp` so we don't allocate a fresh `Vec` per packet.
198 rx_scratch: Vec<u8>,
199}
200 
201/// SrtpContext contains cipher contexts that can't observe broken invariants after a panic.
202impl UnwindSafe for SrtpContext {}
203impl RefUnwindSafe for SrtpContext {}
204 
205impl SrtpContext {
206 pub fn protect_rtp(
207 &mut self,
208 buf: &[u8],
209 header: &RtpHeader,
210 srtp_index: u64, // same as ext_seq
211 ) -> Vec<u8> {
212 // SRTP layout
213 // [header, [rtp, (padding + pad_count)], tag]
214 
215 // 0 1 2 3
216 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
217 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+
218 // |V=2|P|X| CC |M| PT | sequence number | |
219 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
220 // | timestamp | |
221 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
222 // | synchronization source (SSRC) identifier | |
223 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
224 // | contributing source (CSRC) identifiers | |
225 // | .... | |
226 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
227 // | RTP extension (OPTIONAL) | |
228 // +>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
229 // | | payload ... | |
230 // | | +-------------------------------+ |
231 // | | | RTP padding | RTP pad count | |
232 // +>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+
233 // | ~ SRTP MKI (OPTIONAL) ~ |
234 // | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
235 // | : authentication tag (RECOMMENDED) : |
236 // | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
237 // | |
238 // +- Encrypted Portion* Authenticated Portion ---+
239 let hlen = header.header_len;
240 let input = &buf[hlen..];
241 
242 match &mut self.rtp {
243 Derived::Aes128CmSha1_80 { key, salt, enc, .. } => {
244 // arbitrary body lengths are fine: the output buffer below is
245 // allocated with the CTR scratch the ciphers need and truncated
246 // after encryption, so no 16-byte alignment is required.
247 let iv = Aes128CmSha1_80::rtp_iv(*salt, *header.ssrc, srtp_index);
248 
249 // Allocate buffer with CTR padding (aws-lc-rs requirement)
250 // HMAC_TAG_LEN is 10, CTR_BUFFER_PADDING is 15, so we need 5 extra bytes
251 let padding_needed =
252 CTR_BUFFER_PADDING.saturating_sub(Aes128CmSha1_80::HMAC_TAG_LEN);
253 let mut output =
254 vec![0_u8; buf.len() + Aes128CmSha1_80::HMAC_TAG_LEN + padding_needed];
255 
256 enc.encrypt(&iv, input, &mut output[hlen..])
257 .expect("rtp encrypt");
258 
259 output[..hlen].copy_from_slice(&buf[..hlen]);
260 
261 let hmac_start = buf.len();
262 let sha1_hmac = |k: &[u8], p: &[&[u8]]| self.sha1_hmac_provider.sha1_hmac(k, p);
263 Aes128CmSha1_80::rtp_hmac(sha1_hmac, key, &mut output, srtp_index, hmac_start);
264 
265 output.truncate(buf.len() + Aes128CmSha1_80::HMAC_TAG_LEN);
266 output
267 }
268 Derived::AeadAes128Gcm { salt, enc, .. } => {
269 let roc = (srtp_index >> 16) as u32;
270 
271 let iv = AeadAes128Gcm::rtp_iv(*salt, *header.ssrc, roc, header.sequence_number);
272 let aad = &buf[..hlen];
273 
274 // Input and output lengths for encryption:
275 // https://www.rfc-editor.org/rfc/rfc7714#section-5.2.1
276 let mut output = vec![0_u8; buf.len() + AeadAes128Gcm::TAG_LEN];
277 enc.encrypt(&iv, aad, input, &mut output[hlen..])
278 .expect("rtp encrypt");
279 
280 output[..hlen].copy_from_slice(aad);
281 
282 output
283 }
284 Derived::AeadAes256Gcm { salt, enc, .. } => {
285 let roc = (srtp_index >> 16) as u32;
286 
287 let iv = AeadAes256Gcm::rtp_iv(*salt, *header.ssrc, roc, header.sequence_number);
288 let aad = &buf[..hlen];
289 
290 // Input and output lengths for encryption:
291 // https://www.rfc-editor.org/rfc/rfc7714#section-5.2.1
292 let mut output = vec![0_u8; buf.len() + AeadAes256Gcm::TAG_LEN];
293 enc.encrypt(&iv, aad, input, &mut output[hlen..])
294 .expect("rtp encrypt");
295 
296 output[..hlen].copy_from_slice(aad);
297 
298 output
299 }
300 }
301 }
302 
303 /// Decrypts an SRTP packet into the internal reusable scratch buffer and
304 /// returns a slice of the plaintext bytes. The returned slice borrows from
305 /// `self` until the next mutable use; the scratch buffer is reused across
306 /// calls to avoid per-packet allocation.
307 pub fn unprotect_rtp(
308 &mut self,
309 buf: &[u8],
310 header: &RtpHeader,
311 srtp_index: u64, // same as ext_seq
312 ) -> Option<&[u8]> {
313 match &mut self.rtp {
314 Derived::Aes128CmSha1_80 { key, salt, dec, .. } => {
315 if buf.len() < header.header_len + Aes128CmSha1_80::HMAC_TAG_LEN {
316 return None;
317 }
318 
319 let hmac_start = buf.len() - Aes128CmSha1_80::HMAC_TAG_LEN;
320 
321 let sha1_hmac = |k: &[u8], p: &[&[u8]]| self.sha1_hmac_provider.sha1_hmac(k, p);
322 if !Aes128CmSha1_80::rtp_verify(
323 sha1_hmac,
324 key,
325 &buf[..hmac_start],
326 srtp_index,
327 &buf[hmac_start..],
328 ) {
329 trace!("unprotect_rtp hmac verify fail");
330 return None;
331 }
332 
333 let iv = Aes128CmSha1_80::rtp_iv(*salt, *header.ssrc, srtp_index);
334 
335 let input = &buf[header.header_len..hmac_start];
336 // Sized with CTR padding (aws-lc-rs requirement).
337 self.rx_scratch.resize(input.len() + CTR_BUFFER_PADDING, 0);
338 
339 if let Err(e) = dec.decrypt(&iv, input, &mut self.rx_scratch) {
340 warn!(
341 "Failed to decrypt SRTP {} ({}): {}",
342 self.rtp.profile(),
343 error_details(header, srtp_index),
344 e
345 );
346 return None;
347 };
348 
349 Some(&self.rx_scratch[..input.len()])
350 }
351 Derived::AeadAes128Gcm { salt, dec, .. } => {
352 if buf.len() < header.header_len + AeadAes128Gcm::TAG_LEN {
353 return None;
354 }
355 
356 let roc: u32 = (srtp_index >> 16) as u32;
357 let seq = header.sequence_number;
358 
359 let iv = AeadAes128Gcm::rtp_iv(*salt, *header.ssrc, roc, seq);
360 
361 let (aad, input) = buf.split_at(header.header_len);
362 // Input and output lengths for decryption:
363 // https://www.rfc-editor.org/rfc/rfc7714#section-5.2.2
364 let out_len = input.len() - AeadAes128Gcm::TAG_LEN;
365 self.rx_scratch.resize(out_len, 0);
366 
367 match dec.decrypt(&iv, &[aad], input, &mut self.rx_scratch) {
368 Ok(v) => v,
369 Err(e) => {
370 warn!(
371 "Failed to decrypt SRTP {} ({}): {}",
372 self.rtp.profile(),
373 error_details(header, srtp_index),
374 e
375 );
376 return None;
377 }
378 };
379 
380 Some(&self.rx_scratch[..out_len])
381 }
382 Derived::AeadAes256Gcm { salt, dec, .. } => {
383 if buf.len() < header.header_len + AeadAes256Gcm::TAG_LEN {
384 return None;
385 }
386 
387 let roc: u32 = (srtp_index >> 16) as u32;
388 let seq = header.sequence_number;
389 
390 let iv = AeadAes256Gcm::rtp_iv(*salt, *header.ssrc, roc, seq);
391 
392 let (aad, input) = buf.split_at(header.header_len);
393 // Input and output lengths for decryption:
394 // https://www.rfc-editor.org/rfc/rfc7714#section-5.2.2
395 let out_len = input.len() - AeadAes256Gcm::TAG_LEN;
396 self.rx_scratch.resize(out_len, 0);
397 
398 match dec.decrypt(&iv, &[aad], input, &mut self.rx_scratch) {
399 Ok(v) => v,
400 Err(e) => {
401 warn!(
402 "Failed to decrypt SRTP {} ({}): {}",
403 self.rtp.profile(),
404 error_details(header, srtp_index),
405 e
406 );
407 return None;
408 }
409 };
410 
411 Some(&self.rx_scratch[..out_len])
412 }
413 }
414 }
415 
416 pub fn protect_rtcp(&mut self, buf: &[u8]) -> Vec<u8> {
417 let srtcp_index = self.srtcp_index;
418 
419 // https://tools.ietf.org/html/rfc3711#page-15
420 // The SRTCP index MUST be set to zero before the first SRTCP
421 // packet is sent, and MUST be incremented by one,
422 // modulo 2^31, after each SRTCP packet is sent.
423 self.srtcp_index = (self.srtcp_index + 1) % 2_u32.pow(31);
424 
425 // e is always encrypted, rest is 31 byte index.
426 let e_and_si = 0x8000_0000 | srtcp_index;
427 let ssrc = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
428 
429 if ssrc == 0 {
430 warn!("SSRC 0 does not make a good SRTCP IV");
431 }
432 
433 match &mut self.rtcp {
434 Derived::Aes128CmSha1_80 { key, salt, enc, .. } => {
435 let iv = Aes128CmSha1_80::rtp_iv(*salt, ssrc, srtcp_index as u64);
436 
437 let final_size = buf.len() + SRTCP_INDEX_LEN + Aes128CmSha1_80::HMAC_TAG_LEN;
438 // Allocate buffer with CTR padding (aws-lc-rs requirement)
439 // SRTCP_INDEX_LEN + HMAC_TAG_LEN is 14, CTR_BUFFER_PADDING is 15, so we need 1 extra byte
440 let padding_needed = CTR_BUFFER_PADDING
441 .saturating_sub(SRTCP_INDEX_LEN + Aes128CmSha1_80::HMAC_TAG_LEN);
442 let mut output = vec![0_u8; final_size + padding_needed];
443 
444 output[0..8].copy_from_slice(&buf[0..8]);
445 let input = &buf[8..];
446 enc.encrypt(&iv, input, &mut output[8..])
447 .expect("rtcp encrypt");
448 
449 let to = &mut output[buf.len()..];
450 to[0..4].copy_from_slice(&e_and_si.to_be_bytes());
451 
452 let hmac_index = final_size - Aes128CmSha1_80::HMAC_TAG_LEN;
453 let sha1_hmac = |k: &[u8], p: &[&[u8]]| self.sha1_hmac_provider.sha1_hmac(k, p);
454 Aes128CmSha1_80::rtcp_hmac(sha1_hmac, key, &mut output, hmac_index);
455 
456 output.truncate(final_size);
457 output
458 }
459 Derived::AeadAes128Gcm { salt, enc, .. } => {
460 let iv = AeadAes128Gcm::rtcp_iv(*salt, ssrc, srtcp_index);
461 
462 let mut aad = [0; AeadAes128Gcm::RTCP_AAD_LEN];
463 aad[..8].copy_from_slice(&buf[..8]);
464 aad[8..12].copy_from_slice(&e_and_si.to_be_bytes());
465 
466 let mut output = vec![0_u8; buf.len() + SRTCP_INDEX_LEN + AeadAes128Gcm::TAG_LEN];
467 output[0..8].copy_from_slice(&buf[0..8]);
468 let input = &buf[8..];
469 
470 let enc_start = 8;
471 let enc_end = input.len() + 8 + AeadAes128Gcm::TAG_LEN;
472 let encout = &mut output[enc_start..enc_end];
473 
474 enc.encrypt(&iv, &aad, input, encout).expect("rtcp encrypt");
475 
476 let to = &mut output[enc_end..];
477 to[0..4].copy_from_slice(&e_and_si.to_be_bytes());
478 
479 output
480 }
481 Derived::AeadAes256Gcm { salt, enc, .. } => {
482 let iv = AeadAes256Gcm::rtcp_iv(*salt, ssrc, srtcp_index);
483 
484 let mut aad = [0; AeadAes256Gcm::RTCP_AAD_LEN];
485 aad[..8].copy_from_slice(&buf[..8]);
486 aad[8..12].copy_from_slice(&e_and_si.to_be_bytes());
487 
488 let mut output = vec![0_u8; buf.len() + SRTCP_INDEX_LEN + AeadAes256Gcm::TAG_LEN];
489 output[0..8].copy_from_slice(&buf[0..8]);
490 let input = &buf[8..];
491 
492 let enc_start = 8;
493 let enc_end = input.len() + 8 + AeadAes256Gcm::TAG_LEN;
494 let encout = &mut output[enc_start..enc_end];
495 
496 enc.encrypt(&iv, &aad, input, encout).expect("rtcp encrypt");
497 
498 let to = &mut output[enc_end..];
499 to[0..4].copy_from_slice(&e_and_si.to_be_bytes());
500 
501 output
502 }
503 }
504 }
505 
506 // SRTCP layout
507 // ["header", ssrc, payload, ["header", ssrc, payload], ...], ssrtcp_index, tag]
508 //
509 // |----------------------------------------------------------------------|
510 // authenticated
511 //
512 // |--------------------------------------|
513 // encrypted (aes)
514 pub fn unprotect_rtcp(&mut self, buf: &[u8]) -> Option<Vec<u8>> {
515 match &mut self.rtcp {
516 Derived::Aes128CmSha1_80 { key, salt, dec, .. } => {
517 if buf.len() < SRTCP_HEADER_LEN + SRTCP_INDEX_LEN + Aes128CmSha1_80::HMAC_TAG_LEN {
518 return None;
519 }
520 
521 let hmac_start = buf.len() - Aes128CmSha1_80::HMAC_TAG_LEN;
522 
523 let sha1_hmac = |k: &[u8], p: &[&[u8]]| self.sha1_hmac_provider.sha1_hmac(k, p);
524 if !Aes128CmSha1_80::rtcp_verify(
525 sha1_hmac,
526 key,
527 &buf[..hmac_start],
528 &buf[hmac_start..],
529 ) {
530 trace!("unprotect_rtcp hmac verify fail");
531 return None;
532 }
533 
534 let idx_start = hmac_start - SRTCP_INDEX_LEN;
535 
536 let srtcp_index_be = [
537 buf[idx_start],
538 buf[idx_start + 1],
539 buf[idx_start + 2],
540 buf[idx_start + 3],
541 ];
542 
543 // E-flag and SRTCP index.
544 let e_and_si = u32::from_be_bytes(srtcp_index_be);
545 
546 let is_encrypted = e_and_si & 0x8000_0000 > 0;
547 
548 if !is_encrypted {
549 // Non-encrypted we can just return
550 return Some(buf[0..idx_start].to_vec());
551 }
552 
553 // The SRTCP index is a 31-bit counter for the SRTCP packet.
554 let srtcp_index = e_and_si & 0x7fff_ffff;
555 let ssrc = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
556 
557 let iv = Aes128CmSha1_80::rtp_iv(*salt, ssrc, srtcp_index as u64);
558 
559 // The Encrypted Portion of an SRTCP packet consists of the encryption
560 // of the RTCP payload of the equivalent compound RTCP packet, from the
561 // first RTCP packet, i.e., from the ninth (9) octet to the end of the
562 // compound packet.
563 let input = &buf[8..idx_start];
564 // Allocate buffer with CTR padding (aws-lc-rs requirement)
565 let mut output = vec![0_u8; input.len() + 8 + CTR_BUFFER_PADDING];
566 output[0..8].copy_from_slice(&buf[0..8]);
567 
568 if let Err(e) = dec.decrypt(&iv, input, &mut output[8..]) {
569 warn!("Failed to decrypt SRTCP {}: {}", self.rtcp.profile(), e);
570 return None;
571 }
572 
573 output.truncate(input.len() + 8);
574 Some(output)
575 }
576 Derived::AeadAes128Gcm { salt, dec, .. } => {
577 if buf.len() < SRTCP_HEADER_LEN + SRTCP_INDEX_LEN + AeadAes128Gcm::TAG_LEN {
578 // Too short
579 return None;
580 }
581 
582 let idx_start = buf.len() - SRTCP_INDEX_LEN;
583 
584 // Assume no MKI
585 let e_and_si = u32::from_be_bytes(
586 buf[idx_start..buf.len()]
587 .try_into()
588 // This is ok because SRTCP_INDEX_LEN is 4 bytes and the buffer is at least
589 // that long.
590 .expect("SRTCP_INDEX_LEN to be 4"),
591 );
592 let is_encrypted = e_and_si & 0x8000_0000 > 0;
593 
594 // The Encrypted Portion of an SRTCP packet consists of the encryption
595 // of the RTCP payload of the equivalent compound RTCP packet, from the
596 // first RTCP packet, i.e., from the ninth (9) octet to the end of the
597 // compound packet.
598 let input = if is_encrypted {
599 &buf[8..idx_start]
600 } else {
601 // No, encryption but we still pass the tag down to decrypt so it can verify
602 // it.
603 &buf[idx_start - AeadAes128Gcm::TAG_LEN..idx_start]
604 };
605 
606 // The SRTCP index is a 31-bit counter for the SRTCP packet.
607 let srtcp_index = e_and_si & 0x7fff_ffff;
608 let ssrc = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
609 
610 let iv = AeadAes128Gcm::rtcp_iv(*salt, ssrc, srtcp_index);
611 // Declared out here for lifetime purposes, only used in the first branch of the if.
612 let mut encrypted_aad = [0; AeadAes128Gcm::RTCP_AAD_LEN];
613 let mut aads: [&[u8]; 2] = [&[], &[]];
614 
615 if is_encrypted {
616 encrypted_aad[0..8].copy_from_slice(&buf[0..8]);
617 encrypted_aad[8..12].copy_from_slice(&e_and_si.to_be_bytes());
618 
619 aads[0] = encrypted_aad.as_slice();
620 } else {
621 // The whole packet is AAD
622 aads[0] = &buf[0..idx_start - AeadAes128Gcm::TAG_LEN];
623 aads[1] = &buf[idx_start..];
624 };
625 
626 let mut output = vec![0_u8; buf.len() - AeadAes128Gcm::TAG_LEN - SRTCP_INDEX_LEN];
627 output[0..8].copy_from_slice(&buf[0..8]);
628 
629 let count = match dec.decrypt(&iv, &aads, input, &mut output[8..]) {
630 Ok(c) => c,
631 Err(e) => {
632 warn!("Failed to decrypt SRTCP {}: {}", self.rtcp.profile(), e);
633 return None;
634 }
635 };
636 
637 if is_encrypted {
638 output.truncate(8 + count);
639 } else {
640 // decrypt didn't error, the data is authenticated.
641 output.copy_from_slice(
642 &buf[0..buf.len() - SRTCP_INDEX_LEN - AeadAes128Gcm::TAG_LEN],
643 )
644 }
645 
646 Some(output)
647 }
648 Derived::AeadAes256Gcm { salt, dec, .. } => {
649 if buf.len() < SRTCP_HEADER_LEN + SRTCP_INDEX_LEN + AeadAes256Gcm::TAG_LEN {
650 // Too short
651 return None;
652 }
653 
654 let idx_start = buf.len() - SRTCP_INDEX_LEN;
655 
656 // Assume no MKI
657 let e_and_si = u32::from_be_bytes(
658 buf[idx_start..buf.len()]
659 .try_into()
660 // This is ok because SRTCP_INDEX_LEN is 4 bytes and the buffer is at least
661 // that long.
662 .expect("SRTCP_INDEX_LEN to be 4"),
663 );
664 let is_encrypted = e_and_si & 0x8000_0000 > 0;
665 
666 // The Encrypted Portion of an SRTCP packet consists of the encryption
667 // of the RTCP payload of the equivalent compound RTCP packet, from the
668 // first RTCP packet, i.e., from the ninth (9) octet to the end of the
669 // compound packet.
670 let input = if is_encrypted {
671 &buf[8..idx_start]
672 } else {
673 // No, encryption but we still pass the tag down to decrypt so it can verify
674 // it.
675 &buf[idx_start - AeadAes256Gcm::TAG_LEN..idx_start]
676 };
677 
678 // The SRTCP index is a 31-bit counter for the SRTCP packet.
679 let srtcp_index = e_and_si & 0x7fff_ffff;
680 let ssrc = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
681 
682 let iv = AeadAes256Gcm::rtcp_iv(*salt, ssrc, srtcp_index);
683 // Declared out here for lifetime purposes, only used in the first branch of the if.
684 let mut encrypted_aad = [0; AeadAes256Gcm::RTCP_AAD_LEN];
685 let mut aads: [&[u8]; 2] = [&[], &[]];
686 
687 if is_encrypted {
688 encrypted_aad[0..8].copy_from_slice(&buf[0..8]);
689 encrypted_aad[8..12].copy_from_slice(&e_and_si.to_be_bytes());
690 
691 aads[0] = encrypted_aad.as_slice();
692 } else {
693 // The whole packet is AAD
694 aads[0] = &buf[0..idx_start - AeadAes256Gcm::TAG_LEN];
695 aads[1] = &buf[idx_start..];
696 };
697 
698 let mut output = vec![0_u8; buf.len() - AeadAes256Gcm::TAG_LEN - SRTCP_INDEX_LEN];
699 output[0..8].copy_from_slice(&buf[0..8]);
700 
701 let count = match dec.decrypt(&iv, &aads, input, &mut output[8..]) {
702 Ok(c) => c,
703 Err(e) => {
704 warn!("Failed to decrypt SRTCP {}: {}", self.rtcp.profile(), e);
705 return None;
706 }
707 };
708 
709 if is_encrypted {
710 output.truncate(8 + count);
711 } else {
712 // decrypt didn't error, the data is authenticated.
713 output.copy_from_slice(
714 &buf[0..buf.len() - SRTCP_INDEX_LEN - AeadAes256Gcm::TAG_LEN],
715 )
716 }
717 
718 Some(output)
719 }
720 }
721 }
722}
723 
724/// SrtpKeys created from DTLS SrtpKeyMaterial.
725#[derive(Debug)]
726struct SrtpKey<const ML: usize, const SL: usize> {
727 master: [u8; ML],
728 salt: [u8; SL],
729}
730 
731impl<const ML: usize, const SL: usize> SrtpKey<ML, SL> {
732 pub fn new(mat: &KeyingMaterial, left: bool) -> Self {
733 // layout in SrtpKeyMaterial is [key_input, key_output, salt_input, salt_output]
734 
735 // Invariant
736 assert!(
737 mat.len() == ML * 2 + SL * 2,
738 "The KeyingMaterial provided to SrtpKey::new must be ML * 2 + SL * 2 in length"
739 );
740 
741 // offset 0, offset 1
742 let (o0, o1) = if left { (0, 0) } else { (ML, SL) };
743 
744 let mut master = [0; ML];
745 let mut salt = [0; SL];
746 
747 master[0..ML].copy_from_slice(&mat[o0..(o0 + ML)]);
748 salt[0..SL].copy_from_slice(&mat[(ML + ML + o1)..(ML + ML + o1 + SL)]);
749 
750 SrtpKey { master, salt }
751 }
752 
753 fn derive(&self, crypto: &dyn SrtpProvider, label: u8, out: &mut [u8]) {
754 // AES-CM (128 or 256 bits) defined in RFC3711
755 assert!(ML == 16 || ML == 32, "Only valid for 128 bit master keys");
756 assert!(SL <= 14, "Only valid for 128 bit master keys");
757 let mut i = 0; // index in out
758 
759 // input layout: [salt[SL] || label, round[2]] (|| is xor 7th byte)
760 let mut input = [0; 16];
761 
762 input[0..SL].copy_from_slice(&self.salt[..]);
763 input[7] ^= label;
764 
765 let mut buf = [0; 16 + 16]; // output from each AES
766 let mut round: u16 = 0; // counter for each AES round
767 
768 // loop each AES round
769 loop {
770 if i == out.len() {
771 break;
772 }
773 
774 // splice in round at bottom of input
775 input[14..].copy_from_slice(&round.to_be_bytes()[..]);
776 
777 // default key derivation function, which uses AES-128 in Counter Mode
778 match ML {
779 16 => crypto.srtp_aes_128_ecb_round(&self.master, &input[..], &mut buf[..]),
780 32 => crypto.srtp_aes_256_ecb_round(&self.master, &input[..], &mut buf[..]),
781 _ => panic!("Only valid for 128 or 256 bit master keys"),
782 }
783 
784 // Copy to output. Even if we get 32 bytes of output with AES 128 ECB, we
785 // only use the first 16. That matches the tests in the RFC.
786 for j in buf.iter().take(16) {
787 if i == out.len() {
788 break;
789 }
790 out[i] = *j;
791 i += 1;
792 }
793 
794 round += 1;
795 }
796 }
797}
798 
799/// Encryption/decryption derived from the SrtpKey.
800enum Derived {
801 Aes128CmSha1_80 {
802 key: [u8; 20],
803 salt: [u8; 14],
804 enc: Box<dyn Aes128CmSha1_80Cipher>,
805 dec: Box<dyn Aes128CmSha1_80Cipher>,
806 },
807 AeadAes128Gcm {
808 salt: [u8; 12],
809 enc: Box<dyn AeadAes128GcmCipher>,
810 dec: Box<dyn AeadAes128GcmCipher>,
811 },
812 AeadAes256Gcm {
813 salt: [u8; 12],
814 enc: Box<dyn AeadAes256GcmCipher>,
815 dec: Box<dyn AeadAes256GcmCipher>,
816 },
817}
818 
819impl Derived {
820 fn aes_128_cm_sha1_80(
821 crypto: &dyn SrtpProvider,
822 srtp_key: &SrtpKey<{ Aes128CmSha1_80::KEY_LEN }, { Aes128CmSha1_80::SALT_LEN }>,
823 ) -> (Self, Self) {
824 // RTP AES Counter
825 let mut rtp_aes = [0; Aes128CmSha1_80::KEY_LEN];
826 srtp_key.derive(crypto, LABEL_RTP_AES, &mut rtp_aes[..]);
827 
828 // RTP SHA1 HMAC
829 let rtp_hmac = {
830 let mut hmac = [0; Aes128CmSha1_80::HMAC_KEY_LEN];
831 srtp_key.derive(crypto, LABEL_RTP_AUTHENTICATION_KEY, &mut hmac[..]);
832 hmac
833 };
834 
835 // RTP IV SALT
836 let mut rtp_salt = [0; Aes128CmSha1_80::SALT_LEN];
837 srtp_key.derive(crypto, LABEL_RTP_SALT, &mut rtp_salt[..]);
838 
839 // RTCP AES Counter
840 let mut rtcp_aes = [0; Aes128CmSha1_80::KEY_LEN];
841 srtp_key.derive(crypto, LABEL_RTCP_AES, &mut rtcp_aes[..]);
842 
843 // RTCP SHA1 HMAC
844 let rtcp_hmac = {
845 let mut hmac = [0; Aes128CmSha1_80::HMAC_KEY_LEN];
846 srtp_key.derive(crypto, LABEL_RTCP_AUTHENTICATION_KEY, &mut hmac[..]);
847 hmac
848 };
849 
850 // RTCP IV SALT
851 let mut rtcp_salt = [0; Aes128CmSha1_80::SALT_LEN];
852 srtp_key.derive(crypto, LABEL_RTCP_SALT, &mut rtcp_salt[..]);
853 
854 let rtp = Derived::Aes128CmSha1_80 {
855 key: rtp_hmac,
856 salt: rtp_salt,
857 enc: crypto.aes_128_cm_sha1_80().create_cipher(rtp_aes, true),
858 dec: crypto.aes_128_cm_sha1_80().create_cipher(rtp_aes, false),
859 };
860 
861 let rtcp = Derived::Aes128CmSha1_80 {
862 key: rtcp_hmac,
863 salt: rtcp_salt,
864 enc: crypto.aes_128_cm_sha1_80().create_cipher(rtcp_aes, true),
865 dec: crypto.aes_128_cm_sha1_80().create_cipher(rtcp_aes, false),
866 };
867 
868 (rtp, rtcp)
869 }
870 
871 fn aead_aes_128_gcm(
872 crypto: &dyn SrtpProvider,
873 srtp_key: &SrtpKey<{ AeadAes128Gcm::KEY_LEN }, { AeadAes128Gcm::SALT_LEN }>,
874 ) -> (Derived, Derived) {
875 // RTP session key
876 let mut rtp_aes = [0; AeadAes128Gcm::KEY_LEN];
877 srtp_key.derive(crypto, LABEL_RTP_AES, &mut rtp_aes[..]);
878 
879 // RTP session salt
880 let mut rtp_salt = [0; AeadAes128Gcm::SALT_LEN];
881 srtp_key.derive(crypto, LABEL_RTP_SALT, &mut rtp_salt[..]);
882 
883 // RTCP session key
884 let mut rtcp_aes = [0; AeadAes128Gcm::KEY_LEN];
885 srtp_key.derive(crypto, LABEL_RTCP_AES, &mut rtcp_aes[..]);
886 
887 // RTCP session salt
888 let mut rtcp_salt = [0; AeadAes128Gcm::SALT_LEN];
889 srtp_key.derive(crypto, LABEL_RTCP_SALT, &mut rtcp_salt[..]);
890 
891 let rtp = Derived::AeadAes128Gcm {
892 salt: rtp_salt,
893 enc: crypto.aead_aes_128_gcm().create_cipher(rtp_aes, true),
894 dec: crypto.aead_aes_128_gcm().create_cipher(rtp_aes, false),
895 };
896 
897 let rtcp = Derived::AeadAes128Gcm {
898 salt: rtcp_salt,
899 enc: crypto.aead_aes_128_gcm().create_cipher(rtcp_aes, true),
900 dec: crypto.aead_aes_128_gcm().create_cipher(rtcp_aes, false),
901 };
902 
903 (rtp, rtcp)
904 }
905 
906 fn aead_aes_256_gcm(
907 crypto: &dyn SrtpProvider,
908 srtp_key: &SrtpKey<{ AeadAes256Gcm::KEY_LEN }, { AeadAes256Gcm::SALT_LEN }>,
909 ) -> (Derived, Derived) {
910 // RTP session key
911 let mut rtp_aes = [0; AeadAes256Gcm::KEY_LEN];
912 srtp_key.derive(crypto, LABEL_RTP_AES, &mut rtp_aes[..]);
913 
914 // RTP session salt
915 let mut rtp_salt = [0; AeadAes256Gcm::SALT_LEN];
916 srtp_key.derive(crypto, LABEL_RTP_SALT, &mut rtp_salt[..]);
917 
918 // RTCP session key
919 let mut rtcp_aes = [0; AeadAes256Gcm::KEY_LEN];
920 srtp_key.derive(crypto, LABEL_RTCP_AES, &mut rtcp_aes[..]);
921 
922 // RTCP session salt
923 let mut rtcp_salt = [0; AeadAes256Gcm::SALT_LEN];
924 srtp_key.derive(crypto, LABEL_RTCP_SALT, &mut rtcp_salt[..]);
925 
926 let rtp = Derived::AeadAes256Gcm {
927 salt: rtp_salt,
928 enc: crypto.aead_aes_256_gcm().create_cipher(rtp_aes, true),
929 dec: crypto.aead_aes_256_gcm().create_cipher(rtp_aes, false),
930 };
931 
932 let rtcp = Derived::AeadAes256Gcm {
933 salt: rtcp_salt,
934 enc: crypto.aead_aes_256_gcm().create_cipher(rtcp_aes, true),
935 dec: crypto.aead_aes_256_gcm().create_cipher(rtcp_aes, false),
936 };
937 
938 (rtp, rtcp)
939 }
940 
941 fn profile(&self) -> SrtpProfile {
942 match self {
943 Derived::Aes128CmSha1_80 { .. } => SrtpProfile::AES128_CM_SHA1_80,
944 Derived::AeadAes128Gcm { .. } => SrtpProfile::AEAD_AES_128_GCM,
945 Derived::AeadAes256Gcm { .. } => SrtpProfile::AEAD_AES_256_GCM,
946 }
947 }
948}
949 
950impl fmt::Debug for Derived {
951 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
952 write!(f, "Derived")
953 }
954}
955 
956fn error_details(header: &RtpHeader, srtp_index: u64) -> String {
957 format!(
958 "SSRC: {} seq_no: {} pt: {} mid: {:?} rid: {:?} rid_repair: {:?} srtp_index: {}",
959 header.ssrc,
960 header.sequence_number,
961 header.payload_type,
962 header.ext_vals.mid,
963 header.ext_vals.rid,
964 header.ext_vals.rid_repair,
965 srtp_index
966 )
967}
968 
969#[cfg(test)]
970mod test {
971 use super::*;
972 
973 #[test]
974 fn derive_key() {
975 crate::init_crypto_default();
976 let provider = crate::crypto::from_feature_flags();
977 let crypto = provider.srtp_provider;
978 
979 // https://tools.ietf.org/html/rfc3711#appendix-B.3
980 //
981 // Key Derivation Test Vectors.
982 
983 let master = [
984 0xE1, 0xF9, 0x7A, 0x0D, 0x3E, 0x01, 0x8B, 0xE0, //
985 0xD6, 0x4F, 0xA3, 0x2C, 0x06, 0xDE, 0x41, 0x39,
986 ];
987 
988 let salt = [
989 0x0E, 0xC6, 0x75, 0xAD, 0x49, 0x8A, 0xFE, //
990 0xEB, 0xB6, 0x96, 0x0B, 0x3A, 0xAB, 0xE6,
991 ];
992 
993 let sk = SrtpKey { master, salt };
994 
995 // aes crypto key
996 let mut out = [0_u8; 16];
997 sk.derive(crypto, 0, &mut out[..]);
998 
999 assert_eq!(
1000 out,
1001 [
1002 0xC6, 0x1E, 0x7A, 0x93, 0x74, 0x4F, 0x39, 0xEE, //
1003 0x10, 0x73, 0x4A, 0xFE, 0x3F, 0xF7, 0xA0, 0x87
1004 ]
1005 );
1006 
1007 // hmac
1008 let mut out = [0_u8; 20];
1009 sk.derive(crypto, 1, &mut out[..]);
1010 
1011 assert_eq!(
1012 out,
1013 [
1014 0xCE, 0xBE, 0x32, 0x1F, 0x6F, 0xF7, 0x71, 0x6B, //
1015 0x6F, 0xD4, 0xAB, 0x49, 0xAF, 0x25, 0x6A, 0x15, //
1016 0x6D, 0x38, 0xBA, 0xA4
1017 ]
1018 );
1019 
1020 // salt
1021 let mut out = [0_u8; 14];
1022 sk.derive(crypto, 2, &mut out[..]);
1023 
1024 assert_eq!(
1025 out,
1026 [
1027 0x30, 0xCB, 0xBC, 0x08, 0x86, 0x3D, 0x8C, //
1028 0x85, 0xD4, 0x9D, 0xB3, 0x4A, 0x9A, 0xE1
1029 ]
1030 );
1031 }
1032 
1033 mod test_aes128_cm_sha1_80 {
1034 use super::*;
1035 
1036 const MAT: [u8; 60] = [
1037 0x2C, 0xB0, 0x23, 0x46, 0xB4, 0x22, 0x76, 0xA6, 0x72, 0xCF, 0xD1, 0x43, 0xAE, 0xC2,
1038 0xD5, 0xEE, 0xDD, 0xDE, 0x55, 0xF0, 0xAD, 0x7B, 0xCA, 0xC2, 0x26, 0x66, 0xF1, 0xC6,
1039 0x38, 0x61, 0x73, 0xED, 0x6E, 0xB2, 0x5C, 0xB7, 0xD2, 0x6A, 0x61, 0xA1, 0xEE, 0x2C,
1040 0x21, 0x0A, 0xDA, 0xE7, 0x60, 0xAA, 0xA2, 0xFD, 0x67, 0xB6, 0x72, 0xC4, 0x1A, 0xED,
1041 0x10, 0x5F, 0x9D, 0x36,
1042 ];
1043 
1044 const SRTCP: &[u8] = &[
1045 // header
1046 0x80, 0xC8, 0x00, 0x06, //
1047 // ssrc
1048 0x3C, 0xD7, 0xCC, 0x13, //
1049 // encrypted payload
1050 0xB7, 0xC8, 0x31, 0xDC, 0xB7, 0x76, 0xCD, 0x8D, 0xC2, 0x6F, 0xDA, 0x1D, 0x9B, 0xFC,
1051 0x8E, 0xE6, 0x58, 0x9A, 0x1A, 0x8A, 0x49, 0x28, 0x9C, 0xAE, 0xB2, 0x64, 0x20, 0x0C,
1052 0x37, 0xD2, 0xD0, 0xA4, 0xAF, 0xAC, 0x63, 0x85, 0xFF, 0xC6, 0x0D, 0xEC, 0x7D, 0x06,
1053 0xD4, 0x87, 0x3D, 0xD3, 0xA8, 0xCC, //
1054 // E flag and srtcp index (1)
1055 0x80, 0x00, 0x00, 0x01, //
1056 // hmac
1057 0xB7, 0xBB, 0x52, 0x65, 0x21, 0xD1, 0xE7, 0x3C, 0x0F, 0xC0,
1058 ];
1059 
1060 const DECRYPTED_PAYLOAD: &[u8] = &[
1061 0x80, 0xc8, 0x00, 0x06, 0x3c, 0xd7, 0xcc, 0x13, 0xe2, 0xee, 0x35, 0xc8, 0x60, 0x4e,
1062 0x61, 0x8c, 0x26, 0xf3, 0x27, 0x34, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x14, 0x07,
1063 0x81, 0xca, 0x00, 0x06, 0x3c, 0xd7, 0xcc, 0x13, 0x01, 0x10, 0x38, 0x6e, 0x46, 0x75,
1064 0x32, 0x68, 0x57, 0x66, 0x72, 0x4d, 0x44, 0x72, 0x47, 0x66, 0x34, 0x6f, 0x00, 0x00,
1065 ];
1066 
1067 #[test]
1068 fn unprotect_rtcp() {
1069 let key_mat = KeyingMaterial::new(&MAT);
1070 let crypto = crate::crypto::test_default_provider();
1071 let mut ctx_rx =
1072 SrtpContext::new(crypto, SrtpProfile::AES128_CM_SHA1_80, &key_mat, true);
1073 ctx_rx.srtcp_index = 1;
1074 
1075 let decrypted = ctx_rx.unprotect_rtcp(SRTCP).unwrap();
1076 
1077 assert_eq!(ctx_rx.srtcp_index, 1);
1078 // check srtcp_index in incoming was indeed 1
1079 let srtcp_index = SRTCP.len() - Aes128CmSha1_80::HMAC_TAG_LEN - SRTCP_INDEX_LEN;
1080 let e_and_i = &SRTCP[srtcp_index..(srtcp_index + 4)];
1081 assert_eq!(e_and_i, &0x8000_0001_u32.to_be_bytes());
1082 assert_eq!(decrypted, DECRYPTED_PAYLOAD);
1083 
1084 // Take us back to where we started.
1085 let encrypted = ctx_rx.protect_rtcp(&decrypted);
1086 assert_eq!(encrypted, SRTCP);
1087 }
1088 }
1089 
1090 mod test_aead_aes_128_gcm {
1091 use crate::crypto::AeadAes128Gcm;
1092 use crate::rtp_::ExtensionMap;
1093 
1094 use super::*;
1095 
1096 const TAG_LEN: usize = AeadAes128Gcm::TAG_LEN;
1097 
1098 mod rfc7714 {
1099 // Test vectors from RFC7714
1100 
1101 // Session Key (RTP and RTCP)
1102 pub(super) const KEY: [u8; 16] = [
1103 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, //
1104 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1105 ];
1106 
1107 // Session Salt (RTP and RTCP)
1108 pub(super) const SALT: [u8; 12] = [
1109 0x51, 0x75, 0x69, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x20, 0x71, 0x75, 0x6f,
1110 ];
1111 
1112 /// Full plaintext RTP packet. First 12 octets is the header
1113 pub(super) const PLAINTEXT_RTP_PACKET: &[u8] = &[
1114 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, 0x55, 0x01, 0xa0, 0xb2, 0x47, 0x61,
1115 0x6c, 0x6c, 0x69, 0x61, 0x20, 0x65, 0x73, 0x74, 0x20, 0x6f, 0x6d, 0x6e, 0x69, 0x73,
1116 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x72,
1117 0x74, 0x65, 0x73, 0x20, 0x74, 0x72, 0x65, 0x73,
1118 ];
1119 
1120 /// Full encrypted RTP packet. First 12 octets is the header.
1121 pub(super) const PROTECTED_RTP_PACKET: &[u8] = &[
1122 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, 0x55, 0x01, 0xa0, 0xb2, 0xf2, 0x4d,
1123 0xe3, 0xa3, 0xfb, 0x34, 0xde, 0x6c, 0xac, 0xba, 0x86, 0x1c, 0x9d, 0x7e, 0x4b, 0xca,
1124 0xbe, 0x63, 0x3b, 0xd5, 0x0d, 0x29, 0x4e, 0x6f, 0x42, 0xa5, 0xf4, 0x7a, 0x51, 0xc7,
1125 0xd1, 0x9b, 0x36, 0xde, 0x3a, 0xdf, 0x88, 0x33, 0x89, 0x9d, 0x7f, 0x27, 0xbe, 0xb1,
1126 0x6a, 0x91, 0x52, 0xcf, 0x76, 0x5e, 0xe4, 0x39, 0x0c, 0xce,
1127 ];
1128 
1129 // Full plaintext RTCP packet
1130 pub(super) const PLAINTEXT_RTCP_PACKET: &[u8] = &[
1131 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, 0x4e, 0x54, 0x50, 0x31, 0x4e, 0x54,
1132 0x50, 0x32, 0x52, 0x54, 0x50, 0x20, 0x00, 0x00, 0x04, 0x2a, 0x00, 0x00, 0xe9, 0x30,
1133 0x4c, 0x75, 0x6e, 0x61, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
1134 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
1135 ];
1136 
1137 /// Full encrypted RTCP packet
1138 pub(super) const PROTECTED_RTCP_PACKET: &[u8] = &[
1139 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, 0x63, 0xe9, 0x48, 0x85, 0xdc, 0xda,
1140 0xb6, 0x7c, 0xa7, 0x27, 0xd7, 0x66, 0x2f, 0x6b, 0x7e, 0x99, 0x7f, 0xf5, 0xc0, 0xf7,
1141 0x6c, 0x06, 0xf3, 0x2d, 0xc6, 0x76, 0xa5, 0xf1, 0x73, 0x0d, 0x6f, 0xda, 0x4c, 0xe0,
1142 0x9b, 0x46, 0x86, 0x30, 0x3d, 0xed, 0x0b, 0xb9, 0x27, 0x5b, 0xc8, 0x4a, 0xa4, 0x58,
1143 0x96, 0xcf, 0x4d, 0x2f, 0xc5, 0xab, 0xf8, 0x72, 0x45, 0xd9, 0xea, 0xde, 0x80, 0x00,
1144 0x05, 0xd4,
1145 ];
1146 
1147 // A RTCP packet that hasn't been encrypted, only authenticated.
1148 pub(super) const TAGGED_RTCP_PACKET: &[u8] = &[
1149 // RTCP Packet
1150 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, 0x4e, 0x54, 0x50, 0x31, 0x4e, 0x54,
1151 0x50, 0x32, 0x52, 0x54, 0x50, 0x20, 0x00, 0x00, 0x04, 0x2a, 0x00, 0x00, 0xe9, 0x30,
1152 0x4c, 0x75, 0x6e, 0x61, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
1153 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, //
1154 // Tag
1155 0x84, 0x1d, 0xd9, 0x68, 0x3d, 0xd7, 0x8e, 0xc9, 0x2a, 0xe5, 0x87, 0x90, 0x12, 0x5f,
1156 0x62, 0xb3, //
1157 // SRTCP Index
1158 0x00, 0x00, 0x05, 0xd4,
1159 ];
1160 }
1161 
1162 #[test]
1163 fn protect_rtp_rfc_7714_test() {
1164 let mut context = make_rtp_context();
1165 
1166 let header =
1167 RtpHeader::parse(&rfc7714::PLAINTEXT_RTP_PACKET[..12], &ExtensionMap::empty())
1168 .expect("header to parse");
1169 let out = context.protect_rtp(rfc7714::PLAINTEXT_RTP_PACKET, &header, 0);
1170 
1171 assert_eq!(
1172 out,
1173 rfc7714::PROTECTED_RTP_PACKET,
1174 "failed to encrypted packet.\n{:02x?}\n{:02x?}",
1175 out,
1176 &rfc7714::PLAINTEXT_RTP_PACKET
1177 );
1178 }
1179 
1180 #[test]
1181 fn unprotect_rtp_rfc_7714_test() {
1182 let mut context = make_rtp_context();
1183 let header =
1184 RtpHeader::parse(&rfc7714::PROTECTED_RTP_PACKET[..12], &ExtensionMap::empty())
1185 .expect("header to parse");
1186 
1187 let out = context
1188 .unprotect_rtp(rfc7714::PROTECTED_RTP_PACKET, &header, 0)
1189 .expect("decrypt rtp");
1190 
1191 assert_eq!(
1192 out,
1193 &rfc7714::PLAINTEXT_RTP_PACKET[12..],
1194 "failed to decrypt packet.\n{:02x?}\n{:02x?}",
1195 out,
1196 &rfc7714::PLAINTEXT_RTP_PACKET
1197 );
1198 }
1199 
1200 #[test]
1201 fn symmetry_rtp_rfc_7714_test() {
1202 let mut context = make_rtp_context();
1203 
1204 // First we encrypt
1205 let header =
1206 RtpHeader::parse(&rfc7714::PLAINTEXT_RTP_PACKET[..12], &ExtensionMap::empty())
1207 .expect("header to parse");
1208 let encrypted = context.protect_rtp(rfc7714::PLAINTEXT_RTP_PACKET, &header, 0);
1209 
1210 // Then we decrypt the resulting cipher text
1211 let header = RtpHeader::parse(&encrypted[..12], &ExtensionMap::empty())
1212 .expect("header to parse");
1213 let decrypted = context
1214 .unprotect_rtp(&encrypted, &header, 0)
1215 .expect("rtp unprotect");
1216 
1217 // And verify we get the input back.
1218 assert_eq!(decrypted, &rfc7714::PLAINTEXT_RTP_PACKET[12..]);
1219 }
1220 
1221 #[test]
1222 fn unprotect_rtp_should_fail_with_broken_tag_data() {
1223 let mut context = make_rtp_context();
1224 
1225 let header_buf = {
1226 let mut buf = rfc7714::PROTECTED_RTP_PACKET[..12].to_vec();
1227 // Mess with part of the sequence number, since this makes up part of the
1228 // authenticated additional data(AAD) the resulting authenticity tag should not
1229 // match.
1230 buf[3] ^= 0xFF;
1231 
1232 buf
1233 };
1234 
1235 let header =
1236 RtpHeader::parse(&header_buf, &ExtensionMap::empty()).expect("header to parse");
1237 
1238 let result = context.unprotect_rtp(rfc7714::PROTECTED_RTP_PACKET, &header, 0);
1239 assert!(
1240 result.is_none(),
1241 "Should fail to decrypt a SRTP packet that has mismatched \
1242 authenicated additional data"
1243 );
1244 }
1245 
1246 #[test]
1247 fn unprotect_rtp_should_fail_with_broken_null_tag() {
1248 let mut context = make_rtp_context();
1249 
1250 let input = {
1251 let mut input = rfc7714::PROTECTED_RTP_PACKET.to_vec();
1252 let len = input.len();
1253 input[len - TAG_LEN..].copy_from_slice(&[0; TAG_LEN]);
1254 
1255 input
1256 };
1257 
1258 let header =
1259 RtpHeader::parse(&input[..12], &ExtensionMap::empty()).expect("header to parse");
1260 
1261 let result = context.unprotect_rtp(&input, &header, 0);
1262 assert!(
1263 result.is_none(),
1264 "Should fail to decrypt a SRTP packet with null tag"
1265 );
1266 }
1267 
1268 #[test]
1269 fn protect_rtcp_rfc_7714_test() {
1270 let mut context = make_rtcp_context();
1271 
1272 let out = context.protect_rtcp(rfc7714::PLAINTEXT_RTCP_PACKET);
1273 
1274 assert!(
1275 out == rfc7714::PROTECTED_RTCP_PACKET,
1276 "Expected encrypted and tagged RTCP packet:\n{:02x?}\nGot:\n{:02x?}",
1277 rfc7714::PROTECTED_RTCP_PACKET,
1278 out
1279 );
1280 }
1281 
1282 #[test]
1283 fn unprotect_rtcp_rfc_auth_only_7714_test() {
1284 let mut context = make_rtcp_context();
1285 
1286 let out = context
1287 .unprotect_rtcp(rfc7714::TAGGED_RTCP_PACKET)
1288 .expect("Unprotect RTCP");
1289 
1290 assert_eq!(out, rfc7714::PLAINTEXT_RTCP_PACKET);
1291 }
1292 
1293 fn make_rtp_context() -> SrtpContext {
1294 crate::init_crypto_default();
1295 SrtpContext::new_aead_aes_128_gcm(
1296 rfc7714::KEY,
1297 rfc7714::SALT,
1298 rfc7714::KEY,
1299 rfc7714::SALT,
1300 0,
1301 )
1302 }
1303 
1304 fn make_rtcp_context() -> SrtpContext {
1305 crate::init_crypto_default();
1306 SrtpContext::new_aead_aes_128_gcm(
1307 rfc7714::KEY,
1308 rfc7714::SALT,
1309 rfc7714::KEY,
1310 rfc7714::SALT,
1311 0x000005d4,
1312 )
1313 }
1314 }
1315 
1316 mod test_aead_aes_256_gcm {
1317 use crate::crypto::AeadAes256Gcm;
1318 use crate::rtp_::ExtensionMap;
1319 
1320 use super::*;
1321 
1322 const TAG_LEN: usize = AeadAes256Gcm::TAG_LEN;
1323 
1324 mod rfc7714 {
1325 // Test vectors from RFC7714
1326 
1327 // Session Key (RTP and RTCP)
1328 pub(super) const KEY: [u8; 32] = [
1329 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, //
1330 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
1331 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, //
1332 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1333 ];
1334 
1335 // Session Salt (RTP and RTCP)
1336 pub(super) const SALT: [u8; 12] = [
1337 0x51, 0x75, 0x69, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x20, 0x71, 0x75, 0x6f,
1338 ];
1339 
1340 /// Full plaintext RTP packet. First 12 octets is the header
1341 pub(super) const PLAINTEXT_RTP_PACKET: &[u8] = &[
1342 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, 0x55, 0x01, 0xa0, 0xb2, 0x47, 0x61,
1343 0x6c, 0x6c, 0x69, 0x61, 0x20, 0x65, 0x73, 0x74, 0x20, 0x6f, 0x6d, 0x6e, 0x69, 0x73,
1344 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x72,
1345 0x74, 0x65, 0x73, 0x20, 0x74, 0x72, 0x65, 0x73,
1346 ];
1347 
1348 /// Full encrypted RTP packet. First 12 octets is the header.
1349 pub(super) const PROTECTED_RTP_PACKET: &[u8] = &[
1350 0x80, 0x40, 0xf1, 0x7b, 0x80, 0x41, 0xf8, 0xd3, 0x55, 0x01, 0xa0, 0xb2, 0x32, 0xb1,
1351 0xde, 0x78, 0xa8, 0x22, 0xfe, 0x12, 0xef, 0x9f, 0x78, 0xfa, 0x33, 0x2e, 0x33, 0xaa,
1352 0xb1, 0x80, 0x12, 0x38, 0x9a, 0x58, 0xe2, 0xf3, 0xb5, 0x0b, 0x2a, 0x02, 0x76, 0xff,
1353 0xae, 0x0f, 0x1b, 0xa6, 0x37, 0x99, 0xb8, 0x7b, 0x7a, 0xa3, 0xdb, 0x36, 0xdf, 0xff,
1354 0xd6, 0xb0, 0xf9, 0xbb, 0x78, 0x78, 0xd7, 0xa7, 0x6c, 0x13,
1355 ];
1356 
1357 // Full plaintext RTCP packet
1358 pub(super) const PLAINTEXT_RTCP_PACKET: &[u8] = &[
1359 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, 0x4e, 0x54, 0x50, 0x31, 0x4e, 0x54,
1360 0x50, 0x32, 0x52, 0x54, 0x50, 0x20, 0x00, 0x00, 0x04, 0x2a, 0x00, 0x00, 0xe9, 0x30,
1361 0x4c, 0x75, 0x6e, 0x61, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
1362 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
1363 ];
1364 
1365 /// Full encrypted RTCP packet
1366 pub(super) const PROTECTED_RTCP_PACKET: &[u8] = &[
1367 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, 0xd5, 0x0a, 0xe4, 0xd1, 0xf5, 0xce,
1368 0x5d, 0x30, 0x4b, 0xa2, 0x97, 0xe4, 0x7d, 0x47, 0x0c, 0x28, 0x2c, 0x3e, 0xce, 0x5d,
1369 0xbf, 0xfe, 0x0a, 0x50, 0xa2, 0xea, 0xa5, 0xc1, 0x11, 0x05, 0x55, 0xbe, 0x84, 0x15,
1370 0xf6, 0x58, 0xc6, 0x1d, 0xe0, 0x47, 0x6f, 0x1b, 0x6f, 0xad, 0x1d, 0x1e, 0xb3, 0x0c,
1371 0x44, 0x46, 0x83, 0x9f, 0x57, 0xff, 0x6f, 0x6c, 0xb2, 0x6a, 0xc3, 0xbe, 0x80, 0x00,
1372 0x05, 0xd4,
1373 ];
1374 
1375 // A RTCP packet that hasn't been encrypted, only authenticated.
1376 pub(super) const TAGGED_RTCP_PACKET: &[u8] = &[
1377 // RTCP Packet
1378 0x81, 0xc8, 0x00, 0x0d, 0x4d, 0x61, 0x72, 0x73, 0x4e, 0x54, 0x50, 0x31, 0x4e, 0x54,
1379 0x50, 0x32, 0x52, 0x54, 0x50, 0x20, 0x00, 0x00, 0x04, 0x2a, 0x00, 0x00, 0xe9, 0x30,
1380 0x4c, 0x75, 0x6e, 0x61, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
1381 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, //
1382 // Tag
1383 0x91, 0xdb, 0x4a, 0xfb, 0xfe, 0xee, 0x5a, 0x97, 0x8f, 0xab, 0x43, 0x93, 0xed, 0x26,
1384 0x15, 0xfe, //
1385 // SRTCP Index
1386 0x00, 0x00, 0x05, 0xd4,
1387 ];
1388 }
1389 
1390 #[test]
1391 fn protect_rtp_rfc_7714_test() {
1392 let mut context = make_rtp_context();
1393 
1394 let header =
1395 RtpHeader::parse(&rfc7714::PLAINTEXT_RTP_PACKET[..12], &ExtensionMap::empty())
1396 .expect("header to parse");
1397 let out = context.protect_rtp(rfc7714::PLAINTEXT_RTP_PACKET, &header, 0);
1398 
1399 assert_eq!(
1400 out,
1401 rfc7714::PROTECTED_RTP_PACKET,
1402 "failed to encrypted packet.\n{:02x?}\n{:02x?}",
1403 out,
1404 &rfc7714::PLAINTEXT_RTP_PACKET
1405 );
1406 }
1407 
1408 #[test]
1409 fn unprotect_rtp_rfc_7714_test() {
1410 let mut context = make_rtp_context();
1411 let header =
1412 RtpHeader::parse(&rfc7714::PROTECTED_RTP_PACKET[..12], &ExtensionMap::empty())
1413 .expect("header to parse");
1414 
1415 let out = context
1416 .unprotect_rtp(rfc7714::PROTECTED_RTP_PACKET, &header, 0)
1417 .expect("decrypt rtp");
1418 
1419 assert_eq!(
1420 out,
1421 &rfc7714::PLAINTEXT_RTP_PACKET[12..],
1422 "failed to decrypt packet.\n{:02x?}\n{:02x?}",
1423 out,
1424 &rfc7714::PLAINTEXT_RTP_PACKET
1425 );
1426 }
1427 
1428 #[test]
1429 fn symmetry_rtp_rfc_7714_test() {
1430 let mut context = make_rtp_context();
1431 
1432 // First we encrypt
1433 let header =
1434 RtpHeader::parse(&rfc7714::PLAINTEXT_RTP_PACKET[..12], &ExtensionMap::empty())
1435 .expect("header to parse");
1436 let encrypted = context.protect_rtp(rfc7714::PLAINTEXT_RTP_PACKET, &header, 0);
1437 
1438 // Then we decrypt the resulting cipher text
1439 let header = RtpHeader::parse(&encrypted[..12], &ExtensionMap::empty())
1440 .expect("header to parse");
1441 let decrypted = context
1442 .unprotect_rtp(&encrypted, &header, 0)
1443 .expect("rtp unprotect");
1444 
1445 // And verify we get the input back.
1446 assert_eq!(decrypted, &rfc7714::PLAINTEXT_RTP_PACKET[12..]);
1447 }
1448 
1449 #[test]
1450 fn unprotect_rtp_should_fail_with_broken_tag_data() {
1451 let mut context = make_rtp_context();
1452 
1453 let header_buf = {
1454 let mut buf = rfc7714::PROTECTED_RTP_PACKET[..12].to_vec();
1455 // Mess with part of the sequence number, since this makes up part of the
1456 // authenticated additional data(AAD) the resulting authenticity tag should not
1457 // match.
1458 buf[3] ^= 0xFF;
1459 
1460 buf
1461 };
1462 
1463 let header =
1464 RtpHeader::parse(&header_buf, &ExtensionMap::empty()).expect("header to parse");
1465 
1466 let result = context.unprotect_rtp(rfc7714::PROTECTED_RTP_PACKET, &header, 0);
1467 assert!(
1468 result.is_none(),
1469 "Should fail to decrypt a SRTP packet that has mismatched \
1470 authenicated additional data"
1471 );
1472 }
1473 
1474 #[test]
1475 fn unprotect_rtp_should_fail_with_broken_null_tag() {
1476 let mut context = make_rtp_context();
1477 
1478 let input = {
1479 let mut input = rfc7714::PROTECTED_RTP_PACKET.to_vec();
1480 let len = input.len();
1481 input[len - TAG_LEN..].copy_from_slice(&[0; TAG_LEN]);
1482 
1483 input
1484 };
1485 
1486 let header =
1487 RtpHeader::parse(&input[..12], &ExtensionMap::empty()).expect("header to parse");
1488 
1489 let result = context.unprotect_rtp(&input, &header, 0);
1490 assert!(
1491 result.is_none(),
1492 "Should fail to decrypt a SRTP packet with null tag"
1493 );
1494 }
1495 
1496 #[test]
1497 fn protect_rtcp_rfc_7714_test() {
1498 let mut context = make_rtcp_context();
1499 
1500 let out = context.protect_rtcp(rfc7714::PLAINTEXT_RTCP_PACKET);
1501 
1502 assert!(
1503 out == rfc7714::PROTECTED_RTCP_PACKET,
1504 "Expected encrypted and tagged RTCP packet:\n{:02x?}\nGot:\n{:02x?}",
1505 rfc7714::PROTECTED_RTCP_PACKET,
1506 out
1507 );
1508 }
1509 
1510 #[test]
1511 fn unprotect_rtcp_rfc_auth_only_7714_test() {
1512 let mut context = make_rtcp_context();
1513 
1514 let out = context
1515 .unprotect_rtcp(rfc7714::TAGGED_RTCP_PACKET)
1516 .expect("Unprotect RTCP");
1517 
1518 assert_eq!(out, rfc7714::PLAINTEXT_RTCP_PACKET);
1519 }
1520 
1521 fn make_rtp_context() -> SrtpContext {
1522 crate::init_crypto_default();
1523 SrtpContext::new_aead_aes_256_gcm(
1524 rfc7714::KEY,
1525 rfc7714::SALT,
1526 rfc7714::KEY,
1527 rfc7714::SALT,
1528 0,
1529 )
1530 }
1531 
1532 fn make_rtcp_context() -> SrtpContext {
1533 crate::init_crypto_default();
1534 SrtpContext::new_aead_aes_256_gcm(
1535 rfc7714::KEY,
1536 rfc7714::SALT,
1537 rfc7714::KEY,
1538 rfc7714::SALT,
1539 0x000005d4,
1540 )
1541 }
1542 }
1543}