srtp: Add support for GCM (RFC 7714)
authorUlf Olsson <ulfo@axis.com>
Wed, 6 Mar 2019 06:36:44 +0000 (07:36 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Wed, 27 Mar 2019 10:55:27 +0000 (10:55 +0000)
The GCM support in libsrtp have been there for a while and
it can be useful for some applications.

Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/913

ext/srtp/gstsrtp.c
ext/srtp/gstsrtp.h
ext/srtp/gstsrtpdec.c
ext/srtp/gstsrtpenc.c
ext/srtp/gstsrtpenums.h

index 0c1e235..42b0ecf 100644 (file)
@@ -219,6 +219,12 @@ set_crypto_policy_cipher_auth (GstSrtpCipherType cipher,
     case GST_SRTP_CIPHER_AES_256_ICM:
       policy->cipher_type = SRTP_AES_ICM_256;
       break;
+    case GST_SRTP_CIPHER_AES_128_GCM:
+      policy->cipher_type = SRTP_AES_GCM_128;
+      break;
+    case GST_SRTP_CIPHER_AES_256_GCM:
+      policy->cipher_type = SRTP_AES_GCM_256;
+      break;
     case GST_SRTP_CIPHER_NULL:
       policy->cipher_type = SRTP_NULL_CIPHER;
       break;
@@ -242,7 +248,12 @@ set_crypto_policy_cipher_auth (GstSrtpCipherType cipher,
     case GST_SRTP_AUTH_NULL:
       policy->auth_type = SRTP_NULL_AUTH;
       policy->auth_key_len = 0;
-      policy->auth_tag_len = 0;
+      if (cipher == GST_SRTP_CIPHER_AES_128_GCM
+          || cipher == GST_SRTP_CIPHER_AES_256_GCM) {
+        policy->auth_tag_len = 16;
+      } else {
+        policy->auth_tag_len = 0;
+      }
       break;
   }
 
@@ -268,8 +279,13 @@ cipher_key_size (GstSrtpCipherType cipher)
     case GST_SRTP_CIPHER_AES_256_ICM:
       size = SRTP_AES_ICM_256_KEY_LEN_WSALT;
       break;
+    case GST_SRTP_CIPHER_AES_128_GCM:
+      size = SRTP_AES_GCM_128_KEY_LEN_WSALT;
+      break;
+    case GST_SRTP_CIPHER_AES_256_GCM:
+      size = SRTP_AES_GCM_256_KEY_LEN_WSALT;
+      break;
     case GST_SRTP_CIPHER_NULL:
-      size = 0;
       break;
     default:
       g_assert_not_reached ();
index 62c6727..b303fc1 100644 (file)
 #else
 #  include <srtp/srtp.h>
 #  include <srtp/srtp_priv.h>
+#  include <srtp/crypto_types.h>
 
 #  define srtp_crypto_policy_t crypto_policy_t
 #  define SRTP_AES_ICM_128 AES_ICM
 #  define SRTP_AES_ICM_256 AES_ICM
+#  define SRTP_AES_GCM_128 AES_128_GCM
+#  define SRTP_AES_GCM_256 AES_256_GCM
 #  define SRTP_NULL_CIPHER NULL_CIPHER
 #  define SRTP_AES_ICM_128_KEY_LEN_WSALT 30
 #  define SRTP_AES_ICM_256_KEY_LEN_WSALT 46
+#  define SRTP_AES_GCM_128_KEY_LEN_WSALT AES_128_GCM_KEYSIZE_WSALT
+#  define SRTP_AES_GCM_256_KEY_LEN_WSALT AES_256_GCM_KEYSIZE_WSALT
 #  define SRTP_HMAC_SHA1 HMAC_SHA1
 #  define SRTP_NULL_AUTH NULL_AUTH
 #  define srtp_err_status_t err_status_t
index 4ecef54..47ebfae 100644 (file)
@@ -583,8 +583,13 @@ get_stream_from_caps (GstSrtpDec * filter, GstCaps * caps, guint32 ssrc)
     goto error;
   }
 
-  if (stream->rtcp_cipher != SRTP_NULL_CIPHER &&
-      stream->rtcp_auth == SRTP_NULL_AUTH) {
+  /* RFC 3711 says in "3. SRTP Framework" that SRTCP message authentication
+   * is MANDATORY. In case of GCM let the pipeline handle any errors.
+   */
+  if (stream->rtcp_cipher != GST_SRTP_CIPHER_AES_128_GCM
+      && stream->rtcp_cipher != GST_SRTP_CIPHER_AES_256_GCM
+      && stream->rtcp_cipher != GST_SRTP_CIPHER_NULL
+      && stream->rtcp_auth == GST_SRTP_AUTH_NULL) {
     GST_WARNING_OBJECT (filter,
         "Cannot have SRTP NULL authentication with a not-NULL encryption"
         " cipher.");
@@ -930,6 +935,7 @@ update_session_stream_from_caps (GstSrtpDec * filter, guint32 ssrc,
     err = init_session_stream (filter, ssrc, stream);
 
     if (err != srtp_err_status_ok) {
+      GST_WARNING_OBJECT (filter, "Failed to create the stream (err: %d)", err);
       if (stream->key)
         gst_buffer_unref (stream->key);
       g_slice_free (GstSrtpDecSsrcStream, stream);
index 6efe92e..1c50726 100644 (file)
@@ -490,8 +490,10 @@ static void
 gst_srtp_enc_reset_no_lock (GstSrtpEnc * filter)
 {
   if (!filter->first_session) {
-    srtp_dealloc (filter->session);
-    filter->session = NULL;
+    if (filter->session) {
+      srtp_dealloc (filter->session);
+      filter->session = NULL;
+    }
 
     g_hash_table_remove_all (filter->ssrcs_set);
   }
@@ -1374,8 +1376,14 @@ gst_srtp_enc_change_state (GstElement * element, GstStateChange transition)
           }
         }
       }
-      if ((filter->rtcp_cipher != SRTP_NULL_CIPHER)
-          && (filter->rtcp_auth == SRTP_NULL_AUTH)) {
+
+      /* RFC 3711 says in "3. SRTP Framework" that SRTCP message authentication
+       * is MANDATORY. In case of GCM let the pipeline handle any errors.
+       */
+      if (filter->rtcp_cipher != GST_SRTP_CIPHER_AES_128_GCM
+          && filter->rtcp_cipher != GST_SRTP_CIPHER_AES_256_GCM
+          && filter->rtcp_cipher != GST_SRTP_CIPHER_NULL
+          && filter->rtcp_auth == GST_SRTP_AUTH_NULL) {
         GST_ERROR_OBJECT (filter,
             "RTCP authentication can't be NULL if encryption is not NULL.");
         return GST_STATE_CHANGE_FAILURE;
index 91d3955..da6dd29 100644 (file)
@@ -49,7 +49,9 @@ typedef enum
 {
   GST_SRTP_CIPHER_NULL,
   GST_SRTP_CIPHER_AES_128_ICM,
-  GST_SRTP_CIPHER_AES_256_ICM
+  GST_SRTP_CIPHER_AES_256_ICM,
+  GST_SRTP_CIPHER_AES_128_GCM,
+  GST_SRTP_CIPHER_AES_256_GCM
 } GstSrtpCipherType;
 
 typedef enum