/* 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"

BSSL_NAMESPACE_BEGIN

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

BSSL_NAMESPACE_END
