Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/gtests/ssl_gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 29 kB image not shown  

Quelle  tls_grease_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 "secerr.h"
#include "ssl.h"

#include "gtest_utils.h"
#include "tls_connect.h"
#include "util.h"

namespace nss_test {

const uint8_t kTlsGreaseExtensionMessages[] = {kTlsHandshakeEncryptedExtensions,
                                               kTlsHandshakeCertificate};

const uint16_t kTlsGreaseValues[] = {
    0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a,
    0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa};

const uint8_t kTlsGreasePskValues[] = {0x0B, 0x2A, 0x49, 0x68,
                                       0x87, 0xA6, 0xC5, 0xE4};

size_t countGreaseInBuffer(const DataBuffer& list) {
  if (!list.len()) {
    return 0;
  }
  size_t occurrence = 0;
  for (uint16_t greaseVal : kTlsGreaseValues) {
    for (size_t i = 0; i < (list.len() - 1); i += 2) {
      uint16_t sample = list.data()[i + 1] + (list.data()[i] << 8);
      if (greaseVal == sample) {
        occurrence++;
      }
    }
  }
  return occurrence;
}

class GreasePresenceAbsenceTestBase : public TlsConnectTestBase {
 public:
  GreasePresenceAbsenceTestBase(SSLProtocolVariant variant, uint16_t version,
                                bool shouldGrease)
      : TlsConnectTestBase(variant, version), set_grease_(shouldGrease){};

  void SetupGrease() {
    EnsureTlsSetup();
    ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, set_grease_),
              SECSuccess);
    ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, set_grease_),
              SECSuccess);
  }

  bool expectGrease() {
    return set_grease_ && version_ >= SSL_LIBRARY_VERSION_TLS_1_3;
  }

  void checkGreasePresence(const int ifEnabled, const int ifDisabled,
                           const DataBuffer& buffer) {
    size_t expected = expectGrease() ? size_t(ifEnabled) : size_t(ifDisabled);
    EXPECT_EQ(expected, countGreaseInBuffer(buffer));
  }

 private:
  bool set_grease_;
};

class GreasePresenceAbsenceTestAllVersions
    : public GreasePresenceAbsenceTestBase,
      public ::testing::WithParamInterface<
          std::tuple<SSLProtocolVariant, uint16_t, bool>> {
 public:
  GreasePresenceAbsenceTestAllVersions()
      : GreasePresenceAbsenceTestBase(std::get<0>(GetParam()),
                                      std::get<1>(GetParam()),
                                      std::get<2>(GetParam())){};
};

// Varies stream/datagram, TLS Version and whether GREASE is enabled
INSTANTIATE_TEST_SUITE_P(GreaseTests, GreasePresenceAbsenceTestAllVersions,
                         ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
                                            TlsConnectTestBase::kTlsV11Plus,
                                            ::testing::Values(truefalse)));

// Varies whether GREASE is enabled for TLS13 only
class GreasePresenceAbsenceTestTlsStream13
    : public GreasePresenceAbsenceTestBase,
      public ::testing::WithParamInterface<bool> {
 public:
  GreasePresenceAbsenceTestTlsStream13()
      : GreasePresenceAbsenceTestBase(
            ssl_variant_stream, SSL_LIBRARY_VERSION_TLS_1_3, GetParam()){};
};

INSTANTIATE_TEST_SUITE_P(GreaseTests, GreasePresenceAbsenceTestTlsStream13,
                         ::testing::Values(truefalse));

// These tests check for the presence / absence of GREASE values in the various
// positions that we are permitted to add them. For positions which existed in
// prior versions of TLS, we check that enabling GREASE is only effective when
// negotiating TLS1.3 or higher and that disabling GREASE results in the absence
// of any GREASE values.
// For positions that specific to TLS1.3, we only check that enabling/disabling
// GREASE results in the correct presence/absence of the GREASE value.

TEST_P(GreasePresenceAbsenceTestAllVersions, ClientGreaseCiphersuites) {
  SetupGrease();

  auto ch1 = MakeTlsFilter<ClientHelloCiphersuiteCapture>(client_);
  Connect();
  EXPECT_TRUE(ch1->captured());

  checkGreasePresence(1, 0, ch1->contents());
}

TEST_P(GreasePresenceAbsenceTestAllVersions, ClientGreaseNamedGroups) {
  SetupGrease();

  auto ch1 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_supported_groups_xtn);
  Connect();
  EXPECT_TRUE(ch1->captured());

  checkGreasePresence(1, 0, ch1->extension());
}

TEST_P(GreasePresenceAbsenceTestAllVersions, ClientGreaseKeyShare) {
  SetupGrease();

  auto ch1 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_tls13_key_share_xtn);
  Connect();
  EXPECT_TRUE((version_ >= SSL_LIBRARY_VERSION_TLS_1_3) == ch1->captured());

  checkGreasePresence(1, 0, ch1->extension());
}

TEST_P(GreasePresenceAbsenceTestAllVersions, ClientGreaseSigAlg) {
  SetupGrease();

  auto ch1 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
  Connect();
  EXPECT_TRUE((version_ >= SSL_LIBRARY_VERSION_TLS_1_2) == ch1->captured());

  checkGreasePresence(1, 0, ch1->extension());
}

TEST_P(GreasePresenceAbsenceTestAllVersions, ClientGreaseSupportedVersions) {
  SetupGrease();

  auto ch1 = MakeTlsFilter<TlsExtensionCapture>(
      client_, ssl_tls13_supported_versions_xtn);
  Connect();
  EXPECT_TRUE((version_ >= SSL_LIBRARY_VERSION_TLS_1_3) == ch1->captured());

  // Supported Versions have a 1 byte length field.
  TlsParser extParser(ch1->extension());
  DataBuffer versions;
  extParser.ReadVariable(&versions, 1);

  checkGreasePresence(1, 0, versions);
}

TEST_P(GreasePresenceAbsenceTestTlsStream13, ClientGreasePskExchange) {
  SetupGrease();

  auto ch1 = MakeTlsFilter<TlsExtensionCapture>(
      client_, ssl_tls13_psk_key_exchange_modes_xtn);
  Connect();
  EXPECT_TRUE(ch1->captured());

  // PSK Exchange Modes have a 1 byte length field
  TlsParser extParser(ch1->extension());
  DataBuffer modes;
  extParser.ReadVariable(&modes, 1);

  // Scan for single byte GREASE PSK Values
  size_t numGrease = 0;
  for (uint8_t greaseVal : kTlsGreasePskValues) {
    for (unsigned long i = 0; i < modes.len(); i++) {
      if (greaseVal == modes.data()[i]) {
        numGrease++;
      }
    }
  }

  EXPECT_EQ(expectGrease() ? size_t(1) : size_t(0), numGrease);
}

TEST_P(GreasePresenceAbsenceTestAllVersions, ClientGreaseAlpn) {
  SetupGrease();
  EnableAlpn();

  auto ch1 =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_app_layer_protocol_xtn);
  Connect();
  EXPECT_TRUE((version_ >= SSL_LIBRARY_VERSION_TLS_1_1) == ch1->captured());

  // ALPN Xtns have a redundant two-byte length
  TlsParser alpnParser(ch1->extension());
  alpnParser.Skip(2);  // Skip the length
  DataBuffer alpnEntry;

  // Each ALPN entry has a single byte length prefixed.
  size_t greaseAlpnEntrys = 0;
  while (alpnParser.remaining()) {
    alpnParser.ReadVariable(&alpnEntry, 1);
    if (alpnEntry.len() == 2) {
      greaseAlpnEntrys += countGreaseInBuffer(alpnEntry);
    }
  }

  EXPECT_EQ(expectGrease() ? size_t(1) : size_t(0), greaseAlpnEntrys);
}

TEST_P(GreasePresenceAbsenceTestAllVersions, GreaseClientHelloExtension) {
  SetupGrease();

  auto ch1 =
      MakeTlsFilter<TlsHandshakeRecorder>(client_, kTlsHandshakeClientHello);
  Connect();
  EXPECT_TRUE(ch1->buffer().len() > 0);

  TlsParser extParser(ch1->buffer());
  EXPECT_TRUE(extParser.Skip(2 + 32));     // Version + Random
  EXPECT_TRUE(extParser.SkipVariable(1));  // Session ID
  if (variant_ == ssl_variant_datagram) {
    EXPECT_TRUE(extParser.SkipVariable(1));  // Cookie
  }
  EXPECT_TRUE(extParser.SkipVariable(2));  // Ciphersuites
  EXPECT_TRUE(extParser.SkipVariable(1));  // Compression Methods
  EXPECT_TRUE(extParser.Skip(2));          // Extension Lengths

  // Scan for a 1-byte and a 0-byte extension.
  uint32_t extType;
  DataBuffer extBuf;
  bool foundSmall = false;
  bool foundLarge = false;
  size_t numFound = 0;
  while (extParser.remaining()) {
    extParser.Read(&extType, 2);
    extParser.ReadVariable(&extBuf, 2);
    for (uint16_t greaseVal : kTlsGreaseValues) {
      if (greaseVal == extType) {
        numFound++;
        foundSmall |= extBuf.len() == 0;
        foundLarge |= extBuf.len() > 0;
      }
    }
  }

  EXPECT_EQ(foundSmall, expectGrease());
  EXPECT_EQ(foundLarge, expectGrease());
  EXPECT_EQ(numFound, expectGrease() ? size_t(2) : size_t(0));
}

TEST_P(GreasePresenceAbsenceTestTlsStream13, GreaseCertificateRequestSigAlg) {
  SetupGrease();
  client_->SetupClientAuth();
  server_->RequestClientAuth(true);

  auto cr =
      MakeTlsFilter<TlsExtensionCapture>(server_, ssl_signature_algorithms_xtn);
  cr->SetHandshakeTypes({kTlsHandshakeCertificateRequest});
  cr->EnableDecryption();
  Connect();
  EXPECT_TRUE(cr->captured());

  checkGreasePresence(1, 0, cr->extension());
}

TEST_P(GreasePresenceAbsenceTestTlsStream13,
       GreaseCertificateRequestExtension) {
  SetupGrease();
  client_->SetupClientAuth();
  server_->RequestClientAuth(true);

  auto cr = MakeTlsFilter<TlsHandshakeRecorder>(
      server_, kTlsHandshakeCertificateRequest);
  cr->EnableDecryption();
  Connect();
  EXPECT_TRUE(cr->buffer().len() > 0);

  TlsParser extParser(cr->buffer());
  EXPECT_TRUE(extParser.SkipVariable(1));  // Context
  EXPECT_TRUE(extParser.Skip(2));          // Extension Lengths

  uint32_t extType;
  DataBuffer extBuf;
  bool found = false;
  // Scan for a single, empty extension
  while (extParser.remaining()) {
    extParser.Read(&extType, 2);
    extParser.ReadVariable(&extBuf, 2);
    for (uint16_t greaseVal : kTlsGreaseValues) {
      if (greaseVal == extType) {
        EXPECT_TRUE(!found);
        EXPECT_EQ(extBuf.len(), size_t(0));
        found = true;
      }
    }
  }

  EXPECT_EQ(expectGrease(), found);
}

TEST_P(GreasePresenceAbsenceTestTlsStream13, GreaseNewSessionTicketExtension) {
  SetupGrease();

  auto nst = MakeTlsFilter<TlsHandshakeRecorder>(server_,
                                                 kTlsHandshakeNewSessionTicket);
  nst->EnableDecryption();
  Connect();
  EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0));
  EXPECT_TRUE(nst->buffer().len() > 0);

  TlsParser extParser(nst->buffer());
  EXPECT_TRUE(extParser.Skip(4));          // lifetime
  EXPECT_TRUE(extParser.Skip(4));          // age
  EXPECT_TRUE(extParser.SkipVariable(1));  // Nonce
  EXPECT_TRUE(extParser.SkipVariable(2));  // Ticket
  EXPECT_TRUE(extParser.Skip(2));          // Extension Length

  uint32_t extType;
  DataBuffer extBuf;
  bool found = false;
  // Scan for a single, empty extension
  while (extParser.remaining()) {
    extParser.Read(&extType, 2);
    extParser.ReadVariable(&extBuf, 2);
    for (uint16_t greaseVal : kTlsGreaseValues) {
      if (greaseVal == extType) {
        EXPECT_TRUE(!found);
        EXPECT_EQ(extBuf.len(), size_t(0));
        found = true;
      }
    }
  }

  EXPECT_EQ(expectGrease(), found);
}

// Generic Client GREASE test
TEST_P(TlsConnectGeneric, ClientGrease) {
  EnsureTlsSetup();
  ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  Connect();
}

// Generic Server GREASE test
TEST_P(TlsConnectGeneric, ServerGrease) {
  EnsureTlsSetup();
  ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  Connect();
}

// Generic GREASE test
TEST_P(TlsConnectGeneric, Grease) {
  EnsureTlsSetup();
  ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  Connect();
}

// Check that GREASE values can be correctly reconstructed after HRR.
TEST_P(TlsConnectGeneric, GreaseHRR) {
  EnsureTlsSetup();
  const std::vector<SSLNamedGroup> client_groups = {
      ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1};
  const std::vector<SSLNamedGroup> server_groups = {
      ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ec_curve25519};
  client_->ConfigNamedGroups(client_groups);
  server_->ConfigNamedGroups(server_groups);
  ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  Connect();
}

// Check that GREASE additions interact correctly with psk-only handshake.
TEST_F(TlsConnectStreamTls13, GreasePsk) {
  EnsureTlsSetup();
  ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);

  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_);

  Connect();
  SendReceive();
  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none);
}

// Test that ECH and GREASE work together successfully
TEST_F(TlsConnectStreamTls13, GreaseAndECH) {
  EnsureTlsSetup();
  SetupEch(client_, server_);
  ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  Connect();
}

// Test that TLS12 Server handles Client GREASE correctly
TEST_F(TlsConnectTest, GreaseTLS12Server) {
  EnsureTlsSetup();
  ASSERT_EQ(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_2);
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();
}

// Test that TLS12 Client handles Server GREASE correctly
TEST_F(TlsConnectTest, GreaseTLS12Client) {
  EnsureTlsSetup();
  ASSERT_EQ(SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE),
            SECSuccess);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_2);
  Connect();
}

class GreaseOnlyTestStreamTls13 : public TlsConnectStreamTls13 {
 public:
  GreaseOnlyTestStreamTls13() : TlsConnectStreamTls13() {}

  void ConnectWithCustomChExpectFail(const std::string& ch,
                                     uint8_t server_alert, uint32_t server_code,
                                     uint32_t client_code) {
    std::vector<uint8_t> ch_vec = hex_string_to_bytes(ch);
    DataBuffer ch_buf;
    EnsureTlsSetup();

    TlsAgentTestBase::MakeRecord(variant_, ssl_ct_handshake,
                                 SSL_LIBRARY_VERSION_TLS_1_3, ch_vec.data(),
                                 ch_vec.size(), &ch_buf, 0);
    StartConnect();
    client_->SendDirect(ch_buf);
    ExpectAlert(server_, server_alert);
    server_->Handshake();
    server_->CheckErrorCode(server_code);
    client_->ExpectReceiveAlert(server_alert, kTlsAlertFatal);
    client_->Handshake();
    client_->CheckErrorCode(client_code);
  }
};

// Client: Offer only GREASE CipherSuite value
TEST_F(GreaseOnlyTestStreamTls13, GreaseOnlyClientCipherSuite) {
  // 0xdada
  std::string ch =
      "010000b003038afacda2963358e98f464f3ff0680ed3a9d382a8c3eac5e5604f5721add9"
      "855c000002dada010000850000000b0009000006736572766572ff01000100000a001400"
      "12001d00170018001901000101010201030104003300260024001d0020683668992de470"
      "38660ee37bafc7392b05b8a94402ea1f3463ad3cfd7a694a46002b0003020304000d0018"
      "001604030503060302030804080508060401050106010201002d00020101001c0002400"
      "1";

  ConnectWithCustomChExpectFail(ch, kTlsAlertHandshakeFailure,
                                SSL_ERROR_NO_CYPHER_OVERLAP,
                                SSL_ERROR_NO_CYPHER_OVERLAP);
}

// Client: Offer only GREASE SupportedGroups value
TEST_F(GreaseOnlyTestStreamTls13, GreaseOnlyClientSupportedGroup) {
  // 0x3a3a
  std::string ch =
      "010000a40303484a4e14f547404da6115d7f73bbb0f1c9d65e66ac073dee6c4a62f72de9"
      "a36f000006130113031302010000750000000b0009000006736572766572ff0100010000"
      "0a000400023a3a003300260024001d0020e75cb8e217c95176954e8b5fb95843882462ce"
      "2cd3fcfe67cf31463a05ea3d57002b0003020304000d0018001604030503060302030804"
      "080508060401050106010201002d00020101001c00024001";

  ConnectWithCustomChExpectFail(ch, kTlsAlertHandshakeFailure,
                                SSL_ERROR_NO_CYPHER_OVERLAP,
                                SSL_ERROR_NO_CYPHER_OVERLAP);
}

// Client: Offer only GREASE SigAlgs value
TEST_F(GreaseOnlyTestStreamTls13, GreaseOnlyClientSignatureAlgorithm) {
  // 0x8a8a
  std::string ch =
      "010000a00303dfd8e2438a8d1b9f48d921dfc08959108807bd1105238bb3da2a2a8e3db0"
      "6990000006130113031302010000710000000b0009000006736572766572ff0100010000"
      "0a00140012001d00170018001901000101010201030104003300260024001d002074bb2c"
      "94996d3ffc7ae5792f0c3c58676358a85ea304cd029fa3d6551013b333002b0003020304"
      "000d000400028a8a002d00020101001c00024001";

  ConnectWithCustomChExpectFail(ch, kTlsAlertHandshakeFailure,
                                SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM,
                                SSL_ERROR_NO_CYPHER_OVERLAP);
}

// Client: Offer only GREASE SupportedVersions value
TEST_F(GreaseOnlyTestStreamTls13, GreaseOnlyClientSupportedVersion) {
  // 0xeaea
  std::string ch =
      "010000b203037e3618abae0dd0b3f06a504c47354551d1d5be36e9c3e1eac9c139c246b1"
      "66da000006130113031302010000830000000b0009000006736572766572ff0100010000"
      "0a00140012001d00170018001901000101010201030104003300260024001d00206b1816"
      "577ff2e69d4d2661419150eaefa0328ffd396425cf1733ec06536b4e55002b000100000d"
      "0018001604030503060302030804080508060401050106010201002d00020101001c0002"
      "4001";

  ConnectWithCustomChExpectFail(ch, kTlsAlertIllegalParameter,
                                SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
                                SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

class GreaseTestStreamTls12
    : public TlsConnectStreamTls12,
      public ::testing::WithParamInterface<uint16_t /* GREASE */> {
 public:
  GreaseTestStreamTls12() : TlsConnectStreamTls12(), grease_(GetParam()){};

  void ConnectExpectSigAlgFail() {
    client_->ExpectSendAlert(kTlsAlertIllegalParameter);
    server_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
    ConnectExpectFail();
    client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
    server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  }

 protected:
  uint16_t grease_;
};

class TlsCertificateRequestSigAlgSetterFilter : public TlsHandshakeFilter {
 public:
  TlsCertificateRequestSigAlgSetterFilter(const std::shared_ptr<TlsAgent>& a,
                                          uint16_t sigAlg)
      : TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}),
        sigAlg_(sigAlg) {}
  virtual PacketFilter::Action FilterHandshake(
      const TlsHandshakeFilter::HandshakeHeader& header,
      const DataBuffer& input, DataBuffer* output) {
    TlsParser parser(input);
    DataBuffer cert_types;
    if (!parser.ReadVariable(&cert_types, 1)) {
      ADD_FAILURE();
      return KEEP;
    }

    if (!parser.SkipVariable(2)) {
      ADD_FAILURE();
      return KEEP;
    }

    DataBuffer cas;
    if (!parser.ReadVariable(&cas, 2)) {
      ADD_FAILURE();
      return KEEP;
    }

    size_t idx = 0;

    // Write certificate types.
    idx = output->Write(idx, cert_types.len(), 1);
    idx = output->Write(idx, cert_types);

    // Write signature algorithm.
    idx = output->Write(idx, sizeof(sigAlg_), 2);
    idx = output->Write(idx, sigAlg_, 2);

    // Write certificate authorities.
    idx = output->Write(idx, cas.len(), 2);
    idx = output->Write(idx, cas);

    return CHANGE;
  }

 private:
  uint16_t sigAlg_;
};

// Server: Offer only GREASE CertificateRequest SigAlg value
TEST_P(GreaseTestStreamTls12, GreaseOnlyServerTLS12CertificateRequestSigAlg) {
  EnsureTlsSetup();
  client_->SetupClientAuth();
  server_->RequestClientAuth(true);
  MakeTlsFilter<TlsCertificateRequestSigAlgSetterFilter>(server_, grease_);

  client_->ExpectSendAlert(kTlsAlertHandshakeFailure);
  server_->ExpectReceiveAlert(kTlsAlertHandshakeFailure);
  ConnectExpectFail();
  server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
  client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
}

// Illegally GREASE ServerKeyExchange ECC SignatureAlgorithm
TEST_P(GreaseTestStreamTls12, GreasedTLS12ServerKexEccSigAlg) {
  MakeTlsFilter<ECCServerKEXSigAlgReplacer>(server_, grease_);
  EnableSomeEcdhCiphers();

  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

// Illegally GREASE ServerKeyExchange DHE SignatureAlgorithm
TEST_P(GreaseTestStreamTls12, GreasedTLS12ServerKexDheSigAlg) {
  MakeTlsFilter<DHEServerKEXSigAlgReplacer>(server_, grease_);
  EnableOnlyDheCiphers();

  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

// Illegally GREASE ServerKeyExchange ECDHE NamedCurve
TEST_P(GreaseTestStreamTls12, GreasedTLS12ServerKexEcdheNamedCurve) {
  MakeTlsFilter<ECCServerKEXNamedCurveReplacer>(server_, grease_);
  EnableSomeEcdhCiphers();

  client_->ExpectSendAlert(kTlsAlertHandshakeFailure);
  server_->ExpectReceiveAlert(kTlsAlertHandshakeFailure);
  ConnectExpectFail();
  server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
  client_->CheckErrorCode(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
}

// Illegally GREASE TLS12 Client CertificateVerify SignatureAlgorithm
TEST_P(GreaseTestStreamTls12, GreasedTLS12ClientCertificateVerifySigAlg) {
  client_->SetupClientAuth();
  server_->RequestClientAuth(true);
  MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_, grease_);

  server_->ExpectSendAlert(kTlsAlertIllegalParameter);
  client_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
}

class GreaseTestStreamTls13
    : public TlsConnectStreamTls13,
      public ::testing::WithParamInterface<uint16_t /* GREASE */> {
 public:
  GreaseTestStreamTls13() : grease_(GetParam()){};

 protected:
  uint16_t grease_;
};

// Illegally GREASE TLS13 Client CertificateVerify SignatureAlgorithm
TEST_P(GreaseTestStreamTls13, GreasedTLS13ClientCertificateVerifySigAlg) {
  client_->SetupClientAuth();
  server_->RequestClientAuth(true);
  auto filter =
      MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_, grease_);
  filter->EnableDecryption();

  server_->ExpectSendAlert(kTlsAlertIllegalParameter);
  client_->ExpectReceiveAlert(kTlsAlertIllegalParameter);

  // Manually trigger handshake to avoid race conditions
  StartConnect();
  client_->Handshake();
  server_->Handshake();
  client_->Handshake();
  server_->Handshake();
  client_->Handshake();

  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

// Illegally GREASE TLS13 Server CertificateVerify SignatureAlgorithm
TEST_P(GreaseTestStreamTls13, GreasedTLS13ServerCertificateVerifySigAlg) {
  EnsureTlsSetup();
  auto filter =
      MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, grease_);
  filter->EnableDecryption();

  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
}

// Illegally GREASE HelloRetryRequest version value
TEST_P(GreaseTestStreamTls13, GreasedHelloRetryRequestVersion) {
  EnsureTlsSetup();
  // Trigger HelloRetryRequest
  MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_key_share_xtn);
  auto filter = MakeTlsFilter<TlsMessageVersionSetter>(
      server_, kTlsHandshakeHelloRetryRequest, grease_);
  filter->EnableDecryption();

  client_->ExpectSendAlert(kTlsAlertIllegalParameter);
  server_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

class GreaseTestStreamTls123
    : public TlsConnectTestBase,
      public ::testing::WithParamInterface<
          std::tuple<uint16_t /* version */, uint16_t /* GREASE */>> {
 public:
  GreaseTestStreamTls123()
      : TlsConnectTestBase(ssl_variant_stream, std::get<0>(GetParam())),
        grease_(std::get<1>(GetParam())){};

  void ConnectExpectIllegalGreaseFail() {
    client_->ExpectSendAlert(kTlsAlertIllegalParameter);
    if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
      // Server expects handshake but receives encrypted alert.
      server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    } else {
      server_->ExpectReceiveAlert(kTlsAlertIllegalParameter);
    }
    ConnectExpectFail();
  }

 protected:
  uint16_t grease_;
};

// Illegally GREASE TLS12 and TLS13 ServerHello version value
TEST_P(GreaseTestStreamTls123, GreasedServerHelloVersion) {
  EnsureTlsSetup();
  auto filter = MakeTlsFilter<TlsMessageVersionSetter>(
      server_, kTlsHandshakeServerHello, grease_);
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    filter->EnableDecryption();
  }
  ConnectExpectIllegalGreaseFail();
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
}

// Illegally GREASE TLS12 and TLS13 selected CipherSuite value
TEST_P(GreaseTestStreamTls123, GreasedServerHelloCipherSuite) {
  EnsureTlsSetup();
  auto filter = MakeTlsFilter<SelectedCipherSuiteReplacer>(server_, grease_);
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    filter->EnableDecryption();
  }
  ConnectExpectIllegalGreaseFail();
  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
}

class GreaseExtensionTestStreamTls13
    : public TlsConnectStreamTls13,
      public ::testing::WithParamInterface<
          std::tuple<uint8_t /* message */, uint16_t /* GREASE */>> {
 public:
  GreaseExtensionTestStreamTls13()
      : TlsConnectStreamTls13(),
        message_(std::get<0>(GetParam())),
        grease_(std::get<1>(GetParam())){};

 protected:
  uint8_t message_;
  uint16_t grease_;
};

// Illegally GREASE TLS13 Server EncryptedExtensions and Certificate Extensions
// NSS currently allows offering unkown extensions in HelloRetryRequests!
TEST_P(GreaseExtensionTestStreamTls13, GreasedServerExtensions) {
  EnsureTlsSetup();
  DataBuffer empty = DataBuffer(1);
  auto filter =
      MakeTlsFilter<TlsExtensionAppender>(server_, message_, grease_, empty);
  filter->EnableDecryption();

  server_->ExpectReceiveAlert(kTlsAlertUnsupportedExtension);
  client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT);
}

// Illegally GREASE TLS12 and TLS13 ServerHello Extensions
TEST_P(GreaseTestStreamTls123, GreasedServerHelloExtensions) {
  EnsureTlsSetup();
  DataBuffer empty = DataBuffer(1);
  auto filter = MakeTlsFilter<TlsExtensionAppender>(
      server_, kTlsHandshakeServerHello, grease_, empty);

  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    filter->EnableDecryption();
    server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
  } else {
    server_->ExpectReceiveAlert(kTlsAlertUnsupportedExtension);
  }
  client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
}

// Illegally GREASE TLS13 Client Certificate Extensions
// Server ignores injected client extensions and fails on CertificateVerify
TEST_P(GreaseTestStreamTls13, GreasedClientCertificateExtensions) {
  client_->SetupClientAuth();
  server_->RequestClientAuth(true);
  DataBuffer empty = DataBuffer(1);
  auto filter = MakeTlsFilter<TlsExtensionAppender>(
      client_, kTlsHandshakeCertificate, grease_, empty);
  filter->EnableDecryption();

  server_->ExpectSendAlert(kTlsAlertDecryptError);
  client_->ExpectReceiveAlert(kTlsAlertDecryptError);

  // Manually trigger handshake to avoid race conditions
  StartConnect();
  client_->Handshake();
  server_->Handshake();
  client_->Handshake();
  server_->Handshake();
  client_->Handshake();

  server_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE);
  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
}

TEST_F(TlsConnectStreamTls13, GreaseClientHelloExtensionPermutation) {
  EnsureTlsSetup();
  ASSERT_TRUE(SSL_OptionSet(client_->ssl_fd(),
                            SSL_ENABLE_CH_EXTENSION_PERMUTATION,
                            PR_TRUE) == SECSuccess);
  ASSERT_TRUE(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_GREASE, PR_TRUE) ==
              SECSuccess);
  Connect();
}

INSTANTIATE_TEST_SUITE_P(GreaseTestTls12, GreaseTestStreamTls12,
                         ::testing::ValuesIn(kTlsGreaseValues));

INSTANTIATE_TEST_SUITE_P(GreaseTestTls13, GreaseTestStreamTls13,
                         ::testing::ValuesIn(kTlsGreaseValues));

INSTANTIATE_TEST_SUITE_P(
    GreaseTestTls123, GreaseTestStreamTls123,
    ::testing::Combine(TlsConnectTestBase::kTlsV12Plus,
                       ::testing::ValuesIn(kTlsGreaseValues)));

INSTANTIATE_TEST_SUITE_P(
    GreaseExtensionTest, GreaseExtensionTestStreamTls13,
    testing::Combine(testing::ValuesIn(kTlsGreaseExtensionMessages),
                     testing::ValuesIn(kTlsGreaseValues)));

}  // namespace nss_test

Messung V0.5
C=92 H=86 G=88

¤ Dauer der Verarbeitung: 0.2 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.