• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/quic/crypto/proof_verifier_chromium.h"
11 
12 #include <string_view>
13 #include <utility>
14 
15 #include "base/containers/contains.h"
16 #include "base/containers/span.h"
17 #include "base/functional/bind.h"
18 #include "base/functional/callback_helpers.h"
19 #include "base/logging.h"
20 #include "base/memory/raw_ptr.h"
21 #include "base/metrics/histogram_functions.h"
22 #include "base/metrics/histogram_macros.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/time/time.h"
25 #include "crypto/signature_verifier.h"
26 #include "net/base/host_port_pair.h"
27 #include "net/base/net_errors.h"
28 #include "net/base/network_anonymization_key.h"
29 #include "net/cert/cert_status_flags.h"
30 #include "net/cert/cert_verifier.h"
31 #include "net/cert/ct_verifier.h"
32 #include "net/cert/sct_auditing_delegate.h"
33 #include "net/cert/x509_util.h"
34 #include "net/http/transport_security_state.h"
35 #include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h"
36 
37 using base::StringPrintf;
38 using std::string;
39 
40 namespace net {
41 
42 ProofVerifyDetailsChromium::ProofVerifyDetailsChromium() = default;
43 
44 ProofVerifyDetailsChromium::~ProofVerifyDetailsChromium() = default;
45 
46 ProofVerifyDetailsChromium::ProofVerifyDetailsChromium(
47     const ProofVerifyDetailsChromium&) = default;
48 
Clone() const49 quic::ProofVerifyDetails* ProofVerifyDetailsChromium::Clone() const {
50   ProofVerifyDetailsChromium* other = new ProofVerifyDetailsChromium;
51   other->cert_verify_result = cert_verify_result;
52   return other;
53 }
54 
55 // A Job handles the verification of a single proof.  It is owned by the
56 // quic::ProofVerifier. If the verification can not complete synchronously, it
57 // will notify the quic::ProofVerifier upon completion.
58 class ProofVerifierChromium::Job {
59  public:
60   Job(ProofVerifierChromium* proof_verifier,
61       CertVerifier* cert_verifier,
62       TransportSecurityState* transport_security_state,
63       SCTAuditingDelegate* sct_auditing_delegate,
64       int cert_verify_flags,
65       const NetLogWithSource& net_log);
66 
67   Job(const Job&) = delete;
68   Job& operator=(const Job&) = delete;
69 
70   ~Job();
71 
72   // Starts the proof verification.  If |quic::QUIC_PENDING| is returned, then
73   // |callback| will be invoked asynchronously when the verification completes.
74   quic::QuicAsyncStatus VerifyProof(
75       const std::string& hostname,
76       const uint16_t port,
77       const std::string& server_config,
78       quic::QuicTransportVersion quic_version,
79       std::string_view chlo_hash,
80       const std::vector<std::string>& certs,
81       const std::string& cert_sct,
82       const std::string& signature,
83       std::string* error_details,
84       std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
85       std::unique_ptr<quic::ProofVerifierCallback> callback);
86 
87   // Starts the certificate chain verification of |certs|.  If
88   // |quic::QUIC_PENDING| is returned, then |callback| will be invoked
89   // asynchronously when the verification completes.
90   quic::QuicAsyncStatus VerifyCertChain(
91       const std::string& hostname,
92       const uint16_t port,
93       const std::vector<std::string>& certs,
94       const std::string& ocsp_response,
95       const std::string& cert_sct,
96       std::string* error_details,
97       std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
98       std::unique_ptr<quic::ProofVerifierCallback> callback);
99 
100  private:
101   enum State {
102     STATE_NONE,
103     STATE_VERIFY_CERT,
104     STATE_VERIFY_CERT_COMPLETE,
105   };
106 
107   // Convert |certs| to |cert_|(X509Certificate). Returns true if successful.
108   bool GetX509Certificate(
109       const std::vector<string>& certs,
110       std::string* error_details,
111       std::unique_ptr<quic::ProofVerifyDetails>* verify_details);
112 
113   // Start the cert verification.
114   quic::QuicAsyncStatus VerifyCert(
115       const string& hostname,
116       const uint16_t port,
117       const std::string& ocsp_response,
118       const std::string& cert_sct,
119       std::string* error_details,
120       std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
121       std::unique_ptr<quic::ProofVerifierCallback> callback);
122 
123   int DoLoop(int last_io_result);
124   void OnIOComplete(int result);
125   int DoVerifyCert(int result);
126   int DoVerifyCertComplete(int result);
127 
128   bool VerifySignature(const std::string& signed_data,
129                        quic::QuicTransportVersion quic_version,
130                        std::string_view chlo_hash,
131                        const std::string& signature,
132                        const std::string& cert);
133 
134   bool ShouldAllowUnknownRootForHost(const std::string& hostname);
135 
136   int CheckCTRequirements();
137 
138   // Must be before `cert_verifier_request_`, to avoid dangling pointer
139   // warnings, as the Request may be storing a raw pointer to which may have a
140   // raw_ptr to its `cert_verify_result`.
141   std::unique_ptr<ProofVerifyDetailsChromium> verify_details_;
142 
143   // Proof verifier to notify when this jobs completes.
144   raw_ptr<ProofVerifierChromium> proof_verifier_;
145 
146   // The underlying verifier used for verifying certificates.
147   raw_ptr<CertVerifier> verifier_;
148   std::unique_ptr<CertVerifier::Request> cert_verifier_request_;
149 
150   raw_ptr<TransportSecurityState> transport_security_state_;
151 
152   raw_ptr<SCTAuditingDelegate> sct_auditing_delegate_;
153 
154   // |hostname| specifies the hostname for which |certs| is a valid chain.
155   std::string hostname_;
156   // |port| specifies the target port for the connection.
157   uint16_t port_;
158   // Encoded stapled OCSP response for |certs|.
159   std::string ocsp_response_;
160   // Encoded SignedCertificateTimestampList for |certs|.
161   std::string cert_sct_;
162 
163   std::unique_ptr<quic::ProofVerifierCallback> callback_;
164   std::string error_details_;
165 
166   // X509Certificate from a chain of DER encoded certificates.
167   scoped_refptr<X509Certificate> cert_;
168 
169   // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is
170   // passed to CertVerifier::Verify.
171   int cert_verify_flags_;
172 
173   State next_state_ = STATE_NONE;
174 
175   base::TimeTicks start_time_;
176 
177   NetLogWithSource net_log_;
178 };
179 
Job(ProofVerifierChromium * proof_verifier,CertVerifier * cert_verifier,TransportSecurityState * transport_security_state,SCTAuditingDelegate * sct_auditing_delegate,int cert_verify_flags,const NetLogWithSource & net_log)180 ProofVerifierChromium::Job::Job(
181     ProofVerifierChromium* proof_verifier,
182     CertVerifier* cert_verifier,
183     TransportSecurityState* transport_security_state,
184     SCTAuditingDelegate* sct_auditing_delegate,
185     int cert_verify_flags,
186     const NetLogWithSource& net_log)
187     : proof_verifier_(proof_verifier),
188       verifier_(cert_verifier),
189       transport_security_state_(transport_security_state),
190       sct_auditing_delegate_(sct_auditing_delegate),
191       cert_verify_flags_(cert_verify_flags),
192       start_time_(base::TimeTicks::Now()),
193       net_log_(net_log) {
194   CHECK(proof_verifier_);
195   CHECK(verifier_);
196   CHECK(transport_security_state_);
197 }
198 
~Job()199 ProofVerifierChromium::Job::~Job() {
200   base::TimeTicks end_time = base::TimeTicks::Now();
201   UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime",
202                       end_time - start_time_);
203   // |hostname_| will always be canonicalized to lowercase.
204   if (hostname_.compare("www.google.com") == 0) {
205     UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.google",
206                         end_time - start_time_);
207   }
208 }
209 
VerifyProof(const string & hostname,const uint16_t port,const string & server_config,quic::QuicTransportVersion quic_version,std::string_view chlo_hash,const std::vector<string> & certs,const std::string & cert_sct,const string & signature,std::string * error_details,std::unique_ptr<quic::ProofVerifyDetails> * verify_details,std::unique_ptr<quic::ProofVerifierCallback> callback)210 quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
211     const string& hostname,
212     const uint16_t port,
213     const string& server_config,
214     quic::QuicTransportVersion quic_version,
215     std::string_view chlo_hash,
216     const std::vector<string>& certs,
217     const std::string& cert_sct,
218     const string& signature,
219     std::string* error_details,
220     std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
221     std::unique_ptr<quic::ProofVerifierCallback> callback) {
222   DCHECK(error_details);
223   DCHECK(verify_details);
224   DCHECK(callback);
225 
226   error_details->clear();
227 
228   if (STATE_NONE != next_state_) {
229     *error_details = "Certificate is already set and VerifyProof has begun";
230     DLOG(DFATAL) << *error_details;
231     return quic::QUIC_FAILURE;
232   }
233 
234   verify_details_ = std::make_unique<ProofVerifyDetailsChromium>();
235 
236   // Converts |certs| to |cert_|.
237   if (!GetX509Certificate(certs, error_details, verify_details))
238     return quic::QUIC_FAILURE;
239 
240   // We call VerifySignature first to avoid copying of server_config and
241   // signature.
242   if (!VerifySignature(server_config, quic_version, chlo_hash, signature,
243                        certs[0])) {
244     *error_details = "Failed to verify signature of server config";
245     DLOG(WARNING) << *error_details;
246     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
247     *verify_details = std::move(verify_details_);
248     return quic::QUIC_FAILURE;
249   }
250 
251   return VerifyCert(hostname, port, /*ocsp_response=*/std::string(), cert_sct,
252                     error_details, verify_details, std::move(callback));
253 }
254 
VerifyCertChain(const string & hostname,const uint16_t port,const std::vector<string> & certs,const std::string & ocsp_response,const std::string & cert_sct,std::string * error_details,std::unique_ptr<quic::ProofVerifyDetails> * verify_details,std::unique_ptr<quic::ProofVerifierCallback> callback)255 quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
256     const string& hostname,
257     const uint16_t port,
258     const std::vector<string>& certs,
259     const std::string& ocsp_response,
260     const std::string& cert_sct,
261     std::string* error_details,
262     std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
263     std::unique_ptr<quic::ProofVerifierCallback> callback) {
264   DCHECK(error_details);
265   DCHECK(verify_details);
266   DCHECK(callback);
267 
268   error_details->clear();
269 
270   if (STATE_NONE != next_state_) {
271     *error_details = "Certificate is already set and VerifyCertChain has begun";
272     DLOG(DFATAL) << *error_details;
273     return quic::QUIC_FAILURE;
274   }
275 
276   verify_details_ = std::make_unique<ProofVerifyDetailsChromium>();
277 
278   // Converts |certs| to |cert_|.
279   if (!GetX509Certificate(certs, error_details, verify_details))
280     return quic::QUIC_FAILURE;
281 
282   return VerifyCert(hostname, port, ocsp_response, cert_sct, error_details,
283                     verify_details, std::move(callback));
284 }
285 
GetX509Certificate(const std::vector<string> & certs,std::string * error_details,std::unique_ptr<quic::ProofVerifyDetails> * verify_details)286 bool ProofVerifierChromium::Job::GetX509Certificate(
287     const std::vector<string>& certs,
288     std::string* error_details,
289     std::unique_ptr<quic::ProofVerifyDetails>* verify_details) {
290   if (certs.empty()) {
291     *error_details = "Failed to create certificate chain. Certs are empty.";
292     DLOG(WARNING) << *error_details;
293     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
294     *verify_details = std::move(verify_details_);
295     return false;
296   }
297 
298   // Convert certs to X509Certificate.
299   std::vector<std::string_view> cert_pieces(certs.size());
300   for (unsigned i = 0; i < certs.size(); i++) {
301     cert_pieces[i] = std::string_view(certs[i]);
302   }
303   cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
304   if (!cert_.get()) {
305     *error_details = "Failed to create certificate chain";
306     DLOG(WARNING) << *error_details;
307     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
308     *verify_details = std::move(verify_details_);
309     return false;
310   }
311   return true;
312 }
313 
VerifyCert(const string & hostname,const uint16_t port,const std::string & ocsp_response,const std::string & cert_sct,std::string * error_details,std::unique_ptr<quic::ProofVerifyDetails> * verify_details,std::unique_ptr<quic::ProofVerifierCallback> callback)314 quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert(
315     const string& hostname,
316     const uint16_t port,
317     const std::string& ocsp_response,
318     const std::string& cert_sct,
319     std::string* error_details,
320     std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
321     std::unique_ptr<quic::ProofVerifierCallback> callback) {
322   hostname_ = hostname;
323   port_ = port;
324   ocsp_response_ = ocsp_response;
325   cert_sct_ = cert_sct;
326 
327   next_state_ = STATE_VERIFY_CERT;
328   switch (DoLoop(OK)) {
329     case OK:
330       *verify_details = std::move(verify_details_);
331       return quic::QUIC_SUCCESS;
332     case ERR_IO_PENDING:
333       callback_ = std::move(callback);
334       return quic::QUIC_PENDING;
335     default:
336       *error_details = error_details_;
337       *verify_details = std::move(verify_details_);
338       return quic::QUIC_FAILURE;
339   }
340 }
341 
DoLoop(int last_result)342 int ProofVerifierChromium::Job::DoLoop(int last_result) {
343   int rv = last_result;
344   do {
345     State state = next_state_;
346     next_state_ = STATE_NONE;
347     switch (state) {
348       case STATE_VERIFY_CERT:
349         DCHECK(rv == OK);
350         rv = DoVerifyCert(rv);
351         break;
352       case STATE_VERIFY_CERT_COMPLETE:
353         rv = DoVerifyCertComplete(rv);
354         break;
355       case STATE_NONE:
356       default:
357         rv = ERR_UNEXPECTED;
358         LOG(DFATAL) << "unexpected state " << state;
359         break;
360     }
361   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
362   return rv;
363 }
364 
OnIOComplete(int result)365 void ProofVerifierChromium::Job::OnIOComplete(int result) {
366   int rv = DoLoop(result);
367   if (rv != ERR_IO_PENDING) {
368     std::unique_ptr<quic::ProofVerifierCallback> callback(std::move(callback_));
369     // Callback expects quic::ProofVerifyDetails not ProofVerifyDetailsChromium.
370     std::unique_ptr<quic::ProofVerifyDetails> verify_details(
371         std::move(verify_details_));
372     callback->Run(rv == OK, error_details_, &verify_details);
373     // Will delete |this|.
374     proof_verifier_->OnJobComplete(this);
375   }
376 }
377 
DoVerifyCert(int result)378 int ProofVerifierChromium::Job::DoVerifyCert(int result) {
379   next_state_ = STATE_VERIFY_CERT_COMPLETE;
380 
381   return verifier_->Verify(
382       CertVerifier::RequestParams(cert_, hostname_, cert_verify_flags_,
383                                   ocsp_response_, cert_sct_),
384       &verify_details_->cert_verify_result,
385       base::BindOnce(&ProofVerifierChromium::Job::OnIOComplete,
386                      base::Unretained(this)),
387       &cert_verifier_request_, net_log_);
388 }
389 
ShouldAllowUnknownRootForHost(const std::string & hostname)390 bool ProofVerifierChromium::Job::ShouldAllowUnknownRootForHost(
391     const std::string& hostname) {
392   if (base::Contains(proof_verifier_->hostnames_to_allow_unknown_roots_, "")) {
393     return true;
394   }
395   return base::Contains(proof_verifier_->hostnames_to_allow_unknown_roots_,
396                         hostname);
397 }
398 
DoVerifyCertComplete(int result)399 int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
400   base::UmaHistogramSparse("Net.QuicSession.CertVerificationResult", -result);
401   cert_verifier_request_.reset();
402 
403   const CertVerifyResult& cert_verify_result =
404       verify_details_->cert_verify_result;
405   const CertStatus cert_status = cert_verify_result.cert_status;
406 
407   // If the connection was good, check HPKP and CT status simultaneously,
408   // but prefer to treat the HPKP error as more serious, if there was one.
409   if (result == OK) {
410     int ct_result = CheckCTRequirements();
411     TransportSecurityState::PKPStatus pin_validity =
412         transport_security_state_->CheckPublicKeyPins(
413             HostPortPair(hostname_, port_),
414             cert_verify_result.is_issued_by_known_root,
415             cert_verify_result.public_key_hashes);
416     switch (pin_validity) {
417       case TransportSecurityState::PKPStatus::VIOLATED:
418         result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
419         verify_details_->cert_verify_result.cert_status |=
420             CERT_STATUS_PINNED_KEY_MISSING;
421         break;
422       case TransportSecurityState::PKPStatus::BYPASSED:
423         verify_details_->pkp_bypassed = true;
424         [[fallthrough]];
425       case TransportSecurityState::PKPStatus::OK:
426         // Do nothing.
427         break;
428     }
429     if (result != ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN && ct_result != OK)
430       result = ct_result;
431   }
432 
433   if (result == OK &&
434       !verify_details_->cert_verify_result.is_issued_by_known_root &&
435       !ShouldAllowUnknownRootForHost(hostname_)) {
436     result = ERR_QUIC_CERT_ROOT_NOT_KNOWN;
437   }
438 
439   verify_details_->is_fatal_cert_error =
440       IsCertStatusError(cert_status) &&
441       result != ERR_CERT_KNOWN_INTERCEPTION_BLOCKED &&
442       transport_security_state_->ShouldSSLErrorsBeFatal(hostname_);
443 
444   if (result != OK) {
445     std::string error_string = ErrorToString(result);
446     error_details_ = StringPrintf("Failed to verify certificate chain: %s",
447                                   error_string.c_str());
448     DLOG(WARNING) << error_details_;
449   }
450 
451   // Exit DoLoop and return the result to the caller to VerifyProof.
452   DCHECK_EQ(STATE_NONE, next_state_);
453   return result;
454 }
455 
VerifySignature(const string & signed_data,quic::QuicTransportVersion quic_version,std::string_view chlo_hash,const string & signature,const string & cert)456 bool ProofVerifierChromium::Job::VerifySignature(
457     const string& signed_data,
458     quic::QuicTransportVersion quic_version,
459     std::string_view chlo_hash,
460     const string& signature,
461     const string& cert) {
462   size_t size_bits;
463   X509Certificate::PublicKeyType type;
464   X509Certificate::GetPublicKeyInfo(cert_->cert_buffer(), &size_bits, &type);
465   crypto::SignatureVerifier::SignatureAlgorithm algorithm;
466   switch (type) {
467     case X509Certificate::kPublicKeyTypeRSA:
468       algorithm = crypto::SignatureVerifier::RSA_PSS_SHA256;
469       break;
470     case X509Certificate::kPublicKeyTypeECDSA:
471       algorithm = crypto::SignatureVerifier::ECDSA_SHA256;
472       break;
473     default:
474       LOG(ERROR) << "Unsupported public key type " << type;
475       return false;
476   }
477 
478   if (signature.empty()) {
479     DLOG(WARNING) << "Signature is empty, thus cannot possibly be valid";
480     return false;
481   }
482 
483   crypto::SignatureVerifier verifier;
484   if (!x509_util::SignatureVerifierInitWithCertificate(
485           &verifier, algorithm, base::as_byte_span(signature),
486           cert_->cert_buffer())) {
487     DLOG(WARNING) << "SignatureVerifierInitWithCertificate failed";
488     return false;
489   }
490 
491   verifier.VerifyUpdate(base::as_byte_span(quic::kProofSignatureLabel));
492   uint32_t len = chlo_hash.length();
493   verifier.VerifyUpdate(base::byte_span_from_ref(len));
494   verifier.VerifyUpdate(base::as_byte_span(chlo_hash));
495   verifier.VerifyUpdate(base::as_byte_span(signed_data));
496 
497   if (!verifier.VerifyFinal()) {
498     DLOG(WARNING) << "VerifyFinal failed";
499     return false;
500   }
501 
502   DVLOG(1) << "VerifyFinal success";
503   return true;
504 }
505 
CheckCTRequirements()506 int ProofVerifierChromium::Job::CheckCTRequirements() {
507   const CertVerifyResult& cert_verify_result =
508       verify_details_->cert_verify_result;
509 
510   TransportSecurityState::CTRequirementsStatus ct_requirement_status =
511       transport_security_state_->CheckCTRequirements(
512           HostPortPair(hostname_, port_),
513           cert_verify_result.is_issued_by_known_root,
514           cert_verify_result.public_key_hashes,
515           cert_verify_result.verified_cert.get(),
516           cert_verify_result.policy_compliance);
517 
518   if (sct_auditing_delegate_) {
519     sct_auditing_delegate_->MaybeEnqueueReport(
520         HostPortPair(hostname_, port_), cert_verify_result.verified_cert.get(),
521         cert_verify_result.scts);
522   }
523 
524   switch (ct_requirement_status) {
525     case TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
526       verify_details_->cert_verify_result.cert_status |=
527           CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
528       return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
529     case TransportSecurityState::CT_REQUIREMENTS_MET:
530     case TransportSecurityState::CT_NOT_REQUIRED:
531       return OK;
532   }
533 }
534 
ProofVerifierChromium(CertVerifier * cert_verifier,TransportSecurityState * transport_security_state,SCTAuditingDelegate * sct_auditing_delegate,std::set<std::string> hostnames_to_allow_unknown_roots,const NetworkAnonymizationKey & network_anonymization_key)535 ProofVerifierChromium::ProofVerifierChromium(
536     CertVerifier* cert_verifier,
537     TransportSecurityState* transport_security_state,
538     SCTAuditingDelegate* sct_auditing_delegate,
539     std::set<std::string> hostnames_to_allow_unknown_roots,
540     const NetworkAnonymizationKey& network_anonymization_key)
541     : cert_verifier_(cert_verifier),
542       transport_security_state_(transport_security_state),
543       sct_auditing_delegate_(sct_auditing_delegate),
544       hostnames_to_allow_unknown_roots_(hostnames_to_allow_unknown_roots),
545       network_anonymization_key_(network_anonymization_key) {
546   DCHECK(cert_verifier_);
547   DCHECK(transport_security_state_);
548 }
549 
550 ProofVerifierChromium::~ProofVerifierChromium() = default;
551 
VerifyProof(const std::string & hostname,const uint16_t port,const std::string & server_config,quic::QuicTransportVersion quic_version,std::string_view chlo_hash,const std::vector<std::string> & certs,const std::string & cert_sct,const std::string & signature,const quic::ProofVerifyContext * verify_context,std::string * error_details,std::unique_ptr<quic::ProofVerifyDetails> * verify_details,std::unique_ptr<quic::ProofVerifierCallback> callback)552 quic::QuicAsyncStatus ProofVerifierChromium::VerifyProof(
553     const std::string& hostname,
554     const uint16_t port,
555     const std::string& server_config,
556     quic::QuicTransportVersion quic_version,
557     std::string_view chlo_hash,
558     const std::vector<std::string>& certs,
559     const std::string& cert_sct,
560     const std::string& signature,
561     const quic::ProofVerifyContext* verify_context,
562     std::string* error_details,
563     std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
564     std::unique_ptr<quic::ProofVerifierCallback> callback) {
565   if (!verify_context) {
566     DLOG(FATAL) << "Missing proof verify context";
567     *error_details = "Missing context";
568     return quic::QUIC_FAILURE;
569   }
570   const ProofVerifyContextChromium* chromium_context =
571       reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
572   std::unique_ptr<Job> job = std::make_unique<Job>(
573       this, cert_verifier_, transport_security_state_, sct_auditing_delegate_,
574       chromium_context->cert_verify_flags, chromium_context->net_log);
575   quic::QuicAsyncStatus status = job->VerifyProof(
576       hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
577       signature, error_details, verify_details, std::move(callback));
578   if (status == quic::QUIC_PENDING) {
579     Job* job_ptr = job.get();
580     active_jobs_[job_ptr] = std::move(job);
581   }
582   return status;
583 }
584 
VerifyCertChain(const std::string & hostname,const uint16_t port,const std::vector<std::string> & certs,const std::string & ocsp_response,const std::string & cert_sct,const quic::ProofVerifyContext * verify_context,std::string * error_details,std::unique_ptr<quic::ProofVerifyDetails> * verify_details,uint8_t *,std::unique_ptr<quic::ProofVerifierCallback> callback)585 quic::QuicAsyncStatus ProofVerifierChromium::VerifyCertChain(
586     const std::string& hostname,
587     const uint16_t port,
588     const std::vector<std::string>& certs,
589     const std::string& ocsp_response,
590     const std::string& cert_sct,
591     const quic::ProofVerifyContext* verify_context,
592     std::string* error_details,
593     std::unique_ptr<quic::ProofVerifyDetails>* verify_details,
594     uint8_t* /*out_alert*/,
595     std::unique_ptr<quic::ProofVerifierCallback> callback) {
596   if (!verify_context) {
597     *error_details = "Missing context";
598     return quic::QUIC_FAILURE;
599   }
600   const ProofVerifyContextChromium* chromium_context =
601       reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
602   std::unique_ptr<Job> job = std::make_unique<Job>(
603       this, cert_verifier_, transport_security_state_, sct_auditing_delegate_,
604       chromium_context->cert_verify_flags, chromium_context->net_log);
605   quic::QuicAsyncStatus status =
606       job->VerifyCertChain(hostname, port, certs, ocsp_response, cert_sct,
607                            error_details, verify_details, std::move(callback));
608   if (status == quic::QUIC_PENDING) {
609     Job* job_ptr = job.get();
610     active_jobs_[job_ptr] = std::move(job);
611   }
612   return status;
613 }
614 
615 std::unique_ptr<quic::ProofVerifyContext>
CreateDefaultContext()616 ProofVerifierChromium::CreateDefaultContext() {
617   return std::make_unique<ProofVerifyContextChromium>(0,
618                                                       net::NetLogWithSource());
619 }
620 
OnJobComplete(Job * job)621 void ProofVerifierChromium::OnJobComplete(Job* job) {
622   active_jobs_.erase(job);
623 }
624 
625 }  // namespace net
626