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

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

namespace nss_test {

// This class tracks the maximum size of record that was sent, both cleartext
// and plain.  It only tracks records that have an outer type of
// application_data.  In TLS 1.3, this includes handshake messages.
class TlsRecordMaximum : public TlsRecordFilter {
 public:
  TlsRecordMaximum(const std::shared_ptr<TlsAgent>& a)
      : TlsRecordFilter(a), max_ciphertext_(0), max_plaintext_(0) {}

  size_t max_ciphertext() const { return max_ciphertext_; }
  size_t max_plaintext() const { return max_plaintext_; }

 protected:
  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                    const DataBuffer& record, size_t* offset,
                                    DataBuffer* output) override {
    std::cerr << "max: " << record << std::endl;
    // Ignore unprotected packets.
    if (header.content_type() != ssl_ct_application_data) {
      return KEEP;
    }

    max_ciphertext_ = (std::max)(max_ciphertext_, record.len());
    return TlsRecordFilter::FilterRecord(header, record, offset, output);
  }

  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                    const DataBuffer& data,
                                    DataBuffer* changed) override {
    max_plaintext_ = (std::max)(max_plaintext_, data.len());
    return KEEP;
  }

 private:
  size_t max_ciphertext_;
  size_t max_plaintext_;
};

void CheckRecordSizes(const std::shared_ptr<TlsAgent>& agent,
                      const std::shared_ptr<TlsRecordMaximum>& record_max,
                      size_t config) {
  uint16_t cipher_suite;
  ASSERT_TRUE(agent->cipher_suite(&cipher_suite));

  size_t expansion;
  size_t iv;
  switch (cipher_suite) {
    case TLS_AES_128_GCM_SHA256:
    case TLS_AES_256_GCM_SHA384:
    case TLS_CHACHA20_POLY1305_SHA256:
      expansion = 16;
      iv = 0;
      break;

    case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
      expansion = 16;
      iv = 8;
      break;

    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
      // Expansion is 20 for the MAC.  Maximum block padding is 16.  Maximum
      // padding is added when the input plus the MAC is an exact multiple of
      // the block size.
      expansion = 20 + 16 - ((config + 20) % 16);
      iv = 16;
      break;

    default:
      ADD_FAILURE() << "No expansion set for ciphersuite "
                    << agent->cipher_suite_name();
      return;
  }

  switch (agent->version()) {
    case SSL_LIBRARY_VERSION_TLS_1_3:
      EXPECT_EQ(0U, iv) << "No IV for TLS 1.3";
      // We only have decryption in TLS 1.3.
      EXPECT_EQ(config - 1, record_max->max_plaintext())
          << "bad plaintext length for " << agent->role_str();
      break;

    case SSL_LIBRARY_VERSION_TLS_1_2:
    case SSL_LIBRARY_VERSION_TLS_1_1:
      expansion += iv;
      break;

    case SSL_LIBRARY_VERSION_TLS_1_0:
      break;

    default:
      ADD_FAILURE() << "Unexpected version " << agent->version();
      return;
  }

  EXPECT_EQ(config + expansion, record_max->max_ciphertext())
      << "bad ciphertext length for " << agent->role_str();
}

TEST_P(TlsConnectGeneric, RecordSizeMaximum) {
  uint16_t max_record_size =
      (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) ? 16385 : 16384;
  size_t send_size = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3)
                         ? max_record_size
                         : max_record_size + 1;

  EnsureTlsSetup();
  auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
  client_max->EnableDecryption();
  auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
  server_max->EnableDecryption();

  Connect();
  client_->SendData(send_size, send_size);
  server_->SendData(send_size, send_size);
  server_->ReadBytes(send_size);
  client_->ReadBytes(send_size);

  CheckRecordSizes(client_, client_max, max_record_size);
  CheckRecordSizes(server_, server_max, max_record_size);
}

TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) {
  EnsureTlsSetup();
  auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
  server_max->EnableDecryption();

  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
  Connect();
  SendReceive(127);  // Big enough for one record, allowing for 1+N splitting.

  CheckRecordSizes(server_, server_max, 64);
}

TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) {
  EnsureTlsSetup();
  auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
  client_max->EnableDecryption();

  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
  Connect();
  SendReceive(127);

  CheckRecordSizes(client_, client_max, 64);
}

TEST_P(TlsConnectGeneric, RecordSizeAsymmetric) {
  EnsureTlsSetup();
  auto client_max = MakeTlsFilter<TlsRecordMaximum>(client_);
  client_max->EnableDecryption();
  auto server_max = MakeTlsFilter<TlsRecordMaximum>(server_);
  server_max->EnableDecryption();

  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 100);
  Connect();
  SendReceive(127);

  CheckRecordSizes(client_, client_max, 100);
  CheckRecordSizes(server_, server_max, 64);
}

// This just modifies the encrypted payload so to include a few extra zeros.
class TlsRecordExpander : public TlsRecordFilter {
 public:
  TlsRecordExpander(const std::shared_ptr<TlsAgent>& a, size_t expansion)
      : TlsRecordFilter(a), expansion_(expansion) {}

 protected:
  virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                            const DataBuffer& data,
                                            DataBuffer* changed) {
    if (header.content_type() != ssl_ct_application_data) {
      return KEEP;
    }
    changed->Allocate(data.len() + expansion_);
    changed->Write(0, data.data(), data.len());
    return CHANGE;
  }

 private:
  size_t expansion_;
};

// Tweak the plaintext of server records so that they exceed the client's limit.
TEST_P(TlsConnectTls13, RecordSizePlaintextExceed) {
  EnsureTlsSetup();
  auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 1);
  server_expand->EnableDecryption();

  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
  Connect();

  server_->SendData(100);

  client_->ExpectReadWriteError();
  ExpectAlert(client_, kTlsAlertRecordOverflow);
  client_->ReadBytes(100);
  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());

  // Consume the alert at the server.
  server_->Handshake();
  server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
}

// Tweak the ciphertext of server records so that they greatly exceed the limit.
// This requires a much larger expansion than for plaintext to trigger the
// guard, which runs before decryption (current allowance is 304 octets).
TEST_P(TlsConnectTls13, RecordSizeCiphertextExceed) {
  EnsureTlsSetup();

  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
  Connect();

  auto server_expand = MakeTlsFilter<TlsRecordExpander>(server_, 320);
  server_->SendData(100);

  client_->ExpectReadWriteError();
  ExpectAlert(client_, kTlsAlertRecordOverflow);
  client_->ReadBytes(100);
  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());

  // Consume the alert at the server.
  server_->Handshake();
  server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
}

// This indiscriminately adds padding to application data records.
class TlsRecordPadder : public TlsRecordFilter {
 public:
  TlsRecordPadder(const std::shared_ptr<TlsAgent>& a, size_t padding)
      : TlsRecordFilter(a), padding_(padding) {}

 protected:
  PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                    const DataBuffer& record, size_t* offset,
                                    DataBuffer* output) override {
    if (header.content_type() != ssl_ct_application_data) {
      return KEEP;
    }

    uint8_t inner_content_type;
    DataBuffer plaintext;
    if (!Unprotect(header, record, &inner_content_type, &plaintext)) {
      return KEEP;
    }

    if (inner_content_type != ssl_ct_application_data) {
      return KEEP;
    }

    DataBuffer ciphertext;
    bool ok =
        Protect(header, inner_content_type, plaintext, &ciphertext, padding_);
    EXPECT_TRUE(ok);
    if (!ok) {
      return KEEP;
    }
    *offset = header.Write(output, *offset, ciphertext);
    return CHANGE;
  }

 private:
  size_t padding_;
};

TEST_P(TlsConnectTls13, RecordSizeExceedPad) {
  EnsureTlsSetup();
  auto server_max = std::make_shared<TlsRecordMaximum>(server_);
  auto server_expand = std::make_shared<TlsRecordPadder>(server_, 1);
  server_->SetFilter(std::make_shared<ChainedPacketFilter>(
      ChainedPacketFilterInit({server_max, server_expand})));
  server_expand->EnableDecryption();

  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64);
  Connect();

  server_->SendData(100);

  client_->ExpectReadWriteError();
  ExpectAlert(client_, kTlsAlertRecordOverflow);
  client_->ReadBytes(100);
  EXPECT_EQ(SSL_ERROR_RX_RECORD_TOO_LONG, client_->error_code());

  // Consume the alert at the server.
  server_->Handshake();
  server_->CheckErrorCode(SSL_ERROR_RECORD_OVERFLOW_ALERT);
}

TEST_P(TlsConnectGeneric, RecordSizeBadValues) {
  EnsureTlsSetup();
  EXPECT_EQ(SECFailure,
            SSL_OptionSet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, 63));
  EXPECT_EQ(SECFailure,
            SSL_OptionSet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, -1));
  EXPECT_EQ(SECFailure,
            SSL_OptionSet(server_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, 16386));
  Connect();
}

TEST_P(TlsConnectGeneric, RecordSizeGetValues) {
  EnsureTlsSetup();
  int v;
  EXPECT_EQ(SECSuccess,
            SSL_OptionGet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, &v));
  EXPECT_EQ(16385, v);
  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 300);
  EXPECT_EQ(SECSuccess,
            SSL_OptionGet(client_->ssl_fd(), SSL_RECORD_SIZE_LIMIT, &v));
  EXPECT_EQ(300, v);
  Connect();
}

// The value of the extension is capped by the maximum version of the client.
TEST_P(TlsConnectGeneric, RecordSizeCapExtensionClient) {
  EnsureTlsSetup();
  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385);
  auto capture =
      MakeTlsFilter<TlsExtensionCapture>(client_, ssl_record_size_limit_xtn);
  capture->EnableDecryption();
  Connect();

  uint64_t val = 0;
  EXPECT_TRUE(capture->extension().Read(0, 2, &val));
  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_EQ(16384U, val) << "Extension should be capped";
  } else {
    EXPECT_EQ(16385U, val);
  }
}

// The value of the extension is capped by the maximum version of the server.
TEST_P(TlsConnectGeneric, RecordSizeCapExtensionServer) {
  EnsureTlsSetup();
  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385);
  auto capture =
      MakeTlsFilter<TlsExtensionCapture>(server_, ssl_record_size_limit_xtn);
  capture->EnableDecryption();
  Connect();

  uint64_t val = 0;
  EXPECT_TRUE(capture->extension().Read(0, 2, &val));
  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_EQ(16384U, val) << "Extension should be capped";
  } else {
    EXPECT_EQ(16385U, val);
  }
}

// Damage the client extension and the handshake fails, but the server
// doesn't generate a validation error.
TEST_P(TlsConnectGenericPre13, RecordSizeClientExtensionInvalid) {
  EnsureTlsSetup();
  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
  static const uint8_t v[] = {0xf4, 0x1f};
  MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_record_size_limit_xtn,
                                      DataBuffer(v, sizeof(v)));
  ConnectExpectAlert(server_, kTlsAlertDecryptError);
}

// Special handling for TLS 1.3, where the alert isn't read.
TEST_F(TlsConnectStreamTls13, RecordSizeClientExtensionInvalid) {
  EnsureTlsSetup();
  client_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
  static const uint8_t v[] = {0xf4, 0x1f};
  MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_record_size_limit_xtn,
                                      DataBuffer(v, sizeof(v)));
  client_->ExpectSendAlert(kTlsAlertBadRecordMac);
  server_->ExpectSendAlert(kTlsAlertBadRecordMac);
  ConnectExpectFail();
}

TEST_P(TlsConnectGeneric, RecordSizeServerExtensionInvalid) {
  EnsureTlsSetup();
  server_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000);
  static const uint8_t v[] = {0xf4, 0x1f};
  auto replace = MakeTlsFilter<TlsExtensionReplacer>(
      server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v)));
  replace->EnableDecryption();
  ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
}

class RecordSizeDefaultsTest : public ::testing::Test {
 public:
  void SetUp() {
    EXPECT_EQ(SECSuccess,
              SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &default_));
  }
  void TearDown() {
    // Make sure to restore the default value at the end.
    EXPECT_EQ(SECSuccess,
              SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, default_));
  }

 private:
  PRIntn default_ = 0;
};

TEST_F(RecordSizeDefaultsTest, RecordSizeBadValues) {
  EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 63));
  EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, -1));
  EXPECT_EQ(SECFailure, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 16386));
}

TEST_F(RecordSizeDefaultsTest, RecordSizeGetValue) {
  int v;
  EXPECT_EQ(SECSuccess, SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &v));
  EXPECT_EQ(16385, v);
  EXPECT_EQ(SECSuccess, SSL_OptionSetDefault(SSL_RECORD_SIZE_LIMIT, 3000));
  EXPECT_EQ(SECSuccess, SSL_OptionGetDefault(SSL_RECORD_SIZE_LIMIT, &v));
  EXPECT_EQ(3000, v);
}

}  // namespace nss_test
