mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00
ringrtc: Propagate externally-negotiated keys.
This commit is contained in:
parent
e0b555e38d
commit
2cf10f1072
19 changed files with 410 additions and 48 deletions
|
@ -274,6 +274,8 @@ rtc_library("libjingle_peerconnection_api") {
|
|||
visibility = [ "*" ]
|
||||
cflags = []
|
||||
sources = [
|
||||
# RingRTC change: Propagate externally-negotiated keys.
|
||||
"crypto_params.h",
|
||||
"data_channel_interface.cc",
|
||||
"data_channel_interface.h",
|
||||
# RingRTC change to add ICE forking
|
||||
|
|
44
api/crypto_params.h
Normal file
44
api/crypto_params.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2019-2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
// RingRTC change: Struct to carry SRTP crypto parameters to RTP transport.
|
||||
|
||||
#ifndef API_CRYPTO_PARAMS_H_
|
||||
#define API_CRYPTO_PARAMS_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/ssl_stream_adapter.h" // kSrtpInvalidCryptoSuite
|
||||
|
||||
namespace cricket {
|
||||
|
||||
// Parameters for propagating SRTP params to RTP transport.
|
||||
struct CryptoParams {
|
||||
CryptoParams() = default;
|
||||
|
||||
// Manually define a copy constructor because ZeroOnFreeBuffer assumes its
|
||||
// contents might be quite large, and wants us to be explicit. However, keys
|
||||
// won't be extremely large, so allow copies.
|
||||
CryptoParams(const CryptoParams& other)
|
||||
: crypto_suite(other.crypto_suite),
|
||||
key_params(other.key_params.data(), other.key_params.size()) {}
|
||||
|
||||
// Similarly define an assignment constructor.
|
||||
CryptoParams& operator=(CryptoParams other) {
|
||||
std::swap(crypto_suite, other.crypto_suite);
|
||||
// ZeroOnFreeBuffer defines a swap()
|
||||
std::swap(key_params, other.key_params);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int crypto_suite = rtc::kSrtpInvalidCryptoSuite;
|
||||
// Key and salt.
|
||||
rtc::ZeroOnFreeBuffer<uint8_t> key_params;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // API_CRYPTO_PARAMS_H_
|
|
@ -23,7 +23,8 @@ namespace cricket {
|
|||
|
||||
TransportDescriptionFactory::TransportDescriptionFactory(
|
||||
const webrtc::FieldTrialsView& field_trials)
|
||||
: field_trials_(field_trials) {}
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
: manually_specify_keys_(false), field_trials_(field_trials) {}
|
||||
|
||||
TransportDescriptionFactory::~TransportDescriptionFactory() = default;
|
||||
|
||||
|
@ -52,6 +53,12 @@ std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateOffer(
|
|||
if (insecure_ && !certificate_) {
|
||||
return desc;
|
||||
}
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
if (manually_specify_keys_) {
|
||||
RTC_LOG(LS_INFO) << "Skipping SetSecurityInfo because expect manual keys";
|
||||
return desc;
|
||||
}
|
||||
// Fail if we can't create the fingerprint.
|
||||
// If we are the initiator set role to "actpass".
|
||||
if (!SetSecurityInfo(desc.get(), CONNECTIONROLE_ACTPASS)) {
|
||||
|
@ -95,6 +102,12 @@ std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateAnswer(
|
|||
if ((!certificate_ || !offer->identity_fingerprint.get()) && insecure()) {
|
||||
return desc;
|
||||
}
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
if (manually_specify_keys_) {
|
||||
RTC_LOG(LS_INFO) << "Skipping SetSecurityInfo because expect manual keys";
|
||||
return desc;
|
||||
}
|
||||
|
||||
if (!offer->identity_fingerprint.get()) {
|
||||
if (require_transport_attributes) {
|
||||
// We require DTLS, but the other side didn't offer it. Fail.
|
||||
|
|
|
@ -43,12 +43,17 @@ class TransportDescriptionFactory {
|
|||
const webrtc::FieldTrialsView& field_trials);
|
||||
~TransportDescriptionFactory();
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
bool manually_specify_keys() const { return manually_specify_keys_; }
|
||||
// The certificate to use when setting up DTLS.
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate() const {
|
||||
return certificate_;
|
||||
}
|
||||
|
||||
// Specifies the certificate to use
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
// Specifies that keys should be manually specified.
|
||||
void set_manually_specify_keys(bool b) { manually_specify_keys_ = b; }
|
||||
// Specifies the certificate to use (only used when !manually_specify_keys).
|
||||
void set_certificate(rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
|
||||
certificate_ = std::move(certificate);
|
||||
}
|
||||
|
@ -85,6 +90,11 @@ class TransportDescriptionFactory {
|
|||
bool SetSecurityInfo(TransportDescription* description,
|
||||
ConnectionRole role) const;
|
||||
bool insecure_ = false;
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
// True iff keys should be manually specified (e.g. negotiated out of band,
|
||||
// and not via DTLS).
|
||||
bool manually_specify_keys_ = false;
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
|
||||
const webrtc::FieldTrialsView& field_trials_;
|
||||
};
|
||||
|
|
17
pc/BUILD.gn
17
pc/BUILD.gn
|
@ -213,6 +213,8 @@ rtc_source_set("jsep_transport") {
|
|||
":rtp_transport_internal",
|
||||
":sctp_transport",
|
||||
":session_description",
|
||||
# RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
":srtp_key_carrier",
|
||||
":srtp_transport",
|
||||
":transport_stats",
|
||||
"../api:array_view",
|
||||
|
@ -538,6 +540,21 @@ rtc_source_set("sctp_utils") {
|
|||
]
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||
}
|
||||
# RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
rtc_source_set("srtp_key_carrier") {
|
||||
visibility = [ ":*" ]
|
||||
sources = [
|
||||
"srtp_key_carrier.cc",
|
||||
"srtp_key_carrier.h",
|
||||
]
|
||||
deps = [
|
||||
":session_description",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:ssl",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("srtp_session") {
|
||||
visibility = [ ":*" ]
|
||||
sources = [
|
||||
|
|
|
@ -36,10 +36,14 @@ JsepTransportDescription::JsepTransportDescription() {}
|
|||
|
||||
JsepTransportDescription::JsepTransportDescription(
|
||||
bool rtcp_mux_enabled,
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
const std::optional<CryptoParams>& crypto,
|
||||
const std::vector<int>& encrypted_header_extension_ids,
|
||||
int rtp_abs_sendtime_extn_id,
|
||||
const TransportDescription& transport_desc)
|
||||
: rtcp_mux_enabled(rtcp_mux_enabled),
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
crypto(crypto),
|
||||
encrypted_header_extension_ids(encrypted_header_extension_ids),
|
||||
rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id),
|
||||
transport_desc(transport_desc) {}
|
||||
|
@ -47,6 +51,8 @@ JsepTransportDescription::JsepTransportDescription(
|
|||
JsepTransportDescription::JsepTransportDescription(
|
||||
const JsepTransportDescription& from)
|
||||
: rtcp_mux_enabled(from.rtcp_mux_enabled),
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
crypto(from.crypto),
|
||||
encrypted_header_extension_ids(from.encrypted_header_extension_ids),
|
||||
rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id),
|
||||
transport_desc(from.transport_desc) {}
|
||||
|
@ -59,6 +65,8 @@ JsepTransportDescription& JsepTransportDescription::operator=(
|
|||
return *this;
|
||||
}
|
||||
rtcp_mux_enabled = from.rtcp_mux_enabled;
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
crypto = from.crypto;
|
||||
encrypted_header_extension_ids = from.encrypted_header_extension_ids;
|
||||
rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id;
|
||||
transport_desc = from.transport_desc;
|
||||
|
@ -72,7 +80,8 @@ JsepTransport::JsepTransport(
|
|||
rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
|
||||
rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
|
||||
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
|
||||
std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::unique_ptr<webrtc::SrtpTransport> srtp_transport,
|
||||
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
|
||||
|
@ -84,7 +93,8 @@ JsepTransport::JsepTransport(
|
|||
ice_transport_(std::move(ice_transport)),
|
||||
rtcp_ice_transport_(std::move(rtcp_ice_transport)),
|
||||
unencrypted_rtp_transport_(std::move(unencrypted_rtp_transport)),
|
||||
sdes_transport_(std::move(sdes_transport)),
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
srtp_transport_(std::move(srtp_transport)),
|
||||
dtls_srtp_transport_(std::move(dtls_srtp_transport)),
|
||||
rtp_dtls_transport_(rtp_dtls_transport
|
||||
? rtc::make_ref_counted<webrtc::DtlsTransport>(
|
||||
|
@ -108,15 +118,18 @@ JsepTransport::JsepTransport(
|
|||
(rtcp_dtls_transport_ != nullptr));
|
||||
// Verify the "only one out of these three can be set" invariant.
|
||||
if (unencrypted_rtp_transport_) {
|
||||
RTC_DCHECK(!sdes_transport);
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!srtp_transport);
|
||||
RTC_DCHECK(!dtls_srtp_transport);
|
||||
} else if (sdes_transport_) {
|
||||
} else if (srtp_transport_) {
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!unencrypted_rtp_transport);
|
||||
RTC_DCHECK(!dtls_srtp_transport);
|
||||
} else {
|
||||
RTC_DCHECK(dtls_srtp_transport_);
|
||||
RTC_DCHECK(!unencrypted_rtp_transport);
|
||||
RTC_DCHECK(!sdes_transport);
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!srtp_transport);
|
||||
}
|
||||
|
||||
if (sctp_transport_) {
|
||||
|
@ -163,9 +176,21 @@ webrtc::RTCError JsepTransport::SetLocalJsepTransportDescription(
|
|||
"Failed to setup RTCP mux.");
|
||||
}
|
||||
|
||||
if (dtls_srtp_transport_) {
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
// If doing SRTP with manual keys, setup the crypto parameters.
|
||||
if (srtp_transport_) {
|
||||
RTC_DCHECK(!unencrypted_rtp_transport_);
|
||||
RTC_DCHECK(!sdes_transport_);
|
||||
RTC_DCHECK(!dtls_srtp_transport_);
|
||||
if (!SetSrtpCrypto(jsep_description.crypto,
|
||||
jsep_description.encrypted_header_extension_ids, type,
|
||||
ContentSource::CS_LOCAL)) {
|
||||
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
|
||||
"Failed to setup SRTP crypto parameters.");
|
||||
}
|
||||
} else if (dtls_srtp_transport_) {
|
||||
RTC_DCHECK(!unencrypted_rtp_transport_);
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!srtp_transport_);
|
||||
dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
|
||||
jsep_description.encrypted_header_extension_ids);
|
||||
}
|
||||
|
@ -240,9 +265,22 @@ webrtc::RTCError JsepTransport::SetRemoteJsepTransportDescription(
|
|||
"Failed to setup RTCP mux.");
|
||||
}
|
||||
|
||||
if (dtls_srtp_transport_) {
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
// If doing SRTP, setup the SRTP crypto parameters.
|
||||
if (srtp_transport_) {
|
||||
RTC_DCHECK(!unencrypted_rtp_transport_);
|
||||
RTC_DCHECK(!sdes_transport_);
|
||||
RTC_DCHECK(!dtls_srtp_transport_);
|
||||
if (!SetSrtpCrypto(jsep_description.crypto,
|
||||
jsep_description.encrypted_header_extension_ids, type,
|
||||
ContentSource::CS_REMOTE)) {
|
||||
return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
|
||||
"Failed to setup SRTP crypto parameters.");
|
||||
}
|
||||
srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
|
||||
jsep_description.rtp_abs_sendtime_extn_id);
|
||||
} else if (dtls_srtp_transport_) {
|
||||
RTC_DCHECK(!unencrypted_rtp_transport_);
|
||||
RTC_DCHECK(!srtp_transport_);
|
||||
dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
|
||||
jsep_description.encrypted_header_extension_ids);
|
||||
dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
|
||||
|
@ -429,17 +467,20 @@ bool JsepTransport::SetRtcpMux(bool enable,
|
|||
|
||||
void JsepTransport::ActivateRtcpMux() {
|
||||
if (unencrypted_rtp_transport_) {
|
||||
RTC_DCHECK(!sdes_transport_);
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!srtp_transport_);
|
||||
RTC_DCHECK(!dtls_srtp_transport_);
|
||||
unencrypted_rtp_transport_->SetRtcpPacketTransport(nullptr);
|
||||
} else if (sdes_transport_) {
|
||||
} else if (srtp_transport_) {
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!unencrypted_rtp_transport_);
|
||||
RTC_DCHECK(!dtls_srtp_transport_);
|
||||
sdes_transport_->SetRtcpPacketTransport(nullptr);
|
||||
srtp_transport_->SetRtcpPacketTransport(nullptr);
|
||||
} else if (dtls_srtp_transport_) {
|
||||
RTC_DCHECK(dtls_srtp_transport_);
|
||||
RTC_DCHECK(!unencrypted_rtp_transport_);
|
||||
RTC_DCHECK(!sdes_transport_);
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
RTC_DCHECK(!srtp_transport_);
|
||||
dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(),
|
||||
/*rtcp_dtls_transport=*/nullptr);
|
||||
}
|
||||
|
@ -448,6 +489,46 @@ void JsepTransport::ActivateRtcpMux() {
|
|||
rtcp_mux_active_callback_();
|
||||
}
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
bool JsepTransport::SetSrtpCrypto(
|
||||
const std::optional<CryptoParams>& crypto,
|
||||
const std::vector<int>& encrypted_extension_ids,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source) {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
if (!crypto.has_value()) {
|
||||
RTC_LOG(LS_ERROR) << "Setting manually-specified SRTP without any keys";
|
||||
return false;
|
||||
}
|
||||
if (!srtp_key_carrier_.ApplyParams(crypto.value(), type, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source == ContentSource::CS_LOCAL) {
|
||||
recv_extension_ids_ = encrypted_extension_ids;
|
||||
} else {
|
||||
send_extension_ids_ = encrypted_extension_ids;
|
||||
}
|
||||
|
||||
// If appropriate, apply the negotiated parameters
|
||||
// to the SRTP transport.
|
||||
if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) {
|
||||
const CryptoParams& send = srtp_key_carrier_.send_params();
|
||||
const CryptoParams& recv = srtp_key_carrier_.recv_params();
|
||||
RTC_DCHECK(send_extension_ids_);
|
||||
RTC_DCHECK(recv_extension_ids_);
|
||||
return srtp_transport_->SetRtpParams(
|
||||
send.crypto_suite,
|
||||
send.key_params.data(),
|
||||
static_cast<int>(send.key_params.size()),
|
||||
*(send_extension_ids_), recv.crypto_suite,
|
||||
recv.key_params.data(),
|
||||
static_cast<int>(recv.key_params.size()),
|
||||
*(recv_extension_ids_));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
|
||||
SdpType local_description_type) {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
#include <optional>
|
||||
#include "api/crypto_params.h"
|
||||
#include "pc/srtp_key_carrier.h"
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/candidate.h"
|
||||
#include "api/ice_transport_interface.h"
|
||||
|
@ -57,6 +62,8 @@ struct JsepTransportDescription {
|
|||
JsepTransportDescription();
|
||||
JsepTransportDescription(
|
||||
bool rtcp_mux_enabled,
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
const std::optional<CryptoParams>& crypto,
|
||||
const std::vector<int>& encrypted_header_extension_ids,
|
||||
int rtp_abs_sendtime_extn_id,
|
||||
const TransportDescription& transport_description);
|
||||
|
@ -66,6 +73,8 @@ struct JsepTransportDescription {
|
|||
JsepTransportDescription& operator=(const JsepTransportDescription& from);
|
||||
|
||||
bool rtcp_mux_enabled = true;
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::optional<CryptoParams> crypto;
|
||||
std::vector<int> encrypted_header_extension_ids;
|
||||
int rtp_abs_sendtime_extn_id = -1;
|
||||
// TODO(zhihuang): Add the ICE and DTLS related variables and methods from
|
||||
|
@ -92,7 +101,8 @@ class JsepTransport {
|
|||
rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport,
|
||||
rtc::scoped_refptr<webrtc::IceTransportInterface> rtcp_ice_transport,
|
||||
std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport,
|
||||
std::unique_ptr<webrtc::SrtpTransport> sdes_transport,
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::unique_ptr<webrtc::SrtpTransport> srtp_transport,
|
||||
std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport,
|
||||
std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport,
|
||||
|
@ -169,8 +179,9 @@ class JsepTransport {
|
|||
if (dtls_srtp_transport_) {
|
||||
return dtls_srtp_transport_.get();
|
||||
}
|
||||
if (sdes_transport_) {
|
||||
return sdes_transport_.get();
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
if (srtp_transport_) {
|
||||
return srtp_transport_.get();
|
||||
}
|
||||
if (unencrypted_rtp_transport_) {
|
||||
return unencrypted_rtp_transport_.get();
|
||||
|
@ -239,6 +250,12 @@ class JsepTransport {
|
|||
|
||||
void ActivateRtcpMux() RTC_RUN_ON(network_thread_);
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
bool SetSrtpCrypto(const std::optional<CryptoParams>& crypto,
|
||||
const std::vector<int>& encrypted_extension_ids,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source);
|
||||
|
||||
// Negotiates and sets the DTLS parameters based on the current local and
|
||||
// remote transport description, such as the DTLS role to use, and whether
|
||||
// DTLS should be activated.
|
||||
|
@ -290,7 +307,8 @@ class JsepTransport {
|
|||
// To avoid downcasting and make it type safe, keep three unique pointers for
|
||||
// different SRTP mode and only one of these is non-nullptr.
|
||||
const std::unique_ptr<webrtc::RtpTransport> unencrypted_rtp_transport_;
|
||||
const std::unique_ptr<webrtc::SrtpTransport> sdes_transport_;
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
const std::unique_ptr<webrtc::SrtpTransport> srtp_transport_;
|
||||
const std::unique_ptr<webrtc::DtlsSrtpTransport> dtls_srtp_transport_;
|
||||
|
||||
const rtc::scoped_refptr<webrtc::DtlsTransport> rtp_dtls_transport_;
|
||||
|
@ -301,6 +319,8 @@ class JsepTransport {
|
|||
|
||||
const rtc::scoped_refptr<webrtc::SctpTransport> sctp_transport_;
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
SrtpKeyCarrier srtp_key_carrier_ RTC_GUARDED_BY(network_thread_);
|
||||
RtcpMuxFilter rtcp_mux_negotiator_ RTC_GUARDED_BY(network_thread_);
|
||||
|
||||
// Cache the encrypted header extension IDs for SDES negoitation.
|
||||
|
|
|
@ -527,7 +527,8 @@ JsepTransportController::CreateUnencryptedRtpTransport(
|
|||
return unencrypted_rtp_transport;
|
||||
}
|
||||
|
||||
std::unique_ptr<SrtpTransport> JsepTransportController::CreateSdesTransport(
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::unique_ptr<SrtpTransport> JsepTransportController::CreateSrtpTransport(
|
||||
const std::string& transport_name,
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport,
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport) {
|
||||
|
@ -987,9 +988,10 @@ JsepTransportController::CreateJsepTransportDescription(
|
|||
? true
|
||||
: content_desc->rtcp_mux();
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
return cricket::JsepTransportDescription(
|
||||
rtcp_mux_enabled, encrypted_extension_ids, rtp_abs_sendtime_extn_id,
|
||||
transport_info.description);
|
||||
rtcp_mux_enabled, content_desc->crypto(), encrypted_extension_ids,
|
||||
rtp_abs_sendtime_extn_id, transport_info.description);
|
||||
}
|
||||
|
||||
std::vector<int> JsepTransportController::GetEncryptedHeaderExtensionIds(
|
||||
|
@ -1095,6 +1097,13 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
|||
if (transport) {
|
||||
return RTCError::OK();
|
||||
}
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
const cricket::MediaContentDescription* content_desc =
|
||||
content_info.media_description();
|
||||
if (certificate_ && content_desc->crypto().has_value()) {
|
||||
return RTCError(RTCErrorType::INVALID_PARAMETER,
|
||||
"Manual keys and DTLS-SRTP cannot be enabled at the same time.");
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<IceTransportInterface> ice =
|
||||
CreateIceTransport(content_info.name, /*rtcp=*/false);
|
||||
|
@ -1104,7 +1113,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
|||
|
||||
std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport;
|
||||
std::unique_ptr<RtpTransport> unencrypted_rtp_transport;
|
||||
std::unique_ptr<SrtpTransport> sdes_transport;
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::unique_ptr<SrtpTransport> srtp_transport;
|
||||
std::unique_ptr<DtlsSrtpTransport> dtls_srtp_transport;
|
||||
|
||||
rtc::scoped_refptr<IceTransportInterface> rtcp_ice;
|
||||
|
@ -1121,6 +1131,11 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
|||
<< "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
|
||||
unencrypted_rtp_transport = CreateUnencryptedRtpTransport(
|
||||
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
|
||||
} else if (content_desc->crypto().has_value()) {
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
srtp_transport = CreateSrtpTransport(
|
||||
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
|
||||
RTC_LOG(LS_INFO) << "Creating SrtpTransport.";
|
||||
} else {
|
||||
RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
|
||||
dtls_srtp_transport = CreateDtlsSrtpTransport(
|
||||
|
@ -1136,7 +1151,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport(
|
|||
std::unique_ptr<cricket::JsepTransport> jsep_transport =
|
||||
std::make_unique<cricket::JsepTransport>(
|
||||
content_info.name, certificate_, std::move(ice), std::move(rtcp_ice),
|
||||
std::move(unencrypted_rtp_transport), std::move(sdes_transport),
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::move(unencrypted_rtp_transport), std::move(srtp_transport),
|
||||
std::move(dtls_srtp_transport), std::move(rtp_dtls_transport),
|
||||
std::move(rtcp_dtls_transport), std::move(sctp_transport), [&]() {
|
||||
RTC_DCHECK_RUN_ON(network_thread_);
|
||||
|
|
|
@ -450,7 +450,8 @@ class JsepTransportController : public sigslot::has_slots<> {
|
|||
const std::string& transport_name,
|
||||
rtc::PacketTransportInternal* rtp_packet_transport,
|
||||
rtc::PacketTransportInternal* rtcp_packet_transport);
|
||||
std::unique_ptr<SrtpTransport> CreateSdesTransport(
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
std::unique_ptr<SrtpTransport> CreateSrtpTransport(
|
||||
const std::string& transport_name,
|
||||
cricket::DtlsTransportInternal* rtp_dtls_transport,
|
||||
cricket::DtlsTransportInternal* rtcp_dtls_transport);
|
||||
|
|
|
@ -1161,8 +1161,12 @@ bool IsMediaProtocolSupported(MediaType type,
|
|||
}
|
||||
}
|
||||
|
||||
void SetMediaProtocol(bool secure_transport, MediaContentDescription* desc) {
|
||||
if (secure_transport)
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
void SetMediaProtocol(bool secure_transport, bool manually_specify_keys,
|
||||
MediaContentDescription* desc) {
|
||||
if (desc->crypto().has_value() || manually_specify_keys)
|
||||
desc->set_protocol(kMediaProtocolSavpf);
|
||||
else if (secure_transport)
|
||||
desc->set_protocol(kMediaProtocolDtlsSavpf);
|
||||
else
|
||||
desc->set_protocol(kMediaProtocolAvpf);
|
||||
|
@ -2090,7 +2094,9 @@ RTCError MediaSessionDescriptionFactory::AddRtpContentForOffer(
|
|||
|
||||
// Insecure transport should only occur in testing.
|
||||
bool secure_transport = !(transport_desc_factory_->insecure());
|
||||
SetMediaProtocol(secure_transport, content_description.get());
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
SetMediaProtocol(secure_transport, manually_specify_keys(),
|
||||
content_description.get());
|
||||
|
||||
content_description->set_direction(media_description_options.direction);
|
||||
|
||||
|
|
|
@ -161,6 +161,9 @@ class MediaSessionDescriptionFactory {
|
|||
const VideoCodecs& recv_codecs);
|
||||
RtpHeaderExtensions filtered_rtp_header_extensions(
|
||||
RtpHeaderExtensions extensions) const;
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
bool manually_specify_keys() const { return manually_specify_keys_; }
|
||||
void set_manually_specify_keys(bool b) { manually_specify_keys_ = b; }
|
||||
|
||||
void set_enable_encrypted_rtp_header_extensions(bool enable) {
|
||||
enable_encrypted_rtp_header_extensions_ = enable;
|
||||
|
@ -319,6 +322,8 @@ class MediaSessionDescriptionFactory {
|
|||
webrtc::AlwaysValidPointer<rtc::UniqueRandomIdGenerator> const
|
||||
ssrc_generator_;
|
||||
bool enable_encrypted_rtp_header_extensions_ = false;
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
bool manually_specify_keys_ = false;
|
||||
const TransportDescriptionFactory* transport_desc_factory_;
|
||||
};
|
||||
|
||||
|
|
|
@ -2734,9 +2734,11 @@ void PeerConnection::ReportRemoteIceCandidateAdded(
|
|||
}
|
||||
}
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
bool PeerConnection::SrtpRequired() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
return dtls_enabled_;
|
||||
return (dtls_enabled_ ||
|
||||
sdp_handler_->webrtc_session_desc_factory()->ManuallySpecifyKeys());
|
||||
}
|
||||
|
||||
void PeerConnection::OnTransportControllerGatheringState(
|
||||
|
|
|
@ -286,8 +286,7 @@ RTCError VerifyCrypto(const SessionDescription* desc,
|
|||
continue;
|
||||
}
|
||||
#if !defined(WEBRTC_FUCHSIA)
|
||||
// RingRTC change to always disable DTLS.
|
||||
// RTC_CHECK(dtls_enabled) << "SDES protocol is only allowed in Fuchsia";
|
||||
RTC_CHECK(dtls_enabled) << "SDES protocol is only allowed in Fuchsia";
|
||||
#endif
|
||||
const std::string& mid = content_info.name;
|
||||
auto it = bundle_groups_by_mid.find(mid);
|
||||
|
@ -1397,6 +1396,8 @@ void SdpOfferAnswerHandler::Initialize(
|
|||
RTC_LOG(LS_INFO)
|
||||
<< "Disabling encryption. This should only be done in tests.";
|
||||
webrtc_session_desc_factory_->SetInsecureForTesting();
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
webrtc_session_desc_factory_->SetManuallySpecifyKeys(false);
|
||||
}
|
||||
|
||||
webrtc_session_desc_factory_->set_enable_encrypted_rtp_header_extensions(
|
||||
|
@ -3559,7 +3560,11 @@ RTCError SdpOfferAnswerHandler::ValidateSessionDescription(
|
|||
|
||||
// Verify crypto settings.
|
||||
std::string crypto_error;
|
||||
if (pc_->dtls_enabled()) {
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
// Do not verify if "ManuallySpecifyKeys" is set; `VerifyCrypto` only makes
|
||||
// sense for DTLS.
|
||||
if (!webrtc_session_desc_factory_->ManuallySpecifyKeys() &&
|
||||
pc_->dtls_enabled()) {
|
||||
RTCError crypto_error = VerifyCrypto(
|
||||
sdesc->description(), pc_->dtls_enabled(), bundle_groups_by_mid);
|
||||
if (!crypto_error.ok()) {
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
#include "api/crypto_params.h"
|
||||
#include "api/media_types.h"
|
||||
#include "api/rtp_parameters.h"
|
||||
#include "api/rtp_transceiver_direction.h"
|
||||
|
@ -121,6 +123,12 @@ class MediaContentDescription {
|
|||
bandwidth_type_ = bandwidth_type;
|
||||
}
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
const absl::optional<CryptoParams>& crypto() const { return crypto_; }
|
||||
void set_crypto(const absl::optional<CryptoParams>& crypto) {
|
||||
crypto_ = crypto;
|
||||
}
|
||||
|
||||
// List of RTP header extensions. URIs are **NOT** guaranteed to be unique
|
||||
// as they can appear twice when both encrypted and non-encrypted extensions
|
||||
// are present.
|
||||
|
@ -260,6 +268,8 @@ class MediaContentDescription {
|
|||
int bandwidth_ = kAutoBandwidth;
|
||||
std::string bandwidth_type_ = kApplicationSpecificBandwidth;
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
absl::optional<CryptoParams> crypto_;
|
||||
std::vector<webrtc::RtpExtension> rtp_header_extensions_;
|
||||
bool rtp_header_extensions_set_ = false;
|
||||
StreamParamsVec send_streams_;
|
||||
|
|
67
pc/srtp_key_carrier.cc
Normal file
67
pc/srtp_key_carrier.cc
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2009 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
|
||||
#include "pc/srtp_key_carrier.h"
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ssl_stream_adapter.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
SrtpKeyCarrier::SrtpKeyCarrier() = default;
|
||||
|
||||
SrtpKeyCarrier::~SrtpKeyCarrier() = default;
|
||||
|
||||
bool SrtpKeyCarrier::ApplyParams(const CryptoParams& crypto,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source) {
|
||||
switch (type) {
|
||||
case webrtc::SdpType::kOffer:
|
||||
offer_params_ = crypto;
|
||||
return true;
|
||||
case webrtc::SdpType::kPrAnswer:
|
||||
case webrtc::SdpType::kAnswer:
|
||||
return SetAnswer(crypto, source);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SrtpKeyCarrier::SetAnswer(const CryptoParams& answer_params,
|
||||
ContentSource source) {
|
||||
if (!offer_params_.has_value()) {
|
||||
RTC_LOG(LS_WARNING) << "Missing offer parameters when handling SRTP answer";
|
||||
return false;
|
||||
}
|
||||
|
||||
const CryptoParams& new_send_params =
|
||||
(source == CS_REMOTE) ? offer_params_.value() : answer_params;
|
||||
const CryptoParams& new_recv_params =
|
||||
(source == CS_REMOTE) ? answer_params : offer_params_.value();
|
||||
|
||||
if (new_send_params.crypto_suite == rtc::kSrtpInvalidCryptoSuite) {
|
||||
RTC_LOG(LS_WARNING) << "Invalid crypto suite(s) received for send";
|
||||
return false;
|
||||
}
|
||||
if (new_recv_params.crypto_suite == rtc::kSrtpInvalidCryptoSuite) {
|
||||
RTC_LOG(LS_WARNING) << "Invalid crypto suite(s) received for recv";
|
||||
return false;
|
||||
}
|
||||
|
||||
applied_send_params_ = new_send_params;
|
||||
applied_recv_params_ = new_recv_params;
|
||||
|
||||
offer_params_ = std::nullopt;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cricket
|
51
pc/srtp_key_carrier.h
Normal file
51
pc/srtp_key_carrier.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2009 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
|
||||
#ifndef PC_SRTP_KEY_CARRIER_H_
|
||||
#define PC_SRTP_KEY_CARRIER_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "api/crypto_params.h"
|
||||
#include "api/jsep.h"
|
||||
#include "pc/session_description.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
// A helper class used to propagate crypto params.
|
||||
class SrtpKeyCarrier {
|
||||
public:
|
||||
SrtpKeyCarrier();
|
||||
~SrtpKeyCarrier();
|
||||
|
||||
// Handle the offer/answer propagation of the crypto parameters.
|
||||
// If type is kPrAnswer or kAnswer, returns true iff `send_params` and
|
||||
// `recv_params` are usable.
|
||||
bool ApplyParams(const CryptoParams& crypto,
|
||||
webrtc::SdpType type,
|
||||
ContentSource source);
|
||||
|
||||
const CryptoParams& send_params() { return applied_send_params_; }
|
||||
const CryptoParams& recv_params() { return applied_recv_params_; }
|
||||
|
||||
private:
|
||||
// Applies params to be visible from `send_params` and `recv_params`.
|
||||
bool SetAnswer(const CryptoParams& answer_params, ContentSource source);
|
||||
|
||||
std::optional<CryptoParams> offer_params_;
|
||||
CryptoParams applied_send_params_;
|
||||
CryptoParams applied_recv_params_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // PC_SRTP_KEY_CARRIER_H_
|
|
@ -129,9 +129,14 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
|
|||
|
||||
if (!dtls_enabled) {
|
||||
RTC_LOG(LS_INFO) << "DTLS-SRTP disabled";
|
||||
transport_desc_factory_.SetInsecureForTesting();
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
SetManuallySpecifyKeys(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
// Manual keys are disabled if DTLS is on.
|
||||
SetManuallySpecifyKeys(false);
|
||||
if (certificate) {
|
||||
// Use `certificate`.
|
||||
certificate_request_state_ = CERTIFICATE_WAITING;
|
||||
|
@ -256,6 +261,16 @@ void WebRtcSessionDescriptionFactory::CreateAnswer(
|
|||
}
|
||||
}
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
void WebRtcSessionDescriptionFactory::SetManuallySpecifyKeys(bool b) {
|
||||
transport_desc_factory_.set_manually_specify_keys(b);
|
||||
session_desc_factory_.set_manually_specify_keys(b);
|
||||
}
|
||||
|
||||
bool WebRtcSessionDescriptionFactory::ManuallySpecifyKeys() const {
|
||||
return session_desc_factory_.manually_specify_keys();
|
||||
}
|
||||
|
||||
void WebRtcSessionDescriptionFactory::InternalCreateOffer(
|
||||
CreateSessionDescriptionRequest request) {
|
||||
if (sdp_info_->local_description()) {
|
||||
|
|
|
@ -73,6 +73,10 @@ class WebRtcSessionDescriptionFactory {
|
|||
void CreateAnswer(CreateSessionDescriptionObserver* observer,
|
||||
const cricket::MediaSessionOptions& session_options);
|
||||
|
||||
// RingRTC: Allow out-of-band / "manual" key negotiation.
|
||||
void SetManuallySpecifyKeys(bool b);
|
||||
bool ManuallySpecifyKeys() const;
|
||||
|
||||
void set_enable_encrypted_rtp_header_extensions(bool enable) {
|
||||
session_desc_factory_.set_enable_encrypted_rtp_header_extensions(enable);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "rffi/src/stats_observer.h"
|
||||
#include "rtc_base/message_digest.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
#include "rtc_base/third_party/base64/base64.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -201,11 +200,10 @@ Rust_disableDtlsAndSetSrtpKey(webrtc::SessionDescriptionInterface* session_descr
|
|||
}
|
||||
|
||||
cricket::CryptoParams crypto_params;
|
||||
crypto_params.crypto_suite = rtc::SrtpCryptoSuiteToName(crypto_suite);
|
||||
crypto_params.crypto_suite = crypto_suite;
|
||||
|
||||
std::string key(key_borrowed, key_len);
|
||||
std::string salt(salt_borrowed, salt_len);
|
||||
crypto_params.key_params = "inline:" + rtc::Base64::Encode(key + salt);
|
||||
crypto_params.key_params.SetData(key_borrowed, key_len);
|
||||
crypto_params.key_params.AppendData(salt_borrowed, salt_len);
|
||||
|
||||
// Disable DTLS
|
||||
for (cricket::TransportInfo& transport : session->transport_infos()) {
|
||||
|
@ -218,9 +216,7 @@ Rust_disableDtlsAndSetSrtpKey(webrtc::SessionDescriptionInterface* session_descr
|
|||
cricket::MediaContentDescription* media = content.media_description();
|
||||
if (media) {
|
||||
media->set_protocol(cricket::kMediaProtocolSavpf);
|
||||
std::vector<cricket::CryptoParams> cryptos;
|
||||
cryptos.push_back(crypto_params);
|
||||
media->set_cryptos(cryptos);
|
||||
media->set_crypto(crypto_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,18 +546,15 @@ CreateSessionDescriptionForGroupCall(bool local,
|
|||
|
||||
// Use SRTP master key material instead
|
||||
cricket::CryptoParams crypto_params;
|
||||
crypto_params.crypto_suite = rtc::SrtpCryptoSuiteToName(srtp_key.suite);
|
||||
std::string key(srtp_key.key_borrowed, srtp_key.key_len);
|
||||
std::string salt(srtp_key.salt_borrowed, srtp_key.salt_len);
|
||||
crypto_params.key_params = "inline:" + rtc::Base64::Encode(key + salt);
|
||||
crypto_params.crypto_suite = srtp_key.suite;
|
||||
crypto_params.key_params.SetData(srtp_key.key_borrowed, srtp_key.key_len);
|
||||
crypto_params.key_params.AppendData(srtp_key.salt_borrowed, srtp_key.salt_len);
|
||||
|
||||
auto set_rtp_params = [crypto_params] (cricket::MediaContentDescription* media) {
|
||||
media->set_protocol(cricket::kMediaProtocolSavpf);
|
||||
media->set_rtcp_mux(true);
|
||||
|
||||
std::vector<cricket::CryptoParams> cryptos;
|
||||
cryptos.push_back(crypto_params);
|
||||
media->set_cryptos(cryptos);
|
||||
media->set_crypto(crypto_params);
|
||||
};
|
||||
|
||||
auto local_direction = local ? RtpTransceiverDirection::kSendOnly : RtpTransceiverDirection::kRecvOnly;
|
||||
|
|
Loading…
Reference in a new issue