1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BSSL_PKI_OCSP_H_ 6 #define BSSL_PKI_OCSP_H_ 7 8 #include <memory> 9 #include <optional> 10 #include <string> 11 #include <vector> 12 13 #include <openssl/base.h> 14 15 #include "input.h" 16 #include "ocsp_revocation_status.h" 17 #include "ocsp_verify_result.h" 18 #include "parse_values.h" 19 #include "parser.h" 20 #include "signature_algorithm.h" 21 22 namespace bssl { 23 24 class ParsedCertificate; 25 26 // OCSPCertID contains a representation of a DER-encoded RFC 6960 "CertID". 27 // 28 // CertID ::= SEQUENCE { 29 // hashAlgorithm AlgorithmIdentifier, 30 // issuerNameHash OCTET STRING, -- Hash of issuer's DN 31 // issuerKeyHash OCTET STRING, -- Hash of issuer's public key 32 // serialNumber CertificateSerialNumber 33 // } 34 struct OPENSSL_EXPORT OCSPCertID { 35 OCSPCertID(); 36 ~OCSPCertID(); 37 38 DigestAlgorithm hash_algorithm; 39 der::Input issuer_name_hash; 40 der::Input issuer_key_hash; 41 der::Input serial_number; 42 }; 43 44 // OCSPCertStatus contains a representation of a DER-encoded RFC 6960 45 // "CertStatus". |revocation_time| and |has_reason| are only valid when 46 // |status| is REVOKED. |revocation_reason| is only valid when |has_reason| is 47 // true. 48 // 49 // CertStatus ::= CHOICE { 50 // good [0] IMPLICIT NULL, 51 // revoked [1] IMPLICIT RevokedInfo, 52 // unknown [2] IMPLICIT UnknownInfo 53 // } 54 // 55 // RevokedInfo ::= SEQUENCE { 56 // revocationTime GeneralizedTime, 57 // revocationReason [0] EXPLICIT CRLReason OPTIONAL 58 // } 59 // 60 // UnknownInfo ::= NULL 61 // 62 // CRLReason ::= ENUMERATED { 63 // unspecified (0), 64 // keyCompromise (1), 65 // cACompromise (2), 66 // affiliationChanged (3), 67 // superseded (4), 68 // cessationOfOperation (5), 69 // certificateHold (6), 70 // -- value 7 is not used 71 // removeFromCRL (8), 72 // privilegeWithdrawn (9), 73 // aACompromise (10) 74 // } 75 // (from RFC 5280) 76 struct OCSPCertStatus { 77 // Correspond to the values of CRLReason 78 enum class RevocationReason { 79 UNSPECIFIED = 0, 80 KEY_COMPROMISE = 1, 81 CA_COMPROMISE = 2, 82 AFFILIATION_CHANGED = 3, 83 SUPERSEDED = 4, 84 CESSATION_OF_OPERATION = 5, 85 CERTIFICATE_HOLD = 6, 86 UNUSED = 7, 87 REMOVE_FROM_CRL = 8, 88 PRIVILEGE_WITHDRAWN = 9, 89 AA_COMPROMISE = 10, 90 91 LAST = AA_COMPROMISE, 92 }; 93 94 OCSPRevocationStatus status; 95 der::GeneralizedTime revocation_time; 96 bool has_reason; 97 RevocationReason revocation_reason; 98 }; 99 100 // OCSPSingleResponse contains a representation of a DER-encoded RFC 6960 101 // "SingleResponse". The |cert_id_tlv| and |extensions| fields are pointers to 102 // the original object and are only valid as long as it is alive. They also 103 // aren't verified until they are parsed. |next_update| is only valid if 104 // |has_next_update| is true and |extensions| is only valid if |has_extensions| 105 // is true. 106 // 107 // SingleResponse ::= SEQUENCE { 108 // certID CertID, 109 // certStatus CertStatus, 110 // thisUpdate GeneralizedTime, 111 // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, 112 // singleExtensions [1] EXPLICIT Extensions OPTIONAL 113 // } 114 struct OPENSSL_EXPORT OCSPSingleResponse { 115 OCSPSingleResponse(); 116 ~OCSPSingleResponse(); 117 118 der::Input cert_id_tlv; 119 OCSPCertStatus cert_status; 120 der::GeneralizedTime this_update; 121 bool has_next_update; 122 der::GeneralizedTime next_update; 123 bool has_extensions; 124 der::Input extensions; 125 }; 126 127 // OCSPResponseData contains a representation of a DER-encoded RFC 6960 128 // "ResponseData". The |responses| and |extensions| fields are pointers to the 129 // original object and are only valid as long as it is alive. They also aren't 130 // verified until they are parsed into OCSPSingleResponse and ParsedExtensions. 131 // |extensions| is only valid if |has_extensions| is true. 132 // 133 // ResponseData ::= SEQUENCE { 134 // version [0] EXPLICIT Version DEFAULT v1, 135 // responderID ResponderID, 136 // producedAt GeneralizedTime, 137 // responses SEQUENCE OF SingleResponse, 138 // responseExtensions [1] EXPLICIT Extensions OPTIONAL 139 // } 140 struct OPENSSL_EXPORT OCSPResponseData { 141 enum class ResponderType { NAME, KEY_HASH }; 142 143 struct ResponderID { 144 ResponderType type; 145 der::Input name; 146 der::Input key_hash; 147 }; 148 149 OCSPResponseData(); 150 ~OCSPResponseData(); 151 152 uint8_t version; 153 OCSPResponseData::ResponderID responder_id; 154 der::GeneralizedTime produced_at; 155 std::vector<der::Input> responses; 156 bool has_extensions; 157 der::Input extensions; 158 }; 159 160 // OCSPResponse contains a representation of a DER-encoded RFC 6960 161 // "OCSPResponse" and the corresponding "BasicOCSPResponse". The |data| field 162 // is a pointer to the original object and are only valid as long is it is 163 // alive. The |data| field isn't verified until it is parsed into an 164 // OCSPResponseData. |data|, |signature_algorithm|, |signature|, and 165 // |has_certs| is only valid if |status| is SUCCESSFUL. |certs| is only valid 166 // if |has_certs| is true. 167 // 168 // OCSPResponse ::= SEQUENCE { 169 // responseStatus OCSPResponseStatus, 170 // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL 171 // } 172 // 173 // ResponseBytes ::= SEQUENCE { 174 // responseType OBJECT IDENTIFIER, 175 // response OCTET STRING 176 // } 177 // 178 // BasicOCSPResponse ::= SEQUENCE { 179 // tbsResponseData ResponseData, 180 // signatureAlgorithm AlgorithmIdentifier, 181 // signature BIT STRING, 182 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL 183 // } 184 // 185 // OCSPResponseStatus ::= ENUMERATED { 186 // successful (0), -- Response has valid confirmations 187 // malformedRequest (1), -- Illegal confirmation request 188 // internalError (2), -- Internal error in issuer 189 // tryLater (3), -- Try again later 190 // -- (4) is not used 191 // sigRequired (5), -- Must sign the request 192 // unauthorized (6) -- Request unauthorized 193 // } 194 struct OPENSSL_EXPORT OCSPResponse { 195 // Correspond to the values of OCSPResponseStatus 196 enum class ResponseStatus { 197 SUCCESSFUL = 0, 198 MALFORMED_REQUEST = 1, 199 INTERNAL_ERROR = 2, 200 TRY_LATER = 3, 201 UNUSED = 4, 202 SIG_REQUIRED = 5, 203 UNAUTHORIZED = 6, 204 205 LAST = UNAUTHORIZED, 206 }; 207 208 OCSPResponse(); 209 ~OCSPResponse(); 210 211 ResponseStatus status; 212 der::Input data; 213 SignatureAlgorithm signature_algorithm; 214 der::BitString signature; 215 bool has_certs; 216 std::vector<der::Input> certs; 217 }; 218 219 // From RFC 6960: 220 // 221 // id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp } 222 // id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 } 223 // 224 // In dotted notation: 1.3.6.1.5.5.7.48.1.1 225 inline constexpr uint8_t kBasicOCSPResponseOid[] = { 226 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01}; 227 228 // Parses a DER-encoded OCSP "CertID" as specified by RFC 6960. Returns true on 229 // success and sets the results in |out|. 230 // 231 // On failure |out| has an undefined state. Some of its fields may have been 232 // updated during parsing, whereas others may not have been changed. 233 OPENSSL_EXPORT bool ParseOCSPCertID(der::Input raw_tlv, OCSPCertID *out); 234 235 // Parses a DER-encoded OCSP "SingleResponse" as specified by RFC 6960. Returns 236 // true on success and sets the results in |out|. The resulting |out| 237 // references data from |raw_tlv| and is only valid for the lifetime of 238 // |raw_tlv|. 239 // 240 // On failure |out| has an undefined state. Some of its fields may have been 241 // updated during parsing, whereas others may not have been changed. 242 OPENSSL_EXPORT bool ParseOCSPSingleResponse(der::Input raw_tlv, 243 OCSPSingleResponse *out); 244 245 // Parses a DER-encoded OCSP "ResponseData" as specified by RFC 6960. Returns 246 // true on success and sets the results in |out|. The resulting |out| 247 // references data from |raw_tlv| and is only valid for the lifetime of 248 // |raw_tlv|. 249 // 250 // On failure |out| has an undefined state. Some of its fields may have been 251 // updated during parsing, whereas others may not have been changed. 252 OPENSSL_EXPORT bool ParseOCSPResponseData(der::Input raw_tlv, 253 OCSPResponseData *out); 254 255 // Parses a DER-encoded "OCSPResponse" as specified by RFC 6960. Returns true 256 // on success and sets the results in |out|. The resulting |out| 257 // references data from |raw_tlv| and is only valid for the lifetime of 258 // |raw_tlv|. 259 // 260 // On failure |out| has an undefined state. Some of its fields may have been 261 // updated during parsing, whereas others may not have been changed. 262 OPENSSL_EXPORT bool ParseOCSPResponse(der::Input raw_tlv, OCSPResponse *out); 263 264 // Checks the revocation status of the certificate |certificate_der| by using 265 // the DER-encoded |raw_response|. 266 // 267 // Returns GOOD if the OCSP response indicates the certificate is not revoked, 268 // REVOKED if it indicates it is revoked, or UNKNOWN for all other cases. 269 // 270 // * |raw_response|: A DER encoded OCSPResponse. 271 // * |certificate_der|: The certificate being checked for revocation. 272 // * |issuer_certificate_der|: The certificate that signed |certificate_der|. 273 // The caller must have already performed path verification. 274 // * |verify_time_epoch_seconds|: The time as the difference in seconds from 275 // the POSIX epoch to use when checking revocation status. 276 // * |max_age_seconds|: The maximum age in seconds for a CRL, implemented as 277 // time since the |thisUpdate| field in the CRL TBSCertList. Responses 278 // older than |max_age_seconds| will be considered invalid. 279 // * |response_details|: Additional details about failures. 280 [[nodiscard]] OPENSSL_EXPORT OCSPRevocationStatus CheckOCSP( 281 std::string_view raw_response, std::string_view certificate_der, 282 std::string_view issuer_certificate_der, int64_t verify_time_epoch_seconds, 283 std::optional<int64_t> max_age_seconds, 284 OCSPVerifyResult::ResponseStatus *response_details); 285 286 // Checks the revocation status of |certificate| by using the DER-encoded 287 // |raw_response|. 288 // 289 // Arguments are the same as above, except that it takes already parsed 290 // instances of the certificate and issuer certificate. 291 [[nodiscard]] OPENSSL_EXPORT OCSPRevocationStatus CheckOCSP( 292 std::string_view raw_response, const ParsedCertificate *certificate, 293 const ParsedCertificate *issuer_certificate, 294 int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds, 295 OCSPVerifyResult::ResponseStatus *response_details); 296 297 // Creates a DER-encoded OCSPRequest for |cert|. The request is fairly basic: 298 // * No signature 299 // * No requestorName 300 // * No extensions 301 // * Uses SHA1 for all hashes. 302 // 303 // Returns true on success and fills |request_der| with the resulting bytes. 304 OPENSSL_EXPORT bool CreateOCSPRequest(const ParsedCertificate *cert, 305 const ParsedCertificate *issuer, 306 std::vector<uint8_t> *request_der); 307 308 // Creates a URL to issue a GET request for OCSP information for |cert|. 309 OPENSSL_EXPORT std::optional<std::string> CreateOCSPGetURL( 310 const ParsedCertificate *cert, const ParsedCertificate *issuer, 311 std::string_view ocsp_responder_url); 312 313 } // namespace bssl 314 315 #endif // BSSL_PKI_OCSP_H_ 316