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}
This commit is contained in:
Benjamin Wright 2018-10-15 10:20:24 -07:00 committed by Commit Bot
parent d932fba3bc
commit bfb444ce2c
24 changed files with 258 additions and 110 deletions

View File

@ -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<int> 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

View File

@ -33,6 +33,9 @@ struct CryptoOptions {
// 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 @@ 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

View File

@ -76,7 +76,7 @@ std::unique_ptr<voe::ChannelReceiveProxy> 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

View File

@ -51,11 +51,12 @@ std::unique_ptr<voe::ChannelSendProxy> 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<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 @@ 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,

View File

@ -206,7 +206,8 @@ ChannelReceive::ChannelReceive(
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 @@ 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) {

View File

@ -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<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 @@ class ChannelReceive : public RtpData {
// E2EE Audio Frame Decryption
FrameDecryptorInterface* frame_decryptor_ = nullptr;
webrtc::CryptoOptions crypto_options_;
};
} // namespace voe

View File

@ -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()));

View File

@ -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

View File

@ -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<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.

View File

@ -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.

View File

@ -776,9 +776,11 @@ class FakeVoiceEngine : public FakeBaseEngine {
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 @@ 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;
}

View File

@ -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<AudioCodec>& audio_send_codecs() = 0;
virtual const std::vector<AudioCodec>& audio_recv_codecs() = 0;
@ -110,15 +114,19 @@ class CompositeMediaEngine : public MediaEngineInterface {
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() {

View File

@ -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;
}
};

View File

@ -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<VideoCodec> 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),

View File

@ -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<VideoCodec> 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;

View File

@ -452,8 +452,8 @@ TEST_F(WebRtcVideoEngineTest, CVOSetHeaderExtensionAfterCapturer) {
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, SetSendFailsBeforeSettingCodecs) {
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 @@ 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<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 @@ TEST_F(WebRtcVideoEngineTest, ChannelWithH264CanChangeToVp8) {
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 @@ TEST_F(WebRtcVideoEngineTest,
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 @@ TEST_F(WebRtcVideoEngineTest,
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 @@ TEST_F(WebRtcVideoEngineTest, SimulcastEnabledForH264BehindFieldTrial) {
"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 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) {
// 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 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, Vp8) {
// 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 @@ TEST(WebRtcVideoEngineNewVideoCodecFactoryTest, NullDecoder) {
// 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 @@ 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<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 @@ TEST_F(WebRtcVideoChannelTest, TestSetDscpOptions) {
// 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 @@ 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;
}

View File

@ -305,9 +305,11 @@ rtc::scoped_refptr<webrtc::AudioState> 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<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 @@ 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<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 @@ 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;

View File

@ -58,7 +58,8 @@ class WebRtcVoiceEngine final {
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 @@ 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<webrtc::FrameDecryptorInterface>
unsignaled_frame_decryptor_;

View File

@ -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<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 @@ TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
.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 @@ TEST_F(WebRtcVoiceEngineTestFake, TestSetDscpOptions) {
// 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 @@ TEST(WebRtcVoiceEngineTest, StartupShutdown) {
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 @@ TEST(WebRtcVoiceEngineTest, StartupShutdownWithExternalADM) {
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 @@ 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<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));

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -35,6 +35,8 @@ RTC_OBJC_EXPORT
@property(nonatomic, assign) BOOL enableGcmCryptoSuites;
@property(nonatomic, assign) BOOL requireFrameEncryption;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
@end

View File

@ -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;
}