blob: e247b597f9c2664e36f339ddaf6b4f12e77a1421 [file] [log] [blame]
[email protected]2662ed562013-07-03 10:27:461// Copyright 2013 The Chromium Authors. All rights reserved.
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 "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback_helpers.h"
10#include "base/compiler_specific.h"
11#include "base/logging.h"
asvitkinec3c93722015-06-17 14:48:3712#include "base/metrics/histogram_macros.h"
[email protected]5c78ce62014-03-13 19:48:0113#include "base/stl_util.h"
[email protected]2662ed562013-07-03 10:27:4614#include "base/strings/stringprintf.h"
15#include "crypto/signature_verifier.h"
estark1a66df72015-07-28 15:24:0016#include "net/base/host_port_pair.h"
[email protected]2662ed562013-07-03 10:27:4617#include "net/base/net_errors.h"
[email protected]2662ed562013-07-03 10:27:4618#include "net/cert/asn1_util.h"
rsleevi9541f8632015-07-31 00:07:0019#include "net/cert/cert_policy_enforcer.h"
[email protected]2662ed562013-07-03 10:27:4620#include "net/cert/cert_status_flags.h"
21#include "net/cert/cert_verifier.h"
22#include "net/cert/cert_verify_result.h"
rtenneti052774e2015-11-24 21:00:1223#include "net/cert/ct_verifier.h"
[email protected]2662ed562013-07-03 10:27:4624#include "net/cert/x509_certificate.h"
25#include "net/cert/x509_util.h"
[email protected]080b77932014-08-04 01:22:4626#include "net/http/transport_security_state.h"
eroman87c53d62015-04-02 06:51:0727#include "net/log/net_log.h"
[email protected]2662ed562013-07-03 10:27:4628#include "net/quic/crypto/crypto_protocol.h"
29#include "net/ssl/ssl_config_service.h"
30
31using base::StringPiece;
32using base::StringPrintf;
33using std::string;
34using std::vector;
35
36namespace net {
37
[email protected]92bc621d2014-07-29 21:42:1338ProofVerifyDetails* ProofVerifyDetailsChromium::Clone() const {
39 ProofVerifyDetailsChromium* other = new ProofVerifyDetailsChromium;
40 other->cert_verify_result = cert_verify_result;
rtenneti052774e2015-11-24 21:00:1241 other->ct_verify_result = ct_verify_result;
[email protected]92bc621d2014-07-29 21:42:1342 return other;
43}
44
[email protected]5c78ce62014-03-13 19:48:0145// A Job handles the verification of a single proof. It is owned by the
46// ProofVerifier. If the verification can not complete synchronously, it
47// will notify the ProofVerifier upon completion.
48class ProofVerifierChromium::Job {
49 public:
50 Job(ProofVerifierChromium* proof_verifier,
51 CertVerifier* cert_verifier,
rsleevi9541f8632015-07-31 00:07:0052 CertPolicyEnforcer* cert_policy_enforcer,
[email protected]080b77932014-08-04 01:22:4653 TransportSecurityState* transport_security_state,
rtenneti052774e2015-11-24 21:00:1254 CTVerifier* cert_transparency_verifier,
rtennetia75df622015-06-21 23:59:5055 int cert_verify_flags,
[email protected]5c78ce62014-03-13 19:48:0156 const BoundNetLog& net_log);
57
[email protected]05bfc260f2014-06-07 06:31:2558 // Starts the proof verification. If |QUIC_PENDING| is returned, then
59 // |callback| will be invoked asynchronously when the verification completes.
[email protected]730b35d72014-06-05 03:23:2260 QuicAsyncStatus VerifyProof(const std::string& hostname,
61 const std::string& server_config,
62 const std::vector<std::string>& certs,
rjshadec86dbfa2015-11-12 20:16:2563 const std::string& cert_sct,
[email protected]730b35d72014-06-05 03:23:2264 const std::string& signature,
65 std::string* error_details,
66 scoped_ptr<ProofVerifyDetails>* verify_details,
67 ProofVerifierCallback* callback);
[email protected]5c78ce62014-03-13 19:48:0168
69 private:
70 enum State {
71 STATE_NONE,
72 STATE_VERIFY_CERT,
73 STATE_VERIFY_CERT_COMPLETE,
74 };
75
76 int DoLoop(int last_io_result);
77 void OnIOComplete(int result);
78 int DoVerifyCert(int result);
79 int DoVerifyCertComplete(int result);
80
81 bool VerifySignature(const std::string& signed_data,
82 const std::string& signature,
83 const std::string& cert);
84
85 // Proof verifier to notify when this jobs completes.
86 ProofVerifierChromium* proof_verifier_;
87
88 // The underlying verifier used for verifying certificates.
eroman7f9236a2015-05-11 21:23:4389 CertVerifier* verifier_;
90 scoped_ptr<CertVerifier::Request> cert_verifier_request_;
[email protected]5c78ce62014-03-13 19:48:0191
rsleevi9541f8632015-07-31 00:07:0092 CertPolicyEnforcer* policy_enforcer_;
93
[email protected]080b77932014-08-04 01:22:4694 TransportSecurityState* transport_security_state_;
95
rtenneti052774e2015-11-24 21:00:1296 CTVerifier* cert_transparency_verifier_;
97
[email protected]5c78ce62014-03-13 19:48:0198 // |hostname| specifies the hostname for which |certs| is a valid chain.
99 std::string hostname_;
100
101 scoped_ptr<ProofVerifierCallback> callback_;
102 scoped_ptr<ProofVerifyDetailsChromium> verify_details_;
103 std::string error_details_;
104
105 // X509Certificate from a chain of DER encoded certificates.
106 scoped_refptr<X509Certificate> cert_;
107
rtennetia75df622015-06-21 23:59:50108 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is
109 // passed to CertVerifier::Verify.
110 int cert_verify_flags_;
111
[email protected]5c78ce62014-03-13 19:48:01112 State next_state_;
113
114 BoundNetLog net_log_;
115
116 DISALLOW_COPY_AND_ASSIGN(Job);
117};
118
[email protected]080b77932014-08-04 01:22:46119ProofVerifierChromium::Job::Job(
120 ProofVerifierChromium* proof_verifier,
121 CertVerifier* cert_verifier,
rsleevi9541f8632015-07-31 00:07:00122 CertPolicyEnforcer* cert_policy_enforcer,
[email protected]080b77932014-08-04 01:22:46123 TransportSecurityState* transport_security_state,
rtenneti052774e2015-11-24 21:00:12124 CTVerifier* cert_transparency_verifier,
rtennetia75df622015-06-21 23:59:50125 int cert_verify_flags,
[email protected]080b77932014-08-04 01:22:46126 const BoundNetLog& net_log)
[email protected]5c78ce62014-03-13 19:48:01127 : proof_verifier_(proof_verifier),
eroman7f9236a2015-05-11 21:23:43128 verifier_(cert_verifier),
rsleevi9541f8632015-07-31 00:07:00129 policy_enforcer_(cert_policy_enforcer),
[email protected]080b77932014-08-04 01:22:46130 transport_security_state_(transport_security_state),
rtenneti052774e2015-11-24 21:00:12131 cert_transparency_verifier_(cert_transparency_verifier),
rtennetia75df622015-06-21 23:59:50132 cert_verify_flags_(cert_verify_flags),
[email protected]5c78ce62014-03-13 19:48:01133 next_state_(STATE_NONE),
rsleevi9541f8632015-07-31 00:07:00134 net_log_(net_log) {}
[email protected]2662ed562013-07-03 10:27:46135
[email protected]730b35d72014-06-05 03:23:22136QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
[email protected]72e65992013-07-30 17:16:14137 const string& hostname,
138 const string& server_config,
139 const vector<string>& certs,
rjshadec86dbfa2015-11-12 20:16:25140 const std::string& cert_sct,
[email protected]72e65992013-07-30 17:16:14141 const string& signature,
142 std::string* error_details,
[email protected]c817c672014-03-21 22:25:34143 scoped_ptr<ProofVerifyDetails>* verify_details,
[email protected]72e65992013-07-30 17:16:14144 ProofVerifierCallback* callback) {
[email protected]2662ed562013-07-03 10:27:46145 DCHECK(error_details);
[email protected]c817c672014-03-21 22:25:34146 DCHECK(verify_details);
[email protected]72e65992013-07-30 17:16:14147 DCHECK(callback);
148
[email protected]2662ed562013-07-03 10:27:46149 error_details->clear();
150
[email protected]2662ed562013-07-03 10:27:46151 if (STATE_NONE != next_state_) {
152 *error_details = "Certificate is already set and VerifyProof has begun";
[email protected]5c78ce62014-03-13 19:48:01153 DLOG(DFATAL) << *error_details;
[email protected]730b35d72014-06-05 03:23:22154 return QUIC_FAILURE;
[email protected]2662ed562013-07-03 10:27:46155 }
156
[email protected]72e65992013-07-30 17:16:14157 verify_details_.reset(new ProofVerifyDetailsChromium);
158
[email protected]2662ed562013-07-03 10:27:46159 if (certs.empty()) {
160 *error_details = "Failed to create certificate chain. Certs are empty.";
161 DLOG(WARNING) << *error_details;
[email protected]72e65992013-07-30 17:16:14162 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
[email protected]0cceb922014-07-01 02:00:56163 *verify_details = verify_details_.Pass();
[email protected]730b35d72014-06-05 03:23:22164 return QUIC_FAILURE;
[email protected]2662ed562013-07-03 10:27:46165 }
166
167 // Convert certs to X509Certificate.
168 vector<StringPiece> cert_pieces(certs.size());
169 for (unsigned i = 0; i < certs.size(); i++) {
170 cert_pieces[i] = base::StringPiece(certs[i]);
171 }
172 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
173 if (!cert_.get()) {
[email protected]2662ed562013-07-03 10:27:46174 *error_details = "Failed to create certificate chain";
175 DLOG(WARNING) << *error_details;
[email protected]72e65992013-07-30 17:16:14176 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
[email protected]0cceb922014-07-01 02:00:56177 *verify_details = verify_details_.Pass();
[email protected]730b35d72014-06-05 03:23:22178 return QUIC_FAILURE;
[email protected]2662ed562013-07-03 10:27:46179 }
180
rtenneti052774e2015-11-24 21:00:12181 if (cert_transparency_verifier_ && !cert_sct.empty()) {
182 // Note that this is a completely synchronous operation: The CT Log Verifier
183 // gets all the data it needs for SCT verification and does not do any
184 // external communication.
185 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct,
186 &verify_details_->ct_verify_result,
187 net_log_);
188 }
189
[email protected]2662ed562013-07-03 10:27:46190 // We call VerifySignature first to avoid copying of server_config and
191 // signature.
[email protected]d5c9e4ba2013-09-14 05:25:58192 if (!VerifySignature(server_config, signature, certs[0])) {
[email protected]2662ed562013-07-03 10:27:46193 *error_details = "Failed to verify signature of server config";
194 DLOG(WARNING) << *error_details;
[email protected]72e65992013-07-30 17:16:14195 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
[email protected]0cceb922014-07-01 02:00:56196 *verify_details = verify_details_.Pass();
[email protected]730b35d72014-06-05 03:23:22197 return QUIC_FAILURE;
[email protected]2662ed562013-07-03 10:27:46198 }
199
200 hostname_ = hostname;
[email protected]2662ed562013-07-03 10:27:46201
202 next_state_ = STATE_VERIFY_CERT;
[email protected]72e65992013-07-30 17:16:14203 switch (DoLoop(OK)) {
204 case OK:
[email protected]0cceb922014-07-01 02:00:56205 *verify_details = verify_details_.Pass();
[email protected]730b35d72014-06-05 03:23:22206 return QUIC_SUCCESS;
[email protected]72e65992013-07-30 17:16:14207 case ERR_IO_PENDING:
[email protected]3ce3bf22014-04-03 08:02:01208 callback_.reset(callback);
[email protected]730b35d72014-06-05 03:23:22209 return QUIC_PENDING;
[email protected]72e65992013-07-30 17:16:14210 default:
211 *error_details = error_details_;
[email protected]0cceb922014-07-01 02:00:56212 *verify_details = verify_details_.Pass();
[email protected]730b35d72014-06-05 03:23:22213 return QUIC_FAILURE;
[email protected]72e65992013-07-30 17:16:14214 }
[email protected]2662ed562013-07-03 10:27:46215}
216
[email protected]5c78ce62014-03-13 19:48:01217int ProofVerifierChromium::Job::DoLoop(int last_result) {
[email protected]2662ed562013-07-03 10:27:46218 int rv = last_result;
219 do {
220 State state = next_state_;
221 next_state_ = STATE_NONE;
222 switch (state) {
223 case STATE_VERIFY_CERT:
224 DCHECK(rv == OK);
225 rv = DoVerifyCert(rv);
226 break;
227 case STATE_VERIFY_CERT_COMPLETE:
228 rv = DoVerifyCertComplete(rv);
229 break;
230 case STATE_NONE:
231 default:
232 rv = ERR_UNEXPECTED;
233 LOG(DFATAL) << "unexpected state " << state;
234 break;
235 }
236 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
237 return rv;
238}
239
[email protected]5c78ce62014-03-13 19:48:01240void ProofVerifierChromium::Job::OnIOComplete(int result) {
[email protected]2662ed562013-07-03 10:27:46241 int rv = DoLoop(result);
242 if (rv != ERR_IO_PENDING) {
[email protected]0cceb922014-07-01 02:00:56243 scoped_ptr<ProofVerifierCallback> callback(callback_.Pass());
[email protected]5c78ce62014-03-13 19:48:01244 // Callback expects ProofVerifyDetails not ProofVerifyDetailsChromium.
[email protected]0cceb922014-07-01 02:00:56245 scoped_ptr<ProofVerifyDetails> verify_details(verify_details_.Pass());
[email protected]5c78ce62014-03-13 19:48:01246 callback->Run(rv == OK, error_details_, &verify_details);
247 // Will delete |this|.
248 proof_verifier_->OnJobComplete(this);
[email protected]2662ed562013-07-03 10:27:46249 }
250}
251
[email protected]5c78ce62014-03-13 19:48:01252int ProofVerifierChromium::Job::DoVerifyCert(int result) {
[email protected]2662ed562013-07-03 10:27:46253 next_state_ = STATE_VERIFY_CERT_COMPLETE;
254
rtennetia75df622015-06-21 23:59:50255 return verifier_->Verify(
256 cert_.get(), hostname_, std::string(), cert_verify_flags_,
257 SSLConfigService::GetCRLSet().get(), &verify_details_->cert_verify_result,
258 base::Bind(&ProofVerifierChromium::Job::OnIOComplete,
259 base::Unretained(this)),
260 &cert_verifier_request_, net_log_);
[email protected]2662ed562013-07-03 10:27:46261}
262
[email protected]5c78ce62014-03-13 19:48:01263int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
eroman7f9236a2015-05-11 21:23:43264 cert_verifier_request_.reset();
[email protected]2662ed562013-07-03 10:27:46265
[email protected]080b77932014-08-04 01:22:46266 const CertVerifyResult& cert_verify_result =
267 verify_details_->cert_verify_result;
[email protected]080b77932014-08-04 01:22:46268 const CertStatus cert_status = cert_verify_result.cert_status;
rsleevi9541f8632015-07-31 00:07:00269 if (result == OK && policy_enforcer_ &&
270 (cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
rsleevi9541f8632015-07-31 00:07:00271 if (!policy_enforcer_->DoesConformToCTEVPolicy(
272 cert_verify_result.verified_cert.get(),
rtenneti052774e2015-11-24 21:00:12273 SSLConfigService::GetEVCertsWhitelist().get(),
274 verify_details_->ct_verify_result, net_log_)) {
haavardm533c27b2015-08-13 09:27:29275 verify_details_->cert_verify_result.cert_status |=
276 CERT_STATUS_CT_COMPLIANCE_FAILED;
rsleevi9541f8632015-07-31 00:07:00277 verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
278 }
279 }
280
estark1a66df72015-07-28 15:24:00281 // TODO(estark): replace 0 below with the port of the connection.
[email protected]8d60aa52014-08-08 21:22:45282 if (transport_security_state_ &&
[email protected]080b77932014-08-04 01:22:46283 (result == OK ||
284 (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
[email protected]8d60aa52014-08-08 21:22:45285 !transport_security_state_->CheckPublicKeyPins(
estark1a66df72015-07-28 15:24:00286 HostPortPair(hostname_, 0),
[email protected]8d60aa52014-08-08 21:22:45287 cert_verify_result.is_issued_by_known_root,
estark1a66df72015-07-28 15:24:00288 cert_verify_result.public_key_hashes, cert_.get(),
289 cert_verify_result.verified_cert.get(),
290 TransportSecurityState::ENABLE_PIN_REPORTS,
[email protected]8d60aa52014-08-08 21:22:45291 &verify_details_->pinning_failure_log)) {
292 result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
[email protected]080b77932014-08-04 01:22:46293 }
[email protected]080b77932014-08-04 01:22:46294
[email protected]0cceb922014-07-01 02:00:56295 if (result != OK) {
[email protected]3030374e32014-08-07 16:12:06296 std::string error_string = ErrorToString(result);
[email protected]72e65992013-07-30 17:16:14297 error_details_ = StringPrintf("Failed to verify certificate chain: %s",
[email protected]3030374e32014-08-07 16:12:06298 error_string.c_str());
[email protected]72e65992013-07-30 17:16:14299 DLOG(WARNING) << error_details_;
[email protected]2662ed562013-07-03 10:27:46300 }
301
302 // Exit DoLoop and return the result to the caller to VerifyProof.
303 DCHECK_EQ(STATE_NONE, next_state_);
304 return result;
305}
306
[email protected]5c78ce62014-03-13 19:48:01307bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
[email protected]3030374e32014-08-07 16:12:06308 const string& signature,
309 const string& cert) {
[email protected]2662ed562013-07-03 10:27:46310 StringPiece spki;
311 if (!asn1::ExtractSPKIFromDERCert(cert, &spki)) {
312 DLOG(WARNING) << "ExtractSPKIFromDERCert failed";
313 return false;
314 }
315
316 crypto::SignatureVerifier verifier;
317
318 size_t size_bits;
319 X509Certificate::PublicKeyType type;
rjshaded5ced072015-12-18 19:26:02320 X509Certificate::GetPublicKeyInfo(cert_->os_cert_handle(), &size_bits, &type);
[email protected]2662ed562013-07-03 10:27:46321 if (type == X509Certificate::kPublicKeyTypeRSA) {
322 crypto::SignatureVerifier::HashAlgorithm hash_alg =
323 crypto::SignatureVerifier::SHA256;
324 crypto::SignatureVerifier::HashAlgorithm mask_hash_alg = hash_alg;
325 unsigned int hash_len = 32; // 32 is the length of a SHA-256 hash.
[email protected]2662ed562013-07-03 10:27:46326
327 bool ok = verifier.VerifyInitRSAPSS(
[email protected]d5c9e4ba2013-09-14 05:25:58328 hash_alg, mask_hash_alg, hash_len,
[email protected]2662ed562013-07-03 10:27:46329 reinterpret_cast<const uint8*>(signature.data()), signature.size(),
330 reinterpret_cast<const uint8*>(spki.data()), spki.size());
331 if (!ok) {
332 DLOG(WARNING) << "VerifyInitRSAPSS failed";
333 return false;
334 }
335 } else if (type == X509Certificate::kPublicKeyTypeECDSA) {
336 // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT.
337 // RFC 5758:
338 // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
339 // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
340 // ...
341 // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or
342 // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field
343 // as an AlgorithmIdentifier, the encoding MUST omit the parameters
344 // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one
345 // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-
346 // SHA384, or ecdsa-with-SHA512.
347 // See also RFC 5480, Appendix A.
348 static const uint8 kECDSAWithSHA256AlgorithmID[] = {
rjshaded5ced072015-12-18 19:26:02349 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
[email protected]2662ed562013-07-03 10:27:46350 };
351
352 if (!verifier.VerifyInit(
353 kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID),
rjshaded5ced072015-12-18 19:26:02354 reinterpret_cast<const uint8*>(signature.data()), signature.size(),
355 reinterpret_cast<const uint8*>(spki.data()), spki.size())) {
[email protected]2662ed562013-07-03 10:27:46356 DLOG(WARNING) << "VerifyInit failed";
357 return false;
358 }
359 } else {
360 LOG(ERROR) << "Unsupported public key type " << type;
361 return false;
362 }
363
364 verifier.VerifyUpdate(reinterpret_cast<const uint8*>(kProofSignatureLabel),
365 sizeof(kProofSignatureLabel));
366 verifier.VerifyUpdate(reinterpret_cast<const uint8*>(signed_data.data()),
367 signed_data.size());
368
369 if (!verifier.VerifyFinal()) {
370 DLOG(WARNING) << "VerifyFinal failed";
371 return false;
372 }
373
[email protected]3e5fed12013-11-22 22:21:41374 DVLOG(1) << "VerifyFinal success";
[email protected]2662ed562013-07-03 10:27:46375 return true;
376}
377
[email protected]080b77932014-08-04 01:22:46378ProofVerifierChromium::ProofVerifierChromium(
379 CertVerifier* cert_verifier,
rsleevi9541f8632015-07-31 00:07:00380 CertPolicyEnforcer* cert_policy_enforcer,
rtenneti052774e2015-11-24 21:00:12381 TransportSecurityState* transport_security_state,
382 CTVerifier* cert_transparency_verifier)
[email protected]080b77932014-08-04 01:22:46383 : cert_verifier_(cert_verifier),
rsleevi9541f8632015-07-31 00:07:00384 cert_policy_enforcer_(cert_policy_enforcer),
rtenneti052774e2015-11-24 21:00:12385 transport_security_state_(transport_security_state),
386 cert_transparency_verifier_(cert_transparency_verifier) {}
[email protected]5c78ce62014-03-13 19:48:01387
388ProofVerifierChromium::~ProofVerifierChromium() {
389 STLDeleteElements(&active_jobs_);
390}
391
[email protected]730b35d72014-06-05 03:23:22392QuicAsyncStatus ProofVerifierChromium::VerifyProof(
[email protected]5c78ce62014-03-13 19:48:01393 const std::string& hostname,
394 const std::string& server_config,
395 const std::vector<std::string>& certs,
rjshadec86dbfa2015-11-12 20:16:25396 const std::string& cert_sct,
[email protected]5c78ce62014-03-13 19:48:01397 const std::string& signature,
[email protected]c817c672014-03-21 22:25:34398 const ProofVerifyContext* verify_context,
[email protected]5c78ce62014-03-13 19:48:01399 std::string* error_details,
[email protected]c817c672014-03-21 22:25:34400 scoped_ptr<ProofVerifyDetails>* verify_details,
[email protected]5c78ce62014-03-13 19:48:01401 ProofVerifierCallback* callback) {
[email protected]c817c672014-03-21 22:25:34402 if (!verify_context) {
403 *error_details = "Missing context";
[email protected]730b35d72014-06-05 03:23:22404 return QUIC_FAILURE;
[email protected]c817c672014-03-21 22:25:34405 }
406 const ProofVerifyContextChromium* chromium_context =
407 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
rtenneti052774e2015-11-24 21:00:12408 scoped_ptr<Job> job(
409 new Job(this, cert_verifier_, cert_policy_enforcer_,
410 transport_security_state_, cert_transparency_verifier_,
411 chromium_context->cert_verify_flags, chromium_context->net_log));
rtennetia75df622015-06-21 23:59:50412 QuicAsyncStatus status =
rjshadec86dbfa2015-11-12 20:16:25413 job->VerifyProof(hostname, server_config, certs, cert_sct, signature,
414 error_details, verify_details, callback);
[email protected]730b35d72014-06-05 03:23:22415 if (status == QUIC_PENDING) {
[email protected]5c78ce62014-03-13 19:48:01416 active_jobs_.insert(job.release());
417 }
418 return status;
419}
420
421void ProofVerifierChromium::OnJobComplete(Job* job) {
422 active_jobs_.erase(job);
423 delete job;
424}
425
[email protected]2662ed562013-07-03 10:27:46426} // namespace net