/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This code is made available to you under your choice of the following sets
 * of licensing terms:
 */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
/* Copyright 2013 Mozilla Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <limits>

#include "mozpkix/pkix.h"
#include "mozpkix/pkixcheck.h"
#include "mozpkix/pkixutil.h"

namespace {

const size_t SHA1_DIGEST_LENGTH = 160 / 8;

} // namespace

namespace mozilla { namespace pkix {

// These values correspond to the tag values in the ASN.1 CertStatus
enum class CertStatus : uint8_t {
  Good = der::CONTEXT_SPECIFIC | 0,
  Revoked = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
  Unknown = der::CONTEXT_SPECIFIC | 2
};

class Context final
{
public:
  Context(TrustDomain& aTrustDomain, const CertID& aCertID, Time aTime,
          uint16_t aMaxLifetimeInDays, /*optional out*/ Time* aThisUpdate,
          /*optional out*/ Time* aValidThrough)
    : trustDomain(aTrustDomain)
    , certID(aCertID)
    , time(aTime)
    , maxLifetimeInDays(aMaxLifetimeInDays)
    , certStatus(CertStatus::Unknown)
    , thisUpdate(aThisUpdate)
    , validThrough(aValidThrough)
    , expired(false)
    , matchFound(false)
  {
    if (thisUpdate) {
      *thisUpdate = TimeFromElapsedSecondsAD(0);
    }
    if (validThrough) {
      *validThrough = TimeFromElapsedSecondsAD(0);
    }
  }

  TrustDomain& trustDomain;
  const CertID& certID;
  const Time time;
  const uint16_t maxLifetimeInDays;
  CertStatus certStatus;
  Time* thisUpdate;
  Time* validThrough;
  bool expired;

  Input signedCertificateTimestamps;

  // Keep track of whether the OCSP response contains the status of the
  // certificate we're interested in. Responders might reply without
  // including the status of any of the requested certs, we should
  // indicate a server failure in those cases.
  bool matchFound;

  Context(const Context&) = delete;
  void operator=(const Context&) = delete;
};

// Verify that potentialSigner is a valid delegated OCSP response signing cert
// according to RFC 6960 section 4.2.2.2.
static Result
CheckOCSPResponseSignerCert(TrustDomain& trustDomain,
                            BackCert& potentialSigner,
                            Input issuerSubject,
                            Input issuerSubjectPublicKeyInfo,
                            Time time)
{
  Result rv;

  // We don't need to do a complete verification of the signer (i.e. we don't
  // have to call BuildCertChain to verify the entire chain) because we
  // already know that the issuer is valid, since revocation checking is done
  // from the root to the parent after we've built a complete chain that we
  // know is otherwise valid. Rather, we just need to do a one-step validation
  // from potentialSigner to the issuer.
  //
  // It seems reasonable to require the KU_DIGITAL_SIGNATURE key usage on the
  // OCSP responder certificate if the OCSP responder certificate has a
  // key usage extension. However, according to bug 240456, some OCSP responder
  // certificates may have only the nonRepudiation bit set. Also, the OCSP
  // specification (RFC 6960) does not mandate any particular key usage to be
  // asserted for OCSP responde signers. Oddly, the CABForum Baseline
  // Requirements v.1.1.5 do say "If the Root CA Private Key is used for
  // signing OCSP responses, then the digitalSignature bit MUST be set."
  //
  // Note that CheckIssuerIndependentProperties processes
  // SEC_OID_OCSP_RESPONDER in the way that the OCSP specification requires us
  // to--in particular, it doesn't allow SEC_OID_OCSP_RESPONDER to be implied
  // by a missing EKU extension, unlike other EKUs.
  //
  // TODO(bug 926261): If we're validating for a policy then the policy OID we
  // are validating for should be passed to CheckIssuerIndependentProperties.
  TrustLevel unusedTrustLevel;
  rv = CheckIssuerIndependentProperties(trustDomain, potentialSigner, time,
                                        KeyUsage::noParticularKeyUsageRequired,
                                        KeyPurposeId::id_kp_OCSPSigning,
                                        CertPolicyId::anyPolicy, 0,
                                        unusedTrustLevel);
  if (rv != Success) {
    return rv;
  }

  // It is possible that there exists a certificate with the same key as the
  // issuer but with a different name, so we need to compare names
  // XXX(bug 926270) XXX(bug 1008133) XXX(bug 980163): Improve name
  // comparison.
  // TODO: needs test
  if (!InputsAreEqual(potentialSigner.GetIssuer(), issuerSubject)) {
    return Result::ERROR_OCSP_RESPONDER_CERT_INVALID;
  }

  // TODO(bug 926260): check name constraints

  rv = VerifySignedData(trustDomain, potentialSigner.GetSignedData(),
                        issuerSubjectPublicKeyInfo);

  // TODO: check for revocation of the OCSP responder certificate unless no-check
  // or the caller forcing no-check. To properly support the no-check policy, we'd
  // need to enforce policy constraints from the issuerChain.

  return rv;
}

enum class ResponderIDType : uint8_t
{
  byName = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
  byKey = der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 2
};

static inline Result OCSPResponse(Reader&, Context&);
static inline Result ResponseBytes(Reader&, Context&);
static inline Result BasicResponse(Reader&, Context&);
static inline Result ResponseData(
                       Reader& tbsResponseData,
                       Context& context,
                       const der::SignedDataWithSignature& signedResponseData,
                       const DERArray& certs);
static inline Result SingleResponse(Reader& input, Context& context);
static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
                                     bool critical, /*out*/ bool& understood);
static Result RememberSingleExtension(Context& context, Reader& extnID,
                                      Input extnValue, bool critical,
                                      /*out*/ bool& understood);
// It is convention to name the function after the part of the data structure
// we're parsing from the RFC (e.g. OCSPResponse, ResponseBytes).
// But since we also have a C++ type called CertID, this function doesn't
// follow the convention to prevent shadowing.
static inline Result MatchCertID(Reader& input,
                                 const Context& context,
                                 /*out*/ bool& match);
static Result MatchKeyHash(TrustDomain& trustDomain,
                           Input issuerKeyHash,
                           Input issuerSubjectPublicKeyInfo,
                           /*out*/ bool& match);
static Result KeyHash(TrustDomain& trustDomain,
                      Input subjectPublicKeyInfo,
                      /*out*/ uint8_t* hashBuf, size_t hashBufSize);

static Result
MatchResponderID(TrustDomain& trustDomain,
                 ResponderIDType responderIDType,
                 Input responderID,
                 Input potentialSignerSubject,
                 Input potentialSignerSubjectPublicKeyInfo,
                 /*out*/ bool& match)
{
  match = false;

  switch (responderIDType) {
    case ResponderIDType::byName:
      // XXX(bug 926270) XXX(bug 1008133) XXX(bug 980163): Improve name
      // comparison.
      match = InputsAreEqual(responderID, potentialSignerSubject);
      return Success;

    case ResponderIDType::byKey:
    {
      Reader input(responderID);
      Input keyHash;
      Result rv = der::ExpectTagAndGetValue(input, der::OCTET_STRING, keyHash);
      if (rv != Success) {
        return rv;
      }
      return MatchKeyHash(trustDomain, keyHash,
                          potentialSignerSubjectPublicKeyInfo, match);
    }

    MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
  }
}

static Result
VerifyOCSPSignedData(TrustDomain& trustDomain,
                     const der::SignedDataWithSignature& signedResponseData,
                     Input spki)
{
  Result rv = VerifySignedData(trustDomain, signedResponseData, spki);
  if (rv == Result::ERROR_BAD_SIGNATURE) {
    rv = Result::ERROR_OCSP_BAD_SIGNATURE;
  }
  return rv;
}

// RFC 6960 section 4.2.2.2: The OCSP responder must either be the issuer of
// the cert or it must be a delegated OCSP response signing cert directly
// issued by the issuer. If the OCSP responder is a delegated OCSP response
// signer, then its certificate is (probably) embedded within the OCSP
// response and we'll need to verify that it is a valid certificate that chains
// *directly* to issuerCert.
static Result
VerifySignature(Context& context, ResponderIDType responderIDType,
                Input responderID, const DERArray& certs,
                const der::SignedDataWithSignature& signedResponseData)
{
  bool match;
  Result rv = MatchResponderID(context.trustDomain, responderIDType,
                               responderID, context.certID.issuer,
                               context.certID.issuerSubjectPublicKeyInfo,
                               match);
  if (rv != Success) {
    return rv;
  }
  if (match) {
    return VerifyOCSPSignedData(context.trustDomain, signedResponseData,
                                context.certID.issuerSubjectPublicKeyInfo);
  }

  size_t numCerts = certs.GetLength();
  for (size_t i = 0; i < numCerts; ++i) {
    BackCert cert(*certs.GetDER(i), EndEntityOrCA::MustBeEndEntity, nullptr);
    rv = cert.Init();
    if (rv != Success) {
      return rv;
    }
    rv = MatchResponderID(context.trustDomain, responderIDType, responderID,
                          cert.GetSubject(), cert.GetSubjectPublicKeyInfo(),
                          match);
    if (rv != Success) {
      if (IsFatalError(rv)) {
        return rv;
      }
      continue;
    }

    if (match) {
      rv = CheckOCSPResponseSignerCert(context.trustDomain, cert,
                                       context.certID.issuer,
                                       context.certID.issuerSubjectPublicKeyInfo,
                                       context.time);
      if (rv != Success) {
        if (IsFatalError(rv)) {
          return rv;
        }
        continue;
      }

      return VerifyOCSPSignedData(context.trustDomain, signedResponseData,
                                  cert.GetSubjectPublicKeyInfo());
    }
  }

  return Result::ERROR_OCSP_INVALID_SIGNING_CERT;
}

static inline Result
MapBadDERToMalformedOCSPResponse(Result rv)
{
  if (rv == Result::ERROR_BAD_DER) {
    return Result::ERROR_OCSP_MALFORMED_RESPONSE;
  }
  return rv;
}

Result
VerifyEncodedOCSPResponse(TrustDomain& trustDomain, const struct CertID& certID,
                          Time time, uint16_t maxOCSPLifetimeInDays,
                          Input encodedResponse,
                          /*out*/ bool& expired,
                          /*optional out*/ Time* thisUpdate,
                          /*optional out*/ Time* validThrough)
{
  // Always initialize this to something reasonable.
  expired = false;

  Context context(trustDomain, certID, time, maxOCSPLifetimeInDays,
                  thisUpdate, validThrough);

  Reader input(encodedResponse);
  Result rv = der::Nested(input, der::SEQUENCE, [&context](Reader& r) {
    return OCSPResponse(r, context);
  });
  if (rv != Success) {
    return MapBadDERToMalformedOCSPResponse(rv);
  }
  rv = der::End(input);
  if (rv != Success) {
    return MapBadDERToMalformedOCSPResponse(rv);
  }
  if (!context.matchFound) {
    return Result::ERROR_OCSP_RESPONSE_FOR_CERT_MISSING;
  }

  expired = context.expired;

  switch (context.certStatus) {
    case CertStatus::Good:
      if (expired) {
        return Result::ERROR_OCSP_OLD_RESPONSE;
      }
      if (context.signedCertificateTimestamps.GetLength()) {
        Input sctList;
        rv = ExtractSignedCertificateTimestampListFromExtension(
          context.signedCertificateTimestamps, sctList);
        if (rv != Success) {
          return MapBadDERToMalformedOCSPResponse(rv);
        }
        context.trustDomain.NoteAuxiliaryExtension(
          AuxiliaryExtension::SCTListFromOCSPResponse, sctList);
      }
      return Success;
    case CertStatus::Revoked:
      return Result::ERROR_REVOKED_CERTIFICATE;
    case CertStatus::Unknown:
      return Result::ERROR_OCSP_UNKNOWN_CERT;
     MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
  }
}

// OCSPResponse ::= SEQUENCE {
//       responseStatus         OCSPResponseStatus,
//       responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
//
static inline Result
OCSPResponse(Reader& input, Context& context)
{
  // OCSPResponseStatus ::= ENUMERATED {
  //     successful            (0),  -- Response has valid confirmations
  //     malformedRequest      (1),  -- Illegal confirmation request
  //     internalError         (2),  -- Internal error in issuer
  //     tryLater              (3),  -- Try again later
  //                                 -- (4) is not used
  //     sigRequired           (5),  -- Must sign the request
  //     unauthorized          (6)   -- Request unauthorized
  // }
  uint8_t responseStatus;

  Result rv = der::Enumerated(input, responseStatus);
  if (rv != Success) {
    return rv;
  }
  switch (responseStatus) {
    case 0: break; // successful
    case 1: return Result::ERROR_OCSP_MALFORMED_REQUEST;
    case 2: return Result::ERROR_OCSP_SERVER_ERROR;
    case 3: return Result::ERROR_OCSP_TRY_SERVER_LATER;
    case 5: return Result::ERROR_OCSP_REQUEST_NEEDS_SIG;
    case 6: return Result::ERROR_OCSP_UNAUTHORIZED_REQUEST;
    default: return Result::ERROR_OCSP_UNKNOWN_RESPONSE_STATUS;
  }

  return der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
                     der::SEQUENCE, [&context](Reader& r) {
    return ResponseBytes(r, context);
  });
}

// ResponseBytes ::=       SEQUENCE {
//     responseType   OBJECT IDENTIFIER,
//     response       OCTET STRING }
static inline Result
ResponseBytes(Reader& input, Context& context)
{
  static const uint8_t id_pkix_ocsp_basic[] = {
    0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
  };

  Result rv = der::OID(input, id_pkix_ocsp_basic);
  if (rv != Success) {
    return rv;
  }

  return der::Nested(input, der::OCTET_STRING, der::SEQUENCE,
                     [&context](Reader& r) {
    return BasicResponse(r, context);
  });
}

// BasicOCSPResponse       ::= SEQUENCE {
//    tbsResponseData      ResponseData,
//    signatureAlgorithm   AlgorithmIdentifier,
//    signature            BIT STRING,
//    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
Result
BasicResponse(Reader& input, Context& context)
{
  Reader tbsResponseData;
  der::SignedDataWithSignature signedData;
  Result rv = der::SignedData(input, tbsResponseData, signedData);
  if (rv != Success) {
    if (rv == Result::ERROR_BAD_SIGNATURE) {
      return Result::ERROR_OCSP_BAD_SIGNATURE;
    }
    return rv;
  }

  // Parse certificates, if any
  NonOwningDERArray certs;
  if (!input.AtEnd()) {
    rv = der::Nested(input, der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
                     der::SEQUENCE, [&certs](Reader& certsDER) -> Result {
      while (!certsDER.AtEnd()) {
        Input cert;
        Result nestedRv =
          der::ExpectTagAndGetTLV(certsDER, der::SEQUENCE, cert);
        if (nestedRv != Success) {
          return nestedRv;
        }
        nestedRv = certs.Append(cert);
        if (nestedRv != Success) {
          return Result::ERROR_BAD_DER; // Too many certs
        }
      }
      return Success;
    });
    if (rv != Success) {
      return rv;
    }
  }

  return ResponseData(tbsResponseData, context, signedData, certs);
}

// ResponseData ::= SEQUENCE {
//    version             [0] EXPLICIT Version DEFAULT v1,
//    responderID             ResponderID,
//    producedAt              GeneralizedTime,
//    responses               SEQUENCE OF SingleResponse,
//    responseExtensions  [1] EXPLICIT Extensions OPTIONAL }
static inline Result
ResponseData(Reader& input, Context& context,
             const der::SignedDataWithSignature& signedResponseData,
             const DERArray& certs)
{
  der::Version version;
  Result rv = der::OptionalVersion(input, version);
  if (rv != Success) {
    return rv;
  }
  if (version != der::Version::v1) {
    // TODO: more specific error code for bad version?
    return Result::ERROR_BAD_DER;
  }

  // ResponderID ::= CHOICE {
  //    byName              [1] Name,
  //    byKey               [2] KeyHash }
  Input responderID;
  ResponderIDType responderIDType
    = input.Peek(static_cast<uint8_t>(ResponderIDType::byName))
    ? ResponderIDType::byName
    : ResponderIDType::byKey;
  rv = der::ExpectTagAndGetValue(input, static_cast<uint8_t>(responderIDType),
                                 responderID);
  if (rv != Success) {
    return rv;
  }

  // This is the soonest we can verify the signature. We verify the signature
  // right away to follow the principal of minimizing the processing of data
  // before verifying its signature.
  rv = VerifySignature(context, responderIDType, responderID, certs,
                       signedResponseData);
  if (rv != Success) {
    return rv;
  }

  // TODO: Do we even need to parse this? Should we just skip it?
  Time producedAt(Time::uninitialized);
  rv = der::GeneralizedTime(input, producedAt);
  if (rv != Success) {
    return rv;
  }

  // We don't accept an empty sequence of responses. In practice, a legit OCSP
  // responder will never return an empty response, and handling the case of an
  // empty response makes things unnecessarily complicated.
  rv = der::NestedOf(input, der::SEQUENCE, der::SEQUENCE,
                     der::EmptyAllowed::No, [&context](Reader& r) {
    return SingleResponse(r, context);
  });
  if (rv != Success) {
    return rv;
  }

  return der::OptionalExtensions(input,
                                 der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
                                 ExtensionNotUnderstood);
}

// SingleResponse ::= SEQUENCE {
//    certID                       CertID,
//    certStatus                   CertStatus,
//    thisUpdate                   GeneralizedTime,
//    nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
//    singleExtensions     [1]     EXPLICIT Extensions{{re-ocsp-crl |
//                                              re-ocsp-archive-cutoff |
//                                              CrlEntryExtensions, ...}
//                                              } OPTIONAL }
static inline Result
SingleResponse(Reader& input, Context& context)
{
  bool match = false;
  Result rv = der::Nested(input, der::SEQUENCE, [&context, &match](Reader& r) {
    return MatchCertID(r, context, match);
  });
  if (rv != Success) {
    return rv;
  }

  if (!match) {
    // This response does not reference the certificate we're interested in.
    // By consuming the rest of our input and returning successfully, we can
    // continue processing and examine another response that might have what
    // we want.
    input.SkipToEnd();
    return Success;
  }

  // We found a response for the cert we're interested in.
  context.matchFound = true;

  // CertStatus ::= CHOICE {
  //     good        [0]     IMPLICIT NULL,
  //     revoked     [1]     IMPLICIT RevokedInfo,
  //     unknown     [2]     IMPLICIT UnknownInfo }
  //
  // In the event of multiple SingleResponses for a cert that have conflicting
  // statuses, we use the following precedence rules:
  //
  // * revoked overrides good and unknown
  // * good overrides unknown
  if (input.Peek(static_cast<uint8_t>(CertStatus::Good))) {
    rv = der::ExpectTagAndEmptyValue(input,
                                     static_cast<uint8_t>(CertStatus::Good));
    if (rv != Success) {
      return rv;
    }
    if (context.certStatus != CertStatus::Revoked) {
      context.certStatus = CertStatus::Good;
    }
  } else if (input.Peek(static_cast<uint8_t>(CertStatus::Revoked))) {
    // We don't need any info from the RevokedInfo structure, so we don't even
    // parse it. TODO: We should mention issues like this in the explanation of
    // why we treat invalid OCSP responses equivalently to revoked for OCSP
    // stapling.
    rv = der::ExpectTagAndSkipValue(input,
                                    static_cast<uint8_t>(CertStatus::Revoked));
    if (rv != Success) {
      return rv;
    }
    context.certStatus = CertStatus::Revoked;
  } else {
    rv = der::ExpectTagAndEmptyValue(input,
                                     static_cast<uint8_t>(CertStatus::Unknown));
    if (rv != Success) {
      return rv;
    }
  }

  // http://tools.ietf.org/html/rfc6960#section-3.2
  // 5. The time at which the status being indicated is known to be
  //    correct (thisUpdate) is sufficiently recent;
  // 6. When available, the time at or before which newer information will
  //    be available about the status of the certificate (nextUpdate) is
  //    greater than the current time.

  Time thisUpdate(Time::uninitialized);
  rv = der::GeneralizedTime(input, thisUpdate);
  if (rv != Success) {
    return rv;
  }

  static const uint64_t SLOP_SECONDS = Time::ONE_DAY_IN_SECONDS;

  Time timePlusSlop(context.time);
  rv = timePlusSlop.AddSeconds(SLOP_SECONDS);
  if (rv != Success) {
    return rv;
  }
  if (thisUpdate > timePlusSlop) {
    return Result::ERROR_OCSP_FUTURE_RESPONSE;
  }

  Time notAfter(Time::uninitialized);
  static const uint8_t NEXT_UPDATE_TAG =
    der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0;
  if (input.Peek(NEXT_UPDATE_TAG)) {
    Time nextUpdate(Time::uninitialized);
    rv = der::Nested(input, NEXT_UPDATE_TAG, [&nextUpdate](Reader& r) {
      return der::GeneralizedTime(r, nextUpdate);
    });
    if (rv != Success) {
      return rv;
    }

    if (nextUpdate < thisUpdate) {
      return Result::ERROR_OCSP_MALFORMED_RESPONSE;
    }
    notAfter = thisUpdate;
    if (notAfter.AddSeconds(context.maxLifetimeInDays *
                            Time::ONE_DAY_IN_SECONDS) != Success) {
      // This could only happen if we're dealing with times beyond the year
      // 10,000AD.
      return Result::ERROR_OCSP_FUTURE_RESPONSE;
    }
    if (nextUpdate <= notAfter) {
      notAfter = nextUpdate;
    }
  } else {
    // NSS requires all OCSP responses without a nextUpdate to be recent.
    // Match that stricter behavior.
    notAfter = thisUpdate;
    if (notAfter.AddSeconds(Time::ONE_DAY_IN_SECONDS) != Success) {
      // This could only happen if we're dealing with times beyond the year
      // 10,000AD.
      return Result::ERROR_OCSP_FUTURE_RESPONSE;
    }
  }

  // Add some slop to hopefully handle clock-skew.
  Time notAfterPlusSlop(notAfter);
  rv = notAfterPlusSlop.AddSeconds(SLOP_SECONDS);
  if (rv != Success) {
    // This could only happen if we're dealing with times beyond the year
    // 10,000AD.
    return Result::ERROR_OCSP_FUTURE_RESPONSE;
  }
  if (context.time > notAfterPlusSlop) {
    context.expired = true;
  }

  rv = der::OptionalExtensions(
    input,
    der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
    [&context](Reader& extnID, const Input& extnValue, bool critical,
               /*out*/ bool& understood) {
      return RememberSingleExtension(context, extnID, extnValue, critical,
                                     understood);
    });

  if (rv != Success) {
    return rv;
  }

  if (context.thisUpdate) {
    *context.thisUpdate = thisUpdate;
  }
  if (context.validThrough) {
    *context.validThrough = notAfterPlusSlop;
  }

  return Success;
}

// CertID          ::=     SEQUENCE {
//        hashAlgorithm       AlgorithmIdentifier,
//        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
//        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
//        serialNumber        CertificateSerialNumber }
static inline Result
MatchCertID(Reader& input, const Context& context, /*out*/ bool& match)
{
  match = false;

  DigestAlgorithm hashAlgorithm;
  Result rv = der::DigestAlgorithmIdentifier(input, hashAlgorithm);
  if (rv != Success) {
    if (rv == Result::ERROR_INVALID_ALGORITHM) {
      // Skip entries that are hashed with algorithms we don't support.
      input.SkipToEnd();
      return Success;
    }
    return rv;
  }

  Input issuerNameHash;
  rv = der::ExpectTagAndGetValue(input, der::OCTET_STRING, issuerNameHash);
  if (rv != Success) {
    return rv;
  }

  Input issuerKeyHash;
  rv = der::ExpectTagAndGetValue(input, der::OCTET_STRING, issuerKeyHash);
  if (rv != Success) {
    return rv;
  }

  Input serialNumber;
  rv = der::CertificateSerialNumber(input, serialNumber);
  if (rv != Success) {
    return rv;
  }

  if (!InputsAreEqual(serialNumber, context.certID.serialNumber)) {
    // This does not reference the certificate we're interested in.
    // Consume the rest of the input and return successfully to
    // potentially continue processing other responses.
    input.SkipToEnd();
    return Success;
  }

  // TODO: support SHA-2 hashes.

  if (hashAlgorithm != DigestAlgorithm::sha1) {
    // Again, not interested in this response. Consume input, return success.
    input.SkipToEnd();
    return Success;
  }

  if (issuerNameHash.GetLength() != SHA1_DIGEST_LENGTH) {
    return Result::ERROR_OCSP_MALFORMED_RESPONSE;
  }

  // From http://tools.ietf.org/html/rfc6960#section-4.1.1:
  // "The hash shall be calculated over the DER encoding of the
  // issuer's name field in the certificate being checked."
  uint8_t hashBuf[SHA1_DIGEST_LENGTH];
  rv = context.trustDomain.DigestBuf(context.certID.issuer,
                                     DigestAlgorithm::sha1, hashBuf,
                                     sizeof(hashBuf));
  if (rv != Success) {
    return rv;
  }
  Input computed(hashBuf);
  if (!InputsAreEqual(computed, issuerNameHash)) {
    // Again, not interested in this response. Consume input, return success.
    input.SkipToEnd();
    return Success;
  }

  return MatchKeyHash(context.trustDomain, issuerKeyHash,
                      context.certID.issuerSubjectPublicKeyInfo, match);
}

// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
// "The hash shall be calculated over the value (excluding tag and length) of
// the subject public key field in the issuer's certificate."
//
// From http://tools.ietf.org/html/rfc6960#appendix-B.1:
// KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
//                          -- (i.e., the SHA-1 hash of the value of the
//                          -- BIT STRING subjectPublicKey [excluding
//                          -- the tag, length, and number of unused
//                          -- bits] in the responder's certificate)
static Result
MatchKeyHash(TrustDomain& trustDomain, Input keyHash,
             const Input subjectPublicKeyInfo, /*out*/ bool& match)
{
  if (keyHash.GetLength() != SHA1_DIGEST_LENGTH)  {
    return Result::ERROR_OCSP_MALFORMED_RESPONSE;
  }
  uint8_t hashBuf[SHA1_DIGEST_LENGTH];
  Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
                      sizeof hashBuf);
  if (rv != Success) {
    return rv;
  }
  Input computed(hashBuf);
  match = InputsAreEqual(computed, keyHash);
  return Success;
}

// TODO(bug 966856): support SHA-2 hashes
Result
KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
        /*out*/ uint8_t* hashBuf, size_t hashBufSize)
{
  if (!hashBuf || hashBufSize != SHA1_DIGEST_LENGTH) {
    return Result::FATAL_ERROR_LIBRARY_FAILURE;
  }

  // RFC 5280 Section 4.1
  //
  // SubjectPublicKeyInfo  ::=  SEQUENCE  {
  //    algorithm            AlgorithmIdentifier,
  //    subjectPublicKey     BIT STRING  }

  Reader spki;
  Result rv = der::ExpectTagAndGetValueAtEnd(subjectPublicKeyInfo,
                                             der::SEQUENCE, spki);
  if (rv != Success) {
    return rv;
  }

  // Skip AlgorithmIdentifier
  rv = der::ExpectTagAndSkipValue(spki, der::SEQUENCE);
  if (rv != Success) {
    return rv;
  }

  Input subjectPublicKey;
  rv = der::BitStringWithNoUnusedBits(spki, subjectPublicKey);
  if (rv != Success) {
    return rv;
  }
  rv = der::End(spki);
  if (rv != Success) {
    return rv;
  }

  return trustDomain.DigestBuf(subjectPublicKey, DigestAlgorithm::sha1,
                               hashBuf, hashBufSize);
}

Result
ExtensionNotUnderstood(Reader& /*extnID*/, Input /*extnValue*/,
                       bool /*critical*/, /*out*/ bool& understood)
{
  understood = false;
  return Success;
}

Result
RememberSingleExtension(Context& context, Reader& extnID, Input extnValue,
                        bool /*critical*/, /*out*/ bool& understood)
{
  understood = false;

  // SingleExtension for Signed Certificate Timestamp List.
  // See Section 3.3 of RFC 6962.
  // python DottedOIDToCode.py
  //   id_ocsp_singleExtensionSctList 1.3.6.1.4.1.11129.2.4.5
  static const uint8_t id_ocsp_singleExtensionSctList[] = {
    0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x05
  };

  if (extnID.MatchRest(id_ocsp_singleExtensionSctList)) {
    // Empty values are not allowed for this extension. Note that
    // we assume this later, when checking if the extension was present.
    if (extnValue.GetLength() == 0) {
      return Result::ERROR_EXTENSION_VALUE_INVALID;
    }
    if (context.signedCertificateTimestamps.Init(extnValue) != Success) {
      // Duplicate extension.
      return Result::ERROR_EXTENSION_VALUE_INVALID;
    }
    understood = true;
  }

  return Success;
}

//   1. The certificate identified in a received response corresponds to
//      the certificate that was identified in the corresponding request;
//   2. The signature on the response is valid;
//   3. The identity of the signer matches the intended recipient of the
//      request;
//   4. The signer is currently authorized to provide a response for the
//      certificate in question;
//   5. The time at which the status being indicated is known to be
//      correct (thisUpdate) is sufficiently recent;
//   6. When available, the time at or before which newer information will
//      be available about the status of the certificate (nextUpdate) is
//      greater than the current time.
//
//   Responses whose nextUpdate value is earlier than
//   the local system time value SHOULD be considered unreliable.
//   Responses whose thisUpdate time is later than the local system time
//   SHOULD be considered unreliable.
//
//   If nextUpdate is not set, the responder is indicating that newer
//   revocation information is available all the time.
//
// http://tools.ietf.org/html/rfc5019#section-4

Result
CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
                         /*out*/ uint8_t (&out)[OCSP_REQUEST_MAX_LENGTH],
                         /*out*/ size_t& outLen)
{
  // We do not add any extensions to the request.

  // RFC 6960 says "An OCSP client MAY wish to specify the kinds of response
  // types it understands. To do so, it SHOULD use an extension with the OID
  // id-pkix-ocsp-response." This use of MAY and SHOULD is unclear. MSIE11
  // on Windows 8.1 does not include any extensions, whereas NSS has always
  // included the id-pkix-ocsp-response extension. Avoiding the sending the
  // extension is better for OCSP GET because it makes the request smaller,
  // and thus more likely to fit within the 255 byte limit for OCSP GET that
  // is specified in RFC 5019 Section 5.

  // Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.

  // Since we don't know whether the OCSP responder supports anything other
  // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
  // issuerKeyHash.
  static const uint8_t hashAlgorithm[11] = {
    0x30, 0x09,                               // SEQUENCE
    0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, //   OBJECT IDENTIFIER id-sha1
    0x05, 0x00,                               //   NULL
  };
  static const uint8_t hashLen = 160 / 8;

  static const unsigned int totalLenWithoutSerialNumberData
    = 2                             // OCSPRequest
    + 2                             //   tbsRequest
    + 2                             //     requestList
    + 2                             //       Request
    + 2                             //         reqCert (CertID)
    + sizeof(hashAlgorithm)         //           hashAlgorithm
    + 2 + hashLen                   //           issuerNameHash
    + 2 + hashLen                   //           issuerKeyHash
    + 2;                            //           serialNumber (header)

  // The only way we could have a request this large is if the serialNumber was
  // ridiculously and unreasonably large. RFC 5280 says "Conforming CAs MUST
  // NOT use serialNumber values longer than 20 octets." With this restriction,
  // we allow for some amount of non-conformance with that requirement while
  // still ensuring we can encode the length values in the ASN.1 TLV structures
  // in a single byte.
  static_assert(totalLenWithoutSerialNumberData < OCSP_REQUEST_MAX_LENGTH,
                "totalLenWithoutSerialNumberData too big");
  if (certID.serialNumber.GetLength() >
        OCSP_REQUEST_MAX_LENGTH - totalLenWithoutSerialNumberData) {
    return Result::ERROR_BAD_DER;
  }

  outLen = totalLenWithoutSerialNumberData + certID.serialNumber.GetLength();

  uint8_t totalLen = static_cast<uint8_t>(outLen);

  uint8_t* d = out;
  *d++ = 0x30; *d++ = totalLen - 2u;  // OCSPRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 4u;  //   tbsRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 6u;  //     requestList (SEQUENCE OF)
  *d++ = 0x30; *d++ = totalLen - 8u;  //       Request (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 10u; //         reqCert (CertID SEQUENCE)

  // reqCert.hashAlgorithm
  for (const uint8_t hashAlgorithmByte : hashAlgorithm) {
    *d++ = hashAlgorithmByte;
  }

  // reqCert.issuerNameHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  Result rv = trustDomain.DigestBuf(certID.issuer, DigestAlgorithm::sha1, d,
                                    hashLen);
  if (rv != Success) {
    return rv;
  }
  d += hashLen;

  // reqCert.issuerKeyHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  rv = KeyHash(trustDomain, certID.issuerSubjectPublicKeyInfo, d, hashLen);
  if (rv != Success) {
    return rv;
  }
  d += hashLen;

  // reqCert.serialNumber (INTEGER)
  *d++ = 0x02; // INTEGER
  *d++ = static_cast<uint8_t>(certID.serialNumber.GetLength());
  Reader serialNumber(certID.serialNumber);
  do {
    rv = serialNumber.Read(*d);
    if (rv != Success) {
      return rv;
    }
    ++d;
  } while (!serialNumber.AtEnd());

  assert(d == out + totalLen);

  return Success;
}

} } // namespace mozilla::pkix
