blob: 54afab5418e1582cb1fd859f9ba61f60d0a0288b [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
Bob Beckbc97b7a2023-04-18 08:35:15 -06005#include "ocsp.h"
6
Bob Beck5c7a2a02023-11-20 17:28:21 -07007#include <openssl/bytestring.h>
8#include <openssl/digest.h>
9#include <openssl/mem.h>
10#include <openssl/pool.h>
11#include <openssl/sha.h>
Bob Beckbc97b7a2023-04-18 08:35:15 -060012#include "cert_errors.h"
13#include "extended_key_usage.h"
14#include "parsed_certificate.h"
15#include "revocation_util.h"
16#include "string_util.h"
17#include "verify_name_match.h"
18#include "verify_signed_data.h"
Bob Beckbc97b7a2023-04-18 08:35:15 -060019
20namespace bssl {
21
22OCSPCertID::OCSPCertID() = default;
23OCSPCertID::~OCSPCertID() = default;
24
25OCSPSingleResponse::OCSPSingleResponse() = default;
26OCSPSingleResponse::~OCSPSingleResponse() = default;
27
28OCSPResponseData::OCSPResponseData() = default;
29OCSPResponseData::~OCSPResponseData() = default;
30
31OCSPResponse::OCSPResponse() = default;
32OCSPResponse::~OCSPResponse() = default;
33
34// CertID ::= SEQUENCE {
35// hashAlgorithm AlgorithmIdentifier,
36// issuerNameHash OCTET STRING, -- Hash of issuer's DN
37// issuerKeyHash OCTET STRING, -- Hash of issuer's public key
38// serialNumber CertificateSerialNumber
39// }
Bob Beck5c7a2a02023-11-20 17:28:21 -070040bool ParseOCSPCertID(const der::Input &raw_tlv, OCSPCertID *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060041 der::Parser outer_parser(raw_tlv);
42 der::Parser parser;
Bob Beck6beabf32023-11-21 09:43:52 -070043 if (!outer_parser.ReadSequence(&parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060044 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070045 }
46 if (outer_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060047 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070048 }
Bob Beckbc97b7a2023-04-18 08:35:15 -060049
50 der::Input sigalg_tlv;
Bob Beck6beabf32023-11-21 09:43:52 -070051 if (!parser.ReadRawTLV(&sigalg_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060052 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070053 }
54 if (!ParseHashAlgorithm(sigalg_tlv, &(out->hash_algorithm))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060055 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070056 }
57 if (!parser.ReadTag(der::kOctetString, &(out->issuer_name_hash))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060058 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070059 }
60 if (!parser.ReadTag(der::kOctetString, &(out->issuer_key_hash))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060061 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070062 }
63 if (!parser.ReadTag(der::kInteger, &(out->serial_number))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060064 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070065 }
Bob Beckbc97b7a2023-04-18 08:35:15 -060066 CertErrors errors;
Bob Beck6beabf32023-11-21 09:43:52 -070067 if (!VerifySerialNumber(out->serial_number, false /*warnings_only*/,
68 &errors)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060069 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070070 }
Bob Beckbc97b7a2023-04-18 08:35:15 -060071
72 return !parser.HasMore();
73}
74
75namespace {
76
77// Parses |raw_tlv| to extract an OCSP RevokedInfo (RFC 6960) and stores the
78// result in the OCSPCertStatus |out|. Returns whether the parsing was
79// successful.
80//
81// RevokedInfo ::= SEQUENCE {
82// revocationTime GeneralizedTime,
83// revocationReason [0] EXPLICIT CRLReason OPTIONAL
84// }
Bob Beck5c7a2a02023-11-20 17:28:21 -070085bool ParseRevokedInfo(const der::Input &raw_tlv, OCSPCertStatus *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060086 der::Parser parser(raw_tlv);
Bob Beck6beabf32023-11-21 09:43:52 -070087 if (!parser.ReadGeneralizedTime(&(out->revocation_time))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060088 return false;
Bob Beck6beabf32023-11-21 09:43:52 -070089 }
Bob Beckbc97b7a2023-04-18 08:35:15 -060090
91 der::Input reason_input;
92 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &reason_input,
93 &(out->has_reason))) {
94 return false;
95 }
96 if (out->has_reason) {
97 der::Parser reason_parser(reason_input);
98 der::Input reason_value_input;
99 uint8_t reason_value;
Bob Beck6beabf32023-11-21 09:43:52 -0700100 if (!reason_parser.ReadTag(der::kEnumerated, &reason_value_input)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600101 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700102 }
103 if (!der::ParseUint8(reason_value_input, &reason_value)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600104 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700105 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600106 if (reason_value >
107 static_cast<uint8_t>(OCSPCertStatus::RevocationReason::LAST)) {
108 return false;
109 }
110 out->revocation_reason =
111 static_cast<OCSPCertStatus::RevocationReason>(reason_value);
Bob Beck6beabf32023-11-21 09:43:52 -0700112 if (out->revocation_reason == OCSPCertStatus::RevocationReason::UNUSED) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600113 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700114 }
115 if (reason_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600116 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700117 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600118 }
119 return !parser.HasMore();
120}
121
122// Parses |raw_tlv| to extract an OCSP CertStatus (RFC 6960) and stores the
123// result in the OCSPCertStatus |out|. Returns whether the parsing was
124// successful.
125//
126// CertStatus ::= CHOICE {
127// good [0] IMPLICIT NULL,
128// revoked [1] IMPLICIT RevokedInfo,
129// unknown [2] IMPLICIT UnknownInfo
130// }
131//
132// UnknownInfo ::= NULL
Bob Beck5c7a2a02023-11-20 17:28:21 -0700133bool ParseCertStatus(const der::Input &raw_tlv, OCSPCertStatus *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600134 der::Parser parser(raw_tlv);
135 der::Tag status_tag;
136 der::Input status;
Bob Beck6beabf32023-11-21 09:43:52 -0700137 if (!parser.ReadTagAndValue(&status_tag, &status)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600138 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700139 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600140
141 out->has_reason = false;
142 if (status_tag == der::ContextSpecificPrimitive(0)) {
143 out->status = OCSPRevocationStatus::GOOD;
144 } else if (status_tag == der::ContextSpecificConstructed(1)) {
145 out->status = OCSPRevocationStatus::REVOKED;
Bob Beck6beabf32023-11-21 09:43:52 -0700146 if (!ParseRevokedInfo(status, out)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600147 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700148 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600149 } else if (status_tag == der::ContextSpecificPrimitive(2)) {
150 out->status = OCSPRevocationStatus::UNKNOWN;
151 } else {
152 return false;
153 }
154
155 return !parser.HasMore();
156}
157
158// Writes the hash of |value| as an OCTET STRING to |cbb|, using |hash_type| as
159// the algorithm. Returns true on success.
Bob Beck5c7a2a02023-11-20 17:28:21 -0700160bool AppendHashAsOctetString(const EVP_MD *hash_type, CBB *cbb,
161 const der::Input &value) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600162 CBB octet_string;
163 unsigned hash_len;
164 uint8_t hash_buffer[EVP_MAX_MD_SIZE];
165
166 return CBB_add_asn1(cbb, &octet_string, CBS_ASN1_OCTETSTRING) &&
167 EVP_Digest(value.UnsafeData(), value.Length(), hash_buffer, &hash_len,
168 hash_type, nullptr) &&
169 CBB_add_bytes(&octet_string, hash_buffer, hash_len) && CBB_flush(cbb);
170}
171
172} // namespace
173
174// SingleResponse ::= SEQUENCE {
175// certID CertID,
176// certStatus CertStatus,
177// thisUpdate GeneralizedTime,
178// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
179// singleExtensions [1] EXPLICIT Extensions OPTIONAL
180// }
Bob Beck5c7a2a02023-11-20 17:28:21 -0700181bool ParseOCSPSingleResponse(const der::Input &raw_tlv,
182 OCSPSingleResponse *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600183 der::Parser outer_parser(raw_tlv);
184 der::Parser parser;
Bob Beck6beabf32023-11-21 09:43:52 -0700185 if (!outer_parser.ReadSequence(&parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600186 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700187 }
188 if (outer_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600189 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700190 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600191
Bob Beck6beabf32023-11-21 09:43:52 -0700192 if (!parser.ReadRawTLV(&(out->cert_id_tlv))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600193 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700194 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600195 der::Input status_tlv;
Bob Beck6beabf32023-11-21 09:43:52 -0700196 if (!parser.ReadRawTLV(&status_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600197 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700198 }
199 if (!ParseCertStatus(status_tlv, &(out->cert_status))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600200 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700201 }
202 if (!parser.ReadGeneralizedTime(&(out->this_update))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600203 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700204 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600205
206 der::Input next_update_input;
207 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
208 &next_update_input, &(out->has_next_update))) {
209 return false;
210 }
211 if (out->has_next_update) {
212 der::Parser next_update_parser(next_update_input);
Bob Beck6beabf32023-11-21 09:43:52 -0700213 if (!next_update_parser.ReadGeneralizedTime(&(out->next_update))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600214 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700215 }
216 if (next_update_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600217 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700218 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600219 }
220
221 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
222 &(out->extensions), &(out->has_extensions))) {
223 return false;
224 }
225
226 return !parser.HasMore();
227}
228
229namespace {
230
231// Parses |raw_tlv| to extract a ResponderID (RFC 6960) and stores the
232// result in the ResponderID |out|. Returns whether the parsing was successful.
233//
234// ResponderID ::= CHOICE {
235// byName [1] Name,
236// byKey [2] KeyHash
237// }
Bob Beck5c7a2a02023-11-20 17:28:21 -0700238bool ParseResponderID(const der::Input &raw_tlv,
239 OCSPResponseData::ResponderID *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600240 der::Parser parser(raw_tlv);
241 der::Tag id_tag;
242 der::Input id_input;
Bob Beck6beabf32023-11-21 09:43:52 -0700243 if (!parser.ReadTagAndValue(&id_tag, &id_input)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600244 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700245 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600246
247 if (id_tag == der::ContextSpecificConstructed(1)) {
248 out->type = OCSPResponseData::ResponderType::NAME;
249 out->name = id_input;
250 } else if (id_tag == der::ContextSpecificConstructed(2)) {
251 der::Parser key_parser(id_input);
252 der::Input key_hash;
Bob Beck6beabf32023-11-21 09:43:52 -0700253 if (!key_parser.ReadTag(der::kOctetString, &key_hash)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600254 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700255 }
256 if (key_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600257 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700258 }
259 if (key_hash.Length() != SHA_DIGEST_LENGTH) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600260 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700261 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600262
263 out->type = OCSPResponseData::ResponderType::KEY_HASH;
264 out->key_hash = key_hash;
265 } else {
266 return false;
267 }
268 return !parser.HasMore();
269}
270
271} // namespace
272
273// ResponseData ::= SEQUENCE {
274// version [0] EXPLICIT Version DEFAULT v1,
275// responderID ResponderID,
276// producedAt GeneralizedTime,
277// responses SEQUENCE OF SingleResponse,
278// responseExtensions [1] EXPLICIT Extensions OPTIONAL
279// }
Bob Beck5c7a2a02023-11-20 17:28:21 -0700280bool ParseOCSPResponseData(const der::Input &raw_tlv, OCSPResponseData *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600281 der::Parser outer_parser(raw_tlv);
282 der::Parser parser;
Bob Beck6beabf32023-11-21 09:43:52 -0700283 if (!outer_parser.ReadSequence(&parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600284 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700285 }
286 if (outer_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600287 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700288 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600289
290 der::Input version_input;
291 bool version_present;
292 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
293 &version_input, &version_present)) {
294 return false;
295 }
296
297 // For compatibilty, we ignore the restriction from X.690 Section 11.5 that
298 // DEFAULT values should be omitted for values equal to the default value.
299 // TODO: Add warning about non-strict parsing.
300 if (version_present) {
301 der::Parser version_parser(version_input);
Bob Beck6beabf32023-11-21 09:43:52 -0700302 if (!version_parser.ReadUint8(&(out->version))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600303 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700304 }
305 if (version_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600306 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700307 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600308 } else {
309 out->version = 0;
310 }
311
Bob Beck6beabf32023-11-21 09:43:52 -0700312 if (out->version != 0) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600313 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700314 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600315
316 der::Input responder_input;
Bob Beck6beabf32023-11-21 09:43:52 -0700317 if (!parser.ReadRawTLV(&responder_input)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600318 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700319 }
320 if (!ParseResponderID(responder_input, &(out->responder_id))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600321 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700322 }
323 if (!parser.ReadGeneralizedTime(&(out->produced_at))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600324 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700325 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600326
327 der::Parser responses_parser;
Bob Beck6beabf32023-11-21 09:43:52 -0700328 if (!parser.ReadSequence(&responses_parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600329 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700330 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600331 out->responses.clear();
332 while (responses_parser.HasMore()) {
333 der::Input single_response;
Bob Beck6beabf32023-11-21 09:43:52 -0700334 if (!responses_parser.ReadRawTLV(&single_response)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600335 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700336 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600337 out->responses.push_back(single_response);
338 }
339
340 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
341 &(out->extensions), &(out->has_extensions))) {
342 return false;
343 }
344
345 return !parser.HasMore();
346}
347
348namespace {
349
350// Parses |raw_tlv| to extract a BasicOCSPResponse (RFC 6960) and stores the
351// result in the OCSPResponse |out|. Returns whether the parsing was
352// successful.
353//
354// BasicOCSPResponse ::= SEQUENCE {
355// tbsResponseData ResponseData,
356// signatureAlgorithm AlgorithmIdentifier,
357// signature BIT STRING,
358// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
359// }
Bob Beck5c7a2a02023-11-20 17:28:21 -0700360bool ParseBasicOCSPResponse(const der::Input &raw_tlv, OCSPResponse *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600361 der::Parser outer_parser(raw_tlv);
362 der::Parser parser;
Bob Beck6beabf32023-11-21 09:43:52 -0700363 if (!outer_parser.ReadSequence(&parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600364 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700365 }
366 if (outer_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600367 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700368 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600369
Bob Beck6beabf32023-11-21 09:43:52 -0700370 if (!parser.ReadRawTLV(&(out->data))) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600371 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700372 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600373 der::Input sigalg_tlv;
Bob Beck6beabf32023-11-21 09:43:52 -0700374 if (!parser.ReadRawTLV(&sigalg_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600375 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700376 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600377 // TODO(crbug.com/634443): Propagate the errors.
378 std::optional<SignatureAlgorithm> sigalg =
379 ParseSignatureAlgorithm(sigalg_tlv);
Bob Beck6beabf32023-11-21 09:43:52 -0700380 if (!sigalg) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600381 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700382 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600383 out->signature_algorithm = sigalg.value();
384 std::optional<der::BitString> signature = parser.ReadBitString();
Bob Beck6beabf32023-11-21 09:43:52 -0700385 if (!signature) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600386 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700387 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600388 out->signature = signature.value();
389 der::Input certs_input;
390 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &certs_input,
391 &(out->has_certs))) {
392 return false;
393 }
394
395 out->certs.clear();
396 if (out->has_certs) {
397 der::Parser certs_seq_parser(certs_input);
398 der::Parser certs_parser;
Bob Beck6beabf32023-11-21 09:43:52 -0700399 if (!certs_seq_parser.ReadSequence(&certs_parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600400 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700401 }
402 if (certs_seq_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600403 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700404 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600405 while (certs_parser.HasMore()) {
406 der::Input cert_tlv;
Bob Beck6beabf32023-11-21 09:43:52 -0700407 if (!certs_parser.ReadRawTLV(&cert_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600408 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700409 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600410 out->certs.push_back(cert_tlv);
411 }
412 }
413
414 return !parser.HasMore();
415}
416
417} // namespace
418
419// OCSPResponse ::= SEQUENCE {
420// responseStatus OCSPResponseStatus,
421// responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
422// }
423//
424// ResponseBytes ::= SEQUENCE {
425// responseType OBJECT IDENTIFIER,
426// response OCTET STRING
427// }
Bob Beck5c7a2a02023-11-20 17:28:21 -0700428bool ParseOCSPResponse(const der::Input &raw_tlv, OCSPResponse *out) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600429 der::Parser outer_parser(raw_tlv);
430 der::Parser parser;
Bob Beck6beabf32023-11-21 09:43:52 -0700431 if (!outer_parser.ReadSequence(&parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600432 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700433 }
434 if (outer_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600435 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700436 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600437
438 der::Input response_status_input;
439 uint8_t response_status;
Bob Beck6beabf32023-11-21 09:43:52 -0700440 if (!parser.ReadTag(der::kEnumerated, &response_status_input)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600441 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700442 }
443 if (!der::ParseUint8(response_status_input, &response_status)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600444 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700445 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600446 if (response_status >
447 static_cast<uint8_t>(OCSPResponse::ResponseStatus::LAST)) {
448 return false;
449 }
450 out->status = static_cast<OCSPResponse::ResponseStatus>(response_status);
Bob Beck6beabf32023-11-21 09:43:52 -0700451 if (out->status == OCSPResponse::ResponseStatus::UNUSED) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600452 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700453 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600454
455 if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) {
456 der::Parser outer_bytes_parser;
457 der::Parser bytes_parser;
458 if (!parser.ReadConstructed(der::ContextSpecificConstructed(0),
459 &outer_bytes_parser)) {
460 return false;
461 }
Bob Beck6beabf32023-11-21 09:43:52 -0700462 if (!outer_bytes_parser.ReadSequence(&bytes_parser)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600463 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700464 }
465 if (outer_bytes_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600466 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700467 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600468
469 der::Input type_oid;
Bob Beck6beabf32023-11-21 09:43:52 -0700470 if (!bytes_parser.ReadTag(der::kOid, &type_oid)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600471 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700472 }
473 if (type_oid != der::Input(kBasicOCSPResponseOid)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600474 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700475 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600476
477 // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER
478 // encoding of BasicOCSPResponse.
479 der::Input response;
Bob Beck6beabf32023-11-21 09:43:52 -0700480 if (!bytes_parser.ReadTag(der::kOctetString, &response)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600481 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700482 }
483 if (!ParseBasicOCSPResponse(response, out)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600484 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700485 }
486 if (bytes_parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600487 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700488 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600489 }
490
491 return !parser.HasMore();
492}
493
494namespace {
495
496// Checks that the |type| hash of |value| is equal to |hash|
Bob Beck5c7a2a02023-11-20 17:28:21 -0700497bool VerifyHash(const EVP_MD *type, const der::Input &hash,
498 const der::Input &value) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600499 unsigned value_hash_len;
500 uint8_t value_hash[EVP_MAX_MD_SIZE];
501 if (!EVP_Digest(value.UnsafeData(), value.Length(), value_hash,
502 &value_hash_len, type, nullptr)) {
503 return false;
504 }
505
506 return hash == der::Input(value_hash, value_hash_len);
507}
508
509// Extracts the bytes of the SubjectPublicKey bit string given an SPKI. That is
510// to say, the value of subjectPublicKey without the leading unused bit
511// count octet.
512//
513// Returns true on success and fills |*spk_tlv| with the result.
514//
515// From RFC 5280, Section 4.1
516// SubjectPublicKeyInfo ::= SEQUENCE {
517// algorithm AlgorithmIdentifier,
518// subjectPublicKey BIT STRING }
519//
520// AlgorithmIdentifier ::= SEQUENCE {
521// algorithm OBJECT IDENTIFIER,
522// parameters ANY DEFINED BY algorithm OPTIONAL }
523//
Bob Beck5c7a2a02023-11-20 17:28:21 -0700524bool GetSubjectPublicKeyBytes(const der::Input &spki_tlv, der::Input *spk_tlv) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600525 CBS outer, inner, alg, spk;
526 uint8_t unused_bit_count;
527 CBS_init(&outer, spki_tlv.UnsafeData(), spki_tlv.Length());
528 // The subjectPublicKey field includes the unused bit count. For this
529 // application, the unused bit count must be zero, and is not included in
530 // the result. We extract the subjectPubicKey bit string, verify the first
531 // byte is 0, and if so set |spk_tlv| to the remaining bytes.
532 if (!CBS_get_asn1(&outer, &inner, CBS_ASN1_SEQUENCE) ||
533 !CBS_get_asn1(&inner, &alg, CBS_ASN1_SEQUENCE) ||
534 !CBS_get_asn1(&inner, &spk, CBS_ASN1_BITSTRING) ||
535 !CBS_get_u8(&spk, &unused_bit_count) || unused_bit_count != 0) {
536 return false;
537 }
538 *spk_tlv = der::Input(CBS_data(&spk), CBS_len(&spk));
539 return true;
540}
541
542// Checks the OCSPCertID |id| identifies |certificate|.
543bool CheckCertIDMatchesCertificate(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700544 const OCSPCertID &id, const ParsedCertificate *certificate,
545 const ParsedCertificate *issuer_certificate) {
546 const EVP_MD *type = nullptr;
Bob Beckbc97b7a2023-04-18 08:35:15 -0600547 switch (id.hash_algorithm) {
548 case DigestAlgorithm::Md2:
549 case DigestAlgorithm::Md4:
550 case DigestAlgorithm::Md5:
551 // Unsupported.
552 return false;
553 case DigestAlgorithm::Sha1:
554 type = EVP_sha1();
555 break;
556 case DigestAlgorithm::Sha256:
557 type = EVP_sha256();
558 break;
559 case DigestAlgorithm::Sha384:
560 type = EVP_sha384();
561 break;
562 case DigestAlgorithm::Sha512:
563 type = EVP_sha512();
564 break;
565 }
566
Bob Beck6beabf32023-11-21 09:43:52 -0700567 if (!VerifyHash(type, id.issuer_name_hash, certificate->tbs().issuer_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600568 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700569 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600570
571 der::Input key_tlv;
Bob Beck6beabf32023-11-21 09:43:52 -0700572 if (!GetSubjectPublicKeyBytes(issuer_certificate->tbs().spki_tlv, &key_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600573 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700574 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600575
Bob Beck6beabf32023-11-21 09:43:52 -0700576 if (!VerifyHash(type, id.issuer_key_hash, key_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600577 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700578 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600579
580 return id.serial_number == certificate->tbs().serial_number;
581}
582
583// TODO(eroman): Revisit how certificate parsing is used by this file. Ideally
584// would either pass in the parsed bits, or have a better abstraction for lazily
585// parsing.
586std::shared_ptr<const ParsedCertificate> OCSPParseCertificate(
587 std::string_view der) {
588 ParseCertificateOptions parse_options;
589 parse_options.allow_invalid_serial_numbers = true;
590
Bob Beck300f2212023-08-16 22:18:25 +0000591 // The objects returned by this function only last for the duration of a
592 // single certificate verification, so there is no need to pool them to save
593 // memory.
594 //
Bob Beckbc97b7a2023-04-18 08:35:15 -0600595 // TODO(eroman): Swallows the parsing errors. However uses a permissive
596 // parsing model.
597 CertErrors errors;
598 return ParsedCertificate::Create(
Bob Beck300f2212023-08-16 22:18:25 +0000599 bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700600 reinterpret_cast<const uint8_t *>(der.data()), der.size(), nullptr)),
Bob Beckbc97b7a2023-04-18 08:35:15 -0600601 {}, &errors);
602}
603
604// Checks that the ResponderID |id| matches the certificate |cert| either
605// by verifying the name matches that of the certificate or that the hash
606// matches the certificate's public key hash (RFC 6960, 4.2.2.3).
607[[nodiscard]] bool CheckResponderIDMatchesCertificate(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700608 const OCSPResponseData::ResponderID &id, const ParsedCertificate *cert) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600609 switch (id.type) {
610 case OCSPResponseData::ResponderType::NAME: {
611 der::Input name_rdn;
612 der::Input cert_rdn;
613 if (!der::Parser(id.name).ReadTag(der::kSequence, &name_rdn) ||
614 !der::Parser(cert->tbs().subject_tlv)
Bob Beck6beabf32023-11-21 09:43:52 -0700615 .ReadTag(der::kSequence, &cert_rdn)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600616 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700617 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600618 return VerifyNameMatch(name_rdn, cert_rdn);
619 }
620 case OCSPResponseData::ResponderType::KEY_HASH: {
621 der::Input key;
Bob Beck6beabf32023-11-21 09:43:52 -0700622 if (!GetSubjectPublicKeyBytes(cert->tbs().spki_tlv, &key)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600623 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700624 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600625 return VerifyHash(EVP_sha1(), id.key_hash, key);
626 }
627 }
628
629 return false;
630}
631
632// Verifies that |responder_certificate| has been authority for OCSP signing,
633// delegated to it by |issuer_certificate|.
634//
635// TODO(eroman): No revocation checks are done (see id-pkix-ocsp-nocheck in the
636// spec). extension).
637//
638// TODO(eroman): Not all properties of the certificate are verified, only the
639// signature and EKU. Can full RFC 5280 validation be used, or are there
640// compatibility concerns?
641[[nodiscard]] bool VerifyAuthorizedResponderCert(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700642 const ParsedCertificate *responder_certificate,
643 const ParsedCertificate *issuer_certificate) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600644 // The Authorized Responder must be directly signed by the issuer of the
645 // certificate being checked.
646 // TODO(eroman): Must check the signature algorithm against policy.
647 if (!responder_certificate->signature_algorithm().has_value() ||
648 !VerifySignedData(*responder_certificate->signature_algorithm(),
649 responder_certificate->tbs_certificate_tlv(),
650 responder_certificate->signature_value(),
651 issuer_certificate->tbs().spki_tlv,
652 /*cache=*/nullptr)) {
653 return false;
654 }
655
656 // The Authorized Responder must include the value id-kp-OCSPSigning as
657 // part of the extended key usage extension.
Bob Beck6beabf32023-11-21 09:43:52 -0700658 if (!responder_certificate->has_extended_key_usage()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600659 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700660 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600661
Bob Beck5c7a2a02023-11-20 17:28:21 -0700662 for (const auto &key_purpose_oid :
Bob Beckbc97b7a2023-04-18 08:35:15 -0600663 responder_certificate->extended_key_usage()) {
Bob Beck6beabf32023-11-21 09:43:52 -0700664 if (key_purpose_oid == der::Input(kOCSPSigning)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600665 return true;
Bob Beck6beabf32023-11-21 09:43:52 -0700666 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600667 }
668 return false;
669}
670
671[[nodiscard]] bool VerifyOCSPResponseSignatureGivenCert(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700672 const OCSPResponse &response, const ParsedCertificate *cert) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600673 // TODO(eroman): Must check the signature algorithm against policy.
674 return VerifySignedData(response.signature_algorithm, response.data,
675 response.signature, cert->tbs().spki_tlv,
676 /*cache=*/nullptr);
677}
678
679// Verifies that the OCSP response has a valid signature using
680// |issuer_certificate|, or an authorized responder issued by
681// |issuer_certificate| for OCSP signing.
682[[nodiscard]] bool VerifyOCSPResponseSignature(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700683 const OCSPResponse &response, const OCSPResponseData &response_data,
684 const ParsedCertificate *issuer_certificate) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600685 // In order to verify the OCSP signature, a valid responder matching the OCSP
686 // Responder ID must be located (RFC 6960, 4.2.2.2). The responder is allowed
687 // to be either the certificate issuer or a delegated authority directly
688 // signed by the issuer.
689 if (CheckResponderIDMatchesCertificate(response_data.responder_id,
690 issuer_certificate) &&
691 VerifyOCSPResponseSignatureGivenCert(response, issuer_certificate)) {
692 return true;
693 }
694
695 // Otherwise search through the provided certificates for the Authorized
696 // Responder. Want a certificate that:
697 // (1) Matches the OCSP Responder ID.
698 // (2) Has been given authority for OCSP signing by |issuer_certificate|.
699 // (3) Has signed the OCSP response using its public key.
Bob Beck5c7a2a02023-11-20 17:28:21 -0700700 for (const auto &responder_cert_tlv : response.certs) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600701 std::shared_ptr<const ParsedCertificate> cur_responder_certificate =
702 OCSPParseCertificate(responder_cert_tlv.AsStringView());
703
704 // If failed parsing the certificate, keep looking.
Bob Beck6beabf32023-11-21 09:43:52 -0700705 if (!cur_responder_certificate) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600706 continue;
Bob Beck6beabf32023-11-21 09:43:52 -0700707 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600708
709 // If the certificate doesn't match the OCSP's responder ID, keep looking.
710 if (!CheckResponderIDMatchesCertificate(response_data.responder_id,
711 cur_responder_certificate.get())) {
712 continue;
713 }
714
715 // If the certificate isn't a valid Authorized Responder certificate, keep
716 // looking.
717 if (!VerifyAuthorizedResponderCert(cur_responder_certificate.get(),
718 issuer_certificate)) {
719 continue;
720 }
721
722 // If the certificate signed this OCSP response, have found a match.
723 // Otherwise keep looking.
724 if (VerifyOCSPResponseSignatureGivenCert(response,
725 cur_responder_certificate.get())) {
726 return true;
727 }
728 }
729
730 // Failed to confirm the validity of the OCSP signature using any of the
731 // candidate certificates.
732 return false;
733}
734
735// Parse ResponseData and return false if any unhandled critical extensions are
736// found. No known critical ResponseData extensions exist.
737bool ParseOCSPResponseDataExtensions(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700738 const der::Input &response_extensions,
739 OCSPVerifyResult::ResponseStatus *response_details) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600740 std::map<der::Input, ParsedExtension> extensions;
741 if (!ParseExtensions(response_extensions, &extensions)) {
742 *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
743 return false;
744 }
745
Bob Beck5c7a2a02023-11-20 17:28:21 -0700746 for (const auto &ext : extensions) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600747 // TODO: handle ResponseData extensions
748
749 if (ext.second.critical) {
750 *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
751 return false;
752 }
753 }
754
755 return true;
756}
757
758// Parse SingleResponse and return false if any unhandled critical extensions
759// (other than the CT extension) are found. The CT-SCT extension is not required
760// to be marked critical, but since it is handled by Chrome, we will overlook
761// the flag setting.
762bool ParseOCSPSingleResponseExtensions(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700763 const der::Input &single_extensions,
764 OCSPVerifyResult::ResponseStatus *response_details) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600765 std::map<der::Input, ParsedExtension> extensions;
766 if (!ParseExtensions(single_extensions, &extensions)) {
767 *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
768 return false;
769 }
770
771 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for
772 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see
773 // Section 3.3 of RFC6962.
774 const uint8_t ct_ocsp_ext_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
775 0xD6, 0x79, 0x02, 0x04, 0x05};
776 der::Input ct_ext_oid(ct_ocsp_ext_oid);
777
Bob Beck5c7a2a02023-11-20 17:28:21 -0700778 for (const auto &ext : extensions) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600779 // The CT OCSP extension is handled in ct::ExtractSCTListFromOCSPResponse
Bob Beck6beabf32023-11-21 09:43:52 -0700780 if (ext.second.oid == ct_ext_oid) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600781 continue;
Bob Beck6beabf32023-11-21 09:43:52 -0700782 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600783
784 // TODO: handle SingleResponse extensions
785
786 if (ext.second.critical) {
787 *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
788 return false;
789 }
790 }
791
792 return true;
793}
794
795// Loops through the OCSPSingleResponses to find the best match for |cert|.
796OCSPRevocationStatus GetRevocationStatusForCert(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700797 const OCSPResponseData &response_data, const ParsedCertificate *cert,
798 const ParsedCertificate *issuer_certificate,
799 int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
800 OCSPVerifyResult::ResponseStatus *response_details) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600801 OCSPRevocationStatus result = OCSPRevocationStatus::UNKNOWN;
802 *response_details = OCSPVerifyResult::NO_MATCHING_RESPONSE;
803
Bob Beck5c7a2a02023-11-20 17:28:21 -0700804 for (const auto &single_response_der : response_data.responses) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600805 // In the common case, there should only be one SingleResponse in the
806 // ResponseData (matching the certificate requested and used on this
807 // connection). However, it is possible for the OCSP responder to provide
808 // multiple responses for multiple certificates. Look through all the
809 // provided SingleResponses, and check to see if any match the
810 // certificate. A SingleResponse matches a certificate if it has the same
811 // serial number, issuer name (hash), and issuer public key (hash).
812 OCSPSingleResponse single_response;
Bob Beck6beabf32023-11-21 09:43:52 -0700813 if (!ParseOCSPSingleResponse(single_response_der, &single_response)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600814 return OCSPRevocationStatus::UNKNOWN;
Bob Beck6beabf32023-11-21 09:43:52 -0700815 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600816
817 // Reject unhandled critical extensions in SingleResponse
818 if (single_response.has_extensions &&
819 !ParseOCSPSingleResponseExtensions(single_response.extensions,
820 response_details)) {
821 return OCSPRevocationStatus::UNKNOWN;
822 }
823
824 OCSPCertID cert_id;
Bob Beck6beabf32023-11-21 09:43:52 -0700825 if (!ParseOCSPCertID(single_response.cert_id_tlv, &cert_id)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600826 return OCSPRevocationStatus::UNKNOWN;
Bob Beck6beabf32023-11-21 09:43:52 -0700827 }
828 if (!CheckCertIDMatchesCertificate(cert_id, cert, issuer_certificate)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600829 continue;
Bob Beck6beabf32023-11-21 09:43:52 -0700830 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600831
832 // The SingleResponse matches the certificate, but may be out of date. Out
833 // of date responses are noted seperate from responses with mismatched
834 // serial numbers. If an OCSP responder provides both an up to date
835 // response and an expired response, the up to date response takes
836 // precedence (PROVIDED > INVALID_DATE).
837 if (!CheckRevocationDateValid(single_response.this_update,
838 single_response.has_next_update
839 ? &single_response.next_update
840 : nullptr,
841 verify_time_epoch_seconds, max_age_seconds)) {
Bob Beck6beabf32023-11-21 09:43:52 -0700842 if (*response_details != OCSPVerifyResult::PROVIDED) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600843 *response_details = OCSPVerifyResult::INVALID_DATE;
Bob Beck6beabf32023-11-21 09:43:52 -0700844 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600845 continue;
846 }
847
848 // In the case with multiple matching and up to date responses, keep only
849 // the strictest status (REVOKED > UNKNOWN > GOOD).
850 if (*response_details != OCSPVerifyResult::PROVIDED ||
851 result == OCSPRevocationStatus::GOOD ||
852 single_response.cert_status.status == OCSPRevocationStatus::REVOKED) {
853 result = single_response.cert_status.status;
854 }
855 *response_details = OCSPVerifyResult::PROVIDED;
856 }
857
858 return result;
859}
860
861OCSPRevocationStatus CheckOCSP(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700862 std::string_view raw_response, std::string_view certificate_der,
863 const ParsedCertificate *certificate,
Bob Beckbc97b7a2023-04-18 08:35:15 -0600864 std::string_view issuer_certificate_der,
Bob Beck5c7a2a02023-11-20 17:28:21 -0700865 const ParsedCertificate *issuer_certificate,
866 int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
867 OCSPVerifyResult::ResponseStatus *response_details) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600868 *response_details = OCSPVerifyResult::NOT_CHECKED;
869
870 if (raw_response.empty()) {
871 *response_details = OCSPVerifyResult::MISSING;
872 return OCSPRevocationStatus::UNKNOWN;
873 }
874
875 der::Input response_der(raw_response);
876 OCSPResponse response;
877 if (!ParseOCSPResponse(response_der, &response)) {
878 *response_details = OCSPVerifyResult::PARSE_RESPONSE_ERROR;
879 return OCSPRevocationStatus::UNKNOWN;
880 }
881
882 // RFC 6960 defines all responses |response_status| != SUCCESSFUL as error
883 // responses. No revocation information is provided on error responses, and
884 // the OCSPResponseData structure is not set.
885 if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) {
886 *response_details = OCSPVerifyResult::ERROR_RESPONSE;
887 return OCSPRevocationStatus::UNKNOWN;
888 }
889
890 // Actual revocation information is contained within the BasicOCSPResponse as
891 // a ResponseData structure. The BasicOCSPResponse was parsed above, and
892 // contains an unparsed ResponseData. From RFC 6960:
893 //
894 // BasicOCSPResponse ::= SEQUENCE {
895 // tbsResponseData ResponseData,
896 // signatureAlgorithm AlgorithmIdentifier,
897 // signature BIT STRING,
898 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
899 //
900 // ResponseData ::= SEQUENCE {
901 // version [0] EXPLICIT Version DEFAULT v1,
902 // responderID ResponderID,
903 // producedAt GeneralizedTime,
904 // responses SEQUENCE OF SingleResponse,
905 // responseExtensions [1] EXPLICIT Extensions OPTIONAL }
906 OCSPResponseData response_data;
907 if (!ParseOCSPResponseData(response.data, &response_data)) {
908 *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
909 return OCSPRevocationStatus::UNKNOWN;
910 }
911
912 // Process the OCSP ResponseData extensions. In particular, must reject if
913 // there are any critical extensions that are not understood.
914 if (response_data.has_extensions &&
915 !ParseOCSPResponseDataExtensions(response_data.extensions,
916 response_details)) {
917 return OCSPRevocationStatus::UNKNOWN;
918 }
919
920 std::shared_ptr<const ParsedCertificate> parsed_certificate;
921 std::shared_ptr<const ParsedCertificate> parsed_issuer_certificate;
922 if (!certificate) {
923 parsed_certificate = OCSPParseCertificate(certificate_der);
924 certificate = parsed_certificate.get();
925 }
926 if (!issuer_certificate) {
927 parsed_issuer_certificate = OCSPParseCertificate(issuer_certificate_der);
928 issuer_certificate = parsed_issuer_certificate.get();
929 }
930
931 if (!certificate || !issuer_certificate) {
932 *response_details = OCSPVerifyResult::NOT_CHECKED;
933 return OCSPRevocationStatus::UNKNOWN;
934 }
935
936 // If producedAt is outside of the certificate validity period, reject the
937 // response.
938 if (response_data.produced_at < certificate->tbs().validity_not_before ||
939 response_data.produced_at > certificate->tbs().validity_not_after) {
940 *response_details = OCSPVerifyResult::BAD_PRODUCED_AT;
941 return OCSPRevocationStatus::UNKNOWN;
942 }
943
944 // Look through all of the OCSPSingleResponses for a match (based on CertID
945 // and time).
946 OCSPRevocationStatus status = GetRevocationStatusForCert(
947 response_data, certificate, issuer_certificate, verify_time_epoch_seconds,
948 max_age_seconds, response_details);
949
950 // Check that the OCSP response has a valid signature. It must either be
951 // signed directly by the issuing certificate, or a valid authorized
952 // responder.
953 if (!VerifyOCSPResponseSignature(response, response_data,
954 issuer_certificate)) {
955 return OCSPRevocationStatus::UNKNOWN;
956 }
957
958 return status;
959}
960
961} // namespace
962
963OCSPRevocationStatus CheckOCSP(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700964 std::string_view raw_response, std::string_view certificate_der,
965 std::string_view issuer_certificate_der, int64_t verify_time_epoch_seconds,
Bob Beckbc97b7a2023-04-18 08:35:15 -0600966 std::optional<int64_t> max_age_seconds,
Bob Beck5c7a2a02023-11-20 17:28:21 -0700967 OCSPVerifyResult::ResponseStatus *response_details) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600968 return CheckOCSP(raw_response, certificate_der, nullptr,
969 issuer_certificate_der, nullptr, verify_time_epoch_seconds,
970 max_age_seconds, response_details);
971}
972
973OCSPRevocationStatus CheckOCSP(
Bob Beck5c7a2a02023-11-20 17:28:21 -0700974 std::string_view raw_response, const ParsedCertificate *certificate,
975 const ParsedCertificate *issuer_certificate,
976 int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds,
977 OCSPVerifyResult::ResponseStatus *response_details) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600978 return CheckOCSP(raw_response, std::string_view(), certificate,
979 std::string_view(), issuer_certificate,
980 verify_time_epoch_seconds, max_age_seconds,
981 response_details);
982}
983
Bob Beck5c7a2a02023-11-20 17:28:21 -0700984bool CreateOCSPRequest(const ParsedCertificate *cert,
985 const ParsedCertificate *issuer,
986 std::vector<uint8_t> *request_der) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600987 request_der->clear();
988
989 bssl::ScopedCBB cbb;
990
991 // This initial buffer size is big enough for 20 octet long serial numbers
992 // (upper bound from RFC 5280) and then a handful of extra bytes. This
993 // number doesn't matter for correctness.
994 const size_t kInitialBufferSize = 100;
995
Bob Beck6beabf32023-11-21 09:43:52 -0700996 if (!CBB_init(cbb.get(), kInitialBufferSize)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600997 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700998 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600999
1000 // OCSPRequest ::= SEQUENCE {
1001 // tbsRequest TBSRequest,
1002 // optionalSignature [0] EXPLICIT Signature OPTIONAL }
1003 //
1004 // TBSRequest ::= SEQUENCE {
1005 // version [0] EXPLICIT Version DEFAULT v1,
1006 // requestorName [1] EXPLICIT GeneralName OPTIONAL,
1007 // requestList SEQUENCE OF Request,
1008 // requestExtensions [2] EXPLICIT Extensions OPTIONAL }
1009 CBB ocsp_request;
Bob Beck6beabf32023-11-21 09:43:52 -07001010 if (!CBB_add_asn1(cbb.get(), &ocsp_request, CBS_ASN1_SEQUENCE)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001011 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001012 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001013
1014 CBB tbs_request;
Bob Beck6beabf32023-11-21 09:43:52 -07001015 if (!CBB_add_asn1(&ocsp_request, &tbs_request, CBS_ASN1_SEQUENCE)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001016 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001017 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001018
1019 // "version", "requestorName", and "requestExtensions" are omitted.
1020
1021 CBB request_list;
Bob Beck6beabf32023-11-21 09:43:52 -07001022 if (!CBB_add_asn1(&tbs_request, &request_list, CBS_ASN1_SEQUENCE)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001023 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001024 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001025
1026 CBB request;
Bob Beck6beabf32023-11-21 09:43:52 -07001027 if (!CBB_add_asn1(&request_list, &request, CBS_ASN1_SEQUENCE)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001028 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001029 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001030
1031 // Request ::= SEQUENCE {
1032 // reqCert CertID,
1033 // singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
1034 CBB req_cert;
Bob Beck6beabf32023-11-21 09:43:52 -07001035 if (!CBB_add_asn1(&request, &req_cert, CBS_ASN1_SEQUENCE)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001036 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001037 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001038
1039 // CertID ::= SEQUENCE {
1040 // hashAlgorithm AlgorithmIdentifier,
1041 // issuerNameHash OCTET STRING, -- Hash of issuer's DN
1042 // issuerKeyHash OCTET STRING, -- Hash of issuer's public key
1043 // serialNumber CertificateSerialNumber }
1044
1045 // TODO(eroman): Don't use SHA1.
Bob Beck5c7a2a02023-11-20 17:28:21 -07001046 const EVP_MD *md = EVP_sha1();
Bob Beck6beabf32023-11-21 09:43:52 -07001047 if (!EVP_marshal_digest_algorithm(&req_cert, md)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001048 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001049 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001050
1051 AppendHashAsOctetString(md, &req_cert, issuer->tbs().subject_tlv);
1052
1053 der::Input key_tlv;
Bob Beck6beabf32023-11-21 09:43:52 -07001054 if (!GetSubjectPublicKeyBytes(issuer->tbs().spki_tlv, &key_tlv)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001055 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001056 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001057 AppendHashAsOctetString(md, &req_cert, key_tlv);
1058
1059 CBB serial_number;
Bob Beck6beabf32023-11-21 09:43:52 -07001060 if (!CBB_add_asn1(&req_cert, &serial_number, CBS_ASN1_INTEGER)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001061 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001062 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001063 if (!CBB_add_bytes(&serial_number, cert->tbs().serial_number.UnsafeData(),
1064 cert->tbs().serial_number.Length())) {
1065 return false;
1066 }
1067
Bob Beck5c7a2a02023-11-20 17:28:21 -07001068 uint8_t *result_bytes;
Bob Beckbc97b7a2023-04-18 08:35:15 -06001069 size_t result_bytes_length;
Bob Beck6beabf32023-11-21 09:43:52 -07001070 if (!CBB_finish(cbb.get(), &result_bytes, &result_bytes_length)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001071 return false;
Bob Beck6beabf32023-11-21 09:43:52 -07001072 }
Bob Beckbc97b7a2023-04-18 08:35:15 -06001073 bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(result_bytes);
1074
1075 request_der->assign(result_bytes, result_bytes + result_bytes_length);
1076 return true;
1077}
1078
1079// From RFC 2560 section A.1.1:
1080//
1081// An OCSP request using the GET method is constructed as follows:
1082//
1083// GET {url}/{url-encoding of base-64 encoding of the DER encoding of
1084// the OCSPRequest}
Bob Beck300f2212023-08-16 22:18:25 +00001085std::optional<std::string> CreateOCSPGetURL(
Bob Beck5c7a2a02023-11-20 17:28:21 -07001086 const ParsedCertificate *cert, const ParsedCertificate *issuer,
Bob Beck300f2212023-08-16 22:18:25 +00001087 std::string_view ocsp_responder_url) {
Bob Beckbc97b7a2023-04-18 08:35:15 -06001088 std::vector<uint8_t> ocsp_request_der;
1089 if (!CreateOCSPRequest(cert, issuer, &ocsp_request_der)) {
1090 // Unexpected (means BoringSSL failed an operation).
Bob Beck300f2212023-08-16 22:18:25 +00001091 return std::nullopt;
Bob Beckbc97b7a2023-04-18 08:35:15 -06001092 }
1093
1094 // Base64 encode the request data.
1095 size_t len;
1096 if (!EVP_EncodedLength(&len, ocsp_request_der.size())) {
Bob Beck300f2212023-08-16 22:18:25 +00001097 return std::nullopt;
Bob Beckbc97b7a2023-04-18 08:35:15 -06001098 }
1099 std::vector<uint8_t> encoded(len);
1100 len = EVP_EncodeBlock(encoded.data(), ocsp_request_der.data(),
1101 ocsp_request_der.size());
1102
1103 std::string b64_encoded(encoded.begin(), encoded.begin() + len);
1104
1105 // In theory +, /, and = are valid in paths and don't need to be escaped.
1106 // However from the example in RFC 5019 section 5 it is clear that the intent
1107 // is to escape non-alphanumeric characters (the example conclusively escapes
1108 // '/' and '=', but doesn't clarify '+').
1109 b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "+", "%2B");
1110 b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "/", "%2F");
1111 b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "=", "%3D");
1112
1113 // No attempt is made to collapse double slashes for URLs that end in slash,
1114 // since the spec doesn't do that.
Bob Beck300f2212023-08-16 22:18:25 +00001115 return std::string(ocsp_responder_url) + "/" + b64_encoded;
Bob Beckbc97b7a2023-04-18 08:35:15 -06001116}
1117
Bob Beck5c7a2a02023-11-20 17:28:21 -07001118} // namespace bssl