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