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