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