Source code

Revision control

Copy as Markdown

Other Tools

/*
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/crypto/crypto_options.h"
#include <algorithm>
#include <cstdint>
#include <set>
#include <utility>
#include <vector>
#include "api/field_trials_view.h"
#include "rtc_base/checks.h"
#include "rtc_base/ssl_stream_adapter.h"
namespace webrtc {
CryptoOptions::CryptoOptions() {}
// static
CryptoOptions CryptoOptions::NoGcm() {
CryptoOptions options;
options.srtp.enable_gcm_crypto_suites = false;
return options;
}
std::vector<int> CryptoOptions::GetSupportedDtlsSrtpCryptoSuites() const {
std::vector<int> crypto_suites;
// Note: kSrtpAes128CmSha1_80 is what is required to be supported (by
// draft-ietf-rtcweb-security-arch), but kSrtpAes128CmSha1_32 is allowed as
// well, and saves a few bytes per packet if it ends up selected.
// As the cipher suite is potentially insecure, it will only be used if
// enabled by both peers.
if (srtp.enable_aes128_sha1_32_crypto_cipher) {
crypto_suites.push_back(kSrtpAes128CmSha1_32);
}
if (srtp.enable_aes128_sha1_80_crypto_cipher) {
crypto_suites.push_back(kSrtpAes128CmSha1_80);
}
// Note: GCM cipher suites are not the top choice since they increase the
// packet size. In order to negotiate them the other side must not support
// kSrtpAes128CmSha1_80.
if (srtp.enable_gcm_crypto_suites) {
crypto_suites.push_back(kSrtpAeadAes256Gcm);
crypto_suites.push_back(kSrtpAeadAes128Gcm);
}
RTC_CHECK(!crypto_suites.empty());
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_aes128_sha1_80_crypto_cipher;
bool enable_encrypted_rtp_header_extensions;
} srtp;
struct SFrame {
bool require_frame_encryption;
} sframe;
EphemeralKeyExchangeCipherGroups ephemeral_key_exchange_cipher_groups;
};
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_aes128_sha1_80_crypto_cipher ==
other.srtp.enable_aes128_sha1_80_crypto_cipher &&
srtp.enable_encrypted_rtp_header_extensions ==
other.srtp.enable_encrypted_rtp_header_extensions &&
sframe.require_frame_encryption ==
other.sframe.require_frame_encryption &&
ephemeral_key_exchange_cipher_groups ==
other.ephemeral_key_exchange_cipher_groups;
}
bool CryptoOptions::operator!=(const CryptoOptions& other) const {
return !(*this == other);
}
CryptoOptions::EphemeralKeyExchangeCipherGroups::
EphemeralKeyExchangeCipherGroups()
: enabled_(SSLStreamAdapter::GetDefaultEphemeralKeyExchangeCipherGroups(
/* field_trials= */ nullptr)) {}
bool CryptoOptions::EphemeralKeyExchangeCipherGroups::operator==(
const CryptoOptions::EphemeralKeyExchangeCipherGroups& other) const {
return enabled_ == other.enabled_;
}
std::set<uint16_t>
CryptoOptions::EphemeralKeyExchangeCipherGroups::GetSupported() {
return SSLStreamAdapter::GetSupportedEphemeralKeyExchangeCipherGroups();
}
void CryptoOptions::EphemeralKeyExchangeCipherGroups::AddFirst(uint16_t group) {
#if defined(WEBRTC_MOZILLA_BUILD)
// until we support c++20
enabled_.erase(std::remove(enabled_.begin(), enabled_.end(), group));
#else
std::erase(enabled_, group);
#endif
enabled_.insert(enabled_.begin(), group);
}
void CryptoOptions::EphemeralKeyExchangeCipherGroups::Update(
const FieldTrialsView* field_trials,
const std::vector<uint16_t>* disabled_groups) {
// Note: assumption is that these lists contains few elements...so converting
// to set<> is not worth it.
std::vector<uint16_t> default_groups =
SSLStreamAdapter::GetDefaultEphemeralKeyExchangeCipherGroups(
field_trials);
// Remove all disabled.
if (disabled_groups) {
default_groups.erase(std::remove_if(
default_groups.begin(), default_groups.end(), [&](uint16_t val) {
return std::find(disabled_groups->begin(), disabled_groups->end(),
val) != disabled_groups->end();
}));
enabled_.erase(
std::remove_if(enabled_.begin(), enabled_.end(), [&](uint16_t val) {
return std::find(disabled_groups->begin(), disabled_groups->end(),
val) != disabled_groups->end();
}));
}
// Add those enabled by field-trials first.
std::vector<uint16_t> current = std::move(enabled_);
for (auto val : default_groups) {
if (std::find(current.begin(), current.end(), val) == current.end()) {
enabled_.push_back(val);
}
}
// Then re-add those present (unless already there).
for (auto val : current) {
if (std::find(enabled_.begin(), enabled_.end(), val) == enabled_.end()) {
enabled_.push_back(val);
}
}
}
} // namespace webrtc