srtpenc: Add support for adding a MKI

https://bugzilla.gnome.org/show_bug.cgi?id=797305
This commit is contained in:
Olivier Crête 2018-10-17 18:30:10 -04:00
parent 46b5756d30
commit 75d4ede815
2 changed files with 83 additions and 9 deletions

View file

@ -100,6 +100,10 @@
* 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.
*
* This element supports sending with a single Master Key, it is possible to set the
* Master Key Identifier (MKI) using the "mki" property. If this property is set, the MKI
* will be added to every buffer.
*/
#include "gstsrtpenc.h"
@ -152,7 +156,8 @@ enum
PROP_RANDOM_KEY,
PROP_REPLAY_WINDOW_SIZE,
PROP_ALLOW_REPEAT_TX,
PROP_STATS
PROP_STATS,
PROP_MKI
};
typedef struct ProcessBufferItData
@ -318,6 +323,13 @@ gst_srtp_enc_class_init (GstSrtpEncClass * klass)
g_object_class_install_property (gobject_class, PROP_STATS,
g_param_spec_boxed ("stats", "Statistics", "Various statistics",
GST_TYPE_STRUCTURE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
#ifdef HAVE_SRTP2
g_object_class_install_property (gobject_class, PROP_MKI,
g_param_spec_boxed ("mki", "MKI",
"Master key Identifier (NULL means no MKI)", GST_TYPE_BUFFER,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_PLAYING));
#endif
/**
* GstSrtpEnc::soft-limit:
@ -372,6 +384,12 @@ gst_srtp_enc_create_session (GstSrtpEnc * filter)
srtp_policy_t policy;
GstMapInfo map;
guchar tmp[1];
#ifdef HAVE_SRTP2
srtp_master_key_t mkey;
srtp_master_key_t *mkey_ptr = &mkey;
gboolean has_mki = FALSE;
GstMapInfo mki_map;
#endif
memset (&policy, 0, sizeof (srtp_policy_t));
@ -416,6 +434,29 @@ gst_srtp_enc_create_session (GstSrtpEnc * filter)
policy.key = tmp;
}
#ifdef HAVE_SRTP2
if (filter->mki) {
if (!gst_buffer_map (filter->mki, &mki_map, GST_MAP_READ)) {
GST_OBJECT_UNLOCK (filter);
GST_ELEMENT_ERROR (filter, LIBRARY, SETTINGS, ("Could not map MKI"),
(NULL));
GST_OBJECT_LOCK (filter);
ret = srtp_err_status_fail;
goto done;
}
has_mki = TRUE;
policy.num_master_keys = 1;
policy.keys = &mkey_ptr;
mkey.key = policy.key;
policy.key = NULL;
mkey.mki_id = (guchar *) mki_map.data;
mkey.mki_size = mki_map.size;
}
#endif
policy.ssrc.value = 0;
policy.ssrc.type = ssrc_any_outbound;
policy.next = NULL;
@ -429,9 +470,17 @@ gst_srtp_enc_create_session (GstSrtpEnc * filter)
ret = srtp_create (&filter->session, &policy);
filter->first_session = FALSE;
#ifdef HAVE_SRTP2
done:
if (has_mki)
gst_buffer_unmap (filter->mki, &mki_map);
#endif
if (HAS_CRYPTO (filter))
gst_buffer_unmap (filter->key, &map);
return ret;
}
@ -595,9 +644,8 @@ gst_srtp_enc_dispose (GObject * object)
}
gst_iterator_free (it);
if (filter->key)
gst_buffer_unref (filter->key);
filter->key = NULL;
gst_buffer_replace (&filter->key, NULL);
gst_buffer_replace (&filter->mki, NULL);
if (filter->ssrcs_set)
g_hash_table_unref (filter->ssrcs_set);
@ -658,8 +706,7 @@ gst_srtp_enc_set_property (GObject * object, guint prop_id,
switch (prop_id) {
case PROP_MKEY:
if (filter->key)
gst_buffer_unref (filter->key);
gst_clear_buffer (&filter->key);
filter->key = g_value_dup_boxed (value);
filter->key_changed = TRUE;
GST_INFO_OBJECT (object, "Set property: key=[%p]", filter->key);
@ -697,7 +744,14 @@ gst_srtp_enc_set_property (GObject * object, guint prop_id,
case PROP_ALLOW_REPEAT_TX:
filter->allow_repeat_tx = g_value_get_boolean (value);
break;
#ifdef HAVE_SRTP2
case PROP_MKI:
gst_clear_buffer (&filter->mki);
filter->mki = g_value_dup_boxed (value);
filter->key_changed = TRUE;
GST_INFO_OBJECT (object, "Set property: mki=[%p]", filter->mki);
break;
#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -742,6 +796,12 @@ gst_srtp_enc_get_property (GObject * object, guint prop_id,
case PROP_STATS:
g_value_take_boxed (value, gst_srtp_enc_create_stats (filter));
break;
#ifdef HAVE_SRTP2
case PROP_MKI:
if (filter->mki)
g_value_set_boxed (value, filter->mki);
break;
#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -816,6 +876,11 @@ gst_srtp_enc_sink_setcaps (GstPad * pad, GstSrtpEnc * filter,
if (HAS_CRYPTO (filter))
gst_structure_set (ps, "srtp-key", GST_TYPE_BUFFER, filter->key, NULL);
#ifdef HAVE_SRTP2
if (filter->mki)
gst_structure_set (ps, "mki", GST_TYPE_BUFFER, filter->mki, NULL);
#endif
/* Add srtp-specific params to source caps */
gst_structure_set (ps,
"srtp-cipher", G_TYPE_STRING,
@ -894,7 +959,7 @@ gst_srtp_enc_sink_query (GstPad * pad, GstObject * parent, GstQuery * query,
else
gst_structure_set_name (ps, "application/x-rtp");
gst_structure_remove_fields (ps, "srtp-key", "srtp-cipher", "srtp-auth",
"srtcp-cipher", "srtcp-auth", NULL);
"srtcp-cipher", "srtcp-auth", "mki", NULL);
}
gst_query_set_caps_result (query, ret);
@ -1059,11 +1124,19 @@ gst_srtp_enc_process_buffer (GstSrtpEnc * filter, GstPad * pad,
ret = GST_FLOW_FLUSHING;
goto fail;
}
#ifdef HAVE_SRTP2
if (is_rtcp)
err = srtp_protect_rtcp_mki (filter->session, mapout.data, &size,
(filter->mki != NULL), 0);
else
err = srtp_protect_mki (filter->session, mapout.data, &size,
(filter->mki != NULL), 0);
#else
if (is_rtcp)
err = srtp_protect_rtcp (filter->session, mapout.data, &size);
else
err = srtp_protect (filter->session, mapout.data, &size);
#endif
GST_OBJECT_UNLOCK (filter);

View file

@ -76,6 +76,7 @@ struct _GstSrtpEnc
guint rtp_auth;
guint rtcp_cipher;
guint rtcp_auth;
GstBuffer *mki;
srtp_t session;
gboolean first_session;