From b2d0795185463ecd7aae126e5aeff41148308d38 Mon Sep 17 00:00:00 2001 From: Ulf Olsson Date: Wed, 6 Mar 2019 07:36:44 +0100 Subject: [PATCH] srtp: Add support for GCM (RFC 7714) 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 | 20 ++++++++++++++++++-- ext/srtp/gstsrtp.h | 5 +++++ ext/srtp/gstsrtpdec.c | 10 ++++++++-- ext/srtp/gstsrtpenc.c | 16 ++++++++++++---- ext/srtp/gstsrtpenums.h | 4 +++- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/ext/srtp/gstsrtp.c b/ext/srtp/gstsrtp.c index 0c1e235ab2..42b0ecf2f1 100644 --- a/ext/srtp/gstsrtp.c +++ b/ext/srtp/gstsrtp.c @@ -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 (); diff --git a/ext/srtp/gstsrtp.h b/ext/srtp/gstsrtp.h index 62c67276d8..b303fc1f42 100644 --- a/ext/srtp/gstsrtp.h +++ b/ext/srtp/gstsrtp.h @@ -60,13 +60,18 @@ #else # include # include +# include # 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 diff --git a/ext/srtp/gstsrtpdec.c b/ext/srtp/gstsrtpdec.c index 4ecef543be..47ebfae0b9 100644 --- a/ext/srtp/gstsrtpdec.c +++ b/ext/srtp/gstsrtpdec.c @@ -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); diff --git a/ext/srtp/gstsrtpenc.c b/ext/srtp/gstsrtpenc.c index 6efe92e407..1c50726e06 100644 --- a/ext/srtp/gstsrtpenc.c +++ b/ext/srtp/gstsrtpenc.c @@ -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; diff --git a/ext/srtp/gstsrtpenums.h b/ext/srtp/gstsrtpenums.h index 91d395507c..da6dd299eb 100644 --- a/ext/srtp/gstsrtpenums.h +++ b/ext/srtp/gstsrtpenums.h @@ -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 -- 2.34.1