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