Skip to content
File

Blob: firmware/vendor/str0m/tests/srtp-replay-attack.rs

rust235 lines
1use std::time::{Duration, Instant};
2 
3use str0m::format::Codec;
4use str0m::media::MediaKind;
5use str0m::net::Receive;
6use str0m::rtp::{ExtensionValues, RawPacket, RtpWrite, SeqNo, Ssrc};
7use str0m::{Event, Input, Output, Rtc, RtcError};
8 
9mod common;
10use common::{TestRtc, connect_l_r, connect_l_r_with_rtc, init_crypto_default, init_log};
11 
12const EXPECTED_PACKETS: usize = 50;
13const REPLAY_PER_PACKET: usize = 5;
14 
15#[test]
16pub fn srtp_replay_attack_rtp_mode() -> Result<(), RtcError> {
17 init_log();
18 init_crypto_default();
19 
20 let (mut l, mut r) = connect_l_r();
21 let mid = "aud".into();
22 
23 let ssrc_tx: Ssrc = 42.into();
24 l.direct_api().declare_media(mid, MediaKind::Audio);
25 l.direct_api().declare_stream_tx(ssrc_tx, None, mid, None);
26 r.direct_api().declare_media(mid, MediaKind::Audio);
27 
28 let max = l.last.max(r.last);
29 l.last = max;
30 r.last = max;
31 
32 let params = l.params_opus();
33 let ssrc = l.direct_api().stream_tx_by_mid(mid, None).unwrap().ssrc();
34 assert_eq!(params.spec().codec, Codec::Opus);
35 let pt = params.pt();
36 let mut write_at = l.last + Duration::from_millis(20);
37 let mut seq_no: SeqNo = 0_u64.into();
38 let mut time = 0;
39 let mut send_count = 0;
40 const TIME_INTERVAL: u32 = 960;
41 
42 // Process the DTLS Handshake, before we start duplicating SRTP packets
43 progress_with_replay(&mut l, &mut r, 1)?;
44 
45 loop {
46 if l.start + l.duration() > write_at && send_count < EXPECTED_PACKETS {
47 seq_no.inc();
48 time += TIME_INTERVAL;
49 write_at = l.last + Duration::from_millis(20);
50 let wallclock = l.start + l.duration();
51 let mut direct = l.direct_api();
52 let stream = direct.stream_tx(&ssrc).unwrap();
53 let exts = ExtensionValues {
54 audio_level: Some(-42),
55 voice_activity: Some(false),
56 ..Default::default()
57 };
58 
59 stream
60 .write_rtp(RtpWrite::new(pt, seq_no, time, wallclock, [1, 3, 3, 7]).ext_vals(exts));
61 send_count += 1;
62 }
63 
64 progress_with_replay(&mut l, &mut r, REPLAY_PER_PACKET)?;
65 
66 if l.duration() > Duration::from_secs(5) {
67 break;
68 }
69 }
70 
71 let rtp_raw_rx: Vec<_> = r
72 .events
73 .iter()
74 .filter_map(|(_, e)| {
75 if let Some(RawPacket::RtpRx(header, payload)) = e.as_raw_packet() {
76 Some((header, payload))
77 } else {
78 None
79 }
80 })
81 .collect();
82 assert_eq!(rtp_raw_rx.len(), EXPECTED_PACKETS);
83 
84 let rtp: Vec<_> = r
85 .events
86 .iter()
87 .filter_map(|(_, e)| {
88 if let Event::RtpPacket(v) = e {
89 Some(v)
90 } else {
91 None
92 }
93 })
94 .collect();
95 assert_eq!(rtp.len(), EXPECTED_PACKETS);
96 Ok(())
97}
98 
99#[test]
100pub fn srtp_replay_attack_frame_mode() -> Result<(), RtcError> {
101 init_log();
102 init_crypto_default();
103 
104 let now = Instant::now();
105 let rtc1 = Rtc::builder()
106 .set_rtp_mode(true)
107 .enable_raw_packets(true)
108 .build(now);
109 let rtc2 = Rtc::builder()
110 .enable_raw_packets(true)
111 // release packet straight away
112 .set_reordering_size_audio(0)
113 .build(now);
114 
115 let (mut l, mut r) = connect_l_r_with_rtc(rtc1, rtc2);
116 
117 let mid = "aud".into();
118 
119 let ssrc_tx: Ssrc = 42.into();
120 l.direct_api().declare_media(mid, MediaKind::Audio);
121 l.direct_api().declare_stream_tx(ssrc_tx, None, mid, None);
122 r.direct_api().declare_media(mid, MediaKind::Audio);
123 
124 let max = l.last.max(r.last);
125 l.last = max;
126 r.last = max;
127 
128 let params = l.params_opus();
129 let ssrc = l.direct_api().stream_tx_by_mid(mid, None).unwrap().ssrc();
130 assert_eq!(params.spec().codec, Codec::Opus);
131 let pt = params.pt();
132 let mut write_at = l.last + Duration::from_millis(20);
133 let mut seq_no: SeqNo = 0_u64.into();
134 let mut time = 0;
135 let mut send_count = 0;
136 const TIME_INTERVAL: u32 = 960;
137 
138 // Process the DTLS Handshake, before we start duplicating SRTP packets
139 progress_with_replay(&mut l, &mut r, 1)?;
140 
141 loop {
142 if l.start + l.duration() > write_at && send_count < EXPECTED_PACKETS {
143 seq_no.inc();
144 time += TIME_INTERVAL;
145 write_at = l.last + Duration::from_millis(20);
146 let wallclock = l.start + l.duration();
147 let mut direct = l.direct_api();
148 let stream = direct.stream_tx(&ssrc).unwrap();
149 let exts = ExtensionValues {
150 audio_level: Some(-42),
151 voice_activity: Some(false),
152 ..Default::default()
153 };
154 
155 stream
156 .write_rtp(RtpWrite::new(pt, seq_no, time, wallclock, [1, 3, 3, 7]).ext_vals(exts));
157 send_count += 1;
158 }
159 
160 progress_with_replay(&mut l, &mut r, REPLAY_PER_PACKET)?;
161 
162 if l.duration() > Duration::from_secs(5) {
163 break;
164 }
165 }
166 
167 let rtp_raw_rx: Vec<_> = r
168 .events
169 .iter()
170 .filter_map(|(_, e)| {
171 if let Some(RawPacket::RtpRx(header, payload)) = e.as_raw_packet() {
172 Some((header, payload))
173 } else {
174 None
175 }
176 })
177 .collect();
178 assert_eq!(rtp_raw_rx.len(), EXPECTED_PACKETS);
179 
180 let media: Vec<_> = r
181 .events
182 .iter()
183 .filter_map(|(_, e)| {
184 if let Event::MediaData(v) = e {
185 Some(v)
186 } else {
187 None
188 }
189 })
190 .collect();
191 assert_eq!(media.len(), EXPECTED_PACKETS);
192 Ok(())
193}
194 
195pub fn progress_with_replay(
196 l: &mut TestRtc,
197 r: &mut TestRtc,
198 replay: usize,
199) -> Result<(), RtcError> {
200 let (f, t) = if l.last < r.last { (l, r) } else { (r, l) };
201 
202 loop {
203 f.span
204 .in_scope(|| f.rtc.handle_input(Input::Timeout(f.last)))?;
205 
206 match f.span.in_scope(|| f.rtc.poll_output())? {
207 Output::Timeout(v) => {
208 let tick = f.last + Duration::from_millis(10);
209 f.last = if v == f.last { tick } else { tick.min(v) };
210 break;
211 }
212 Output::Transmit(v) => {
213 let data = v.contents;
214 for _ in 0..replay {
215 let input = Input::Receive(
216 f.last,
217 Receive {
218 proto: v.proto,
219 source: v.source,
220 destination: v.destination,
221 contents: (&*data).try_into().unwrap(),
222 },
223 );
224 t.span.in_scope(|| t.rtc.handle_input(input)).unwrap();
225 }
226 }
227 Output::Event(v) => {
228 f.events.push((f.last, v));
229 }
230 }
231 }
232 
233 Ok(())
234}