mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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
This commit is contained in:
parent
c9ae275c72
commit
da30669589
4 changed files with 107 additions and 3 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -81,6 +81,8 @@ struct _GstSrtpDec
|
|||
|
||||
gboolean rtp_has_segment;
|
||||
gboolean rtcp_has_segment;
|
||||
|
||||
gboolean roc_changed;
|
||||
};
|
||||
|
||||
struct _GstSrtpDecClass
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue