Browse Source

Merge pull request #981 from paullouisageneau/system-srtp-disable-gcm

Disable GCM suites if unsupported by system libSRTP
Paul-Louis Ageneau 1 year ago
parent
commit
5105eda25e
4 changed files with 44 additions and 17 deletions
  1. 3 1
      Makefile
  2. 22 6
      src/impl/dtlssrtptransport.cpp
  3. 7 6
      src/impl/dtlssrtptransport.hpp
  4. 12 4
      src/impl/dtlstransport.cpp

+ 3 - 1
Makefile

@@ -11,6 +11,7 @@ LIBS=
 LOCALLIBS=libusrsctp.a
 LOCALLIBS=libusrsctp.a
 USRSCTP_DIR=deps/usrsctp
 USRSCTP_DIR=deps/usrsctp
 SRTP_DIR=deps/libsrtp
 SRTP_DIR=deps/libsrtp
+SRTP_CONFIGURE_FLAGS=
 JUICE_DIR=deps/libjuice
 JUICE_DIR=deps/libjuice
 PLOG_DIR=deps/plog
 PLOG_DIR=deps/plog
 
 
@@ -24,6 +25,7 @@ ifneq ($(USE_GNUTLS), 0)
 else
 else
         CPPFLAGS+=-DUSE_GNUTLS=0
         CPPFLAGS+=-DUSE_GNUTLS=0
         LIBS+=openssl
         LIBS+=openssl
+        SRTP_CONFIGURE_FLAGS+=--enable-openssl
 endif
 endif
 
 
 USE_NICE ?= 0
 USE_NICE ?= 0
@@ -122,7 +124,7 @@ libusrsctp.a:
 
 
 libsrtp2.a:
 libsrtp2.a:
 	cd $(SRTP_DIR) && \
 	cd $(SRTP_DIR) && \
-		./configure && \
+		./configure $(SRTP_CONFIGURE_FLAGS) && \
 		make
 		make
 	cp $(SRTP_DIR)/libsrtp2.a .
 	cp $(SRTP_DIR)/libsrtp2.a .
 
 

+ 22 - 6
src/impl/dtlssrtptransport.cpp

@@ -45,6 +45,17 @@ void DtlsSrtpTransport::Init() { srtp_init(); }
 
 
 void DtlsSrtpTransport::Cleanup() { srtp_shutdown(); }
 void DtlsSrtpTransport::Cleanup() { srtp_shutdown(); }
 
 
+bool DtlsSrtpTransport::IsGcmSupported() {
+#if RTC_SYSTEM_SRTP
+	// system libSRTP may not have GCM support
+	srtp_policy_t policy = {};
+	return srtp_crypto_policy_set_from_profile_for_rtp(
+	           &policy.rtp, srtp_profile_aead_aes_256_gcm) == srtp_err_status_ok;
+#else
+	return true;
+#endif
+}
+
 DtlsSrtpTransport::DtlsSrtpTransport(shared_ptr<IceTransport> lower,
 DtlsSrtpTransport::DtlsSrtpTransport(shared_ptr<IceTransport> lower,
                                      shared_ptr<Certificate> certificate, optional<size_t> mtu,
                                      shared_ptr<Certificate> certificate, optional<size_t> mtu,
                                      verifier_callback verifierCallback,
                                      verifier_callback verifierCallback,
@@ -326,11 +337,13 @@ void DtlsSrtpTransport::postHandshake() {
 	std::memcpy(mServerSessionKey.data() + keySize, serverSalt, saltSize);
 	std::memcpy(mServerSessionKey.data() + keySize, serverSalt, saltSize);
 
 
 	srtp_policy_t inbound = {};
 	srtp_policy_t inbound = {};
-	srtp_crypto_policy_set_from_profile_for_rtp(&inbound.rtp, srtpProfile);
-	srtp_crypto_policy_set_from_profile_for_rtcp(&inbound.rtcp, srtpProfile);
+	if (srtp_crypto_policy_set_from_profile_for_rtp(&inbound.rtp, srtpProfile))
+		throw std::runtime_error("SRTP profile is not supported");
+	if (srtp_crypto_policy_set_from_profile_for_rtcp(&inbound.rtcp, srtpProfile))
+		throw std::runtime_error("SRTP profile is not supported");
+
 	inbound.ssrc.type = ssrc_any_inbound;
 	inbound.ssrc.type = ssrc_any_inbound;
 	inbound.key = mIsClient ? mServerSessionKey.data() : mClientSessionKey.data();
 	inbound.key = mIsClient ? mServerSessionKey.data() : mClientSessionKey.data();
-
 	inbound.window_size = 1024;
 	inbound.window_size = 1024;
 	inbound.allow_repeat_tx = true;
 	inbound.allow_repeat_tx = true;
 	inbound.next = nullptr;
 	inbound.next = nullptr;
@@ -340,8 +353,11 @@ void DtlsSrtpTransport::postHandshake() {
 		                         to_string(static_cast<int>(err)));
 		                         to_string(static_cast<int>(err)));
 
 
 	srtp_policy_t outbound = {};
 	srtp_policy_t outbound = {};
-	srtp_crypto_policy_set_from_profile_for_rtp(&outbound.rtp, srtpProfile);
-	srtp_crypto_policy_set_from_profile_for_rtcp(&outbound.rtcp, srtpProfile);
+	if (srtp_crypto_policy_set_from_profile_for_rtp(&outbound.rtp, srtpProfile))
+		throw std::runtime_error("SRTP profile is not supported");
+	if (srtp_crypto_policy_set_from_profile_for_rtcp(&outbound.rtcp, srtpProfile))
+		throw std::runtime_error("SRTP profile is not supported");
+
 	outbound.ssrc.type = ssrc_any_outbound;
 	outbound.ssrc.type = ssrc_any_outbound;
 	outbound.key = mIsClient ? mClientSessionKey.data() : mServerSessionKey.data();
 	outbound.key = mIsClient ? mClientSessionKey.data() : mServerSessionKey.data();
 	outbound.window_size = 1024;
 	outbound.window_size = 1024;
@@ -356,7 +372,7 @@ void DtlsSrtpTransport::postHandshake() {
 }
 }
 
 
 #if !USE_GNUTLS && !USE_MBEDTLS
 #if !USE_GNUTLS && !USE_MBEDTLS
-ProfileParams DtlsSrtpTransport::getProfileParamsFromName(string_view name) {
+DtlsSrtpTransport::ProfileParams DtlsSrtpTransport::getProfileParamsFromName(string_view name) {
 	if (name == "SRTP_AES128_CM_SHA1_80")
 	if (name == "SRTP_AES128_CM_SHA1_80")
 		return {srtp_profile_aes128_cm_sha1_80, SRTP_AES_128_KEY_LEN, SRTP_SALT_LEN};
 		return {srtp_profile_aes128_cm_sha1_80, SRTP_AES_128_KEY_LEN, SRTP_SALT_LEN};
 	if (name == "SRTP_AES128_CM_SHA1_32")
 	if (name == "SRTP_AES128_CM_SHA1_32")

+ 7 - 6
src/impl/dtlssrtptransport.hpp

@@ -24,16 +24,11 @@
 
 
 namespace rtc::impl {
 namespace rtc::impl {
 
 
-struct ProfileParams {
-	srtp_profile_t srtpProfile;
-	size_t keySize;
-	size_t saltSize;
-};
-
 class DtlsSrtpTransport final : public DtlsTransport {
 class DtlsSrtpTransport final : public DtlsTransport {
 public:
 public:
 	static void Init();
 	static void Init();
 	static void Cleanup();
 	static void Cleanup();
+	static bool IsGcmSupported();
 
 
 	DtlsSrtpTransport(shared_ptr<IceTransport> lower, certificate_ptr certificate,
 	DtlsSrtpTransport(shared_ptr<IceTransport> lower, certificate_ptr certificate,
 	                  optional<size_t> mtu, verifier_callback verifierCallback,
 	                  optional<size_t> mtu, verifier_callback verifierCallback,
@@ -48,6 +43,12 @@ private:
 	void postHandshake() override;
 	void postHandshake() override;
 
 
 #if !USE_GNUTLS && !USE_MBEDTLS
 #if !USE_GNUTLS && !USE_MBEDTLS
+	struct ProfileParams {
+		srtp_profile_t srtpProfile;
+		size_t keySize;
+		size_t saltSize;
+	};
+
 	ProfileParams getProfileParamsFromName(string_view name);
 	ProfileParams getProfileParamsFromName(string_view name);
 #endif
 #endif
 
 

+ 12 - 4
src/impl/dtlstransport.cpp

@@ -7,6 +7,7 @@
  */
  */
 
 
 #include "dtlstransport.hpp"
 #include "dtlstransport.hpp"
+#include "dtlssrtptransport.hpp"
 #include "icetransport.hpp"
 #include "icetransport.hpp"
 #include "internals.hpp"
 #include "internals.hpp"
 #include "threadpool.hpp"
 #include "threadpool.hpp"
@@ -794,16 +795,23 @@ DtlsTransport::DtlsTransport(shared_ptr<IceTransport> lower, certificate_ptr cer
 		SSL_set_bio(mSsl, mInBio, mOutBio);
 		SSL_set_bio(mSsl, mInBio, mOutBio);
 
 
 		// RFC 8827: The DTLS-SRTP protection profile SRTP_AES128_CM_HMAC_SHA1_80 MUST be supported
 		// RFC 8827: The DTLS-SRTP protection profile SRTP_AES128_CM_HMAC_SHA1_80 MUST be supported
-		// See https://www.rfc-editor.org/rfc/rfc8827.html#section-6.5 Warning:
-		// SSL_set_tlsext_use_srtp() returns 0 on success and 1 on error
+		// See https://www.rfc-editor.org/rfc/rfc8827.html#section-6.5
+		// Warning: SSL_set_tlsext_use_srtp() returns 0 on success and 1 on error
+#if RTC_ENABLE_MEDIA
 		// Try to use GCM suite
 		// Try to use GCM suite
-		if (SSL_set_tlsext_use_srtp(
+		if (!DtlsSrtpTransport::IsGcmSupported() ||
+		    SSL_set_tlsext_use_srtp(
 		        mSsl, "SRTP_AEAD_AES_256_GCM:SRTP_AEAD_AES_128_GCM:SRTP_AES128_CM_SHA1_80")) {
 		        mSsl, "SRTP_AEAD_AES_256_GCM:SRTP_AEAD_AES_128_GCM:SRTP_AES128_CM_SHA1_80")) {
+			PLOG_WARNING << "AES-GCM for SRTP is not supported, falling back to default profile";
 			if (SSL_set_tlsext_use_srtp(mSsl, "SRTP_AES128_CM_SHA1_80"))
 			if (SSL_set_tlsext_use_srtp(mSsl, "SRTP_AES128_CM_SHA1_80"))
 				throw std::runtime_error("Failed to set SRTP profile: " +
 				throw std::runtime_error("Failed to set SRTP profile: " +
 				                         openssl::error_string(ERR_get_error()));
 				                         openssl::error_string(ERR_get_error()));
 		}
 		}
-
+#else
+		if (SSL_set_tlsext_use_srtp(mSsl, "SRTP_AES128_CM_SHA1_80"))
+			throw std::runtime_error("Failed to set SRTP profile: " +
+			                         openssl::error_string(ERR_get_error()));
+#endif
 	} catch (...) {
 	} catch (...) {
 		if (mSsl)
 		if (mSsl)
 			SSL_free(mSsl);
 			SSL_free(mSsl);