srtpenc: Add support for adding a MKI
authorOlivier Crête <olivier.crete@collabora.com>
Wed, 17 Oct 2018 22:30:10 +0000 (18:30 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Fri, 9 Nov 2018 20:08:05 +0000 (15:08 -0500)
https://bugzilla.gnome.org/show_bug.cgi?id=797305

ext/srtp/gstsrtpenc.c
ext/srtp/gstsrtpenc.h

index fffaebb..5248c1f 100644 (file)
  * 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);
 
index 5c64e0b..df2f8fd 100644 (file)
@@ -76,6 +76,7 @@ struct _GstSrtpEnc
   guint rtp_auth;
   guint rtcp_cipher;
   guint rtcp_auth;
+  GstBuffer *mki;
 
   srtp_t session;
   gboolean first_session;