blob: b9052aee9f6df9c4e4797a928b5c7024a917ba4e [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_CERT_INTERNAL_PARSE_OCSP_H_
#define NET_CERT_INTERNAL_PARSE_OCSP_H_
#include <memory>
#include <string>
#include <vector>
#include "net/base/hash_value.h"
#include "net/cert/internal/parse_certificate.h"
#include "net/cert/internal/signature_algorithm.h"
#include "net/der/input.h"
#include "net/der/parse_values.h"
#include "net/der/parser.h"
#include "net/der/tag.h"
namespace net {
// OCSPCertID contains a representation of a DER-encoded RFC 6960 "CertID".
//
// CertID ::= SEQUENCE {
// hashAlgorithm AlgorithmIdentifier,
// issuerNameHash OCTET STRING, -- Hash of issuer's DN
// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
// serialNumber CertificateSerialNumber
// }
struct OCSPCertID {
OCSPCertID();
~OCSPCertID();
DigestAlgorithm hash_algorithm;
der::Input issuer_name_hash;
der::Input issuer_key_hash;
der::Input serial_number;
};
// OCSPCertStatus contains a representation of a DER-encoded RFC 6960
// "CertStatus". |revocation_time| and |has_reason| are only valid when
// |status| is REVOKED. |revocation_reason| is only valid when |has_reason| is
// true.
//
// CertStatus ::= CHOICE {
// good [0] IMPLICIT NULL,
// revoked [1] IMPLICIT RevokedInfo,
// unknown [2] IMPLICIT UnknownInfo
// }
//
// RevokedInfo ::= SEQUENCE {
// revocationTime GeneralizedTime,
// revocationReason [0] EXPLICIT CRLReason OPTIONAL
// }
//
// UnknownInfo ::= NULL
//
// CRLReason ::= ENUMERATED {
// unspecified (0),
// keyCompromise (1),
// cACompromise (2),
// affiliationChanged (3),
// superseded (4),
// cessationOfOperation (5),
// certificateHold (6),
// -- value 7 is not used
// removeFromCRL (8),
// privilegeWithdrawn (9),
// aACompromise (10)
// }
// (from RFC 5280)
struct OCSPCertStatus {
enum class Status {
GOOD,
REVOKED,
UNKNOWN,
};
// Correspond to the values of CRLReason
enum class RevocationReason {
UNSPECIFIED = 0,
KEY_COMPROMISE = 1,
CA_COMPROMISE = 2,
AFFILIATION_CHANGED = 3,
SUPERSEDED = 4,
CESSATION_OF_OPERATION = 5,
CERTIFICATE_HOLD = 6,
UNUSED = 7,
REMOVE_FROM_CRL = 8,
PRIVILEGE_WITHDRAWN = 9,
AA_COMPROMISE = 10,
LAST = AA_COMPROMISE,
};
Status status;
der::GeneralizedTime revocation_time;
bool has_reason;
RevocationReason revocation_reason;
};
// OCSPSingleResponse contains a representation of a DER-encoded RFC 6960
// "SingleResponse". The |cert_id_tlv| and |extensions| fields are pointers to
// the original object and are only valid as long as it is alive. They also
// aren't verified until they are parsed. |next_update| is only valid if
// |has_next_update| is true and |extensions| is only valid if |has_extensions|
// is true.
//
// SingleResponse ::= SEQUENCE {
// certID CertID,
// certStatus CertStatus,
// thisUpdate GeneralizedTime,
// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
// singleExtensions [1] EXPLICIT Extensions OPTIONAL
// }
struct NET_EXPORT OCSPSingleResponse {
OCSPSingleResponse();
~OCSPSingleResponse();
der::Input cert_id_tlv;
OCSPCertStatus cert_status;
der::GeneralizedTime this_update;
bool has_next_update;
der::GeneralizedTime next_update;
bool has_extensions;
der::Input extensions;
};
// OCSPResponseData contains a representation of a DER-encoded RFC 6960
// "ResponseData". The |responses| and |extensions| fields are pointers to the
// original object and are only valid as long as it is alive. They also aren't
// verified until they are parsed into OCSPSingleResponse and ParsedExtensions.
// |extensions| is only valid if |has_extensions| is true.
//
// ResponseData ::= SEQUENCE {
// version [0] EXPLICIT Version DEFAULT v1,
// responderID ResponderID,
// producedAt GeneralizedTime,
// responses SEQUENCE OF SingleResponse,
// responseExtensions [1] EXPLICIT Extensions OPTIONAL
// }
struct NET_EXPORT OCSPResponseData {
enum class ResponderType { NAME, KEY_HASH };
struct ResponderID {
ResponderType type;
der::Input name;
HashValue key_hash;
};
OCSPResponseData();
~OCSPResponseData();
uint8_t version;
OCSPResponseData::ResponderID responder_id;
der::GeneralizedTime produced_at;
std::vector<der::Input> responses;
bool has_extensions;
der::Input extensions;
};
// OCSPResponse contains a representation of a DER-encoded RFC 6960
// "OCSPResponse" and the corresponding "BasicOCSPResponse". The |data| field
// is a pointer to the original object and are only valid as long is it is
// alive. The |data| field isn't verified until it is parsed into an
// OCSPResponseData. |data|, |signature_algorithm|, |signature|, and
// |has_certs| is only valid if |status| is SUCCESSFUL. |certs| is only valid
// if |has_certs| is true.
//
// OCSPResponse ::= SEQUENCE {
// responseStatus OCSPResponseStatus,
// responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
// }
//
// ResponseBytes ::= SEQUENCE {
// responseType OBJECT IDENTIFIER,
// response OCTET STRING
// }
//
// BasicOCSPResponse ::= SEQUENCE {
// tbsResponseData ResponseData,
// signatureAlgorithm AlgorithmIdentifier,
// signature BIT STRING,
// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
// }
//
// 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
// }
struct NET_EXPORT OCSPResponse {
// Correspond to the values of OCSPResponseStatus
enum class ResponseStatus {
SUCCESSFUL = 0,
MALFORMED_REQUEST = 1,
INTERNAL_ERROR = 2,
TRY_LATER = 3,
UNUSED = 4,
SIG_REQUIRED = 5,
UNAUTHORIZED = 6,
LAST = UNAUTHORIZED,
};
OCSPResponse();
~OCSPResponse();
ResponseStatus status;
der::Input data;
std::unique_ptr<SignatureAlgorithm> signature_algorithm;
der::BitString signature;
bool has_certs;
std::vector<der::Input> certs;
};
// From RFC 6960:
//
// id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp }
// id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
//
// In dotted notation: 1.3.6.1.5.5.7.48.1.1
NET_EXPORT der::Input BasicOCSPResponseOid();
// Parses a DER-encoded OCSP "CertID" as specified by RFC 6960. Returns true on
// success and sets the results in |out|.
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
NET_EXPORT_PRIVATE bool ParseOCSPCertID(const der::Input& raw_tlv,
OCSPCertID* out);
// Parses a DER-encoded OCSP "SingleResponse" as specified by RFC 6960. Returns
// true on success and sets the results in |out|. The resulting |out|
// references data from |raw_tlv| and is only valid for the lifetime of
// |raw_tlv|.
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
NET_EXPORT_PRIVATE bool ParseOCSPSingleResponse(const der::Input& raw_tlv,
OCSPSingleResponse* out);
// Parses a DER-encoded OCSP "ResponseData" as specified by RFC 6960. Returns
// true on success and sets the results in |out|. The resulting |out|
// references data from |raw_tlv| and is only valid for the lifetime of
// |raw_tlv|.
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
NET_EXPORT_PRIVATE bool ParseOCSPResponseData(const der::Input& raw_tlv,
OCSPResponseData* out);
// Parses a DER-encoded "OCSPResponse" as specified by RFC 6960. Returns true
// on success and sets the results in |out|. The resulting |out|
// references data from |raw_tlv| and is only valid for the lifetime of
// |raw_tlv|.
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
NET_EXPORT_PRIVATE bool ParseOCSPResponse(const der::Input& raw_tlv,
OCSPResponse* out);
// Checks the certificate status of |cert_tbs_certificate_tlv| based on the
// OCSPResponseData |response_data| and issuer |issuer_tbs_certificate_tlv| and
// sets the results in |out|. In the case that there are multiple responses for
// a given certificate, as a result of caching or performance (RFC 6960,
// 4.2.2.3), the strictest response is returned (REVOKED > UNKNOWN > GOOD).
//
// On failure |out| has an undefined state. Some of its fields may have been
// updated during parsing, whereas others may not have been changed.
NET_EXPORT_PRIVATE bool GetOCSPCertStatus(
const OCSPResponseData& response_data,
const der::Input& issuer_tbs_certificate_tlv,
const der::Input& cert_tbs_certificate_tlv,
OCSPCertStatus* out);
} // namespace net
#endif // NET_CERT_INTERNAL_PARSE_OCSP_H_