/* Copyright (c) 2023, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <openssl/pki/verify.h>

#include <assert.h>

#include <chrono>
#include <optional>
#include <string_view>

#include <openssl/base.h>
#include <openssl/bytestring.h>
#include <openssl/pool.h>

#include <openssl/pki/signature_verify_cache.h>

#include "cert_errors.h"
#include "cert_issuer_source_static.h"
#include "certificate_policies.h"
#include "common_cert_errors.h"
#include "encode_values.h"
#include "input.h"
#include "parse_certificate.h"
#include "parse_values.h"
#include "parsed_certificate.h"
#include "path_builder.h"
#include "simple_path_builder_delegate.h"
#include "trust_store.h"
#include "trust_store_in_memory.h"
#include "verify_certificate_chain.h"

namespace bssl {

namespace {

std::optional<std::shared_ptr<const ParsedCertificate>>
InternalParseCertificate(Span<const uint8_t> cert, std::string *out_diagnostic) {
  ParseCertificateOptions default_options{};
  // We follow Chromium in setting |allow_invalid_serial_numbers| in order to
  // not choke on 21-byte serial numbers, which are common.
  //
  // The reason for the discrepancy is that unsigned numbers with the high bit
  // otherwise set get an extra 0 byte in front to keep them positive. So if you
  // do:
  //    var num [20]byte
  //    fillWithRandom(num[:])
  //    serialNumber := new(big.Int).SetBytes(num[:])
  //    encodeASN1Integer(serialNumber)
  //
  // Then half of your serial numbers will be encoded with 21 bytes. (And
  // 1/512th will have 19 bytes instead of 20.)
  default_options.allow_invalid_serial_numbers = true;

  UniquePtr<CRYPTO_BUFFER> buffer(
      CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
  CertErrors errors;
  std::shared_ptr<const ParsedCertificate> parsed_cert(
      ParsedCertificate::Create(std::move(buffer), default_options, &errors));
  if (!parsed_cert) {
    *out_diagnostic = errors.ToDebugString();
    return {};
  }
  return parsed_cert;
}
}  // namespace


CertPool::CertPool() {}

CertificateVerifyOptions::CertificateVerifyOptions() {}

static std::unique_ptr<VerifyTrustStore> WrapTrustStore(
    std::unique_ptr<TrustStoreInMemory> trust_store) {
  std::unique_ptr<VerifyTrustStore> ret(new VerifyTrustStore);
  ret->trust_store = std::move(trust_store);
  return ret;
}

VerifyTrustStore::~VerifyTrustStore() {}

std::unique_ptr<VerifyTrustStore> VerifyTrustStore::FromDER(
    std::string_view der_certs, std::string *out_diagnostic) {
  auto store = std::make_unique<TrustStoreInMemory>();
  CBS cbs = StringAsBytes(der_certs);

  for (size_t cert_num = 1; CBS_len(&cbs) != 0; cert_num++) {
    CBS cert;
    if (!CBS_get_asn1_element(&cbs, &cert, CBS_ASN1_SEQUENCE)) {
      *out_diagnostic = "failed to get ASN.1 SEQUENCE from input at cert " +
                        std::to_string(cert_num);
      return {};
    }

    auto parsed_cert = InternalParseCertificate(cert, out_diagnostic);
    if (!parsed_cert.has_value()) {
      return {};
    }
    store->AddTrustAnchor(parsed_cert.value());
  }

  return WrapTrustStore(std::move(store));
}

std::unique_ptr<VerifyTrustStore> VerifyTrustStore::FromDER(
    const std::vector<std::string_view> &der_roots,
    std::string *out_diagnostic) {
  auto store = std::make_unique<TrustStoreInMemory>();

  for (const std::string_view &cert : der_roots) {
    auto parsed_cert = InternalParseCertificate(StringAsBytes(cert), out_diagnostic);
    if (!parsed_cert.has_value()) {
      return {};
    }
    store->AddTrustAnchor(parsed_cert.value());
  }

  return WrapTrustStore(std::move(store));
}

CertPool::~CertPool() {}


std::unique_ptr<CertPool> CertPool::FromCerts(
    const std::vector<std::string_view> &der_certs,
    std::string *out_diagnostic) {
  auto pool = std::make_unique<CertPool>();
  pool->impl_ = std::make_unique<CertIssuerSourceStatic>();

  for (const std::string_view &cert : der_certs) {
    auto parsed_cert =
        InternalParseCertificate(StringAsBytes(cert), out_diagnostic);
    if (!parsed_cert.has_value()) {
      return {};
    }
    pool->impl_->AddCert(std::move(parsed_cert.value()));
  }

  return pool;
}

CertificateVerifyStatus::CertificateVerifyStatus() {}

size_t CertificateVerifyStatus::IterationCount() const {
  return iteration_count_;
}

size_t CertificateVerifyStatus::MaxDepthSeen() const { return max_depth_seen_; }

// PathBuilderDelegateImpl implements a deadline and allows for the
// use of a SignatureVerifyCache if an implementation is provided.
class PathBuilderDelegateImpl : public SimplePathBuilderDelegate {
 public:
  PathBuilderDelegateImpl(
      size_t min_rsa_modulus_length_bits, DigestPolicy digest_policy,
      std::chrono::time_point<std::chrono::steady_clock> deadline,
      SignatureVerifyCache *cache)
      : SimplePathBuilderDelegate(min_rsa_modulus_length_bits, digest_policy),
        deadline_(deadline),
        cache_(cache) {}

  bool IsDeadlineExpired() override {
    return (std::chrono::steady_clock::now() > deadline_);
  }

  SignatureVerifyCache *GetVerifyCache() override { return cache_; }

 private:
  const std::chrono::time_point<std::chrono::steady_clock> deadline_;
  SignatureVerifyCache *cache_;
};

std::optional<std::vector<std::vector<std::string>>> CertificateVerifyInternal(
    const CertificateVerifyOptions &opts, VerifyError *out_error,
    CertificateVerifyStatus *out_status, bool all_paths) {
  VerifyError dummy;
  if (!out_error) {
    out_error = &dummy;
  }
  if (out_status != nullptr) {
    out_status->iteration_count_ = 0;
    out_status->max_depth_seen_ = 0;
  }

  std::string diagnostic;
  std::optional<std::shared_ptr<const ParsedCertificate>> maybe_leaf =
      InternalParseCertificate(StringAsBytes(opts.leaf_cert), &diagnostic);

  if (!maybe_leaf.has_value()) {
    *out_error = {VerifyError::StatusCode::CERTIFICATE_INVALID, 0, diagnostic};
    return {};
  }
  std::shared_ptr<const ParsedCertificate> leaf_cert = maybe_leaf.value();

  int64_t now;
  if (opts.time.has_value()) {
    now = opts.time.value();
  } else {
    now = time(NULL);
  }

  der::GeneralizedTime verification_time;
  if (!der::EncodePosixTimeAsGeneralizedTime(now, &verification_time)) {
    *out_error = {VerifyError::StatusCode::VERIFICATION_FAILURE, -1,
                  "\nCould not encode verification time\n"};
    return {};
  }

  TrustStore *trust_store = nullptr;
  if (opts.trust_store) {
    trust_store = opts.trust_store->trust_store.get();
  }

  auto digest_policy = SimplePathBuilderDelegate::DigestPolicy::kStrong;
  // TODO(b/111551631): remove this
  if (opts.insecurely_allow_sha1) {
    digest_policy = SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
  }

  std::chrono::time_point<std::chrono::steady_clock> deadline =
      std::chrono::time_point<std::chrono::steady_clock>::max();
  if (opts.deadline.has_value()) {
    deadline = opts.deadline.value();
  }

  PathBuilderDelegateImpl path_builder_delegate(
      opts.min_rsa_modulus_length, digest_policy, deadline,
      opts.signature_verify_cache);

  KeyPurpose key_purpose = KeyPurpose::SERVER_AUTH;
  switch (opts.key_purpose) {
    case CertificateVerifyOptions::KeyPurpose::ANY_EKU:
      key_purpose = KeyPurpose::ANY_EKU;
      break;
    case CertificateVerifyOptions::KeyPurpose::SERVER_AUTH:
      key_purpose = KeyPurpose::SERVER_AUTH;
      break;
    case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH:
      key_purpose = KeyPurpose::CLIENT_AUTH;
      break;
    case CertificateVerifyOptions::KeyPurpose::SERVER_AUTH_STRICT:
      key_purpose = KeyPurpose::SERVER_AUTH_STRICT;
      break;
    case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH_STRICT:
      key_purpose = KeyPurpose::CLIENT_AUTH_STRICT;
      break;
    case CertificateVerifyOptions::KeyPurpose::SERVER_AUTH_STRICT_LEAF:
      key_purpose = KeyPurpose::SERVER_AUTH_STRICT_LEAF;
      break;
    case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH_STRICT_LEAF:
      key_purpose = KeyPurpose::CLIENT_AUTH_STRICT_LEAF;
      break;
  }
  CertPathBuilder path_builder(leaf_cert, trust_store, &path_builder_delegate,
                               verification_time, key_purpose,
                               InitialExplicitPolicy::kFalse,
                               /* user_initial_policy_set= */
                               {der::Input(kAnyPolicyOid)},
                               InitialPolicyMappingInhibit::kFalse,
                               InitialAnyPolicyInhibit::kFalse);

  CertIssuerSourceStatic intermediates;
  for (const std::string_view &cert : opts.intermediates) {
    std::string diag_string;
    std::optional<std::shared_ptr<const ParsedCertificate>> parsed =
        InternalParseCertificate(StringAsBytes(cert), &diag_string);
    if (!parsed.has_value()) {
      if (path_builder_delegate.IsDebugLogEnabled()) {
        path_builder_delegate.DebugLog("skipping bad intermediate: " +
                                       diag_string);
      }
      continue;
    }
    intermediates.AddCert(std::move(parsed.value()));
  }
  path_builder.AddCertIssuerSource(&intermediates);

  if (opts.extra_intermediates != nullptr) {
    path_builder.AddCertIssuerSource(opts.extra_intermediates->impl_.get());
  }

  if (opts.max_iteration_count > 0) {
    path_builder.SetIterationLimit(opts.max_iteration_count);
  }

  if (opts.max_path_building_depth > 0) {
    path_builder.SetDepthLimit(opts.max_path_building_depth);
  }

  path_builder.SetExploreAllPaths(all_paths);

  CertPathBuilder::Result result = path_builder.Run();

  if (out_status != nullptr) {
    out_status->iteration_count_ = result.iteration_count;
    out_status->max_depth_seen_ = result.max_depth_seen;
  }

  *out_error = result.GetBestPathVerifyError();

  if (result.HasValidPath()) {
    std::vector<std::vector<std::string>> ret;
    if (!all_paths) {
      auto best_path = result.GetBestValidPath();
      ret.push_back(std::vector<std::string>());
      for (size_t i = 0; i < best_path->certs.size(); i++) {
        ret[0].emplace_back(BytesAsStringView(best_path->certs[i]->der_cert()));
      }
      return ret;
    }
    for (const auto &path : result.paths) {
      if (!path->IsValid()) {
        continue;
      }
      std::vector<std::string> ret_path;
      for (const auto &cert : path->certs) {
        ret_path.emplace_back(BytesAsStringView(cert->der_cert()));
      }
      ret.push_back(ret_path);
    }
    return ret;
  }

  return {};
}

std::optional<std::vector<std::string>> CertificateVerify(
    const CertificateVerifyOptions &opts, VerifyError *out_error,
    CertificateVerifyStatus *out_status) {
  auto single_path = CertificateVerifyInternal(opts, out_error, out_status,
                                               /*all_paths=*/false);
  if (!single_path.has_value()) {
    return {};
  }
  return single_path.value()[0];
}

std::optional<std::vector<std::vector<std::string>>> CertificateVerifyAllPaths(
    const CertificateVerifyOptions &opts) {
  return CertificateVerifyInternal(opts, nullptr, nullptr, /*all_paths=*/true);
}

}  // namespace bssl
