Adds new CryptoOption crypto_options.frame.require_frame_encryption.
This change adds a new subcategory to the public native webrtc::CryptoOptions
structure: webrtc::CryptoOptions::Frame.
This new structure has a single off by default property:
crypto_options.frame.require_frame_encryption.
This new flag if set prevents RtpSenders from sending outgoing payloads unless
a frame_encryptor_ is attached and prevents RtpReceivers from receiving
incoming payloads unless a frame_decryptor_ is attached.
This option is important to enforce no unencrypted data can ever leave the
device or be received.
I have also attached bindings for Java and Objective-C.
I have implemented this functionality for E2EE audio but not E2EE video
since the changes are still in review.
Bug: webrtc:9681
Change-Id: Ie184711190e0cdf5ac781f69e9489ceec904736f
Reviewed-on: https://webrtc-review.googlesource.com/c/105540
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Commit-Queue: Benjamin Wright <benwright@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25238}
diff --git a/api/crypto/cryptooptions.cc b/api/crypto/cryptooptions.cc
index 2c34822..7f34f19 100644
--- a/api/crypto/cryptooptions.cc
+++ b/api/crypto/cryptooptions.cc
@@ -17,6 +17,7 @@
CryptoOptions::CryptoOptions(const CryptoOptions& other) {
srtp = other.srtp;
+ sframe = other.sframe;
}
CryptoOptions::~CryptoOptions() {}
@@ -46,4 +47,32 @@
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 de674c2..bd4a1c4 100644
--- a/api/crypto/cryptooptions.h
+++ b/api/crypto/cryptooptions.h
@@ -33,6 +33,9 @@
// of crypto options.
std::vector<int> 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 @@
// 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 563e8a0..bf06cd2 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -76,7 +76,7 @@
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 49d933c..39cb4e8 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -51,11 +51,12 @@
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<voe::ChannelSendProxy>(
absl::make_unique<voe::ChannelSend>(worker_queue, module_process_thread,
rtcp_rtt_stats, event_log,
- frame_encryptor));
+ frame_encryptor, crypto_options));
}
} // namespace
@@ -106,7 +107,8 @@
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 e9f7503..2384999 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -206,7 +206,8 @@
bool jitter_buffer_fast_playout,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
absl::optional<AudioCodecPairId> 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 @@
_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 @@
// 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 82eb4df..ac359bb 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 @@
bool jitter_buffer_fast_playout,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
absl::optional<AudioCodecPairId> codec_pair_id,
- FrameDecryptorInterface* frame_decryptor);
+ FrameDecryptorInterface* frame_decryptor,
+ const webrtc::CryptoOptions& crypto_options);
virtual ~ChannelReceive();
void SetSink(AudioSinkInterface* sink);
@@ -259,6 +261,7 @@
// 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 8639fbd..bdabe8f 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -289,6 +289,10 @@
// 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 @@
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 @@
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 ef92f8e..306d6a8 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 @@
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 @@
// 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 9c890b1..786c3ba 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 @@
absl::optional<AudioCodecPairId> 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 61e2531..a659dd6 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 @@
// 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 62bd6ba..a20beb0 100644
--- a/media/base/fakemediaengine.h
+++ b/media/base/fakemediaengine.h
@@ -776,9 +776,11 @@
return rtc::scoped_refptr<webrtc::AudioState>();
}
- 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 @@
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 01c6fb6..e752da8 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 @@
// 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<AudioCodec>& audio_send_codecs() = 0;
virtual const std::vector<AudioCodec>& audio_recv_codecs() = 0;
@@ -110,15 +114,19 @@
virtual rtc::scoped_refptr<webrtc::AudioState> 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<AudioCodec>& audio_send_codecs() {
diff --git a/media/engine/nullwebrtcvideoengine.h b/media/engine/nullwebrtcvideoengine.h
index 9af0f9b..ae519b6 100644
--- a/media/engine/nullwebrtcvideoengine.h
+++ b/media/engine/nullwebrtcvideoengine.h
@@ -36,9 +36,11 @@
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 8b17ccd..de1a886 100644
--- a/media/engine/webrtcvideoengine.cc
+++ b/media/engine/webrtcvideoengine.cc
@@ -460,10 +460,11 @@
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<VideoCodec> WebRtcVideoEngine::codecs() const {
@@ -512,6 +513,7 @@
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 27911b6..cf37e45 100644
--- a/media/engine/webrtcvideoengine.h
+++ b/media/engine/webrtcvideoengine.h
@@ -96,9 +96,11 @@
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<VideoCodec> codecs() const;
RtpCapabilities GetCapabilities() const;
@@ -113,6 +115,7 @@
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 e799b88..ce2bbd9 100644
--- a/media/engine/webrtcvideoengine_unittest.cc
+++ b/media/engine/webrtcvideoengine_unittest.cc
@@ -452,8 +452,8 @@
TEST_F(WebRtcVideoEngineTest, SetSendFailsBeforeSettingCodecs) {
encoder_factory_->AddSupportedVideoCodecType("VP8");
- std::unique_ptr<VideoMediaChannel> channel(
- engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> channel(engine_.CreateChannel(
+ call_.get(), GetMediaConfig(), VideoOptions(), webrtc::CryptoOptions()));
EXPECT_TRUE(channel->AddSendStream(StreamParams::CreateLegacy(123)));
@@ -466,8 +466,8 @@
TEST_F(WebRtcVideoEngineTest, GetStatsWithoutSendCodecsSetDoesNotCrash) {
encoder_factory_->AddSupportedVideoCodecType("VP8");
- std::unique_ptr<VideoMediaChannel> channel(
- engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
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 @@
VideoMediaChannel* WebRtcVideoEngineTest::SetRecvParamsWithSupportedCodecs(
const std::vector<VideoCodec>& 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 @@
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
- std::unique_ptr<VideoMediaChannel> channel(
- engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
encoder_factory_->AddSupportedVideoCodecType("VP8");
encoder_factory_->AddSupportedVideoCodecType("H264");
- std::unique_ptr<VideoMediaChannel> channel(
- engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
encoder_factory_->AddSupportedVideoCodecType("VP8");
encoder_factory_->AddSupportedVideoCodecType("H264");
- std::unique_ptr<VideoMediaChannel> channel(
- engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
"WebRTC-H264Simulcast/Enabled/");
encoder_factory_->AddSupportedVideoCodecType("H264");
- std::unique_ptr<VideoMediaChannel> channel(
- engine_.CreateChannel(call_.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
// Create send channel.
const int send_ssrc = 123;
- std::unique_ptr<VideoMediaChannel> send_channel(
- engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
// Create recv channel.
const int recv_ssrc = 321;
- std::unique_ptr<VideoMediaChannel> recv_channel(
- engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
// Create recv channel.
const int recv_ssrc = 321;
- std::unique_ptr<VideoMediaChannel> recv_channel(
- engine.CreateChannel(call.get(), GetMediaConfig(), VideoOptions()));
+ std::unique_ptr<VideoMediaChannel> 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
MediaConfig config;
std::unique_ptr<cricket::WebRtcVideoChannel> channel;
- channel.reset(static_cast<cricket::WebRtcVideoChannel*>(
- engine_.CreateChannel(call_.get(), config, VideoOptions())));
+ channel.reset(static_cast<cricket::WebRtcVideoChannel*>(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<cricket::WebRtcVideoChannel*>(
- engine_.CreateChannel(call_.get(), config, VideoOptions())));
+ channel.reset(static_cast<cricket::WebRtcVideoChannel*>(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 @@
// Verify that setting the option to false resets the
// DiffServCodePoint.
config.enable_dscp = false;
- channel.reset(static_cast<cricket::WebRtcVideoChannel*>(
- engine_.CreateChannel(call_.get(), config, VideoOptions())));
+ channel.reset(static_cast<cricket::WebRtcVideoChannel*>(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 @@
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 bfd0d7e..b71354f 100644
--- a/media/engine/webrtcvoiceengine.cc
+++ b/media/engine/webrtcvoiceengine.cc
@@ -305,9 +305,11 @@
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 @@
webrtc::Transport* send_transport,
const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
const absl::optional<webrtc::AudioCodecPairId> codec_pair_id,
- rtc::scoped_refptr<webrtc::FrameEncryptorInterface> frame_encryptor)
+ rtc::scoped_refptr<webrtc::FrameEncryptorInterface> frame_encryptor,
+ const webrtc::CryptoOptions& crypto_options)
: call_(call),
config_(send_transport),
send_side_bwe_with_overhead_(
@@ -732,6 +735,7 @@
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 @@
absl::optional<webrtc::AudioCodecPairId> codec_pair_id,
size_t jitter_buffer_max_packets,
bool jitter_buffer_fast_accelerate,
- rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor)
+ rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor,
+ const webrtc::CryptoOptions& crypto_options)
: call_(call), config_() {
RTC_DCHECK(call);
config_.rtp.remote_ssrc = remote_ssrc;
@@ -1094,6 +1099,7 @@
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 @@
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 @@
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 @@
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 b39642a..9c013cd 100644
--- a/media/engine/webrtcvoiceengine.h
+++ b/media/engine/webrtcvoiceengine.h
@@ -58,7 +58,8 @@
rtc::scoped_refptr<webrtc::AudioState> GetAudioState() const;
VoiceMediaChannel* CreateChannel(webrtc::Call* call,
const MediaConfig& config,
- const AudioOptions& options);
+ const AudioOptions& options,
+ const webrtc::CryptoOptions& crypto_options);
const std::vector<AudioCodec>& send_codecs() const;
const std::vector<AudioCodec>& recv_codecs() const;
@@ -142,6 +143,7 @@
WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
const MediaConfig& config,
const AudioOptions& options,
+ const webrtc::CryptoOptions& crypto_options,
webrtc::Call* call);
~WebRtcVoiceMediaChannel() override;
@@ -306,6 +308,9 @@
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<webrtc::FrameDecryptorInterface>
unsignaled_frame_decryptor_;
diff --git a/media/engine/webrtcvoiceengine_unittest.cc b/media/engine/webrtcvoiceengine_unittest.cc
index bb816ee..8d20b72 100644
--- a/media/engine/webrtcvoiceengine_unittest.cc
+++ b/media/engine/webrtcvoiceengine_unittest.cc
@@ -211,7 +211,8 @@
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 @@
std::unique_ptr<cricket::WebRtcVoiceMediaChannel> channel1(
static_cast<cricket::WebRtcVoiceMediaChannel*>(engine_->CreateChannel(
- &call_, cricket::MediaConfig(), cricket::AudioOptions())));
+ &call_, cricket::MediaConfig(), cricket::AudioOptions(),
+ webrtc::CryptoOptions())));
std::unique_ptr<cricket::WebRtcVoiceMediaChannel> channel2(
static_cast<cricket::WebRtcVoiceMediaChannel*>(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 @@
.WillRepeatedly(SaveArg<0>(&apm_config));
EXPECT_CALL(*apm_, SetExtraOptions(testing::_)).Times(3);
- channel.reset(static_cast<cricket::WebRtcVoiceMediaChannel*>(
- engine_->CreateChannel(&call_, config, cricket::AudioOptions())));
+ channel.reset(
+ static_cast<cricket::WebRtcVoiceMediaChannel*>(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<cricket::WebRtcVoiceMediaChannel*>(
- engine_->CreateChannel(&call_, config, cricket::AudioOptions())));
+ channel.reset(
+ static_cast<cricket::WebRtcVoiceMediaChannel*>(engine_->CreateChannel(
+ &call_, config, cricket::AudioOptions(), webrtc::CryptoOptions())));
channel->SetInterface(&network_interface);
EXPECT_EQ(rtc::DSCP_EF, network_interface.dscp());
@@ -3045,8 +3050,9 @@
// Verify that setting the option to false resets the
// DiffServCodePoint.
config.enable_dscp = false;
- channel.reset(static_cast<cricket::WebRtcVoiceMediaChannel*>(
- engine_->CreateChannel(&call_, config, cricket::AudioOptions())));
+ channel.reset(
+ static_cast<cricket::WebRtcVoiceMediaChannel*>(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 @@
webrtc::RtcEventLogNullImpl event_log;
std::unique_ptr<webrtc::Call> 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 @@
webrtc::RtcEventLogNullImpl event_log;
std::unique_ptr<webrtc::Call> 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 @@
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 @@
std::unique_ptr<webrtc::Call> 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 1c80719..3ef9a42 100644
--- a/pc/channelmanager.cc
+++ b/pc/channelmanager.cc
@@ -177,7 +177,7 @@
}
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 @@
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 7c67ca3..fdc29bb 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -122,9 +122,27 @@
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 @@
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 83591cb..148375e 100644
--- a/sdk/android/src/jni/pc/peerconnectionfactory.cc
+++ b/sdk/android/src/jni/pc/peerconnectionfactory.cc
@@ -54,6 +54,8 @@
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 @@
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 af327f9..fb65512 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h
+++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h
@@ -35,6 +35,8 @@
@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 1690385..743cb4d 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.mm
+++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactoryOptions.mm
@@ -36,6 +36,7 @@
@synthesize ignoreEthernetNetworkAdapter = _ignoreEthernetNetworkAdapter;
@synthesize enableAes128Sha1_32CryptoCipher = _enableAes128Sha1_32CryptoCipher;
@synthesize enableGcmCryptoSuites = _enableGcmCryptoSuites;
+@synthesize requireFrameEncryption = _requireFrameEncryption;
- (instancetype)init {
return [super init];
@@ -55,6 +56,7 @@
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;
}