/* -*- 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 "pk11pub.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

extern "C" {
// This is not something that should make you happy.
#include "libssl_internals.h"
}

#include "gtest_utils.h"
#include "tls_connect.h"
#include "tls_filter.h"

namespace nss_test {

// Replaces the client hello with an SSLv2 version once.
class SSLv2ClientHelloFilter : public PacketFilter {
 public:
  SSLv2ClientHelloFilter(const std::shared_ptr<TlsAgent>& client,
                         uint16_t version)
      : replaced_(false),
        client_(client),
        version_(version),
        pad_len_(0),
        reported_pad_len_(0),
        client_random_len_(16),
        ciphers_(0),
        send_escape_(false) {}

  void SetVersion(uint16_t version) { version_ = version; }

  void SetCipherSuites(const std::vector<uint16_t>& ciphers) {
    ciphers_ = ciphers;
  }

  // Set a padding length and announce it correctly.
  void SetPadding(uint8_t pad_len) { SetPadding(pad_len, pad_len); }

  // Set a padding length and allow to lie about its length.
  void SetPadding(uint8_t pad_len, uint8_t reported_pad_len) {
    pad_len_ = pad_len;
    reported_pad_len_ = reported_pad_len;
  }

  void SetClientRandomLength(uint16_t client_random_len) {
    client_random_len_ = client_random_len;
  }

  void SetSendEscape(bool send_escape) { send_escape_ = send_escape; }

 protected:
  virtual PacketFilter::Action Filter(const DataBuffer& input,
                                      DataBuffer* output) {
    if (replaced_) {
      return KEEP;
    }

    // Replace only the very first packet.
    replaced_ = true;

    // The SSLv2 client hello size.
    size_t packet_len = SSL_HL_CLIENT_HELLO_HBYTES + (ciphers_.size() * 3) +
                        client_random_len_ + pad_len_;

    size_t idx = 0;
    *output = input;
    output->Allocate(packet_len);
    output->Truncate(packet_len);

    // Write record length.
    if (pad_len_ > 0) {
      size_t masked_len = 0x3fff & packet_len;
      if (send_escape_) {
        masked_len |= 0x4000;
      }

      idx = output->Write(idx, masked_len, 2);
      idx = output->Write(idx, reported_pad_len_, 1);
    } else {
      PR_ASSERT(!send_escape_);
      idx = output->Write(idx, 0x8000 | packet_len, 2);
    }

    // Remember header length.
    size_t hdr_len = idx;

    // Write client hello.
    idx = output->Write(idx, SSL_MT_CLIENT_HELLO, 1);
    idx = output->Write(idx, version_, 2);

    // Cipher list length.
    idx = output->Write(idx, (ciphers_.size() * 3), 2);

    // Session ID length.
    idx = output->Write(idx, static_cast<uint32_t>(0), 2);

    // ClientRandom length.
    idx = output->Write(idx, client_random_len_, 2);

    // Cipher suites.
    for (auto cipher : ciphers_) {
      idx = output->Write(idx, static_cast<uint32_t>(cipher), 3);
    }

    // Challenge.
    std::vector<uint8_t> challenge(client_random_len_);
    PK11_GenerateRandom(challenge.data(), challenge.size());
    idx = output->Write(idx, challenge.data(), challenge.size());

    // Add padding if any.
    if (pad_len_ > 0) {
      std::vector<uint8_t> pad(pad_len_);
      idx = output->Write(idx, pad.data(), pad.size());
    }

    // Update the client random so that the handshake succeeds.
    SECStatus rv = SSLInt_UpdateSSLv2ClientRandom(
        client_.lock()->ssl_fd(), challenge.data(), challenge.size(),
        output->data() + hdr_len, output->len() - hdr_len);
    EXPECT_EQ(SECSuccess, rv);

    return CHANGE;
  }

 private:
  bool replaced_;
  std::weak_ptr<TlsAgent> client_;
  uint16_t version_;
  uint8_t pad_len_;
  uint8_t reported_pad_len_;
  uint16_t client_random_len_;
  std::vector<uint16_t> ciphers_;
  bool send_escape_;
};

class SSLv2ClientHelloTestF : public TlsConnectTestBase {
 public:
  SSLv2ClientHelloTestF()
      : TlsConnectTestBase(ssl_variant_stream, 0), filter_(nullptr) {}

  SSLv2ClientHelloTestF(SSLProtocolVariant variant, uint16_t version)
      : TlsConnectTestBase(variant, version), filter_(nullptr) {}

  void SetUp() override {
    TlsConnectTestBase::SetUp();
    filter_ = MakeTlsFilter<SSLv2ClientHelloFilter>(client_, version_);
    server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE);
  }

  void SetExpectedVersion(uint16_t version) {
    TlsConnectTestBase::SetExpectedVersion(version);
    filter_->SetVersion(version);
  }

  void SetAvailableCipherSuite(uint16_t cipher) {
    filter_->SetCipherSuites(std::vector<uint16_t>(1, cipher));
  }

  void SetAvailableCipherSuites(const std::vector<uint16_t>& ciphers) {
    filter_->SetCipherSuites(ciphers);
  }

  void SetPadding(uint8_t pad_len) { filter_->SetPadding(pad_len); }

  void SetPadding(uint8_t pad_len, uint8_t reported_pad_len) {
    filter_->SetPadding(pad_len, reported_pad_len);
  }

  void SetClientRandomLength(uint16_t client_random_len) {
    filter_->SetClientRandomLength(client_random_len);
  }

  void SetSendEscape(bool send_escape) { filter_->SetSendEscape(send_escape); }

 private:
  std::shared_ptr<SSLv2ClientHelloFilter> filter_;
};

// Parameterized version of SSLv2ClientHelloTestF we can
// use with TEST_P to test multiple TLS versions easily.
class SSLv2ClientHelloTest : public SSLv2ClientHelloTestF,
                             public ::testing::WithParamInterface<uint16_t> {
 public:
  SSLv2ClientHelloTest()
      : SSLv2ClientHelloTestF(ssl_variant_stream, GetParam()) {}
};

// Test negotiating TLS 1.0 - 1.2.
TEST_P(SSLv2ClientHelloTest, Connect) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
  Connect();
}

TEST_P(SSLv2ClientHelloTest, ConnectDisabled) {
  server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_FALSE);
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  StartConnect();
  client_->Handshake();  // Send the modified ClientHello.
  server_->Handshake();  // Read some.
  // The problem here is that the v2 ClientHello puts the version where the v3
  // ClientHello puts a version number.  So the version number (0x0301+) appears
  // to be a length and server blocks waiting for that much data.
  EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());

  // This is usually what happens with v2-compatible: the server hangs.
  // But to be certain, feed in more data to see if an error comes out.
  uint8_t zeros[SSL_LIBRARY_VERSION_TLS_1_2] = {0};
  client_->SendDirect(DataBuffer(zeros, sizeof(zeros)));
  ExpectAlert(server_, kTlsAlertIllegalParameter);
  server_->Handshake();
  client_->Handshake();
}

// Sending a v2 ClientHello after a no-op v3 record must fail.
TEST_P(SSLv2ClientHelloTest, ConnectAfterEmptyV3Record) {
  DataBuffer buffer;

  size_t idx = 0;
  idx = buffer.Write(idx, 0x16, 1);    // handshake
  idx = buffer.Write(idx, 0x0301, 2);  // record_version
  (void)buffer.Write(idx, 0U, 2);      // length=0

  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
  EnsureTlsSetup();
  client_->SendDirect(buffer);

  // Need padding so the connection doesn't just time out. With a v2
  // ClientHello parsed as a v3 record we will use the record version
  // as the record length.
  SetPadding(255);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  EXPECT_EQ(SSL_ERROR_BAD_CLIENT, server_->error_code());
}

// Test negotiating TLS 1.3.
TEST_F(SSLv2ClientHelloTestF, Connect13) {
  EnsureTlsSetup();
  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);

  std::vector<uint16_t> cipher_suites = {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256};
  SetAvailableCipherSuites(cipher_suites);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, server_->error_code());
}

// Test negotiating an EC suite.
TEST_P(SSLv2ClientHelloTest, NegotiateECSuite) {
  SetAvailableCipherSuite(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
  Connect();
}

// Test negotiating TLS 1.0 - 1.2 with a padded client hello.
TEST_P(SSLv2ClientHelloTest, AddPadding) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
  SetPadding(255);
  Connect();
}

// Test that sending a security escape fails the handshake.
TEST_P(SSLv2ClientHelloTest, SendSecurityEscape) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  // Send a security escape.
  SetSendEscape(true);

  // Set a big padding so that the server fails instead of timing out.
  SetPadding(255);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
}

// Invalid SSLv2 client hello padding must fail the handshake.
TEST_P(SSLv2ClientHelloTest, AddErroneousPadding) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  // Append 5 bytes of padding but say it's only 4.
  SetPadding(5, 4);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, server_->error_code());
}

// Invalid SSLv2 client hello padding must fail the handshake.
TEST_P(SSLv2ClientHelloTest, AddErroneousPadding2) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  // Append 5 bytes of padding but say it's 6.
  SetPadding(5, 6);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, server_->error_code());
}

// Wrong amount of bytes for the ClientRandom must fail the handshake.
TEST_P(SSLv2ClientHelloTest, SmallClientRandom) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  // Send a ClientRandom that's too small.
  SetClientRandomLength(15);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, server_->error_code());
}

// Test sending the maximum accepted number of ClientRandom bytes.
TEST_P(SSLv2ClientHelloTest, MaxClientRandom) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
  SetClientRandomLength(32);
  Connect();
}

// Wrong amount of bytes for the ClientRandom must fail the handshake.
TEST_P(SSLv2ClientHelloTest, BigClientRandom) {
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  // Send a ClientRandom that's too big.
  SetClientRandomLength(33);

  ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, server_->error_code());
}

// Connection must fail if we require safe renegotiation but the client doesn't
// include TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the list of cipher suites.
TEST_P(SSLv2ClientHelloTest, RequireSafeRenegotiation) {
  server_->SetOption(SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
  ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
  EXPECT_EQ(SSL_ERROR_UNSAFE_NEGOTIATION, server_->error_code());
}

// Connection must succeed when requiring safe renegotiation and the client
// includes TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the list of cipher suites.
TEST_P(SSLv2ClientHelloTest, RequireSafeRenegotiationWithSCSV) {
  server_->SetOption(SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
  std::vector<uint16_t> cipher_suites = {TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                                         TLS_EMPTY_RENEGOTIATION_INFO_SCSV};
  SetAvailableCipherSuites(cipher_suites);
  Connect();
}

TEST_P(SSLv2ClientHelloTest, CheckServerRandom) {
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
  SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);

  static const size_t random_len = 32;
  uint8_t srandom1[random_len];
  uint8_t z[random_len] = {0};

  auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
  Connect();
  ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
  memcpy(srandom1, sh->buffer().data() + 2, random_len);
  EXPECT_NE(0, memcmp(srandom1, z, random_len));

  Reset();
  sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
  Connect();
  ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
  const uint8_t* srandom2 = sh->buffer().data() + 2;

  EXPECT_NE(0, memcmp(srandom2, z, random_len));
  EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
}

// Connect to the server with TLS 1.1, signalling that this is a fallback from
// a higher version. As the server doesn't support anything higher than TLS 1.1
// it must accept the connection.
TEST_F(SSLv2ClientHelloTestF, FallbackSCSV) {
  EnsureTlsSetup();
  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_1);

  std::vector<uint16_t> cipher_suites = {TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                                         TLS_FALLBACK_SCSV};
  SetAvailableCipherSuites(cipher_suites);
  Connect();
}

// Connect to the server with TLS 1.1, signalling that this is a fallback from
// a higher version. As the server supports TLS 1.2 though it must reject the
// connection due to a possible downgrade attack.
TEST_F(SSLv2ClientHelloTestF, InappropriateFallbackSCSV) {
  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                           SSL_LIBRARY_VERSION_TLS_1_1);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                           SSL_LIBRARY_VERSION_TLS_1_2);

  std::vector<uint16_t> cipher_suites = {TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                                         TLS_FALLBACK_SCSV};
  SetAvailableCipherSuites(cipher_suites);

  ConnectExpectAlert(server_, kTlsAlertInappropriateFallback);
  EXPECT_EQ(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, server_->error_code());
}

INSTANTIATE_TEST_CASE_P(VersionsStream10Pre13, SSLv2ClientHelloTest,
                        TlsConnectTestBase::kTlsV10);
INSTANTIATE_TEST_CASE_P(VersionsStreamPre13, SSLv2ClientHelloTest,
                        TlsConnectTestBase::kTlsV11V12);

}  // namespace nss_test
