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