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