// 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 "ocsp.h"

#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/mem.h>
#include <openssl/pool.h>
#include <openssl/sha.h>
#include "cert_errors.h"
#include "extended_key_usage.h"
#include "parsed_certificate.h"
#include "revocation_util.h"
#include "string_util.h"
#include "verify_name_match.h"
#include "verify_signed_data.h"

namespace bssl {

OCSPCertID::OCSPCertID() = default;
OCSPCertID::~OCSPCertID() = default;

OCSPSingleResponse::OCSPSingleResponse() = default;
OCSPSingleResponse::~OCSPSingleResponse() = default;

OCSPResponseData::OCSPResponseData() = default;
OCSPResponseData::~OCSPResponseData() = default;

OCSPResponse::OCSPResponse() = default;
OCSPResponse::~OCSPResponse() = default;

// CertID ::= SEQUENCE {
//    hashAlgorithm           AlgorithmIdentifier,
//    issuerNameHash          OCTET STRING, -- Hash of issuer's DN
//    issuerKeyHash           OCTET STRING, -- Hash of issuer's public key
//    serialNumber            CertificateSerialNumber
// }
bool ParseOCSPCertID(der::Input raw_tlv, OCSPCertID *out) {
  der::Parser outer_parser(raw_tlv);
  der::Parser parser;
  if (!outer_parser.ReadSequence(&parser)) {
    return false;
  }
  if (outer_parser.HasMore()) {
    return false;
  }

  der::Input sigalg_tlv;
  if (!parser.ReadRawTLV(&sigalg_tlv)) {
    return false;
  }
  if (!ParseHashAlgorithm(sigalg_tlv, &(out->hash_algorithm))) {
    return false;
  }
  if (!parser.ReadTag(der::kOctetString, &(out->issuer_name_hash))) {
    return false;
  }
  if (!parser.ReadTag(der::kOctetString, &(out->issuer_key_hash))) {
    return false;
  }
  if (!parser.ReadTag(der::kInteger, &(out->serial_number))) {
    return false;
  }
  CertErrors errors;
  if (!VerifySerialNumber(out->serial_number, false /*warnings_only*/,
                          &errors)) {
    return false;
  }

  return !parser.HasMore();
}

namespace {

// Parses |raw_tlv| to extract an OCSP RevokedInfo (RFC 6960) and stores the
// result in the OCSPCertStatus |out|. Returns whether the parsing was
// successful.
//
// RevokedInfo ::= SEQUENCE {
//      revocationTime              GeneralizedTime,
//      revocationReason    [0]     EXPLICIT CRLReason OPTIONAL
// }
bool ParseRevokedInfo(der::Input raw_tlv, OCSPCertStatus *out) {
  der::Parser parser(raw_tlv);
  if (!parser.ReadGeneralizedTime(&(out->revocation_time))) {
    return false;
  }

  der::Input reason_input;
  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &reason_input,
                              &(out->has_reason))) {
    return false;
  }
  if (out->has_reason) {
    der::Parser reason_parser(reason_input);
    der::Input reason_value_input;
    uint8_t reason_value;
    if (!reason_parser.ReadTag(der::kEnumerated, &reason_value_input)) {
      return false;
    }
    if (!der::ParseUint8(reason_value_input, &reason_value)) {
      return false;
    }
    if (reason_value >
        static_cast<uint8_t>(OCSPCertStatus::RevocationReason::LAST)) {
      return false;
    }
    out->revocation_reason =
        static_cast<OCSPCertStatus::RevocationReason>(reason_value);
    if (out->revocation_reason == OCSPCertStatus::RevocationReason::UNUSED) {
      return false;
    }
    if (reason_parser.HasMore()) {
      return false;
    }
  }
  return !parser.HasMore();
}

// Parses |raw_tlv| to extract an OCSP CertStatus (RFC 6960) and stores the
// result in the OCSPCertStatus |out|. Returns whether the parsing was
// successful.
//
// CertStatus ::= CHOICE {
//      good        [0]     IMPLICIT NULL,
//      revoked     [1]     IMPLICIT RevokedInfo,
//      unknown     [2]     IMPLICIT UnknownInfo
// }
//
// UnknownInfo ::= NULL
bool ParseCertStatus(der::Input raw_tlv, OCSPCertStatus *out) {
  der::Parser parser(raw_tlv);
  der::Tag status_tag;
  der::Input status;
  if (!parser.ReadTagAndValue(&status_tag, &status)) {
    return false;
  }

  out->has_reason = false;
  if (status_tag == der::ContextSpecificPrimitive(0)) {
    out->status = OCSPRevocationStatus::GOOD;
  } else if (status_tag == der::ContextSpecificConstructed(1)) {
    out->status = OCSPRevocationStatus::REVOKED;
    if (!ParseRevokedInfo(status, out)) {
      return false;
    }
  } else if (status_tag == der::ContextSpecificPrimitive(2)) {
    out->status = OCSPRevocationStatus::UNKNOWN;
  } else {
    return false;
  }

  return !parser.HasMore();
}

// Writes the hash of |value| as an OCTET STRING to |cbb|, using |hash_type| as
// the algorithm. Returns true on success.
bool AppendHashAsOctetString(const EVP_MD *hash_type, CBB *cbb,
                             der::Input value) {
  CBB octet_string;
  unsigned hash_len;
  uint8_t hash_buffer[EVP_MAX_MD_SIZE];

  return CBB_add_asn1(cbb, &octet_string, CBS_ASN1_OCTETSTRING) &&
         EVP_Digest(value.data(), value.size(), hash_buffer, &hash_len,
                    hash_type, nullptr) &&
         CBB_add_bytes(&octet_string, hash_buffer, hash_len) && CBB_flush(cbb);
}

}  // namespace

// SingleResponse ::= SEQUENCE {
//      certID                       CertID,
//      certStatus                   CertStatus,
//      thisUpdate                   GeneralizedTime,
//      nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
//      singleExtensions   [1]       EXPLICIT Extensions OPTIONAL
// }
bool ParseOCSPSingleResponse(der::Input raw_tlv, OCSPSingleResponse *out) {
  der::Parser outer_parser(raw_tlv);
  der::Parser parser;
  if (!outer_parser.ReadSequence(&parser)) {
    return false;
  }
  if (outer_parser.HasMore()) {
    return false;
  }

  if (!parser.ReadRawTLV(&(out->cert_id_tlv))) {
    return false;
  }
  der::Input status_tlv;
  if (!parser.ReadRawTLV(&status_tlv)) {
    return false;
  }
  if (!ParseCertStatus(status_tlv, &(out->cert_status))) {
    return false;
  }
  if (!parser.ReadGeneralizedTime(&(out->this_update))) {
    return false;
  }

  der::Input next_update_input;
  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
                              &next_update_input, &(out->has_next_update))) {
    return false;
  }
  if (out->has_next_update) {
    der::Parser next_update_parser(next_update_input);
    if (!next_update_parser.ReadGeneralizedTime(&(out->next_update))) {
      return false;
    }
    if (next_update_parser.HasMore()) {
      return false;
    }
  }

  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
                              &(out->extensions), &(out->has_extensions))) {
    return false;
  }

  return !parser.HasMore();
}

namespace {

// Parses |raw_tlv| to extract a ResponderID (RFC 6960) and stores the
// result in the ResponderID |out|. Returns whether the parsing was successful.
//
// ResponderID ::= CHOICE {
//      byName               [1] Name,
//      byKey                [2] KeyHash
// }
bool ParseResponderID(der::Input raw_tlv, OCSPResponseData::ResponderID *out) {
  der::Parser parser(raw_tlv);
  der::Tag id_tag;
  der::Input id_input;
  if (!parser.ReadTagAndValue(&id_tag, &id_input)) {
    return false;
  }

  if (id_tag == der::ContextSpecificConstructed(1)) {
    out->type = OCSPResponseData::ResponderType::NAME;
    out->name = id_input;
  } else if (id_tag == der::ContextSpecificConstructed(2)) {
    der::Parser key_parser(id_input);
    der::Input key_hash;
    if (!key_parser.ReadTag(der::kOctetString, &key_hash)) {
      return false;
    }
    if (key_parser.HasMore()) {
      return false;
    }
    if (key_hash.size() != SHA_DIGEST_LENGTH) {
      return false;
    }

    out->type = OCSPResponseData::ResponderType::KEY_HASH;
    out->key_hash = key_hash;
  } else {
    return false;
  }
  return !parser.HasMore();
}

}  // namespace

// ResponseData ::= SEQUENCE {
//      version              [0] EXPLICIT Version DEFAULT v1,
//      responderID              ResponderID,
//      producedAt               GeneralizedTime,
//      responses                SEQUENCE OF SingleResponse,
//      responseExtensions   [1] EXPLICIT Extensions OPTIONAL
// }
bool ParseOCSPResponseData(der::Input raw_tlv, OCSPResponseData *out) {
  der::Parser outer_parser(raw_tlv);
  der::Parser parser;
  if (!outer_parser.ReadSequence(&parser)) {
    return false;
  }
  if (outer_parser.HasMore()) {
    return false;
  }

  der::Input version_input;
  bool version_present;
  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
                              &version_input, &version_present)) {
    return false;
  }

  // For compatibilty, we ignore the restriction from X.690 Section 11.5 that
  // DEFAULT values should be omitted for values equal to the default value.
  // TODO: Add warning about non-strict parsing.
  if (version_present) {
    der::Parser version_parser(version_input);
    if (!version_parser.ReadUint8(&(out->version))) {
      return false;
    }
    if (version_parser.HasMore()) {
      return false;
    }
  } else {
    out->version = 0;
  }

  if (out->version != 0) {
    return false;
  }

  der::Input responder_input;
  if (!parser.ReadRawTLV(&responder_input)) {
    return false;
  }
  if (!ParseResponderID(responder_input, &(out->responder_id))) {
    return false;
  }
  if (!parser.ReadGeneralizedTime(&(out->produced_at))) {
    return false;
  }

  der::Parser responses_parser;
  if (!parser.ReadSequence(&responses_parser)) {
    return false;
  }
  out->responses.clear();
  while (responses_parser.HasMore()) {
    der::Input single_response;
    if (!responses_parser.ReadRawTLV(&single_response)) {
      return false;
    }
    out->responses.push_back(single_response);
  }

  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
                              &(out->extensions), &(out->has_extensions))) {
    return false;
  }

  return !parser.HasMore();
}

namespace {

// Parses |raw_tlv| to extract a BasicOCSPResponse (RFC 6960) and stores the
// result in the OCSPResponse |out|. Returns whether the parsing was
// successful.
//
// BasicOCSPResponse       ::= SEQUENCE {
//      tbsResponseData      ResponseData,
//      signatureAlgorithm   AlgorithmIdentifier,
//      signature            BIT STRING,
//      certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
// }
bool ParseBasicOCSPResponse(der::Input raw_tlv, OCSPResponse *out) {
  der::Parser outer_parser(raw_tlv);
  der::Parser parser;
  if (!outer_parser.ReadSequence(&parser)) {
    return false;
  }
  if (outer_parser.HasMore()) {
    return false;
  }

  if (!parser.ReadRawTLV(&(out->data))) {
    return false;
  }
  der::Input sigalg_tlv;
  if (!parser.ReadRawTLV(&sigalg_tlv)) {
    return false;
  }
  // TODO(crbug.com/634443): Propagate the errors.
  std::optional<SignatureAlgorithm> sigalg =
      ParseSignatureAlgorithm(sigalg_tlv);
  if (!sigalg) {
    return false;
  }
  out->signature_algorithm = sigalg.value();
  std::optional<der::BitString> signature = parser.ReadBitString();
  if (!signature) {
    return false;
  }
  out->signature = signature.value();
  der::Input certs_input;
  if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &certs_input,
                              &(out->has_certs))) {
    return false;
  }

  out->certs.clear();
  if (out->has_certs) {
    der::Parser certs_seq_parser(certs_input);
    der::Parser certs_parser;
    if (!certs_seq_parser.ReadSequence(&certs_parser)) {
      return false;
    }
    if (certs_seq_parser.HasMore()) {
      return false;
    }
    while (certs_parser.HasMore()) {
      der::Input cert_tlv;
      if (!certs_parser.ReadRawTLV(&cert_tlv)) {
        return false;
      }
      out->certs.push_back(cert_tlv);
    }
  }

  return !parser.HasMore();
}

}  // namespace

// OCSPResponse ::= SEQUENCE {
//      responseStatus         OCSPResponseStatus,
//      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL
// }
//
// ResponseBytes ::=       SEQUENCE {
//      responseType   OBJECT IDENTIFIER,
//      response       OCTET STRING
// }
bool ParseOCSPResponse(der::Input raw_tlv, OCSPResponse *out) {
  der::Parser outer_parser(raw_tlv);
  der::Parser parser;
  if (!outer_parser.ReadSequence(&parser)) {
    return false;
  }
  if (outer_parser.HasMore()) {
    return false;
  }

  der::Input response_status_input;
  uint8_t response_status;
  if (!parser.ReadTag(der::kEnumerated, &response_status_input)) {
    return false;
  }
  if (!der::ParseUint8(response_status_input, &response_status)) {
    return false;
  }
  if (response_status >
      static_cast<uint8_t>(OCSPResponse::ResponseStatus::LAST)) {
    return false;
  }
  out->status = static_cast<OCSPResponse::ResponseStatus>(response_status);
  if (out->status == OCSPResponse::ResponseStatus::UNUSED) {
    return false;
  }

  if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) {
    der::Parser outer_bytes_parser;
    der::Parser bytes_parser;
    if (!parser.ReadConstructed(der::ContextSpecificConstructed(0),
                                &outer_bytes_parser)) {
      return false;
    }
    if (!outer_bytes_parser.ReadSequence(&bytes_parser)) {
      return false;
    }
    if (outer_bytes_parser.HasMore()) {
      return false;
    }

    der::Input type_oid;
    if (!bytes_parser.ReadTag(der::kOid, &type_oid)) {
      return false;
    }
    if (type_oid != der::Input(kBasicOCSPResponseOid)) {
      return false;
    }

    // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER
    // encoding of BasicOCSPResponse.
    der::Input response;
    if (!bytes_parser.ReadTag(der::kOctetString, &response)) {
      return false;
    }
    if (!ParseBasicOCSPResponse(response, out)) {
      return false;
    }
    if (bytes_parser.HasMore()) {
      return false;
    }
  }

  return !parser.HasMore();
}

namespace {

// Checks that the |type| hash of |value| is equal to |hash|
bool VerifyHash(const EVP_MD *type, der::Input hash, der::Input value) {
  unsigned value_hash_len;
  uint8_t value_hash[EVP_MAX_MD_SIZE];
  if (!EVP_Digest(value.data(), value.size(), value_hash, &value_hash_len, type,
                  nullptr)) {
    return false;
  }

  return hash == der::Input(value_hash, value_hash_len);
}

// Extracts the bytes of the SubjectPublicKey bit string given an SPKI. That is
// to say, the value of subjectPublicKey without the leading unused bit
// count octet.
//
// Returns true on success and fills |*spk_tlv| with the result.
//
// From RFC 5280, Section 4.1
//   SubjectPublicKeyInfo  ::=  SEQUENCE  {
//     algorithm            AlgorithmIdentifier,
//     subjectPublicKey     BIT STRING  }
//
//   AlgorithmIdentifier  ::=  SEQUENCE  {
//     algorithm               OBJECT IDENTIFIER,
//     parameters              ANY DEFINED BY algorithm OPTIONAL  }
//
bool GetSubjectPublicKeyBytes(der::Input spki_tlv, der::Input *spk_tlv) {
  CBS outer, inner, alg, spk;
  uint8_t unused_bit_count;
  CBS_init(&outer, spki_tlv.data(), spki_tlv.size());
  //   The subjectPublicKey field includes the unused bit count. For this
  //   application, the unused bit count must be zero, and is not included in
  //   the result. We extract the subjectPubicKey bit string, verify the first
  //   byte is 0, and if so set |spk_tlv| to the remaining bytes.
  if (!CBS_get_asn1(&outer, &inner, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1(&inner, &alg, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1(&inner, &spk, CBS_ASN1_BITSTRING) ||
      !CBS_get_u8(&spk, &unused_bit_count) || unused_bit_count != 0) {
    return false;
  }
  *spk_tlv = der::Input(CBS_data(&spk), CBS_len(&spk));
  return true;
}

// Checks the OCSPCertID |id| identifies |certificate|.
bool CheckCertIDMatchesCertificate(
    const OCSPCertID &id, const ParsedCertificate *certificate,
    const ParsedCertificate *issuer_certificate) {
  const EVP_MD *type = nullptr;
  switch (id.hash_algorithm) {
    case DigestAlgorithm::Md2:
    case DigestAlgorithm::Md4:
    case DigestAlgorithm::Md5:
      // Unsupported.
      return false;
    case DigestAlgorithm::Sha1:
      type = EVP_sha1();
      break;
    case DigestAlgorithm::Sha256:
      type = EVP_sha256();
      break;
    case DigestAlgorithm::Sha384:
      type = EVP_sha384();
      break;
    case DigestAlgorithm::Sha512:
      type = EVP_sha512();
      break;
  }

  if (!VerifyHash(type, id.issuer_name_hash, certificate->tbs().issuer_tlv)) {
    return false;
  }

  der::Input key_tlv;
  if (!GetSubjectPublicKeyBytes(issuer_certificate->tbs().spki_tlv, &key_tlv)) {
    return false;
  }

  if (!VerifyHash(type, id.issuer_key_hash, key_tlv)) {
    return false;
  }

  return id.serial_number == certificate->tbs().serial_number;
}

// TODO(eroman): Revisit how certificate parsing is used by this file. Ideally
// would either pass in the parsed bits, or have a better abstraction for lazily
// parsing.
std::shared_ptr<const ParsedCertificate> OCSPParseCertificate(
    std::string_view der) {
  ParseCertificateOptions parse_options;
  parse_options.allow_invalid_serial_numbers = true;

  // The objects returned by this function only last for the duration of a
  // single certificate verification, so there is no need to pool them to save
  // memory.
  //
  // TODO(eroman): Swallows the parsing errors. However uses a permissive
  // parsing model.
  CertErrors errors;
  return ParsedCertificate::Create(
      bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
          reinterpret_cast<const uint8_t *>(der.data()), der.size(), nullptr)),
      {}, &errors);
}

// Checks that the ResponderID |id| matches the certificate |cert| either
// by verifying the name matches that of the certificate or that the hash
// matches the certificate's public key hash (RFC 6960, 4.2.2.3).
[[nodiscard]] bool CheckResponderIDMatchesCertificate(
    const OCSPResponseData::ResponderID &id, const ParsedCertificate *cert) {
  switch (id.type) {
    case OCSPResponseData::ResponderType::NAME: {
      der::Input name_rdn;
      der::Input cert_rdn;
      if (!der::Parser(id.name).ReadTag(der::kSequence, &name_rdn) ||
          !der::Parser(cert->tbs().subject_tlv)
               .ReadTag(der::kSequence, &cert_rdn)) {
        return false;
      }
      return VerifyNameMatch(name_rdn, cert_rdn);
    }
    case OCSPResponseData::ResponderType::KEY_HASH: {
      der::Input key;
      if (!GetSubjectPublicKeyBytes(cert->tbs().spki_tlv, &key)) {
        return false;
      }
      return VerifyHash(EVP_sha1(), id.key_hash, key);
    }
  }

  return false;
}

// Verifies that |responder_certificate| has been authority for OCSP signing,
// delegated to it by |issuer_certificate|.
//
// TODO(eroman): No revocation checks are done (see id-pkix-ocsp-nocheck in the
//     spec). extension).
//
// TODO(eroman): Not all properties of the certificate are verified, only the
//     signature and EKU. Can full RFC 5280 validation be used, or are there
//     compatibility concerns?
[[nodiscard]] bool VerifyAuthorizedResponderCert(
    const ParsedCertificate *responder_certificate,
    const ParsedCertificate *issuer_certificate) {
  // The Authorized Responder must be directly signed by the issuer of the
  // certificate being checked.
  // TODO(eroman): Must check the signature algorithm against policy.
  if (!responder_certificate->signature_algorithm().has_value() ||
      !VerifySignedData(*responder_certificate->signature_algorithm(),
                        responder_certificate->tbs_certificate_tlv(),
                        responder_certificate->signature_value(),
                        issuer_certificate->tbs().spki_tlv,
                        /*cache=*/nullptr)) {
    return false;
  }

  // The Authorized Responder must include the value id-kp-OCSPSigning as
  // part of the extended key usage extension.
  if (!responder_certificate->has_extended_key_usage()) {
    return false;
  }

  for (const auto &key_purpose_oid :
       responder_certificate->extended_key_usage()) {
    if (key_purpose_oid == der::Input(kOCSPSigning)) {
      return true;
    }
  }
  return false;
}

[[nodiscard]] bool VerifyOCSPResponseSignatureGivenCert(
    const OCSPResponse &response, const ParsedCertificate *cert) {
  // TODO(eroman): Must check the signature algorithm against policy.
  return VerifySignedData(response.signature_algorithm, response.data,
                          response.signature, cert->tbs().spki_tlv,
                          /*cache=*/nullptr);
}

// Verifies that the OCSP response has a valid signature using
// |issuer_certificate|, or an authorized responder issued by
// |issuer_certificate| for OCSP signing.
[[nodiscard]] bool VerifyOCSPResponseSignature(
    const OCSPResponse &response, const OCSPResponseData &response_data,
    const ParsedCertificate *issuer_certificate) {
  // In order to verify the OCSP signature, a valid responder matching the OCSP
  // Responder ID must be located (RFC 6960, 4.2.2.2). The responder is allowed
  // to be either the certificate issuer or a delegated authority directly
  // signed by the issuer.
  if (CheckResponderIDMatchesCertificate(response_data.responder_id,
                                         issuer_certificate) &&
      VerifyOCSPResponseSignatureGivenCert(response, issuer_certificate)) {
    return true;
  }

  // Otherwise search through the provided certificates for the Authorized
  // Responder. Want a certificate that:
  //  (1) Matches the OCSP Responder ID.
  //  (2) Has been given authority for OCSP signing by |issuer_certificate|.
  //  (3) Has signed the OCSP response using its public key.
  for (const auto &responder_cert_tlv : response.certs) {
    std::shared_ptr<const ParsedCertificate> cur_responder_certificate =
        OCSPParseCertificate(responder_cert_tlv.AsStringView());

    // If failed parsing the certificate, keep looking.
    if (!cur_responder_certificate) {
      continue;
    }

    // If the certificate doesn't match the OCSP's responder ID, keep looking.
    if (!CheckResponderIDMatchesCertificate(response_data.responder_id,
                                            cur_responder_certificate.get())) {
      continue;
    }

    // If the certificate isn't a valid Authorized Responder certificate, keep
    // looking.
    if (!VerifyAuthorizedResponderCert(cur_responder_certificate.get(),
                                       issuer_certificate)) {
      continue;
    }

    // If the certificate signed this OCSP response, have found a match.
    // Otherwise keep looking.
    if (VerifyOCSPResponseSignatureGivenCert(response,
                                             cur_responder_certificate.get())) {
      return true;
    }
  }

  // Failed to confirm the validity of the OCSP signature using any of the
  // candidate certificates.
  return false;
}

// Parse ResponseData and return false if any unhandled critical extensions are
// found. No known critical ResponseData extensions exist.
bool ParseOCSPResponseDataExtensions(
    der::Input response_extensions,
    OCSPVerifyResult::ResponseStatus *response_details) {
  std::map<der::Input, ParsedExtension> extensions;
  if (!ParseExtensions(response_extensions, &extensions)) {
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
    return false;
  }

  for (const auto &ext : extensions) {
    // TODO: handle ResponseData extensions

    if (ext.second.critical) {
      *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
      return false;
    }
  }

  return true;
}

// Parse SingleResponse and return false if any unhandled critical extensions
// (other than the CT extension) are found. The CT-SCT extension is not required
// to be marked critical, but since it is handled by Chrome, we will overlook
// the flag setting.
bool ParseOCSPSingleResponseExtensions(
    der::Input single_extensions,
    OCSPVerifyResult::ResponseStatus *response_details) {
  std::map<der::Input, ParsedExtension> extensions;
  if (!ParseExtensions(single_extensions, &extensions)) {
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
    return false;
  }

  // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for
  // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see
  // Section 3.3 of RFC6962.
  const uint8_t ct_ocsp_ext_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
                                     0xD6, 0x79, 0x02, 0x04, 0x05};
  der::Input ct_ext_oid(ct_ocsp_ext_oid);

  for (const auto &ext : extensions) {
    // The CT OCSP extension is handled in ct::ExtractSCTListFromOCSPResponse
    if (ext.second.oid == ct_ext_oid) {
      continue;
    }

    // TODO: handle SingleResponse extensions

    if (ext.second.critical) {
      *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
      return false;
    }
  }

  return true;
}

// Loops through the OCSPSingleResponses to find the best match for |cert|.
OCSPRevocationStatus GetRevocationStatusForCert(
    const OCSPResponseData &response_data, const ParsedCertificate *cert,
    const ParsedCertificate *issuer_certificate,
    int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
    OCSPVerifyResult::ResponseStatus *response_details) {
  OCSPRevocationStatus result = OCSPRevocationStatus::UNKNOWN;
  *response_details = OCSPVerifyResult::NO_MATCHING_RESPONSE;

  for (const auto &single_response_der : response_data.responses) {
    // In the common case, there should only be one SingleResponse in the
    // ResponseData (matching the certificate requested and used on this
    // connection). However, it is possible for the OCSP responder to provide
    // multiple responses for multiple certificates. Look through all the
    // provided SingleResponses, and check to see if any match the
    // certificate. A SingleResponse matches a certificate if it has the same
    // serial number, issuer name (hash), and issuer public key (hash).
    OCSPSingleResponse single_response;
    if (!ParseOCSPSingleResponse(single_response_der, &single_response)) {
      return OCSPRevocationStatus::UNKNOWN;
    }

    // Reject unhandled critical extensions in SingleResponse
    if (single_response.has_extensions &&
        !ParseOCSPSingleResponseExtensions(single_response.extensions,
                                           response_details)) {
      return OCSPRevocationStatus::UNKNOWN;
    }

    OCSPCertID cert_id;
    if (!ParseOCSPCertID(single_response.cert_id_tlv, &cert_id)) {
      return OCSPRevocationStatus::UNKNOWN;
    }
    if (!CheckCertIDMatchesCertificate(cert_id, cert, issuer_certificate)) {
      continue;
    }

    // The SingleResponse matches the certificate, but may be out of date. Out
    // of date responses are noted seperate from responses with mismatched
    // serial numbers. If an OCSP responder provides both an up to date
    // response and an expired response, the up to date response takes
    // precedence (PROVIDED > INVALID_DATE).
    if (!CheckRevocationDateValid(single_response.this_update,
                                  single_response.has_next_update
                                      ? &single_response.next_update
                                      : nullptr,
                                  verify_time_epoch_seconds, max_age_seconds)) {
      if (*response_details != OCSPVerifyResult::PROVIDED) {
        *response_details = OCSPVerifyResult::INVALID_DATE;
      }
      continue;
    }

    // In the case with multiple matching and up to date responses, keep only
    // the strictest status (REVOKED > UNKNOWN > GOOD).
    if (*response_details != OCSPVerifyResult::PROVIDED ||
        result == OCSPRevocationStatus::GOOD ||
        single_response.cert_status.status == OCSPRevocationStatus::REVOKED) {
      result = single_response.cert_status.status;
    }
    *response_details = OCSPVerifyResult::PROVIDED;
  }

  return result;
}

OCSPRevocationStatus CheckOCSP(
    std::string_view raw_response, std::string_view certificate_der,
    const ParsedCertificate *certificate,
    std::string_view issuer_certificate_der,
    const ParsedCertificate *issuer_certificate,
    int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
    OCSPVerifyResult::ResponseStatus *response_details) {
  *response_details = OCSPVerifyResult::NOT_CHECKED;

  if (raw_response.empty()) {
    *response_details = OCSPVerifyResult::MISSING;
    return OCSPRevocationStatus::UNKNOWN;
  }

  der::Input response_der(raw_response);
  OCSPResponse response;
  if (!ParseOCSPResponse(response_der, &response)) {
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_ERROR;
    return OCSPRevocationStatus::UNKNOWN;
  }

  // RFC 6960 defines all responses |response_status| != SUCCESSFUL as error
  // responses. No revocation information is provided on error responses, and
  // the OCSPResponseData structure is not set.
  if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) {
    *response_details = OCSPVerifyResult::ERROR_RESPONSE;
    return OCSPRevocationStatus::UNKNOWN;
  }

  // Actual revocation information is contained within the BasicOCSPResponse as
  // a ResponseData structure. The BasicOCSPResponse was parsed above, and
  // contains an unparsed ResponseData. From RFC 6960:
  //
  // BasicOCSPResponse       ::= SEQUENCE {
  //    tbsResponseData      ResponseData,
  //    signatureAlgorithm   AlgorithmIdentifier,
  //    signature            BIT STRING,
  //    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
  //
  // ResponseData ::= SEQUENCE {
  //     version              [0] EXPLICIT Version DEFAULT v1,
  //     responderID              ResponderID,
  //     producedAt               GeneralizedTime,
  //     responses                SEQUENCE OF SingleResponse,
  //     responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
  OCSPResponseData response_data;
  if (!ParseOCSPResponseData(response.data, &response_data)) {
    *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
    return OCSPRevocationStatus::UNKNOWN;
  }

  // Process the OCSP ResponseData extensions. In particular, must reject if
  // there are any critical extensions that are not understood.
  if (response_data.has_extensions &&
      !ParseOCSPResponseDataExtensions(response_data.extensions,
                                       response_details)) {
    return OCSPRevocationStatus::UNKNOWN;
  }

  std::shared_ptr<const ParsedCertificate> parsed_certificate;
  std::shared_ptr<const ParsedCertificate> parsed_issuer_certificate;
  if (!certificate) {
    parsed_certificate = OCSPParseCertificate(certificate_der);
    certificate = parsed_certificate.get();
  }
  if (!issuer_certificate) {
    parsed_issuer_certificate = OCSPParseCertificate(issuer_certificate_der);
    issuer_certificate = parsed_issuer_certificate.get();
  }

  if (!certificate || !issuer_certificate) {
    *response_details = OCSPVerifyResult::NOT_CHECKED;
    return OCSPRevocationStatus::UNKNOWN;
  }

  // If producedAt is outside of the certificate validity period, reject the
  // response.
  if (response_data.produced_at < certificate->tbs().validity_not_before ||
      response_data.produced_at > certificate->tbs().validity_not_after) {
    *response_details = OCSPVerifyResult::BAD_PRODUCED_AT;
    return OCSPRevocationStatus::UNKNOWN;
  }

  // Look through all of the OCSPSingleResponses for a match (based on CertID
  // and time).
  OCSPRevocationStatus status = GetRevocationStatusForCert(
      response_data, certificate, issuer_certificate, verify_time_epoch_seconds,
      max_age_seconds, response_details);

  // Check that the OCSP response has a valid signature. It must either be
  // signed directly by the issuing certificate, or a valid authorized
  // responder.
  if (!VerifyOCSPResponseSignature(response, response_data,
                                   issuer_certificate)) {
    return OCSPRevocationStatus::UNKNOWN;
  }

  return status;
}

}  // namespace

OCSPRevocationStatus CheckOCSP(
    std::string_view raw_response, std::string_view certificate_der,
    std::string_view issuer_certificate_der, int64_t verify_time_epoch_seconds,
    std::optional<int64_t> max_age_seconds,
    OCSPVerifyResult::ResponseStatus *response_details) {
  return CheckOCSP(raw_response, certificate_der, nullptr,
                   issuer_certificate_der, nullptr, verify_time_epoch_seconds,
                   max_age_seconds, response_details);
}

OCSPRevocationStatus CheckOCSP(
    std::string_view raw_response, const ParsedCertificate *certificate,
    const ParsedCertificate *issuer_certificate,
    int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
    OCSPVerifyResult::ResponseStatus *response_details) {
  return CheckOCSP(raw_response, std::string_view(), certificate,
                   std::string_view(), issuer_certificate,
                   verify_time_epoch_seconds, max_age_seconds,
                   response_details);
}

bool CreateOCSPRequest(const ParsedCertificate *cert,
                       const ParsedCertificate *issuer,
                       std::vector<uint8_t> *request_der) {
  request_der->clear();

  bssl::ScopedCBB cbb;

  // This initial buffer size is big enough for 20 octet long serial numbers
  // (upper bound from RFC 5280) and then a handful of extra bytes. This
  // number doesn't matter for correctness.
  const size_t kInitialBufferSize = 100;

  if (!CBB_init(cbb.get(), kInitialBufferSize)) {
    return false;
  }

  //   OCSPRequest     ::=     SEQUENCE {
  //       tbsRequest                  TBSRequest,
  //       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
  //
  //   TBSRequest      ::=     SEQUENCE {
  //       version             [0]     EXPLICIT Version DEFAULT v1,
  //       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
  //       requestList                 SEQUENCE OF Request,
  //       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
  CBB ocsp_request;
  if (!CBB_add_asn1(cbb.get(), &ocsp_request, CBS_ASN1_SEQUENCE)) {
    return false;
  }

  CBB tbs_request;
  if (!CBB_add_asn1(&ocsp_request, &tbs_request, CBS_ASN1_SEQUENCE)) {
    return false;
  }

  // "version", "requestorName", and "requestExtensions" are omitted.

  CBB request_list;
  if (!CBB_add_asn1(&tbs_request, &request_list, CBS_ASN1_SEQUENCE)) {
    return false;
  }

  CBB request;
  if (!CBB_add_asn1(&request_list, &request, CBS_ASN1_SEQUENCE)) {
    return false;
  }

  //   Request         ::=     SEQUENCE {
  //       reqCert                     CertID,
  //       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
  CBB req_cert;
  if (!CBB_add_asn1(&request, &req_cert, CBS_ASN1_SEQUENCE)) {
    return false;
  }

  //   CertID          ::=     SEQUENCE {
  //       hashAlgorithm       AlgorithmIdentifier,
  //       issuerNameHash      OCTET STRING, -- Hash of issuer's DN
  //       issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
  //       serialNumber        CertificateSerialNumber }

  // TODO(eroman): Don't use SHA1.
  const EVP_MD *md = EVP_sha1();
  if (!EVP_marshal_digest_algorithm(&req_cert, md)) {
    return false;
  }

  AppendHashAsOctetString(md, &req_cert, issuer->tbs().subject_tlv);

  der::Input key_tlv;
  if (!GetSubjectPublicKeyBytes(issuer->tbs().spki_tlv, &key_tlv)) {
    return false;
  }
  AppendHashAsOctetString(md, &req_cert, key_tlv);

  CBB serial_number;
  if (!CBB_add_asn1(&req_cert, &serial_number, CBS_ASN1_INTEGER)) {
    return false;
  }
  if (!CBB_add_bytes(&serial_number, cert->tbs().serial_number.data(),
                     cert->tbs().serial_number.size())) {
    return false;
  }

  uint8_t *result_bytes;
  size_t result_bytes_length;
  if (!CBB_finish(cbb.get(), &result_bytes, &result_bytes_length)) {
    return false;
  }
  bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(result_bytes);

  request_der->assign(result_bytes, result_bytes + result_bytes_length);
  return true;
}

// From RFC 2560 section A.1.1:
//
//    An OCSP request using the GET method is constructed as follows:
//
//    GET {url}/{url-encoding of base-64 encoding of the DER encoding of
//    the OCSPRequest}
std::optional<std::string> CreateOCSPGetURL(
    const ParsedCertificate *cert, const ParsedCertificate *issuer,
    std::string_view ocsp_responder_url) {
  std::vector<uint8_t> ocsp_request_der;
  if (!CreateOCSPRequest(cert, issuer, &ocsp_request_der)) {
    // Unexpected (means BoringSSL failed an operation).
    return std::nullopt;
  }

  // Base64 encode the request data.
  size_t len;
  if (!EVP_EncodedLength(&len, ocsp_request_der.size())) {
    return std::nullopt;
  }
  std::vector<uint8_t> encoded(len);
  len = EVP_EncodeBlock(encoded.data(), ocsp_request_der.data(),
                        ocsp_request_der.size());

  std::string b64_encoded(encoded.begin(), encoded.begin() + len);

  // In theory +, /, and = are valid in paths and don't need to be escaped.
  // However from the example in RFC 5019 section 5 it is clear that the intent
  // is to escape non-alphanumeric characters (the example conclusively escapes
  // '/' and '=', but doesn't clarify '+').
  b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "+", "%2B");
  b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "/", "%2F");
  b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "=", "%3D");

  // No attempt is made to collapse double slashes for URLs that end in slash,
  // since the spec doesn't do that.
  return std::string(ocsp_responder_url) + "/" + b64_encoded;
}

}  // namespace bssl
