/* 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 "mozpkix/pkixc.h"

#include "mozpkix/pkix.h"
#include "mozpkix/pkixnss.h"
#include "mozpkix/pkixtypes.h"
#include "secerr.h"

using namespace mozilla::pkix;

const size_t SHA256_DIGEST_LENGTH = 256 / 8;

class CodeSigningTrustDomain final : public TrustDomain {
 public:
  explicit CodeSigningTrustDomain(const uint8_t** certificates,
                                  const uint16_t* certificateLengths,
                                  size_t numCertificates,
                                  const uint8_t* rootSHA256Digest)
      : mCertificates(certificates),
        mCertificateLengths(certificateLengths),
        mNumCertificates(numCertificates),
        mRootSHA256Digest(rootSHA256Digest) {}

  virtual Result GetCertTrust(EndEntityOrCA endEntityOrCA,
                              const CertPolicyId& policy,
                              Input candidateCertDER,
                              /*out*/ TrustLevel& trustLevel) override {
    uint8_t digestBuf[SHA256_DIGEST_LENGTH] = {0};
    Result rv = DigestBufNSS(candidateCertDER, DigestAlgorithm::sha256,
                             digestBuf, SHA256_DIGEST_LENGTH);
    if (rv != Success) {
      return rv;
    }
    Input candidateDigestInput;
    rv = candidateDigestInput.Init(digestBuf, SHA256_DIGEST_LENGTH);
    if (rv != Success) {
      return rv;
    }
    Input rootDigestInput;
    rv = rootDigestInput.Init(mRootSHA256Digest, SHA256_DIGEST_LENGTH);
    if (rv != Success) {
      return rv;
    }
    if (InputsAreEqual(candidateDigestInput, rootDigestInput)) {
      trustLevel = TrustLevel::TrustAnchor;
    } else {
      trustLevel = TrustLevel::InheritsTrust;
    }
    return Success;
  }

  virtual Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker,
                            Time time) override {
    for (size_t i = 0; i < mNumCertificates; i++) {
      Input certInput;
      Result rv = certInput.Init(mCertificates[i], mCertificateLengths[i]);
      if (rv != Success) {
        return rv;
      }
      bool keepGoing;
      rv = checker.Check(certInput, nullptr /*additionalNameConstraints*/,
                         keepGoing);
      if (rv != Success) {
        return rv;
      }
      if (!keepGoing) {
        break;
      }
    }

    return Success;
  }

  virtual Result CheckRevocation(
      EndEntityOrCA endEntityOrCA, const CertID& certID, Time time,
      Duration validityDuration,
      /*optional*/ const Input* stapledOCSPresponse,
      /*optional*/ const Input* aiaExtension,
      /*optional*/ const Input* sctExtension) override {
    return Success;
  }

  virtual Result IsChainValid(const DERArray& certChain, Time time,
                              const CertPolicyId& requiredPolicy) override {
    return Success;
  }

  virtual Result CheckSignatureDigestAlgorithm(DigestAlgorithm digestAlg,
                                               EndEntityOrCA endEntityOrCA,
                                               Time notBefore) override {
    switch (digestAlg) {
      case DigestAlgorithm::sha256:  // fall through
      case DigestAlgorithm::sha384:  // fall through
      case DigestAlgorithm::sha512:
        return Success;
      default:
        return Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED;
    }
  }

  virtual Result CheckRSAPublicKeyModulusSizeInBits(
      EndEntityOrCA endEntityOrCA, unsigned int modulusSizeInBits) override {
    if (modulusSizeInBits < 2048) {
      return Result::ERROR_INADEQUATE_KEY_SIZE;
    }
    return Success;
  }

  virtual Result VerifyRSAPKCS1SignedDigest(
      const SignedDigest& signedDigest, Input subjectPublicKeyInfo) override {
    return VerifyRSAPKCS1SignedDigestNSS(signedDigest, subjectPublicKeyInfo,
                                         nullptr);
  }

  virtual Result CheckECDSACurveIsAcceptable(EndEntityOrCA endEntityOrCA,
                                             NamedCurve curve) override {
    switch (curve) {
      case NamedCurve::secp256r1:  // fall through
      case NamedCurve::secp384r1:  // fall through
      case NamedCurve::secp521r1:
        return Success;
    }

    return Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
  }

  virtual Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
                                         Input subjectPublicKeyInfo) override {
    return VerifyECDSASignedDigestNSS(signedDigest, subjectPublicKeyInfo,
                                      nullptr);
  }

  virtual Result CheckValidityIsAcceptable(Time notBefore, Time notAfter,
                                           EndEntityOrCA endEntityOrCA,
                                           KeyPurposeId keyPurpose) override {
    return Success;
  }

  virtual Result NetscapeStepUpMatchesServerAuth(
      Time notBefore, /*out*/ bool& matches) override {
    matches = false;
    return Success;
  }

  virtual void NoteAuxiliaryExtension(AuxiliaryExtension extension,
                                      Input extensionData) override {}

  virtual Result DigestBuf(Input item, DigestAlgorithm digestAlg,
                           /*out*/ uint8_t* digestBuf,
                           size_t digestBufLen) override {
    return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen);
  }

 private:
  const uint8_t** mCertificates;
  const uint16_t* mCertificateLengths;
  size_t mNumCertificates;
  const uint8_t* mRootSHA256Digest;
};

class CodeSigningNameMatchingPolicy : public NameMatchingPolicy {
 public:
  virtual Result FallBackToCommonName(
      Time notBefore,
      /*out*/ FallBackToSearchWithinSubject& fallBackToCommonName) override {
    fallBackToCommonName = FallBackToSearchWithinSubject::No;
    return Success;
  }
};

bool VerifyCodeSigningCertificateChain(
    const uint8_t** certificates, const uint16_t* certificateLengths,
    size_t numCertificates, uint64_t secondsSinceEpoch,
    const uint8_t* rootSHA256Digest, const uint8_t* hostname,
    size_t hostnameLength, PRErrorCode* error) {
  if (!error) {
    return false;
  }
  if (!certificates || !certificateLengths || !rootSHA256Digest) {
    *error = SEC_ERROR_INVALID_ARGS;
    return false;
  }

  CodeSigningTrustDomain trustDomain(certificates, certificateLengths,
                                     numCertificates, rootSHA256Digest);
  Input certificate;
  Result rv = certificate.Init(certificates[0], certificateLengths[0]);
  if (rv != Success) {
    *error = MapResultToPRErrorCode(rv);
    return false;
  }
  Time time = TimeFromEpochInSeconds(secondsSinceEpoch);
  rv = BuildCertChain(
      trustDomain, certificate, time, EndEntityOrCA::MustBeEndEntity,
      KeyUsage::noParticularKeyUsageRequired, KeyPurposeId::id_kp_codeSigning,
      CertPolicyId::anyPolicy, nullptr);
  if (rv != Success) {
    *error = MapResultToPRErrorCode(rv);
    return false;
  }
  Input hostnameInput;
  rv = hostnameInput.Init(hostname, hostnameLength);
  if (rv != Success) {
    *error = MapResultToPRErrorCode(rv);
    return false;
  }
  CodeSigningNameMatchingPolicy nameMatchingPolicy;
  rv = CheckCertHostname(certificate, hostnameInput, nameMatchingPolicy);
  if (rv != Success) {
    *error = MapResultToPRErrorCode(rv);
    return false;
  }
  return true;
}
