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