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