blob: 69c41c8ed3f1a6d8c9005e451c93f16ba513e2de [file] [log] [blame]
Bob Beckbc97b7a2023-04-18 08:35:15 -06001// 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
Bob Beckbc97b7a2023-04-18 08:35:15 -06008#include "fillins/openssl_util.h"
Bob Beckbc97b7a2023-04-18 08:35:15 -06009#include <memory>
Bob Beck300f2212023-08-16 22:18:25 +000010#include <string>
Bob Beckbc97b7a2023-04-18 08:35:15 -060011#include <vector>
12
13
14#include "ocsp_revocation_status.h"
15#include "ocsp_verify_result.h"
Bob Beckbc97b7a2023-04-18 08:35:15 -060016#include "signature_algorithm.h"
17#include "input.h"
18#include "parse_values.h"
19#include "parser.h"
Bob Beck300f2212023-08-16 22:18:25 +000020#include <optional>
Bob Beckbc97b7a2023-04-18 08:35:15 -060021
22namespace bssl {
23
24class 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// }
34struct 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)
76struct 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// }
114struct 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// }
140struct 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// }
194struct 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
225inline 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.
233OPENSSL_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.
243OPENSSL_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.
253OPENSSL_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.
263OPENSSL_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
283CheckOCSP(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
296CheckOCSP(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.
310OPENSSL_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|.
Bob Beck300f2212023-08-16 22:18:25 +0000315OPENSSL_EXPORT std::optional<std::string> CreateOCSPGetURL(
316 const ParsedCertificate* cert,
317 const ParsedCertificate* issuer,
318 std::string_view ocsp_responder_url);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600319
320} // namespace net
321
322#endif // BSSL_PKI_OCSP_H_