• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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