Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ssl_extension_unittest.cc   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "ssl.h"
#include "ssl3prot.h"
#include "sslerr.h"
#include "sslproto.h"

#include <memory>

#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

namespace nss_test {

class Dtls13LegacyCookieInjector : public TlsHandshakeFilter {
 public:
  Dtls13LegacyCookieInjector(const std::shared_ptr<TlsAgent>& a)
      : TlsHandshakeFilter(a, {kTlsHandshakeClientHello}) {}

  virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
                                               const DataBuffer& input,
                                               DataBuffer* output) {
    const uint8_t cookie_bytes[] = {0x03, 0x0A, 0x0B, 0x0C};
    uint32_t offset = 2 /* version */ + 32 /* random */;

    if (agent()->variant() != ssl_variant_datagram) {
      ADD_FAILURE();
      return KEEP;
    }

    if (header.handshake_type() != ssl_hs_client_hello) {
      return KEEP;
    }

    DataBuffer cookie(cookie_bytes, sizeof(cookie_bytes));
    *output = input;

    // Add the SID length (if any) to locate the cookie.
    uint32_t sid_len = 0;
    if (!output->Read(offset, 1, &sid_len)) {
      ADD_FAILURE();
      return KEEP;
    }
    offset += 1 + sid_len;
    output->Splice(cookie, offset, 1);

    return CHANGE;
  }

 private:
  DataBuffer cookie_;
};

class TlsExtensionTruncator : public TlsExtensionFilter {
 public:
  TlsExtensionTruncator(const std::shared_ptr<TlsAgent>& a, uint16_t extension,
                        size_t length)
      : TlsExtensionFilter(a), extension_(extension), length_(length) {}
  virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
                                               const DataBuffer& input,
                                               DataBuffer* output) {
    if (extension_type != extension_) {
      return KEEP;
    }
    if (input.len() <= length_) {
      return KEEP;
    }

    output->Assign(input.data(), length_);
    return CHANGE;
  }

 private:
  uint16_t extension_;
  size_t length_;
};

class TlsExtensionTestBase : public TlsConnectTestBase {
 protected:
  TlsExtensionTestBase(SSLProtocolVariant variant, uint16_t version)
      : TlsConnectTestBase(variant, version) {}

  void ClientHelloErrorTest(std::shared_ptr<PacketFilter> filter,
                            uint8_t desc = kTlsAlertDecodeError) {
    client_->SetFilter(filter);
    ConnectExpectAlert(server_, desc);
  }

  void ServerHelloErrorTest(std::shared_ptr<PacketFilter> filter,
                            uint8_t desc = kTlsAlertDecodeError) {
    server_->SetFilter(filter);
    ConnectExpectAlert(client_, desc);
  }

  static void InitSimpleSni(DataBuffer* extension) {
    const char* name = "host.name";
    const size_t namelen = PL_strlen(name);
    extension->Allocate(namelen + 5);
    extension->Write(0, namelen + 3, 2);
    extension->Write(2, static_cast<uint32_t>(0), 1);  // 0 == hostname
    extension->Write(3, namelen, 2);
    extension->Write(5, reinterpret_cast<const uint8_t*>(name), namelen);
  }

  void HrrThenRemoveExtensionsTest(SSLExtensionType type, PRInt32 client_error,
                                   PRInt32 server_error) {
    static const std::vector<SSLNamedGroup> client_groups = {
        ssl_grp_ec_secp384r1, ssl_grp_ec_curve25519};
    static const std::vector<SSLNamedGroup> server_groups = {
        ssl_grp_ec_curve25519, ssl_grp_ec_secp384r1};
    client_->ConfigNamedGroups(client_groups);
    server_->ConfigNamedGroups(server_groups);
    EnsureTlsSetup();
    StartConnect();
    client_->Handshake();  // Send ClientHello
    server_->Handshake();  // Send HRR.
    MakeTlsFilter<TlsExtensionDropper>(client_, type);
    Handshake();
    client_->CheckErrorCode(client_error);
    server_->CheckErrorCode(server_error);
  }
};

class TlsExtensionTestDtls : public TlsExtensionTestBase,
                             public ::testing::WithParamInterface<uint16_t> {
 public:
  TlsExtensionTestDtls()
      : TlsExtensionTestBase(ssl_variant_datagram, GetParam()) {}
};

class TlsExtensionTest12Plus : public TlsExtensionTestBase,
                               public ::testing::WithParamInterface<
                                   std::tuple<SSLProtocolVariant, uint16_t>> {
 public:
  TlsExtensionTest12Plus()
      : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {
  }
};

class TlsExtensionTest12 : public TlsExtensionTestBase,
                           public ::testing::WithParamInterface<
                               std::tuple<SSLProtocolVariant, uint16_t>> {
 public:
  TlsExtensionTest12()
      : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {
  }
};

class TlsExtensionTest13
    : public TlsExtensionTestBase,
      public ::testing::WithParamInterface<SSLProtocolVariant> {
 public:
  TlsExtensionTest13()
      : TlsExtensionTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {}

  void ConnectWithBogusVersionList(const uint8_t* buf, size_t len) {
    DataBuffer versions_buf(buf, len);
    MakeTlsFilter<TlsExtensionReplacer>(
        client_, ssl_tls13_supported_versions_xtn, versions_buf);
    ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
    client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
    server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
  }

  void ConnectWithReplacementVersionList(uint16_t version) {
    // Convert the version encoding for DTLS, if needed.
    if (variant_ == ssl_variant_datagram) {
      switch (version) {
        case SSL_LIBRARY_VERSION_TLS_1_3:
          version = SSL_LIBRARY_VERSION_DTLS_1_3_WIRE;
          break;
        case SSL_LIBRARY_VERSION_TLS_1_2:
          version = SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
          break;
        case SSL_LIBRARY_VERSION_TLS_1_1:
          /* TLS_1_1 maps to DTLS_1_0, see sslproto.h. */
          version = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
          break;
        default:
          PORT_Assert(0);
      }
    }

    DataBuffer versions_buf;
    size_t index = versions_buf.Write(0, 2, 1);
    versions_buf.Write(index, version, 2);
    MakeTlsFilter<TlsExtensionReplacer>(
        client_, ssl_tls13_supported_versions_xtn, versions_buf);
    ConnectExpectFail();
  }
};

class TlsExtensionTest13Stream : public TlsExtensionTestBase {
 public:
  TlsExtensionTest13Stream()
      : TlsExtensionTestBase(ssl_variant_stream, SSL_LIBRARY_VERSION_TLS_1_3) {}
};

class TlsExtensionTestGeneric : public TlsExtensionTestBase,
                                public ::testing::WithParamInterface<
                                    std::tuple<SSLProtocolVariant, uint16_t>> {
 public:
  TlsExtensionTestGeneric()
      : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {
  }
};

class TlsExtensionTestPre13 : public TlsExtensionTestBase,
                              public ::testing::WithParamInterface<
                                  std::tuple<SSLProtocolVariant, uint16_t>> {
 public:
  TlsExtensionTestPre13()
      : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {
  }
};

TEST_P(TlsExtensionTestGeneric, DamageSniLength) {
  ClientHelloErrorTest(
      std::make_shared<TlsExtensionDamager>(client_, ssl_server_name_xtn, 1));
}

TEST_P(TlsExtensionTestGeneric, DamageSniHostLength) {
  ClientHelloErrorTest(
      std::make_shared<TlsExtensionDamager>(client_, ssl_server_name_xtn, 4));
}

TEST_P(TlsExtensionTestGeneric, TruncateSni) {
  ClientHelloErrorTest(
      std::make_shared<TlsExtensionTruncator>(client_, ssl_server_name_xtn, 7));
}

// A valid extension that appears twice will be reported as unsupported.
TEST_P(TlsExtensionTestGeneric, RepeatSni) {
  DataBuffer extension;
  InitSimpleSni(&extension);
  ClientHelloErrorTest(std::make_shared<TlsExtensionInjector>(
                           client_, ssl_server_name_xtn, extension),
                       kTlsAlertIllegalParameter);
}

// An SNI entry with zero length is considered invalid (strangely, not if it is
// the last entry, which is probably a bug).
TEST_P(TlsExtensionTestGeneric, BadSni) {
  DataBuffer simple;
  InitSimpleSni(&simple);
  DataBuffer extension;
  extension.Allocate(simple.len() + 3);
  extension.Write(0, static_cast<uint32_t>(0), 3);
  extension.Write(3, simple);
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_server_name_xtn, extension));
}

TEST_P(TlsExtensionTestGeneric, EmptySni) {
  DataBuffer extension;
  extension.Allocate(2);
  extension.Write(0, static_cast<uint32_t>(0), 2);
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_server_name_xtn, extension));
}

TEST_P(TlsExtensionTestGeneric, EmptyAlpnExtension) {
  EnableAlpn();
  DataBuffer extension;
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_app_layer_protocol_xtn, extension),
                       kTlsAlertIllegalParameter);
}

// An empty ALPN isn't considered bad, though it does lead to there being no
// protocol for the server to select.
TEST_P(TlsExtensionTestGeneric, EmptyAlpnList) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_app_layer_protocol_xtn, extension),
                       kTlsAlertNoApplicationProtocol);
}

TEST_P(TlsExtensionTestGeneric, OneByteAlpn) {
  EnableAlpn();
  ClientHelloErrorTest(std::make_shared<TlsExtensionTruncator>(
      client_, ssl_app_layer_protocol_xtn, 1));
}

TEST_P(TlsExtensionTestGeneric, AlpnMissingValue) {
  EnableAlpn();
  // This will leave the length of the second entry, but no value.
  ClientHelloErrorTest(std::make_shared<TlsExtensionTruncator>(
      client_, ssl_app_layer_protocol_xtn, 5));
}

TEST_P(TlsExtensionTestGeneric, AlpnZeroLength) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x03, 0x01, 0x61, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestGeneric, AlpnLengthOverflow) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x03, 0x01, 0x61, 0x01};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestGeneric, AlpnMismatch) {
  const uint8_t client_alpn[] = {0x01, 0x61};
  client_->EnableAlpn(client_alpn, sizeof(client_alpn));
  const uint8_t server_alpn[] = {0x02, 0x61, 0x62};
  server_->EnableAlpn(server_alpn, sizeof(server_alpn));

  ClientHelloErrorTest(nullptr, kTlsAlertNoApplicationProtocol);
  client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
}

TEST_P(TlsExtensionTestGeneric, AlpnDisabledServer) {
  const uint8_t client_alpn[] = {0x01, 0x61};
  client_->EnableAlpn(client_alpn, sizeof(client_alpn));
  server_->EnableAlpn(nullptr, 0);

  ClientHelloErrorTest(nullptr, kTlsAlertUnsupportedExtension);
}

TEST_P(TlsConnectGeneric, AlpnDisabled) {
  server_->EnableAlpn(nullptr, 0);
  Connect();

  SSLNextProtoState state;
  uint8_t buf[255] = {0};
  unsigned int buf_len = 3;
  EXPECT_EQ(SECSuccess, SSL_GetNextProto(client_->ssl_fd(), &state, buf,
                                         &buf_len, sizeof(buf)));
  EXPECT_EQ(SSL_NEXT_PROTO_NO_SUPPORT, state);
  EXPECT_EQ(0U, buf_len);
}

// Many of these tests fail in TLS 1.3 because the extension is encrypted, which
// prevents modification of the value from the ServerHello.
TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyList) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      server_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyName) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x01, 0x00};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      server_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, AlpnReturnedListTrailingData) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x02, 0x01, 0x61, 0x00};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      server_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, AlpnReturnedExtraEntry) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x04, 0x01, 0x61, 0x01, 0x62};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      server_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, AlpnReturnedBadListLength) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x99, 0x01, 0x61, 0x00};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      server_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, AlpnReturnedBadNameLength) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x02, 0x99, 0x61};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      server_, ssl_app_layer_protocol_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, AlpnReturnedUnknownName) {
  EnableAlpn();
  const uint8_t val[] = {0x00, 0x02, 0x01, 0x67};
  DataBuffer extension(val, sizeof(val));
  ServerHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           server_, ssl_app_layer_protocol_xtn, extension),
                       kTlsAlertIllegalParameter);
}

TEST_P(TlsExtensionTestDtls, SrtpShort) {
  EnableSrtp();
  ClientHelloErrorTest(
      std::make_shared<TlsExtensionTruncator>(client_, ssl_use_srtp_xtn, 3));
}

TEST_P(TlsExtensionTestDtls, SrtpOdd) {
  EnableSrtp();
  const uint8_t val[] = {0x00, 0x01, 0xff, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_use_srtp_xtn, extension));
}

TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsBadLength) {
  const uint8_t val[] = {0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_signature_algorithms_xtn, extension));
}

TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsTrailingData) {
  // make sure the test uses an algorithm that is legal for
  // tls 1.3 (or tls 1.3 will throw a handshake failure alert
  // instead of a decode error alert)
  const uint8_t val[] = {0x00, 0x02, 0x08, 0x09, 0x00};  // sha-256, rsa-pss-pss
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_signature_algorithms_xtn, extension));
}

TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsEmpty) {
  const uint8_t val[] = {0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_signature_algorithms_xtn, extension),
                       kTlsAlertHandshakeFailure);
}

TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsNoOverlap) {
  const uint8_t val[] = {0x00, 0x02, 0xff, 0xff};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_signature_algorithms_xtn, extension),
                       kTlsAlertHandshakeFailure);
}

TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
  const uint8_t val[] = {0x00, 0x01, 0x04};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_signature_algorithms_xtn, extension));
}

TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) {
  // 31 unknown signature algorithms followed by sha-256, rsa-pss
  const uint8_t val[] = {
      0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x04};
  DataBuffer extension(val, sizeof(val));
  MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn,
                                      extension);
  client_->ExpectSendAlert(kTlsAlertBadRecordMac);
  server_->ExpectSendAlert(kTlsAlertBadRecordMac);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}

TEST_P(TlsExtensionTestGeneric, NoSupportedGroups) {
  ClientHelloErrorTest(
      std::make_shared<TlsExtensionDropper>(client_, ssl_supported_groups_xtn),
      version_ < SSL_LIBRARY_VERSION_TLS_1_3 ? kTlsAlertDecryptError
                                             : kTlsAlertMissingExtension);
}

TEST_P(TlsExtensionTestGeneric, SupportedCurvesShort) {
  const uint8_t val[] = {0x00, 0x01, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_elliptic_curves_xtn, extension));
}

TEST_P(TlsExtensionTestGeneric, SupportedCurvesBadLength) {
  const uint8_t val[] = {0x09, 0x99, 0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_elliptic_curves_xtn, extension));
}

TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) {
  const uint8_t val[] = {0x00, 0x02, 0x00, 0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_elliptic_curves_xtn, extension));
}

TEST_P(TlsExtensionTest12, SupportedCurvesDisableX25519) {
  // Disable session resumption.
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);

  // Ensure that we can enable its use in the key exchange.
  SECStatus rv =
      NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, NSS_USE_ALG_IN_SSL_KX, 0);
  ASSERT_EQ(SECSuccess, rv);
  rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
                              0);
  ASSERT_EQ(SECSuccess, rv);

  auto capture1 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_elliptic_curves_xtn);
  Connect();

  EXPECT_TRUE(capture1->captured());
  const DataBuffer& ext1 = capture1->extension();

  uint32_t count;
  ASSERT_TRUE(ext1.Read(0, 2, &count));

  // Whether or not we've seen x25519 offered in this handshake.
  bool seen1_x25519 = false;
  for (size_t offset = 2; offset <= count; offset++) {
    uint32_t val;
    ASSERT_TRUE(ext1.Read(offset, 2, &val));
    if (val == ssl_grp_ec_curve25519) {
      seen1_x25519 = true;
      break;
    }
  }
  ASSERT_TRUE(seen1_x25519);

  // Ensure that we can disable its use in the key exchange.
  rv = NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, 0, NSS_USE_ALG_IN_SSL_KX);
  ASSERT_EQ(SECSuccess, rv);
  rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
                              0);
  ASSERT_EQ(SECSuccess, rv);

  // Clean up after the last run.
  Reset();
  auto capture2 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_elliptic_curves_xtn);
  Connect();

  EXPECT_TRUE(capture2->captured());
  const DataBuffer& ext2 = capture2->extension();

  ASSERT_TRUE(ext2.Read(0, 2, &count));

  // Whether or not we've seen x25519 offered in this handshake.
  bool seen2_x25519 = false;
  for (size_t offset = 2; offset <= count; offset++) {
    uint32_t val;
    ASSERT_TRUE(ext2.Read(offset, 2, &val));

    if (val == ssl_grp_ec_curve25519) {
      seen2_x25519 = true;
      break;
    }
  }

  ASSERT_FALSE(seen2_x25519);
}

TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) {
  const uint8_t val[] = {0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_ec_point_formats_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, SupportedPointsBadLength) {
  const uint8_t val[] = {0x99, 0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_ec_point_formats_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, SupportedPointsTrailingData) {
  const uint8_t val[] = {0x01, 0x00, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_ec_point_formats_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, SupportedPointsCompressed) {
  const uint8_t val[] = {0x01, 0x02};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_ec_point_formats_xtn, extension),
                       kTlsAlertIllegalParameter);
}

TEST_P(TlsExtensionTestPre13, SupportedPointsUndefined) {
  const uint8_t val[] = {0x01, 0xAA};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_ec_point_formats_xtn, extension),
                       kTlsAlertIllegalParameter);
}

TEST_P(TlsExtensionTestPre13, RenegotiationInfoBadLength) {
  const uint8_t val[] = {0x99};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_renegotiation_info_xtn, extension));
}

TEST_P(TlsExtensionTestPre13, RenegotiationInfoMismatch) {
  const uint8_t val[] = {0x01, 0x00};
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_renegotiation_info_xtn, extension));
}

// The extension has to contain a length.
TEST_P(TlsExtensionTestPre13, RenegotiationInfoExtensionEmpty) {
  DataBuffer extension;
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
      client_, ssl_renegotiation_info_xtn, extension));
}

// This only works on TLS 1.2, since it relies on static RSA; otherwise libssl
// picks the wrong cipher suite.
TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) {
  const SSLSignatureScheme schemes[] = {ssl_sig_rsa_pss_rsae_sha512,
                                        ssl_sig_rsa_pss_rsae_sha384};

  auto capture =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
  client_->SetSignatureSchemes(schemes, PR_ARRAY_SIZE(schemes));
  EnableOnlyStaticRsaCiphers();
  Connect();

  const DataBuffer& ext = capture->extension();
  EXPECT_EQ(2 + PR_ARRAY_SIZE(schemes) * 2, ext.len());
  for (size_t i = 0, cursor = 2;
       i < PR_ARRAY_SIZE(schemes) && cursor < ext.len(); ++i) {
    uint32_t v = 0;
    EXPECT_TRUE(ext.Read(cursor, 2, &v));
    cursor += 2;
    EXPECT_EQ(schemes[i], static_cast<SSLSignatureScheme>(v));
  }
}

// This only works on TLS 1.2, since it relies on DSA.
TEST_P(TlsExtensionTest12, SignatureAlgorithmDisableDSA) {
  const std::vector<SSLSignatureScheme> schemes = {
      ssl_sig_dsa_sha1, ssl_sig_dsa_sha256, ssl_sig_dsa_sha384,
      ssl_sig_dsa_sha512, ssl_sig_rsa_pss_rsae_sha256};

  // Connect with DSA enabled by policy.
  SECStatus rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE,
                                        NSS_USE_ALG_IN_SSL_KX, 0);
  ASSERT_EQ(SECSuccess, rv);
  rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
                              0);
  ASSERT_EQ(SECSuccess, rv);

  Reset(TlsAgent::kServerDsa);
  auto capture1 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
  client_->SetSignatureSchemes(schemes.data(), schemes.size());
  Connect();

  // Check if all the signature algorithms are advertised.
  EXPECT_TRUE(capture1->captured());
  const DataBuffer& ext1 = capture1->extension();
  EXPECT_EQ(2U + 2U * schemes.size(), ext1.len());

  // Connect with DSA disabled by policy.
  rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, 0,
                              NSS_USE_ALG_IN_SSL_KX);
  ASSERT_EQ(SECSuccess, rv);
  rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
                              0);
  ASSERT_EQ(SECSuccess, rv);

  Reset(TlsAgent::kServerDsa);
  auto capture2 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
  client_->SetSignatureSchemes(schemes.data(), schemes.size());
  ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
  server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);

  // Check if no DSA algorithms are advertised.
  EXPECT_TRUE(capture2->captured());
  const DataBuffer& ext2 = capture2->extension();
  EXPECT_EQ(2U + 2U, ext2.len());
  uint32_t v = 0;
  EXPECT_TRUE(ext2.Read(2, 2, &v));
  EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, v);
}

// Temporary test to verify that we choke on an empty ClientKeyShare.
// This test will fail when we implement HelloRetryRequest.
TEST_P(TlsExtensionTest13, EmptyClientKeyShare) {
  ClientHelloErrorTest(std::make_shared<TlsExtensionTruncator>(
                           client_, ssl_tls13_key_share_xtn, 2),
                       kTlsAlertHandshakeFailure);
}

// These tests only work in stream mode because the client sends a
// cleartext alert which causes a MAC error on the server. With
// stream this causes handshake failure but with datagram, the
// packet gets dropped.
TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) {
  EnsureTlsSetup();
  MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_key_share_xtn);
  client_->ExpectSendAlert(kTlsAlertMissingExtension);
  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
  ConnectExpectFail();
  EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
  EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}

TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) {
  const uint16_t wrong_group = ssl_grp_ec_secp384r1;

  static const uint8_t key_share[] = {
      wrong_group >> 8,
      wrong_group & 0xff,  // Group we didn't offer.
      0x00,
      0x02,  // length = 2
      0x01,
      0x02};
  DataBuffer buf(key_share, sizeof(key_share));
  EnsureTlsSetup();
  MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf);
  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
  ConnectExpectFail();
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
  EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}

TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) {
  const uint16_t wrong_group = 0xffff;

  static const uint8_t key_share[] = {
      wrong_group >> 8,
      wrong_group & 0xff,  // Group we didn't offer.
      0x00,
      0x02,  // length = 2
      0x01,
      0x02};
  DataBuffer buf(key_share, sizeof(key_share));
  EnsureTlsSetup();
  MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf);
  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
  ConnectExpectFail();
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
  EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}

TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
  SetupForResume();
  DataBuffer empty;
  MakeTlsFilter<TlsExtensionInjector>(server_, ssl_signature_algorithms_xtn,
                                      empty);
  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
  ConnectExpectFail();
  EXPECT_EQ(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, client_->error_code());
  EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}

struct PskIdentity {
  DataBuffer identity;
  uint32_t obfuscated_ticket_age;
};

class TlsPreSharedKeyReplacer;

typedef std::function<void(TlsPreSharedKeyReplacer*)>
    TlsPreSharedKeyReplacerFunc;

class TlsPreSharedKeyReplacer : public TlsExtensionFilter {
 public:
  TlsPreSharedKeyReplacer(const std::shared_ptr<TlsAgent>& a,
                          TlsPreSharedKeyReplacerFunc function)
      : TlsExtensionFilter(a), identities_(), binders_(), function_(function) {}

  static size_t CopyAndMaybeReplace(TlsParser* parser, size_t size,
                                    const std::unique_ptr<DataBuffer>& replace,
                                    size_t index, DataBuffer* output) {
    DataBuffer tmp;
    bool ret = parser->ReadVariable(&tmp, size);
    EXPECT_EQ(true, ret);
    if (!ret) return 0;
    if (replace) {
      tmp = *replace;
    }

    return WriteVariable(output, index, tmp, size);
  }

  PacketFilter::Action FilterExtension(uint16_t extension_type,
                                       const DataBuffer& input,
                                       DataBuffer* output) {
    if (extension_type != ssl_tls13_pre_shared_key_xtn) {
      return KEEP;
    }

    if (!Decode(input)) {
      return KEEP;
    }

    // Call the function.
    function_(this);

    Encode(output);

    return CHANGE;
  }

  std::vector<PskIdentity> identities_;
  std::vector<DataBuffer> binders_;

 private:
  bool Decode(const DataBuffer& input) {
    std::unique_ptr<TlsParser> parser(new TlsParser(input));
    DataBuffer identities;

    if (!parser->ReadVariable(&identities, 2)) {
      ADD_FAILURE();
      return false;
    }

    DataBuffer binders;
    if (!parser->ReadVariable(&binders, 2)) {
      ADD_FAILURE();
      return false;
    }
    EXPECT_EQ(0UL, parser->remaining());

    // Now parse the inner sections.
    parser.reset(new TlsParser(identities));
    while (parser->remaining()) {
      PskIdentity identity;

      if (!parser->ReadVariable(&identity.identity, 2)) {
        ADD_FAILURE();
        return false;
      }

      if (!parser->Read(&identity.obfuscated_ticket_age, 4)) {
        ADD_FAILURE();
        return false;
      }

      identities_.push_back(identity);
    }

    parser.reset(new TlsParser(binders));
    while (parser->remaining()) {
      DataBuffer binder;

      if (!parser->ReadVariable(&binder, 1)) {
        ADD_FAILURE();
        return false;
      }

      binders_.push_back(binder);
    }

    return true;
  }

  void Encode(DataBuffer* output) {
    DataBuffer identities;
    size_t index = 0;
    for (auto id : identities_) {
      index = WriteVariable(&identities, index, id.identity, 2);
      index = identities.Write(index, id.obfuscated_ticket_age, 4);
    }

    DataBuffer binders;
    index = 0;
    for (auto binder : binders_) {
      index = WriteVariable(&binders, index, binder, 1);
    }

    output->Truncate(0);
    index = 0;
    index = WriteVariable(output, index, identities, 2);
    index = WriteVariable(output, index, binders, 2);
  }

  TlsPreSharedKeyReplacerFunc function_;
};

TEST_F(TlsExtensionTest13Stream, ResumeEmptyPskLabel) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->identities_[0].identity.Truncate(0);
      });
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

// Flip the first byte of the binder.
TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderValue) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->binders_[0].Write(0, r->binders_[0].data()[0] ^ 0xff, 1);
      });
  ConnectExpectAlert(server_, kTlsAlertDecryptError);
  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}

// Do the same with an External PSK.
TEST_P(TlsConnectTls13, TestTls13PskInvalidBinderValue) {
  ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
  ASSERT_TRUE(!!slot);
  ScopedPK11SymKey key(
      PK11_KeyGen(slot.get(), CKM_HKDF_KEY_GEN, nullptr, 16, nullptr));
  ASSERT_TRUE(!!key);
  AddPsk(key, std::string("foo"), ssl_hash_sha256);
  StartConnect();
  ASSERT_TRUE(client_->MaybeSetResumptionToken());

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->binders_[0].Write(0, r->binders_[0].data()[0] ^ 0xff, 1);
      });
  ConnectExpectAlert(server_, kTlsAlertDecryptError);
  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}

// Extend the binder by one.
TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderLength) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->binders_[0].Write(r->binders_[0].len(), 0xff, 1);
      });
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

// Binders must be at least 32 bytes.
TEST_F(TlsExtensionTest13Stream, ResumeBinderTooShort) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Truncate(31); });
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

// Duplicate the identity and binder. This will fail with an error
// processing the binder (because we extended the identity list.)
TEST_F(TlsExtensionTest13Stream, ResumeTwoPsks) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->identities_.push_back(r->identities_[0]);
        r->binders_.push_back(r->binders_[0]);
      });
  ConnectExpectAlert(server_, kTlsAlertDecryptError);
  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}

// The next two tests have mismatches in the number of identities
// and binders. This generates an illegal parameter alert.
TEST_F(TlsExtensionTest13Stream, ResumeTwoIdentitiesOneBinder) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->identities_.push_back(r->identities_[0]);
      });
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

TEST_F(TlsExtensionTest13Stream, ResumeOneIdentityTwoBinders) {
  SetupForResume();

  MakeTlsFilter<TlsPreSharedKeyReplacer>(
      client_, [](TlsPreSharedKeyReplacer* r) {
        r->binders_.push_back(r->binders_[0]);
      });
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

TEST_F(TlsExtensionTest13Stream, ResumePskExtensionNotLast) {
  SetupForResume();

  const uint8_t empty_buf[] = {0};
  DataBuffer empty(empty_buf, 0);
  // Inject an unused extension after the PSK extension.
  MakeTlsFilter<TlsExtensionAppender>(client_, kTlsHandshakeClientHello, 0xffff,
                                      empty);
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

TEST_F(TlsExtensionTest13Stream, ResumeNoKeModes) {
  SetupForResume();

  DataBuffer empty;
  MakeTlsFilter<TlsExtensionDropper>(client_,
                                     ssl_tls13_psk_key_exchange_modes_xtn);
  ConnectExpectAlert(server_, kTlsAlertMissingExtension);
  client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT);
  server_->CheckErrorCode(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES);
}

// The following test contains valid but unacceptable PreSharedKey
// modes and therefore produces non-resumption followed by MAC
// errors.
TEST_F(TlsExtensionTest13Stream, ResumeBogusKeModes) {
  SetupForResume();
  const static uint8_t ke_modes[] = {1,  // Length
                                     kTls13PskKe};

  DataBuffer modes(ke_modes, sizeof(ke_modes));
  MakeTlsFilter<TlsExtensionReplacer>(
      client_, ssl_tls13_psk_key_exchange_modes_xtn, modes);
  client_->ExpectSendAlert(kTlsAlertBadRecordMac);
  server_->ExpectSendAlert(kTlsAlertBadRecordMac);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}

TEST_P(TlsExtensionTest13, NoKeModesIfResumptionOff) {
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
  auto capture = MakeTlsFilter<TlsExtensionCapture>(
      client_, ssl_tls13_psk_key_exchange_modes_xtn);
  Connect();
  EXPECT_FALSE(capture->captured());
}

// In these tests, we downgrade to TLS 1.2, causing the
// server to negotiate TLS 1.2.
// 1. Both sides only support TLS 1.3, so we get a cipher version
//    error.
TEST_P(TlsExtensionTest13, RemoveTls13FromVersionList) {
  ExpectAlert(server_, kTlsAlertProtocolVersion);
  ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2);
  client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
}

// 2. Server supports 1.2 and 1.3, client supports 1.2, so we
//    can't negotiate any ciphers.
TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListServerV12) {
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);
  ExpectAlert(server_, kTlsAlertHandshakeFailure);
  ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2);
  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
  server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
}

// 3. Server supports 1.2 and 1.3, client supports 1.2 and 1.3
// but advertises 1.2 (because we changed things).
TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListBothV12) {
  client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);
  // The downgrade check is disabled in DTLS 1.3, so all that happens when we
  // tamper with the supported versions is that the Finished check fails.
  ExpectAlert(client_, kTlsAlertIllegalParameter);
  ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2);
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

TEST_P(TlsExtensionTest13, HrrThenRemoveSignatureAlgorithms) {
  ExpectAlert(server_, kTlsAlertMissingExtension);
  HrrThenRemoveExtensionsTest(ssl_signature_algorithms_xtn,
                              SSL_ERROR_MISSING_EXTENSION_ALERT,
                              SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION);
}

TEST_P(TlsExtensionTest13, HrrThenRemoveKeyShare) {
  ExpectAlert(server_, kTlsAlertIllegalParameter);
  HrrThenRemoveExtensionsTest(ssl_tls13_key_share_xtn,
                              SSL_ERROR_ILLEGAL_PARAMETER_ALERT,
                              SSL_ERROR_BAD_2ND_CLIENT_HELLO);
}

TEST_P(TlsExtensionTest13, HrrThenRemoveSupportedGroups) {
  ExpectAlert(server_, kTlsAlertMissingExtension);
  HrrThenRemoveExtensionsTest(ssl_supported_groups_xtn,
                              SSL_ERROR_MISSING_EXTENSION_ALERT,
                              SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION);
}

TEST_P(TlsExtensionTest13, EmptyVersionList) {
  static const uint8_t kExt[] = {0x00, 0x00};
  ConnectWithBogusVersionList(kExt, sizeof(kExt));
}

TEST_P(TlsExtensionTest13, OddVersionList) {
  static const uint8_t kExt[] = {0x00, 0x01, 0x00};
  ConnectWithBogusVersionList(kExt, sizeof(kExt));
}

TEST_P(TlsExtensionTest13, SignatureAlgorithmsInvalidTls13) {
  // testing the case where we ask for a invalid parameter for tls13
  const uint8_t val[] = {0x00, 0x02, 0x04, 0x01};  // sha-256, rsa-pkcs1
  DataBuffer extension(val, sizeof(val));
  ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
                           client_, ssl_signature_algorithms_xtn, extension),
                       kTlsAlertHandshakeFailure);
}

// Use the stream version number for TLS 1.3 (0x0304) in DTLS.
TEST_F(TlsConnectDatagram13, TlsVersionInDtls) {
  static const uint8_t kExt[] = {0x02, 0x03, 0x04};

  DataBuffer versions_buf(kExt, sizeof(kExt));
  MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_tls13_supported_versions_xtn,
                                      versions_buf);
  ConnectExpectAlert(server_, kTlsAlertProtocolVersion);
  client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
}

// TODO: this only tests extensions in server messages.  The client can extend
// Certificate messages, which is not checked here.
class TlsBogusExtensionTest : public TlsConnectTestBase,
                              public ::testing::WithParamInterface<
                                  std::tuple<SSLProtocolVariant, uint16_t>> {
 public:
  TlsBogusExtensionTest()
      : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {}

 protected:
  virtual void ConnectAndFail(uint8_t message) = 0;

  void AddFilter(uint8_t message, uint16_t extension) {
    static uint8_t empty_buf[1] = {0};
    DataBuffer empty(empty_buf, 0);
    auto filter =
        MakeTlsFilter<TlsExtensionAppender>(server_, message, extension, empty);
    if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
      filter->EnableDecryption();
    }
  }

  void Run(uint8_t message, uint16_t extension = 0xff) {
    EnsureTlsSetup();
    AddFilter(message, extension);
    ConnectAndFail(message);
  }
};

class TlsBogusExtensionTestPre13 : public TlsBogusExtensionTest {
 protected:
  void ConnectAndFail(uint8_t) override {
    ConnectExpectAlert(client_, kTlsAlertUnsupportedExtension);
  }
};

class TlsBogusExtensionTest13 : public TlsBogusExtensionTest {
 protected:
  void ConnectAndFail(uint8_t message) override {
    if (message != kTlsHandshakeServerHello) {
      ConnectExpectAlert(client_, kTlsAlertUnsupportedExtension);
      return;
    }

    FailWithAlert(kTlsAlertUnsupportedExtension);
  }

  void FailWithAlert(uint8_t alert) {
    StartConnect();
    client_->Handshake();  // ClientHello
    server_->Handshake();  // ServerHello

    client_->ExpectSendAlert(alert);
    client_->Handshake();
    if (variant_ == ssl_variant_stream) {
      server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    }
    server_->Handshake();
  }
};

TEST_P(TlsBogusExtensionTestPre13, AddBogusExtensionServerHello) {
  Run(kTlsHandshakeServerHello);
}

TEST_P(TlsBogusExtensionTest13, AddBogusExtensionServerHello) {
  Run(kTlsHandshakeServerHello);
}

TEST_P(TlsBogusExtensionTest13, AddBogusExtensionEncryptedExtensions) {
  Run(kTlsHandshakeEncryptedExtensions);
}

TEST_P(TlsBogusExtensionTest13, AddBogusExtensionCertificate) {
  Run(kTlsHandshakeCertificate);
}

// It's perfectly valid to set unknown extensions in CertificateRequest.
TEST_P(TlsBogusExtensionTest13, AddBogusExtensionCertificateRequest) {
  server_->RequestClientAuth(false);
  AddFilter(kTlsHandshakeCertificateRequest, 0xff);
  ConnectExpectAlert(client_, kTlsAlertDecryptError);
  client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE);
}

TEST_P(TlsBogusExtensionTest13, AddBogusExtensionHelloRetryRequest) {
  static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
  server_->ConfigNamedGroups(groups);

  Run(kTlsHandshakeHelloRetryRequest);
}

// NewSessionTicket allows unknown extensions AND it isn't protected by the
// Finished.  So adding an unknown extension doesn't cause an error.
TEST_P(TlsBogusExtensionTest13, AddBogusExtensionNewSessionTicket) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);

  AddFilter(kTlsHandshakeNewSessionTicket, 0xff);
  Connect();
  SendReceive();
  CheckKeys();

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_TICKET);
  Connect();
  SendReceive();
}

class TlsDisallowedExtensionTest13 : public TlsBogusExtensionTest {
 protected:
  void ConnectAndFail(uint8_t message) override {
    ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
  }
};

TEST_P(TlsDisallowedExtensionTest13, AddVersionExtensionEncryptedExtensions) {
  Run(kTlsHandshakeEncryptedExtensions, ssl_tls13_supported_versions_xtn);
}

TEST_P(TlsDisallowedExtensionTest13, AddVersionExtensionCertificate) {
  Run(kTlsHandshakeCertificate, ssl_tls13_supported_versions_xtn);
}

TEST_P(TlsDisallowedExtensionTest13, AddVersionExtensionCertificateRequest) {
  server_->RequestClientAuth(false);
  Run(kTlsHandshakeCertificateRequest, ssl_tls13_supported_versions_xtn);
}

/* For unadvertised disallowed extensions an unsupported_extension alert is
 * thrown since NSS checks for unadvertised extensions before its disallowed
 * extension check. */

class TlsDisallowedUnadvertisedExtensionTest13 : public TlsBogusExtensionTest {
 protected:
  void ConnectAndFail(uint8_t message) override {
    uint8_t alert = kTlsAlertUnsupportedExtension;
    if (message == kTlsHandshakeCertificateRequest) {
      alert = kTlsAlertIllegalParameter;
    }
    ConnectExpectAlert(client_, alert);
  }
};

TEST_P(TlsDisallowedUnadvertisedExtensionTest13,
       AddPSKExtensionEncryptedExtensions) {
  Run(kTlsHandshakeEncryptedExtensions, ssl_tls13_pre_shared_key_xtn);
}

TEST_P(TlsDisallowedUnadvertisedExtensionTest13, AddPSKExtensionCertificate) {
  Run(kTlsHandshakeCertificate, ssl_tls13_pre_shared_key_xtn);
}

TEST_P(TlsDisallowedUnadvertisedExtensionTest13,
       AddPSKExtensionCertificateRequest) {
  server_->RequestClientAuth(false);
  Run(kTlsHandshakeCertificateRequest, ssl_tls13_pre_shared_key_xtn);
}

TEST_P(TlsConnectStream, IncludePadding) {
  EnsureTlsSetup();
  SSL_EnableTls13GreaseEch(client_->ssl_fd(), PR_FALSE);  // Don't GREASE

  // This needs to be long enough to push a TLS 1.0 ClientHello over 255, but
  // short enough not to push a TLS 1.3 ClientHello over 511.
  static const char* long_name =
      "chickenchickenchickenchickenchickenchickenchickenchicken."
      "chickenchickenchickenchickenchickenchickenchickenchicken."
      "chickenchickenchickenchickenchicken.";
  SECStatus rv = SSL_SetURL(client_->ssl_fd(), long_name);
  EXPECT_EQ(SECSuccess, rv);

  auto capture = MakeTlsFilter<TlsExtensionCapture>(client_, ssl_padding_xtn);
  client_->StartConnect();
  client_->Handshake();
  EXPECT_TRUE(capture->captured());
}

TEST_F(TlsConnectDatagram13, Dtls13RejectLegacyCookie) {
  EnsureTlsSetup();
  MakeTlsFilter<Dtls13LegacyCookieInjector>(client_);
  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

TEST_P(TlsConnectGeneric, ClientHelloExtensionPermutation) {
  EnsureTlsSetup();
  ASSERT_TRUE(SSL_OptionSet(client_->ssl_fd(),
                            SSL_ENABLE_CH_EXTENSION_PERMUTATION,
                            PR_TRUE) == SECSuccess);
  Connect();
}

TEST_F(TlsConnectStreamTls13, ClientHelloExtensionPermutationWithPSK) {
  EnsureTlsSetup();

  ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
  const uint8_t kPskDummyVal_[16] = {0x01, 0x02, 0x03, 0x04, 0x05,
                                     0x06, 0x07, 0x08, 0x09, 0x0a,
                                     0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
  SECItem psk_item;
  psk_item.type = siBuffer;
  psk_item.len = sizeof(kPskDummyVal_);
  psk_item.data = const_cast<uint8_t*>(kPskDummyVal_);
  PK11SymKey* key =
      PK11_ImportSymKey(slot.get(), CKM_HKDF_KEY_GEN, PK11_OriginUnwrap,
                        CKA_DERIVE, &psk_item, NULL);

  ScopedPK11SymKey scoped_psk_(key);
  const std::string kPskDummyLabel_ = "NSS PSK GTEST label";
  const SSLHashType kPskHash_ = ssl_hash_sha384;
  AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_);

  ASSERT_TRUE(SSL_OptionSet(client_->ssl_fd(),
                            SSL_ENABLE_CH_EXTENSION_PERMUTATION,
                            PR_TRUE) == SECSuccess);
  Connect();
  SendReceive();
  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none);
}

/* This test checks that the ClientHello extension order is actually permuted
 * if ss->opt.chXtnPermutation is set. It is asserted that at least one out of
 * 10 extension orders differs from the others.
 *
 * This is a probabilistic test: The default TLS 1.3 ClientHello contains 8
 * extensions, leading to a 1/8! probability for any extension order and the
 * same probability for two drawn extension orders to coincide.
 * Since all sequences are compared against each other this leads to a false
 * positive rate of (1/8!)^(n^2-n).
 * To achieve a spurious failure rate << 1/2^64, we compare n=10 drawn orders.
 *
 * This test assures that randomisation is happening but does not check quality
 * of the used Fisher-Yates shuffle. */

TEST_F(TlsConnectStreamTls13,
       ClientHelloExtensionPermutationProbabilisticTest) {
  std::vector<std::vector<uint16_t>> orders;

  /* Capture the extension order of 10 ClientHello messages. */
  for (size_t i = 0; i < 10; i++) {
    client_->StartConnect();
    /* Enable ClientHello extension permutation. */
    ASSERT_TRUE(SSL_OptionSet(client_->ssl_fd(),
                              SSL_ENABLE_CH_EXTENSION_PERMUTATION,
                              PR_TRUE) == SECSuccess);
    /* Capture extension order filter. */
    auto filter = MakeTlsFilter<TlsExtensionOrderCapture>(
        client_, kTlsHandshakeClientHello);
    /* Send ClientHello. */
    client_->Handshake();
    /* Remember extension order. */
    orders.push_back(filter->order);
    /* Reset client / server state. */
    Reset();
  }

  /* Check for extension order inequality. */
  size_t inequal = 0;
  for (auto& outerOrders : orders) {
    for (auto& innerOrders : orders) {
      if (outerOrders != innerOrders) {
        inequal++;
      }
    }
  }
  ASSERT_TRUE(inequal >= 1);
}

// The certificate_authorities xtn can be included in a ClientHello [RFC 8446,
// Section 4.2]
TEST_F(TlsConnectStreamTls13, ClientHelloCertAuthXtnToleration) {
  EnsureTlsSetup();
  uint8_t bodyBuf[3] = {0x00, 0x01, 0xff};
  DataBuffer body(bodyBuf, sizeof(bodyBuf));
  auto ch = MakeTlsFilter<TlsExtensionAppender>(
      client_, kTlsHandshakeClientHello, ssl_tls13_certificate_authorities_xtn,
      body);
  // The Connection will fail because the added extension isn't in the client's
  // transcript  not because the extension is unsupported (Bug 1815167).
  server_->ExpectSendAlert(bad_record_mac);
  client_->ExpectSendAlert(bad_record_mac);
  ConnectExpectFail();
  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
  client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}

INSTANTIATE_TEST_SUITE_P(
    ExtensionStream, TlsExtensionTestGeneric,
    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                       TlsConnectTestBase::kTlsVAll));
INSTANTIATE_TEST_SUITE_P(
    ExtensionDatagram, TlsExtensionTestGeneric,
    ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
                       TlsConnectTestBase::kTlsV11Plus));
INSTANTIATE_TEST_SUITE_P(ExtensionDatagramOnly, TlsExtensionTestDtls,
                         TlsConnectTestBase::kTlsV11Plus);

INSTANTIATE_TEST_SUITE_P(ExtensionTls12, TlsExtensionTest12,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV12));

INSTANTIATE_TEST_SUITE_P(ExtensionTls12Plus, TlsExtensionTest12Plus,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV12Plus));

INSTANTIATE_TEST_SUITE_P(
    ExtensionPre13Stream, TlsExtensionTestPre13,
    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                       TlsConnectTestBase::kTlsV10ToV12));
INSTANTIATE_TEST_SUITE_P(ExtensionPre13Datagram, TlsExtensionTestPre13,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV11V12));

INSTANTIATE_TEST_SUITE_P(ExtensionTls13, TlsExtensionTest13,
                         TlsConnectTestBase::kTlsVariantsAll);

INSTANTIATE_TEST_SUITE_P(
    BogusExtensionStream, TlsBogusExtensionTestPre13,
    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                       TlsConnectTestBase::kTlsV10ToV12));
INSTANTIATE_TEST_SUITE_P(
    BogusExtensionDatagram, TlsBogusExtensionTestPre13,
    ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
                       TlsConnectTestBase::kTlsV11V12));

INSTANTIATE_TEST_SUITE_P(BogusExtension13, TlsBogusExtensionTest13,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV13));

INSTANTIATE_TEST_SUITE_P(DisallowedExtension13, TlsDisallowedExtensionTest13,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV13));

INSTANTIATE_TEST_SUITE_P(DisallowedUnadvertisedExtension13,
                         TlsDisallowedUnadvertisedExtensionTest13,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV13));

}  // namespace nss_test

Messung V0.5
C=94 H=94 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge