tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

crypto_options.cc (5363B)


      1 /*
      2 *  Copyright 2018 The WebRTC Project Authors. All rights reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "api/crypto/crypto_options.h"
     12 
     13 #include <cstdint>
     14 #include <optional>
     15 #include <set>
     16 #include <string>
     17 #include <utility>
     18 #include <vector>
     19 
     20 #include "absl/algorithm/container.h"
     21 #include "api/field_trials_view.h"
     22 #include "rtc_base/checks.h"
     23 #include "rtc_base/ssl_stream_adapter.h"
     24 
     25 namespace webrtc {
     26 
     27 CryptoOptions::CryptoOptions() {}
     28 
     29 // static
     30 CryptoOptions CryptoOptions::NoGcm() {
     31  CryptoOptions options;
     32  options.srtp.enable_gcm_crypto_suites = false;
     33  return options;
     34 }
     35 
     36 std::vector<int> CryptoOptions::GetSupportedDtlsSrtpCryptoSuites() const {
     37  std::vector<int> crypto_suites;
     38  // Note: kSrtpAes128CmSha1_80 is what is required to be supported (by
     39  // draft-ietf-rtcweb-security-arch), but kSrtpAes128CmSha1_32 is allowed as
     40  // well, and saves a few bytes per packet if it ends up selected.
     41  // As the cipher suite is potentially insecure, it will only be used if
     42  // enabled by both peers.
     43  if (srtp.enable_aes128_sha1_32_crypto_cipher) {
     44    crypto_suites.push_back(kSrtpAes128CmSha1_32);
     45  }
     46  if (srtp.enable_aes128_sha1_80_crypto_cipher) {
     47    crypto_suites.push_back(kSrtpAes128CmSha1_80);
     48  }
     49 
     50  // Note: GCM cipher suites are not the top choice since they increase the
     51  // packet size. In order to negotiate them the other side must not support
     52  // kSrtpAes128CmSha1_80.
     53  if (srtp.enable_gcm_crypto_suites) {
     54    crypto_suites.push_back(kSrtpAeadAes256Gcm);
     55    crypto_suites.push_back(kSrtpAeadAes128Gcm);
     56  }
     57  RTC_CHECK(!crypto_suites.empty());
     58  return crypto_suites;
     59 }
     60 
     61 bool CryptoOptions::operator==(const CryptoOptions& other) const {
     62  struct data_being_tested_for_equality {
     63    struct Srtp {
     64      bool enable_gcm_crypto_suites;
     65      bool enable_aes128_sha1_32_crypto_cipher;
     66      bool enable_aes128_sha1_80_crypto_cipher;
     67      bool enable_encrypted_rtp_header_extensions;
     68    } srtp;
     69    struct SFrame {
     70      bool require_frame_encryption;
     71    } sframe;
     72    EphemeralKeyExchangeCipherGroups ephemeral_key_exchange_cipher_groups;
     73  };
     74  static_assert(sizeof(data_being_tested_for_equality) == sizeof(*this),
     75                "Did you add something to CryptoOptions and forget to "
     76                "update operator==?");
     77 
     78  return srtp.enable_gcm_crypto_suites == other.srtp.enable_gcm_crypto_suites &&
     79         srtp.enable_aes128_sha1_32_crypto_cipher ==
     80             other.srtp.enable_aes128_sha1_32_crypto_cipher &&
     81         srtp.enable_aes128_sha1_80_crypto_cipher ==
     82             other.srtp.enable_aes128_sha1_80_crypto_cipher &&
     83         srtp.enable_encrypted_rtp_header_extensions ==
     84             other.srtp.enable_encrypted_rtp_header_extensions &&
     85         sframe.require_frame_encryption ==
     86             other.sframe.require_frame_encryption &&
     87         ephemeral_key_exchange_cipher_groups ==
     88             other.ephemeral_key_exchange_cipher_groups;
     89 }
     90 
     91 bool CryptoOptions::operator!=(const CryptoOptions& other) const {
     92  return !(*this == other);
     93 }
     94 
     95 CryptoOptions::EphemeralKeyExchangeCipherGroups::
     96    EphemeralKeyExchangeCipherGroups()
     97    : enabled_(SSLStreamAdapter::GetDefaultEphemeralKeyExchangeCipherGroups(
     98          /* field_trials= */ nullptr)) {}
     99 
    100 bool CryptoOptions::EphemeralKeyExchangeCipherGroups::operator==(
    101    const CryptoOptions::EphemeralKeyExchangeCipherGroups& other) const {
    102  return enabled_ == other.enabled_;
    103 }
    104 
    105 std::set<uint16_t>
    106 CryptoOptions::EphemeralKeyExchangeCipherGroups::GetSupported() {
    107  return SSLStreamAdapter::GetSupportedEphemeralKeyExchangeCipherGroups();
    108 }
    109 
    110 std::optional<std::string>
    111 CryptoOptions::EphemeralKeyExchangeCipherGroups::GetName(uint16_t group_id) {
    112  return SSLStreamAdapter::GetEphemeralKeyExchangeCipherGroupName(group_id);
    113 }
    114 
    115 void CryptoOptions::EphemeralKeyExchangeCipherGroups::AddFirst(uint16_t group) {
    116  std::erase(enabled_, group);
    117  enabled_.insert(enabled_.begin(), group);
    118 }
    119 
    120 void CryptoOptions::EphemeralKeyExchangeCipherGroups::Update(
    121    const FieldTrialsView* field_trials,
    122    const std::vector<uint16_t>* disabled_groups) {
    123  // Note: assumption is that these lists contains few elements...so converting
    124  // to set<> is not worth it.
    125  std::vector<uint16_t> default_groups =
    126      SSLStreamAdapter::GetDefaultEphemeralKeyExchangeCipherGroups(
    127          field_trials);
    128  // Remove all disabled.
    129  if (disabled_groups) {
    130    std::erase_if(default_groups, [&](uint16_t val) {
    131      return absl::c_linear_search(*disabled_groups, val);
    132    });
    133    std::erase_if(enabled_, [&](uint16_t val) {
    134      return absl::c_linear_search(*disabled_groups, val);
    135    });
    136  }
    137 
    138  // Add those enabled by field-trials first.
    139  std::vector<uint16_t> current = std::move(enabled_);
    140  enabled_.clear();
    141  for (auto val : default_groups) {
    142    if (!absl::c_linear_search(current, val)) {
    143      enabled_.push_back(val);
    144    }
    145  }
    146 
    147  // Then re-add those present (unless already there).
    148  for (auto val : current) {
    149    if (!absl::c_linear_search(enabled_, val)) {
    150      enabled_.push_back(val);
    151    }
    152  }
    153 }
    154 
    155 }  // namespace webrtc