// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "parsed_certificate.h"

#include "cert_errors.h"
#include "certificate_policies.h"
#include "extended_key_usage.h"
#include "name_constraints.h"
#include "signature_algorithm.h"
#include "verify_name_match.h"
#include "parser.h"
#include <openssl/pool.h>

namespace bssl {

namespace {

DEFINE_CERT_ERROR_ID(kFailedParsingCertificate, "Failed parsing Certificate");
DEFINE_CERT_ERROR_ID(kFailedParsingTbsCertificate,
                     "Failed parsing TBSCertificate");
DEFINE_CERT_ERROR_ID(kFailedReadingIssuerOrSubject,
                     "Failed reading issuer or subject");
DEFINE_CERT_ERROR_ID(kFailedNormalizingSubject, "Failed normalizing subject");
DEFINE_CERT_ERROR_ID(kFailedNormalizingIssuer, "Failed normalizing issuer");
DEFINE_CERT_ERROR_ID(kFailedParsingExtensions, "Failed parsing extensions");
DEFINE_CERT_ERROR_ID(kFailedParsingBasicConstraints,
                     "Failed parsing basic constraints");
DEFINE_CERT_ERROR_ID(kFailedParsingKeyUsage, "Failed parsing key usage");
DEFINE_CERT_ERROR_ID(kFailedParsingEku, "Failed parsing extended key usage");
DEFINE_CERT_ERROR_ID(kFailedParsingSubjectAltName,
                     "Failed parsing subjectAltName");
DEFINE_CERT_ERROR_ID(kSubjectAltNameNotCritical,
                     "Empty subject and subjectAltName is not critical");
DEFINE_CERT_ERROR_ID(kFailedParsingNameConstraints,
                     "Failed parsing name constraints");
DEFINE_CERT_ERROR_ID(kFailedParsingAia, "Failed parsing authority info access");
DEFINE_CERT_ERROR_ID(kFailedParsingPolicies,
                     "Failed parsing certificate policies");
DEFINE_CERT_ERROR_ID(kFailedParsingPolicyConstraints,
                     "Failed parsing policy constraints");
DEFINE_CERT_ERROR_ID(kFailedParsingPolicyMappings,
                     "Failed parsing policy mappings");
DEFINE_CERT_ERROR_ID(kFailedParsingInhibitAnyPolicy,
                     "Failed parsing inhibit any policy");
DEFINE_CERT_ERROR_ID(kFailedParsingAuthorityKeyIdentifier,
                     "Failed parsing authority key identifier");
DEFINE_CERT_ERROR_ID(kFailedParsingSubjectKeyIdentifier,
                     "Failed parsing subject key identifier");

[[nodiscard]] bool GetSequenceValue(const der::Input& tlv, der::Input* value) {
  der::Parser parser(tlv);
  return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
}

}  // namespace

bool ParsedCertificate::GetExtension(const der::Input& extension_oid,
                                     ParsedExtension* parsed_extension) const {
  if (!tbs_.extensions_tlv)
    return false;

  auto it = extensions_.find(extension_oid);
  if (it == extensions_.end()) {
    *parsed_extension = ParsedExtension();
    return false;
  }

  *parsed_extension = it->second;
  return true;
}

ParsedCertificate::ParsedCertificate(PrivateConstructor) {}
ParsedCertificate::~ParsedCertificate() = default;

// static
std::shared_ptr<const ParsedCertificate> ParsedCertificate::Create(
    bssl::UniquePtr<CRYPTO_BUFFER> backing_data,
    const ParseCertificateOptions& options,
    CertErrors* errors) {
  // |errors| is an optional parameter, but to keep the code simpler, use a
  // dummy object when one wasn't provided.
  CertErrors unused_errors;
  if (!errors)
    errors = &unused_errors;

  auto result = std::make_shared<ParsedCertificate>(PrivateConstructor{});
  result->cert_data_ = std::move(backing_data);
  result->cert_ = der::Input(CRYPTO_BUFFER_data(result->cert_data_.get()),
                             CRYPTO_BUFFER_len(result->cert_data_.get()));

  if (!ParseCertificate(result->cert_, &result->tbs_certificate_tlv_,
                        &result->signature_algorithm_tlv_,
                        &result->signature_value_, errors)) {
    errors->AddError(kFailedParsingCertificate);
    return nullptr;
  }

  if (!ParseTbsCertificate(result->tbs_certificate_tlv_, options, &result->tbs_,
                           errors)) {
    errors->AddError(kFailedParsingTbsCertificate);
    return nullptr;
  }

  // Attempt to parse the signature algorithm contained in the Certificate.
  result->signature_algorithm_ =
      ParseSignatureAlgorithm(result->signature_algorithm_tlv_);

  der::Input subject_value;
  if (!GetSequenceValue(result->tbs_.subject_tlv, &subject_value)) {
    errors->AddError(kFailedReadingIssuerOrSubject);
    return nullptr;
  }
  if (!NormalizeName(subject_value, &result->normalized_subject_, errors)) {
    errors->AddError(kFailedNormalizingSubject);
    return nullptr;
  }
  der::Input issuer_value;
  if (!GetSequenceValue(result->tbs_.issuer_tlv, &issuer_value)) {
    errors->AddError(kFailedReadingIssuerOrSubject);
    return nullptr;
  }
  if (!NormalizeName(issuer_value, &result->normalized_issuer_, errors)) {
    errors->AddError(kFailedNormalizingIssuer);
    return nullptr;
  }

  // Parse the standard X.509 extensions.
  if (result->tbs_.extensions_tlv) {
    // ParseExtensions() ensures there are no duplicates, and maps the (unique)
    // OID to the extension value.
    if (!ParseExtensions(result->tbs_.extensions_tlv.value(),
                         &result->extensions_)) {
      errors->AddError(kFailedParsingExtensions);
      return nullptr;
    }

    ParsedExtension extension;

    // Basic constraints.
    if (result->GetExtension(der::Input(kBasicConstraintsOid), &extension)) {
      result->has_basic_constraints_ = true;
      if (!ParseBasicConstraints(extension.value,
                                 &result->basic_constraints_)) {
        errors->AddError(kFailedParsingBasicConstraints);
        return nullptr;
      }
    }

    // Key Usage.
    if (result->GetExtension(der::Input(kKeyUsageOid), &extension)) {
      result->has_key_usage_ = true;
      if (!ParseKeyUsage(extension.value, &result->key_usage_)) {
        errors->AddError(kFailedParsingKeyUsage);
        return nullptr;
      }
    }

    // Extended Key Usage.
    if (result->GetExtension(der::Input(kExtKeyUsageOid), &extension)) {
      result->has_extended_key_usage_ = true;
      if (!ParseEKUExtension(extension.value, &result->extended_key_usage_)) {
        errors->AddError(kFailedParsingEku);
        return nullptr;
      }
    }

    // Subject alternative name.
    if (result->GetExtension(der::Input(kSubjectAltNameOid),
                             &result->subject_alt_names_extension_)) {
      // RFC 5280 section 4.2.1.6:
      // SubjectAltName ::= GeneralNames
      result->subject_alt_names_ = GeneralNames::Create(
          result->subject_alt_names_extension_.value, errors);
      if (!result->subject_alt_names_) {
        errors->AddError(kFailedParsingSubjectAltName);
        return nullptr;
      }
      // RFC 5280 section 4.1.2.6:
      // If subject naming information is present only in the subjectAltName
      // extension (e.g., a key bound only to an email address or URI), then the
      // subject name MUST be an empty sequence and the subjectAltName extension
      // MUST be critical.
      if (subject_value.Length() == 0 &&
          !result->subject_alt_names_extension_.critical) {
        errors->AddError(kSubjectAltNameNotCritical);
        return nullptr;
      }
    }

    // Name constraints.
    if (result->GetExtension(der::Input(kNameConstraintsOid), &extension)) {
      result->name_constraints_ =
          NameConstraints::Create(extension.value, extension.critical, errors);
      if (!result->name_constraints_) {
        errors->AddError(kFailedParsingNameConstraints);
        return nullptr;
      }
    }

    // Authority information access.
    if (result->GetExtension(der::Input(kAuthorityInfoAccessOid),
                             &result->authority_info_access_extension_)) {
      result->has_authority_info_access_ = true;
      if (!ParseAuthorityInfoAccessURIs(
              result->authority_info_access_extension_.value,
              &result->ca_issuers_uris_, &result->ocsp_uris_)) {
        errors->AddError(kFailedParsingAia);
        return nullptr;
      }
    }

    // Policies.
    if (result->GetExtension(der::Input(kCertificatePoliciesOid), &extension)) {
      result->has_policy_oids_ = true;
      if (!ParseCertificatePoliciesExtensionOids(
              extension.value, false /*fail_parsing_unknown_qualifier_oids*/,
              &result->policy_oids_, errors)) {
        errors->AddError(kFailedParsingPolicies);
        return nullptr;
      }
    }

    // Policy constraints.
    if (result->GetExtension(der::Input(kPolicyConstraintsOid), &extension)) {
      result->has_policy_constraints_ = true;
      if (!ParsePolicyConstraints(extension.value,
                                  &result->policy_constraints_)) {
        errors->AddError(kFailedParsingPolicyConstraints);
        return nullptr;
      }
    }

    // Policy mappings.
    if (result->GetExtension(der::Input(kPolicyMappingsOid), &extension)) {
      result->has_policy_mappings_ = true;
      if (!ParsePolicyMappings(extension.value, &result->policy_mappings_)) {
        errors->AddError(kFailedParsingPolicyMappings);
        return nullptr;
      }
    }

    // Inhibit Any Policy.
    if (result->GetExtension(der::Input(kInhibitAnyPolicyOid), &extension)) {
      result->has_inhibit_any_policy_ = true;
      if (!ParseInhibitAnyPolicy(extension.value,
                                 &result->inhibit_any_policy_)) {
        errors->AddError(kFailedParsingInhibitAnyPolicy);
        return nullptr;
      }
    }

    // Subject Key Identifier.
    if (result->GetExtension(der::Input(kSubjectKeyIdentifierOid),
                             &extension)) {
      result->subject_key_identifier_ = std::make_optional<der::Input>();
      if (!ParseSubjectKeyIdentifier(
              extension.value, &result->subject_key_identifier_.value())) {
        errors->AddError(kFailedParsingSubjectKeyIdentifier);
        return nullptr;
      }
    }

    // Authority Key Identifier.
    if (result->GetExtension(der::Input(kAuthorityKeyIdentifierOid),
                             &extension)) {
      result->authority_key_identifier_ =
          std::make_optional<ParsedAuthorityKeyIdentifier>();
      if (!ParseAuthorityKeyIdentifier(
              extension.value, &result->authority_key_identifier_.value())) {
        errors->AddError(kFailedParsingAuthorityKeyIdentifier);
        return nullptr;
      }
    }
  }

  return result;
}

// static
bool ParsedCertificate::CreateAndAddToVector(
    bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
    const ParseCertificateOptions& options,
    std::vector<std::shared_ptr<const ParsedCertificate>>* chain,
    CertErrors* errors) {
  std::shared_ptr<const ParsedCertificate> cert(
      Create(std::move(cert_data), options, errors));
  if (!cert)
    return false;
  chain->push_back(std::move(cert));
  return true;
}

}  // namespace net
