1 /* GStreamer unit tests for the srtp elements
2 * Copyright (C) 2007 Tim-Philipp Müller <tim centricular net>
3 * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
4 * Copyright (C) 2016 Collabora Ltd <vincent.penquerch@collabora.co.uk>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #ifdef HAVE_VALGRIND
27 # include <valgrind/valgrind.h>
28 #endif
29
30 #include <gst/check/gstcheck.h>
31
32 #include <gst/check/gstharness.h>
33
GST_START_TEST(test_create_and_unref)34 GST_START_TEST (test_create_and_unref)
35 {
36 GstElement *e;
37
38 e = gst_element_factory_make ("srtpenc", NULL);
39 fail_unless (e != NULL);
40 gst_element_set_state (e, GST_STATE_NULL);
41 gst_object_unref (e);
42
43 e = gst_element_factory_make ("srtpdec", NULL);
44 fail_unless (e != NULL);
45 gst_element_set_state (e, GST_STATE_NULL);
46 gst_object_unref (e);
47 }
48
49 GST_END_TEST;
50
GST_START_TEST(test_play)51 GST_START_TEST (test_play)
52 {
53 GstElement *source_pipeline, *sink_pipeline;
54 GstBus *source_bus;
55 GstMessage *msg;
56
57 source_pipeline =
58 gst_parse_launch
59 ("audiotestsrc num-buffers=50 ! alawenc ! rtppcmapay ! application/x-rtp, payload=(int)8, ssrc=(uint)1356955624 ! srtpenc name=enc key=012345678901234567890123456789012345678901234567890123456789 ! udpsink port=5004 sync=false",
60 NULL);
61 sink_pipeline =
62 gst_parse_launch
63 ("udpsrc port=5004 caps=\"application/x-srtp, payload=(int)8, ssrc=(uint)1356955624, srtp-key=(buffer)012345678901234567890123456789012345678901234567890123456789, srtp-cipher=(string)aes-128-icm, srtp-auth=(string)hmac-sha1-80, srtcp-cipher=(string)aes-128-icm, srtcp-auth=(string)hmac-sha1-80\" ! srtpdec name=dec ! rtppcmadepay ! alawdec ! fakesink",
64 NULL);
65
66 fail_unless (gst_element_set_state (source_pipeline,
67 GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE);
68 fail_unless (gst_element_set_state (sink_pipeline,
69 GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE);
70
71 source_bus = gst_pipeline_get_bus (GST_PIPELINE (source_pipeline));
72
73 msg =
74 gst_bus_timed_pop_filtered (source_bus, GST_CLOCK_TIME_NONE,
75 GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
76 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
77 gst_message_unref (msg);
78
79 gst_object_unref (source_bus);
80
81 gst_element_set_state (source_pipeline, GST_STATE_NULL);
82 gst_element_set_state (sink_pipeline, GST_STATE_NULL);
83
84 gst_object_unref (source_pipeline);
85 gst_object_unref (sink_pipeline);
86 }
87
88 GST_END_TEST;
89
90 typedef struct
91 {
92 guint counter;
93 guint start_roc;
94 } roc_check_data;
95
96 static guint
get_roc(GstElement * e)97 get_roc (GstElement * e)
98 {
99 const GstStructure *s, *ss;
100 const GValue *v;
101 guint roc = 0;
102
103 g_object_get (e, "stats", &s, NULL);
104 v = gst_structure_get_value (s, "streams");
105 fail_unless (v);
106 v = gst_value_array_get_value (v, 0);
107 ss = gst_value_get_structure (v);
108 gst_structure_get_uint (ss, "roc", &roc);
109 return roc;
110 }
111
112 static GstPadProbeReturn
roc_check_probe(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)113 roc_check_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
114 {
115 roc_check_data *data = user_data;
116 GstElement *e = GST_PAD_PARENT (pad);
117
118 if (G_UNLIKELY (data->counter % 8192 == 0))
119 GST_DEBUG_OBJECT (pad, "counter at %d", data->counter);
120
121 /* record first roc, then wait for 2^16 packets to pass */
122 if (data->counter == 0) {
123 data->start_roc = get_roc (e);
124 } else if (data->counter == 65536) {
125 /* get roc and check it's one more than what we started with */
126 fail_unless ((get_roc (e) & 0xffff) == ((data->start_roc + 1) & 0xffff));
127 }
128 data->counter++;
129 return GST_PAD_PROBE_OK;
130 }
131
132 static GstCaps *
request_key(void)133 request_key (void)
134 {
135 GstCaps *caps;
136
137 caps =
138 gst_caps_from_string
139 ("application/x-srtp, payload=(int)8, ssrc=(uint)1356955624, srtp-key=(buffer)012345678901234567890123456789012345678901234567890123456789, srtp-cipher=(string)aes-128-icm, srtp-auth=(string)hmac-sha1-80, srtcp-cipher=(string)aes-128-icm, srtcp-auth=(string)hmac-sha1-80");
140 return caps;
141 }
142
GST_START_TEST(test_roc)143 GST_START_TEST (test_roc)
144 {
145 GstElement *source_pipeline, *sink_pipeline;
146 GstElement *srtpenc, *srtpdec;
147 GstBus *source_bus, *sink_bus;
148 GstMessage *msg;
149 GstPad *pad;
150 roc_check_data source_roc_check_data, sink_roc_check_data;
151
152 source_pipeline =
153 gst_parse_launch
154 ("audiotestsrc num-buffers=65555 ! alawenc ! rtppcmapay ! application/x-rtp, payload=(int)8, ssrc=(uint)1356955624 ! srtpenc name=enc key=012345678901234567890123456789012345678901234567890123456789 ! udpsink port=5004 sync=false",
155 NULL);
156 sink_pipeline =
157 gst_parse_launch
158 ("udpsrc port=5004 caps=\"application/x-srtp, payload=(int)8, ssrc=(uint)1356955624, srtp-key=(buffer)012345678901234567890123456789012345678901234567890123456789, srtp-cipher=(string)aes-128-icm, srtp-auth=(string)hmac-sha1-80, srtcp-cipher=(string)aes-128-icm, srtcp-auth=(string)hmac-sha1-80\" ! srtpdec name=dec ! rtppcmadepay ! alawdec ! fakesink",
159 NULL);
160
161 fail_unless (gst_element_set_state (source_pipeline,
162 GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE);
163 fail_unless (gst_element_set_state (sink_pipeline,
164 GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE);
165
166 source_bus = gst_pipeline_get_bus (GST_PIPELINE (source_pipeline));
167 sink_bus = gst_pipeline_get_bus (GST_PIPELINE (sink_pipeline));
168
169 /* install a pad probe on the srtp elements' source pads */
170 srtpenc = gst_bin_get_by_name (GST_BIN (source_pipeline), "enc");
171 fail_unless (srtpenc != NULL);
172 pad = gst_element_get_static_pad (srtpenc, "rtp_src_0");
173 fail_unless (pad != NULL);
174 source_roc_check_data.counter = 0;
175 gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, roc_check_probe,
176 &source_roc_check_data, NULL);
177 gst_object_unref (pad);
178 gst_object_unref (srtpenc);
179
180 srtpdec = gst_bin_get_by_name (GST_BIN (sink_pipeline), "dec");
181 fail_unless (srtpdec != NULL);
182 g_signal_connect (srtpdec, "request_key", G_CALLBACK (request_key),
183 GINT_TO_POINTER (0));
184 pad = gst_element_get_static_pad (srtpdec, "rtp_src");
185 sink_roc_check_data.counter = 0;
186 gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, roc_check_probe,
187 &sink_roc_check_data, NULL);
188 fail_unless (pad != NULL);
189 gst_object_unref (pad);
190 gst_object_unref (srtpdec);
191
192 msg =
193 gst_bus_timed_pop_filtered (source_bus, GST_CLOCK_TIME_NONE,
194 GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
195 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
196 gst_message_unref (msg);
197
198 gst_object_unref (source_bus);
199 gst_object_unref (sink_bus);
200
201 gst_element_set_state (source_pipeline, GST_STATE_NULL);
202 gst_element_set_state (sink_pipeline, GST_STATE_NULL);
203
204 gst_object_unref (source_pipeline);
205 gst_object_unref (sink_pipeline);
206 }
207
208 GST_END_TEST;
209
210 #ifdef HAVE_SRTP2
211
GST_START_TEST(test_simple_mki)212 GST_START_TEST (test_simple_mki)
213 {
214 GstElement *pipeline;
215 GstElement *dec;
216 GstPad *pad;
217 GstBus *bus;
218 GstMessage *msg;
219 GstCaps *caps1, *caps2;
220
221 pipeline =
222 gst_parse_launch
223 ("audiotestsrc num-buffers=50 ! alawenc ! rtppcmapay ! application/x-rtp, payload=(int)8, ssrc=(uint)1356955624 ! srtpenc name=enc key=012345678901234567890123456789012345678901234567890123456789 mki=1234 ! srtpdec name=dec ! rtppcmadepay ! alawdec ! fakesink",
224 NULL);
225
226 fail_unless (gst_element_set_state (pipeline,
227 GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE);
228
229 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
230
231 msg =
232 gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
233 GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
234 fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS);
235 gst_message_unref (msg);
236
237 gst_object_unref (bus);
238
239 dec = gst_bin_get_by_name (GST_BIN (pipeline), "dec");
240 fail_unless (dec);
241 pad = gst_element_get_static_pad (dec, "rtp_sink");
242 fail_unless (pad);
243 g_object_get (pad, "caps", &caps1, NULL);
244 fail_unless (caps1);
245 caps2 =
246 gst_caps_from_string
247 ("application/x-srtp, srtp-key=(buffer)012345678901234567890123456789012345678901234567890123456789, mki=(buffer)1234");
248 fail_unless (gst_caps_can_intersect (caps1, caps2));
249 gst_caps_unref (caps1);
250 gst_caps_unref (caps2);
251 gst_object_unref (pad);
252 gst_object_unref (dec);
253
254 gst_element_set_state (pipeline, GST_STATE_NULL);
255 gst_object_unref (pipeline);
256 }
257
258 GST_END_TEST;
259
GST_START_TEST(test_srtpdec_multiple_mki)260 GST_START_TEST (test_srtpdec_multiple_mki)
261 {
262 static const char CAPS_RTP[] =
263 "application/x-rtp, media=(string)audio, clock-rate=(int)8000, encoding-name=(string)PCMA, payload=(int)8, ssrc=(uint)2648728855";
264 static const char CAPS_SRTP[] =
265 "application/x-srtp, media=(string)audio, clock-rate=(int)8000, encoding-name=(string)PCMA, payload=(int)8, ssrc=(uint)2648728855, srtp-key=(buffer)012345678901234567890123456789012345678901234567890123456789, mki=(buffer)01, srtp-cipher=(string)aes-128-icm, srtp-auth=(string)hmac-sha1-80, srtcp-cipher=(string)aes-128-icm, srtcp-auth=(string)hmac-sha1-80, srtp-key2=(buffer)678901234567890123456789012345678901234567890123456780123456, mki2=(buffer)02";
266
267 unsigned char DECRYPTED_1_PKT[] = {
268 0x80, 0x88, 0x13, 0xe1, 0x87, 0x76, 0xda, 0x98, 0x9d, 0xe0, 0x65, 0x17,
269 0xb4, 0xa5, 0xa3, 0xac, 0xac, 0xa3, 0xa5, 0xb7, 0xfc, 0x0a
270 };
271 unsigned int DECRYPTED_1_PKT_LEN = 22;
272 unsigned char DECRYPTED_2_PKT[] = {
273 0x80, 0x08, 0x13, 0xe2, 0x87, 0x76, 0xda, 0xa2, 0x9d, 0xe0, 0x65, 0x17,
274 0x3a, 0x20, 0x2d, 0x2c, 0x23, 0x24, 0x31, 0x6c, 0x89, 0xbb
275 };
276 unsigned int DECRYPTED_2_PKT_LEN = 22;
277 unsigned char DECRYPTED_3_PKT[] = {
278 0x80, 0x08, 0x13, 0xe3, 0x87, 0x76, 0xda, 0xac, 0x9d, 0xe0, 0x65, 0x17,
279 0xa0, 0xad, 0xac, 0xa2, 0xa7, 0xb0, 0x96, 0x0c, 0x39, 0x21
280 };
281 unsigned int DECRYPTED_3_PKT_LEN = 22;
282 unsigned char MKI_1_01_PKT[] = {
283 0x80, 0x88, 0x13, 0xe1, 0x87, 0x76, 0xda, 0x98, 0x9d, 0xe0, 0x65, 0x17,
284 0xd7, 0x16, 0xac, 0x3e, 0x60, 0x08, 0x04, 0xd6, 0xfb, 0x0e, 0x01, 0x77,
285 0x93, 0x20, 0x3f, 0x45, 0x2c, 0xb3, 0x74, 0xd1, 0x20
286 };
287 unsigned int MKI_1_01_PKT_LEN = 33;
288 unsigned char MKI_2_02_PKT[] = {
289 0x80, 0x08, 0x13, 0xe2, 0x87, 0x76, 0xda, 0xa2, 0x9d, 0xe0, 0x65, 0x17,
290 0xc4, 0x69, 0x8c, 0xb3, 0xf8, 0x64, 0x66, 0x78, 0x7f, 0x1d, 0x02, 0x8f,
291 0x50, 0x57, 0xff, 0xa4, 0x80, 0xe6, 0x68, 0x74, 0x21
292 };
293 unsigned int MKI_2_02_PKT_LEN = 33;
294 unsigned char MKI_3_01_PKT[] = {
295 0x80, 0x08, 0x13, 0xe3, 0x87, 0x76, 0xda, 0xac, 0x9d, 0xe0, 0x65, 0x17,
296 0xa6, 0xdf, 0x77, 0x4c, 0xb0, 0xe9, 0x3c, 0x1a, 0x54, 0x6f, 0x01, 0x9d,
297 0xc3, 0x4b, 0x1d, 0x29, 0x67, 0xa0, 0x4d, 0xde, 0xec
298 };
299 unsigned int MKI_3_01_PKT_LEN = 33;
300
301
302 GstHarness *h =
303 gst_harness_new_with_padnames ("srtpdec", "rtp_sink", "rtp_src");
304 GstBuffer *buf;
305
306 gst_harness_set_caps_str (h, CAPS_SRTP, CAPS_RTP);
307
308 buf = gst_harness_push_and_pull (h,
309 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
310 (char *) MKI_1_01_PKT, MKI_1_01_PKT_LEN, 0, MKI_1_01_PKT_LEN, NULL,
311 NULL));
312 fail_unless (buf);
313 fail_unless_equals_int (gst_buffer_get_size (buf), DECRYPTED_1_PKT_LEN);
314 fail_unless (!gst_buffer_memcmp (buf, 0, DECRYPTED_1_PKT,
315 DECRYPTED_1_PKT_LEN));
316 gst_buffer_unref (buf);
317
318 buf = gst_harness_push_and_pull (h,
319 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
320 (char *) MKI_2_02_PKT, MKI_2_02_PKT_LEN, 0, MKI_2_02_PKT_LEN, NULL,
321 NULL));
322 fail_unless_equals_int (gst_buffer_get_size (buf), DECRYPTED_2_PKT_LEN);
323 fail_unless (!gst_buffer_memcmp (buf, 0, DECRYPTED_2_PKT,
324 DECRYPTED_2_PKT_LEN));
325 gst_buffer_unref (buf);
326
327 buf = gst_harness_push_and_pull (h,
328 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
329 (char *) MKI_3_01_PKT, MKI_3_01_PKT_LEN, 0, MKI_3_01_PKT_LEN, NULL,
330 NULL));
331 fail_unless_equals_int (gst_buffer_get_size (buf), DECRYPTED_3_PKT_LEN);
332 fail_unless (!gst_buffer_memcmp (buf, 0, DECRYPTED_3_PKT,
333 DECRYPTED_3_PKT_LEN));
334 gst_buffer_unref (buf);
335
336 gst_harness_teardown (h);
337 }
338
339 GST_END_TEST;
340
341
342 #endif
343
344 static Suite *
srtp_suite(void)345 srtp_suite (void)
346 {
347 Suite *s = suite_create ("srtp");
348 TCase *tc_chain = tcase_create ("general");
349
350 suite_add_tcase (s, tc_chain);
351 tcase_set_timeout (tc_chain, 180);
352 tcase_add_test (tc_chain, test_create_and_unref);
353 tcase_add_test (tc_chain, test_play);
354 tcase_add_test (tc_chain, test_roc);
355 #ifdef HAVE_SRTP2
356 tcase_add_test (tc_chain, test_simple_mki);
357 tcase_add_test (tc_chain, test_srtpdec_multiple_mki);
358 #endif
359
360 return s;
361 }
362
363 GST_CHECK_MAIN (srtp);
364