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 "fillins/openssl_util.h" 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 14 #include "ocsp_revocation_status.h" 15 #include "ocsp_verify_result.h" 16 #include "signature_algorithm.h" 17 #include "input.h" 18 #include "parse_values.h" 19 #include "parser.h" 20 #include <optional> 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(const der::Input& raw_tlv, 234 OCSPCertID* out); 235 236 // Parses a DER-encoded OCSP "SingleResponse" as specified by RFC 6960. Returns 237 // true on success and sets the results in |out|. The resulting |out| 238 // references data from |raw_tlv| and is only valid for the lifetime of 239 // |raw_tlv|. 240 // 241 // On failure |out| has an undefined state. Some of its fields may have been 242 // updated during parsing, whereas others may not have been changed. 243 OPENSSL_EXPORT bool ParseOCSPSingleResponse(const der::Input& raw_tlv, 244 OCSPSingleResponse* out); 245 246 // Parses a DER-encoded OCSP "ResponseData" as specified by RFC 6960. Returns 247 // true on success and sets the results in |out|. The resulting |out| 248 // references data from |raw_tlv| and is only valid for the lifetime of 249 // |raw_tlv|. 250 // 251 // On failure |out| has an undefined state. Some of its fields may have been 252 // updated during parsing, whereas others may not have been changed. 253 OPENSSL_EXPORT bool ParseOCSPResponseData(const der::Input& raw_tlv, 254 OCSPResponseData* out); 255 256 // Parses a DER-encoded "OCSPResponse" as specified by RFC 6960. Returns true 257 // on success and sets the results in |out|. The resulting |out| 258 // references data from |raw_tlv| and is only valid for the lifetime of 259 // |raw_tlv|. 260 // 261 // On failure |out| has an undefined state. Some of its fields may have been 262 // updated during parsing, whereas others may not have been changed. 263 OPENSSL_EXPORT bool ParseOCSPResponse(const der::Input& raw_tlv, 264 OCSPResponse* out); 265 266 // Checks the revocation status of the certificate |certificate_der| by using 267 // the DER-encoded |raw_response|. 268 // 269 // Returns GOOD if the OCSP response indicates the certificate is not revoked, 270 // REVOKED if it indicates it is revoked, or UNKNOWN for all other cases. 271 // 272 // * |raw_response|: A DER encoded OCSPResponse. 273 // * |certificate_der|: The certificate being checked for revocation. 274 // * |issuer_certificate_der|: The certificate that signed |certificate_der|. 275 // The caller must have already performed path verification. 276 // * |verify_time_epoch_seconds|: The time as the difference in seconds from 277 // the POSIX epoch to use when checking revocation status. 278 // * |max_age_seconds|: The maximum age in seconds for a CRL, implemented as 279 // time since the |thisUpdate| field in the CRL TBSCertList. Responses 280 // older than |max_age_seconds| will be considered invalid. 281 // * |response_details|: Additional details about failures. 282 [[nodiscard]] OPENSSL_EXPORT OCSPRevocationStatus 283 CheckOCSP(std::string_view raw_response, 284 std::string_view certificate_der, 285 std::string_view issuer_certificate_der, 286 int64_t verify_time_epoch_seconds, 287 std::optional<int64_t> max_age_seconds, 288 OCSPVerifyResult::ResponseStatus* response_details); 289 290 // Checks the revocation status of |certificate| by using the DER-encoded 291 // |raw_response|. 292 // 293 // Arguments are the same as above, except that it takes already parsed 294 // instances of the certificate and issuer certificate. 295 [[nodiscard]] OPENSSL_EXPORT OCSPRevocationStatus 296 CheckOCSP(std::string_view raw_response, 297 const ParsedCertificate* certificate, 298 const ParsedCertificate* issuer_certificate, 299 int64_t verify_time_epoch_seconds, 300 std::optional<int64_t> max_age_seconds, 301 OCSPVerifyResult::ResponseStatus* response_details); 302 303 // Creates a DER-encoded OCSPRequest for |cert|. The request is fairly basic: 304 // * No signature 305 // * No requestorName 306 // * No extensions 307 // * Uses SHA1 for all hashes. 308 // 309 // Returns true on success and fills |request_der| with the resulting bytes. 310 OPENSSL_EXPORT bool CreateOCSPRequest(const ParsedCertificate* cert, 311 const ParsedCertificate* issuer, 312 std::vector<uint8_t>* request_der); 313 314 // Creates a URL to issue a GET request for OCSP information for |cert|. 315 OPENSSL_EXPORT std::optional<std::string> CreateOCSPGetURL( 316 const ParsedCertificate* cert, 317 const ParsedCertificate* issuer, 318 std::string_view ocsp_responder_url); 319 320 } // namespace net 321 322 #endif // BSSL_PKI_OCSP_H_ 323