xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/ocsp.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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