1 /*
2 * GStreamer - GStreamer SRTP decoder
3 *
4 * Copyright 2009-2011 Collabora Ltd.
5 * @author: Gabriel Millaire <gabriel.millaire@collabora.co.uk>
6 * @author: Olivier Crete <olivier.crete@collabora.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Alternatively, the contents of this file may be used under the
27 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
28 * which case the following provisions apply instead of the ones
29 * mentioned above:
30 *
31 * This library is free software; you can redistribute it and/or
32 * modify it under the terms of the GNU Library General Public
33 * License as published by the Free Software Foundation; either
34 * version 2 of the License, or (at your option) any later version.
35 *
36 * This library is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 * Library General Public License for more details.
40 *
41 * You should have received a copy of the GNU Library General Public
42 * License along with this library; if not, write to the
43 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
44 * Boston, MA 02111-1307, USA.
45 */
46
47 /**
48 * SECTION:element-srtpdec
49 * @title: srtpdec
50 * @see_also: srtpenc
51 *
52 * gstrtpdec acts as a decoder that removes security from SRTP and SRTCP
53 * packets (encryption and authentication) and out RTP and RTCP. It
54 * receives packet of type 'application/x-srtp' or 'application/x-srtcp'
55 * on its sink pad, and outs packets of type 'application/x-rtp' or
56 * 'application/x-rtcp' on its source pad.
57 *
58 * For each packet received, it checks if the internal SSRC is in the list
59 * of streams already in use. If this is not the case, it sends a signal to
60 * the user to get the needed parameters to create a new stream : master
61 * key, encryption and authentication mechanisms for both RTP and RTCP. If
62 * the user can't provide those parameters, the buffer is dropped and a
63 * warning is emitted.
64 *
65 * This element uses libsrtp library. The encryption and authentication
66 * mechanisms available are :
67 *
68 * Encryption
69 * - AES_ICM 256 bits (maximum security)
70 * - AES_ICM 128 bits (default)
71 * - NULL
72 *
73 * Authentication
74 * - HMAC_SHA1 80 bits (default, maximum protection)
75 * - HMAC_SHA1 32 bits
76 * - NULL
77 *
78 * Note that for SRTP protection, authentication is mandatory (non-null)
79 * if encryption is used (non-null).
80 *
81 * Each packet received is first analysed (checked for valid SSRC) then
82 * its buffer is unprotected with libsrtp, then pushed on the source pad.
83 * If protection failed or the stream could not be created, the buffer
84 * is dropped and a warning is emitted.
85 *
86 * When the maximum usage of the master key is reached, a soft-limit
87 * signal is sent to the user, and new parameters (master key) are needed
88 * in return. If the hard limit is reached, a flag is set and every
89 * subsequent packet is dropped, until a new key is set and the stream
90 * has been updated.
91 *
92 * If a stream is to be shared between multiple clients the SRTP
93 * rollover counter for a given SSRC must be set in the caps "roc" field
94 * when the request-key signal is emitted by the decoder. The rollover
95 * counters should have been transmitted by a signaling protocol by some
96 * other means. If no rollover counter is provided by the user, 0 is
97 * used by default.
98 *
99 * It is possible to receive a stream protected by multiple master keys, each buffer
100 * then contains a Master Key Identifier (MKI) to identify which key was used for this
101 * buffer. If multiple keys are needed, the first key can be specified in the caps as
102 * "srtp-key=(buffer)key1data, mki=(buffer)mki1data", then the second one can be given in
103 * the same caps as "srtp-key2=(buffer)key2data, mki2=(buffer)mki2data", and more can
104 * be added up to 15.
105 *
106 * ## Example pipelines
107 * |[
108 * gst-launch-1.0 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 ! rtppcmadepay ! alawdec ! pulsesink
109 * ]| Receive PCMA SRTP packets through UDP using caps to specify
110 * master key and protection.
111 * |[
112 * gst-launch-1.0 audiotestsrc ! alawenc ! rtppcmapay ! 'application/x-rtp, payload=(int)8, ssrc=(uint)1356955624' ! srtpenc key="012345678901234567890123456789012345678901234567890123456789" ! udpsink port=5004
113 * ]| Send PCMA SRTP packets through UDP, nothing how the SSRC is forced so
114 * that the receiver will recognize it.
115 *
116 */
117
118 #include "gstsrtpdec.h"
119
120 #include <gst/rtp/gstrtpbuffer.h>
121 #include <string.h>
122
123 GST_DEBUG_CATEGORY_STATIC (gst_srtp_dec_debug);
124 #define GST_CAT_DEFAULT gst_srtp_dec_debug
125
126 #define DEFAULT_REPLAY_WINDOW_SIZE 128
127
128 /* Filter signals and args */
129 enum
130 {
131 SIGNAL_REQUEST_KEY = 1,
132 SIGNAL_CLEAR_KEYS,
133 SIGNAL_SOFT_LIMIT,
134 SIGNAL_HARD_LIMIT,
135 SIGNAL_REMOVE_KEY,
136 LAST_SIGNAL
137 };
138
139 enum
140 {
141 PROP_0,
142 PROP_REPLAY_WINDOW_SIZE,
143 PROP_STATS
144 };
145
146 /* the capabilities of the inputs and outputs.
147 *
148 * describe the real formats here.
149 */
150 static GstStaticPadTemplate rtp_sink_template =
151 GST_STATIC_PAD_TEMPLATE ("rtp_sink",
152 GST_PAD_SINK,
153 GST_PAD_ALWAYS,
154 GST_STATIC_CAPS ("application/x-srtp")
155 );
156
157 static GstStaticPadTemplate rtp_src_template =
158 GST_STATIC_PAD_TEMPLATE ("rtp_src",
159 GST_PAD_SRC,
160 GST_PAD_ALWAYS,
161 GST_STATIC_CAPS ("application/x-rtp")
162 );
163
164 static GstStaticPadTemplate rtcp_sink_template =
165 GST_STATIC_PAD_TEMPLATE ("rtcp_sink",
166 GST_PAD_SINK,
167 GST_PAD_ALWAYS,
168 GST_STATIC_CAPS ("application/x-srtcp")
169 );
170
171 static GstStaticPadTemplate rtcp_src_template =
172 GST_STATIC_PAD_TEMPLATE ("rtcp_src",
173 GST_PAD_SRC,
174 GST_PAD_ALWAYS,
175 GST_STATIC_CAPS ("application/x-rtcp")
176 );
177
178 static guint gst_srtp_dec_signals[LAST_SIGNAL] = { 0 };
179
180 G_DEFINE_TYPE (GstSrtpDec, gst_srtp_dec, GST_TYPE_ELEMENT);
181
182 static void gst_srtp_dec_set_property (GObject * object, guint prop_id,
183 const GValue * value, GParamSpec * pspec);
184 static void gst_srtp_dec_get_property (GObject * object, guint prop_id,
185 GValue * value, GParamSpec * pspec);
186
187 static void gst_srtp_dec_clear_streams (GstSrtpDec * filter);
188 static void gst_srtp_dec_remove_stream (GstSrtpDec * filter, guint ssrc);
189
190 static gboolean gst_srtp_dec_sink_event_rtp (GstPad * pad, GstObject * parent,
191 GstEvent * event);
192 static gboolean gst_srtp_dec_sink_event_rtcp (GstPad * pad, GstObject * parent,
193 GstEvent * event);
194
195 static gboolean gst_srtp_dec_sink_query_rtp (GstPad * pad, GstObject * parent,
196 GstQuery * query);
197 static gboolean gst_srtp_dec_sink_query_rtcp (GstPad * pad,
198 GstObject * parent, GstQuery * query);
199
200
201 static GstIterator *gst_srtp_dec_iterate_internal_links_rtp (GstPad * pad,
202 GstObject * parent);
203 static GstIterator *gst_srtp_dec_iterate_internal_links_rtcp (GstPad * pad,
204 GstObject * parent);
205
206 static GstFlowReturn gst_srtp_dec_chain_rtp (GstPad * pad,
207 GstObject * parent, GstBuffer * buf);
208 static GstFlowReturn gst_srtp_dec_chain_rtcp (GstPad * pad,
209 GstObject * parent, GstBuffer * buf);
210
211 static GstStateChangeReturn gst_srtp_dec_change_state (GstElement * element,
212 GstStateChange transition);
213
214 static GstSrtpDecSsrcStream *request_key_with_signal (GstSrtpDec * filter,
215 guint32 ssrc, gint signal);
216
217 struct _GstSrtpDecSsrcStream
218 {
219 guint32 ssrc;
220
221 guint32 roc;
222 GstBuffer *key;
223 GstSrtpCipherType rtp_cipher;
224 GstSrtpAuthType rtp_auth;
225 GstSrtpCipherType rtcp_cipher;
226 GstSrtpAuthType rtcp_auth;
227 GArray *keys;
228 };
229
230 #ifdef HAVE_SRTP2
231 struct GstSrtpDecKey
232 {
233 GstBuffer *mki;
234 GstBuffer *key;
235 };
236 #endif
237
238 #define STREAM_HAS_CRYPTO(stream) \
239 (stream->rtp_cipher != GST_SRTP_CIPHER_NULL || \
240 stream->rtcp_cipher != GST_SRTP_CIPHER_NULL || \
241 stream->rtp_auth != GST_SRTP_AUTH_NULL || \
242 stream->rtcp_auth != GST_SRTP_AUTH_NULL)
243
244
245 /* initialize the srtpdec's class */
246 static void
gst_srtp_dec_class_init(GstSrtpDecClass * klass)247 gst_srtp_dec_class_init (GstSrtpDecClass * klass)
248 {
249 GObjectClass *gobject_class;
250 GstElementClass *gstelement_class;
251
252 gobject_class = (GObjectClass *) klass;
253 gstelement_class = (GstElementClass *) klass;
254
255 gobject_class->set_property = gst_srtp_dec_set_property;
256 gobject_class->get_property = gst_srtp_dec_get_property;
257
258 gst_element_class_add_static_pad_template (gstelement_class,
259 &rtp_src_template);
260 gst_element_class_add_static_pad_template (gstelement_class,
261 &rtp_sink_template);
262 gst_element_class_add_static_pad_template (gstelement_class,
263 &rtcp_src_template);
264 gst_element_class_add_static_pad_template (gstelement_class,
265 &rtcp_sink_template);
266
267 gst_element_class_set_static_metadata (gstelement_class, "SRTP decoder",
268 "Filter/Network/SRTP",
269 "A SRTP and SRTCP decoder",
270 "Gabriel Millaire <millaire.gabriel@collabora.com>");
271
272 /* Install callbacks */
273 gstelement_class->change_state =
274 GST_DEBUG_FUNCPTR (gst_srtp_dec_change_state);
275
276 klass->clear_streams = GST_DEBUG_FUNCPTR (gst_srtp_dec_clear_streams);
277 klass->remove_stream = GST_DEBUG_FUNCPTR (gst_srtp_dec_remove_stream);
278
279 /* Install properties */
280 g_object_class_install_property (gobject_class, PROP_REPLAY_WINDOW_SIZE,
281 g_param_spec_uint ("replay-window-size", "Replay window size",
282 "Size of the replay protection window",
283 64, 0x8000, DEFAULT_REPLAY_WINDOW_SIZE,
284 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285 g_object_class_install_property (gobject_class, PROP_STATS,
286 g_param_spec_boxed ("stats", "Statistics", "Various statistics",
287 GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
288
289 /* Install signals */
290 /**
291 * GstSrtpDec::request-key:
292 * @gstsrtpdec: the element on which the signal is emitted
293 * @ssrc: The unique SSRC of the stream
294 *
295 * Signal emited to get the parameters relevant to stream
296 * with @ssrc. User should provide the key and the RTP and
297 * RTCP encryption ciphers and authentication, and return
298 * them wrapped in a GstCaps.
299 */
300 gst_srtp_dec_signals[SIGNAL_REQUEST_KEY] =
301 g_signal_new ("request-key", G_TYPE_FROM_CLASS (klass),
302 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
303
304 /**
305 * GstSrtpDec::clear-keys:
306 * @gstsrtpdec: the element on which the signal is emitted
307 *
308 * Clear the internal list of streams
309 */
310 gst_srtp_dec_signals[SIGNAL_CLEAR_KEYS] =
311 g_signal_new ("clear-keys", G_TYPE_FROM_CLASS (klass),
312 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
313 G_STRUCT_OFFSET (GstSrtpDecClass, clear_streams), NULL, NULL, NULL,
314 G_TYPE_NONE, 0, G_TYPE_NONE);
315
316 /**
317 * GstSrtpDec::soft-limit:
318 * @gstsrtpdec: the element on which the signal is emitted
319 * @ssrc: The unique SSRC of the stream
320 *
321 * Signal emited when the stream with @ssrc has reached the
322 * soft limit of utilisation of it's master encryption key.
323 * User should provide a new key and new RTP and RTCP encryption
324 * ciphers and authentication, and return them wrapped in a
325 * GstCaps.
326 */
327 gst_srtp_dec_signals[SIGNAL_SOFT_LIMIT] =
328 g_signal_new ("soft-limit", G_TYPE_FROM_CLASS (klass),
329 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
330
331 /**
332 * GstSrtpDec::hard-limit:
333 * @gstsrtpdec: the element on which the signal is emitted
334 * @ssrc: The unique SSRC of the stream
335 *
336 * Signal emited when the stream with @ssrc has reached the
337 * hard limit of utilisation of it's master encryption key.
338 * User should provide a new key and new RTP and RTCP encryption
339 * ciphers and authentication, and return them wrapped in a
340 * GstCaps. If user could not provide those parameters or signal
341 * is not answered, the buffers of this stream will be dropped.
342 */
343 gst_srtp_dec_signals[SIGNAL_HARD_LIMIT] =
344 g_signal_new ("hard-limit", G_TYPE_FROM_CLASS (klass),
345 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, GST_TYPE_CAPS, 1, G_TYPE_UINT);
346
347 /**
348 * GstSrtpDec::remove-key:
349 * @gstsrtpdec: the element on which the signal is emitted
350 * @ssrc: The SSRC for which to remove the key.
351 *
352 * Removes keys for a specific SSRC
353 */
354 gst_srtp_dec_signals[SIGNAL_REMOVE_KEY] =
355 g_signal_new ("remove-key", G_TYPE_FROM_CLASS (klass),
356 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
357 G_STRUCT_OFFSET (GstSrtpDecClass, remove_stream), NULL, NULL, NULL,
358 G_TYPE_NONE, 1, G_TYPE_UINT);
359
360 }
361
362 /* initialize the new element
363 * instantiate pads and add them to element
364 * set pad calback functions
365 * initialize instance structure
366 */
367 static void
gst_srtp_dec_init(GstSrtpDec * filter)368 gst_srtp_dec_init (GstSrtpDec * filter)
369 {
370 filter->replay_window_size = DEFAULT_REPLAY_WINDOW_SIZE;
371
372 filter->rtp_sinkpad =
373 gst_pad_new_from_static_template (&rtp_sink_template, "rtp_sink");
374 gst_pad_set_event_function (filter->rtp_sinkpad,
375 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_event_rtp));
376 gst_pad_set_query_function (filter->rtp_sinkpad,
377 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_query_rtp));
378 gst_pad_set_iterate_internal_links_function (filter->rtp_sinkpad,
379 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtp));
380 gst_pad_set_chain_function (filter->rtp_sinkpad,
381 GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_rtp));
382
383 filter->rtp_srcpad =
384 gst_pad_new_from_static_template (&rtp_src_template, "rtp_src");
385 gst_pad_set_iterate_internal_links_function (filter->rtp_srcpad,
386 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtp));
387
388 gst_pad_set_element_private (filter->rtp_sinkpad, filter->rtp_srcpad);
389 gst_pad_set_element_private (filter->rtp_srcpad, filter->rtp_sinkpad);
390
391 gst_element_add_pad (GST_ELEMENT (filter), filter->rtp_sinkpad);
392 gst_element_add_pad (GST_ELEMENT (filter), filter->rtp_srcpad);
393
394
395 filter->rtcp_sinkpad =
396 gst_pad_new_from_static_template (&rtcp_sink_template, "rtcp_sink");
397 gst_pad_set_event_function (filter->rtcp_sinkpad,
398 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_event_rtcp));
399 gst_pad_set_query_function (filter->rtcp_sinkpad,
400 GST_DEBUG_FUNCPTR (gst_srtp_dec_sink_query_rtcp));
401 gst_pad_set_iterate_internal_links_function (filter->rtcp_sinkpad,
402 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtcp));
403 gst_pad_set_chain_function (filter->rtcp_sinkpad,
404 GST_DEBUG_FUNCPTR (gst_srtp_dec_chain_rtcp));
405
406 filter->rtcp_srcpad =
407 gst_pad_new_from_static_template (&rtcp_src_template, "rtcp_src");
408 gst_pad_set_iterate_internal_links_function (filter->rtcp_srcpad,
409 GST_DEBUG_FUNCPTR (gst_srtp_dec_iterate_internal_links_rtcp));
410
411 gst_pad_set_element_private (filter->rtcp_sinkpad, filter->rtcp_srcpad);
412 gst_pad_set_element_private (filter->rtcp_srcpad, filter->rtcp_sinkpad);
413
414 gst_element_add_pad (GST_ELEMENT (filter), filter->rtcp_sinkpad);
415 gst_element_add_pad (GST_ELEMENT (filter), filter->rtcp_srcpad);
416
417 filter->first_session = TRUE;
418
419 #ifndef HAVE_SRTP2
420 filter->roc_changed = FALSE;
421 #endif
422 }
423
424 static GstStructure *
gst_srtp_dec_create_stats(GstSrtpDec * filter)425 gst_srtp_dec_create_stats (GstSrtpDec * filter)
426 {
427 GstStructure *s;
428 GValue va = G_VALUE_INIT;
429 GValue v = G_VALUE_INIT;
430
431 s = gst_structure_new_empty ("application/x-srtp-decoder-stats");
432
433 g_value_init (&va, GST_TYPE_ARRAY);
434 g_value_init (&v, GST_TYPE_STRUCTURE);
435
436 if (filter->session) {
437 GHashTableIter iter;
438 gpointer key;
439
440 g_hash_table_iter_init (&iter, filter->streams);
441 while (g_hash_table_iter_next (&iter, &key, NULL)) {
442 GstStructure *ss;
443 guint32 ssrc = GPOINTER_TO_UINT (key);
444 srtp_err_status_t status;
445 guint32 roc;
446
447 status = srtp_get_stream_roc (filter->session, ssrc, &roc);
448 if (status != srtp_err_status_ok) {
449 continue;
450 }
451
452 ss = gst_structure_new ("application/x-srtp-stream",
453 "ssrc", G_TYPE_UINT, ssrc, "roc", G_TYPE_UINT, roc, NULL);
454
455 g_value_take_boxed (&v, ss);
456 gst_value_array_append_value (&va, &v);
457 }
458 }
459
460 gst_structure_take_value (s, "streams", &va);
461 g_value_unset (&v);
462
463 return s;
464 }
465
466 static void
gst_srtp_dec_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)467 gst_srtp_dec_set_property (GObject * object, guint prop_id,
468 const GValue * value, GParamSpec * pspec)
469 {
470 GstSrtpDec *filter = GST_SRTP_DEC (object);
471
472 GST_OBJECT_LOCK (filter);
473
474 switch (prop_id) {
475 case PROP_REPLAY_WINDOW_SIZE:
476 filter->replay_window_size = g_value_get_uint (value);
477 break;
478 default:
479 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
480 break;
481 }
482
483 GST_OBJECT_UNLOCK (filter);
484 }
485
486 static void
gst_srtp_dec_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)487 gst_srtp_dec_get_property (GObject * object, guint prop_id,
488 GValue * value, GParamSpec * pspec)
489 {
490 GstSrtpDec *filter = GST_SRTP_DEC (object);
491
492 GST_OBJECT_LOCK (filter);
493
494 switch (prop_id) {
495 case PROP_REPLAY_WINDOW_SIZE:
496 g_value_set_uint (value, filter->replay_window_size);
497 break;
498 case PROP_STATS:
499 g_value_take_boxed (value, gst_srtp_dec_create_stats (filter));
500 break;
501 default:
502 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
503 break;
504 }
505
506 GST_OBJECT_UNLOCK (filter);
507 }
508
509 static void
gst_srtp_dec_remove_stream(GstSrtpDec * filter,guint ssrc)510 gst_srtp_dec_remove_stream (GstSrtpDec * filter, guint ssrc)
511 {
512 GstSrtpDecSsrcStream *stream = NULL;
513
514 if (filter->streams == NULL)
515 return;
516
517 stream = g_hash_table_lookup (filter->streams, GUINT_TO_POINTER (ssrc));
518
519 if (stream) {
520 srtp_remove_stream (filter->session, ssrc);
521 g_hash_table_remove (filter->streams, GUINT_TO_POINTER (ssrc));
522 }
523 }
524
525 static GstSrtpDecSsrcStream *
find_stream_by_ssrc(GstSrtpDec * filter,guint32 ssrc)526 find_stream_by_ssrc (GstSrtpDec * filter, guint32 ssrc)
527 {
528 return g_hash_table_lookup (filter->streams, GUINT_TO_POINTER (ssrc));
529 }
530
531 #ifdef HAVE_SRTP2
532 static void
clear_key(gpointer data)533 clear_key (gpointer data)
534 {
535 struct GstSrtpDecKey *key = data;
536
537 gst_clear_buffer (&key->mki);
538 gst_clear_buffer (&key->key);
539 }
540 #endif
541
542
543 /* get info from buffer caps
544 */
545 static GstSrtpDecSsrcStream *
get_stream_from_caps(GstSrtpDec * filter,GstCaps * caps,guint32 ssrc)546 get_stream_from_caps (GstSrtpDec * filter, GstCaps * caps, guint32 ssrc)
547 {
548 GstSrtpDecSsrcStream *stream;
549 GstStructure *s;
550 GstBuffer *buf;
551 const gchar *rtp_cipher, *rtp_auth, *rtcp_cipher, *rtcp_auth;
552
553 /* Create new stream structure and set default values */
554 stream = g_slice_new0 (GstSrtpDecSsrcStream);
555 stream->ssrc = ssrc;
556 stream->key = NULL;
557
558 /* Get info from caps */
559 s = gst_caps_get_structure (caps, 0);
560 if (!s)
561 goto error;
562
563 rtp_cipher = gst_structure_get_string (s, "srtp-cipher");
564 rtp_auth = gst_structure_get_string (s, "srtp-auth");
565 rtcp_cipher = gst_structure_get_string (s, "srtcp-cipher");
566 rtcp_auth = gst_structure_get_string (s, "srtcp-auth");
567 if (!rtp_cipher || !rtp_auth || !rtcp_cipher || !rtcp_auth)
568 goto error;
569
570 gst_structure_get_uint (s, "roc", &stream->roc);
571
572 stream->rtp_cipher = enum_value_from_nick (GST_TYPE_SRTP_CIPHER_TYPE,
573 rtp_cipher);
574 stream->rtp_auth = enum_value_from_nick (GST_TYPE_SRTP_AUTH_TYPE, rtp_auth);
575 stream->rtcp_cipher = enum_value_from_nick (GST_TYPE_SRTP_CIPHER_TYPE,
576 rtcp_cipher);
577 stream->rtcp_auth = enum_value_from_nick (GST_TYPE_SRTP_AUTH_TYPE, rtcp_auth);
578
579 if ((gint) stream->rtp_cipher == -1 || (gint) stream->rtp_auth == -1 ||
580 (gint) stream->rtcp_cipher == -1 || (gint) stream->rtcp_auth == -1) {
581 GST_WARNING_OBJECT (filter, "Invalid caps for stream,"
582 " unknown cipher or auth type");
583 goto error;
584 }
585
586 /* RFC 3711 says in "3. SRTP Framework" that SRTCP message authentication
587 * is MANDATORY. In case of GCM let the pipeline handle any errors.
588 */
589 if (stream->rtcp_cipher != GST_SRTP_CIPHER_AES_128_GCM
590 && stream->rtcp_cipher != GST_SRTP_CIPHER_AES_256_GCM
591 && stream->rtcp_cipher != GST_SRTP_CIPHER_NULL
592 && stream->rtcp_auth == GST_SRTP_AUTH_NULL) {
593 GST_WARNING_OBJECT (filter,
594 "Cannot have SRTP NULL authentication with a not-NULL encryption"
595 " cipher.");
596 goto error;
597 }
598
599 if (gst_structure_get (s, "srtp-key", GST_TYPE_BUFFER, &buf, NULL) || !buf) {
600 #ifdef HAVE_SRTP2
601 GstBuffer *mki = NULL;
602 guint i;
603 gsize mki_size = 0;
604 #endif
605
606 GST_DEBUG_OBJECT (filter, "Got key [%p] for SSRC %u", buf, ssrc);
607
608 #ifdef HAVE_SRTP2
609 if (gst_structure_get (s, "mki", GST_TYPE_BUFFER, &mki, NULL) && mki) {
610 struct GstSrtpDecKey key = {.mki = mki,.key = buf };
611
612 mki_size = gst_buffer_get_size (mki);
613 if (mki_size > SRTP_MAX_MKI_LEN) {
614 GST_WARNING_OBJECT (filter, "MKI is longer than allowed (%zu > %d).",
615 mki_size, SRTP_MAX_MKI_LEN);
616 gst_buffer_unref (mki);
617 gst_buffer_unref (buf);
618 goto error;
619 }
620
621 stream->keys =
622 g_array_sized_new (FALSE, TRUE, sizeof (struct GstSrtpDecKey), 2);
623 g_array_set_clear_func (stream->keys, clear_key);
624
625 g_array_append_val (stream->keys, key);
626
627 /* Append more MKIs */
628 for (i = 1; i < SRTP_MAX_NUM_MASTER_KEYS; i++) {
629 char mki_id[16];
630 char key_id[16];
631 g_snprintf (mki_id, 16, "mki%d", i + 1);
632 g_snprintf (key_id, 16, "srtp-key%d", i + 1);
633
634 if (gst_structure_get (s, mki_id, GST_TYPE_BUFFER, &mki,
635 key_id, GST_TYPE_BUFFER, &buf, NULL)) {
636 if (gst_buffer_get_size (mki) != mki_size) {
637 GST_WARNING_OBJECT (filter,
638 "MKIs need to all have the same size (first was %zu,"
639 " current is %zu).", mki_size, gst_buffer_get_size (mki));
640 gst_buffer_unref (mki);
641 gst_buffer_unref (buf);
642 goto error;
643 }
644 key.mki = mki;
645 key.key = buf;
646 g_array_append_val (stream->keys, key);
647 } else {
648 break;
649 }
650 }
651 } else
652 #endif
653 {
654 stream->key = buf;
655 }
656 } else if (STREAM_HAS_CRYPTO (stream)) {
657 goto error;
658 }
659
660 return stream;
661
662 error:
663 g_slice_free (GstSrtpDecSsrcStream, stream);
664 return NULL;
665 }
666
667 /* Get SRTP params by signal
668 */
669 static GstCaps *
signal_get_srtp_params(GstSrtpDec * filter,guint32 ssrc,gint signal)670 signal_get_srtp_params (GstSrtpDec * filter, guint32 ssrc, gint signal)
671 {
672 GstCaps *caps = NULL;
673
674 g_signal_emit (filter, gst_srtp_dec_signals[signal], 0, ssrc, &caps);
675
676 if (caps != NULL)
677 GST_DEBUG_OBJECT (filter, "Caps received");
678
679 return caps;
680 }
681
682 /* Create a stream in the session
683 */
684 static srtp_err_status_t
init_session_stream(GstSrtpDec * filter,guint32 ssrc,GstSrtpDecSsrcStream * stream)685 init_session_stream (GstSrtpDec * filter, guint32 ssrc,
686 GstSrtpDecSsrcStream * stream)
687 {
688 srtp_err_status_t ret;
689 srtp_policy_t policy;
690 GstMapInfo map;
691 guchar tmp[1];
692 #ifdef HAVE_SRTP2
693 GstMapInfo *key_maps = NULL;
694 GstMapInfo *mki_maps = NULL;
695 #endif
696
697 memset (&policy, 0, sizeof (srtp_policy_t));
698
699 if (!stream)
700 return srtp_err_status_bad_param;
701
702 GST_INFO_OBJECT (filter, "Setting RTP policy...");
703 set_crypto_policy_cipher_auth (stream->rtp_cipher, stream->rtp_auth,
704 &policy.rtp);
705 GST_INFO_OBJECT (filter, "Setting RTCP policy...");
706 set_crypto_policy_cipher_auth (stream->rtcp_cipher, stream->rtcp_auth,
707 &policy.rtcp);
708
709 #ifdef HAVE_SRTP2
710 if (stream->keys) {
711 guint i;
712 srtp_master_key_t *keys;
713
714 keys = g_alloca (sizeof (srtp_master_key_t) * stream->keys->len);
715 policy.keys = g_alloca (sizeof (gpointer) * stream->keys->len);
716 key_maps = g_alloca (sizeof (GstMapInfo) * stream->keys->len);
717 mki_maps = g_alloca (sizeof (GstMapInfo) * stream->keys->len);
718
719 for (i = 0; i < stream->keys->len; i++) {
720 struct GstSrtpDecKey *key =
721 &g_array_index (stream->keys, struct GstSrtpDecKey, i);
722 policy.keys[i] = &keys[i];
723
724 gst_buffer_map (key->mki, &mki_maps[i], GST_MAP_READ);
725 gst_buffer_map (key->key, &key_maps[i], GST_MAP_READ);
726
727 policy.keys[i]->key = (guchar *) key_maps[i].data;
728 policy.keys[i]->mki_id = (guchar *) mki_maps[i].data;
729 policy.keys[i]->mki_size = mki_maps[i].size;
730 }
731 policy.num_master_keys = stream->keys->len;
732 } else
733 #endif
734 if (stream->key) {
735 gst_buffer_map (stream->key, &map, GST_MAP_READ);
736 policy.key = (guchar *) map.data;
737 } else {
738 policy.key = tmp;
739 }
740
741 policy.ssrc.value = ssrc;
742 policy.ssrc.type = ssrc_specific;
743 policy.window_size = filter->replay_window_size;
744 policy.next = NULL;
745
746 /* If it is the first stream, create the session
747 * If not, add the stream policy to the session
748 */
749 if (filter->first_session)
750 ret = srtp_create (&filter->session, &policy);
751 else
752 ret = srtp_add_stream (filter->session, &policy);
753
754 if (stream->key)
755 gst_buffer_unmap (stream->key, &map);
756
757 #ifdef HAVE_SRTP2
758 if (key_maps) {
759 guint i;
760
761 for (i = 0; i < stream->keys->len; i++) {
762 struct GstSrtpDecKey *key = &g_array_index (stream->keys,
763 struct GstSrtpDecKey, i);
764 gst_buffer_unmap (key->mki, &mki_maps[i]);
765 gst_buffer_unmap (key->key, &key_maps[i]);
766 }
767
768 }
769 #endif
770
771 if (ret == srtp_err_status_ok) {
772 srtp_err_status_t status;
773
774 status = srtp_set_stream_roc (filter->session, ssrc, stream->roc);
775 #ifdef HAVE_SRTP2
776 (void) status; /* Ignore unused variable */
777 #else
778 if (status == srtp_err_status_ok) {
779 /* Here, we just set the ROC, but we also need to set the initial
780 * RTP sequence number later, otherwise libsrtp will not be able
781 * to get the right packet index. */
782 filter->roc_changed = TRUE;
783 }
784 #endif
785
786 filter->first_session = FALSE;
787 g_hash_table_insert (filter->streams, GUINT_TO_POINTER (stream->ssrc),
788 stream);
789 }
790
791 return ret;
792 }
793
794 /* Return a stream structure for a given buffer
795 */
796 static GstSrtpDecSsrcStream *
validate_buffer(GstSrtpDec * filter,GstBuffer * buf,guint32 * ssrc,gboolean * is_rtcp)797 validate_buffer (GstSrtpDec * filter, GstBuffer * buf, guint32 * ssrc,
798 gboolean * is_rtcp)
799 {
800 GstSrtpDecSsrcStream *stream = NULL;
801 GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
802
803 if (gst_rtp_buffer_map (buf,
804 GST_MAP_READ | GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING, &rtpbuf)) {
805 if (gst_rtp_buffer_get_payload_type (&rtpbuf) < 64
806 || gst_rtp_buffer_get_payload_type (&rtpbuf) > 80) {
807 *ssrc = gst_rtp_buffer_get_ssrc (&rtpbuf);
808
809 gst_rtp_buffer_unmap (&rtpbuf);
810 *is_rtcp = FALSE;
811 goto have_ssrc;
812 }
813 gst_rtp_buffer_unmap (&rtpbuf);
814 }
815
816 if (rtcp_buffer_get_ssrc (buf, ssrc)) {
817 *is_rtcp = TRUE;
818 } else {
819 GST_WARNING_OBJECT (filter, "No SSRC found in buffer");
820 return NULL;
821 }
822
823 have_ssrc:
824
825 stream = find_stream_by_ssrc (filter, *ssrc);
826
827 if (stream)
828 return stream;
829
830 return request_key_with_signal (filter, *ssrc, SIGNAL_REQUEST_KEY);
831 }
832
833 static void
free_stream(GstSrtpDecSsrcStream * stream)834 free_stream (GstSrtpDecSsrcStream * stream)
835 {
836 if (stream->key)
837 gst_buffer_unref (stream->key);
838 if (stream->keys)
839 g_array_free (stream->keys, TRUE);
840 g_slice_free (GstSrtpDecSsrcStream, stream);
841 }
842
843 static gboolean
buffers_are_equal(GstBuffer * a,GstBuffer * b)844 buffers_are_equal (GstBuffer * a, GstBuffer * b)
845 {
846 GstMapInfo info;
847
848 if (a == b)
849 return TRUE;
850
851 if (a == NULL || b == NULL)
852 return FALSE;
853
854 if (gst_buffer_get_size (a) != gst_buffer_get_size (b))
855 return FALSE;
856
857 if (gst_buffer_map (a, &info, GST_MAP_READ)) {
858 gboolean equal;
859
860 equal = (gst_buffer_memcmp (b, 0, info.data, info.size) == 0);
861 gst_buffer_unmap (a, &info);
862
863 return equal;
864 } else {
865 return FALSE;
866 }
867 }
868
869 static gboolean
keys_are_equal(GArray * a,GArray * b)870 keys_are_equal (GArray * a, GArray * b)
871 {
872 #ifdef HAVE_SRTP2
873 guint i;
874
875 if (a == b)
876 return TRUE;
877
878 if (a == NULL || b == NULL)
879 return FALSE;
880
881 if (a->len != b->len)
882 return FALSE;
883
884 for (i = 0; i < a->len; i++) {
885 struct GstSrtpDecKey *key_a = &g_array_index (a,
886 struct GstSrtpDecKey, i);
887 struct GstSrtpDecKey *key_b = &g_array_index (b,
888 struct GstSrtpDecKey, i);
889
890 if (!buffers_are_equal (key_a->mki, key_b->mki))
891 return FALSE;
892
893 if (!buffers_are_equal (key_a->key, key_b->key))
894 return FALSE;
895 }
896
897 return TRUE;
898 #else
899 return FALSE;
900 #endif
901 }
902
903 /* Create new stream from params in caps
904 */
905 static GstSrtpDecSsrcStream *
update_session_stream_from_caps(GstSrtpDec * filter,guint32 ssrc,GstCaps * caps)906 update_session_stream_from_caps (GstSrtpDec * filter, guint32 ssrc,
907 GstCaps * caps)
908 {
909 GstSrtpDecSsrcStream *stream = NULL;
910 GstSrtpDecSsrcStream *old_stream = NULL;
911 srtp_err_status_t err;
912
913 g_return_val_if_fail (GST_IS_SRTP_DEC (filter), NULL);
914 g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
915
916 stream = get_stream_from_caps (filter, caps, ssrc);
917
918 old_stream = find_stream_by_ssrc (filter, ssrc);
919 if (stream && old_stream &&
920 stream->rtp_cipher == old_stream->rtp_cipher &&
921 stream->rtcp_cipher == old_stream->rtcp_cipher &&
922 stream->rtp_auth == old_stream->rtp_auth &&
923 stream->rtcp_auth == old_stream->rtcp_auth &&
924 ((stream->keys && keys_are_equal (stream->keys, old_stream->keys)) ||
925 buffers_are_equal (stream->key, old_stream->key))) {
926 free_stream (stream);
927 return old_stream;
928 }
929
930 /* Remove existing stream, if any */
931 gst_srtp_dec_remove_stream (filter, ssrc);
932
933 if (stream) {
934 /* Create new session stream */
935 err = init_session_stream (filter, ssrc, stream);
936
937 if (err != srtp_err_status_ok) {
938 GST_WARNING_OBJECT (filter, "Failed to create the stream (err: %d)", err);
939 if (stream->key)
940 gst_buffer_unref (stream->key);
941 g_slice_free (GstSrtpDecSsrcStream, stream);
942 stream = NULL;
943 }
944 }
945
946 return stream;
947 }
948
949 static gboolean
remove_yes(gpointer key,gpointer value,gpointer user_data)950 remove_yes (gpointer key, gpointer value, gpointer user_data)
951 {
952 return TRUE;
953 }
954
955 /* Clear the policy list
956 */
957 static void
gst_srtp_dec_clear_streams(GstSrtpDec * filter)958 gst_srtp_dec_clear_streams (GstSrtpDec * filter)
959 {
960 guint nb = 0;
961
962 GST_OBJECT_LOCK (filter);
963
964 if (!filter->first_session) {
965 srtp_dealloc (filter->session);
966 filter->session = NULL;
967 }
968
969 if (filter->streams)
970 nb = g_hash_table_foreach_remove (filter->streams, remove_yes, NULL);
971
972 filter->first_session = TRUE;
973
974 GST_OBJECT_UNLOCK (filter);
975
976 GST_DEBUG_OBJECT (filter, "Cleared %d streams", nb);
977 }
978
979 /* Send a signal
980 */
981 static GstSrtpDecSsrcStream *
request_key_with_signal(GstSrtpDec * filter,guint32 ssrc,gint signal)982 request_key_with_signal (GstSrtpDec * filter, guint32 ssrc, gint signal)
983 {
984 GstCaps *caps;
985 GstSrtpDecSsrcStream *stream = NULL;
986
987 caps = signal_get_srtp_params (filter, ssrc, signal);
988
989 if (caps) {
990 stream = update_session_stream_from_caps (filter, ssrc, caps);
991 if (stream)
992 GST_DEBUG_OBJECT (filter, "New stream set with SSRC %u", ssrc);
993 else
994 GST_WARNING_OBJECT (filter, "Could not set stream with SSRC %u", ssrc);
995 gst_caps_unref (caps);
996 } else {
997 GST_WARNING_OBJECT (filter, "Could not get caps for stream with SSRC %u",
998 ssrc);
999 }
1000
1001 return stream;
1002 }
1003
1004 static gboolean
gst_srtp_dec_sink_setcaps(GstPad * pad,GstObject * parent,GstCaps * caps,gboolean is_rtcp)1005 gst_srtp_dec_sink_setcaps (GstPad * pad, GstObject * parent,
1006 GstCaps * caps, gboolean is_rtcp)
1007 {
1008 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1009 GstPad *otherpad;
1010 GstStructure *ps;
1011 gboolean ret = FALSE;
1012
1013 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
1014
1015 ps = gst_caps_get_structure (caps, 0);
1016
1017 if (gst_structure_has_field_typed (ps, "ssrc", G_TYPE_UINT) &&
1018 gst_structure_has_field_typed (ps, "srtp-cipher", G_TYPE_STRING) &&
1019 gst_structure_has_field_typed (ps, "srtp-auth", G_TYPE_STRING) &&
1020 gst_structure_has_field_typed (ps, "srtcp-cipher", G_TYPE_STRING) &&
1021 gst_structure_has_field_typed (ps, "srtcp-auth", G_TYPE_STRING)) {
1022 guint ssrc;
1023
1024 gst_structure_get_uint (ps, "ssrc", &ssrc);
1025
1026 if (!update_session_stream_from_caps (filter, ssrc, caps)) {
1027 GST_WARNING_OBJECT (pad, "Could not create session from pad caps: %"
1028 GST_PTR_FORMAT, caps);
1029 return FALSE;
1030 }
1031 }
1032
1033 caps = gst_caps_copy (caps);
1034 ps = gst_caps_get_structure (caps, 0);
1035 gst_structure_remove_fields (ps, "srtp-key", "srtp-cipher", "srtp-auth",
1036 "srtcp-cipher", "srtcp-auth", "mki", NULL);
1037
1038 if (is_rtcp)
1039 gst_structure_set_name (ps, "application/x-rtcp");
1040 else
1041 gst_structure_set_name (ps, "application/x-rtp");
1042
1043 otherpad = gst_pad_get_element_private (pad);
1044
1045 ret = gst_pad_set_caps (otherpad, caps);
1046
1047 gst_caps_unref (caps);
1048
1049 return ret;
1050 }
1051
1052 static gboolean
gst_srtp_dec_sink_event_rtp(GstPad * pad,GstObject * parent,GstEvent * event)1053 gst_srtp_dec_sink_event_rtp (GstPad * pad, GstObject * parent, GstEvent * event)
1054 {
1055 gboolean ret;
1056 GstCaps *caps;
1057 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1058
1059 switch (GST_EVENT_TYPE (event)) {
1060 case GST_EVENT_CAPS:
1061 gst_event_parse_caps (event, &caps);
1062 ret = gst_srtp_dec_sink_setcaps (pad, parent, caps, FALSE);
1063 gst_event_unref (event);
1064 return ret;
1065 case GST_EVENT_SEGMENT:
1066 /* Make sure to send a caps event downstream before the segment event,
1067 * even if upstream didn't */
1068 if (!gst_pad_has_current_caps (filter->rtp_srcpad)) {
1069 GstCaps *caps = gst_caps_new_empty_simple ("application/x-rtp");
1070
1071 gst_pad_set_caps (filter->rtp_srcpad, caps);
1072 gst_caps_unref (caps);
1073 }
1074 filter->rtp_has_segment = TRUE;
1075 break;
1076 case GST_EVENT_FLUSH_STOP:
1077 filter->rtp_has_segment = FALSE;
1078 break;
1079 default:
1080 break;
1081 }
1082
1083 return gst_pad_event_default (pad, parent, event);
1084 }
1085
1086 static gboolean
gst_srtp_dec_sink_event_rtcp(GstPad * pad,GstObject * parent,GstEvent * event)1087 gst_srtp_dec_sink_event_rtcp (GstPad * pad, GstObject * parent,
1088 GstEvent * event)
1089 {
1090 gboolean ret;
1091 GstCaps *caps;
1092 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1093
1094 switch (GST_EVENT_TYPE (event)) {
1095 case GST_EVENT_CAPS:
1096 gst_event_parse_caps (event, &caps);
1097 ret = gst_srtp_dec_sink_setcaps (pad, parent, caps, TRUE);
1098 gst_event_unref (event);
1099 return ret;
1100 case GST_EVENT_SEGMENT:
1101 /* Make sure to send a caps event downstream before the segment event,
1102 * even if upstream didn't */
1103 if (!gst_pad_has_current_caps (filter->rtcp_srcpad)) {
1104 GstCaps *caps = gst_caps_new_empty_simple ("application/x-rtcp");
1105
1106 gst_pad_set_caps (filter->rtcp_srcpad, caps);
1107 gst_caps_unref (caps);
1108 }
1109 filter->rtcp_has_segment = TRUE;
1110 break;
1111 case GST_EVENT_FLUSH_STOP:
1112 filter->rtcp_has_segment = FALSE;
1113 break;
1114 default:
1115 break;
1116 }
1117
1118 return gst_pad_event_default (pad, parent, event);
1119 }
1120
1121 static gboolean
gst_srtp_dec_sink_query(GstPad * pad,GstObject * parent,GstQuery * query,gboolean is_rtcp)1122 gst_srtp_dec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query,
1123 gboolean is_rtcp)
1124 {
1125 switch (GST_QUERY_TYPE (query)) {
1126 case GST_QUERY_CAPS:
1127 {
1128 GstCaps *filter = NULL;
1129 GstCaps *other_filter = NULL;
1130 GstCaps *template_caps;
1131 GstPad *otherpad;
1132 GstCaps *other_caps;
1133 GstCaps *ret;
1134 int i;
1135
1136 gst_query_parse_caps (query, &filter);
1137
1138 otherpad = (GstPad *) gst_pad_get_element_private (pad);
1139
1140 if (filter) {
1141 other_filter = gst_caps_copy (filter);
1142
1143 for (i = 0; i < gst_caps_get_size (other_filter); i++) {
1144 GstStructure *ps = gst_caps_get_structure (other_filter, i);
1145 if (is_rtcp)
1146 gst_structure_set_name (ps, "application/x-rtcp");
1147 else
1148 gst_structure_set_name (ps, "application/x-rtp");
1149 gst_structure_remove_fields (ps, "srtp-key", "srtp-cipher",
1150 "srtp-auth", "srtcp-cipher", "srtcp-auth", "mki", NULL);
1151 }
1152 }
1153
1154
1155 other_caps = gst_pad_peer_query_caps (otherpad, other_filter);
1156 if (other_filter)
1157 gst_caps_unref (other_filter);
1158 if (!other_caps) {
1159 goto return_template;
1160 }
1161
1162 template_caps = gst_pad_get_pad_template_caps (otherpad);
1163 ret = gst_caps_intersect_full (other_caps, template_caps,
1164 GST_CAPS_INTERSECT_FIRST);
1165 gst_caps_unref (other_caps);
1166 gst_caps_unref (template_caps);
1167
1168 ret = gst_caps_make_writable (ret);
1169
1170 for (i = 0; i < gst_caps_get_size (ret); i++) {
1171 GstStructure *ps = gst_caps_get_structure (ret, i);
1172 if (is_rtcp)
1173 gst_structure_set_name (ps, "application/x-srtcp");
1174 else
1175 gst_structure_set_name (ps, "application/x-srtp");
1176 }
1177
1178 if (filter) {
1179 GstCaps *tmp;
1180
1181 tmp = gst_caps_intersect (ret, filter);
1182 gst_caps_unref (ret);
1183 ret = tmp;
1184 }
1185
1186 gst_query_set_caps_result (query, ret);
1187 gst_caps_unref (ret);
1188 return TRUE;
1189
1190 return_template:
1191
1192 ret = gst_pad_get_pad_template_caps (pad);
1193 gst_query_set_caps_result (query, ret);
1194 gst_caps_unref (ret);
1195 return TRUE;
1196 }
1197 default:
1198 return gst_pad_query_default (pad, parent, query);
1199 }
1200 }
1201
1202 static gboolean
gst_srtp_dec_sink_query_rtp(GstPad * pad,GstObject * parent,GstQuery * query)1203 gst_srtp_dec_sink_query_rtp (GstPad * pad, GstObject * parent, GstQuery * query)
1204 {
1205 return gst_srtp_dec_sink_query (pad, parent, query, FALSE);
1206 }
1207
1208 static gboolean
gst_srtp_dec_sink_query_rtcp(GstPad * pad,GstObject * parent,GstQuery * query)1209 gst_srtp_dec_sink_query_rtcp (GstPad * pad, GstObject * parent,
1210 GstQuery * query)
1211 {
1212 return gst_srtp_dec_sink_query (pad, parent, query, TRUE);
1213 }
1214
1215 static GstIterator *
gst_srtp_dec_iterate_internal_links(GstPad * pad,GstObject * parent,gboolean is_rtcp)1216 gst_srtp_dec_iterate_internal_links (GstPad * pad, GstObject * parent,
1217 gboolean is_rtcp)
1218 {
1219 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1220 GstPad *otherpad = NULL;
1221 GstIterator *it = NULL;
1222
1223 otherpad = (GstPad *) gst_pad_get_element_private (pad);
1224
1225 if (otherpad) {
1226 GValue val = { 0 };
1227
1228 g_value_init (&val, GST_TYPE_PAD);
1229 g_value_set_object (&val, otherpad);
1230 it = gst_iterator_new_single (GST_TYPE_PAD, &val);
1231 g_value_unset (&val);
1232 } else {
1233 GST_ELEMENT_ERROR (GST_ELEMENT_CAST (filter), CORE, PAD, (NULL),
1234 ("Unable to get linked pad"));
1235 }
1236
1237 return it;
1238 }
1239
1240 static GstIterator *
gst_srtp_dec_iterate_internal_links_rtp(GstPad * pad,GstObject * parent)1241 gst_srtp_dec_iterate_internal_links_rtp (GstPad * pad, GstObject * parent)
1242 {
1243 return gst_srtp_dec_iterate_internal_links (pad, parent, FALSE);
1244 }
1245
1246 static GstIterator *
gst_srtp_dec_iterate_internal_links_rtcp(GstPad * pad,GstObject * parent)1247 gst_srtp_dec_iterate_internal_links_rtcp (GstPad * pad, GstObject * parent)
1248 {
1249 return gst_srtp_dec_iterate_internal_links (pad, parent, TRUE);
1250 }
1251
1252 static void
gst_srtp_dec_push_early_events(GstSrtpDec * filter,GstPad * pad,GstPad * otherpad,gboolean is_rtcp)1253 gst_srtp_dec_push_early_events (GstSrtpDec * filter, GstPad * pad,
1254 GstPad * otherpad, gboolean is_rtcp)
1255 {
1256 GstEvent *otherev, *ev;
1257
1258 ev = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0);
1259 if (ev) {
1260 gst_event_unref (ev);
1261 } else {
1262 gchar *new_stream_id;
1263
1264 otherev = gst_pad_get_sticky_event (otherpad, GST_EVENT_STREAM_START, 0);
1265
1266 if (otherev) {
1267 const gchar *other_stream_id;
1268
1269 gst_event_parse_stream_start (otherev, &other_stream_id);
1270
1271 new_stream_id = g_strdup_printf ("%s/%s", other_stream_id,
1272 is_rtcp ? "rtcp" : "rtp");
1273 gst_event_unref (otherev);
1274 } else {
1275 new_stream_id = gst_pad_create_stream_id (pad, GST_ELEMENT (filter),
1276 is_rtcp ? "rtcp" : "rtp");
1277 }
1278
1279 ev = gst_event_new_stream_start (new_stream_id);
1280 g_free (new_stream_id);
1281
1282 gst_pad_push_event (pad, ev);
1283 }
1284
1285 ev = gst_pad_get_sticky_event (pad, GST_EVENT_CAPS, 0);
1286 if (ev) {
1287 gst_event_unref (ev);
1288 } else {
1289 GstCaps *caps;
1290
1291 if (is_rtcp)
1292 caps = gst_caps_new_empty_simple ("application/x-rtcp");
1293 else
1294 caps = gst_caps_new_empty_simple ("application/x-rtp");
1295
1296 gst_pad_set_caps (pad, caps);
1297 gst_caps_unref (caps);
1298 }
1299
1300 ev = gst_pad_get_sticky_event (pad, GST_EVENT_SEGMENT, 0);
1301 if (ev) {
1302 gst_event_unref (ev);
1303 } else {
1304 ev = gst_pad_get_sticky_event (otherpad, GST_EVENT_SEGMENT, 0);
1305
1306 if (ev)
1307 gst_pad_push_event (pad, ev);
1308 }
1309
1310 if (is_rtcp)
1311 filter->rtcp_has_segment = TRUE;
1312 else
1313 filter->rtp_has_segment = TRUE;
1314
1315 }
1316
1317 /*
1318 * This function should be called while holding the filter lock
1319 */
1320 static gboolean
gst_srtp_dec_decode_buffer(GstSrtpDec * filter,GstPad * pad,GstBuffer * buf,gboolean is_rtcp,guint32 ssrc)1321 gst_srtp_dec_decode_buffer (GstSrtpDec * filter, GstPad * pad, GstBuffer * buf,
1322 gboolean is_rtcp, guint32 ssrc)
1323 {
1324 GstMapInfo map;
1325 srtp_err_status_t err;
1326 gint size;
1327
1328 GST_LOG_OBJECT (pad, "Received %s buffer of size %" G_GSIZE_FORMAT
1329 " with SSRC = %u", is_rtcp ? "RTCP" : "RTP", gst_buffer_get_size (buf),
1330 ssrc);
1331
1332 /* Change buffer to remove protection */
1333 buf = gst_buffer_make_writable (buf);
1334
1335 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
1336 size = map.size;
1337
1338 unprotect:
1339
1340 gst_srtp_init_event_reporter ();
1341
1342 if (is_rtcp) {
1343 #ifdef HAVE_SRTP2
1344 GstSrtpDecSsrcStream *stream = find_stream_by_ssrc (filter, ssrc);
1345
1346 err = srtp_unprotect_rtcp_mki (filter->session, map.data, &size,
1347 stream && stream->keys);
1348 #else
1349 err = srtp_unprotect_rtcp (filter->session, map.data, &size);
1350 #endif
1351 } else {
1352 #ifndef HAVE_SRTP2
1353 /* If ROC has changed, we know we need to set the initial RTP
1354 * sequence number too. */
1355 if (filter->roc_changed) {
1356 srtp_stream_t stream;
1357
1358 stream = srtp_get_stream (filter->session, htonl (ssrc));
1359
1360 if (stream) {
1361 guint16 seqnum = 0;
1362 GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
1363
1364 gst_rtp_buffer_map (buf,
1365 GST_MAP_READ | GST_RTP_BUFFER_MAP_FLAG_SKIP_PADDING, &rtpbuf);
1366 seqnum = gst_rtp_buffer_get_seq (&rtpbuf);
1367 gst_rtp_buffer_unmap (&rtpbuf);
1368
1369 /* We finally add the RTP sequence number to the current
1370 * rollover counter. */
1371 stream->rtp_rdbx.index &= ~0xFFFF;
1372 stream->rtp_rdbx.index |= seqnum;
1373 }
1374
1375 filter->roc_changed = FALSE;
1376 }
1377 #endif
1378
1379 #ifdef HAVE_SRTP2
1380 {
1381 GstSrtpDecSsrcStream *stream = find_stream_by_ssrc (filter, ssrc);
1382
1383 err = srtp_unprotect_mki (filter->session, map.data, &size,
1384 stream && stream->keys);
1385 }
1386 #else
1387 err = srtp_unprotect (filter->session, map.data, &size);
1388 #endif
1389 }
1390
1391 /* Signal user depending on type of error */
1392 switch (err) {
1393 case srtp_err_status_ok:
1394 /* success! */
1395 break;
1396 case srtp_err_status_replay_fail:
1397 GST_INFO_OBJECT (filter,
1398 "Dropping replayed packet, probably retransmission");
1399 goto err;
1400 case srtp_err_status_key_expired:{
1401 GstSrtpDecSsrcStream *stream;
1402
1403 /* Check we have an existing stream to rekey */
1404 stream = find_stream_by_ssrc (filter, ssrc);
1405 if (stream == NULL) {
1406 GST_WARNING_OBJECT (filter, "Could not find matching stream, dropping");
1407 goto err;
1408 }
1409
1410 GST_OBJECT_UNLOCK (filter);
1411 stream = request_key_with_signal (filter, ssrc, SIGNAL_HARD_LIMIT);
1412 GST_OBJECT_LOCK (filter);
1413
1414 /* Check the key request created a new stream */
1415 if (stream == NULL) {
1416 GST_WARNING_OBJECT (filter, "Hard limit reached, no new key, dropping");
1417 goto err;
1418 }
1419
1420 goto unprotect;
1421 }
1422 case srtp_err_status_auth_fail:
1423 GST_WARNING_OBJECT (filter, "Error authentication packet, dropping");
1424 goto err;
1425 case srtp_err_status_cipher_fail:
1426 GST_WARNING_OBJECT (filter, "Error while decrypting packet, dropping");
1427 goto err;
1428 default:
1429 GST_WARNING_OBJECT (pad,
1430 "Unable to unprotect buffer (unprotect failed code %d)", err);
1431 goto err;
1432 }
1433
1434 gst_buffer_unmap (buf, &map);
1435 gst_buffer_set_size (buf, size);
1436 return TRUE;
1437
1438 err:
1439 gst_buffer_unmap (buf, &map);
1440 return FALSE;
1441 }
1442
1443 static GstFlowReturn
gst_srtp_dec_chain(GstPad * pad,GstObject * parent,GstBuffer * buf,gboolean is_rtcp)1444 gst_srtp_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf,
1445 gboolean is_rtcp)
1446 {
1447 GstSrtpDec *filter = GST_SRTP_DEC (parent);
1448 GstPad *otherpad;
1449 GstSrtpDecSsrcStream *stream = NULL;
1450 GstFlowReturn ret = GST_FLOW_OK;
1451 guint32 ssrc = 0;
1452
1453 GST_OBJECT_LOCK (filter);
1454
1455 /* Check if this stream exists, if not create a new stream */
1456
1457 if (!(stream = validate_buffer (filter, buf, &ssrc, &is_rtcp))) {
1458 GST_OBJECT_UNLOCK (filter);
1459 GST_WARNING_OBJECT (filter, "Invalid buffer, dropping");
1460 goto drop_buffer;
1461 }
1462
1463 if (!STREAM_HAS_CRYPTO (stream)) {
1464 GST_OBJECT_UNLOCK (filter);
1465 goto push_out;
1466 }
1467
1468 if (!gst_srtp_dec_decode_buffer (filter, pad, buf, is_rtcp, ssrc)) {
1469 GST_OBJECT_UNLOCK (filter);
1470 goto drop_buffer;
1471 }
1472
1473 GST_OBJECT_UNLOCK (filter);
1474
1475 /* If all is well, we may have reached soft limit */
1476 if (gst_srtp_get_soft_limit_reached ())
1477 request_key_with_signal (filter, ssrc, SIGNAL_SOFT_LIMIT);
1478
1479 push_out:
1480 /* Push buffer to source pad */
1481 if (is_rtcp) {
1482 otherpad = filter->rtcp_srcpad;
1483 if (!filter->rtcp_has_segment)
1484 gst_srtp_dec_push_early_events (filter, filter->rtcp_srcpad,
1485 filter->rtp_srcpad, TRUE);
1486 } else {
1487 otherpad = filter->rtp_srcpad;
1488 if (!filter->rtp_has_segment)
1489 gst_srtp_dec_push_early_events (filter, filter->rtp_srcpad,
1490 filter->rtcp_srcpad, FALSE);
1491 }
1492 ret = gst_pad_push (otherpad, buf);
1493
1494 return ret;
1495
1496 drop_buffer:
1497 /* Drop buffer, except if gst_pad_push returned OK or an error */
1498
1499 gst_buffer_unref (buf);
1500
1501 return ret;
1502 }
1503
1504 static GstFlowReturn
gst_srtp_dec_chain_rtp(GstPad * pad,GstObject * parent,GstBuffer * buf)1505 gst_srtp_dec_chain_rtp (GstPad * pad, GstObject * parent, GstBuffer * buf)
1506 {
1507 return gst_srtp_dec_chain (pad, parent, buf, FALSE);
1508 }
1509
1510 static GstFlowReturn
gst_srtp_dec_chain_rtcp(GstPad * pad,GstObject * parent,GstBuffer * buf)1511 gst_srtp_dec_chain_rtcp (GstPad * pad, GstObject * parent, GstBuffer * buf)
1512 {
1513 return gst_srtp_dec_chain (pad, parent, buf, TRUE);
1514 }
1515
1516 static GstStateChangeReturn
gst_srtp_dec_change_state(GstElement * element,GstStateChange transition)1517 gst_srtp_dec_change_state (GstElement * element, GstStateChange transition)
1518 {
1519 GstStateChangeReturn res;
1520 GstSrtpDec *filter;
1521
1522 filter = GST_SRTP_DEC (element);
1523 GST_OBJECT_LOCK (filter);
1524
1525 switch (transition) {
1526 case GST_STATE_CHANGE_READY_TO_PAUSED:
1527 filter->streams = g_hash_table_new_full (g_direct_hash, g_direct_equal,
1528 NULL, (GDestroyNotify) free_stream);
1529 filter->rtp_has_segment = FALSE;
1530 filter->rtcp_has_segment = FALSE;
1531 break;
1532 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1533 break;
1534 default:
1535 break;
1536 }
1537
1538 GST_OBJECT_UNLOCK (filter);
1539
1540 res = GST_ELEMENT_CLASS (gst_srtp_dec_parent_class)->change_state (element,
1541 transition);
1542
1543 switch (transition) {
1544 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1545 break;
1546 case GST_STATE_CHANGE_PAUSED_TO_READY:
1547 gst_srtp_dec_clear_streams (filter);
1548 g_hash_table_unref (filter->streams);
1549 filter->streams = NULL;
1550 break;
1551 case GST_STATE_CHANGE_READY_TO_NULL:
1552 break;
1553 default:
1554 break;
1555 }
1556 return res;
1557 }
1558
1559
1560 /* entry point to initialize the plug-in
1561 * initialize the plug-in itself
1562 * register the element factories and other features
1563 */
1564 gboolean
gst_srtp_dec_plugin_init(GstPlugin * srtpdec)1565 gst_srtp_dec_plugin_init (GstPlugin * srtpdec)
1566 {
1567 GST_DEBUG_CATEGORY_INIT (gst_srtp_dec_debug, "srtpdec", 0, "SRTP dec");
1568
1569 return gst_element_register (srtpdec, "srtpdec", GST_RANK_NONE,
1570 GST_TYPE_SRTP_DEC);
1571 }
1572