diff --git a/api/crypto/cryptooptions.cc b/api/crypto/cryptooptions.cc index 2c34822b28..7f34f19b53 100644 --- a/api/crypto/cryptooptions.cc +++ b/api/crypto/cryptooptions.cc @@ -17,6 +17,7 @@ CryptoOptions::CryptoOptions() {} CryptoOptions::CryptoOptions(const CryptoOptions& other) { srtp = other.srtp; + sframe = other.sframe; } CryptoOptions::~CryptoOptions() {} @@ -46,4 +47,32 @@ std::vector CryptoOptions::GetSupportedDtlsSrtpCryptoSuites() const { return crypto_suites; } +bool CryptoOptions::operator==(const CryptoOptions& other) const { + struct data_being_tested_for_equality { + struct Srtp { + bool enable_gcm_crypto_suites; + bool enable_aes128_sha1_32_crypto_cipher; + bool enable_encrypted_rtp_header_extensions; + } srtp; + struct SFrame { + bool require_frame_encryption; + } sframe; + }; + static_assert(sizeof(data_being_tested_for_equality) == sizeof(*this), + "Did you add something to CryptoOptions and forget to " + "update operator==?"); + + return srtp.enable_gcm_crypto_suites == other.srtp.enable_gcm_crypto_suites && + srtp.enable_aes128_sha1_32_crypto_cipher == + other.srtp.enable_aes128_sha1_32_crypto_cipher && + srtp.enable_encrypted_rtp_header_extensions == + other.srtp.enable_encrypted_rtp_header_extensions && + sframe.require_frame_encryption == + other.sframe.require_frame_encryption; +} + +bool CryptoOptions::operator!=(const CryptoOptions& other) const { + return !(*this == other); +} + } // namespace webrtc diff --git a/api/crypto/cryptooptions.h b/api/crypto/cryptooptions.h index de674c25c6..bd4a1c4ad1 100644 --- a/api/crypto/cryptooptions.h +++ b/api/crypto/cryptooptions.h @@ -33,6 +33,9 @@ struct CryptoOptions { // of crypto options. std::vector GetSupportedDtlsSrtpCryptoSuites() const; + bool operator==(const CryptoOptions& other) const; + bool operator!=(const CryptoOptions& other) const; + // SRTP Related Peer Connection options. struct Srtp { // Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used @@ -49,6 +52,14 @@ struct CryptoOptions { // will be negotiated. They will only be used if both peers support them. bool enable_encrypted_rtp_header_extensions = false; } srtp; + + // Options to be used when the FrameEncryptor / FrameDecryptor APIs are used. + struct 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. + bool require_frame_encryption = false; + } sframe; }; } // namespace webrtc diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index 563e8a036a..bf06cd258a 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -76,7 +76,7 @@ std::unique_ptr CreateChannelAndProxy( config.rtcp_send_transport, event_log, config.rtp.remote_ssrc, config.jitter_buffer_max_packets, config.jitter_buffer_fast_accelerate, config.decoder_factory, - config.codec_pair_id, config.frame_decryptor)); + config.codec_pair_id, config.frame_decryptor, config.crypto_options)); } } // namespace diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc index 49d933c3f4..39cb4e8017 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -51,11 +51,12 @@ std::unique_ptr CreateChannelAndProxy( ProcessThread* module_process_thread, RtcpRttStats* rtcp_rtt_stats, RtcEventLog* event_log, - FrameEncryptorInterface* frame_encryptor) { + FrameEncryptorInterface* frame_encryptor, + const webrtc::CryptoOptions& crypto_options) { return absl::make_unique( absl::make_unique(worker_queue, module_process_thread, rtcp_rtt_stats, event_log, - frame_encryptor)); + frame_encryptor, crypto_options)); } } // namespace @@ -106,7 +107,8 @@ AudioSendStream::AudioSendStream( module_process_thread, rtcp_rtt_stats, event_log, - config.frame_encryptor)) {} + config.frame_encryptor, + config.crypto_options)) {} AudioSendStream::AudioSendStream( const webrtc::AudioSendStream::Config& config, diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc index e9f7503474..238499909d 100644 --- a/audio/channel_receive.cc +++ b/audio/channel_receive.cc @@ -206,7 +206,8 @@ ChannelReceive::ChannelReceive( bool jitter_buffer_fast_playout, rtc::scoped_refptr decoder_factory, absl::optional codec_pair_id, - FrameDecryptorInterface* frame_decryptor) + FrameDecryptorInterface* frame_decryptor, + const webrtc::CryptoOptions& crypto_options) : event_log_(rtc_event_log), rtp_receive_statistics_( ReceiveStatistics::Create(Clock::GetRealTimeClock())), @@ -222,7 +223,8 @@ ChannelReceive::ChannelReceive( _audioDeviceModulePtr(audio_device_module), _outputGain(1.0f), associated_send_channel_(nullptr), - frame_decryptor_(frame_decryptor) { + frame_decryptor_(frame_decryptor), + crypto_options_(crypto_options) { RTC_DCHECK(module_process_thread); RTC_DCHECK(audio_device_module); AudioCodingModule::Config acm_config; @@ -429,6 +431,10 @@ bool ChannelReceive::ReceivePacket(const uint8_t* packet, // Update the final payload. payload = decrypted_audio_payload.data(); payload_data_length = decrypted_audio_payload.size(); + } else if (crypto_options_.sframe.require_frame_encryption) { + RTC_DLOG(LS_ERROR) + << "FrameDecryptor required but not set, dropping packet"; + payload_data_length = 0; } if (payload_data_length == 0) { diff --git a/audio/channel_receive.h b/audio/channel_receive.h index 82eb4dff0c..ac359bb62f 100644 --- a/audio/channel_receive.h +++ b/audio/channel_receive.h @@ -19,6 +19,7 @@ #include "api/audio/audio_mixer.h" #include "api/call/audio_sink.h" #include "api/call/transport.h" +#include "api/crypto/cryptooptions.h" #include "api/rtpreceiverinterface.h" #include "audio/audio_level.h" #include "call/syncable.h" @@ -114,7 +115,8 @@ class ChannelReceive : public RtpData { bool jitter_buffer_fast_playout, rtc::scoped_refptr decoder_factory, absl::optional codec_pair_id, - FrameDecryptorInterface* frame_decryptor); + FrameDecryptorInterface* frame_decryptor, + const webrtc::CryptoOptions& crypto_options); virtual ~ChannelReceive(); void SetSink(AudioSinkInterface* sink); @@ -259,6 +261,7 @@ class ChannelReceive : public RtpData { // E2EE Audio Frame Decryption FrameDecryptorInterface* frame_decryptor_ = nullptr; + webrtc::CryptoOptions crypto_options_; }; } // namespace voe diff --git a/audio/channel_send.cc b/audio/channel_send.cc index 8639fbd814..bdabe8f2b5 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -289,6 +289,10 @@ int32_t ChannelSend::SendData(FrameType frameType, // Rewrite the payloadData and size to the new encrypted payload. payloadData = encrypted_audio_payload.data(); payloadSize = encrypted_audio_payload.size(); + } else if (crypto_options_.sframe.require_frame_encryption) { + RTC_DLOG(LS_ERROR) << "Channel::SendData() failed sending audio payload: " + << "A frame encryptor is required but one is not set."; + return -1; } // Push data from ACM to RTP/RTCP-module to deliver audio frame for @@ -354,7 +358,8 @@ ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue, ProcessThread* module_process_thread, RtcpRttStats* rtcp_rtt_stats, RtcEventLog* rtc_event_log, - FrameEncryptorInterface* frame_encryptor) + FrameEncryptorInterface* frame_encryptor, + const webrtc::CryptoOptions& crypto_options) : event_log_(rtc_event_log), _timeStamp(0), // This is just an offset, RTP module will add it's own // random offset @@ -375,7 +380,8 @@ ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue, use_twcc_plr_for_ana_( webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"), encoder_queue_(encoder_queue), - frame_encryptor_(frame_encryptor) { + frame_encryptor_(frame_encryptor), + crypto_options_(crypto_options) { RTC_DCHECK(module_process_thread); RTC_DCHECK(encoder_queue); audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config())); diff --git a/audio/channel_send.h b/audio/channel_send.h index ef92f8e84e..306d6a8b3e 100644 --- a/audio/channel_send.h +++ b/audio/channel_send.h @@ -19,6 +19,7 @@ #include "api/audio/audio_frame.h" #include "api/audio_codecs/audio_encoder.h" #include "api/call/transport.h" +#include "api/crypto/cryptooptions.h" #include "common_types.h" // NOLINT(build/include) #include "modules/audio_coding/include/audio_coding_module.h" #include "modules/audio_processing/rms_level.h" @@ -120,7 +121,8 @@ class ChannelSend ProcessThread* module_process_thread, RtcpRttStats* rtcp_rtt_stats, RtcEventLog* rtc_event_log, - FrameEncryptorInterface* frame_encryptor); + FrameEncryptorInterface* frame_encryptor, + const webrtc::CryptoOptions& crypto_options); virtual ~ChannelSend(); @@ -298,6 +300,8 @@ class ChannelSend // E2EE Audio Frame Encryption FrameEncryptorInterface* frame_encryptor_ = nullptr; + // E2EE Frame Encryption Options + webrtc::CryptoOptions crypto_options_; }; } // namespace voe diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h index 9c890b1cda..786c3bacd7 100644 --- a/call/audio_receive_stream.h +++ b/call/audio_receive_stream.h @@ -19,6 +19,7 @@ #include "absl/types/optional.h" #include "api/audio_codecs/audio_decoder_factory.h" #include "api/call/transport.h" +#include "api/crypto/cryptooptions.h" #include "api/rtpparameters.h" #include "api/rtpreceiverinterface.h" #include "call/rtp_config.h" @@ -122,6 +123,9 @@ class AudioReceiveStream { absl::optional codec_pair_id; + // Per PeerConnection crypto options. + webrtc::CryptoOptions crypto_options; + // An optional custom frame decryptor that allows the entire frame to be // decrypted in whatever way the caller choses. This is not required by // default. diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h index 61e2531222..a659dd68cb 100644 --- a/call/audio_send_stream.h +++ b/call/audio_send_stream.h @@ -21,6 +21,7 @@ #include "api/audio_codecs/audio_encoder_factory.h" #include "api/audio_codecs/audio_format.h" #include "api/call/transport.h" +#include "api/crypto/cryptooptions.h" #include "api/crypto/frameencryptorinterface.h" #include "api/rtpparameters.h" #include "call/rtp_config.h" @@ -130,6 +131,9 @@ class AudioSendStream { // Track ID as specified during track creation. std::string track_id; + // Per PeerConnection crypto options. + webrtc::CryptoOptions crypto_options; + // An optional custom frame encryptor that allows the entire frame to be // encryptor in whatever way the caller choses. This is not required by // default. diff --git a/media/base/fakemediaengine.h b/media/base/fakemediaengine.h index 62bd6ba5ba..a20beb0f28 100644 --- a/media/base/fakemediaengine.h +++ b/media/base/fakemediaengine.h @@ -776,9 +776,11 @@ class FakeVoiceEngine : public FakeBaseEngine { return rtc::scoped_refptr(); } - VoiceMediaChannel* CreateChannel(webrtc::Call* call, - const MediaConfig& config, - const AudioOptions& options) { + VoiceMediaChannel* CreateChannel( + webrtc::Call* call, + const MediaConfig& config, + const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options) { if (fail_create_channel_) { return nullptr; } @@ -837,7 +839,8 @@ class FakeVideoEngine : public FakeBaseEngine { VideoMediaChannel* CreateChannel(webrtc::Call* call, const MediaConfig& config, - const VideoOptions& options) { + const VideoOptions& options, + const webrtc::CryptoOptions crypto_options) { if (fail_create_channel_) { return nullptr; } diff --git a/media/base/mediaengine.h b/media/base/mediaengine.h index 01c6fb6526..e752da8988 100644 --- a/media/base/mediaengine.h +++ b/media/base/mediaengine.h @@ -22,6 +22,7 @@ #include "api/audio_codecs/audio_decoder_factory.h" #include "api/audio_codecs/audio_encoder_factory.h" +#include "api/crypto/cryptooptions.h" #include "api/rtpparameters.h" #include "call/audio_state.h" #include "media/base/codec.h" @@ -64,15 +65,18 @@ class MediaEngineInterface { // MediaChannel creation // Creates a voice media channel. Returns NULL on failure. - virtual VoiceMediaChannel* CreateChannel(webrtc::Call* call, - const MediaConfig& config, - const AudioOptions& options) = 0; + virtual VoiceMediaChannel* CreateChannel( + webrtc::Call* call, + const MediaConfig& config, + const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options) = 0; // Creates a video media channel, paired with the specified voice channel. // Returns NULL on failure. virtual VideoMediaChannel* CreateVideoChannel( webrtc::Call* call, const MediaConfig& config, - const VideoOptions& options) = 0; + const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options) = 0; virtual const std::vector& audio_send_codecs() = 0; virtual const std::vector& audio_recv_codecs() = 0; @@ -110,15 +114,19 @@ class CompositeMediaEngine : public MediaEngineInterface { virtual rtc::scoped_refptr GetAudioState() const { return voice().GetAudioState(); } - virtual VoiceMediaChannel* CreateChannel(webrtc::Call* call, - const MediaConfig& config, - const AudioOptions& options) { - return voice().CreateChannel(call, config, options); + virtual VoiceMediaChannel* CreateChannel( + webrtc::Call* call, + const MediaConfig& config, + const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options) { + return voice().CreateChannel(call, config, options, crypto_options); } - virtual VideoMediaChannel* CreateVideoChannel(webrtc::Call* call, - const MediaConfig& config, - const VideoOptions& options) { - return video().CreateChannel(call, config, options); + virtual VideoMediaChannel* CreateVideoChannel( + webrtc::Call* call, + const MediaConfig& config, + const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options) { + return video().CreateChannel(call, config, options, crypto_options); } virtual const std::vector& audio_send_codecs() { diff --git a/media/engine/nullwebrtcvideoengine.h b/media/engine/nullwebrtcvideoengine.h index 9af0f9b130..ae519b6cea 100644 --- a/media/engine/nullwebrtcvideoengine.h +++ b/media/engine/nullwebrtcvideoengine.h @@ -36,9 +36,11 @@ class NullWebRtcVideoEngine { RtpCapabilities GetCapabilities() const { return RtpCapabilities(); } - VideoMediaChannel* CreateChannel(webrtc::Call* call, - const MediaConfig& config, - const VideoOptions& options) { + VideoMediaChannel* CreateChannel( + webrtc::Call* call, + const MediaConfig& config, + const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options) { return nullptr; } }; diff --git a/media/engine/webrtcvideoengine.cc b/media/engine/webrtcvideoengine.cc index 8b17ccd51f..de1a886441 100644 --- a/media/engine/webrtcvideoengine.cc +++ b/media/engine/webrtcvideoengine.cc @@ -460,10 +460,11 @@ WebRtcVideoEngine::~WebRtcVideoEngine() { WebRtcVideoChannel* WebRtcVideoEngine::CreateChannel( webrtc::Call* call, const MediaConfig& config, - const VideoOptions& options) { + const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options) { RTC_LOG(LS_INFO) << "CreateChannel. Options: " << options.ToString(); - return new WebRtcVideoChannel(call, config, options, encoder_factory_.get(), - decoder_factory_.get()); + return new WebRtcVideoChannel(call, config, options, crypto_options, + encoder_factory_.get(), decoder_factory_.get()); } std::vector WebRtcVideoEngine::codecs() const { @@ -512,6 +513,7 @@ WebRtcVideoChannel::WebRtcVideoChannel( webrtc::Call* call, const MediaConfig& config, const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options, webrtc::VideoEncoderFactory* encoder_factory, webrtc::VideoDecoderFactory* decoder_factory) : VideoMediaChannel(config), diff --git a/media/engine/webrtcvideoengine.h b/media/engine/webrtcvideoengine.h index 27911b6ccd..cf37e45a52 100644 --- a/media/engine/webrtcvideoengine.h +++ b/media/engine/webrtcvideoengine.h @@ -96,9 +96,11 @@ class WebRtcVideoEngine { virtual ~WebRtcVideoEngine(); - WebRtcVideoChannel* CreateChannel(webrtc::Call* call, - const MediaConfig& config, - const VideoOptions& options); + WebRtcVideoChannel* CreateChannel( + webrtc::Call* call, + const MediaConfig& config, + const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options); std::vector codecs() const; RtpCapabilities GetCapabilities() const; @@ -113,6 +115,7 @@ class WebRtcVideoChannel : public VideoMediaChannel, public webrtc::Transport { WebRtcVideoChannel(webrtc::Call* call, const MediaConfig& config, const VideoOptions& options, + const webrtc::CryptoOptions& crypto_options, webrtc::VideoEncoderFactory* encoder_factory, webrtc::VideoDecoderFactory* decoder_factory); ~WebRtcVideoChannel() override; diff --git a/media/engine/webrtcvideoengine_unittest.cc b/media/engine/webrtcvideoengine_unittest.cc index e799b88770..ce2bbd910f 100644 --- a/media/engine/webrtcvideoengine_unittest.cc +++ b/media/engine/webrtcvideoengine_unittest.cc @@ -452,8 +452,8 @@ TEST_F(WebRtcVideoEngineTest, CVOSetHeaderExtensionAfterCapturer) { TEST_F(WebRtcVideoEngineTest, SetSendFailsBeforeSettingCodecs) { encoder_factory_->AddSupportedVideoCodecType("VP8"); - std::unique_ptr channel( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr channel(engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123))); @@ -466,8 +466,8 @@ TEST_F(WebRtcVideoEngineTest, SetSendFailsBeforeSettingCodecs) { TEST_F(WebRtcVideoEngineTest, GetStatsWithoutSendCodecsSetDoesNotCrash) { encoder_factory_->AddSupportedVideoCodecType("VP8"); - std::unique_ptr channel( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr channel(engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123))); VideoMediaInfo info; channel->GetStats(&info); @@ -676,8 +676,8 @@ cricket::VideoCodec WebRtcVideoEngineTest::GetEngineCodec( VideoMediaChannel* WebRtcVideoEngineTest::SetSendParamsWithAllSupportedCodecs() { - VideoMediaChannel* channel = - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()); + VideoMediaChannel* channel = engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions()); cricket::VideoSendParameters parameters; // We need to look up the codec in the engine to get the correct payload type. for (const webrtc::SdpVideoFormat& format : @@ -696,8 +696,8 @@ WebRtcVideoEngineTest::SetSendParamsWithAllSupportedCodecs() { VideoMediaChannel* WebRtcVideoEngineTest::SetRecvParamsWithSupportedCodecs( const std::vector& codecs) { - VideoMediaChannel* channel = - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()); + VideoMediaChannel* channel = engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions()); cricket::VideoRecvParameters parameters; parameters.codecs = codecs; EXPECT_TRUE(channel->SetRecvParameters(parameters)); @@ -751,8 +751,8 @@ TEST_F(WebRtcVideoEngineTest, ChannelWithH264CanChangeToVp8) { EXPECT_EQ(cricket::CS_RUNNING, capturer.Start(capturer.GetSupportedFormats()->front())); - std::unique_ptr channel( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr channel(engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoSendParameters parameters; parameters.codecs.push_back(GetEngineCodec("H264")); EXPECT_TRUE(channel->SetSendParameters(parameters)); @@ -780,8 +780,8 @@ TEST_F(WebRtcVideoEngineTest, encoder_factory_->AddSupportedVideoCodecType("VP8"); encoder_factory_->AddSupportedVideoCodecType("H264"); - std::unique_ptr channel( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr channel(engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoSendParameters parameters; parameters.codecs.push_back(GetEngineCodec("VP8")); EXPECT_TRUE(channel->SetSendParameters(parameters)); @@ -815,8 +815,8 @@ TEST_F(WebRtcVideoEngineTest, encoder_factory_->AddSupportedVideoCodecType("VP8"); encoder_factory_->AddSupportedVideoCodecType("H264"); - std::unique_ptr channel( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr channel(engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoSendParameters parameters; parameters.codecs.push_back(GetEngineCodec("H264")); EXPECT_TRUE(channel->SetSendParameters(parameters)); @@ -847,8 +847,8 @@ TEST_F(WebRtcVideoEngineTest, SimulcastEnabledForH264BehindFieldTrial) { "WebRTC-H264Simulcast/Enabled/"); encoder_factory_->AddSupportedVideoCodecType("H264"); - std::unique_ptr channel( - engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr channel(engine_.CreateChannel( + call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoSendParameters parameters; parameters.codecs.push_back(GetEngineCodec("H264")); EXPECT_TRUE(channel->SetSendParameters(parameters)); @@ -1104,8 +1104,8 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) { // Create send channel. const int send_ssrc = 123; - std::unique_ptr send_channel( - engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr send_channel(engine.CreateChannel( + call.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoSendParameters send_parameters; send_parameters.codecs.push_back(engine_codecs.at(0)); EXPECT_TRUE(send_channel->SetSendParameters(send_parameters)); @@ -1125,8 +1125,8 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) { // Create recv channel. const int recv_ssrc = 321; - std::unique_ptr recv_channel( - engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr recv_channel(engine.CreateChannel( + call.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoRecvParameters recv_parameters; recv_parameters.codecs.push_back(engine_codecs.at(0)); EXPECT_TRUE(recv_channel->SetRecvParameters(recv_parameters)); @@ -1166,8 +1166,8 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, NullDecoder) { // Create recv channel. const int recv_ssrc = 321; - std::unique_ptr recv_channel( - engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions())); + std::unique_ptr recv_channel(engine.CreateChannel( + call.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions())); cricket::VideoRecvParameters recv_parameters; recv_parameters.codecs.push_back(engine.codecs().front()); EXPECT_TRUE(recv_channel->SetRecvParameters(recv_parameters)); @@ -1256,7 +1256,8 @@ class WebRtcVideoChannelBaseTest : public testing::Test { // frames become flaky. media_config.video.enable_cpu_adaptation = false; channel_.reset(engine_.CreateChannel(call_.get(), media_config, - cricket::VideoOptions())); + cricket::VideoOptions(), + webrtc::CryptoOptions())); channel_->OnReadyToSend(true); EXPECT_TRUE(channel_.get() != NULL); network_interface_.SetDestination(channel_.get()); @@ -2066,7 +2067,8 @@ class WebRtcVideoChannelTest : public WebRtcVideoEngineTest { fake_call_.reset(new FakeCall()); channel_.reset(engine_.CreateChannel(fake_call_.get(), GetMediaConfig(), - VideoOptions())); + VideoOptions(), + webrtc::CryptoOptions())); channel_->OnReadyToSend(true); last_ssrc_ = 123; send_parameters_.codecs = engine_.codecs(); @@ -2872,8 +2874,8 @@ TEST_F(WebRtcVideoChannelTest, SetMediaConfigSuspendBelowMinBitrate) { MediaConfig media_config = GetMediaConfig(); media_config.video.suspend_below_min_bitrate = true; - channel_.reset( - engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions())); + channel_.reset(engine_.CreateChannel( + fake_call_.get(), media_config, VideoOptions(), webrtc::CryptoOptions())); channel_->OnReadyToSend(true); channel_->SetSendParameters(send_parameters_); @@ -2882,8 +2884,8 @@ TEST_F(WebRtcVideoChannelTest, SetMediaConfigSuspendBelowMinBitrate) { EXPECT_TRUE(stream->GetConfig().suspend_below_min_bitrate); media_config.video.suspend_below_min_bitrate = false; - channel_.reset( - engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions())); + channel_.reset(engine_.CreateChannel( + fake_call_.get(), media_config, VideoOptions(), webrtc::CryptoOptions())); channel_->OnReadyToSend(true); channel_->SetSendParameters(send_parameters_); @@ -3223,8 +3225,8 @@ TEST_F(WebRtcVideoChannelTest, AdaptsOnOveruseAndChangeResolution) { parameters.codecs.push_back(codec); MediaConfig media_config = GetMediaConfig(); - channel_.reset( - engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions())); + channel_.reset(engine_.CreateChannel( + fake_call_.get(), media_config, VideoOptions(), webrtc::CryptoOptions())); channel_->OnReadyToSend(true); ASSERT_TRUE(channel_->SetSendParameters(parameters)); @@ -3304,8 +3306,8 @@ TEST_F(WebRtcVideoChannelTest, PreviousAdaptationDoesNotApplyToScreenshare) { MediaConfig media_config = GetMediaConfig(); media_config.video.enable_cpu_adaptation = true; - channel_.reset( - engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions())); + channel_.reset(engine_.CreateChannel( + fake_call_.get(), media_config, VideoOptions(), webrtc::CryptoOptions())); channel_->OnReadyToSend(true); ASSERT_TRUE(channel_->SetSendParameters(parameters)); @@ -3378,8 +3380,8 @@ void WebRtcVideoChannelTest::TestDegradationPreference( MediaConfig media_config = GetMediaConfig(); media_config.video.enable_cpu_adaptation = true; - channel_.reset( - engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions())); + channel_.reset(engine_.CreateChannel( + fake_call_.get(), media_config, VideoOptions(), webrtc::CryptoOptions())); channel_->OnReadyToSend(true); EXPECT_TRUE(channel_->SetSendParameters(parameters)); @@ -3413,8 +3415,8 @@ void WebRtcVideoChannelTest::TestCpuAdaptation(bool enable_overuse, if (enable_overuse) { media_config.video.enable_cpu_adaptation = true; } - channel_.reset( - engine_.CreateChannel(fake_call_.get(), media_config, VideoOptions())); + channel_.reset(engine_.CreateChannel( + fake_call_.get(), media_config, VideoOptions(), webrtc::CryptoOptions())); channel_->OnReadyToSend(true); EXPECT_TRUE(channel_->SetSendParameters(parameters)); @@ -4595,15 +4597,15 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) { MediaConfig config; std::unique_ptr channel; - channel.reset(static_cast( - engine_.CreateChannel(call_.get(), config, VideoOptions()))); + channel.reset(static_cast(engine_.CreateChannel( + call_.get(), config, VideoOptions(), webrtc::CryptoOptions()))); channel->SetInterface(network_interface.get()); // Default value when DSCP is disabled should be DSCP_DEFAULT. EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp()); config.enable_dscp = true; - channel.reset(static_cast( - engine_.CreateChannel(call_.get(), config, VideoOptions()))); + channel.reset(static_cast(engine_.CreateChannel( + call_.get(), config, VideoOptions(), webrtc::CryptoOptions()))); channel->SetInterface(network_interface.get()); EXPECT_EQ(rtc::DSCP_AF41, network_interface->dscp()); @@ -4616,8 +4618,8 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) { // Verify that setting the option to false resets the // DiffServCodePoint. config.enable_dscp = false; - channel.reset(static_cast( - engine_.CreateChannel(call_.get(), config, VideoOptions()))); + channel.reset(static_cast(engine_.CreateChannel( + call_.get(), config, VideoOptions(), webrtc::CryptoOptions()))); channel->SetInterface(network_interface.get()); EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface->dscp()); } @@ -6738,8 +6740,9 @@ class WebRtcVideoChannelSimulcastTest : public testing::Test { void SetUp() override { encoder_factory_->AddSupportedVideoCodecType("VP8"); - channel_.reset( - engine_.CreateChannel(&fake_call_, GetMediaConfig(), VideoOptions())); + channel_.reset(engine_.CreateChannel(&fake_call_, GetMediaConfig(), + VideoOptions(), + webrtc::CryptoOptions())); channel_->OnReadyToSend(true); last_ssrc_ = 123; } diff --git a/media/engine/webrtcvoiceengine.cc b/media/engine/webrtcvoiceengine.cc index bfd0d7ec8e..b71354fb20 100644 --- a/media/engine/webrtcvoiceengine.cc +++ b/media/engine/webrtcvoiceengine.cc @@ -305,9 +305,11 @@ rtc::scoped_refptr WebRtcVoiceEngine::GetAudioState() VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel( webrtc::Call* call, const MediaConfig& config, - const AudioOptions& options) { + const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); - return new WebRtcVoiceMediaChannel(this, config, options, call); + return new WebRtcVoiceMediaChannel(this, config, options, crypto_options, + call); } bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { @@ -714,7 +716,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream webrtc::Transport* send_transport, const rtc::scoped_refptr& encoder_factory, const absl::optional codec_pair_id, - rtc::scoped_refptr frame_encryptor) + rtc::scoped_refptr frame_encryptor, + const webrtc::CryptoOptions& crypto_options) : call_(call), config_(send_transport), send_side_bwe_with_overhead_( @@ -732,6 +735,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream config_.codec_pair_id = codec_pair_id; config_.track_id = track_id; config_.frame_encryptor = frame_encryptor; + config_.crypto_options = crypto_options; rtp_parameters_.encodings[0].ssrc = ssrc; rtp_parameters_.rtcp.cname = c_name; rtp_parameters_.header_extensions = extensions; @@ -1076,7 +1080,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { absl::optional codec_pair_id, size_t jitter_buffer_max_packets, bool jitter_buffer_fast_accelerate, - rtc::scoped_refptr frame_decryptor) + rtc::scoped_refptr frame_decryptor, + const webrtc::CryptoOptions& crypto_options) : call_(call), config_() { RTC_DCHECK(call); config_.rtp.remote_ssrc = remote_ssrc; @@ -1094,6 +1099,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { config_.decoder_map = decoder_map; config_.codec_pair_id = codec_pair_id; config_.frame_decryptor = frame_decryptor; + config_.crypto_options = crypto_options; RecreateAudioReceiveStream(); } @@ -1231,11 +1237,16 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream); }; -WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, - const MediaConfig& config, - const AudioOptions& options, - webrtc::Call* call) - : VoiceMediaChannel(config), engine_(engine), call_(call) { +WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel( + WebRtcVoiceEngine* engine, + const MediaConfig& config, + const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options, + webrtc::Call* call) + : VoiceMediaChannel(config), + engine_(engine), + call_(call), + crypto_options_(crypto_options) { RTC_LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel"; RTC_DCHECK(call); engine->RegisterChannel(this); @@ -1757,7 +1768,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { WebRtcAudioSendStream* stream = new WebRtcAudioSendStream( ssrc, mid_, sp.cname, sp.id, send_codec_spec_, send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config, call_, this, - engine()->encoder_factory_, codec_pair_id_, nullptr); + engine()->encoder_factory_, codec_pair_id_, nullptr, crypto_options_); send_streams_.insert(std::make_pair(ssrc, stream)); // At this point the stream's local SSRC has been updated. If it is the first @@ -1844,7 +1855,7 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { call_, this, engine()->decoder_factory_, decoder_map_, codec_pair_id_, engine()->audio_jitter_buffer_max_packets_, engine()->audio_jitter_buffer_fast_accelerate_, - unsignaled_frame_decryptor_))); + unsignaled_frame_decryptor_, crypto_options_))); recv_streams_[ssrc]->SetPlayout(playout_); return true; diff --git a/media/engine/webrtcvoiceengine.h b/media/engine/webrtcvoiceengine.h index b39642a1d3..9c013cd405 100644 --- a/media/engine/webrtcvoiceengine.h +++ b/media/engine/webrtcvoiceengine.h @@ -58,7 +58,8 @@ class WebRtcVoiceEngine final { rtc::scoped_refptr GetAudioState() const; VoiceMediaChannel* CreateChannel(webrtc::Call* call, const MediaConfig& config, - const AudioOptions& options); + const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options); const std::vector& send_codecs() const; const std::vector& recv_codecs() const; @@ -142,6 +143,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, const MediaConfig& config, const AudioOptions& options, + const webrtc::CryptoOptions& crypto_options, webrtc::Call* call); ~WebRtcVoiceMediaChannel() override; @@ -306,6 +308,9 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, const webrtc::AudioCodecPairId codec_pair_id_ = webrtc::AudioCodecPairId::Create(); + // Per peer connection crypto options that last for the lifetime of the peer + // connection. + const webrtc::CryptoOptions crypto_options_; // Unsignaled streams have an option to have a frame decryptor set on them. rtc::scoped_refptr unsignaled_frame_decryptor_; diff --git a/media/engine/webrtcvoiceengine_unittest.cc b/media/engine/webrtcvoiceengine_unittest.cc index bb816eed11..8d20b72795 100644 --- a/media/engine/webrtcvoiceengine_unittest.cc +++ b/media/engine/webrtcvoiceengine_unittest.cc @@ -211,7 +211,8 @@ class WebRtcVoiceEngineTestFake : public testing::Test { bool SetupChannel() { EXPECT_CALL(*apm_, SetExtraOptions(testing::_)); channel_ = engine_->CreateChannel(&call_, cricket::MediaConfig(), - cricket::AudioOptions()); + cricket::AudioOptions(), + webrtc::CryptoOptions()); return (channel_ != nullptr); } @@ -2915,10 +2916,12 @@ TEST_F(WebRtcVoiceEngineTestFake, SetOptionOverridesViaChannels) { std::unique_ptr channel1( static_cast(engine_->CreateChannel( - &call_, cricket::MediaConfig(), cricket::AudioOptions()))); + &call_, cricket::MediaConfig(), cricket::AudioOptions(), + webrtc::CryptoOptions()))); std::unique_ptr channel2( static_cast(engine_->CreateChannel( - &call_, cricket::MediaConfig(), cricket::AudioOptions()))); + &call_, cricket::MediaConfig(), cricket::AudioOptions(), + webrtc::CryptoOptions()))); // Have to add a stream to make SetSend work. cricket::StreamParams stream1; @@ -3025,15 +3028,17 @@ TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) { .WillRepeatedly(SaveArg<0>(&apm_config)); EXPECT_CALL(*apm_, SetExtraOptions(testing::_)).Times(3); - channel.reset(static_cast( - engine_->CreateChannel(&call_, config, cricket::AudioOptions()))); + channel.reset( + static_cast(engine_->CreateChannel( + &call_, config, cricket::AudioOptions(), webrtc::CryptoOptions()))); channel->SetInterface(&network_interface); // Default value when DSCP is disabled should be DSCP_DEFAULT. EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface.dscp()); config.enable_dscp = true; - channel.reset(static_cast( - engine_->CreateChannel(&call_, config, cricket::AudioOptions()))); + channel.reset( + static_cast(engine_->CreateChannel( + &call_, config, cricket::AudioOptions(), webrtc::CryptoOptions()))); channel->SetInterface(&network_interface); EXPECT_EQ(rtc::DSCP_EF, network_interface.dscp()); @@ -3045,8 +3050,9 @@ TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) { // Verify that setting the option to false resets the // DiffServCodePoint. config.enable_dscp = false; - channel.reset(static_cast( - engine_->CreateChannel(&call_, config, cricket::AudioOptions()))); + channel.reset( + static_cast(engine_->CreateChannel( + &call_, config, cricket::AudioOptions(), webrtc::CryptoOptions()))); channel->SetInterface(&network_interface); // Default value when DSCP is disabled should be DSCP_DEFAULT. EXPECT_EQ(rtc::DSCP_DEFAULT, network_interface.dscp()); @@ -3374,8 +3380,9 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) { webrtc::RtcEventLogNullImpl event_log; std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log))); - cricket::VoiceMediaChannel* channel = engine.CreateChannel( - call.get(), cricket::MediaConfig(), cricket::AudioOptions()); + cricket::VoiceMediaChannel* channel = + engine.CreateChannel(call.get(), cricket::MediaConfig(), + cricket::AudioOptions(), webrtc::CryptoOptions()); EXPECT_TRUE(channel != nullptr); delete channel; } @@ -3397,8 +3404,9 @@ TEST(WebRtcVoiceEngineTest, StartupShutdownWithExternalADM) { webrtc::RtcEventLogNullImpl event_log; std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log))); - cricket::VoiceMediaChannel* channel = engine.CreateChannel( - call.get(), cricket::MediaConfig(), cricket::AudioOptions()); + cricket::VoiceMediaChannel* channel = + engine.CreateChannel(call.get(), cricket::MediaConfig(), + cricket::AudioOptions(), webrtc::CryptoOptions()); EXPECT_TRUE(channel != nullptr); delete channel; } @@ -3467,8 +3475,9 @@ TEST(WebRtcVoiceEngineTest, Has32Channels) { cricket::VoiceMediaChannel* channels[32]; size_t num_channels = 0; while (num_channels < arraysize(channels)) { - cricket::VoiceMediaChannel* channel = engine.CreateChannel( - call.get(), cricket::MediaConfig(), cricket::AudioOptions()); + cricket::VoiceMediaChannel* channel = + engine.CreateChannel(call.get(), cricket::MediaConfig(), + cricket::AudioOptions(), webrtc::CryptoOptions()); if (!channel) break; channels[num_channels++] = channel; @@ -3502,7 +3511,8 @@ TEST(WebRtcVoiceEngineTest, SetRecvCodecs) { std::unique_ptr call( webrtc::Call::Create(webrtc::Call::Config(&event_log))); cricket::WebRtcVoiceMediaChannel channel(&engine, cricket::MediaConfig(), - cricket::AudioOptions(), call.get()); + cricket::AudioOptions(), + webrtc::CryptoOptions(), call.get()); cricket::AudioRecvParameters parameters; parameters.codecs = engine.recv_codecs(); EXPECT_TRUE(channel.SetRecvParameters(parameters)); diff --git a/pc/channelmanager.cc b/pc/channelmanager.cc index 1c80719949..3ef9a42765 100644 --- a/pc/channelmanager.cc +++ b/pc/channelmanager.cc @@ -177,7 +177,7 @@ VoiceChannel* ChannelManager::CreateVoiceChannel( } VoiceMediaChannel* media_channel = - media_engine_->CreateChannel(call, media_config, options); + media_engine_->CreateChannel(call, media_config, options, crypto_options); if (!media_channel) { return nullptr; } @@ -243,8 +243,8 @@ VideoChannel* ChannelManager::CreateVideoChannel( return nullptr; } - VideoMediaChannel* media_channel = - media_engine_->CreateVideoChannel(call, media_config, options); + VideoMediaChannel* media_channel = media_engine_->CreateVideoChannel( + call, media_config, options, crypto_options); if (!media_channel) { return nullptr; } diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java index 7c67ca3d16..fdc29bbae9 100644 --- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java +++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java @@ -122,9 +122,27 @@ public class PeerConnectionFactory { public int networkIgnoreMask; public boolean disableEncryption; public boolean disableNetworkMonitor; + + /** + * 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. + */ public boolean enableAes128Sha1_32CryptoCipher; + + /** + * Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used if both sides enable + * it. + */ public boolean enableGcmCryptoSuites; + /** + * 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. + */ + public boolean requireFrameEncryption; + @CalledByNative("Options") int getNetworkIgnoreMask() { return networkIgnoreMask; @@ -149,6 +167,11 @@ public class PeerConnectionFactory { boolean getEnableGcmCryptoSuites() { return enableGcmCryptoSuites; } + + @CalledByNative("Options") + boolean getRequireFrameEncryption() { + return requireFrameEncryption; + } } public static class Builder { diff --git a/sdk/android/src/jni/pc/peerconnectionfactory.cc b/sdk/android/src/jni/pc/peerconnectionfactory.cc index 83591cb8bb..148375e3d6 100644 --- a/sdk/android/src/jni/pc/peerconnectionfactory.cc +++ b/sdk/android/src/jni/pc/peerconnectionfactory.cc @@ -54,6 +54,8 @@ JavaToNativePeerConnectionFactoryOptions(JNIEnv* jni, Java_Options_getEnableAes128Sha1_32CryptoCipher(jni, options); bool enable_gcm_crypto_suites = Java_Options_getEnableGcmCryptoSuites(jni, options); + bool require_frame_encryption = + Java_Options_getRequireFrameEncryption(jni, options); PeerConnectionFactoryInterface::Options native_options; @@ -67,6 +69,9 @@ JavaToNativePeerConnectionFactoryOptions(JNIEnv* jni, enable_aes128_sha1_32_crypto_cipher; native_options.crypto_options.srtp.enable_gcm_crypto_suites = enable_gcm_crypto_suites; + native_options.crypto_options.sframe.require_frame_encryption = + require_frame_encryption; + return native_options; } diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h index af327f987b..fb65512c0c 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h +++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h @@ -35,6 +35,8 @@ RTC_OBJC_EXPORT @property(nonatomic, assign) BOOL enableGcmCryptoSuites; +@property(nonatomic, assign) BOOL requireFrameEncryption; + - (instancetype)init NS_DESIGNATED_INITIALIZER; @end diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.mm b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.mm index 1690385937..743cb4da09 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.mm +++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.mm @@ -36,6 +36,7 @@ void setNetworkBit(webrtc::PeerConnectionFactoryInterface::Options* options, @synthesize ignoreEthernetNetworkAdapter = _ignoreEthernetNetworkAdapter; @synthesize enableAes128Sha1_32CryptoCipher = _enableAes128Sha1_32CryptoCipher; @synthesize enableGcmCryptoSuites = _enableGcmCryptoSuites; +@synthesize requireFrameEncryption = _requireFrameEncryption; - (instancetype)init { return [super init]; @@ -55,6 +56,7 @@ void setNetworkBit(webrtc::PeerConnectionFactoryInterface::Options* options, options.crypto_options.srtp.enable_aes128_sha1_32_crypto_cipher = self.enableAes128Sha1_32CryptoCipher; options.crypto_options.srtp.enable_gcm_crypto_suites = self.enableGcmCryptoSuites; + options.crypto_options.sframe.require_frame_encryption = self.requireFrameEncryption; return options; }