blob: d42dba8acc9b73b894580ad83d543158a8374b3d [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
rch675757b2016-07-29 16:40:115#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
[email protected]2662ed562013-07-03 10:27:466
dchengc7eeda422015-12-26 03:56:487#include <utility>
8
[email protected]2662ed562013-07-03 10:27:469#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/callback_helpers.h"
[email protected]2662ed562013-07-03 10:27:4612#include "base/logging.h"
asvitkinec3c93722015-06-17 14:48:3713#include "base/metrics/histogram_macros.h"
[email protected]5c78ce62014-03-13 19:48:0114#include "base/stl_util.h"
[email protected]2662ed562013-07-03 10:27:4615#include "base/strings/stringprintf.h"
16#include "crypto/signature_verifier.h"
estark1a66df72015-07-28 15:24:0017#include "net/base/host_port_pair.h"
[email protected]2662ed562013-07-03 10:27:4618#include "net/base/net_errors.h"
[email protected]2662ed562013-07-03 10:27:4619#include "net/cert/asn1_util.h"
20#include "net/cert/cert_status_flags.h"
21#include "net/cert/cert_verifier.h"
estark6f9b3d82016-01-12 21:37:0522#include "net/cert/ct_policy_enforcer.h"
estark723b5eeb2016-02-18 21:01:1223#include "net/cert/ct_policy_status.h"
rtenneti052774e2015-11-24 21:00:1224#include "net/cert/ct_verifier.h"
[email protected]2662ed562013-07-03 10:27:4625#include "net/cert/x509_util.h"
[email protected]080b77932014-08-04 01:22:4626#include "net/http/transport_security_state.h"
rchd4db7c152016-07-29 21:58:1227#include "net/quic/core/crypto/crypto_protocol.h"
[email protected]2662ed562013-07-03 10:27:4628#include "net/ssl/ssl_config_service.h"
29
30using base::StringPiece;
31using base::StringPrintf;
32using std::string;
33using std::vector;
34
35namespace net {
36
dadriandf302c42016-06-10 18:48:5937ProofVerifyDetailsChromium::ProofVerifyDetailsChromium()
38 : pkp_bypassed(false) {}
39
40ProofVerifyDetailsChromium::~ProofVerifyDetailsChromium() {}
41
42ProofVerifyDetailsChromium::ProofVerifyDetailsChromium(
43 const ProofVerifyDetailsChromium&) = default;
44
[email protected]92bc621d2014-07-29 21:42:1345ProofVerifyDetails* ProofVerifyDetailsChromium::Clone() const {
46 ProofVerifyDetailsChromium* other = new ProofVerifyDetailsChromium;
47 other->cert_verify_result = cert_verify_result;
rtenneti052774e2015-11-24 21:00:1248 other->ct_verify_result = ct_verify_result;
[email protected]92bc621d2014-07-29 21:42:1349 return other;
50}
51
[email protected]5c78ce62014-03-13 19:48:0152// A Job handles the verification of a single proof. It is owned by the
53// ProofVerifier. If the verification can not complete synchronously, it
54// will notify the ProofVerifier upon completion.
55class ProofVerifierChromium::Job {
56 public:
57 Job(ProofVerifierChromium* proof_verifier,
58 CertVerifier* cert_verifier,
estark6f9b3d82016-01-12 21:37:0559 CTPolicyEnforcer* ct_policy_enforcer,
[email protected]080b77932014-08-04 01:22:4660 TransportSecurityState* transport_security_state,
rtenneti052774e2015-11-24 21:00:1261 CTVerifier* cert_transparency_verifier,
rtennetia75df622015-06-21 23:59:5062 int cert_verify_flags,
[email protected]5c78ce62014-03-13 19:48:0163 const BoundNetLog& net_log);
rtennetidd4f1bd72015-12-23 19:17:5064 ~Job();
[email protected]5c78ce62014-03-13 19:48:0165
[email protected]05bfc260f2014-06-07 06:31:2566 // Starts the proof verification. If |QUIC_PENDING| is returned, then
67 // |callback| will be invoked asynchronously when the verification completes.
danakjad1777e2016-04-16 00:56:4268 QuicAsyncStatus VerifyProof(
69 const std::string& hostname,
70 const uint16_t port,
71 const std::string& server_config,
72 QuicVersion quic_version,
73 base::StringPiece chlo_hash,
74 const std::vector<std::string>& certs,
75 const std::string& cert_sct,
76 const std::string& signature,
77 std::string* error_details,
78 std::unique_ptr<ProofVerifyDetails>* verify_details,
ckrasic6567aa52016-07-08 09:24:3579 std::unique_ptr<ProofVerifierCallback> callback);
[email protected]5c78ce62014-03-13 19:48:0180
rtennetid073dd22016-08-04 01:58:3381 // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is
82 // returned, then |callback| will be invoked asynchronously when the
83 // verification completes.
84 QuicAsyncStatus VerifyCertChain(
85 const std::string& hostname,
86 const std::vector<std::string>& certs,
87 std::string* error_details,
88 std::unique_ptr<ProofVerifyDetails>* verify_details,
89 std::unique_ptr<ProofVerifierCallback> callback);
90
[email protected]5c78ce62014-03-13 19:48:0191 private:
92 enum State {
93 STATE_NONE,
94 STATE_VERIFY_CERT,
95 STATE_VERIFY_CERT_COMPLETE,
96 };
97
rtennetid073dd22016-08-04 01:58:3398 // Convert |certs| to |cert_|(X509Certificate). Returns true if successful.
99 bool GetX509Certificate(const vector<string>& certs,
100 std::string* error_details,
101 std::unique_ptr<ProofVerifyDetails>* verify_details);
102
103 // Start the cert verification.
104 QuicAsyncStatus VerifyCert(
105 const string& hostname,
106 const uint16_t port,
107 std::string* error_details,
108 std::unique_ptr<ProofVerifyDetails>* verify_details,
109 std::unique_ptr<ProofVerifierCallback> callback);
110
[email protected]5c78ce62014-03-13 19:48:01111 int DoLoop(int last_io_result);
112 void OnIOComplete(int result);
113 int DoVerifyCert(int result);
114 int DoVerifyCertComplete(int result);
115
116 bool VerifySignature(const std::string& signed_data,
rch28f6469d2016-03-13 21:13:08117 QuicVersion quic_version,
118 StringPiece chlo_hash,
[email protected]5c78ce62014-03-13 19:48:01119 const std::string& signature,
120 const std::string& cert);
121
122 // Proof verifier to notify when this jobs completes.
123 ProofVerifierChromium* proof_verifier_;
124
125 // The underlying verifier used for verifying certificates.
eroman7f9236a2015-05-11 21:23:43126 CertVerifier* verifier_;
danakjad1777e2016-04-16 00:56:42127 std::unique_ptr<CertVerifier::Request> cert_verifier_request_;
[email protected]5c78ce62014-03-13 19:48:01128
estark6f9b3d82016-01-12 21:37:05129 CTPolicyEnforcer* policy_enforcer_;
rsleevi9541f8632015-07-31 00:07:00130
[email protected]080b77932014-08-04 01:22:46131 TransportSecurityState* transport_security_state_;
132
rtenneti052774e2015-11-24 21:00:12133 CTVerifier* cert_transparency_verifier_;
134
[email protected]5c78ce62014-03-13 19:48:01135 // |hostname| specifies the hostname for which |certs| is a valid chain.
136 std::string hostname_;
elawrence954bb5472016-04-04 22:03:11137 // |port| specifies the target port for the connection.
138 uint16_t port_;
[email protected]5c78ce62014-03-13 19:48:01139
danakjad1777e2016-04-16 00:56:42140 std::unique_ptr<ProofVerifierCallback> callback_;
141 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_;
[email protected]5c78ce62014-03-13 19:48:01142 std::string error_details_;
143
144 // X509Certificate from a chain of DER encoded certificates.
145 scoped_refptr<X509Certificate> cert_;
146
rtennetia75df622015-06-21 23:59:50147 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is
148 // passed to CertVerifier::Verify.
149 int cert_verify_flags_;
150
rtennetid073dd22016-08-04 01:58:33151 // If set to true, enforces policy checking in DoVerifyCertComplete().
152 bool enforce_policy_checking_;
153
[email protected]5c78ce62014-03-13 19:48:01154 State next_state_;
155
rtennetidd4f1bd72015-12-23 19:17:50156 base::TimeTicks start_time_;
157
[email protected]5c78ce62014-03-13 19:48:01158 BoundNetLog net_log_;
159
160 DISALLOW_COPY_AND_ASSIGN(Job);
161};
162
[email protected]080b77932014-08-04 01:22:46163ProofVerifierChromium::Job::Job(
164 ProofVerifierChromium* proof_verifier,
165 CertVerifier* cert_verifier,
estark6f9b3d82016-01-12 21:37:05166 CTPolicyEnforcer* ct_policy_enforcer,
[email protected]080b77932014-08-04 01:22:46167 TransportSecurityState* transport_security_state,
rtenneti052774e2015-11-24 21:00:12168 CTVerifier* cert_transparency_verifier,
rtennetia75df622015-06-21 23:59:50169 int cert_verify_flags,
[email protected]080b77932014-08-04 01:22:46170 const BoundNetLog& net_log)
[email protected]5c78ce62014-03-13 19:48:01171 : proof_verifier_(proof_verifier),
eroman7f9236a2015-05-11 21:23:43172 verifier_(cert_verifier),
estark6f9b3d82016-01-12 21:37:05173 policy_enforcer_(ct_policy_enforcer),
[email protected]080b77932014-08-04 01:22:46174 transport_security_state_(transport_security_state),
rtenneti052774e2015-11-24 21:00:12175 cert_transparency_verifier_(cert_transparency_verifier),
rtennetia75df622015-06-21 23:59:50176 cert_verify_flags_(cert_verify_flags),
rtennetid073dd22016-08-04 01:58:33177 enforce_policy_checking_(true),
[email protected]5c78ce62014-03-13 19:48:01178 next_state_(STATE_NONE),
rtennetidd4f1bd72015-12-23 19:17:50179 start_time_(base::TimeTicks::Now()),
rsleevid6de8302016-06-21 01:33:20180 net_log_(net_log) {
rsleevibe81cd62016-06-24 01:38:59181 CHECK(proof_verifier_);
182 CHECK(verifier_);
183 CHECK(policy_enforcer_);
184 CHECK(transport_security_state_);
185 CHECK(cert_transparency_verifier_);
rsleevid6de8302016-06-21 01:33:20186}
[email protected]2662ed562013-07-03 10:27:46187
rtennetidd4f1bd72015-12-23 19:17:50188ProofVerifierChromium::Job::~Job() {
189 base::TimeTicks end_time = base::TimeTicks::Now();
190 UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime",
191 end_time - start_time_);
192 // |hostname_| will always be canonicalized to lowercase.
193 if (hostname_.compare("www.google.com") == 0) {
194 UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.google",
195 end_time - start_time_);
196 }
197}
198
[email protected]730b35d72014-06-05 03:23:22199QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
[email protected]72e65992013-07-30 17:16:14200 const string& hostname,
elawrence954bb5472016-04-04 22:03:11201 const uint16_t port,
[email protected]72e65992013-07-30 17:16:14202 const string& server_config,
rch28f6469d2016-03-13 21:13:08203 QuicVersion quic_version,
204 StringPiece chlo_hash,
[email protected]72e65992013-07-30 17:16:14205 const vector<string>& certs,
rjshadec86dbfa2015-11-12 20:16:25206 const std::string& cert_sct,
[email protected]72e65992013-07-30 17:16:14207 const string& signature,
208 std::string* error_details,
danakjad1777e2016-04-16 00:56:42209 std::unique_ptr<ProofVerifyDetails>* verify_details,
ckrasic6567aa52016-07-08 09:24:35210 std::unique_ptr<ProofVerifierCallback> callback) {
[email protected]2662ed562013-07-03 10:27:46211 DCHECK(error_details);
[email protected]c817c672014-03-21 22:25:34212 DCHECK(verify_details);
[email protected]72e65992013-07-30 17:16:14213 DCHECK(callback);
214
[email protected]2662ed562013-07-03 10:27:46215 error_details->clear();
216
[email protected]2662ed562013-07-03 10:27:46217 if (STATE_NONE != next_state_) {
218 *error_details = "Certificate is already set and VerifyProof has begun";
[email protected]5c78ce62014-03-13 19:48:01219 DLOG(DFATAL) << *error_details;
[email protected]730b35d72014-06-05 03:23:22220 return QUIC_FAILURE;
[email protected]2662ed562013-07-03 10:27:46221 }
222
[email protected]72e65992013-07-30 17:16:14223 verify_details_.reset(new ProofVerifyDetailsChromium);
224
rtennetid073dd22016-08-04 01:58:33225 // Converts |certs| to |cert_|.
226 if (!GetX509Certificate(certs, error_details, verify_details))
227 return QUIC_FAILURE;
228
229 if (!cert_sct.empty()) {
230 // Note that this is a completely synchronous operation: The CT Log Verifier
231 // gets all the data it needs for SCT verification and does not do any
232 // external communication.
233 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct,
234 &verify_details_->ct_verify_result,
235 net_log_);
236 }
237
238 // We call VerifySignature first to avoid copying of server_config and
239 // signature.
240 if (!signature.empty() &&
241 !VerifySignature(server_config, quic_version, chlo_hash, signature,
242 certs[0])) {
243 *error_details = "Failed to verify signature of server config";
244 DLOG(WARNING) << *error_details;
245 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
246 *verify_details = std::move(verify_details_);
247 return QUIC_FAILURE;
248 }
249
250 DCHECK(enforce_policy_checking_);
251 return VerifyCert(hostname, port, error_details, verify_details,
252 std::move(callback));
253}
254
255QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain(
256 const string& hostname,
257 const vector<string>& certs,
258 std::string* error_details,
259 std::unique_ptr<ProofVerifyDetails>* verify_details,
260 std::unique_ptr<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_FAILURE;
271 }
272
273 verify_details_.reset(new ProofVerifyDetailsChromium);
274
275 // Converts |certs| to |cert_|.
276 if (!GetX509Certificate(certs, error_details, verify_details))
277 return QUIC_FAILURE;
278
279 enforce_policy_checking_ = false;
280 // |port| is not needed because |enforce_policy_checking_| is false.
281 return VerifyCert(hostname, /*port=*/0, error_details, verify_details,
282 std::move(callback));
283}
284
285bool ProofVerifierChromium::Job::GetX509Certificate(
286 const vector<string>& certs,
287 std::string* error_details,
288 std::unique_ptr<ProofVerifyDetails>* verify_details) {
rtennetic14d86fd2016-07-10 16:33:34289 if (certs.empty()) {
290 *error_details = "Failed to create certificate chain. Certs are empty.";
291 DLOG(WARNING) << *error_details;
292 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
293 *verify_details = std::move(verify_details_);
rtennetid073dd22016-08-04 01:58:33294 return false;
rtennetic14d86fd2016-07-10 16:33:34295 }
296
297 // Convert certs to X509Certificate.
298 vector<StringPiece> cert_pieces(certs.size());
299 for (unsigned i = 0; i < certs.size(); i++) {
300 cert_pieces[i] = base::StringPiece(certs[i]);
301 }
302 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces);
303 if (!cert_.get()) {
304 *error_details = "Failed to create certificate chain";
305 DLOG(WARNING) << *error_details;
306 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
307 *verify_details = std::move(verify_details_);
rtennetid073dd22016-08-04 01:58:33308 return false;
rtennetic14d86fd2016-07-10 16:33:34309 }
rtennetid073dd22016-08-04 01:58:33310 return true;
311}
[email protected]2662ed562013-07-03 10:27:46312
rtennetid073dd22016-08-04 01:58:33313QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert(
314 const string& hostname,
315 const uint16_t port,
316 std::string* error_details,
317 std::unique_ptr<ProofVerifyDetails>* verify_details,
318 std::unique_ptr<ProofVerifierCallback> callback) {
[email protected]2662ed562013-07-03 10:27:46319 hostname_ = hostname;
elawrence954bb5472016-04-04 22:03:11320 port_ = port;
[email protected]2662ed562013-07-03 10:27:46321
322 next_state_ = STATE_VERIFY_CERT;
[email protected]72e65992013-07-30 17:16:14323 switch (DoLoop(OK)) {
324 case OK:
dchengc7eeda422015-12-26 03:56:48325 *verify_details = std::move(verify_details_);
[email protected]730b35d72014-06-05 03:23:22326 return QUIC_SUCCESS;
[email protected]72e65992013-07-30 17:16:14327 case ERR_IO_PENDING:
ckrasic6567aa52016-07-08 09:24:35328 callback_ = std::move(callback);
[email protected]730b35d72014-06-05 03:23:22329 return QUIC_PENDING;
[email protected]72e65992013-07-30 17:16:14330 default:
331 *error_details = error_details_;
dchengc7eeda422015-12-26 03:56:48332 *verify_details = std::move(verify_details_);
[email protected]730b35d72014-06-05 03:23:22333 return QUIC_FAILURE;
[email protected]72e65992013-07-30 17:16:14334 }
[email protected]2662ed562013-07-03 10:27:46335}
336
[email protected]5c78ce62014-03-13 19:48:01337int ProofVerifierChromium::Job::DoLoop(int last_result) {
[email protected]2662ed562013-07-03 10:27:46338 int rv = last_result;
339 do {
340 State state = next_state_;
341 next_state_ = STATE_NONE;
342 switch (state) {
343 case STATE_VERIFY_CERT:
344 DCHECK(rv == OK);
345 rv = DoVerifyCert(rv);
346 break;
347 case STATE_VERIFY_CERT_COMPLETE:
348 rv = DoVerifyCertComplete(rv);
349 break;
350 case STATE_NONE:
351 default:
352 rv = ERR_UNEXPECTED;
353 LOG(DFATAL) << "unexpected state " << state;
354 break;
355 }
356 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
357 return rv;
358}
359
[email protected]5c78ce62014-03-13 19:48:01360void ProofVerifierChromium::Job::OnIOComplete(int result) {
[email protected]2662ed562013-07-03 10:27:46361 int rv = DoLoop(result);
362 if (rv != ERR_IO_PENDING) {
danakjad1777e2016-04-16 00:56:42363 std::unique_ptr<ProofVerifierCallback> callback(std::move(callback_));
[email protected]5c78ce62014-03-13 19:48:01364 // Callback expects ProofVerifyDetails not ProofVerifyDetailsChromium.
danakjad1777e2016-04-16 00:56:42365 std::unique_ptr<ProofVerifyDetails> verify_details(
366 std::move(verify_details_));
[email protected]5c78ce62014-03-13 19:48:01367 callback->Run(rv == OK, error_details_, &verify_details);
368 // Will delete |this|.
369 proof_verifier_->OnJobComplete(this);
[email protected]2662ed562013-07-03 10:27:46370 }
371}
372
[email protected]5c78ce62014-03-13 19:48:01373int ProofVerifierChromium::Job::DoVerifyCert(int result) {
[email protected]2662ed562013-07-03 10:27:46374 next_state_ = STATE_VERIFY_CERT_COMPLETE;
375
rtennetia75df622015-06-21 23:59:50376 return verifier_->Verify(
rsleevi06bd78552016-06-08 22:34:46377 CertVerifier::RequestParams(cert_, hostname_, cert_verify_flags_,
378 std::string(), CertificateList()),
rtennetia75df622015-06-21 23:59:50379 SSLConfigService::GetCRLSet().get(), &verify_details_->cert_verify_result,
380 base::Bind(&ProofVerifierChromium::Job::OnIOComplete,
381 base::Unretained(this)),
382 &cert_verifier_request_, net_log_);
[email protected]2662ed562013-07-03 10:27:46383}
384
[email protected]5c78ce62014-03-13 19:48:01385int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
eroman7f9236a2015-05-11 21:23:43386 cert_verifier_request_.reset();
[email protected]2662ed562013-07-03 10:27:46387
[email protected]080b77932014-08-04 01:22:46388 const CertVerifyResult& cert_verify_result =
389 verify_details_->cert_verify_result;
[email protected]080b77932014-08-04 01:22:46390 const CertStatus cert_status = cert_verify_result.cert_status;
rsleevid6de8302016-06-21 01:33:20391 verify_details_->ct_verify_result.ct_policies_applied = result == OK;
estark723b5eeb2016-02-18 21:01:12392 verify_details_->ct_verify_result.ev_policy_compliance =
393 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY;
rsleevi4a6ca8c2016-06-24 03:05:22394
395 // If the connection was good, check HPKP and CT status simultaneously,
396 // but prefer to treat the HPKP error as more serious, if there was one.
rtennetid073dd22016-08-04 01:58:33397 if (enforce_policy_checking_ &&
398 (result == OK ||
rsleevi4a6ca8c2016-06-24 03:05:22399 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) {
eranm4bed0b572016-08-14 21:00:35400 SCTList verified_scts = ct::SCTsMatchingStatus(
401 verify_details_->ct_verify_result.scts, ct::SCT_STATUS_OK);
estark0fc8d0782016-02-25 20:41:20402 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) {
403 ct::EVPolicyCompliance ev_policy_compliance =
404 policy_enforcer_->DoesConformToCTEVPolicy(
405 cert_verify_result.verified_cert.get(),
eranm4bed0b572016-08-14 21:00:35406 SSLConfigService::GetEVCertsWhitelist().get(), verified_scts,
407 net_log_);
estark0fc8d0782016-02-25 20:41:20408 verify_details_->ct_verify_result.ev_policy_compliance =
409 ev_policy_compliance;
410 if (ev_policy_compliance !=
411 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY &&
412 ev_policy_compliance !=
413 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_WHITELIST &&
414 ev_policy_compliance !=
415 ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS) {
416 verify_details_->cert_verify_result.cert_status |=
417 CERT_STATUS_CT_COMPLIANCE_FAILED;
418 verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV;
419 }
rsleevi9541f8632015-07-31 00:07:00420 }
estark0fc8d0782016-02-25 20:41:20421
422 verify_details_->ct_verify_result.cert_policy_compliance =
423 policy_enforcer_->DoesConformToCertPolicy(
eranm4bed0b572016-08-14 21:00:35424 cert_verify_result.verified_cert.get(), verified_scts, net_log_);
rsleevi9541f8632015-07-31 00:07:00425
rsleevi4a6ca8c2016-06-24 03:05:22426 int ct_result = OK;
427 if (verify_details_->ct_verify_result.cert_policy_compliance !=
428 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS &&
429 transport_security_state_->ShouldRequireCT(
430 hostname_, cert_verify_result.verified_cert.get(),
431 cert_verify_result.public_key_hashes)) {
432 verify_details_->cert_verify_result.cert_status |=
433 CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
434 ct_result = ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
435 }
436
dadrian8f8946652016-06-21 23:48:31437 TransportSecurityState::PKPStatus pin_validity =
438 transport_security_state_->CheckPublicKeyPins(
439 HostPortPair(hostname_, port_),
440 cert_verify_result.is_issued_by_known_root,
441 cert_verify_result.public_key_hashes, cert_.get(),
442 cert_verify_result.verified_cert.get(),
443 TransportSecurityState::ENABLE_PIN_REPORTS,
444 &verify_details_->pinning_failure_log);
445 switch (pin_validity) {
446 case TransportSecurityState::PKPStatus::VIOLATED:
447 result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
448 verify_details_->cert_verify_result.cert_status |=
449 CERT_STATUS_PINNED_KEY_MISSING;
450 break;
451 case TransportSecurityState::PKPStatus::BYPASSED:
452 verify_details_->pkp_bypassed = true;
453 // Fall through.
454 case TransportSecurityState::PKPStatus::OK:
455 // Do nothing.
456 break;
rsleevi9545d342016-06-21 03:17:37457 }
rsleevi4a6ca8c2016-06-24 03:05:22458 if (result != ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN && ct_result != OK)
459 result = ct_result;
[email protected]080b77932014-08-04 01:22:46460 }
[email protected]080b77932014-08-04 01:22:46461
[email protected]0cceb922014-07-01 02:00:56462 if (result != OK) {
[email protected]3030374e32014-08-07 16:12:06463 std::string error_string = ErrorToString(result);
[email protected]72e65992013-07-30 17:16:14464 error_details_ = StringPrintf("Failed to verify certificate chain: %s",
[email protected]3030374e32014-08-07 16:12:06465 error_string.c_str());
[email protected]72e65992013-07-30 17:16:14466 DLOG(WARNING) << error_details_;
[email protected]2662ed562013-07-03 10:27:46467 }
468
469 // Exit DoLoop and return the result to the caller to VerifyProof.
470 DCHECK_EQ(STATE_NONE, next_state_);
471 return result;
472}
473
[email protected]5c78ce62014-03-13 19:48:01474bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
rch28f6469d2016-03-13 21:13:08475 QuicVersion quic_version,
476 StringPiece chlo_hash,
[email protected]3030374e32014-08-07 16:12:06477 const string& signature,
478 const string& cert) {
[email protected]2662ed562013-07-03 10:27:46479 StringPiece spki;
480 if (!asn1::ExtractSPKIFromDERCert(cert, &spki)) {
481 DLOG(WARNING) << "ExtractSPKIFromDERCert failed";
482 return false;
483 }
484
485 crypto::SignatureVerifier verifier;
486
487 size_t size_bits;
488 X509Certificate::PublicKeyType type;
rjshaded5ced072015-12-18 19:26:02489 X509Certificate::GetPublicKeyInfo(cert_->os_cert_handle(), &size_bits, &type);
[email protected]2662ed562013-07-03 10:27:46490 if (type == X509Certificate::kPublicKeyTypeRSA) {
491 crypto::SignatureVerifier::HashAlgorithm hash_alg =
492 crypto::SignatureVerifier::SHA256;
493 crypto::SignatureVerifier::HashAlgorithm mask_hash_alg = hash_alg;
494 unsigned int hash_len = 32; // 32 is the length of a SHA-256 hash.
[email protected]2662ed562013-07-03 10:27:46495
496 bool ok = verifier.VerifyInitRSAPSS(
[email protected]d5c9e4ba2013-09-14 05:25:58497 hash_alg, mask_hash_alg, hash_len,
Avi Drissman13fc8932015-12-20 04:40:46498 reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
499 reinterpret_cast<const uint8_t*>(spki.data()), spki.size());
[email protected]2662ed562013-07-03 10:27:46500 if (!ok) {
501 DLOG(WARNING) << "VerifyInitRSAPSS failed";
502 return false;
503 }
504 } else if (type == X509Certificate::kPublicKeyTypeECDSA) {
davidben9c97a362016-03-03 16:18:26505 if (!verifier.VerifyInit(crypto::SignatureVerifier::ECDSA_SHA256,
506 reinterpret_cast<const uint8_t*>(signature.data()),
507 signature.size(),
508 reinterpret_cast<const uint8_t*>(spki.data()),
509 spki.size())) {
[email protected]2662ed562013-07-03 10:27:46510 DLOG(WARNING) << "VerifyInit failed";
511 return false;
512 }
513 } else {
514 LOG(ERROR) << "Unsupported public key type " << type;
515 return false;
516 }
517
rch28f6469d2016-03-13 21:13:08518 if (quic_version <= QUIC_VERSION_30) {
519 verifier.VerifyUpdate(
520 reinterpret_cast<const uint8_t*>(kProofSignatureLabelOld),
521 sizeof(kProofSignatureLabelOld));
522 } else {
523 verifier.VerifyUpdate(
524 reinterpret_cast<const uint8_t*>(kProofSignatureLabel),
525 sizeof(kProofSignatureLabel));
526 uint32_t len = chlo_hash.length();
527 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(&len), sizeof(len));
528 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(chlo_hash.data()),
529 len);
530 }
531
Avi Drissman13fc8932015-12-20 04:40:46532 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(signed_data.data()),
[email protected]2662ed562013-07-03 10:27:46533 signed_data.size());
534
535 if (!verifier.VerifyFinal()) {
536 DLOG(WARNING) << "VerifyFinal failed";
537 return false;
538 }
539
[email protected]3e5fed12013-11-22 22:21:41540 DVLOG(1) << "VerifyFinal success";
[email protected]2662ed562013-07-03 10:27:46541 return true;
542}
543
[email protected]080b77932014-08-04 01:22:46544ProofVerifierChromium::ProofVerifierChromium(
545 CertVerifier* cert_verifier,
estark6f9b3d82016-01-12 21:37:05546 CTPolicyEnforcer* ct_policy_enforcer,
rtenneti052774e2015-11-24 21:00:12547 TransportSecurityState* transport_security_state,
548 CTVerifier* cert_transparency_verifier)
[email protected]080b77932014-08-04 01:22:46549 : cert_verifier_(cert_verifier),
estark6f9b3d82016-01-12 21:37:05550 ct_policy_enforcer_(ct_policy_enforcer),
rtenneti052774e2015-11-24 21:00:12551 transport_security_state_(transport_security_state),
rsleevid6de8302016-06-21 01:33:20552 cert_transparency_verifier_(cert_transparency_verifier) {
553 DCHECK(cert_verifier_);
554 DCHECK(ct_policy_enforcer_);
555 DCHECK(transport_security_state_);
556 DCHECK(cert_transparency_verifier_);
557}
[email protected]5c78ce62014-03-13 19:48:01558
559ProofVerifierChromium::~ProofVerifierChromium() {
skyostilb8f60ca2016-08-12 12:34:43560 base::STLDeleteElements(&active_jobs_);
[email protected]5c78ce62014-03-13 19:48:01561}
562
[email protected]730b35d72014-06-05 03:23:22563QuicAsyncStatus ProofVerifierChromium::VerifyProof(
[email protected]5c78ce62014-03-13 19:48:01564 const std::string& hostname,
elawrence954bb5472016-04-04 22:03:11565 const uint16_t port,
[email protected]5c78ce62014-03-13 19:48:01566 const std::string& server_config,
rch28f6469d2016-03-13 21:13:08567 QuicVersion quic_version,
568 base::StringPiece chlo_hash,
[email protected]5c78ce62014-03-13 19:48:01569 const std::vector<std::string>& certs,
rjshadec86dbfa2015-11-12 20:16:25570 const std::string& cert_sct,
[email protected]5c78ce62014-03-13 19:48:01571 const std::string& signature,
[email protected]c817c672014-03-21 22:25:34572 const ProofVerifyContext* verify_context,
[email protected]5c78ce62014-03-13 19:48:01573 std::string* error_details,
danakjad1777e2016-04-16 00:56:42574 std::unique_ptr<ProofVerifyDetails>* verify_details,
ckrasic6567aa52016-07-08 09:24:35575 std::unique_ptr<ProofVerifierCallback> callback) {
[email protected]c817c672014-03-21 22:25:34576 if (!verify_context) {
577 *error_details = "Missing context";
[email protected]730b35d72014-06-05 03:23:22578 return QUIC_FAILURE;
[email protected]c817c672014-03-21 22:25:34579 }
580 const ProofVerifyContextChromium* chromium_context =
581 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
danakjad1777e2016-04-16 00:56:42582 std::unique_ptr<Job> job(
estark6f9b3d82016-01-12 21:37:05583 new Job(this, cert_verifier_, ct_policy_enforcer_,
rtenneti052774e2015-11-24 21:00:12584 transport_security_state_, cert_transparency_verifier_,
585 chromium_context->cert_verify_flags, chromium_context->net_log));
rch28f6469d2016-03-13 21:13:08586 QuicAsyncStatus status = job->VerifyProof(
elawrence954bb5472016-04-04 22:03:11587 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct,
ckrasic6567aa52016-07-08 09:24:35588 signature, error_details, verify_details, std::move(callback));
rtennetid073dd22016-08-04 01:58:33589 if (status == QUIC_PENDING)
[email protected]5c78ce62014-03-13 19:48:01590 active_jobs_.insert(job.release());
rtennetid073dd22016-08-04 01:58:33591 return status;
592}
593
594QuicAsyncStatus ProofVerifierChromium::VerifyCertChain(
595 const std::string& hostname,
596 const std::vector<std::string>& certs,
597 const ProofVerifyContext* verify_context,
598 std::string* error_details,
599 std::unique_ptr<ProofVerifyDetails>* verify_details,
600 std::unique_ptr<ProofVerifierCallback> callback) {
601 if (!verify_context) {
602 *error_details = "Missing context";
603 return QUIC_FAILURE;
[email protected]5c78ce62014-03-13 19:48:01604 }
rtennetid073dd22016-08-04 01:58:33605 const ProofVerifyContextChromium* chromium_context =
606 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
607 std::unique_ptr<Job> job(
608 new Job(this, cert_verifier_, ct_policy_enforcer_,
609 transport_security_state_, cert_transparency_verifier_,
610 chromium_context->cert_verify_flags, chromium_context->net_log));
611 QuicAsyncStatus status = job->VerifyCertChain(
612 hostname, certs, error_details, verify_details, std::move(callback));
613 if (status == QUIC_PENDING)
614 active_jobs_.insert(job.release());
[email protected]5c78ce62014-03-13 19:48:01615 return status;
616}
617
618void ProofVerifierChromium::OnJobComplete(Job* job) {
619 active_jobs_.erase(job);
620 delete job;
621}
622
[email protected]2662ed562013-07-03 10:27:46623} // namespace net