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 #include "ocsp.h"
6
7 #include "cert_errors.h"
8 #include "extended_key_usage.h"
9 #include "parsed_certificate.h"
10 #include "revocation_util.h"
11 #include "string_util.h"
12 #include "verify_name_match.h"
13 #include "verify_signed_data.h"
14 #include <openssl/bytestring.h>
15 #include <openssl/digest.h>
16 #include <openssl/mem.h>
17 #include <openssl/pool.h>
18 #include <openssl/sha.h>
19
20 namespace bssl {
21
22 OCSPCertID::OCSPCertID() = default;
23 OCSPCertID::~OCSPCertID() = default;
24
25 OCSPSingleResponse::OCSPSingleResponse() = default;
26 OCSPSingleResponse::~OCSPSingleResponse() = default;
27
28 OCSPResponseData::OCSPResponseData() = default;
29 OCSPResponseData::~OCSPResponseData() = default;
30
31 OCSPResponse::OCSPResponse() = default;
32 OCSPResponse::~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 // }
ParseOCSPCertID(const der::Input & raw_tlv,OCSPCertID * out)40 bool ParseOCSPCertID(const der::Input& raw_tlv, OCSPCertID* out) {
41 der::Parser outer_parser(raw_tlv);
42 der::Parser parser;
43 if (!outer_parser.ReadSequence(&parser))
44 return false;
45 if (outer_parser.HasMore())
46 return false;
47
48 der::Input sigalg_tlv;
49 if (!parser.ReadRawTLV(&sigalg_tlv))
50 return false;
51 if (!ParseHashAlgorithm(sigalg_tlv, &(out->hash_algorithm)))
52 return false;
53 if (!parser.ReadTag(der::kOctetString, &(out->issuer_name_hash)))
54 return false;
55 if (!parser.ReadTag(der::kOctetString, &(out->issuer_key_hash)))
56 return false;
57 if (!parser.ReadTag(der::kInteger, &(out->serial_number)))
58 return false;
59 CertErrors errors;
60 if (!VerifySerialNumber(out->serial_number, false /*warnings_only*/, &errors))
61 return false;
62
63 return !parser.HasMore();
64 }
65
66 namespace {
67
68 // Parses |raw_tlv| to extract an OCSP RevokedInfo (RFC 6960) and stores the
69 // result in the OCSPCertStatus |out|. Returns whether the parsing was
70 // successful.
71 //
72 // RevokedInfo ::= SEQUENCE {
73 // revocationTime GeneralizedTime,
74 // revocationReason [0] EXPLICIT CRLReason OPTIONAL
75 // }
ParseRevokedInfo(const der::Input & raw_tlv,OCSPCertStatus * out)76 bool ParseRevokedInfo(const der::Input& raw_tlv, OCSPCertStatus* out) {
77 der::Parser parser(raw_tlv);
78 if (!parser.ReadGeneralizedTime(&(out->revocation_time)))
79 return false;
80
81 der::Input reason_input;
82 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &reason_input,
83 &(out->has_reason))) {
84 return false;
85 }
86 if (out->has_reason) {
87 der::Parser reason_parser(reason_input);
88 der::Input reason_value_input;
89 uint8_t reason_value;
90 if (!reason_parser.ReadTag(der::kEnumerated, &reason_value_input))
91 return false;
92 if (!der::ParseUint8(reason_value_input, &reason_value))
93 return false;
94 if (reason_value >
95 static_cast<uint8_t>(OCSPCertStatus::RevocationReason::LAST)) {
96 return false;
97 }
98 out->revocation_reason =
99 static_cast<OCSPCertStatus::RevocationReason>(reason_value);
100 if (out->revocation_reason == OCSPCertStatus::RevocationReason::UNUSED)
101 return false;
102 if (reason_parser.HasMore())
103 return false;
104 }
105 return !parser.HasMore();
106 }
107
108 // Parses |raw_tlv| to extract an OCSP CertStatus (RFC 6960) and stores the
109 // result in the OCSPCertStatus |out|. Returns whether the parsing was
110 // successful.
111 //
112 // CertStatus ::= CHOICE {
113 // good [0] IMPLICIT NULL,
114 // revoked [1] IMPLICIT RevokedInfo,
115 // unknown [2] IMPLICIT UnknownInfo
116 // }
117 //
118 // UnknownInfo ::= NULL
ParseCertStatus(const der::Input & raw_tlv,OCSPCertStatus * out)119 bool ParseCertStatus(const der::Input& raw_tlv, OCSPCertStatus* out) {
120 der::Parser parser(raw_tlv);
121 der::Tag status_tag;
122 der::Input status;
123 if (!parser.ReadTagAndValue(&status_tag, &status))
124 return false;
125
126 out->has_reason = false;
127 if (status_tag == der::ContextSpecificPrimitive(0)) {
128 out->status = OCSPRevocationStatus::GOOD;
129 } else if (status_tag == der::ContextSpecificConstructed(1)) {
130 out->status = OCSPRevocationStatus::REVOKED;
131 if (!ParseRevokedInfo(status, out))
132 return false;
133 } else if (status_tag == der::ContextSpecificPrimitive(2)) {
134 out->status = OCSPRevocationStatus::UNKNOWN;
135 } else {
136 return false;
137 }
138
139 return !parser.HasMore();
140 }
141
142 // Writes the hash of |value| as an OCTET STRING to |cbb|, using |hash_type| as
143 // the algorithm. Returns true on success.
AppendHashAsOctetString(const EVP_MD * hash_type,CBB * cbb,const der::Input & value)144 bool AppendHashAsOctetString(const EVP_MD* hash_type,
145 CBB* cbb,
146 const der::Input& value) {
147 CBB octet_string;
148 unsigned hash_len;
149 uint8_t hash_buffer[EVP_MAX_MD_SIZE];
150
151 return CBB_add_asn1(cbb, &octet_string, CBS_ASN1_OCTETSTRING) &&
152 EVP_Digest(value.UnsafeData(), value.Length(), hash_buffer, &hash_len,
153 hash_type, nullptr) &&
154 CBB_add_bytes(&octet_string, hash_buffer, hash_len) && CBB_flush(cbb);
155 }
156
157 } // namespace
158
159 // SingleResponse ::= SEQUENCE {
160 // certID CertID,
161 // certStatus CertStatus,
162 // thisUpdate GeneralizedTime,
163 // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
164 // singleExtensions [1] EXPLICIT Extensions OPTIONAL
165 // }
ParseOCSPSingleResponse(const der::Input & raw_tlv,OCSPSingleResponse * out)166 bool ParseOCSPSingleResponse(const der::Input& raw_tlv,
167 OCSPSingleResponse* out) {
168 der::Parser outer_parser(raw_tlv);
169 der::Parser parser;
170 if (!outer_parser.ReadSequence(&parser))
171 return false;
172 if (outer_parser.HasMore())
173 return false;
174
175 if (!parser.ReadRawTLV(&(out->cert_id_tlv)))
176 return false;
177 der::Input status_tlv;
178 if (!parser.ReadRawTLV(&status_tlv))
179 return false;
180 if (!ParseCertStatus(status_tlv, &(out->cert_status)))
181 return false;
182 if (!parser.ReadGeneralizedTime(&(out->this_update)))
183 return false;
184
185 der::Input next_update_input;
186 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
187 &next_update_input, &(out->has_next_update))) {
188 return false;
189 }
190 if (out->has_next_update) {
191 der::Parser next_update_parser(next_update_input);
192 if (!next_update_parser.ReadGeneralizedTime(&(out->next_update)))
193 return false;
194 if (next_update_parser.HasMore())
195 return false;
196 }
197
198 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
199 &(out->extensions), &(out->has_extensions))) {
200 return false;
201 }
202
203 return !parser.HasMore();
204 }
205
206 namespace {
207
208 // Parses |raw_tlv| to extract a ResponderID (RFC 6960) and stores the
209 // result in the ResponderID |out|. Returns whether the parsing was successful.
210 //
211 // ResponderID ::= CHOICE {
212 // byName [1] Name,
213 // byKey [2] KeyHash
214 // }
ParseResponderID(const der::Input & raw_tlv,OCSPResponseData::ResponderID * out)215 bool ParseResponderID(const der::Input& raw_tlv,
216 OCSPResponseData::ResponderID* out) {
217 der::Parser parser(raw_tlv);
218 der::Tag id_tag;
219 der::Input id_input;
220 if (!parser.ReadTagAndValue(&id_tag, &id_input))
221 return false;
222
223 if (id_tag == der::ContextSpecificConstructed(1)) {
224 out->type = OCSPResponseData::ResponderType::NAME;
225 out->name = id_input;
226 } else if (id_tag == der::ContextSpecificConstructed(2)) {
227 der::Parser key_parser(id_input);
228 der::Input key_hash;
229 if (!key_parser.ReadTag(der::kOctetString, &key_hash))
230 return false;
231 if (key_parser.HasMore())
232 return false;
233 if (key_hash.Length() != SHA_DIGEST_LENGTH)
234 return false;
235
236 out->type = OCSPResponseData::ResponderType::KEY_HASH;
237 out->key_hash = key_hash;
238 } else {
239 return false;
240 }
241 return !parser.HasMore();
242 }
243
244 } // namespace
245
246 // ResponseData ::= SEQUENCE {
247 // version [0] EXPLICIT Version DEFAULT v1,
248 // responderID ResponderID,
249 // producedAt GeneralizedTime,
250 // responses SEQUENCE OF SingleResponse,
251 // responseExtensions [1] EXPLICIT Extensions OPTIONAL
252 // }
ParseOCSPResponseData(const der::Input & raw_tlv,OCSPResponseData * out)253 bool ParseOCSPResponseData(const der::Input& raw_tlv, OCSPResponseData* out) {
254 der::Parser outer_parser(raw_tlv);
255 der::Parser parser;
256 if (!outer_parser.ReadSequence(&parser))
257 return false;
258 if (outer_parser.HasMore())
259 return false;
260
261 der::Input version_input;
262 bool version_present;
263 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
264 &version_input, &version_present)) {
265 return false;
266 }
267
268 // For compatibilty, we ignore the restriction from X.690 Section 11.5 that
269 // DEFAULT values should be omitted for values equal to the default value.
270 // TODO: Add warning about non-strict parsing.
271 if (version_present) {
272 der::Parser version_parser(version_input);
273 if (!version_parser.ReadUint8(&(out->version)))
274 return false;
275 if (version_parser.HasMore())
276 return false;
277 } else {
278 out->version = 0;
279 }
280
281 if (out->version != 0)
282 return false;
283
284 der::Input responder_input;
285 if (!parser.ReadRawTLV(&responder_input))
286 return false;
287 if (!ParseResponderID(responder_input, &(out->responder_id)))
288 return false;
289 if (!parser.ReadGeneralizedTime(&(out->produced_at)))
290 return false;
291
292 der::Parser responses_parser;
293 if (!parser.ReadSequence(&responses_parser))
294 return false;
295 out->responses.clear();
296 while (responses_parser.HasMore()) {
297 der::Input single_response;
298 if (!responses_parser.ReadRawTLV(&single_response))
299 return false;
300 out->responses.push_back(single_response);
301 }
302
303 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
304 &(out->extensions), &(out->has_extensions))) {
305 return false;
306 }
307
308 return !parser.HasMore();
309 }
310
311 namespace {
312
313 // Parses |raw_tlv| to extract a BasicOCSPResponse (RFC 6960) and stores the
314 // result in the OCSPResponse |out|. Returns whether the parsing was
315 // successful.
316 //
317 // BasicOCSPResponse ::= SEQUENCE {
318 // tbsResponseData ResponseData,
319 // signatureAlgorithm AlgorithmIdentifier,
320 // signature BIT STRING,
321 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
322 // }
ParseBasicOCSPResponse(const der::Input & raw_tlv,OCSPResponse * out)323 bool ParseBasicOCSPResponse(const der::Input& raw_tlv, OCSPResponse* out) {
324 der::Parser outer_parser(raw_tlv);
325 der::Parser parser;
326 if (!outer_parser.ReadSequence(&parser))
327 return false;
328 if (outer_parser.HasMore())
329 return false;
330
331 if (!parser.ReadRawTLV(&(out->data)))
332 return false;
333 der::Input sigalg_tlv;
334 if (!parser.ReadRawTLV(&sigalg_tlv))
335 return false;
336 // TODO(crbug.com/634443): Propagate the errors.
337 std::optional<SignatureAlgorithm> sigalg =
338 ParseSignatureAlgorithm(sigalg_tlv);
339 if (!sigalg)
340 return false;
341 out->signature_algorithm = sigalg.value();
342 std::optional<der::BitString> signature = parser.ReadBitString();
343 if (!signature)
344 return false;
345 out->signature = signature.value();
346 der::Input certs_input;
347 if (!parser.ReadOptionalTag(der::ContextSpecificConstructed(0), &certs_input,
348 &(out->has_certs))) {
349 return false;
350 }
351
352 out->certs.clear();
353 if (out->has_certs) {
354 der::Parser certs_seq_parser(certs_input);
355 der::Parser certs_parser;
356 if (!certs_seq_parser.ReadSequence(&certs_parser))
357 return false;
358 if (certs_seq_parser.HasMore())
359 return false;
360 while (certs_parser.HasMore()) {
361 der::Input cert_tlv;
362 if (!certs_parser.ReadRawTLV(&cert_tlv))
363 return false;
364 out->certs.push_back(cert_tlv);
365 }
366 }
367
368 return !parser.HasMore();
369 }
370
371 } // namespace
372
373 // OCSPResponse ::= SEQUENCE {
374 // responseStatus OCSPResponseStatus,
375 // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
376 // }
377 //
378 // ResponseBytes ::= SEQUENCE {
379 // responseType OBJECT IDENTIFIER,
380 // response OCTET STRING
381 // }
ParseOCSPResponse(const der::Input & raw_tlv,OCSPResponse * out)382 bool ParseOCSPResponse(const der::Input& raw_tlv, OCSPResponse* out) {
383 der::Parser outer_parser(raw_tlv);
384 der::Parser parser;
385 if (!outer_parser.ReadSequence(&parser))
386 return false;
387 if (outer_parser.HasMore())
388 return false;
389
390 der::Input response_status_input;
391 uint8_t response_status;
392 if (!parser.ReadTag(der::kEnumerated, &response_status_input))
393 return false;
394 if (!der::ParseUint8(response_status_input, &response_status))
395 return false;
396 if (response_status >
397 static_cast<uint8_t>(OCSPResponse::ResponseStatus::LAST)) {
398 return false;
399 }
400 out->status = static_cast<OCSPResponse::ResponseStatus>(response_status);
401 if (out->status == OCSPResponse::ResponseStatus::UNUSED)
402 return false;
403
404 if (out->status == OCSPResponse::ResponseStatus::SUCCESSFUL) {
405 der::Parser outer_bytes_parser;
406 der::Parser bytes_parser;
407 if (!parser.ReadConstructed(der::ContextSpecificConstructed(0),
408 &outer_bytes_parser)) {
409 return false;
410 }
411 if (!outer_bytes_parser.ReadSequence(&bytes_parser))
412 return false;
413 if (outer_bytes_parser.HasMore())
414 return false;
415
416 der::Input type_oid;
417 if (!bytes_parser.ReadTag(der::kOid, &type_oid))
418 return false;
419 if (type_oid != der::Input(kBasicOCSPResponseOid))
420 return false;
421
422 // As per RFC 6960 Section 4.2.1, the value of |response| SHALL be the DER
423 // encoding of BasicOCSPResponse.
424 der::Input response;
425 if (!bytes_parser.ReadTag(der::kOctetString, &response))
426 return false;
427 if (!ParseBasicOCSPResponse(response, out))
428 return false;
429 if (bytes_parser.HasMore())
430 return false;
431 }
432
433 return !parser.HasMore();
434 }
435
436 namespace {
437
438 // Checks that the |type| hash of |value| is equal to |hash|
VerifyHash(const EVP_MD * type,const der::Input & hash,const der::Input & value)439 bool VerifyHash(const EVP_MD* type,
440 const der::Input& hash,
441 const der::Input& value) {
442 unsigned value_hash_len;
443 uint8_t value_hash[EVP_MAX_MD_SIZE];
444 if (!EVP_Digest(value.UnsafeData(), value.Length(), value_hash,
445 &value_hash_len, type, nullptr)) {
446 return false;
447 }
448
449 return hash == der::Input(value_hash, value_hash_len);
450 }
451
452 // Extracts the bytes of the SubjectPublicKey bit string given an SPKI. That is
453 // to say, the value of subjectPublicKey without the leading unused bit
454 // count octet.
455 //
456 // Returns true on success and fills |*spk_tlv| with the result.
457 //
458 // From RFC 5280, Section 4.1
459 // SubjectPublicKeyInfo ::= SEQUENCE {
460 // algorithm AlgorithmIdentifier,
461 // subjectPublicKey BIT STRING }
462 //
463 // AlgorithmIdentifier ::= SEQUENCE {
464 // algorithm OBJECT IDENTIFIER,
465 // parameters ANY DEFINED BY algorithm OPTIONAL }
466 //
GetSubjectPublicKeyBytes(const der::Input & spki_tlv,der::Input * spk_tlv)467 bool GetSubjectPublicKeyBytes(const der::Input& spki_tlv, der::Input* spk_tlv) {
468 CBS outer, inner, alg, spk;
469 uint8_t unused_bit_count;
470 CBS_init(&outer, spki_tlv.UnsafeData(), spki_tlv.Length());
471 // The subjectPublicKey field includes the unused bit count. For this
472 // application, the unused bit count must be zero, and is not included in
473 // the result. We extract the subjectPubicKey bit string, verify the first
474 // byte is 0, and if so set |spk_tlv| to the remaining bytes.
475 if (!CBS_get_asn1(&outer, &inner, CBS_ASN1_SEQUENCE) ||
476 !CBS_get_asn1(&inner, &alg, CBS_ASN1_SEQUENCE) ||
477 !CBS_get_asn1(&inner, &spk, CBS_ASN1_BITSTRING) ||
478 !CBS_get_u8(&spk, &unused_bit_count) || unused_bit_count != 0) {
479 return false;
480 }
481 *spk_tlv = der::Input(CBS_data(&spk), CBS_len(&spk));
482 return true;
483 }
484
485 // Checks the OCSPCertID |id| identifies |certificate|.
CheckCertIDMatchesCertificate(const OCSPCertID & id,const ParsedCertificate * certificate,const ParsedCertificate * issuer_certificate)486 bool CheckCertIDMatchesCertificate(
487 const OCSPCertID& id,
488 const ParsedCertificate* certificate,
489 const ParsedCertificate* issuer_certificate) {
490 const EVP_MD* type = nullptr;
491 switch (id.hash_algorithm) {
492 case DigestAlgorithm::Md2:
493 case DigestAlgorithm::Md4:
494 case DigestAlgorithm::Md5:
495 // Unsupported.
496 return false;
497 case DigestAlgorithm::Sha1:
498 type = EVP_sha1();
499 break;
500 case DigestAlgorithm::Sha256:
501 type = EVP_sha256();
502 break;
503 case DigestAlgorithm::Sha384:
504 type = EVP_sha384();
505 break;
506 case DigestAlgorithm::Sha512:
507 type = EVP_sha512();
508 break;
509 }
510
511 if (!VerifyHash(type, id.issuer_name_hash, certificate->tbs().issuer_tlv))
512 return false;
513
514 der::Input key_tlv;
515 if (!GetSubjectPublicKeyBytes(issuer_certificate->tbs().spki_tlv, &key_tlv))
516 return false;
517
518 if (!VerifyHash(type, id.issuer_key_hash, key_tlv))
519 return false;
520
521 return id.serial_number == certificate->tbs().serial_number;
522 }
523
524 // TODO(eroman): Revisit how certificate parsing is used by this file. Ideally
525 // would either pass in the parsed bits, or have a better abstraction for lazily
526 // parsing.
OCSPParseCertificate(std::string_view der)527 std::shared_ptr<const ParsedCertificate> OCSPParseCertificate(
528 std::string_view der) {
529 ParseCertificateOptions parse_options;
530 parse_options.allow_invalid_serial_numbers = true;
531
532 // The objects returned by this function only last for the duration of a
533 // single certificate verification, so there is no need to pool them to save
534 // memory.
535 //
536 // TODO(eroman): Swallows the parsing errors. However uses a permissive
537 // parsing model.
538 CertErrors errors;
539 return ParsedCertificate::Create(
540 bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
541 reinterpret_cast<const uint8_t*>(der.data()), der.size(), nullptr)),
542 {}, &errors);
543 }
544
545 // Checks that the ResponderID |id| matches the certificate |cert| either
546 // by verifying the name matches that of the certificate or that the hash
547 // matches the certificate's public key hash (RFC 6960, 4.2.2.3).
CheckResponderIDMatchesCertificate(const OCSPResponseData::ResponderID & id,const ParsedCertificate * cert)548 [[nodiscard]] bool CheckResponderIDMatchesCertificate(
549 const OCSPResponseData::ResponderID& id,
550 const ParsedCertificate* cert) {
551 switch (id.type) {
552 case OCSPResponseData::ResponderType::NAME: {
553 der::Input name_rdn;
554 der::Input cert_rdn;
555 if (!der::Parser(id.name).ReadTag(der::kSequence, &name_rdn) ||
556 !der::Parser(cert->tbs().subject_tlv)
557 .ReadTag(der::kSequence, &cert_rdn))
558 return false;
559 return VerifyNameMatch(name_rdn, cert_rdn);
560 }
561 case OCSPResponseData::ResponderType::KEY_HASH: {
562 der::Input key;
563 if (!GetSubjectPublicKeyBytes(cert->tbs().spki_tlv, &key))
564 return false;
565 return VerifyHash(EVP_sha1(), id.key_hash, key);
566 }
567 }
568
569 return false;
570 }
571
572 // Verifies that |responder_certificate| has been authority for OCSP signing,
573 // delegated to it by |issuer_certificate|.
574 //
575 // TODO(eroman): No revocation checks are done (see id-pkix-ocsp-nocheck in the
576 // spec). extension).
577 //
578 // TODO(eroman): Not all properties of the certificate are verified, only the
579 // signature and EKU. Can full RFC 5280 validation be used, or are there
580 // compatibility concerns?
VerifyAuthorizedResponderCert(const ParsedCertificate * responder_certificate,const ParsedCertificate * issuer_certificate)581 [[nodiscard]] bool VerifyAuthorizedResponderCert(
582 const ParsedCertificate* responder_certificate,
583 const ParsedCertificate* issuer_certificate) {
584 // The Authorized Responder must be directly signed by the issuer of the
585 // certificate being checked.
586 // TODO(eroman): Must check the signature algorithm against policy.
587 if (!responder_certificate->signature_algorithm().has_value() ||
588 !VerifySignedData(*responder_certificate->signature_algorithm(),
589 responder_certificate->tbs_certificate_tlv(),
590 responder_certificate->signature_value(),
591 issuer_certificate->tbs().spki_tlv,
592 /*cache=*/nullptr)) {
593 return false;
594 }
595
596 // The Authorized Responder must include the value id-kp-OCSPSigning as
597 // part of the extended key usage extension.
598 if (!responder_certificate->has_extended_key_usage())
599 return false;
600
601 for (const auto& key_purpose_oid :
602 responder_certificate->extended_key_usage()) {
603 if (key_purpose_oid == der::Input(kOCSPSigning))
604 return true;
605 }
606 return false;
607 }
608
VerifyOCSPResponseSignatureGivenCert(const OCSPResponse & response,const ParsedCertificate * cert)609 [[nodiscard]] bool VerifyOCSPResponseSignatureGivenCert(
610 const OCSPResponse& response,
611 const ParsedCertificate* cert) {
612 // TODO(eroman): Must check the signature algorithm against policy.
613 return VerifySignedData(response.signature_algorithm, response.data,
614 response.signature, cert->tbs().spki_tlv,
615 /*cache=*/nullptr);
616 }
617
618 // Verifies that the OCSP response has a valid signature using
619 // |issuer_certificate|, or an authorized responder issued by
620 // |issuer_certificate| for OCSP signing.
VerifyOCSPResponseSignature(const OCSPResponse & response,const OCSPResponseData & response_data,const ParsedCertificate * issuer_certificate)621 [[nodiscard]] bool VerifyOCSPResponseSignature(
622 const OCSPResponse& response,
623 const OCSPResponseData& response_data,
624 const ParsedCertificate* issuer_certificate) {
625 // In order to verify the OCSP signature, a valid responder matching the OCSP
626 // Responder ID must be located (RFC 6960, 4.2.2.2). The responder is allowed
627 // to be either the certificate issuer or a delegated authority directly
628 // signed by the issuer.
629 if (CheckResponderIDMatchesCertificate(response_data.responder_id,
630 issuer_certificate) &&
631 VerifyOCSPResponseSignatureGivenCert(response, issuer_certificate)) {
632 return true;
633 }
634
635 // Otherwise search through the provided certificates for the Authorized
636 // Responder. Want a certificate that:
637 // (1) Matches the OCSP Responder ID.
638 // (2) Has been given authority for OCSP signing by |issuer_certificate|.
639 // (3) Has signed the OCSP response using its public key.
640 for (const auto& responder_cert_tlv : response.certs) {
641 std::shared_ptr<const ParsedCertificate> cur_responder_certificate =
642 OCSPParseCertificate(responder_cert_tlv.AsStringView());
643
644 // If failed parsing the certificate, keep looking.
645 if (!cur_responder_certificate)
646 continue;
647
648 // If the certificate doesn't match the OCSP's responder ID, keep looking.
649 if (!CheckResponderIDMatchesCertificate(response_data.responder_id,
650 cur_responder_certificate.get())) {
651 continue;
652 }
653
654 // If the certificate isn't a valid Authorized Responder certificate, keep
655 // looking.
656 if (!VerifyAuthorizedResponderCert(cur_responder_certificate.get(),
657 issuer_certificate)) {
658 continue;
659 }
660
661 // If the certificate signed this OCSP response, have found a match.
662 // Otherwise keep looking.
663 if (VerifyOCSPResponseSignatureGivenCert(response,
664 cur_responder_certificate.get())) {
665 return true;
666 }
667 }
668
669 // Failed to confirm the validity of the OCSP signature using any of the
670 // candidate certificates.
671 return false;
672 }
673
674 // Parse ResponseData and return false if any unhandled critical extensions are
675 // found. No known critical ResponseData extensions exist.
ParseOCSPResponseDataExtensions(const der::Input & response_extensions,OCSPVerifyResult::ResponseStatus * response_details)676 bool ParseOCSPResponseDataExtensions(
677 const der::Input& response_extensions,
678 OCSPVerifyResult::ResponseStatus* response_details) {
679 std::map<der::Input, ParsedExtension> extensions;
680 if (!ParseExtensions(response_extensions, &extensions)) {
681 *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
682 return false;
683 }
684
685 for (const auto& ext : extensions) {
686 // TODO: handle ResponseData extensions
687
688 if (ext.second.critical) {
689 *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
690 return false;
691 }
692 }
693
694 return true;
695 }
696
697 // Parse SingleResponse and return false if any unhandled critical extensions
698 // (other than the CT extension) are found. The CT-SCT extension is not required
699 // to be marked critical, but since it is handled by Chrome, we will overlook
700 // the flag setting.
ParseOCSPSingleResponseExtensions(const der::Input & single_extensions,OCSPVerifyResult::ResponseStatus * response_details)701 bool ParseOCSPSingleResponseExtensions(
702 const der::Input& single_extensions,
703 OCSPVerifyResult::ResponseStatus* response_details) {
704 std::map<der::Input, ParsedExtension> extensions;
705 if (!ParseExtensions(single_extensions, &extensions)) {
706 *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
707 return false;
708 }
709
710 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for
711 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see
712 // Section 3.3 of RFC6962.
713 const uint8_t ct_ocsp_ext_oid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
714 0xD6, 0x79, 0x02, 0x04, 0x05};
715 der::Input ct_ext_oid(ct_ocsp_ext_oid);
716
717 for (const auto& ext : extensions) {
718 // The CT OCSP extension is handled in ct::ExtractSCTListFromOCSPResponse
719 if (ext.second.oid == ct_ext_oid)
720 continue;
721
722 // TODO: handle SingleResponse extensions
723
724 if (ext.second.critical) {
725 *response_details = OCSPVerifyResult::UNHANDLED_CRITICAL_EXTENSION;
726 return false;
727 }
728 }
729
730 return true;
731 }
732
733 // Loops through the OCSPSingleResponses to find the best match for |cert|.
GetRevocationStatusForCert(const OCSPResponseData & response_data,const ParsedCertificate * cert,const ParsedCertificate * issuer_certificate,int64_t verify_time_epoch_seconds,std::optional<int64_t> max_age_seconds,OCSPVerifyResult::ResponseStatus * response_details)734 OCSPRevocationStatus GetRevocationStatusForCert(
735 const OCSPResponseData& response_data,
736 const ParsedCertificate* cert,
737 const ParsedCertificate* issuer_certificate,
738 int64_t verify_time_epoch_seconds,
739 std::optional<int64_t> max_age_seconds,
740 OCSPVerifyResult::ResponseStatus* response_details) {
741 OCSPRevocationStatus result = OCSPRevocationStatus::UNKNOWN;
742 *response_details = OCSPVerifyResult::NO_MATCHING_RESPONSE;
743
744 for (const auto& single_response_der : response_data.responses) {
745 // In the common case, there should only be one SingleResponse in the
746 // ResponseData (matching the certificate requested and used on this
747 // connection). However, it is possible for the OCSP responder to provide
748 // multiple responses for multiple certificates. Look through all the
749 // provided SingleResponses, and check to see if any match the
750 // certificate. A SingleResponse matches a certificate if it has the same
751 // serial number, issuer name (hash), and issuer public key (hash).
752 OCSPSingleResponse single_response;
753 if (!ParseOCSPSingleResponse(single_response_der, &single_response))
754 return OCSPRevocationStatus::UNKNOWN;
755
756 // Reject unhandled critical extensions in SingleResponse
757 if (single_response.has_extensions &&
758 !ParseOCSPSingleResponseExtensions(single_response.extensions,
759 response_details)) {
760 return OCSPRevocationStatus::UNKNOWN;
761 }
762
763 OCSPCertID cert_id;
764 if (!ParseOCSPCertID(single_response.cert_id_tlv, &cert_id))
765 return OCSPRevocationStatus::UNKNOWN;
766 if (!CheckCertIDMatchesCertificate(cert_id, cert, issuer_certificate))
767 continue;
768
769 // The SingleResponse matches the certificate, but may be out of date. Out
770 // of date responses are noted seperate from responses with mismatched
771 // serial numbers. If an OCSP responder provides both an up to date
772 // response and an expired response, the up to date response takes
773 // precedence (PROVIDED > INVALID_DATE).
774 if (!CheckRevocationDateValid(single_response.this_update,
775 single_response.has_next_update
776 ? &single_response.next_update
777 : nullptr,
778 verify_time_epoch_seconds, max_age_seconds)) {
779 if (*response_details != OCSPVerifyResult::PROVIDED)
780 *response_details = OCSPVerifyResult::INVALID_DATE;
781 continue;
782 }
783
784 // In the case with multiple matching and up to date responses, keep only
785 // the strictest status (REVOKED > UNKNOWN > GOOD).
786 if (*response_details != OCSPVerifyResult::PROVIDED ||
787 result == OCSPRevocationStatus::GOOD ||
788 single_response.cert_status.status == OCSPRevocationStatus::REVOKED) {
789 result = single_response.cert_status.status;
790 }
791 *response_details = OCSPVerifyResult::PROVIDED;
792 }
793
794 return result;
795 }
796
CheckOCSP(std::string_view raw_response,std::string_view certificate_der,const ParsedCertificate * certificate,std::string_view issuer_certificate_der,const ParsedCertificate * issuer_certificate,int64_t verify_time_epoch_seconds,std::optional<int64_t> max_age_seconds,OCSPVerifyResult::ResponseStatus * response_details)797 OCSPRevocationStatus CheckOCSP(
798 std::string_view raw_response,
799 std::string_view certificate_der,
800 const ParsedCertificate* certificate,
801 std::string_view issuer_certificate_der,
802 const ParsedCertificate* issuer_certificate,
803 int64_t verify_time_epoch_seconds,
804 std::optional<int64_t> max_age_seconds,
805 OCSPVerifyResult::ResponseStatus* response_details) {
806 *response_details = OCSPVerifyResult::NOT_CHECKED;
807
808 if (raw_response.empty()) {
809 *response_details = OCSPVerifyResult::MISSING;
810 return OCSPRevocationStatus::UNKNOWN;
811 }
812
813 der::Input response_der(raw_response);
814 OCSPResponse response;
815 if (!ParseOCSPResponse(response_der, &response)) {
816 *response_details = OCSPVerifyResult::PARSE_RESPONSE_ERROR;
817 return OCSPRevocationStatus::UNKNOWN;
818 }
819
820 // RFC 6960 defines all responses |response_status| != SUCCESSFUL as error
821 // responses. No revocation information is provided on error responses, and
822 // the OCSPResponseData structure is not set.
823 if (response.status != OCSPResponse::ResponseStatus::SUCCESSFUL) {
824 *response_details = OCSPVerifyResult::ERROR_RESPONSE;
825 return OCSPRevocationStatus::UNKNOWN;
826 }
827
828 // Actual revocation information is contained within the BasicOCSPResponse as
829 // a ResponseData structure. The BasicOCSPResponse was parsed above, and
830 // contains an unparsed ResponseData. From RFC 6960:
831 //
832 // BasicOCSPResponse ::= SEQUENCE {
833 // tbsResponseData ResponseData,
834 // signatureAlgorithm AlgorithmIdentifier,
835 // signature BIT STRING,
836 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
837 //
838 // ResponseData ::= SEQUENCE {
839 // version [0] EXPLICIT Version DEFAULT v1,
840 // responderID ResponderID,
841 // producedAt GeneralizedTime,
842 // responses SEQUENCE OF SingleResponse,
843 // responseExtensions [1] EXPLICIT Extensions OPTIONAL }
844 OCSPResponseData response_data;
845 if (!ParseOCSPResponseData(response.data, &response_data)) {
846 *response_details = OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR;
847 return OCSPRevocationStatus::UNKNOWN;
848 }
849
850 // Process the OCSP ResponseData extensions. In particular, must reject if
851 // there are any critical extensions that are not understood.
852 if (response_data.has_extensions &&
853 !ParseOCSPResponseDataExtensions(response_data.extensions,
854 response_details)) {
855 return OCSPRevocationStatus::UNKNOWN;
856 }
857
858 std::shared_ptr<const ParsedCertificate> parsed_certificate;
859 std::shared_ptr<const ParsedCertificate> parsed_issuer_certificate;
860 if (!certificate) {
861 parsed_certificate = OCSPParseCertificate(certificate_der);
862 certificate = parsed_certificate.get();
863 }
864 if (!issuer_certificate) {
865 parsed_issuer_certificate = OCSPParseCertificate(issuer_certificate_der);
866 issuer_certificate = parsed_issuer_certificate.get();
867 }
868
869 if (!certificate || !issuer_certificate) {
870 *response_details = OCSPVerifyResult::NOT_CHECKED;
871 return OCSPRevocationStatus::UNKNOWN;
872 }
873
874 // If producedAt is outside of the certificate validity period, reject the
875 // response.
876 if (response_data.produced_at < certificate->tbs().validity_not_before ||
877 response_data.produced_at > certificate->tbs().validity_not_after) {
878 *response_details = OCSPVerifyResult::BAD_PRODUCED_AT;
879 return OCSPRevocationStatus::UNKNOWN;
880 }
881
882 // Look through all of the OCSPSingleResponses for a match (based on CertID
883 // and time).
884 OCSPRevocationStatus status = GetRevocationStatusForCert(
885 response_data, certificate, issuer_certificate, verify_time_epoch_seconds,
886 max_age_seconds, response_details);
887
888 // Check that the OCSP response has a valid signature. It must either be
889 // signed directly by the issuing certificate, or a valid authorized
890 // responder.
891 if (!VerifyOCSPResponseSignature(response, response_data,
892 issuer_certificate)) {
893 return OCSPRevocationStatus::UNKNOWN;
894 }
895
896 return status;
897 }
898
899 } // namespace
900
CheckOCSP(std::string_view raw_response,std::string_view certificate_der,std::string_view issuer_certificate_der,int64_t verify_time_epoch_seconds,std::optional<int64_t> max_age_seconds,OCSPVerifyResult::ResponseStatus * response_details)901 OCSPRevocationStatus CheckOCSP(
902 std::string_view raw_response,
903 std::string_view certificate_der,
904 std::string_view issuer_certificate_der,
905 int64_t verify_time_epoch_seconds,
906 std::optional<int64_t> max_age_seconds,
907 OCSPVerifyResult::ResponseStatus* response_details) {
908 return CheckOCSP(raw_response, certificate_der, nullptr,
909 issuer_certificate_der, nullptr, verify_time_epoch_seconds,
910 max_age_seconds, response_details);
911 }
912
CheckOCSP(std::string_view raw_response,const ParsedCertificate * certificate,const ParsedCertificate * issuer_certificate,int64_t verify_time_epoch_seconds,std::optional<int64_t> max_age_seconds,OCSPVerifyResult::ResponseStatus * response_details)913 OCSPRevocationStatus CheckOCSP(
914 std::string_view raw_response,
915 const ParsedCertificate* certificate,
916 const ParsedCertificate* issuer_certificate,
917 int64_t verify_time_epoch_seconds,
918 std::optional<int64_t> max_age_seconds,
919 OCSPVerifyResult::ResponseStatus* response_details) {
920 return CheckOCSP(raw_response, std::string_view(), certificate,
921 std::string_view(), issuer_certificate,
922 verify_time_epoch_seconds, max_age_seconds,
923 response_details);
924 }
925
CreateOCSPRequest(const ParsedCertificate * cert,const ParsedCertificate * issuer,std::vector<uint8_t> * request_der)926 bool CreateOCSPRequest(const ParsedCertificate* cert,
927 const ParsedCertificate* issuer,
928 std::vector<uint8_t>* request_der) {
929 request_der->clear();
930
931 bssl::ScopedCBB cbb;
932
933 // This initial buffer size is big enough for 20 octet long serial numbers
934 // (upper bound from RFC 5280) and then a handful of extra bytes. This
935 // number doesn't matter for correctness.
936 const size_t kInitialBufferSize = 100;
937
938 if (!CBB_init(cbb.get(), kInitialBufferSize))
939 return false;
940
941 // OCSPRequest ::= SEQUENCE {
942 // tbsRequest TBSRequest,
943 // optionalSignature [0] EXPLICIT Signature OPTIONAL }
944 //
945 // TBSRequest ::= SEQUENCE {
946 // version [0] EXPLICIT Version DEFAULT v1,
947 // requestorName [1] EXPLICIT GeneralName OPTIONAL,
948 // requestList SEQUENCE OF Request,
949 // requestExtensions [2] EXPLICIT Extensions OPTIONAL }
950 CBB ocsp_request;
951 if (!CBB_add_asn1(cbb.get(), &ocsp_request, CBS_ASN1_SEQUENCE))
952 return false;
953
954 CBB tbs_request;
955 if (!CBB_add_asn1(&ocsp_request, &tbs_request, CBS_ASN1_SEQUENCE))
956 return false;
957
958 // "version", "requestorName", and "requestExtensions" are omitted.
959
960 CBB request_list;
961 if (!CBB_add_asn1(&tbs_request, &request_list, CBS_ASN1_SEQUENCE))
962 return false;
963
964 CBB request;
965 if (!CBB_add_asn1(&request_list, &request, CBS_ASN1_SEQUENCE))
966 return false;
967
968 // Request ::= SEQUENCE {
969 // reqCert CertID,
970 // singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
971 CBB req_cert;
972 if (!CBB_add_asn1(&request, &req_cert, CBS_ASN1_SEQUENCE))
973 return false;
974
975 // CertID ::= SEQUENCE {
976 // hashAlgorithm AlgorithmIdentifier,
977 // issuerNameHash OCTET STRING, -- Hash of issuer's DN
978 // issuerKeyHash OCTET STRING, -- Hash of issuer's public key
979 // serialNumber CertificateSerialNumber }
980
981 // TODO(eroman): Don't use SHA1.
982 const EVP_MD* md = EVP_sha1();
983 if (!EVP_marshal_digest_algorithm(&req_cert, md))
984 return false;
985
986 AppendHashAsOctetString(md, &req_cert, issuer->tbs().subject_tlv);
987
988 der::Input key_tlv;
989 if (!GetSubjectPublicKeyBytes(issuer->tbs().spki_tlv, &key_tlv))
990 return false;
991 AppendHashAsOctetString(md, &req_cert, key_tlv);
992
993 CBB serial_number;
994 if (!CBB_add_asn1(&req_cert, &serial_number, CBS_ASN1_INTEGER))
995 return false;
996 if (!CBB_add_bytes(&serial_number, cert->tbs().serial_number.UnsafeData(),
997 cert->tbs().serial_number.Length())) {
998 return false;
999 }
1000
1001 uint8_t* result_bytes;
1002 size_t result_bytes_length;
1003 if (!CBB_finish(cbb.get(), &result_bytes, &result_bytes_length))
1004 return false;
1005 bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(result_bytes);
1006
1007 request_der->assign(result_bytes, result_bytes + result_bytes_length);
1008 return true;
1009 }
1010
1011 // From RFC 2560 section A.1.1:
1012 //
1013 // An OCSP request using the GET method is constructed as follows:
1014 //
1015 // GET {url}/{url-encoding of base-64 encoding of the DER encoding of
1016 // the OCSPRequest}
CreateOCSPGetURL(const ParsedCertificate * cert,const ParsedCertificate * issuer,std::string_view ocsp_responder_url)1017 std::optional<std::string> CreateOCSPGetURL(
1018 const ParsedCertificate* cert,
1019 const ParsedCertificate* issuer,
1020 std::string_view ocsp_responder_url) {
1021 std::vector<uint8_t> ocsp_request_der;
1022 if (!CreateOCSPRequest(cert, issuer, &ocsp_request_der)) {
1023 // Unexpected (means BoringSSL failed an operation).
1024 return std::nullopt;
1025 }
1026
1027 // Base64 encode the request data.
1028 size_t len;
1029 if (!EVP_EncodedLength(&len, ocsp_request_der.size())) {
1030 return std::nullopt;
1031 }
1032 std::vector<uint8_t> encoded(len);
1033 len = EVP_EncodeBlock(encoded.data(), ocsp_request_der.data(),
1034 ocsp_request_der.size());
1035
1036 std::string b64_encoded(encoded.begin(), encoded.begin() + len);
1037
1038 // In theory +, /, and = are valid in paths and don't need to be escaped.
1039 // However from the example in RFC 5019 section 5 it is clear that the intent
1040 // is to escape non-alphanumeric characters (the example conclusively escapes
1041 // '/' and '=', but doesn't clarify '+').
1042 b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "+", "%2B");
1043 b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "/", "%2F");
1044 b64_encoded = bssl::string_util::FindAndReplace(b64_encoded, "=", "%3D");
1045
1046 // No attempt is made to collapse double slashes for URLs that end in slash,
1047 // since the spec doesn't do that.
1048 return std::string(ocsp_responder_url) + "/" + b64_encoded;
1049 }
1050
1051 } // namespace net
1052