summaryrefslogtreecommitdiff
path: root/ext/srtp
diff options
context:
space:
mode:
authorAleix Conchillo Flaqué <aleix@oblong.com>2014-03-21 22:16:41 -0700
committerOlivier Crête <olivier.crete@collabora.com>2014-06-03 16:18:25 -0400
commitda30669589cfc8189f60aedfae98a217a9fae994 (patch)
treeae6362766d1c4a5a53dc6c88e453ff7f7ad613b7 /ext/srtp
parentc9ae275c7275e45fdfb4e1c33a7e319de473e0dc (diff)
downloadgstreamer-plugins-bad-da30669589cfc8189f60aedfae98a217a9fae994.tar.gz
srtp: add support for rollover counters and replay protection window size
We add a new signal, get-rollover-counter, to the SRTP encoder. Given a ssrc the signal will return the currently internal SRTP rollover counter for the given stream. For the SRTP decoder we have a new SRTP caps parameter "roc" that needs to be set when a new SRTP stream is created for a given SSRC. https://bugzilla.gnome.org/show_bug.cgi?id=726861
Diffstat (limited to 'ext/srtp')
-rw-r--r--ext/srtp/gstsrtpdec.c57
-rw-r--r--ext/srtp/gstsrtpdec.h2
-rw-r--r--ext/srtp/gstsrtpenc.c48
-rw-r--r--ext/srtp/gstsrtpenc.h3
4 files changed, 107 insertions, 3 deletions
diff --git a/ext/srtp/gstsrtpdec.c b/ext/srtp/gstsrtpdec.c
index b82a0a6ca..5d42f4485 100644
--- a/ext/srtp/gstsrtpdec.c
+++ b/ext/srtp/gstsrtpdec.c
@@ -88,6 +88,13 @@
* subsequent packet is dropped, until a new key is set and the stream
* has been updated.
*
+ * If a stream is to be shared between multiple clients the SRTP
+ * rollover counter for a given SSRC must be set in the caps "roc" field
+ * when the request-key signal is emitted by the decoder. The rollover
+ * counters should have been transmitted by a signaling protocol by some
+ * other means. If no rollover counter is provided by the user, 0 is
+ * used by default.
+ *
* <refsect2>
* <title>Example pipelines</title>
* |[
@@ -114,6 +121,8 @@
#include "gstsrtpdec.h"
+#include <srtp/srtp_priv.h>
+
GST_DEBUG_CATEGORY_STATIC (gst_srtp_dec_debug);
#define GST_CAT_DEFAULT gst_srtp_dec_debug
@@ -203,6 +212,7 @@ struct _GstSrtpDecSsrcStream
{
guint32 ssrc;
+ guint32 roc;
GstBuffer *key;
GstSrtpCipherType rtp_cipher;
GstSrtpAuthType rtp_auth;
@@ -216,6 +226,7 @@ struct _GstSrtpDecSsrcStream
stream->rtp_auth != GST_SRTP_AUTH_NULL || \
stream->rtcp_auth != GST_SRTP_AUTH_NULL)
+
/* initialize the srtpdec's class */
static void
gst_srtp_dec_class_init (GstSrtpDecClass * klass)
@@ -238,11 +249,14 @@ gst_srtp_dec_class_init (GstSrtpDecClass * klass)
"A SRTP and SRTCP decoder",
"Gabriel Millaire <millaire.gabriel@collabora.com>");
+ /* Install callbacks */
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_srtp_dec_change_state);
+
klass->clear_streams = GST_DEBUG_FUNCPTR (gst_srtp_dec_clear_streams);
klass->remove_stream = GST_DEBUG_FUNCPTR (gst_srtp_dec_remove_stream);
+ /* Install signals */
/**
* GstSrtpDec::request-key:
* @gstsrtpdec: the element on which the signal is emitted
@@ -369,6 +383,7 @@ gst_srtp_dec_init (GstSrtpDec * filter)
gst_element_add_pad (GST_ELEMENT (filter), filter->rtcp_srcpad);
filter->first_session = TRUE;
+ filter->roc_changed = FALSE;
}
static void
@@ -421,6 +436,7 @@ get_stream_from_caps (GstSrtpDec * filter, GstCaps * caps, guint32 ssrc)
if (!rtp_cipher || !rtp_auth || !rtcp_cipher || !rtcp_auth)
goto error;
+ gst_structure_get_uint (s, "roc", &stream->roc);
stream->rtp_cipher = enum_value_from_nick (GST_TYPE_SRTP_CIPHER_TYPE,
rtp_cipher);
@@ -518,6 +534,17 @@ init_session_stream (GstSrtpDec * filter, guint32 ssrc,
gst_buffer_unmap (stream->key, &map);
if (ret == err_status_ok) {
+ srtp_stream_t srtp_stream;
+
+ srtp_stream = srtp_get_stream (filter->session, htonl (ssrc));
+ if (srtp_stream) {
+ /* Here, we just set the ROC, but we also need to set the initial
+ * RTP sequence number later, otherwise libsrtp will not be able
+ * to get the right packet index. */
+ rdbx_set_roc (&srtp_stream->rtp_rdbx, stream->roc);
+ filter->roc_changed = TRUE;
+ }
+
filter->first_session = FALSE;
g_hash_table_insert (filter->streams, GUINT_TO_POINTER (stream->ssrc),
stream);
@@ -672,9 +699,9 @@ request_key_with_signal (GstSrtpDec * filter, guint32 ssrc, gint signal)
if (caps) {
stream = update_session_stream_from_caps (filter, ssrc, caps);
if (stream)
- GST_DEBUG_OBJECT (filter, "New stream set with SSRC %d", ssrc);
+ GST_DEBUG_OBJECT (filter, "New stream set with SSRC %u", ssrc);
else
- GST_WARNING_OBJECT (filter, "Could not set stream with SSRC %d", ssrc);
+ GST_WARNING_OBJECT (filter, "Could not set stream with SSRC %u", ssrc);
gst_caps_unref (caps);
}
@@ -1016,8 +1043,32 @@ unprotect:
if (is_rtcp)
err = srtp_unprotect_rtcp (filter->session, map.data, &size);
- else
+ else {
+ /* If ROC has changed, we know we need to set the initial RTP
+ * sequence number too. */
+ if (filter->roc_changed) {
+ srtp_stream_t stream;
+
+ stream = srtp_get_stream (filter->session, htonl (ssrc));
+
+ if (stream) {
+ guint16 seqnum = 0;
+ GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT;
+
+ gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf);
+ seqnum = gst_rtp_buffer_get_seq (&rtpbuf);
+ gst_rtp_buffer_unmap (&rtpbuf);
+
+ /* We finally add the RTP sequence number to the current
+ * rollover counter. */
+ stream->rtp_rdbx.index &= ~0xFFFF;
+ stream->rtp_rdbx.index |= seqnum;
+ }
+
+ filter->roc_changed = FALSE;
+ }
err = srtp_unprotect (filter->session, map.data, &size);
+ }
gst_buffer_unmap (buf, &map);
diff --git a/ext/srtp/gstsrtpdec.h b/ext/srtp/gstsrtpdec.h
index 8129dc08f..41862e032 100644
--- a/ext/srtp/gstsrtpdec.h
+++ b/ext/srtp/gstsrtpdec.h
@@ -81,6 +81,8 @@ struct _GstSrtpDec
gboolean rtp_has_segment;
gboolean rtcp_has_segment;
+
+ gboolean roc_changed;
};
struct _GstSrtpDecClass
diff --git a/ext/srtp/gstsrtpenc.c b/ext/srtp/gstsrtpenc.c
index adee36843..ad637a6fe 100644
--- a/ext/srtp/gstsrtpenc.c
+++ b/ext/srtp/gstsrtpenc.c
@@ -92,6 +92,13 @@
* subsequent packet is dropped, until a new key is set and the stream
* has been updated.
*
+ * If a stream is to be shared between multiple clients it is also
+ * possible to request the internal SRTP rollover counter for a given
+ * SSRC. The rollover counter should be then transmitted and used by the
+ * clients to authenticate and decrypt the packets. Failing to do that
+ * the clients will start with a rollover counter of 0 which will
+ * probably be incorrect if the stream has been transmitted for a
+ * while to other clients.
*/
#ifdef HAVE_CONFIG_H
@@ -108,6 +115,8 @@
#include "gstsrtp.h"
#include "gstsrtp-enumtypes.h"
+#include <srtp/srtp_priv.h>
+
GST_DEBUG_CATEGORY_STATIC (gst_srtp_enc_debug);
#define GST_CAT_DEFAULT gst_srtp_enc_debug
@@ -135,6 +144,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_srtp_enc_debug);
enum
{
SIGNAL_SOFT_LIMIT,
+ SIGNAL_GET_ROLLOVER_COUNTER,
LAST_SIGNAL
};
@@ -221,6 +231,28 @@ static GstPad *gst_srtp_enc_request_new_pad (GstElement * element,
static void gst_srtp_enc_release_pad (GstElement * element, GstPad * pad);
+
+static guint32
+gst_srtp_enc_get_rollover_counter (GstSrtpEnc * filter, guint32 ssrc)
+{
+ guint32 roc = 0;
+ srtp_stream_t stream;
+
+ GST_OBJECT_LOCK (filter);
+
+ GST_DEBUG_OBJECT (filter, "retrieving SRTP Rollover Counter, ssrc: %u", ssrc);
+
+ if (filter->session) {
+ stream = srtp_get_stream (filter->session, htonl (ssrc));
+ if (stream)
+ roc = stream->rtp_rdbx.index >> 16;
+ }
+
+ GST_OBJECT_UNLOCK (filter);
+
+ return roc;
+}
+
/* initialize the srtpenc's class
*/
static void
@@ -301,6 +333,22 @@ gst_srtp_enc_class_init (GstSrtpEncClass * klass)
gst_srtp_enc_signals[SIGNAL_SOFT_LIMIT] =
g_signal_new ("soft-limit", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+ /**
+ * GstSrtpEnc::get-rollover-counter:
+ * @gstsrtpenc: the element on which the signal is emitted
+ * @ssrc: The unique SSRC of the stream
+ *
+ * Request the SRTP rollover counter for the stream with @ssrc.
+ */
+ gst_srtp_enc_signals[SIGNAL_GET_ROLLOVER_COUNTER] =
+ g_signal_new ("get-rollover-counter", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstSrtpEncClass,
+ get_rollover_counter), NULL, NULL, g_cclosure_marshal_generic,
+ G_TYPE_UINT, 1, G_TYPE_UINT);
+
+ klass->get_rollover_counter =
+ GST_DEBUG_FUNCPTR (gst_srtp_enc_get_rollover_counter);
}
diff --git a/ext/srtp/gstsrtpenc.h b/ext/srtp/gstsrtpenc.h
index c4bc75cef..36da4ffae 100644
--- a/ext/srtp/gstsrtpenc.h
+++ b/ext/srtp/gstsrtpenc.h
@@ -88,6 +88,9 @@ struct _GstSrtpEnc
struct _GstSrtpEncClass
{
GstElementClass parent_class;
+
+ /* action signals */
+ guint32 (*get_rollover_counter) (GstSrtpEnc *encoder, guint32 ssrc);
};
GType gst_srtp_enc_get_type (void);