tor-browser

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

tls_xyber_unittest.cc (11887B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "ssl.h"
      8 #include "sslerr.h"
      9 #include "sslproto.h"
     10 
     11 extern "C" {
     12 // This is not something that should make you happy.
     13 #include "libssl_internals.h"
     14 }
     15 
     16 #include "gtest_utils.h"
     17 #include "nss_scoped_ptrs.h"
     18 #include "tls_connect.h"
     19 #include "tls_filter.h"
     20 #include "tls_parser.h"
     21 
     22 namespace nss_test {
     23 
     24 TEST_P(TlsKeyExchangeTest13, Xyber768d00Supported) {
     25  EnsureKeyShareSetup();
     26  ConfigNamedGroups({ssl_grp_kem_xyber768d00});
     27 
     28  Connect();
     29  CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_xyber768d00, ssl_auth_rsa_sign,
     30            ssl_sig_rsa_pss_rsae_sha256);
     31 }
     32 
     33 TEST_P(TlsKeyExchangeTest, Tls12ClientXyber768d00NotSupported) {
     34  EnsureKeyShareSetup();
     35  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
     36                           SSL_LIBRARY_VERSION_TLS_1_2);
     37  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
     38                           SSL_LIBRARY_VERSION_TLS_1_3);
     39  client_->DisableAllCiphers();
     40  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
     41  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid);
     42  EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(
     43                            client_->ssl_fd(),
     44                            kECDHEGroups.size() + kEcdhHybridGroups.size()));
     45 
     46  Connect();
     47  std::vector<SSLNamedGroup> groups = GetGroupDetails(groups_capture_);
     48  for (auto group : groups) {
     49    EXPECT_NE(group, ssl_grp_kem_xyber768d00);
     50  }
     51 }
     52 
     53 TEST_P(TlsKeyExchangeTest13, Tls12ServerXyber768d00NotSupported) {
     54  if (variant_ == ssl_variant_datagram) {
     55    /* Bug 1874451 - reenable this test */
     56    return;
     57  }
     58 
     59  EnsureKeyShareSetup();
     60 
     61  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
     62                           SSL_LIBRARY_VERSION_TLS_1_3);
     63  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
     64                           SSL_LIBRARY_VERSION_TLS_1_2);
     65 
     66  client_->DisableAllCiphers();
     67  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
     68  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid);
     69  client_->ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519});
     70  EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
     71 
     72  server_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
     73  server_->EnableCiphersByKeyExchange(ssl_kea_ecdh_hybrid);
     74  server_->ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519});
     75 
     76  Connect();
     77  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
     78            ssl_sig_rsa_pss_rsae_sha256);
     79 }
     80 
     81 TEST_P(TlsKeyExchangeTest13, Xyber768d00ClientDisabledByPolicy) {
     82  EnsureKeyShareSetup();
     83  client_->SetPolicy(SEC_OID_XYBER768D00, 0, NSS_USE_ALG_IN_SSL_KX);
     84  ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_secp256r1});
     85 
     86  Connect();
     87  CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1});
     88 }
     89 
     90 TEST_P(TlsKeyExchangeTest13, Xyber768d00ServerDisabledByPolicy) {
     91  EnsureKeyShareSetup();
     92  server_->SetPolicy(SEC_OID_XYBER768D00, 0, NSS_USE_ALG_IN_SSL_KX);
     93  ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_secp256r1});
     94 
     95  Connect();
     96  CheckKEXDetails({ssl_grp_kem_xyber768d00, ssl_grp_ec_secp256r1},
     97                  {ssl_grp_kem_xyber768d00}, ssl_grp_ec_secp256r1);
     98 }
     99 
    100 void CheckECDHShareReuse(const std::shared_ptr<TlsExtensionCapture>& capture) {
    101  EXPECT_TRUE(capture->captured());
    102  const DataBuffer& ext = capture->extension();
    103  DataBuffer xyber_share;
    104  DataBuffer x25519_share;
    105 
    106  size_t offset = 0;
    107  uint32_t ext_len;
    108  ext.Read(0, 2, &ext_len);
    109  EXPECT_EQ(ext.len() - 2, ext_len);
    110  offset += 2;
    111 
    112  uint32_t named_group;
    113  uint32_t named_group_len;
    114  ext.Read(offset, 2, &named_group);
    115  ext.Read(offset + 2, 2, &named_group_len);
    116  while (offset < ext.len()) {
    117    if (named_group == ssl_grp_kem_xyber768d00) {
    118      xyber_share = DataBuffer(ext.data() + offset + 2 + 2, named_group_len);
    119    }
    120    if (named_group == ssl_grp_ec_curve25519) {
    121      x25519_share = DataBuffer(ext.data() + offset + 2 + 2, named_group_len);
    122    }
    123    offset += 2 + 2 + named_group_len;
    124    ext.Read(offset, 2, &named_group);
    125    ext.Read(offset + 2, 2, &named_group_len);
    126  }
    127  EXPECT_EQ(offset, ext.len());
    128 
    129  ASSERT_TRUE(xyber_share.data());
    130  ASSERT_TRUE(x25519_share.data());
    131  ASSERT_GT(xyber_share.len(), x25519_share.len());
    132  EXPECT_EQ(
    133      0, memcmp(xyber_share.data(), x25519_share.data(), x25519_share.len()));
    134 }
    135 
    136 TEST_P(TlsKeyExchangeTest13, XyberShareReuseFirst) {
    137  if (variant_ == ssl_variant_datagram) {
    138    /* Bug 1874451 - reenable this test */
    139    return;
    140  }
    141  EnsureKeyShareSetup();
    142  ConfigNamedGroups({ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519});
    143  EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
    144 
    145  Connect();
    146 
    147  CheckKEXDetails({ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519},
    148                  {ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519});
    149  CheckECDHShareReuse(shares_capture_);
    150 }
    151 
    152 TEST_P(TlsKeyExchangeTest13, XyberShareReuseSecond) {
    153  if (variant_ == ssl_variant_datagram) {
    154    /* Bug 1874451 - reenable this test */
    155    return;
    156  }
    157  EnsureKeyShareSetup();
    158  ConfigNamedGroups({ssl_grp_ec_curve25519, ssl_grp_kem_xyber768d00});
    159  EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
    160 
    161  Connect();
    162 
    163  CheckKEXDetails({ssl_grp_ec_curve25519, ssl_grp_kem_xyber768d00},
    164                  {ssl_grp_ec_curve25519, ssl_grp_kem_xyber768d00});
    165  CheckECDHShareReuse(shares_capture_);
    166 }
    167 
    168 class XyberShareDamager : public TlsExtensionFilter {
    169 public:
    170  typedef enum {
    171    downgrade,
    172    extend,
    173    truncate,
    174    zero_ecdh,
    175    modify_ecdh,
    176    modify_kyber,
    177  } damage_type;
    178 
    179  XyberShareDamager(const std::shared_ptr<TlsAgent>& a, damage_type damage)
    180      : TlsExtensionFilter(a), damage_(damage) {}
    181 
    182  virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
    183                                               const DataBuffer& input,
    184                                               DataBuffer* output) {
    185    if (extension_type != ssl_tls13_key_share_xtn) {
    186      return KEEP;
    187    }
    188 
    189    // Find the Xyber768d00 share
    190    size_t offset = 0;
    191    if (agent()->role() == TlsAgent::CLIENT) {
    192      offset += 2;  // skip KeyShareClientHello length
    193    }
    194 
    195    uint32_t named_group;
    196    uint32_t named_group_len;
    197    input.Read(offset, 2, &named_group);
    198    input.Read(offset + 2, 2, &named_group_len);
    199    while (named_group != ssl_grp_kem_xyber768d00) {
    200      offset += 2 + 2 + named_group_len;
    201      input.Read(offset, 2, &named_group);
    202      input.Read(offset + 2, 2, &named_group_len);
    203    }
    204    EXPECT_EQ(named_group, ssl_grp_kem_xyber768d00);
    205 
    206    DataBuffer xyber_key_share(input.data() + offset, 2 + 2 + named_group_len);
    207 
    208    // Damage the Xyber768d00 share
    209    unsigned char* ecdh_component = xyber_key_share.data() + 2 + 2;
    210    unsigned char* kyber_component =
    211        xyber_key_share.data() + 2 + 2 + X25519_PUBLIC_KEY_BYTES;
    212    switch (damage_) {
    213      case XyberShareDamager::downgrade:
    214        // Downgrade a Xyber768d00 share to X25519
    215        xyber_key_share.Truncate(2 + 2 + X25519_PUBLIC_KEY_BYTES);
    216        xyber_key_share.Write(0, ssl_grp_ec_curve25519, 2);
    217        xyber_key_share.Write(2, X25519_PUBLIC_KEY_BYTES, 2);
    218        break;
    219      case XyberShareDamager::truncate:
    220        // Truncate a Xyber768d00 share after the X25519 component
    221        xyber_key_share.Truncate(2 + 2 + X25519_PUBLIC_KEY_BYTES);
    222        xyber_key_share.Write(2, X25519_PUBLIC_KEY_BYTES, 2);
    223        break;
    224      case XyberShareDamager::extend:
    225        // Append 4 bytes to a Xyber768d00 share
    226        uint32_t current_len;
    227        xyber_key_share.Read(2, 2, &current_len);
    228        xyber_key_share.Write(xyber_key_share.len(), current_len, 4);
    229        xyber_key_share.Write(2, current_len + 4, 2);
    230        break;
    231      case XyberShareDamager::zero_ecdh:
    232        // Replace an X25519 component with 0s
    233        memset(ecdh_component, 0, X25519_PUBLIC_KEY_BYTES);
    234        break;
    235      case XyberShareDamager::modify_ecdh:
    236        // Flip a bit in the X25519 component
    237        ecdh_component[0] ^= 0x01;
    238        break;
    239      case XyberShareDamager::modify_kyber:
    240        // Flip a bit in the Kyber component
    241        kyber_component[0] ^= 0x01;
    242        break;
    243    }
    244 
    245    *output = input;
    246    output->Splice(xyber_key_share, offset, 2 + 2 + named_group_len);
    247 
    248    // Fix the KeyShareClientHello length if necessary
    249    if (agent()->role() == TlsAgent::CLIENT &&
    250        xyber_key_share.len() != 2 + 2 + named_group_len) {
    251      output->Write(0, output->len() - 2, 2);
    252    }
    253 
    254    return CHANGE;
    255  }
    256 
    257 private:
    258  damage_type damage_;
    259 };
    260 
    261 class TlsXyberDamageTest
    262    : public TlsConnectTestBase,
    263      public ::testing::WithParamInterface<XyberShareDamager::damage_type> {
    264 public:
    265  TlsXyberDamageTest()
    266      : TlsConnectTestBase(ssl_variant_stream, SSL_LIBRARY_VERSION_TLS_1_3) {}
    267 
    268 protected:
    269  void Damage(const std::shared_ptr<TlsAgent>& agent) {
    270    EnsureTlsSetup();
    271    client_->ConfigNamedGroups(
    272        {ssl_grp_ec_curve25519, ssl_grp_kem_xyber768d00});
    273    server_->ConfigNamedGroups(
    274        {ssl_grp_kem_xyber768d00, ssl_grp_ec_curve25519});
    275    EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
    276    MakeTlsFilter<XyberShareDamager>(agent, GetParam());
    277  }
    278 };
    279 
    280 TEST_P(TlsXyberDamageTest, DamageClientShare) {
    281  Damage(client_);
    282 
    283  switch (GetParam()) {
    284    case XyberShareDamager::extend:
    285    case XyberShareDamager::truncate:
    286      ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
    287      server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE);
    288      break;
    289    case XyberShareDamager::zero_ecdh:
    290      ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
    291      server_->CheckErrorCode(SEC_ERROR_INVALID_KEY);
    292      break;
    293    case XyberShareDamager::downgrade:
    294    case XyberShareDamager::modify_ecdh:
    295    case XyberShareDamager::modify_kyber:
    296      client_->ExpectSendAlert(kTlsAlertBadRecordMac);
    297      server_->ExpectSendAlert(kTlsAlertBadRecordMac);
    298      ConnectExpectFail();
    299      client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
    300      server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
    301      break;
    302  }
    303 }
    304 
    305 TEST_P(TlsXyberDamageTest, DamageServerShare) {
    306  Damage(server_);
    307 
    308  switch (GetParam()) {
    309    case XyberShareDamager::extend:
    310    case XyberShareDamager::truncate:
    311      client_->ExpectSendAlert(kTlsAlertIllegalParameter);
    312      server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    313      ConnectExpectFail();
    314      client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE);
    315      break;
    316    case XyberShareDamager::zero_ecdh:
    317      client_->ExpectSendAlert(kTlsAlertIllegalParameter);
    318      server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    319      ConnectExpectFail();
    320      client_->CheckErrorCode(SEC_ERROR_INVALID_KEY);
    321      break;
    322    case XyberShareDamager::downgrade:
    323    case XyberShareDamager::modify_ecdh:
    324    case XyberShareDamager::modify_kyber:
    325      client_->ExpectSendAlert(kTlsAlertBadRecordMac);
    326      server_->ExpectSendAlert(kTlsAlertBadRecordMac);
    327      ConnectExpectFail();
    328      client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
    329      server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
    330      break;
    331  }
    332 }
    333 
    334 INSTANTIATE_TEST_SUITE_P(TlsXyberDamageTest, TlsXyberDamageTest,
    335                         ::testing::Values(XyberShareDamager::downgrade,
    336                                           XyberShareDamager::extend,
    337                                           XyberShareDamager::truncate,
    338                                           XyberShareDamager::zero_ecdh,
    339                                           XyberShareDamager::modify_ecdh,
    340                                           XyberShareDamager::modify_kyber));
    341 
    342 }  // namespace nss_test