Skip to main content

rtc_srtp/context/
srtcp.rs

1use super::*;
2use crate::key_derivation::SRTCP_INDEX_SIZE;
3use shared::{error::Result, marshal::Unmarshal};
4
5use bytes::BytesMut;
6
7impl Context {
8    /// DecryptRTCP decrypts a RTCP packet with an encrypted payload
9    pub fn decrypt_rtcp(&mut self, encrypted: &[u8]) -> Result<BytesMut> {
10        // A received SRTCP packet must be at least the minimum valid size for the
11        // negotiated profile: the RTCP header through the SSRC (read at bytes
12        // 4..8), the trailing SRTCP index, and the auth tag that `get_rtcp_index`
13        // and the cipher read from the end (the HMAC tag for AES-CM, the AEAD tag
14        // for GCM). A shorter packet from the network would otherwise index out
15        // of bounds and panic (a remotely triggerable DoS). This is self-
16        // contained: it does not rely on the individual ciphers' own guards.
17        let min_len = 8
18            + SRTCP_INDEX_SIZE
19            + self.cipher.rtcp_auth_tag_len()
20            + self.cipher.aead_auth_tag_len();
21        if encrypted.len() < min_len {
22            return Err(Error::ErrTooShortRtcp);
23        }
24
25        let mut buf = encrypted;
26        rtcp::Header::unmarshal(&mut buf)?;
27
28        let index = self.cipher.get_rtcp_index(encrypted);
29        let ssrc = u32::from_be_bytes([encrypted[4], encrypted[5], encrypted[6], encrypted[7]]);
30
31        if let Some(replay_detector) = &mut self.get_srtcp_ssrc_state(ssrc).replay_detector
32            && !replay_detector.check(index as u64)
33        {
34            return Err(Error::SrtcpSsrcDuplicated(ssrc, index));
35        }
36
37        let dst = self.cipher.decrypt_rtcp(encrypted, index, ssrc)?;
38
39        if let Some(replay_detector) = &mut self.get_srtcp_ssrc_state(ssrc).replay_detector {
40            replay_detector.accept();
41        }
42
43        Ok(dst)
44    }
45
46    /// EncryptRTCP marshals and encrypts an RTCP packet, writing to the dst buffer provided.
47    /// If the dst buffer does not have the capacity to hold `len(plaintext) + 14` bytes, a new one will be allocated and returned.
48    pub fn encrypt_rtcp(&mut self, decrypted: &[u8]) -> Result<BytesMut> {
49        if decrypted.len() < 8 {
50            return Err(Error::ErrTooShortRtcp);
51        }
52
53        let mut buf = decrypted;
54        rtcp::Header::unmarshal(&mut buf)?;
55
56        let ssrc = u32::from_be_bytes([decrypted[4], decrypted[5], decrypted[6], decrypted[7]]);
57
58        let index = {
59            let state = self.get_srtcp_ssrc_state(ssrc);
60            state.srtcp_index += 1;
61            if state.srtcp_index > MAX_SRTCP_INDEX {
62                state.srtcp_index = 0;
63            }
64            state.srtcp_index
65        };
66
67        self.cipher.encrypt_rtcp(decrypted, index, ssrc)
68    }
69}