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

#include "parse_certificate.h"

#include <optional>
#include <utility>

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

#include "cert_error_params.h"
#include "cert_errors.h"
#include "general_names.h"
#include "input.h"
#include "parse_values.h"
#include "parser.h"
#include "string_util.h"

namespace bssl {

namespace {

DEFINE_CERT_ERROR_ID(kCertificateNotSequence,
                     "Failed parsing Certificate SEQUENCE");
DEFINE_CERT_ERROR_ID(kUnconsumedDataInsideCertificateSequence,
                     "Unconsumed data inside Certificate SEQUENCE");
DEFINE_CERT_ERROR_ID(kUnconsumedDataAfterCertificateSequence,
                     "Unconsumed data after Certificate SEQUENCE");
DEFINE_CERT_ERROR_ID(kTbsCertificateNotSequence,
                     "Couldn't read tbsCertificate as SEQUENCE");
DEFINE_CERT_ERROR_ID(
    kSignatureAlgorithmNotSequence,
    "Couldn't read Certificate.signatureAlgorithm as SEQUENCE");
DEFINE_CERT_ERROR_ID(kSignatureValueNotBitString,
                     "Couldn't read Certificate.signatureValue as BIT STRING");
DEFINE_CERT_ERROR_ID(kUnconsumedDataInsideTbsCertificateSequence,
                     "Unconsumed data inside TBSCertificate");
DEFINE_CERT_ERROR_ID(kTbsNotSequence, "Failed parsing TBSCertificate SEQUENCE");
DEFINE_CERT_ERROR_ID(kFailedReadingVersion, "Failed reading version");
DEFINE_CERT_ERROR_ID(kFailedParsingVersion, "Failed parsing version");
DEFINE_CERT_ERROR_ID(kVersionExplicitlyV1,
                     "Version explicitly V1 (should be omitted)");
DEFINE_CERT_ERROR_ID(kFailedReadingSerialNumber, "Failed reading serialNumber");
DEFINE_CERT_ERROR_ID(kFailedReadingSignatureValue, "Failed reading signature");
DEFINE_CERT_ERROR_ID(kFailedReadingIssuer, "Failed reading issuer");
DEFINE_CERT_ERROR_ID(kFailedReadingValidity, "Failed reading validity");
DEFINE_CERT_ERROR_ID(kFailedParsingValidity, "Failed parsing validity");
DEFINE_CERT_ERROR_ID(kFailedReadingSubject, "Failed reading subject");
DEFINE_CERT_ERROR_ID(kFailedReadingSpki, "Failed reading subjectPublicKeyInfo");
DEFINE_CERT_ERROR_ID(kFailedReadingIssuerUniqueId,
                     "Failed reading issuerUniqueId");
DEFINE_CERT_ERROR_ID(kFailedParsingIssuerUniqueId,
                     "Failed parsing issuerUniqueId");
DEFINE_CERT_ERROR_ID(
    kIssuerUniqueIdNotExpected,
    "Unexpected issuerUniqueId (must be V2 or V3 certificate)");
DEFINE_CERT_ERROR_ID(kFailedReadingSubjectUniqueId,
                     "Failed reading subjectUniqueId");
DEFINE_CERT_ERROR_ID(kFailedParsingSubjectUniqueId,
                     "Failed parsing subjectUniqueId");
DEFINE_CERT_ERROR_ID(
    kSubjectUniqueIdNotExpected,
    "Unexpected subjectUniqueId (must be V2 or V3 certificate)");
DEFINE_CERT_ERROR_ID(kFailedReadingExtensions,
                     "Failed reading extensions SEQUENCE");
DEFINE_CERT_ERROR_ID(kUnexpectedExtensions,
                     "Unexpected extensions (must be V3 certificate)");
DEFINE_CERT_ERROR_ID(kSerialNumberIsNegative, "Serial number is negative");
DEFINE_CERT_ERROR_ID(kSerialNumberIsZero, "Serial number is zero");
DEFINE_CERT_ERROR_ID(kSerialNumberLengthOver20,
                     "Serial number is longer than 20 octets");
DEFINE_CERT_ERROR_ID(kSerialNumberNotValidInteger,
                     "Serial number is not a valid INTEGER");

// Returns true if |input| is a SEQUENCE and nothing else.
[[nodiscard]] bool IsSequenceTLV(der::Input input) {
  der::Parser parser(input);
  der::Parser unused_sequence_parser;
  if (!parser.ReadSequence(&unused_sequence_parser)) {
    return false;
  }
  // Should by a single SEQUENCE by definition of the function.
  return !parser.HasMore();
}

// Reads a SEQUENCE from |parser| and writes the full tag-length-value into
// |out|. On failure |parser| may or may not have been advanced.
[[nodiscard]] bool ReadSequenceTLV(der::Parser *parser, der::Input *out) {
  return parser->ReadRawTLV(out) && IsSequenceTLV(*out);
}

// Parses a Version according to RFC 5280:
//
//     Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
//
// No value other that v1, v2, or v3 is allowed (and if given will fail). RFC
// 5280 minimally requires the handling of v3 (and overwhelmingly these are the
// certificate versions in use today):
//
//     Implementations SHOULD be prepared to accept any version certificate.
//     At a minimum, conforming implementations MUST recognize version 3
//     certificates.
[[nodiscard]] bool ParseVersion(der::Input in, CertificateVersion *version) {
  der::Parser parser(in);
  uint64_t version64;
  if (!parser.ReadUint64(&version64)) {
    return false;
  }

  switch (version64) {
    case 0:
      *version = CertificateVersion::V1;
      break;
    case 1:
      *version = CertificateVersion::V2;
      break;
    case 2:
      *version = CertificateVersion::V3;
      break;
    default:
      // Don't allow any other version identifier.
      return false;
  }

  // By definition the input to this function was a single INTEGER, so there
  // shouldn't be anything else after it.
  return !parser.HasMore();
}

// Returns true if every bit in |bits| is zero (including empty).
[[nodiscard]] bool BitStringIsAllZeros(const der::BitString &bits) {
  // Note that it is OK to read from the unused bits, since BitString parsing
  // guarantees they are all zero.
  for (uint8_t b : bits.bytes()) {
    if (b != 0) {
      return false;
    }
  }
  return true;
}

// Parses a DistributionPointName.
//
// From RFC 5280:
//
//    DistributionPointName ::= CHOICE {
//      fullName                [0]     GeneralNames,
//      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
bool ParseDistributionPointName(der::Input dp_name,
                                ParsedDistributionPoint *distribution_point) {
  der::Parser parser(dp_name);
  std::optional<der::Input> der_full_name;
  if (!parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
          &der_full_name)) {
    return false;
  }
  if (der_full_name) {
    // TODO(mattm): surface the CertErrors.
    CertErrors errors;
    distribution_point->distribution_point_fullname =
        GeneralNames::CreateFromValue(*der_full_name, &errors);
    if (!distribution_point->distribution_point_fullname) {
      return false;
    }
    return !parser.HasMore();
  }

  if (!parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
          &distribution_point
               ->distribution_point_name_relative_to_crl_issuer)) {
    return false;
  }
  if (distribution_point->distribution_point_name_relative_to_crl_issuer) {
    return !parser.HasMore();
  }

  // The CHOICE must contain either fullName or nameRelativeToCRLIssuer.
  return false;
}

// RFC 5280, section 4.2.1.13.
//
// DistributionPoint ::= SEQUENCE {
//  distributionPoint       [0]     DistributionPointName OPTIONAL,
//  reasons                 [1]     ReasonFlags OPTIONAL,
//  cRLIssuer               [2]     GeneralNames OPTIONAL }
bool ParseAndAddDistributionPoint(
    der::Parser *parser,
    std::vector<ParsedDistributionPoint> *distribution_points) {
  ParsedDistributionPoint distribution_point;

  // DistributionPoint ::= SEQUENCE {
  der::Parser distrib_point_parser;
  if (!parser->ReadSequence(&distrib_point_parser)) {
    return false;
  }

  //  distributionPoint       [0]     DistributionPointName OPTIONAL,
  std::optional<der::Input> distribution_point_name;
  if (!distrib_point_parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0,
          &distribution_point_name)) {
    return false;
  }

  if (distribution_point_name &&
      !ParseDistributionPointName(*distribution_point_name,
                                  &distribution_point)) {
    return false;
  }

  //  reasons                 [1]     ReasonFlags OPTIONAL,
  if (!distrib_point_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
                                            &distribution_point.reasons)) {
    return false;
  }

  //  cRLIssuer               [2]     GeneralNames OPTIONAL }
  if (!distrib_point_parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2,
          &distribution_point.crl_issuer)) {
    return false;
  }
  // TODO(eroman): Parse "cRLIssuer"?

  // RFC 5280, section 4.2.1.13:
  // either distributionPoint or cRLIssuer MUST be present.
  if (!distribution_point_name && !distribution_point.crl_issuer) {
    return false;
  }

  if (distrib_point_parser.HasMore()) {
    return false;
  }

  distribution_points->push_back(std::move(distribution_point));
  return true;
}

}  // namespace

ParsedTbsCertificate::ParsedTbsCertificate() = default;

ParsedTbsCertificate::ParsedTbsCertificate(ParsedTbsCertificate &&other) =
    default;

ParsedTbsCertificate::~ParsedTbsCertificate() = default;

bool VerifySerialNumber(der::Input value, bool warnings_only,
                        CertErrors *errors) {
  // If |warnings_only| was set to true, the exact same errors will be logged,
  // only they will be logged with a lower severity (warning rather than error).
  CertError::Severity error_severity =
      warnings_only ? CertError::SEVERITY_WARNING : CertError::SEVERITY_HIGH;

  bool negative;
  if (!der::IsValidInteger(value, &negative)) {
    errors->Add(error_severity, kSerialNumberNotValidInteger, nullptr);
    return false;
  }

  // RFC 5280 section 4.1.2.2:
  //
  //    Note: Non-conforming CAs may issue certificates with serial numbers
  //    that are negative or zero.  Certificate users SHOULD be prepared to
  //    gracefully handle such certificates.
  if (negative) {
    errors->AddWarning(kSerialNumberIsNegative);
  }
  if (value.size() == 1 && value[0] == 0) {
    errors->AddWarning(kSerialNumberIsZero);
  }

  // RFC 5280 section 4.1.2.2:
  //
  //    Certificate users MUST be able to handle serialNumber values up to 20
  //    octets. Conforming CAs MUST NOT use serialNumber values longer than 20
  //    octets.
  if (value.size() > 20) {
    errors->Add(error_severity, kSerialNumberLengthOver20,
                CreateCertErrorParams1SizeT("length", value.size()));
    return false;
  }

  return true;
}

bool ReadUTCOrGeneralizedTime(der::Parser *parser, der::GeneralizedTime *out) {
  der::Input value;
  CBS_ASN1_TAG tag;

  if (!parser->ReadTagAndValue(&tag, &value)) {
    return false;
  }

  if (tag == CBS_ASN1_UTCTIME) {
    return der::ParseUTCTime(value, out);
  }

  if (tag == CBS_ASN1_GENERALIZEDTIME) {
    return der::ParseGeneralizedTime(value, out);
  }

  // Unrecognized tag.
  return false;
}

bool ParseValidity(der::Input validity_tlv, der::GeneralizedTime *not_before,
                   der::GeneralizedTime *not_after) {
  der::Parser parser(validity_tlv);

  //     Validity ::= SEQUENCE {
  der::Parser validity_parser;
  if (!parser.ReadSequence(&validity_parser)) {
    return false;
  }

  //          notBefore      Time,
  if (!ReadUTCOrGeneralizedTime(&validity_parser, not_before)) {
    return false;
  }

  //          notAfter       Time }
  if (!ReadUTCOrGeneralizedTime(&validity_parser, not_after)) {
    return false;
  }

  // By definition the input was a single Validity sequence, so there shouldn't
  // be unconsumed data.
  if (parser.HasMore()) {
    return false;
  }

  // The Validity type does not have an extension point.
  if (validity_parser.HasMore()) {
    return false;
  }

  // Note that RFC 5280 doesn't require notBefore to be <=
  // notAfter, so that will not be considered a "parsing" error here. Instead it
  // will be considered an expired certificate later when testing against the
  // current timestamp.
  return true;
}

bool ParseCertificate(der::Input certificate_tlv,
                      der::Input *out_tbs_certificate_tlv,
                      der::Input *out_signature_algorithm_tlv,
                      der::BitString *out_signature_value,
                      CertErrors *out_errors) {
  // |out_errors| is optional. But ensure it is non-null for the remainder of
  // this function.
  CertErrors unused_errors;
  if (!out_errors) {
    out_errors = &unused_errors;
  }

  der::Parser parser(certificate_tlv);

  //   Certificate  ::=  SEQUENCE  {
  der::Parser certificate_parser;
  if (!parser.ReadSequence(&certificate_parser)) {
    out_errors->AddError(kCertificateNotSequence);
    return false;
  }

  //        tbsCertificate       TBSCertificate,
  if (!ReadSequenceTLV(&certificate_parser, out_tbs_certificate_tlv)) {
    out_errors->AddError(kTbsCertificateNotSequence);
    return false;
  }

  //        signatureAlgorithm   AlgorithmIdentifier,
  if (!ReadSequenceTLV(&certificate_parser, out_signature_algorithm_tlv)) {
    out_errors->AddError(kSignatureAlgorithmNotSequence);
    return false;
  }

  //        signatureValue       BIT STRING  }
  std::optional<der::BitString> signature_value =
      certificate_parser.ReadBitString();
  if (!signature_value) {
    out_errors->AddError(kSignatureValueNotBitString);
    return false;
  }
  *out_signature_value = signature_value.value();

  // There isn't an extension point at the end of Certificate.
  if (certificate_parser.HasMore()) {
    out_errors->AddError(kUnconsumedDataInsideCertificateSequence);
    return false;
  }

  // By definition the input was a single Certificate, so there shouldn't be
  // unconsumed data.
  if (parser.HasMore()) {
    out_errors->AddError(kUnconsumedDataAfterCertificateSequence);
    return false;
  }

  return true;
}

// From RFC 5280 section 4.1:
//
//   TBSCertificate  ::=  SEQUENCE  {
//        version         [0]  EXPLICIT Version DEFAULT v1,
//        serialNumber         CertificateSerialNumber,
//        signature            AlgorithmIdentifier,
//        issuer               Name,
//        validity             Validity,
//        subject              Name,
//        subjectPublicKeyInfo SubjectPublicKeyInfo,
//        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
//                             -- If present, version MUST be v2 or v3
//        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
//                             -- If present, version MUST be v2 or v3
//        extensions      [3]  EXPLICIT Extensions OPTIONAL
//                             -- If present, version MUST be v3
//        }
bool ParseTbsCertificate(der::Input tbs_tlv,
                         const ParseCertificateOptions &options,
                         ParsedTbsCertificate *out, CertErrors *errors) {
  // The rest of this function assumes that |errors| is non-null.
  CertErrors unused_errors;
  if (!errors) {
    errors = &unused_errors;
  }

  // TODO(crbug.com/634443): Add useful error information to |errors|.

  der::Parser parser(tbs_tlv);

  //   TBSCertificate  ::=  SEQUENCE  {
  der::Parser tbs_parser;
  if (!parser.ReadSequence(&tbs_parser)) {
    errors->AddError(kTbsNotSequence);
    return false;
  }

  //        version         [0]  EXPLICIT Version DEFAULT v1,
  std::optional<der::Input> version;
  if (!tbs_parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &version)) {
    errors->AddError(kFailedReadingVersion);
    return false;
  }
  if (version) {
    if (!ParseVersion(version.value(), &out->version)) {
      errors->AddError(kFailedParsingVersion);
      return false;
    }
    if (out->version == CertificateVersion::V1) {
      errors->AddError(kVersionExplicitlyV1);
      // The correct way to specify v1 is to omit the version field since v1 is
      // the DEFAULT.
      return false;
    }
  } else {
    out->version = CertificateVersion::V1;
  }

  //        serialNumber         CertificateSerialNumber,
  if (!tbs_parser.ReadTag(CBS_ASN1_INTEGER, &out->serial_number)) {
    errors->AddError(kFailedReadingSerialNumber);
    return false;
  }
  if (!VerifySerialNumber(out->serial_number,
                          options.allow_invalid_serial_numbers, errors)) {
    // Invalid serial numbers are only considered fatal failures if
    // |!allow_invalid_serial_numbers|.
    if (!options.allow_invalid_serial_numbers) {
      return false;
    }
  }

  //        signature            AlgorithmIdentifier,
  if (!ReadSequenceTLV(&tbs_parser, &out->signature_algorithm_tlv)) {
    errors->AddError(kFailedReadingSignatureValue);
    return false;
  }

  //        issuer               Name,
  if (!ReadSequenceTLV(&tbs_parser, &out->issuer_tlv)) {
    errors->AddError(kFailedReadingIssuer);
    return false;
  }

  //        validity             Validity,
  der::Input validity_tlv;
  if (!tbs_parser.ReadRawTLV(&validity_tlv)) {
    errors->AddError(kFailedReadingValidity);
    return false;
  }
  if (!ParseValidity(validity_tlv, &out->validity_not_before,
                     &out->validity_not_after)) {
    errors->AddError(kFailedParsingValidity);
    return false;
  }

  //        subject              Name,
  if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv)) {
    errors->AddError(kFailedReadingSubject);
    return false;
  }

  //        subjectPublicKeyInfo SubjectPublicKeyInfo,
  if (!ReadSequenceTLV(&tbs_parser, &out->spki_tlv)) {
    errors->AddError(kFailedReadingSpki);
    return false;
  }

  //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
  //                             -- If present, version MUST be v2 or v3
  std::optional<der::Input> issuer_unique_id;
  if (!tbs_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
                                  &issuer_unique_id)) {
    errors->AddError(kFailedReadingIssuerUniqueId);
    return false;
  }
  if (issuer_unique_id) {
    out->issuer_unique_id = der::ParseBitString(issuer_unique_id.value());
    if (!out->issuer_unique_id) {
      errors->AddError(kFailedParsingIssuerUniqueId);
      return false;
    }
    if (out->version != CertificateVersion::V2 &&
        out->version != CertificateVersion::V3) {
      errors->AddError(kIssuerUniqueIdNotExpected);
      return false;
    }
  }

  //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
  //                             -- If present, version MUST be v2 or v3
  std::optional<der::Input> subject_unique_id;
  if (!tbs_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2,
                                  &subject_unique_id)) {
    errors->AddError(kFailedReadingSubjectUniqueId);
    return false;
  }
  if (subject_unique_id) {
    out->subject_unique_id = der::ParseBitString(subject_unique_id.value());
    if (!out->subject_unique_id) {
      errors->AddError(kFailedParsingSubjectUniqueId);
      return false;
    }
    if (out->version != CertificateVersion::V2 &&
        out->version != CertificateVersion::V3) {
      errors->AddError(kSubjectUniqueIdNotExpected);
      return false;
    }
  }

  //        extensions      [3]  EXPLICIT Extensions OPTIONAL
  //                             -- If present, version MUST be v3
  if (!tbs_parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3,
          &out->extensions_tlv)) {
    errors->AddError(kFailedReadingExtensions);
    return false;
  }
  if (out->extensions_tlv) {
    // extensions_tlv must be a single element. Also check that it is a
    // SEQUENCE.
    if (!IsSequenceTLV(out->extensions_tlv.value())) {
      errors->AddError(kFailedReadingExtensions);
      return false;
    }
    if (out->version != CertificateVersion::V3) {
      errors->AddError(kUnexpectedExtensions);
      return false;
    }
  }

  // Note that there IS an extension point at the end of TBSCertificate
  // (according to RFC 5912), so from that interpretation, unconsumed data would
  // be allowed in |tbs_parser|.
  //
  // However because only v1, v2, and v3 certificates are supported by the
  // parsing, there shouldn't be any subsequent data in those versions, so
  // reject.
  if (tbs_parser.HasMore()) {
    errors->AddError(kUnconsumedDataInsideTbsCertificateSequence);
    return false;
  }

  // By definition the input was a single TBSCertificate, so there shouldn't be
  // unconsumed data.
  if (parser.HasMore()) {
    return false;
  }

  return true;
}

// From RFC 5280:
//
//    Extension  ::=  SEQUENCE  {
//            extnID      OBJECT IDENTIFIER,
//            critical    BOOLEAN DEFAULT FALSE,
//            extnValue   OCTET STRING
//                        -- contains the DER encoding of an ASN.1 value
//                        -- corresponding to the extension type identified
//                        -- by extnID
//            }
bool ParseExtension(der::Input extension_tlv, ParsedExtension *out) {
  der::Parser parser(extension_tlv);

  //    Extension  ::=  SEQUENCE  {
  der::Parser extension_parser;
  if (!parser.ReadSequence(&extension_parser)) {
    return false;
  }

  //            extnID      OBJECT IDENTIFIER,
  if (!extension_parser.ReadTag(CBS_ASN1_OBJECT, &out->oid)) {
    return false;
  }

  //            critical    BOOLEAN DEFAULT FALSE,
  out->critical = false;
  bool has_critical;
  der::Input critical;
  if (!extension_parser.ReadOptionalTag(CBS_ASN1_BOOLEAN, &critical,
                                        &has_critical)) {
    return false;
  }
  if (has_critical) {
    if (!der::ParseBool(critical, &out->critical)) {
      return false;
    }
    if (!out->critical) {
      return false;  // DER-encoding requires DEFAULT values be omitted.
    }
  }

  //            extnValue   OCTET STRING
  if (!extension_parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->value)) {
    return false;
  }

  // The Extension type does not have an extension point (everything goes in
  // extnValue).
  if (extension_parser.HasMore()) {
    return false;
  }

  // By definition the input was a single Extension sequence, so there shouldn't
  // be unconsumed data.
  if (parser.HasMore()) {
    return false;
  }

  return true;
}

OPENSSL_EXPORT bool ParseExtensions(
    der::Input extensions_tlv,
    std::map<der::Input, ParsedExtension> *extensions) {
  der::Parser parser(extensions_tlv);

  //    Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
  der::Parser extensions_parser;
  if (!parser.ReadSequence(&extensions_parser)) {
    return false;
  }

  // The Extensions SEQUENCE must contains at least 1 element (otherwise it
  // should have been omitted).
  if (!extensions_parser.HasMore()) {
    return false;
  }

  extensions->clear();

  while (extensions_parser.HasMore()) {
    ParsedExtension extension;

    der::Input extension_tlv;
    if (!extensions_parser.ReadRawTLV(&extension_tlv)) {
      return false;
    }

    if (!ParseExtension(extension_tlv, &extension)) {
      return false;
    }

    bool is_duplicate =
        !extensions->insert(std::make_pair(extension.oid, extension)).second;

    // RFC 5280 says that an extension should not appear more than once.
    if (is_duplicate) {
      return false;
    }
  }

  // By definition the input was a single Extensions sequence, so there
  // shouldn't be unconsumed data.
  if (parser.HasMore()) {
    return false;
  }

  return true;
}

OPENSSL_EXPORT bool ConsumeExtension(
    der::Input oid,
    std::map<der::Input, ParsedExtension> *unconsumed_extensions,
    ParsedExtension *extension) {
  auto it = unconsumed_extensions->find(oid);
  if (it == unconsumed_extensions->end()) {
    return false;
  }

  *extension = it->second;
  unconsumed_extensions->erase(it);
  return true;
}

bool ParseBasicConstraints(der::Input basic_constraints_tlv,
                           ParsedBasicConstraints *out) {
  der::Parser parser(basic_constraints_tlv);

  //    BasicConstraints ::= SEQUENCE {
  der::Parser sequence_parser;
  if (!parser.ReadSequence(&sequence_parser)) {
    return false;
  }

  //         cA                      BOOLEAN DEFAULT FALSE,
  out->is_ca = false;
  bool has_ca;
  der::Input ca;
  if (!sequence_parser.ReadOptionalTag(CBS_ASN1_BOOLEAN, &ca, &has_ca)) {
    return false;
  }
  if (has_ca) {
    if (!der::ParseBool(ca, &out->is_ca)) {
      return false;
    }
    // TODO(eroman): Should reject if CA was set to false, since
    // DER-encoding requires DEFAULT values be omitted. In
    // practice however there are a lot of certificates that use
    // the broken encoding.
  }

  //         pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
  der::Input encoded_path_len;
  if (!sequence_parser.ReadOptionalTag(CBS_ASN1_INTEGER, &encoded_path_len,
                                       &out->has_path_len)) {
    return false;
  }
  if (out->has_path_len) {
    // TODO(eroman): Surface reason for failure if length was longer than uint8.
    if (!der::ParseUint8(encoded_path_len, &out->path_len)) {
      return false;
    }
  } else {
    // Default initialize to 0 as a precaution.
    out->path_len = 0;
  }

  // There shouldn't be any unconsumed data in the extension.
  if (sequence_parser.HasMore()) {
    return false;
  }

  // By definition the input was a single BasicConstraints sequence, so there
  // shouldn't be unconsumed data.
  if (parser.HasMore()) {
    return false;
  }

  return true;
}

// TODO(crbug.com/1314019): return std::optional<BitString> when converting
// has_key_usage_ and key_usage_ into single std::optional field.
bool ParseKeyUsage(der::Input key_usage_tlv, der::BitString *key_usage) {
  der::Parser parser(key_usage_tlv);
  std::optional<der::BitString> key_usage_internal = parser.ReadBitString();
  if (!key_usage_internal) {
    return false;
  }

  // By definition the input was a single BIT STRING.
  if (parser.HasMore()) {
    return false;
  }

  // RFC 5280 section 4.2.1.3:
  //
  //     When the keyUsage extension appears in a certificate, at least
  //     one of the bits MUST be set to 1.
  if (BitStringIsAllZeros(key_usage_internal.value())) {
    return false;
  }

  *key_usage = key_usage_internal.value();
  return true;
}

bool ParseAuthorityInfoAccess(
    der::Input authority_info_access_tlv,
    std::vector<AuthorityInfoAccessDescription> *out_access_descriptions) {
  der::Parser parser(authority_info_access_tlv);

  out_access_descriptions->clear();

  //    AuthorityInfoAccessSyntax  ::=
  //            SEQUENCE SIZE (1..MAX) OF AccessDescription
  der::Parser sequence_parser;
  if (!parser.ReadSequence(&sequence_parser)) {
    return false;
  }
  if (!sequence_parser.HasMore()) {
    return false;
  }

  while (sequence_parser.HasMore()) {
    AuthorityInfoAccessDescription access_description;

    //    AccessDescription  ::=  SEQUENCE {
    der::Parser access_description_sequence_parser;
    if (!sequence_parser.ReadSequence(&access_description_sequence_parser)) {
      return false;
    }

    //            accessMethod          OBJECT IDENTIFIER,
    if (!access_description_sequence_parser.ReadTag(
            CBS_ASN1_OBJECT, &access_description.access_method_oid)) {
      return false;
    }

    //            accessLocation        GeneralName  }
    if (!access_description_sequence_parser.ReadRawTLV(
            &access_description.access_location)) {
      return false;
    }

    if (access_description_sequence_parser.HasMore()) {
      return false;
    }

    out_access_descriptions->push_back(access_description);
  }

  return true;
}

bool ParseAuthorityInfoAccessURIs(
    der::Input authority_info_access_tlv,
    std::vector<std::string_view> *out_ca_issuers_uris,
    std::vector<std::string_view> *out_ocsp_uris) {
  std::vector<AuthorityInfoAccessDescription> access_descriptions;
  if (!ParseAuthorityInfoAccess(authority_info_access_tlv,
                                &access_descriptions)) {
    return false;
  }

  for (const auto &access_description : access_descriptions) {
    der::Parser access_location_parser(access_description.access_location);
    CBS_ASN1_TAG access_location_tag;
    der::Input access_location_value;
    if (!access_location_parser.ReadTagAndValue(&access_location_tag,
                                                &access_location_value)) {
      return false;
    }

    // GeneralName ::= CHOICE {
    if (access_location_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 6)) {
      // uniformResourceIdentifier       [6]     IA5String,
      std::string_view uri = BytesAsStringView(access_location_value);
      if (!bssl::string_util::IsAscii(uri)) {
        return false;
      }

      if (access_description.access_method_oid == der::Input(kAdCaIssuersOid)) {
        out_ca_issuers_uris->push_back(uri);
      } else if (access_description.access_method_oid ==
                 der::Input(kAdOcspOid)) {
        out_ocsp_uris->push_back(uri);
      }
    }
  }
  return true;
}

ParsedDistributionPoint::ParsedDistributionPoint() = default;
ParsedDistributionPoint::ParsedDistributionPoint(
    ParsedDistributionPoint &&other) = default;
ParsedDistributionPoint::~ParsedDistributionPoint() = default;

bool ParseCrlDistributionPoints(
    der::Input extension_value,
    std::vector<ParsedDistributionPoint> *distribution_points) {
  distribution_points->clear();

  // RFC 5280, section 4.2.1.13.
  //
  // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
  der::Parser extension_value_parser(extension_value);
  der::Parser distribution_points_parser;
  if (!extension_value_parser.ReadSequence(&distribution_points_parser)) {
    return false;
  }
  if (extension_value_parser.HasMore()) {
    return false;
  }

  // Sequence must have a minimum of 1 item.
  if (!distribution_points_parser.HasMore()) {
    return false;
  }

  while (distribution_points_parser.HasMore()) {
    if (!ParseAndAddDistributionPoint(&distribution_points_parser,
                                      distribution_points)) {
      return false;
    }
  }

  return true;
}

ParsedAuthorityKeyIdentifier::ParsedAuthorityKeyIdentifier() = default;
ParsedAuthorityKeyIdentifier::~ParsedAuthorityKeyIdentifier() = default;
ParsedAuthorityKeyIdentifier::ParsedAuthorityKeyIdentifier(
    ParsedAuthorityKeyIdentifier &&other) = default;
ParsedAuthorityKeyIdentifier &ParsedAuthorityKeyIdentifier::operator=(
    ParsedAuthorityKeyIdentifier &&other) = default;

bool ParseAuthorityKeyIdentifier(
    der::Input extension_value,
    ParsedAuthorityKeyIdentifier *authority_key_identifier) {
  // RFC 5280, section 4.2.1.1.
  //    AuthorityKeyIdentifier ::= SEQUENCE {
  //       keyIdentifier             [0] KeyIdentifier           OPTIONAL,
  //       authorityCertIssuer       [1] GeneralNames            OPTIONAL,
  //       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
  //
  //    KeyIdentifier ::= OCTET STRING

  der::Parser extension_value_parser(extension_value);
  der::Parser aki_parser;
  if (!extension_value_parser.ReadSequence(&aki_parser)) {
    return false;
  }
  if (extension_value_parser.HasMore()) {
    return false;
  }

  // TODO(mattm): Should having an empty AuthorityKeyIdentifier SEQUENCE be an
  // error? RFC 5280 doesn't explicitly say it.

  //       keyIdentifier             [0] KeyIdentifier           OPTIONAL,
  if (!aki_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 0,
                                  &authority_key_identifier->key_identifier)) {
    return false;
  }

  //       authorityCertIssuer       [1] GeneralNames            OPTIONAL,
  if (!aki_parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1,
          &authority_key_identifier->authority_cert_issuer)) {
    return false;
  }

  //       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
  if (!aki_parser.ReadOptionalTag(
          CBS_ASN1_CONTEXT_SPECIFIC | 2,
          &authority_key_identifier->authority_cert_serial_number)) {
    return false;
  }

  //     -- authorityCertIssuer and authorityCertSerialNumber MUST both
  //     -- be present or both be absent
  if (authority_key_identifier->authority_cert_issuer.has_value() !=
      authority_key_identifier->authority_cert_serial_number.has_value()) {
    return false;
  }

  // There shouldn't be any unconsumed data in the AuthorityKeyIdentifier
  // SEQUENCE.
  if (aki_parser.HasMore()) {
    return false;
  }

  return true;
}

bool ParseSubjectKeyIdentifier(der::Input extension_value,
                               der::Input *subject_key_identifier) {
  //    SubjectKeyIdentifier ::= KeyIdentifier
  //
  //    KeyIdentifier ::= OCTET STRING
  der::Parser extension_value_parser(extension_value);
  if (!extension_value_parser.ReadTag(CBS_ASN1_OCTETSTRING,
                                      subject_key_identifier)) {
    return false;
  }

  // There shouldn't be any unconsumed data in the extension SEQUENCE.
  if (extension_value_parser.HasMore()) {
    return false;
  }

  return true;
}

}  // namespace bssl
