From 8c27ccac75975f38fe030b83582941604e49ec58 Mon Sep 17 00:00:00 2001 From: Benjamin Wright Date: Thu, 25 Oct 2018 10:16:44 -0700 Subject: [PATCH] Promotoing webrtc::CryptoOptions to RTCConfiguration. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the expanding use cases for webrtc::CryptoOptions it makes more sense for it to be be available per peer connection instead of only as a factory option. To support backwards compatability for now this code will support the factory method of setting crypto options by default. However it will completely overwrite these settings if an RTCConfiguration.crypto_options is provided. Got LGTM offline from Sami, adding him to TBR if he has any further comments. TBR=sakal@webrtc.org Bug: webrtc:9891 Change-Id: I86914cab69284ad82afd7285fd84ec5f4f2c4986 Reviewed-on: https://webrtc-review.googlesource.com/c/107029 Commit-Queue: Benjamin Wright Reviewed-by: Seth Hampson Reviewed-by: Patrik Höglund Reviewed-by: Kári Helgason Cr-Commit-Position: refs/heads/master@{#25375} --- BUILD.gn | 1 + api/peerconnectioninterface.h | 7 + pc/peerconnection.cc | 41 +++-- pc/peerconnection.h | 5 + pc/peerconnection_crypto_unittest.cc | 23 +++ sdk/BUILD.gn | 4 + sdk/android/BUILD.gn | 5 + sdk/android/api/org/webrtc/CryptoOptions.java | 144 ++++++++++++++++++ .../api/org/webrtc/PeerConnection.java | 14 ++ .../api/org/webrtc/PeerConnectionFactory.java | 6 + .../src/org/webrtc/PeerConnectionTest.java | 21 +++ sdk/android/src/jni/pc/cryptooptions.cc | 43 ++++++ sdk/android/src/jni/pc/cryptooptions.h | 30 ++++ sdk/android/src/jni/pc/peerconnection.cc | 5 + .../src/org/webrtc/CryptoOptionsTest.java | 74 +++++++++ .../api/peerconnection/RTCConfiguration.h | 8 + .../api/peerconnection/RTCConfiguration.mm | 25 +++ .../api/peerconnection/RTCCryptoOptions.h | 63 ++++++++ .../api/peerconnection/RTCCryptoOptions.mm | 33 ++++ sdk/objc/unittests/RTCConfigurationTest.mm | 26 ++++ sdk/objc/unittests/RTCPeerConnectionTest.mm | 13 ++ 21 files changed, 581 insertions(+), 10 deletions(-) create mode 100644 sdk/android/api/org/webrtc/CryptoOptions.java create mode 100644 sdk/android/src/jni/pc/cryptooptions.cc create mode 100644 sdk/android/src/jni/pc/cryptooptions.h create mode 100644 sdk/android/tests/src/org/webrtc/CryptoOptionsTest.java create mode 100644 sdk/objc/api/peerconnection/RTCCryptoOptions.h create mode 100644 sdk/objc/api/peerconnection/RTCCryptoOptions.mm diff --git a/BUILD.gn b/BUILD.gn index 1fcc310669..d4e89fde83 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -619,6 +619,7 @@ if (rtc_include_tests) { "sdk/android/tests/src/org/webrtc/GlGenericDrawerTest.java", "sdk/android/tests/src/org/webrtc/HardwareVideoEncoderTest.java", "sdk/android/tests/src/org/webrtc/ScalingSettingsTest.java", + "sdk/android/tests/src/org/webrtc/CryptoOptionsTest.java", ] deps = [ diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h index 021be7d366..6504f534e3 100644 --- a/api/peerconnectioninterface.h +++ b/api/peerconnectioninterface.h @@ -406,6 +406,7 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // Use new combined audio/video bandwidth estimation? absl::optional combined_audio_video_bwe; + // TODO(bugs.webrtc.org/9891) - Move to crypto_options // Can be used to disable DTLS-SRTP. This should never be done, but can be // useful for testing purposes, for example in setting up a loopback call // with a single PeerConnection. @@ -568,6 +569,7 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // For all other users, specify kUnifiedPlan. SdpSemantics sdp_semantics = SdpSemantics::kPlanB; + // TODO(bugs.webrtc.org/9891) - Move to crypto_options or remove. // Actively reset the SRTP parameters whenever the DTLS transports // underneath are reset for every offer/answer negotiation. // This is only intended to be a workaround for crbug.com/835958 @@ -581,6 +583,11 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // provided. bool use_media_transport = false; + // Defines advanced optional cryptographic settings related to SRTP and + // frame encryption for native WebRTC. Setting this will overwrite any + // settings set in PeerConnectionFactory (which is deprecated). + absl::optional crypto_options; + // // Don't forget to update operator== if adding something. // diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index 9dc5e663dc..08766445a9 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -706,6 +706,7 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( absl::optional network_preference; bool active_reset_srtp_params; bool use_media_transport; + absl::optional crypto_options; }; static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this), "Did you add something to RTCConfiguration and forget to " @@ -754,7 +755,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( sdp_semantics == o.sdp_semantics && network_preference == o.network_preference && active_reset_srtp_params == o.active_reset_srtp_params && - use_media_transport == o.use_media_transport; + use_media_transport == o.use_media_transport && + crypto_options == o.crypto_options; } bool PeerConnectionInterface::RTCConfiguration::operator!=( @@ -932,7 +934,11 @@ bool PeerConnection::Initialize( config.disable_encryption = options.disable_encryption; config.bundle_policy = configuration.bundle_policy; config.rtcp_mux_policy = configuration.rtcp_mux_policy; - config.crypto_options = options.crypto_options; + // TODO(bugs.webrtc.org/9891) - Remove options.crypto_options then remove this + // stub. + config.crypto_options = configuration.crypto_options.has_value() + ? *configuration.crypto_options + : options.crypto_options; config.transport_observer = this; config.event_log = event_log_.get(); #if defined(ENABLE_EXTERNAL_AUTH) @@ -1043,7 +1049,7 @@ bool PeerConnection::Initialize( } webrtc_session_desc_factory_->set_enable_encrypted_rtp_header_extensions( - options.crypto_options.srtp.enable_encrypted_rtp_header_extensions); + GetCryptoOptions().srtp.enable_encrypted_rtp_header_extensions); // Add default audio/video transceivers for Plan B SDP. if (!IsUnifiedPlan()) { @@ -2913,6 +2919,13 @@ bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration, return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error); } + if (local_description() && + configuration.crypto_options != configuration_.crypto_options) { + RTC_LOG(LS_ERROR) << "Can't change crypto_options after calling " + "SetLocalDescription."; + return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error); + } + // The simplest (and most future-compatible) way to tell if the config was // modified in an invalid way is to copy each property we do support // modifying, then use operator==. There are far more properties we don't @@ -3715,7 +3728,7 @@ void PeerConnection::GetOptionsForOffer( } session_options->rtcp_cname = rtcp_cname_; - session_options->crypto_options = factory_->options().crypto_options; + session_options->crypto_options = GetCryptoOptions(); session_options->is_unified_plan = IsUnifiedPlan(); session_options->pooled_ice_credentials = network_thread()->Invoke>( @@ -3980,7 +3993,7 @@ void PeerConnection::GetOptionsForAnswer( } session_options->rtcp_cname = rtcp_cname_; - session_options->crypto_options = factory_->options().crypto_options; + session_options->crypto_options = GetCryptoOptions(); session_options->is_unified_plan = IsUnifiedPlan(); session_options->pooled_ice_credentials = network_thread()->Invoke>( @@ -5588,8 +5601,8 @@ cricket::VoiceChannel* PeerConnection::CreateVoiceChannel( cricket::VoiceChannel* voice_channel = channel_manager()->CreateVoiceChannel( call_.get(), configuration_.media_config, rtp_transport, media_transport, - signaling_thread(), mid, SrtpRequired(), - factory_->options().crypto_options, audio_options_); + signaling_thread(), mid, SrtpRequired(), GetCryptoOptions(), + audio_options_); if (!voice_channel) { return nullptr; } @@ -5610,8 +5623,8 @@ cricket::VideoChannel* PeerConnection::CreateVideoChannel( // TODO(sukhanov): Propagate media_transport to video channel. cricket::VideoChannel* video_channel = channel_manager()->CreateVideoChannel( call_.get(), configuration_.media_config, rtp_transport, - signaling_thread(), mid, SrtpRequired(), - factory_->options().crypto_options, video_options_); + signaling_thread(), mid, SrtpRequired(), GetCryptoOptions(), + video_options_); if (!video_channel) { return nullptr; } @@ -5645,7 +5658,7 @@ bool PeerConnection::CreateDataChannel(const std::string& mid) { RtpTransportInternal* rtp_transport = GetRtpTransport(mid); rtp_data_channel_ = channel_manager()->CreateRtpDataChannel( configuration_.media_config, rtp_transport, signaling_thread(), mid, - SrtpRequired(), factory_->options().crypto_options); + SrtpRequired(), GetCryptoOptions()); if (!rtp_data_channel_) { return false; } @@ -6343,6 +6356,14 @@ PeerConnectionObserver* PeerConnection::Observer() const { return observer_; } +CryptoOptions PeerConnection::GetCryptoOptions() { + // TODO(bugs.webrtc.org/9891) - Remove PeerConnectionFactory::CryptoOptions + // after it has been removed. + return configuration_.crypto_options.has_value() + ? *configuration_.crypto_options + : factory_->options().crypto_options; +} + void PeerConnection::ClearStatsCache() { if (stats_collector_) { stats_collector_->ClearCachedStatsReport(); diff --git a/pc/peerconnection.h b/pc/peerconnection.h index 604a5d3793..e725798aca 100644 --- a/pc/peerconnection.h +++ b/pc/peerconnection.h @@ -922,6 +922,11 @@ class PeerConnection : public PeerConnectionInternal, // Returns the observer. Will crash on CHECK if the observer is removed. PeerConnectionObserver* Observer() const; + // Returns the CryptoOptions for this PeerConnection. This will always + // return the RTCConfiguration.crypto_options if set and will only default + // back to the PeerConnectionFactory settings if nothing was set. + CryptoOptions GetCryptoOptions(); + // Returns rtp transport, result can not be nullptr. RtpTransportInternal* GetRtpTransport(const std::string& mid) { auto rtp_transport = transport_controller_->GetRtpTransport(mid); diff --git a/pc/peerconnection_crypto_unittest.cc b/pc/peerconnection_crypto_unittest.cc index 1a53d860bf..d61c41c009 100644 --- a/pc/peerconnection_crypto_unittest.cc +++ b/pc/peerconnection_crypto_unittest.cc @@ -278,6 +278,28 @@ TEST_P(PeerConnectionCryptoTest, CorrectCryptoInAnswerWhenEncryptionDisabled) { answer->description())); } +// CryptoOptions has been promoted to RTCConfiguration. As such if it is ever +// set in the configuration it should overrite the settings set in the factory. +TEST_P(PeerConnectionCryptoTest, RTCConfigurationCryptoOptionOverridesFactory) { + PeerConnectionFactoryInterface::Options options; + options.crypto_options.srtp.enable_gcm_crypto_suites = true; + pc_factory_->SetOptions(options); + + RTCConfiguration config; + config.enable_dtls_srtp.emplace(false); + CryptoOptions crypto_options; + crypto_options.srtp.enable_gcm_crypto_suites = false; + config.crypto_options = crypto_options; + auto caller = CreatePeerConnectionWithAudioVideo(config); + + auto offer = caller->CreateOffer(); + ASSERT_TRUE(offer); + + ASSERT_FALSE(offer->description()->contents().empty()); + // This should exist if GCM is enabled see CorrectCryptoInOfferWithSdesAndGcm + EXPECT_FALSE(SdpContentsAll(HaveSdesGcmCryptos(3), offer->description())); +} + // When DTLS is disabled and GCM cipher suites are enabled, the SDP offer/answer // should have the correct ciphers in the SDES crypto options. // With GCM cipher suites enabled, there will be 3 cryptos in the offer and 1 @@ -297,6 +319,7 @@ TEST_P(PeerConnectionCryptoTest, CorrectCryptoInOfferWithSdesAndGcm) { ASSERT_FALSE(offer->description()->contents().empty()); EXPECT_TRUE(SdpContentsAll(HaveSdesGcmCryptos(3), offer->description())); } + TEST_P(PeerConnectionCryptoTest, CorrectCryptoInAnswerWithSdesAndGcm) { PeerConnectionFactoryInterface::Options options; options.crypto_options.srtp.enable_gcm_crypto_suites = true; diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index 03bdf3bd2a..a8a1b03d50 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -797,6 +797,8 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCConfiguration+Private.h", "objc/api/peerconnection/RTCConfiguration.h", "objc/api/peerconnection/RTCConfiguration.mm", + "objc/api/peerconnection/RTCCryptoOptions.h", + "objc/api/peerconnection/RTCCryptoOptions.mm", "objc/api/peerconnection/RTCDataChannel+Private.h", "objc/api/peerconnection/RTCDataChannel.h", "objc/api/peerconnection/RTCDataChannel.mm", @@ -1274,6 +1276,7 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCSessionDescription.h", "objc/api/peerconnection/RTCTracing.h", "objc/api/peerconnection/RTCCertificate.h", + "objc/api/peerconnection/RTCCryptoOptions.h", "objc/api/peerconnection/RTCVideoSource.h", "objc/api/peerconnection/RTCVideoTrack.h", "objc/api/video_codec/RTCVideoCodecConstants.h", @@ -1362,6 +1365,7 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCAudioTrack.h", "objc/api/peerconnection/RTCCertificate.h", "objc/api/peerconnection/RTCConfiguration.h", + "objc/api/peerconnection/RTCCryptoOptions.h", "objc/api/peerconnection/RTCDataChannel.h", "objc/api/peerconnection/RTCDataChannelConfiguration.h", "objc/api/peerconnection/RTCDtmfSender.h", diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 68cd77a669..8a3f8ccd25 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -276,6 +276,7 @@ if (is_android) { "api/org/webrtc/AudioSource.java", "api/org/webrtc/AudioTrack.java", "api/org/webrtc/CallSessionFileRotatingLogSink.java", + "api/org/webrtc/CryptoOptions.java", "api/org/webrtc/DataChannel.java", "api/org/webrtc/DtmfSender.java", "api/org/webrtc/FecControllerFactoryFactoryInterface.java", @@ -609,6 +610,8 @@ if (is_android) { "src/jni/pc/androidnetworkmonitor.h", "src/jni/pc/audiotrack.cc", "src/jni/pc/callsessionfilerotatinglogsink.cc", + "src/jni/pc/cryptooptions.cc", + "src/jni/pc/cryptooptions.h", "src/jni/pc/datachannel.cc", "src/jni/pc/datachannel.h", "src/jni/pc/dtmfsender.cc", @@ -674,6 +677,7 @@ if (is_android) { "../../rtc_base:stringutils", "../../system_wrappers:field_trial", "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/types:optional", ] } @@ -1173,6 +1177,7 @@ if (is_android) { sources = [ "api/org/webrtc/AudioTrack.java", "api/org/webrtc/CallSessionFileRotatingLogSink.java", + "api/org/webrtc/CryptoOptions.java", "api/org/webrtc/DataChannel.java", "api/org/webrtc/DtmfSender.java", "api/org/webrtc/IceCandidate.java", diff --git a/sdk/android/api/org/webrtc/CryptoOptions.java b/sdk/android/api/org/webrtc/CryptoOptions.java new file mode 100644 index 0000000000..1ccc6df71d --- /dev/null +++ b/sdk/android/api/org/webrtc/CryptoOptions.java @@ -0,0 +1,144 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +package org.webrtc; + +/** + * CryptoOptions defines advanced cryptographic settings for native WebRTC. + * These settings must be passed into RTCConfiguration. WebRTC is secur by + * default and you should not need to set any of these options unless you are + * specifically looking for an additional crypto feature such as AES_GCM + * support. This class is the Java binding of native api/crypto/cryptooptions.h + */ +public final class CryptoOptions { + /** + * SRTP Related Peer Connection Options. + */ + public final class Srtp { + /** + * Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used + * if both sides enable it + */ + private final boolean enableGcmCryptoSuites; + /** + * If set to true, the (potentially insecure) crypto cipher + * SRTP_AES128_CM_SHA1_32 will be included in the list of supported ciphers + * during negotiation. It will only be used if both peers support it and no + * other ciphers get preferred. + */ + private final boolean enableAes128Sha1_32CryptoCipher; + /** + * If set to true, encrypted RTP header extensions as defined in RFC 6904 + * will be negotiated. They will only be used if both peers support them. + */ + private final boolean enableEncryptedRtpHeaderExtensions; + + private Srtp(boolean enableGcmCryptoSuites, boolean enableAes128Sha1_32CryptoCipher, + boolean enableEncryptedRtpHeaderExtensions) { + this.enableGcmCryptoSuites = enableGcmCryptoSuites; + this.enableAes128Sha1_32CryptoCipher = enableAes128Sha1_32CryptoCipher; + this.enableEncryptedRtpHeaderExtensions = enableEncryptedRtpHeaderExtensions; + } + + @CalledByNative("Srtp") + public boolean getEnableGcmCryptoSuites() { + return enableGcmCryptoSuites; + } + + @CalledByNative("Srtp") + public boolean getEnableAes128Sha1_32CryptoCipher() { + return enableAes128Sha1_32CryptoCipher; + } + + @CalledByNative("Srtp") + public boolean getEnableEncryptedRtpHeaderExtensions() { + return enableEncryptedRtpHeaderExtensions; + } + } + + /** + * Options to be used when the FrameEncryptor / FrameDecryptor APIs are used. + */ + public final class SFrame { + /** + * If set all RtpSenders must have an FrameEncryptor attached to them before + * they are allowed to send packets. All RtpReceivers must have a + * FrameDecryptor attached to them before they are able to receive packets. + */ + private final boolean requireFrameEncryption; + + private SFrame(boolean requireFrameEncryption) { + this.requireFrameEncryption = requireFrameEncryption; + } + + @CalledByNative("SFrame") + public boolean getRequireFrameEncryption() { + return requireFrameEncryption; + } + } + + private final Srtp srtp; + private final SFrame sframe; + + private CryptoOptions(boolean enableGcmCryptoSuites, boolean enableAes128Sha1_32CryptoCipher, + boolean enableEncryptedRtpHeaderExtensions, boolean requireFrameEncryption) { + this.srtp = new Srtp( + enableGcmCryptoSuites, enableAes128Sha1_32CryptoCipher, enableEncryptedRtpHeaderExtensions); + this.sframe = new SFrame(requireFrameEncryption); + } + + public static Builder builder() { + return new Builder(); + } + + @CalledByNative + public Srtp getSrtp() { + return srtp; + } + + @CalledByNative + public SFrame getSFrame() { + return sframe; + } + + public static class Builder { + private boolean enableGcmCryptoSuites = false; + private boolean enableAes128Sha1_32CryptoCipher = false; + private boolean enableEncryptedRtpHeaderExtensions = false; + private boolean requireFrameEncryption = false; + + private Builder() {} + + public Builder setEnableGcmCryptoSuites(boolean enableGcmCryptoSuites) { + this.enableGcmCryptoSuites = enableGcmCryptoSuites; + return this; + } + + public Builder setEnableAes128Sha1_32CryptoCipher(boolean enableAes128Sha1_32CryptoCipher) { + this.enableAes128Sha1_32CryptoCipher = enableAes128Sha1_32CryptoCipher; + return this; + } + + public Builder setEnableEncryptedRtpHeaderExtensions( + boolean enableEncryptedRtpHeaderExtensions) { + this.enableEncryptedRtpHeaderExtensions = enableEncryptedRtpHeaderExtensions; + return this; + } + + public Builder setRequireFrameEncryption(boolean requireFrameEncryption) { + this.requireFrameEncryption = requireFrameEncryption; + return this; + } + + public CryptoOptions createCryptoOptions() { + return new CryptoOptions(enableGcmCryptoSuites, enableAes128Sha1_32CryptoCipher, + enableEncryptedRtpHeaderExtensions, requireFrameEncryption); + } + } +} diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index d50819c87b..1cb5717b4e 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java @@ -468,6 +468,13 @@ public class PeerConnection { */ public boolean useMediaTransport; + /** + * Defines advanced optional cryptographic settings related to SRTP and + * frame encryption for native WebRTC. Setting this will overwrite any + * options set through the PeerConnectionFactory (which is deprecated). + */ + @Nullable public CryptoOptions cryptoOptions; + // TODO(deadbeef): Instead of duplicating the defaults here, we should do // something to pick up the defaults from C++. The Objective-C equivalent // of RTCConfiguration does that. @@ -508,6 +515,7 @@ public class PeerConnection { sdpSemantics = SdpSemantics.PLAN_B; activeResetSrtpParams = false; useMediaTransport = false; + cryptoOptions = null; } @CalledByNative("RTCConfiguration") @@ -711,6 +719,12 @@ public class PeerConnection { boolean getUseMediaTransport() { return useMediaTransport; } + + @Nullable + @CalledByNative("RTCConfiguration") + CryptoOptions getCryptoOptions() { + return cryptoOptions; + } }; private final List localStreams = new ArrayList<>(); diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java index fdc29bbae9..5e2289cb8c 100644 --- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java +++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java @@ -123,6 +123,9 @@ public class PeerConnectionFactory { public boolean disableEncryption; public boolean disableNetworkMonitor; + // TODO(webrtc:9891) - The below crypto options are deprecated. Please use + // RTCConfiguration to set these options instead. They will be removed in + // a future release. /** * If set to true, the (potentially insecure) crypto cipher SRTP_AES128_CM_SHA1_32 * will be included in the list of supported ciphers during negotiation. It will only @@ -158,16 +161,19 @@ public class PeerConnectionFactory { return disableNetworkMonitor; } + @Deprecated @CalledByNative("Options") boolean getEnableAes128Sha1_32CryptoCipher() { return enableAes128Sha1_32CryptoCipher; } + @Deprecated @CalledByNative("Options") boolean getEnableGcmCryptoSuites() { return enableGcmCryptoSuites; } + @Deprecated @CalledByNative("Options") boolean getRequireFrameEncryption() { return requireFrameEncryption; diff --git a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java index 894e2bde3c..cd24037daf 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java @@ -682,6 +682,27 @@ public class PeerConnectionTest { assertEquals(originalCert.certificate, restoredCert.certificate); } + @Test + @SmallTest + public void testCreationWithCryptoOptions() throws Exception { + PeerConnectionFactory factory = PeerConnectionFactory.builder().createPeerConnectionFactory(); + PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(Arrays.asList()); + + assertNull(config.cryptoOptions); + + CryptoOptions cryptoOptions = CryptoOptions.builder() + .setEnableGcmCryptoSuites(true) + .setEnableAes128Sha1_32CryptoCipher(true) + .setEnableEncryptedRtpHeaderExtensions(true) + .setRequireFrameEncryption(true) + .createCryptoOptions(); + config.cryptoOptions = cryptoOptions; + + ObserverExpectations offeringExpectations = new ObserverExpectations("PCTest:offerer"); + PeerConnection offeringPC = factory.createPeerConnection(config, offeringExpectations); + assertNotNull(offeringPC); + } + @Test @MediumTest public void testCompleteSession() throws Exception { diff --git a/sdk/android/src/jni/pc/cryptooptions.cc b/sdk/android/src/jni/pc/cryptooptions.cc new file mode 100644 index 0000000000..0f38b13f78 --- /dev/null +++ b/sdk/android/src/jni/pc/cryptooptions.cc @@ -0,0 +1,43 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "sdk/android/src/jni/pc/cryptooptions.h" + +#include "sdk/android/generated_peerconnection_jni/jni/CryptoOptions_jni.h" + +namespace webrtc { +namespace jni { + +absl::optional JavaToNativeOptionalCryptoOptions( + JNIEnv* jni, + const JavaRef& j_crypto_options) { + if (j_crypto_options.is_null()) { + return absl::nullopt; + } + + ScopedJavaLocalRef j_srtp = + Java_CryptoOptions_getSrtp(jni, j_crypto_options); + ScopedJavaLocalRef j_sframe = + Java_CryptoOptions_getSFrame(jni, j_crypto_options); + + CryptoOptions native_crypto_options; + native_crypto_options.srtp.enable_gcm_crypto_suites = + Java_Srtp_getEnableGcmCryptoSuites(jni, j_srtp); + native_crypto_options.srtp.enable_aes128_sha1_32_crypto_cipher = + Java_Srtp_getEnableAes128Sha1_32CryptoCipher(jni, j_srtp); + native_crypto_options.srtp.enable_encrypted_rtp_header_extensions = + Java_Srtp_getEnableEncryptedRtpHeaderExtensions(jni, j_srtp); + native_crypto_options.sframe.require_frame_encryption = + Java_SFrame_getRequireFrameEncryption(jni, j_sframe); + return absl::optional(native_crypto_options); +} + +} // namespace jni +} // namespace webrtc diff --git a/sdk/android/src/jni/pc/cryptooptions.h b/sdk/android/src/jni/pc/cryptooptions.h new file mode 100644 index 0000000000..9890264a55 --- /dev/null +++ b/sdk/android/src/jni/pc/cryptooptions.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef SDK_ANDROID_SRC_JNI_PC_CRYPTOOPTIONS_H_ +#define SDK_ANDROID_SRC_JNI_PC_CRYPTOOPTIONS_H_ + +#include + +#include "absl/types/optional.h" +#include "api/crypto/cryptooptions.h" +#include "sdk/android/native_api/jni/scoped_java_ref.h" + +namespace webrtc { +namespace jni { + +absl::optional JavaToNativeOptionalCryptoOptions( + JNIEnv* jni, + const JavaRef& j_crypto_options); + +} // namespace jni +} // namespace webrtc + +#endif // SDK_ANDROID_SRC_JNI_PC_CRYPTOOPTIONS_H_ diff --git a/sdk/android/src/jni/pc/peerconnection.cc b/sdk/android/src/jni/pc/peerconnection.cc index 8a29199cf3..0d51847575 100644 --- a/sdk/android/src/jni/pc/peerconnection.cc +++ b/sdk/android/src/jni/pc/peerconnection.cc @@ -43,6 +43,7 @@ #include "sdk/android/generated_peerconnection_jni/jni/PeerConnection_jni.h" #include "sdk/android/native_api/jni/java_types.h" #include "sdk/android/src/jni/jni_helpers.h" +#include "sdk/android/src/jni/pc/cryptooptions.h" #include "sdk/android/src/jni/pc/datachannel.h" #include "sdk/android/src/jni/pc/icecandidate.h" #include "sdk/android/src/jni/pc/mediaconstraints.h" @@ -146,6 +147,8 @@ void JavaToNativeRTCConfiguration( Java_RTCConfiguration_getNetworkPreference(jni, j_rtc_config); ScopedJavaLocalRef j_sdp_semantics = Java_RTCConfiguration_getSdpSemantics(jni, j_rtc_config); + ScopedJavaLocalRef j_crypto_options = + Java_RTCConfiguration_getCryptoOptions(jni, j_rtc_config); rtc_config->type = JavaToNativeIceTransportsType(jni, j_ice_transports_type); rtc_config->bundle_policy = JavaToNativeBundlePolicy(jni, j_bundle_policy); @@ -246,6 +249,8 @@ void JavaToNativeRTCConfiguration( Java_RTCConfiguration_getActiveResetSrtpParams(jni, j_rtc_config); rtc_config->use_media_transport = Java_RTCConfiguration_getUseMediaTransport(jni, j_rtc_config); + rtc_config->crypto_options = + JavaToNativeOptionalCryptoOptions(jni, j_crypto_options); } rtc::KeyType GetRtcConfigKeyType(JNIEnv* env, diff --git a/sdk/android/tests/src/org/webrtc/CryptoOptionsTest.java b/sdk/android/tests/src/org/webrtc/CryptoOptionsTest.java new file mode 100644 index 0000000000..f03811e6fc --- /dev/null +++ b/sdk/android/tests/src/org/webrtc/CryptoOptionsTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2018 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +package org.webrtc; + +import static com.google.common.truth.Truth.assertThat; + +import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; +import org.webrtc.CryptoOptions; + +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class CryptoOptionsTest { + // Validates the builder builds by default all false options. + @Test + public void testBuilderDefaultsAreFalse() { + CryptoOptions cryptoOptions = CryptoOptions.builder().createCryptoOptions(); + assertThat(cryptoOptions.getSrtp().getEnableGcmCryptoSuites()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableAes128Sha1_32CryptoCipher()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableEncryptedRtpHeaderExtensions()).isFalse(); + assertThat(cryptoOptions.getSFrame().getRequireFrameEncryption()).isFalse(); + } + + // Validates the builder sets the correct parameters. + @Test + public void testBuilderCorrectlyInitializingGcmCrypto() { + CryptoOptions cryptoOptions = + CryptoOptions.builder().setEnableGcmCryptoSuites(true).createCryptoOptions(); + assertThat(cryptoOptions.getSrtp().getEnableGcmCryptoSuites()).isTrue(); + assertThat(cryptoOptions.getSrtp().getEnableAes128Sha1_32CryptoCipher()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableEncryptedRtpHeaderExtensions()).isFalse(); + assertThat(cryptoOptions.getSFrame().getRequireFrameEncryption()).isFalse(); + } + + @Test + public void testBuilderCorrectlyInitializingAes128Sha1_32CryptoCipher() { + CryptoOptions cryptoOptions = + CryptoOptions.builder().setEnableAes128Sha1_32CryptoCipher(true).createCryptoOptions(); + assertThat(cryptoOptions.getSrtp().getEnableGcmCryptoSuites()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableAes128Sha1_32CryptoCipher()).isTrue(); + assertThat(cryptoOptions.getSrtp().getEnableEncryptedRtpHeaderExtensions()).isFalse(); + assertThat(cryptoOptions.getSFrame().getRequireFrameEncryption()).isFalse(); + } + + @Test + public void testBuilderCorrectlyInitializingEncryptedRtpHeaderExtensions() { + CryptoOptions cryptoOptions = + CryptoOptions.builder().setEnableEncryptedRtpHeaderExtensions(true).createCryptoOptions(); + assertThat(cryptoOptions.getSrtp().getEnableGcmCryptoSuites()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableAes128Sha1_32CryptoCipher()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableEncryptedRtpHeaderExtensions()).isTrue(); + assertThat(cryptoOptions.getSFrame().getRequireFrameEncryption()).isFalse(); + } + + @Test + public void testBuilderCorrectlyInitializingRequireFrameEncryption() { + CryptoOptions cryptoOptions = + CryptoOptions.builder().setRequireFrameEncryption(true).createCryptoOptions(); + assertThat(cryptoOptions.getSrtp().getEnableGcmCryptoSuites()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableAes128Sha1_32CryptoCipher()).isFalse(); + assertThat(cryptoOptions.getSrtp().getEnableEncryptedRtpHeaderExtensions()).isFalse(); + assertThat(cryptoOptions.getSFrame().getRequireFrameEncryption()).isTrue(); + } +} diff --git a/sdk/objc/api/peerconnection/RTCConfiguration.h b/sdk/objc/api/peerconnection/RTCConfiguration.h index c7998a5aa2..9f41fd28d2 100644 --- a/sdk/objc/api/peerconnection/RTCConfiguration.h +++ b/sdk/objc/api/peerconnection/RTCConfiguration.h @@ -11,6 +11,7 @@ #import #import "RTCCertificate.h" +#import "RTCCryptoOptions.h" #import "RTCMacros.h" @class RTCIceServer; @@ -174,6 +175,13 @@ RTC_OBJC_EXPORT */ @property(nonatomic, assign) BOOL useMediaTransport; +/** + * Defines advanced optional cryptographic settings related to SRTP and + * frame encryption for native WebRTC. Setting this will overwrite any + * options set through the PeerConnectionFactory (which is deprecated). + */ +@property(nonatomic, nullable) RTCCryptoOptions *cryptoOptions; + - (instancetype)init; @end diff --git a/sdk/objc/api/peerconnection/RTCConfiguration.mm b/sdk/objc/api/peerconnection/RTCConfiguration.mm index bdf4fb6e43..35cdc466e9 100644 --- a/sdk/objc/api/peerconnection/RTCConfiguration.mm +++ b/sdk/objc/api/peerconnection/RTCConfiguration.mm @@ -49,6 +49,7 @@ @synthesize turnCustomizer = _turnCustomizer; @synthesize activeResetSrtpParams = _activeResetSrtpParams; @synthesize useMediaTransport = _useMediaTransport; +@synthesize cryptoOptions = _cryptoOptions; - (instancetype)init { // Copy defaults. @@ -111,6 +112,17 @@ _sdpSemantics = [[self class] sdpSemanticsForNativeSdpSemantics:config.sdp_semantics]; _turnCustomizer = config.turn_customizer; _activeResetSrtpParams = config.active_reset_srtp_params; + if (config.crypto_options) { + _cryptoOptions = [[RTCCryptoOptions alloc] + initWithSrtpEnableGcmCryptoSuites:config.crypto_options->srtp + .enable_gcm_crypto_suites + srtpEnableAes128Sha1_32CryptoCipher:config.crypto_options->srtp + .enable_aes128_sha1_32_crypto_cipher + srtpEnableEncryptedRtpHeaderExtensions:config.crypto_options->srtp + .enable_encrypted_rtp_header_extensions + sframeRequireFrameEncryption:config.crypto_options->sframe + .require_frame_encryption]; + } } return self; } @@ -224,6 +236,19 @@ nativeConfig->turn_customizer = _turnCustomizer; } nativeConfig->active_reset_srtp_params = _activeResetSrtpParams ? true : false; + if (_cryptoOptions) { + webrtc::CryptoOptions nativeCryptoOptions; + nativeCryptoOptions.srtp.enable_gcm_crypto_suites = + _cryptoOptions.srtpEnableGcmCryptoSuites ? true : false; + nativeCryptoOptions.srtp.enable_aes128_sha1_32_crypto_cipher = + _cryptoOptions.srtpEnableAes128Sha1_32CryptoCipher ? true : false; + nativeCryptoOptions.srtp.enable_encrypted_rtp_header_extensions = + _cryptoOptions.srtpEnableEncryptedRtpHeaderExtensions ? true : false; + nativeCryptoOptions.sframe.require_frame_encryption = + _cryptoOptions.sframeRequireFrameEncryption ? true : false; + nativeConfig->crypto_options = absl::optional(nativeCryptoOptions); + } + return nativeConfig.release(); } diff --git a/sdk/objc/api/peerconnection/RTCCryptoOptions.h b/sdk/objc/api/peerconnection/RTCCryptoOptions.h new file mode 100644 index 0000000000..b465bb5a73 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCCryptoOptions.h @@ -0,0 +1,63 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import + +#import "RTCMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Objective-C bindings for webrtc::CryptoOptions. This API had to be flattened + * as Objective-C doesn't support nested structures. + */ +RTC_OBJC_EXPORT +@interface RTCCryptoOptions : NSObject + +/** + * Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used + * if both sides enable it + */ +@property(nonatomic, assign) BOOL srtpEnableGcmCryptoSuites; +/** + * If set to true, the (potentially insecure) crypto cipher + * SRTP_AES128_CM_SHA1_32 will be included in the list of supported ciphers + * during negotiation. It will only be used if both peers support it and no + * other ciphers get preferred. + */ +@property(nonatomic, assign) BOOL srtpEnableAes128Sha1_32CryptoCipher; +/** + * If set to true, encrypted RTP header extensions as defined in RFC 6904 + * will be negotiated. They will only be used if both peers support them. + */ +@property(nonatomic, assign) BOOL srtpEnableEncryptedRtpHeaderExtensions; + +/** + * If set all RtpSenders must have an FrameEncryptor attached to them before + * they are allowed to send packets. All RtpReceivers must have a + * FrameDecryptor attached to them before they are able to receive packets. + */ +@property(nonatomic, assign) BOOL sframeRequireFrameEncryption; + +/** + * Initializes CryptoOptions with all possible options set explicitly. This + * is done when converting from a native RTCConfiguration.crypto_options. + */ +- (instancetype)initWithSrtpEnableGcmCryptoSuites:(BOOL)srtpEnableGcmCryptoSuites + srtpEnableAes128Sha1_32CryptoCipher:(BOOL)srtpEnableAes128Sha1_32CryptoCipher + srtpEnableEncryptedRtpHeaderExtensions:(BOOL)srtpEnableEncryptedRtpHeaderExtensions + sframeRequireFrameEncryption:(BOOL)sframeRequireFrameEncryption + NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCCryptoOptions.mm b/sdk/objc/api/peerconnection/RTCCryptoOptions.mm new file mode 100644 index 0000000000..a059f75599 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCCryptoOptions.mm @@ -0,0 +1,33 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import "RTCCryptoOptions.h" + +@implementation RTCCryptoOptions + +@synthesize srtpEnableGcmCryptoSuites = _srtpEnableGcmCryptoSuites; +@synthesize srtpEnableAes128Sha1_32CryptoCipher = _srtpEnableAes128Sha1_32CryptoCipher; +@synthesize srtpEnableEncryptedRtpHeaderExtensions = _srtpEnableEncryptedRtpHeaderExtensions; +@synthesize sframeRequireFrameEncryption = _sframeRequireFrameEncryption; + +- (instancetype)initWithSrtpEnableGcmCryptoSuites:(BOOL)srtpEnableGcmCryptoSuites + srtpEnableAes128Sha1_32CryptoCipher:(BOOL)srtpEnableAes128Sha1_32CryptoCipher + srtpEnableEncryptedRtpHeaderExtensions:(BOOL)srtpEnableEncryptedRtpHeaderExtensions + sframeRequireFrameEncryption:(BOOL)sframeRequireFrameEncryption { + if (self = [super init]) { + _srtpEnableGcmCryptoSuites = srtpEnableGcmCryptoSuites; + _srtpEnableAes128Sha1_32CryptoCipher = srtpEnableAes128Sha1_32CryptoCipher; + _srtpEnableEncryptedRtpHeaderExtensions = srtpEnableEncryptedRtpHeaderExtensions; + _sframeRequireFrameEncryption = sframeRequireFrameEncryption; + } + return self; +} + +@end diff --git a/sdk/objc/unittests/RTCConfigurationTest.mm b/sdk/objc/unittests/RTCConfigurationTest.mm index 1ef718ad49..67a303e550 100644 --- a/sdk/objc/unittests/RTCConfigurationTest.mm +++ b/sdk/objc/unittests/RTCConfigurationTest.mm @@ -50,6 +50,10 @@ RTCContinualGatheringPolicyGatherContinually; config.shouldPruneTurnPorts = YES; config.iceRegatherIntervalRange = range; + config.cryptoOptions = [[RTCCryptoOptions alloc] initWithSrtpEnableGcmCryptoSuites:YES + srtpEnableAes128Sha1_32CryptoCipher:YES + srtpEnableEncryptedRtpHeaderExtensions:YES + sframeRequireFrameEncryption:YES]; std::unique_ptr nativeConfig([config createNativeConfiguration]); @@ -78,6 +82,10 @@ EXPECT_EQ(true, nativeConfig->prune_turn_ports); EXPECT_EQ(range.min, nativeConfig->ice_regather_interval_range->min()); EXPECT_EQ(range.max, nativeConfig->ice_regather_interval_range->max()); + EXPECT_EQ(true, nativeConfig->crypto_options->srtp.enable_gcm_crypto_suites); + EXPECT_EQ(true, nativeConfig->crypto_options->srtp.enable_aes128_sha1_32_crypto_cipher); + EXPECT_EQ(true, nativeConfig->crypto_options->srtp.enable_encrypted_rtp_header_extensions); + EXPECT_EQ(true, nativeConfig->crypto_options->sframe.require_frame_encryption); } - (void)testNativeConversionToConfiguration { @@ -103,6 +111,10 @@ RTCContinualGatheringPolicyGatherContinually; config.shouldPruneTurnPorts = YES; config.iceRegatherIntervalRange = range; + config.cryptoOptions = [[RTCCryptoOptions alloc] initWithSrtpEnableGcmCryptoSuites:YES + srtpEnableAes128Sha1_32CryptoCipher:NO + srtpEnableEncryptedRtpHeaderExtensions:NO + sframeRequireFrameEncryption:NO]; webrtc::PeerConnectionInterface::RTCConfiguration *nativeConfig = [config createNativeConfiguration]; @@ -130,6 +142,19 @@ EXPECT_EQ(config.shouldPruneTurnPorts, newConfig.shouldPruneTurnPorts); EXPECT_EQ(config.iceRegatherIntervalRange.min, newConfig.iceRegatherIntervalRange.min); EXPECT_EQ(config.iceRegatherIntervalRange.max, newConfig.iceRegatherIntervalRange.max); + EXPECT_EQ(config.cryptoOptions.srtpEnableGcmCryptoSuites, + newConfig.cryptoOptions.srtpEnableGcmCryptoSuites); + EXPECT_EQ(config.cryptoOptions.srtpEnableAes128Sha1_32CryptoCipher, + newConfig.cryptoOptions.srtpEnableAes128Sha1_32CryptoCipher); + EXPECT_EQ(config.cryptoOptions.srtpEnableEncryptedRtpHeaderExtensions, + newConfig.cryptoOptions.srtpEnableEncryptedRtpHeaderExtensions); + EXPECT_EQ(config.cryptoOptions.sframeRequireFrameEncryption, + newConfig.cryptoOptions.sframeRequireFrameEncryption); +} + +- (void)testDefaultValues { + RTCConfiguration *config = [[RTCConfiguration alloc] init]; + EXPECT_EQ(config.cryptoOptions, nil); } @end @@ -139,5 +164,6 @@ TEST(RTCConfigurationTest, NativeConfigurationConversionTest) { RTCConfigurationTest *test = [[RTCConfigurationTest alloc] init]; [test testConversionToNativeConfiguration]; [test testNativeConversionToConfiguration]; + [test testDefaultValues]; } } diff --git a/sdk/objc/unittests/RTCPeerConnectionTest.mm b/sdk/objc/unittests/RTCPeerConnectionTest.mm index 28fdee6a2b..3532258799 100644 --- a/sdk/objc/unittests/RTCPeerConnectionTest.mm +++ b/sdk/objc/unittests/RTCPeerConnectionTest.mm @@ -16,6 +16,7 @@ #import "api/peerconnection/RTCConfiguration+Private.h" #import "api/peerconnection/RTCConfiguration.h" +#import "api/peerconnection/RTCCryptoOptions.h" #import "api/peerconnection/RTCIceServer.h" #import "api/peerconnection/RTCMediaConstraints.h" #import "api/peerconnection/RTCPeerConnection.h" @@ -50,6 +51,10 @@ RTCContinualGatheringPolicyGatherContinually; config.shouldPruneTurnPorts = YES; config.activeResetSrtpParams = YES; + config.cryptoOptions = [[RTCCryptoOptions alloc] initWithSrtpEnableGcmCryptoSuites:YES + srtpEnableAes128Sha1_32CryptoCipher:YES + srtpEnableEncryptedRtpHeaderExtensions:NO + sframeRequireFrameEncryption:NO]; RTCMediaConstraints *contraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{} optionalConstraints:nil]; @@ -89,6 +94,14 @@ EXPECT_EQ(config.continualGatheringPolicy, newConfig.continualGatheringPolicy); EXPECT_EQ(config.shouldPruneTurnPorts, newConfig.shouldPruneTurnPorts); EXPECT_EQ(config.activeResetSrtpParams, newConfig.activeResetSrtpParams); + EXPECT_EQ(config.cryptoOptions.srtpEnableGcmCryptoSuites, + newConfig.cryptoOptions.srtpEnableGcmCryptoSuites); + EXPECT_EQ(config.cryptoOptions.srtpEnableAes128Sha1_32CryptoCipher, + newConfig.cryptoOptions.srtpEnableAes128Sha1_32CryptoCipher); + EXPECT_EQ(config.cryptoOptions.srtpEnableEncryptedRtpHeaderExtensions, + newConfig.cryptoOptions.srtpEnableEncryptedRtpHeaderExtensions); + EXPECT_EQ(config.cryptoOptions.sframeRequireFrameEncryption, + newConfig.cryptoOptions.sframeRequireFrameEncryption); } @end