// 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.

#ifndef BSSL_PKI_PARSE_CERTIFICATE_H_
#define BSSL_PKI_PARSE_CERTIFICATE_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <vector>

#include <openssl/base.h>

#include "general_names.h"
#include "input.h"
#include "parse_values.h"

BSSL_NAMESPACE_BEGIN

namespace der {
class Parser;
}

class CertErrors;
struct ParsedTbsCertificate;

// Returns true if the given serial number (CertificateSerialNumber in RFC 5280)
// is valid:
//
//    CertificateSerialNumber  ::=  INTEGER
//
// The input to this function is the (unverified) value octets of the INTEGER.
// This function will verify that:
//
//   * The octets are a valid DER-encoding of an INTEGER (for instance, minimal
//     encoding length).
//
//   * No more than 20 octets are used.
//
// Note that it DOES NOT reject non-positive values (zero or negative).
//
// For reference, here is what RFC 5280 section 4.1.2.2 says:
//
//     Given the uniqueness requirements above, serial numbers can be
//     expected to contain long integers.  Certificate users MUST be able to
//     handle serialNumber values up to 20 octets.  Conforming CAs MUST NOT
//     use serialNumber values longer than 20 octets.
//
//     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.
//
// |errors| must be a non-null destination for any errors/warnings. If
// |warnings_only| is set to true, then what would ordinarily be errors are
// instead added as warnings.
[[nodiscard]] OPENSSL_EXPORT bool VerifySerialNumber(der::Input value,
                                                     bool warnings_only,
                                                     CertErrors *errors);

// Consumes a "Time" value (as defined by RFC 5280) from |parser|. On success
// writes the result to |*out| and returns true. On failure no guarantees are
// made about the state of |parser|.
//
// From RFC 5280:
//
//     Time ::= CHOICE {
//          utcTime        UTCTime,
//          generalTime    GeneralizedTime }
[[nodiscard]] OPENSSL_EXPORT bool ReadUTCOrGeneralizedTime(
    der::Parser *parser, der::GeneralizedTime *out);

// Parses a DER-encoded "Validity" as specified by RFC 5280. Returns true on
// success and sets the results in |not_before| and |not_after|:
//
//       Validity ::= SEQUENCE {
//            notBefore      Time,
//            notAfter       Time }
//
// Note that upon success it is NOT guaranteed that |*not_before <= *not_after|.
[[nodiscard]] OPENSSL_EXPORT bool ParseValidity(
    der::Input validity_tlv, der::GeneralizedTime *not_before,
    der::GeneralizedTime *not_after);

struct OPENSSL_EXPORT ParseCertificateOptions {
  // If set to true, then parsing will skip checks on the certificate's serial
  // number. The only requirement will be that the serial number is an INTEGER,
  // however it is not required to be a valid DER-encoding (i.e. minimal
  // encoding), nor is it required to be constrained to any particular length.
  bool allow_invalid_serial_numbers = false;
};

// Parses a DER-encoded "Certificate" as specified by RFC 5280. Returns true on
// success and sets the results in the |out_*| parameters. On both the failure
// and success case, if |out_errors| was non-null it may contain extra error
// information.
//
// Note that on success the out parameters alias data from the input
// |certificate_tlv|.  Hence the output values are only valid as long as
// |certificate_tlv| remains valid.
//
// On failure the out parameters have an undefined state, except for
// out_errors. Some of them may have been updated during parsing, whereas
// others may not have been changed.
//
// The out parameters represent each field of the Certificate SEQUENCE:
//       Certificate  ::=  SEQUENCE  {
//
// The |out_tbs_certificate_tlv| parameter corresponds with "tbsCertificate"
// from RFC 5280:
//         tbsCertificate       TBSCertificate,
//
// This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
// guarantees are made regarding the value of this SEQUENCE.
// This can be further parsed using ParseTbsCertificate().
//
// The |out_signature_algorithm_tlv| parameter corresponds with
// "signatureAlgorithm" from RFC 5280:
//         signatureAlgorithm   AlgorithmIdentifier,
//
// This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
// guarantees are made regarding the value of this SEQUENCE.
// This can be further parsed using SignatureValue::Create().
//
// The |out_signature_value| parameter corresponds with "signatureValue" from
// RFC 5280:
//         signatureValue       BIT STRING  }
//
// Parsing guarantees that this is a valid BIT STRING.
[[nodiscard]] OPENSSL_EXPORT 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);

// Parses a DER-encoded "TBSCertificate" as specified by RFC 5280. Returns true
// on success and sets the results in |out|. Certain invalid inputs may
// be accepted based on the provided |options|.
//
// If |errors| was non-null then any warnings/errors that occur during parsing
// are added to it.
//
// Note that on success |out| aliases data from the input |tbs_tlv|.
// Hence the fields of the ParsedTbsCertificate are only valid as long as
// |tbs_tlv| remains valid.
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
//
// Refer to the per-field documentation of ParsedTbsCertificate for details on
// what validity checks parsing performs.
//
//       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
//            }
[[nodiscard]] OPENSSL_EXPORT bool ParseTbsCertificate(
    der::Input tbs_tlv, const ParseCertificateOptions &options,
    ParsedTbsCertificate *out, CertErrors *errors);

// Represents a "Version" from RFC 5280:
//         Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
enum class CertificateVersion {
  V1,
  V2,
  V3,
};

// ParsedTbsCertificate contains pointers to the main fields of a DER-encoded
// RFC 5280 "TBSCertificate".
//
// ParsedTbsCertificate is expected to be filled by ParseTbsCertificate(), so
// subsequent field descriptions are in terms of what ParseTbsCertificate()
// sets.
struct OPENSSL_EXPORT ParsedTbsCertificate {
  ParsedTbsCertificate();
  ParsedTbsCertificate(ParsedTbsCertificate &&other);
  ParsedTbsCertificate &operator=(ParsedTbsCertificate &&other) = default;
  ~ParsedTbsCertificate();

  // Corresponds with "version" from RFC 5280:
  //         version         [0]  EXPLICIT Version DEFAULT v1,
  //
  // Parsing guarantees that the version is one of v1, v2, or v3.
  CertificateVersion version = CertificateVersion::V1;

  // Corresponds with "serialNumber" from RFC 5280:
  //         serialNumber         CertificateSerialNumber,
  //
  // This field specifically contains the content bytes of the INTEGER. So for
  // instance if the serial number was 1000 then this would contain bytes
  // {0x03, 0xE8}.
  //
  // The serial number may or may not be a valid DER-encoded INTEGER:
  //
  // If the option |allow_invalid_serial_numbers=true| was used during
  // parsing, then nothing further can be assumed about these bytes.
  //
  // Otherwise if |allow_invalid_serial_numbers=false| then in addition
  // to being a valid DER-encoded INTEGER, parsing guarantees that
  // the serial number is at most 20 bytes long. Parsing does NOT guarantee
  // that the integer is positive (might be zero or negative).
  der::Input serial_number;

  // Corresponds with "signatureAlgorithm" from RFC 5280:
  //         signatureAlgorithm   AlgorithmIdentifier,
  //
  // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
  // guarantees are made regarding the value of this SEQUENCE.
  //
  // This can be further parsed using SignatureValue::Create().
  der::Input signature_algorithm_tlv;

  // Corresponds with "issuer" from RFC 5280:
  //         issuer               Name,
  //
  // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
  // guarantees are made regarding the value of this SEQUENCE.
  der::Input issuer_tlv;

  // Corresponds with "validity" from RFC 5280:
  //         validity             Validity,
  //
  // Where Validity is defined as:
  //
  //   Validity ::= SEQUENCE {
  //        notBefore      Time,
  //        notAfter       Time }
  //
  // Parsing guarantees that notBefore (validity_not_before) and notAfter
  // (validity_not_after) are valid DER-encoded dates, however it DOES NOT
  // gurantee anything about their values. For instance notAfter could be
  // before notBefore, or the dates could indicate an expired certificate.
  // Consumers are responsible for testing expiration.
  der::GeneralizedTime validity_not_before;
  der::GeneralizedTime validity_not_after;

  // Corresponds with "subject" from RFC 5280:
  //         subject              Name,
  //
  // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
  // guarantees are made regarding the value of this SEQUENCE.
  der::Input subject_tlv;

  // Corresponds with "subjectPublicKeyInfo" from RFC 5280:
  //         subjectPublicKeyInfo SubjectPublicKeyInfo,
  //
  // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
  // guarantees are made regarding the value of this SEQUENCE.
  der::Input spki_tlv;

  // Corresponds with "issuerUniqueID" from RFC 5280:
  //         issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
  //                              -- If present, version MUST be v2 or v3
  //
  // Parsing guarantees that if issuer_unique_id is present it is a valid BIT
  // STRING, and that the version is either v2 or v3
  std::optional<der::BitString> issuer_unique_id;

  // Corresponds with "subjectUniqueID" from RFC 5280:
  //         subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
  //                              -- If present, version MUST be v2 or v3
  //
  // Parsing guarantees that if subject_unique_id is present it is a valid BIT
  // STRING, and that the version is either v2 or v3
  std::optional<der::BitString> subject_unique_id;

  // Corresponds with "extensions" from RFC 5280:
  //         extensions      [3]  EXPLICIT Extensions OPTIONAL
  //                              -- If present, version MUST be v3
  //
  //
  // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No
  // guarantees are made regarding the value of this SEQUENCE. (Note that the
  // EXPLICIT outer tag is stripped.)
  //
  // Parsing guarantees that if extensions is present the version is v3.
  std::optional<der::Input> extensions_tlv;
};

// ParsedExtension represents a parsed "Extension" from RFC 5280. It contains
// der:Inputs which are not owned so the associated data must be kept alive.
//
//    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
//            }
struct OPENSSL_EXPORT ParsedExtension {
  der::Input oid;
  // |value| will contain the contents of the OCTET STRING. For instance for
  // basicConstraints it will be the TLV for a SEQUENCE.
  der::Input value;
  bool critical = false;
};

// Parses a DER-encoded "Extension" as specified by RFC 5280. Returns true on
// success and sets the results in |out|.
//
// Note that on success |out| aliases data from the input |extension_tlv|.
// Hence the fields of the ParsedExtension are only valid as long as
// |extension_tlv| remains valid.
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
[[nodiscard]] OPENSSL_EXPORT bool ParseExtension(der::Input extension_tlv,
                                                 ParsedExtension *out);

// From RFC 5280:
//
//     id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 }
//
// In dotted notation: 2.5.29.14
inline constexpr uint8_t kSubjectKeyIdentifierOid[] = {0x55, 0x1d, 0x0e};

// From RFC 5280:
//
//     id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
//
// In dotted notation: 2.5.29.15
inline constexpr uint8_t kKeyUsageOid[] = {0x55, 0x1d, 0x0f};

// From RFC 5280:
//
//     id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 }
//
// In dotted notation: 2.5.29.17
inline constexpr uint8_t kSubjectAltNameOid[] = {0x55, 0x1d, 0x11};

// From RFC 5280:
//
//     id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 }
//
// In dotted notation: 2.5.29.19
inline constexpr uint8_t kBasicConstraintsOid[] = {0x55, 0x1d, 0x13};

// From RFC 5280:
//
//     id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 }
//
// In dotted notation: 2.5.29.30
inline constexpr uint8_t kNameConstraintsOid[] = {0x55, 0x1d, 0x1e};

// From RFC 5280:
//
//     id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }
//
// In dotted notation: 2.5.29.32
inline constexpr uint8_t kCertificatePoliciesOid[] = {0x55, 0x1d, 0x20};

// From RFC 5280:
//
//     id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
//
// In dotted notation: 2.5.29.35
inline constexpr uint8_t kAuthorityKeyIdentifierOid[] = {0x55, 0x1d, 0x23};

// From RFC 5280:
//
//     id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 }
//
// In dotted notation: 2.5.29.36
inline constexpr uint8_t kPolicyConstraintsOid[] = {0x55, 0x1d, 0x24};

// From RFC 5280:
//
//     id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
//
// In dotted notation: 2.5.29.37
inline constexpr uint8_t kExtKeyUsageOid[] = {0x55, 0x1d, 0x25};

// From RFC 5280:
//
//     id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
//
// In dotted notation: 1.3.6.1.5.5.7.1.1
inline constexpr uint8_t kAuthorityInfoAccessOid[] = {0x2B, 0x06, 0x01, 0x05,
                                                      0x05, 0x07, 0x01, 0x01};

// From RFC 5280:
//
//     id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
//
// In dotted notation: 1.3.6.1.5.5.7.48.2
inline constexpr uint8_t kAdCaIssuersOid[] = {0x2B, 0x06, 0x01, 0x05,
                                              0x05, 0x07, 0x30, 0x02};

// From RFC 5280:
//
//     id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
//
// In dotted notation: 1.3.6.1.5.5.7.48.1
inline constexpr uint8_t kAdOcspOid[] = {0x2B, 0x06, 0x01, 0x05,
                                         0x05, 0x07, 0x30, 0x01};

// From RFC 5280:
//
//     id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::=  { id-ce 31 }
//
// In dotted notation: 2.5.29.31
inline constexpr uint8_t kCrlDistributionPointsOid[] = {0x55, 0x1d, 0x1f};

// From RFC 6962:
//
// critical poison extension.
//
// In dotted notation 1.3.6.1.4.1.11129.2.4.3
inline constexpr uint8_t kCtPoisonOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
                                           0xD6, 0x79, 0x02, 0x04, 0x03};

// From
// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/supported-extensions#msapplicationpolicies
//
// OID: XCN_OID_APPLICATION_CERT_POLICIES (1.3.6.1.4.1.311.21.10)
inline constexpr uint8_t kMSApplicationPoliciesOid[] = {
    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x0a};

// Parses the Extensions sequence as defined by RFC 5280. Extensions are added
// to the map |extensions| keyed by the OID. Parsing guarantees that each OID
// is unique. Note that certificate verification must consume each extension
// marked as critical.
//
// Returns true on success and fills |extensions|. The output will reference
// bytes in |extensions_tlv|, so that data must be kept alive.
// On failure |extensions| may be partially written to and should not be used.
[[nodiscard]] OPENSSL_EXPORT bool ParseExtensions(
    der::Input extensions_tlv,
    std::map<der::Input, ParsedExtension> *extensions);

// Removes the extension with OID |oid| from |unconsumed_extensions| and fills
// |extension| with the matching extension value. If there was no extension
// matching |oid| then returns |false|.
[[nodiscard]] OPENSSL_EXPORT bool ConsumeExtension(
    der::Input oid,
    std::map<der::Input, ParsedExtension> *unconsumed_extensions,
    ParsedExtension *extension);

struct ParsedBasicConstraints {
  bool is_ca = false;
  bool has_path_len = false;
  uint8_t path_len = 0;
};

// Parses the BasicConstraints extension as defined by RFC 5280:
//
//    BasicConstraints ::= SEQUENCE {
//         cA                      BOOLEAN DEFAULT FALSE,
//         pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
//
// The maximum allowed value of pathLenConstraints will be whatever can fit
// into a uint8_t.
[[nodiscard]] OPENSSL_EXPORT bool ParseBasicConstraints(
    der::Input basic_constraints_tlv, ParsedBasicConstraints *out);

// KeyUsageBit contains the index for a particular key usage. The index is
// measured from the most significant bit of a bit string.
//
// From RFC 5280 section 4.2.1.3:
//
//     KeyUsage ::= BIT STRING {
//          digitalSignature        (0),
//          nonRepudiation          (1), -- recent editions of X.509 have
//                               -- renamed this bit to contentCommitment
//          keyEncipherment         (2),
//          dataEncipherment        (3),
//          keyAgreement            (4),
//          keyCertSign             (5),
//          cRLSign                 (6),
//          encipherOnly            (7),
//          decipherOnly            (8) }
enum KeyUsageBit {
  KEY_USAGE_BIT_DIGITAL_SIGNATURE = 0,
  KEY_USAGE_BIT_NON_REPUDIATION = 1,
  KEY_USAGE_BIT_KEY_ENCIPHERMENT = 2,
  KEY_USAGE_BIT_DATA_ENCIPHERMENT = 3,
  KEY_USAGE_BIT_KEY_AGREEMENT = 4,
  KEY_USAGE_BIT_KEY_CERT_SIGN = 5,
  KEY_USAGE_BIT_CRL_SIGN = 6,
  KEY_USAGE_BIT_ENCIPHER_ONLY = 7,
  KEY_USAGE_BIT_DECIPHER_ONLY = 8,
};

// Parses the KeyUsage extension as defined by RFC 5280. Returns true on
// success, and |key_usage| will alias data in |key_usage_tlv|. On failure
// returns false, and |key_usage| may have been modified.
//
// In addition to validating that key_usage_tlv is a BIT STRING, this does
// additional KeyUsage specific validations such as requiring at least 1 bit to
// be set.
//
// To test if a particular key usage is set, call, e.g.:
//     key_usage->AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE);
[[nodiscard]] OPENSSL_EXPORT bool ParseKeyUsage(der::Input key_usage_tlv,
                                                der::BitString *key_usage);

struct AuthorityInfoAccessDescription {
  // The accessMethod DER OID value.
  der::Input access_method_oid;
  // The accessLocation DER TLV.
  der::Input access_location;
};
// Parses the Authority Information Access extension defined by RFC 5280.
// Returns true on success, and |out_access_descriptions| will alias data
// in |authority_info_access_tlv|.On failure returns false, and
// out_access_descriptions may have been partially filled.
//
// No validation is performed on the contents of the
// AuthorityInfoAccessDescription fields.
[[nodiscard]] OPENSSL_EXPORT bool ParseAuthorityInfoAccess(
    der::Input authority_info_access_tlv,
    std::vector<AuthorityInfoAccessDescription> *out_access_descriptions);

// Parses the Authority Information Access extension defined by RFC 5280,
// extracting the caIssuers URIs and OCSP URIs.
//
// Returns true on success, and |out_ca_issuers_uris| and |out_ocsp_uris| will
// alias data in |authority_info_access_tlv|. On failure returns false, and
// |out_ca_issuers_uris| and |out_ocsp_uris| may have been partially filled.
//
// |out_ca_issuers_uris| is filled with the accessLocations of type
// uniformResourceIdentifier for the accessMethod id-ad-caIssuers.
// |out_ocsp_uris| is filled with the accessLocations of type
// uniformResourceIdentifier for the accessMethod id-ad-ocsp.
//
// The values in |out_ca_issuers_uris| and |out_ocsp_uris| are checked to be
// IA5String (ASCII strings), but no other validation is performed on them.
//
// accessMethods other than id-ad-caIssuers and id-ad-ocsp are silently ignored.
// accessLocation types other than uniformResourceIdentifier are silently
// ignored.
[[nodiscard]] OPENSSL_EXPORT 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);

// ParsedDistributionPoint represents a parsed DistributionPoint from RFC 5280.
//
//   DistributionPoint ::= SEQUENCE {
//    distributionPoint       [0]     DistributionPointName OPTIONAL,
//    reasons                 [1]     ReasonFlags OPTIONAL,
//    cRLIssuer               [2]     GeneralNames OPTIONAL }
struct OPENSSL_EXPORT ParsedDistributionPoint {
  ParsedDistributionPoint();
  ParsedDistributionPoint(ParsedDistributionPoint &&other);
  ~ParsedDistributionPoint();

  // The parsed fullName, if distributionPoint was present and was a fullName.
  std::unique_ptr<GeneralNames> distribution_point_fullname;

  // If present, the DER encoded value of the nameRelativeToCRLIssuer field.
  // This should be a RelativeDistinguishedName, but the parser does not
  // validate it.
  std::optional<der::Input> distribution_point_name_relative_to_crl_issuer;

  // If present, the DER encoded value of the reasons field. This should be a
  // ReasonFlags bitString, but the parser does not validate it.
  std::optional<der::Input> reasons;

  // If present, the DER encoded value of the cRLIssuer field. This should be a
  // GeneralNames, but the parser does not validate it.
  std::optional<der::Input> crl_issuer;
};

// Parses the value of a CRL Distribution Points extension (sequence of
// DistributionPoint). Return true on success, and fills |distribution_points|
// with values that reference data in |distribution_points_tlv|.
[[nodiscard]] OPENSSL_EXPORT bool ParseCrlDistributionPoints(
    der::Input distribution_points_tlv,
    std::vector<ParsedDistributionPoint> *distribution_points);

// Represents the AuthorityKeyIdentifier extension defined by RFC 5280 section
// 4.2.1.1.
//
//    AuthorityKeyIdentifier ::= SEQUENCE {
//       keyIdentifier             [0] KeyIdentifier           OPTIONAL,
//       authorityCertIssuer       [1] GeneralNames            OPTIONAL,
//       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
//
//    KeyIdentifier ::= OCTET STRING
struct OPENSSL_EXPORT ParsedAuthorityKeyIdentifier {
  ParsedAuthorityKeyIdentifier();
  ~ParsedAuthorityKeyIdentifier();
  ParsedAuthorityKeyIdentifier(ParsedAuthorityKeyIdentifier &&other);
  ParsedAuthorityKeyIdentifier &operator=(ParsedAuthorityKeyIdentifier &&other);

  // The keyIdentifier, which is an OCTET STRING.
  std::optional<der::Input> key_identifier;

  // The authorityCertIssuer, which should be a GeneralNames, but this is not
  // enforced by ParseAuthorityKeyIdentifier.
  std::optional<der::Input> authority_cert_issuer;

  // The DER authorityCertSerialNumber, which should be a
  // CertificateSerialNumber (an INTEGER) but this is not enforced by
  // ParseAuthorityKeyIdentifier.
  std::optional<der::Input> authority_cert_serial_number;
};

// Parses the value of an authorityKeyIdentifier extension. Returns true on
// success and fills |authority_key_identifier| with values that reference data
// in |extension_value|. On failure the state of |authority_key_identifier| is
// not guaranteed.
[[nodiscard]] OPENSSL_EXPORT bool ParseAuthorityKeyIdentifier(
    der::Input extension_value,
    ParsedAuthorityKeyIdentifier *authority_key_identifier);

// Parses the value of a subjectKeyIdentifier extension. Returns true on
// success and |subject_key_identifier| references data in |extension_value|.
// On failure the state of |subject_key_identifier| is not guaranteed.
[[nodiscard]] OPENSSL_EXPORT bool ParseSubjectKeyIdentifier(
    der::Input extension_value, der::Input *subject_key_identifier);

BSSL_NAMESPACE_END

#endif  // BSSL_PKI_PARSE_CERTIFICATE_H_
