• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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