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

#include <memory>

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

namespace nss_test {

// Tests for Certificate Transparency (RFC 6962)
// These don't work with TLS 1.3: see bug 1252745.

// Helper class - stores signed certificate timestamps as provided
// by the relevant callbacks on the client.
class SignedCertificateTimestampsExtractor {
 public:
  SignedCertificateTimestampsExtractor(std::shared_ptr<TlsAgent>& client)
      : client_(client) {
    client->SetAuthCertificateCallback(
        [this](TlsAgent* agent, bool checksig, bool isServer) -> SECStatus {
          const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd());
          EXPECT_TRUE(scts);
          if (!scts) {
            return SECFailure;
          }
          auth_timestamps_.reset(new DataBuffer(scts->data, scts->len));
          return SECSuccess;
        });
    client->SetHandshakeCallback([this](TlsAgent* agent) {
      const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd());
      ASSERT_TRUE(scts);
      handshake_timestamps_.reset(new DataBuffer(scts->data, scts->len));
    });
  }

  void assertTimestamps(const DataBuffer& timestamps) {
    ASSERT_NE(nullptr, auth_timestamps_);
    EXPECT_EQ(timestamps, *auth_timestamps_);

    ASSERT_NE(nullptr, handshake_timestamps_);
    EXPECT_EQ(timestamps, *handshake_timestamps_);

    const SECItem* current =
        SSL_PeerSignedCertTimestamps(client_.lock()->ssl_fd());
    EXPECT_EQ(timestamps, DataBuffer(current->data, current->len));
  }

 private:
  std::weak_ptr<TlsAgent> client_;
  std::unique_ptr<DataBuffer> auth_timestamps_;
  std::unique_ptr<DataBuffer> handshake_timestamps_;
};

static const uint8_t kSctValue[] = {0x01, 0x23, 0x45, 0x67, 0x89};
static const SECItem kSctItem = {siBuffer, const_cast<uint8_t*>(kSctValue),
                                 sizeof(kSctValue)};
static const DataBuffer kSctBuffer(kSctValue, sizeof(kSctValue));
static const SSLExtraServerCertData kExtraSctData = {
    ssl_auth_null, nullptr, nullptr, &kSctItem, nullptr, nullptr};

// Test timestamps extraction during a successful handshake.
TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsLegacy) {
  EnsureTlsSetup();

  // We have to use the legacy API consistently here for configuring certs.
  // Also, this doesn't work in TLS 1.3 because this only configures the SCT for
  // RSA decrypt and PKCS#1 signing, not PSS.
  ScopedCERTCertificate cert;
  ScopedSECKEYPrivateKey priv;
  ASSERT_TRUE(TlsAgent::LoadCertificate(TlsAgent::kServerRsa, &cert, &priv));
  EXPECT_EQ(SECSuccess, SSL_ConfigSecureServerWithCertChain(
                            server_->ssl_fd(), cert.get(), nullptr, priv.get(),
                            ssl_kea_rsa));
  EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
                                                    &kSctItem, ssl_kea_rsa));

  client_->SetOption(SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE);
  SignedCertificateTimestampsExtractor timestamps_extractor(client_);

  Connect();

  timestamps_extractor.assertTimestamps(kSctBuffer);
}

TEST_P(TlsConnectGeneric, SignedCertificateTimestampsSuccess) {
  EnsureTlsSetup();
  EXPECT_TRUE(
      server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData));
  client_->SetOption(SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE);
  SignedCertificateTimestampsExtractor timestamps_extractor(client_);

  Connect();

  timestamps_extractor.assertTimestamps(kSctBuffer);
}

// Test SSL_PeerSignedCertTimestamps returning zero-length SECItem
// when the client / the server / both have not enabled the feature.
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveClient) {
  EnsureTlsSetup();
  EXPECT_TRUE(
      server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData));
  SignedCertificateTimestampsExtractor timestamps_extractor(client_);

  Connect();
  timestamps_extractor.assertTimestamps(DataBuffer());
}

TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveServer) {
  EnsureTlsSetup();
  client_->SetOption(SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE);
  SignedCertificateTimestampsExtractor timestamps_extractor(client_);

  Connect();
  timestamps_extractor.assertTimestamps(DataBuffer());
}

TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveBoth) {
  EnsureTlsSetup();
  SignedCertificateTimestampsExtractor timestamps_extractor(client_);

  Connect();
  timestamps_extractor.assertTimestamps(DataBuffer());
}

// Check that the given agent doesn't have an OCSP response for its peer.
static SECStatus CheckNoOCSP(TlsAgent* agent, bool checksig, bool isServer) {
  const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd());
  EXPECT_TRUE(ocsp);
  EXPECT_EQ(0U, ocsp->len);
  return SECSuccess;
}

static const uint8_t kOcspValue1[] = {1, 2, 3, 4, 5, 6};
static const uint8_t kOcspValue2[] = {7, 8, 9};
static const SECItem kOcspItems[] = {
    {siBuffer, const_cast<uint8_t*>(kOcspValue1), sizeof(kOcspValue1)},
    {siBuffer, const_cast<uint8_t*>(kOcspValue2), sizeof(kOcspValue2)}};
static const SECItemArray kOcspResponses = {const_cast<SECItem*>(kOcspItems),
                                            PR_ARRAY_SIZE(kOcspItems)};
const static SSLExtraServerCertData kOcspExtraData = {
    ssl_auth_null, nullptr, &kOcspResponses, nullptr, nullptr, nullptr};

TEST_P(TlsConnectGeneric, NoOcsp) {
  EnsureTlsSetup();
  client_->SetAuthCertificateCallback(CheckNoOCSP);
  Connect();
}

// The client doesn't get OCSP stapling unless it asks.
TEST_P(TlsConnectGeneric, OcspNotRequested) {
  EnsureTlsSetup();
  client_->SetAuthCertificateCallback(CheckNoOCSP);
  EXPECT_TRUE(
      server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData));
  Connect();
}

// Even if the client asks, the server has nothing unless it is configured.
TEST_P(TlsConnectGeneric, OcspNotProvided) {
  EnsureTlsSetup();
  client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
  client_->SetAuthCertificateCallback(CheckNoOCSP);
  Connect();
}

TEST_P(TlsConnectGenericPre13, OcspMangled) {
  EnsureTlsSetup();
  client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
  EXPECT_TRUE(
      server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData));

  static const uint8_t val[] = {1};
  auto replacer = MakeTlsFilter<TlsExtensionReplacer>(
      server_, ssl_cert_status_xtn, DataBuffer(val, sizeof(val)));
  ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}

TEST_P(TlsConnectGeneric, OcspSuccess) {
  EnsureTlsSetup();
  client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
  auto capture_ocsp =
      MakeTlsFilter<TlsExtensionCapture>(server_, ssl_cert_status_xtn);

  // The value should be available during the AuthCertificateCallback
  client_->SetAuthCertificateCallback([](TlsAgent* agent, bool checksig,
                                         bool isServer) -> SECStatus {
    const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd());
    if (!ocsp) {
      return SECFailure;
    }
    EXPECT_EQ(1U, ocsp->len) << "We only provide the first item";
    EXPECT_EQ(0, SECITEM_CompareItem(&kOcspItems[0], &ocsp->items[0]));
    return SECSuccess;
  });
  EXPECT_TRUE(
      server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData));

  Connect();
  // In TLS 1.3, the server doesn't provide a visible ServerHello extension.
  // For earlier versions, the extension is just empty.
  EXPECT_EQ(0U, capture_ocsp->extension().len());
}

TEST_P(TlsConnectGeneric, OcspHugeSuccess) {
  EnsureTlsSetup();
  client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE);

  uint8_t hugeOcspValue[16385];
  memset(hugeOcspValue, 0xa1, sizeof(hugeOcspValue));
  const SECItem hugeOcspItems[] = {
      {siBuffer, const_cast<uint8_t*>(hugeOcspValue), sizeof(hugeOcspValue)}};
  const SECItemArray hugeOcspResponses = {const_cast<SECItem*>(hugeOcspItems),
                                          PR_ARRAY_SIZE(hugeOcspItems)};
  const SSLExtraServerCertData hugeOcspExtraData = {
      ssl_auth_null, nullptr, &hugeOcspResponses, nullptr, nullptr, nullptr};

  // The value should be available during the AuthCertificateCallback
  client_->SetAuthCertificateCallback([&](TlsAgent* agent, bool checksig,
                                          bool isServer) -> SECStatus {
    const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd());
    if (!ocsp) {
      return SECFailure;
    }
    EXPECT_EQ(1U, ocsp->len) << "We only provide the first item";
    EXPECT_EQ(0, SECITEM_CompareItem(&hugeOcspItems[0], &ocsp->items[0]));
    return SECSuccess;
  });
  EXPECT_TRUE(server_->ConfigServerCert(TlsAgent::kServerRsa, true,
                                        &hugeOcspExtraData));

  Connect();
}

}  // namespace nss_test
