| // Copyright 2016 The Chromium Authors | |
| // | |
| // 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 | |
| // | |
| // https://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. | |
| #ifndef BSSL_PKI_OCSP_H_ | |
| #define BSSL_PKI_OCSP_H_ | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include <openssl/base.h> | |
| #include <openssl/pki/ocsp.h> | |
| #include "input.h" | |
| #include "parse_values.h" | |
| #include "parser.h" | |
| #include "signature_algorithm.h" | |
| BSSL_NAMESPACE_BEGIN | |
| class ParsedCertificate; | |
| // 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 OPENSSL_EXPORT 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 { | |
| // 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, | |
| }; | |
| OCSPRevocationStatus 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 OPENSSL_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 OPENSSL_EXPORT OCSPResponseData { | |
| enum class ResponderType { NAME, KEY_HASH }; | |
| struct ResponderID { | |
| ResponderType type; | |
| der::Input name; | |
| der::Input 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 OPENSSL_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; | |
| 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 | |
| inline constexpr uint8_t kBasicOCSPResponseOid[] = { | |
| 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01}; | |
| // 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. | |
| OPENSSL_EXPORT bool ParseOCSPCertID(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. | |
| OPENSSL_EXPORT bool ParseOCSPSingleResponse(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. | |
| OPENSSL_EXPORT bool ParseOCSPResponseData(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. | |
| OPENSSL_EXPORT bool ParseOCSPResponse(der::Input raw_tlv, OCSPResponse *out); | |
| // Checks the revocation status of |certificate| by using the DER-encoded | |
| // |raw_response|. | |
| // | |
| // Arguments are the same as above, except that it takes already parsed | |
| // instances of the certificate and issuer certificate. | |
| [[nodiscard]] OPENSSL_EXPORT 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); | |
| // Creates a DER-encoded OCSPRequest for |cert|. The request is fairly basic: | |
| // * No signature | |
| // * No requestorName | |
| // * No extensions | |
| // * Uses SHA1 for all hashes. | |
| // | |
| // Returns true on success and fills |request_der| with the resulting bytes. | |
| OPENSSL_EXPORT bool CreateOCSPRequest(const ParsedCertificate *cert, | |
| const ParsedCertificate *issuer, | |
| std::vector<uint8_t> *request_der); | |
| // Creates a URL to issue a GET request for OCSP information for |cert|. | |
| OPENSSL_EXPORT std::optional<std::string> CreateOCSPGetURL( | |
| const ParsedCertificate *cert, const ParsedCertificate *issuer, | |
| std::string_view ocsp_responder_url); | |
| BSSL_NAMESPACE_END | |
| #endif // BSSL_PKI_OCSP_H_ |