1#[cfg(test)]
2mod context_test;
3#[cfg(test)]
4mod srtcp_test;
5#[cfg(test)]
6mod srtp_test;
7
8use std::collections::HashMap;
9
10use crypto::RTCCrypto;
11use shared::replay_detector::*;
12
13use crate::cipher::cipher_aead_aes_gcm::*;
14use crate::cipher::cipher_aes_cm_hmac_sha1::*;
15use crate::cipher::*;
16use crate::option::*;
17use crate::protection_profile::*;
18use shared::error::{Error, Result};
19
20pub mod srtcp;
22pub mod srtp;
24
25const MAX_ROC: u32 = u32::MAX;
26const SEQ_NUM_MEDIAN: u16 = 1 << 15;
27const SEQ_NUM_MAX: u16 = u16::MAX;
28
29#[derive(Default)]
31pub(crate) struct SrtpSsrcState {
32 ssrc: u32,
33 index: u64,
34 rollover_has_processed: bool,
35 replay_detector: Option<Box<dyn ReplayDetector>>,
36}
37
38#[derive(Default)]
40pub(crate) struct SrtcpSsrcState {
41 srtcp_index: usize,
42 ssrc: u32,
43 replay_detector: Option<Box<dyn ReplayDetector>>,
44}
45
46impl SrtpSsrcState {
47 pub fn next_rollover_count(&self, sequence_number: u16) -> (u32, i32, bool) {
48 let local_roc = (self.index >> 16) as u32;
49 let local_seq = self.index as u16;
50
51 let mut guess_roc = local_roc;
52
53 let diff = if self.rollover_has_processed {
54 let seq = (sequence_number as i32).wrapping_sub(local_seq as i32);
55 if self.index > SEQ_NUM_MEDIAN as _ {
58 if local_seq < SEQ_NUM_MEDIAN {
59 if seq > SEQ_NUM_MEDIAN as i32 {
60 guess_roc = local_roc.wrapping_sub(1);
61 seq.wrapping_sub(SEQ_NUM_MAX as i32 + 1)
62 } else {
63 seq
64 }
65 } else if local_seq - SEQ_NUM_MEDIAN > sequence_number {
66 guess_roc = local_roc.wrapping_add(1);
67 seq.wrapping_add(SEQ_NUM_MAX as i32 + 1)
68 } else {
69 seq
70 }
71 } else {
72 seq
74 }
75 } else {
76 0i32
77 };
78
79 (guess_roc, diff, (guess_roc == 0 && local_roc == MAX_ROC))
80 }
81
82 pub fn update_rollover_count(&mut self, sequence_number: u16, diff: i32) {
84 if !self.rollover_has_processed {
85 self.index |= sequence_number as u64;
86 self.rollover_has_processed = true;
87 } else {
88 self.index = self.index.wrapping_add(diff as _);
89 }
90 }
91}
92
93pub struct Context {
97 cipher: Box<dyn Cipher>,
98
99 srtp_ssrc_states: HashMap<u32, SrtpSsrcState>,
100 srtcp_ssrc_states: HashMap<u32, SrtcpSsrcState>,
101
102 new_srtp_replay_detector: ContextOption,
103 new_srtcp_replay_detector: ContextOption,
104}
105
106impl Context {
107 pub fn new(
113 master_key: &[u8],
114 master_salt: &[u8],
115 profile: ProtectionProfile,
116 srtp_ctx_opt: Option<ContextOption>,
117 srtcp_ctx_opt: Option<ContextOption>,
118 crypto: &dyn RTCCrypto,
119 ) -> Result<Context> {
120 let key_len = profile.key_len();
121 let salt_len = profile.salt_len();
122
123 if master_key.len() != key_len {
124 return Err(Error::SrtpMasterKeyLength(key_len, master_key.len()));
125 } else if master_salt.len() != salt_len {
126 return Err(Error::SrtpSaltLength(salt_len, master_salt.len()));
127 }
128 profile.ensure_crypto_supported(crypto)?;
129
130 let cipher: Box<dyn Cipher> = match profile {
131 ProtectionProfile::Aes128CmHmacSha1_32
132 | ProtectionProfile::Aes128CmHmacSha1_80
133 | ProtectionProfile::Aes256CmHmacSha1_80
134 | ProtectionProfile::Aes256CmHmacSha1_32 => Box::new(CipherAesCmHmacSha1::new(
135 profile,
136 master_key,
137 master_salt,
138 crypto,
139 )?),
140
141 ProtectionProfile::AeadAes128Gcm | ProtectionProfile::AeadAes256Gcm => {
142 Box::new(CipherAeadAesGcm::new(
145 profile,
146 master_key,
147 master_salt,
148 crypto,
149 )?)
150 }
151 };
152
153 let srtp_ctx_opt = if let Some(ctx_opt) = srtp_ctx_opt {
154 ctx_opt
155 } else {
156 srtp_no_replay_protection()
157 };
158
159 let srtcp_ctx_opt = if let Some(ctx_opt) = srtcp_ctx_opt {
160 ctx_opt
161 } else {
162 srtcp_no_replay_protection()
163 };
164
165 Ok(Context {
166 cipher,
167 srtp_ssrc_states: HashMap::new(),
168 srtcp_ssrc_states: HashMap::new(),
169 new_srtp_replay_detector: srtp_ctx_opt,
170 new_srtcp_replay_detector: srtcp_ctx_opt,
171 })
172 }
173
174 fn get_srtp_ssrc_state(&mut self, ssrc: u32) -> &mut SrtpSsrcState {
175 let new_srtp_replay_detector = &self.new_srtp_replay_detector;
180 self.srtp_ssrc_states
181 .entry(ssrc)
182 .or_insert_with(|| SrtpSsrcState {
183 ssrc,
184 replay_detector: Some(new_srtp_replay_detector()),
185 ..Default::default()
186 })
187 }
188
189 fn get_srtcp_ssrc_state(&mut self, ssrc: u32) -> &mut SrtcpSsrcState {
190 let new_srtcp_replay_detector = &self.new_srtcp_replay_detector;
191 self.srtcp_ssrc_states
192 .entry(ssrc)
193 .or_insert_with(|| SrtcpSsrcState {
194 ssrc,
195 replay_detector: Some(new_srtcp_replay_detector()),
196 ..Default::default()
197 })
198 }
199
200 fn get_roc(&self, ssrc: u32) -> Option<u32> {
202 self.srtp_ssrc_states
203 .get(&ssrc)
204 .map(|s| (s.index >> 16) as _)
205 }
206
207 fn set_roc(&mut self, ssrc: u32, roc: u32) {
209 let state = self.get_srtp_ssrc_state(ssrc);
210 state.index = (roc as u64) << 16;
211 state.rollover_has_processed = false;
212 }
213
214 fn get_index(&self, ssrc: u32) -> Option<usize> {
216 self.srtcp_ssrc_states.get(&ssrc).map(|s| s.srtcp_index)
217 }
218
219 fn set_index(&mut self, ssrc: u32, index: usize) {
221 self.get_srtcp_ssrc_state(ssrc).srtcp_index = index % (MAX_SRTCP_INDEX + 1);
222 }
223}