Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/crypto/proof_verifier_chromium.h" | 5 #include "net/quic/crypto/proof_verifier_chromium.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/profiler/scoped_tracker.h" | 13 #include "base/profiler/scoped_tracker.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "crypto/signature_verifier.h" | 16 #include "crypto/signature_verifier.h" |
| 17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #include "net/cert/asn1_util.h" | 18 #include "net/cert/asn1_util.h" |
| 19 #include "net/cert/cert_policy_enforcer.h" | |
| 19 #include "net/cert/cert_status_flags.h" | 20 #include "net/cert/cert_status_flags.h" |
| 20 #include "net/cert/cert_verifier.h" | 21 #include "net/cert/cert_verifier.h" |
| 21 #include "net/cert/cert_verify_result.h" | 22 #include "net/cert/cert_verify_result.h" |
| 23 #include "net/cert/ct_verify_result.h" | |
| 22 #include "net/cert/x509_certificate.h" | 24 #include "net/cert/x509_certificate.h" |
| 23 #include "net/cert/x509_util.h" | 25 #include "net/cert/x509_util.h" |
| 24 #include "net/http/transport_security_state.h" | 26 #include "net/http/transport_security_state.h" |
| 25 #include "net/log/net_log.h" | 27 #include "net/log/net_log.h" |
| 26 #include "net/quic/crypto/crypto_protocol.h" | 28 #include "net/quic/crypto/crypto_protocol.h" |
| 27 #include "net/ssl/ssl_config_service.h" | 29 #include "net/ssl/ssl_config_service.h" |
| 28 | 30 |
| 29 using base::StringPiece; | 31 using base::StringPiece; |
| 30 using base::StringPrintf; | 32 using base::StringPrintf; |
| 31 using std::string; | 33 using std::string; |
| 32 using std::vector; | 34 using std::vector; |
| 33 | 35 |
| 34 namespace net { | 36 namespace net { |
| 35 | 37 |
| 36 ProofVerifyDetails* ProofVerifyDetailsChromium::Clone() const { | 38 ProofVerifyDetails* ProofVerifyDetailsChromium::Clone() const { |
| 37 ProofVerifyDetailsChromium* other = new ProofVerifyDetailsChromium; | 39 ProofVerifyDetailsChromium* other = new ProofVerifyDetailsChromium; |
| 38 other->cert_verify_result = cert_verify_result; | 40 other->cert_verify_result = cert_verify_result; |
| 39 return other; | 41 return other; |
| 40 } | 42 } |
| 41 | 43 |
| 42 // A Job handles the verification of a single proof. It is owned by the | 44 // A Job handles the verification of a single proof. It is owned by the |
| 43 // ProofVerifier. If the verification can not complete synchronously, it | 45 // ProofVerifier. If the verification can not complete synchronously, it |
| 44 // will notify the ProofVerifier upon completion. | 46 // will notify the ProofVerifier upon completion. |
| 45 class ProofVerifierChromium::Job { | 47 class ProofVerifierChromium::Job { |
| 46 public: | 48 public: |
| 47 Job(ProofVerifierChromium* proof_verifier, | 49 Job(ProofVerifierChromium* proof_verifier, |
| 48 CertVerifier* cert_verifier, | 50 CertVerifier* cert_verifier, |
| 51 CertPolicyEnforcer* cert_policy_enforcer, | |
| 49 TransportSecurityState* transport_security_state, | 52 TransportSecurityState* transport_security_state, |
| 50 int cert_verify_flags, | 53 int cert_verify_flags, |
| 51 const BoundNetLog& net_log); | 54 const BoundNetLog& net_log); |
| 52 | 55 |
| 53 // Starts the proof verification. If |QUIC_PENDING| is returned, then | 56 // Starts the proof verification. If |QUIC_PENDING| is returned, then |
| 54 // |callback| will be invoked asynchronously when the verification completes. | 57 // |callback| will be invoked asynchronously when the verification completes. |
| 55 QuicAsyncStatus VerifyProof(const std::string& hostname, | 58 QuicAsyncStatus VerifyProof(const std::string& hostname, |
| 56 const std::string& server_config, | 59 const std::string& server_config, |
| 57 const std::vector<std::string>& certs, | 60 const std::vector<std::string>& certs, |
| 58 const std::string& signature, | 61 const std::string& signature, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 76 const std::string& signature, | 79 const std::string& signature, |
| 77 const std::string& cert); | 80 const std::string& cert); |
| 78 | 81 |
| 79 // Proof verifier to notify when this jobs completes. | 82 // Proof verifier to notify when this jobs completes. |
| 80 ProofVerifierChromium* proof_verifier_; | 83 ProofVerifierChromium* proof_verifier_; |
| 81 | 84 |
| 82 // The underlying verifier used for verifying certificates. | 85 // The underlying verifier used for verifying certificates. |
| 83 CertVerifier* verifier_; | 86 CertVerifier* verifier_; |
| 84 scoped_ptr<CertVerifier::Request> cert_verifier_request_; | 87 scoped_ptr<CertVerifier::Request> cert_verifier_request_; |
| 85 | 88 |
| 89 CertPolicyEnforcer* policy_enforcer_; | |
| 90 | |
| 86 TransportSecurityState* transport_security_state_; | 91 TransportSecurityState* transport_security_state_; |
| 87 | 92 |
| 88 // |hostname| specifies the hostname for which |certs| is a valid chain. | 93 // |hostname| specifies the hostname for which |certs| is a valid chain. |
| 89 std::string hostname_; | 94 std::string hostname_; |
| 90 | 95 |
| 91 scoped_ptr<ProofVerifierCallback> callback_; | 96 scoped_ptr<ProofVerifierCallback> callback_; |
| 92 scoped_ptr<ProofVerifyDetailsChromium> verify_details_; | 97 scoped_ptr<ProofVerifyDetailsChromium> verify_details_; |
| 93 std::string error_details_; | 98 std::string error_details_; |
| 94 | 99 |
| 95 // X509Certificate from a chain of DER encoded certificates. | 100 // X509Certificate from a chain of DER encoded certificates. |
| 96 scoped_refptr<X509Certificate> cert_; | 101 scoped_refptr<X509Certificate> cert_; |
| 97 | 102 |
| 98 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is | 103 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is |
| 99 // passed to CertVerifier::Verify. | 104 // passed to CertVerifier::Verify. |
| 100 int cert_verify_flags_; | 105 int cert_verify_flags_; |
| 101 | 106 |
| 102 State next_state_; | 107 State next_state_; |
| 103 | 108 |
| 104 BoundNetLog net_log_; | 109 BoundNetLog net_log_; |
| 105 | 110 |
| 106 DISALLOW_COPY_AND_ASSIGN(Job); | 111 DISALLOW_COPY_AND_ASSIGN(Job); |
| 107 }; | 112 }; |
| 108 | 113 |
| 109 ProofVerifierChromium::Job::Job( | 114 ProofVerifierChromium::Job::Job( |
| 110 ProofVerifierChromium* proof_verifier, | 115 ProofVerifierChromium* proof_verifier, |
| 111 CertVerifier* cert_verifier, | 116 CertVerifier* cert_verifier, |
| 117 CertPolicyEnforcer* cert_policy_enforcer, | |
| 112 TransportSecurityState* transport_security_state, | 118 TransportSecurityState* transport_security_state, |
| 113 int cert_verify_flags, | 119 int cert_verify_flags, |
| 114 const BoundNetLog& net_log) | 120 const BoundNetLog& net_log) |
| 115 : proof_verifier_(proof_verifier), | 121 : proof_verifier_(proof_verifier), |
| 116 verifier_(cert_verifier), | 122 verifier_(cert_verifier), |
| 123 policy_enforcer_(cert_policy_enforcer), | |
| 117 transport_security_state_(transport_security_state), | 124 transport_security_state_(transport_security_state), |
| 118 cert_verify_flags_(cert_verify_flags), | 125 cert_verify_flags_(cert_verify_flags), |
| 119 next_state_(STATE_NONE), | 126 next_state_(STATE_NONE), |
| 120 net_log_(net_log) { | 127 net_log_(net_log) { |
| 121 } | 128 } |
| 122 | 129 |
| 123 QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( | 130 QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( |
| 124 const string& hostname, | 131 const string& hostname, |
| 125 const string& server_config, | 132 const string& server_config, |
| 126 const vector<string>& certs, | 133 const vector<string>& certs, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 base::Unretained(this)), | 243 base::Unretained(this)), |
| 237 &cert_verifier_request_, net_log_); | 244 &cert_verifier_request_, net_log_); |
| 238 } | 245 } |
| 239 | 246 |
| 240 int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { | 247 int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { |
| 241 cert_verifier_request_.reset(); | 248 cert_verifier_request_.reset(); |
| 242 | 249 |
| 243 const CertVerifyResult& cert_verify_result = | 250 const CertVerifyResult& cert_verify_result = |
| 244 verify_details_->cert_verify_result; | 251 verify_details_->cert_verify_result; |
| 245 const CertStatus cert_status = cert_verify_result.cert_status; | 252 const CertStatus cert_status = cert_verify_result.cert_status; |
| 253 | |
| 254 if (result == OK && policy_enforcer_ && | |
| 255 (cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { | |
| 256 // QUIC does not support OCSP stapling or the CT TLS extension; as a | |
| 257 // result, CT can never be verified, thus the result is always empty. | |
| 258 ct::CTVerifyResult empty_ct_result; | |
| 259 if (!policy_enforcer_->DoesConformToCTEVPolicy( | |
| 260 cert_verify_result.verified_cert.get(), | |
| 261 SSLConfigService::GetEVCertsWhitelist().get(), empty_ct_result, | |
| 262 net_log_)) { | |
| 263 verify_details_->cert_verify_result.cert_status &= ~CERT_STATUS_IS_EV; | |
| 264 } | |
| 265 } | |
| 266 | |
| 246 if (transport_security_state_ && | 267 if (transport_security_state_ && |
| 247 (result == OK || | 268 (result == OK || |
| 248 (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) && | 269 (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) && |
| 249 !transport_security_state_->CheckPublicKeyPins( | 270 !transport_security_state_->CheckPublicKeyPins( |
| 250 hostname_, | 271 hostname_, |
| 251 cert_verify_result.is_issued_by_known_root, | 272 cert_verify_result.is_issued_by_known_root, |
| 252 cert_verify_result.public_key_hashes, | 273 cert_verify_result.public_key_hashes, |
| 253 &verify_details_->pinning_failure_log)) { | 274 &verify_details_->pinning_failure_log)) { |
| 254 result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN; | 275 result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN; |
| 255 } | 276 } |
| 256 | 277 |
| 257 scoped_refptr<ct::EVCertsWhitelist> ev_whitelist = | |
| 258 SSLConfigService::GetEVCertsWhitelist(); | |
| 259 if ((cert_status & CERT_STATUS_IS_EV) && ev_whitelist.get() && | |
| 260 ev_whitelist->IsValid()) { | |
| 261 const SHA256HashValue fingerprint( | |
| 262 X509Certificate::CalculateFingerprint256(cert_->os_cert_handle())); | |
| 263 | |
| 264 UMA_HISTOGRAM_BOOLEAN( | |
| 265 "Net.SSL_EVCertificateInWhitelist", | |
| 266 ev_whitelist->ContainsCertificateHash( | |
| 267 std::string(reinterpret_cast<const char*>(fingerprint.data), 8))); | |
|
Ryan Hamilton
2015/07/06 17:36:48
You would know better than I would, of course, but
Ryan Sleevi
2015/07/06 17:38:51
This code should not have been histogramming here
Ryan Hamilton
2015/07/06 17:39:43
Ah, that makes sense. Thanks!
| |
| 268 } | |
| 269 | |
| 270 if (result != OK) { | 278 if (result != OK) { |
| 271 std::string error_string = ErrorToString(result); | 279 std::string error_string = ErrorToString(result); |
| 272 error_details_ = StringPrintf("Failed to verify certificate chain: %s", | 280 error_details_ = StringPrintf("Failed to verify certificate chain: %s", |
| 273 error_string.c_str()); | 281 error_string.c_str()); |
| 274 DLOG(WARNING) << error_details_; | 282 DLOG(WARNING) << error_details_; |
| 275 } | 283 } |
| 276 | 284 |
| 277 // Exit DoLoop and return the result to the caller to VerifyProof. | 285 // Exit DoLoop and return the result to the caller to VerifyProof. |
| 278 DCHECK_EQ(STATE_NONE, next_state_); | 286 DCHECK_EQ(STATE_NONE, next_state_); |
| 279 return result; | 287 return result; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 DLOG(WARNING) << "VerifyFinal failed"; | 363 DLOG(WARNING) << "VerifyFinal failed"; |
| 356 return false; | 364 return false; |
| 357 } | 365 } |
| 358 | 366 |
| 359 DVLOG(1) << "VerifyFinal success"; | 367 DVLOG(1) << "VerifyFinal success"; |
| 360 return true; | 368 return true; |
| 361 } | 369 } |
| 362 | 370 |
| 363 ProofVerifierChromium::ProofVerifierChromium( | 371 ProofVerifierChromium::ProofVerifierChromium( |
| 364 CertVerifier* cert_verifier, | 372 CertVerifier* cert_verifier, |
| 373 CertPolicyEnforcer* cert_policy_enforcer, | |
| 365 TransportSecurityState* transport_security_state) | 374 TransportSecurityState* transport_security_state) |
| 366 : cert_verifier_(cert_verifier), | 375 : cert_verifier_(cert_verifier), |
| 376 cert_policy_enforcer_(cert_policy_enforcer), | |
| 367 transport_security_state_(transport_security_state) { | 377 transport_security_state_(transport_security_state) { |
| 368 } | 378 } |
| 369 | 379 |
| 370 ProofVerifierChromium::~ProofVerifierChromium() { | 380 ProofVerifierChromium::~ProofVerifierChromium() { |
| 371 STLDeleteElements(&active_jobs_); | 381 STLDeleteElements(&active_jobs_); |
| 372 } | 382 } |
| 373 | 383 |
| 374 QuicAsyncStatus ProofVerifierChromium::VerifyProof( | 384 QuicAsyncStatus ProofVerifierChromium::VerifyProof( |
| 375 const std::string& hostname, | 385 const std::string& hostname, |
| 376 const std::string& server_config, | 386 const std::string& server_config, |
| 377 const std::vector<std::string>& certs, | 387 const std::vector<std::string>& certs, |
| 378 const std::string& signature, | 388 const std::string& signature, |
| 379 const ProofVerifyContext* verify_context, | 389 const ProofVerifyContext* verify_context, |
| 380 std::string* error_details, | 390 std::string* error_details, |
| 381 scoped_ptr<ProofVerifyDetails>* verify_details, | 391 scoped_ptr<ProofVerifyDetails>* verify_details, |
| 382 ProofVerifierCallback* callback) { | 392 ProofVerifierCallback* callback) { |
| 383 if (!verify_context) { | 393 if (!verify_context) { |
| 384 *error_details = "Missing context"; | 394 *error_details = "Missing context"; |
| 385 return QUIC_FAILURE; | 395 return QUIC_FAILURE; |
| 386 } | 396 } |
| 387 const ProofVerifyContextChromium* chromium_context = | 397 const ProofVerifyContextChromium* chromium_context = |
| 388 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | 398 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); |
| 389 scoped_ptr<Job> job(new Job(this, cert_verifier_, transport_security_state_, | 399 scoped_ptr<Job> job(new Job( |
| 390 chromium_context->cert_verify_flags, | 400 this, cert_verifier_, cert_policy_enforcer_, transport_security_state_, |
| 391 chromium_context->net_log)); | 401 chromium_context->cert_verify_flags, chromium_context->net_log)); |
| 392 QuicAsyncStatus status = | 402 QuicAsyncStatus status = |
| 393 job->VerifyProof(hostname, server_config, certs, signature, error_details, | 403 job->VerifyProof(hostname, server_config, certs, signature, error_details, |
| 394 verify_details, callback); | 404 verify_details, callback); |
| 395 if (status == QUIC_PENDING) { | 405 if (status == QUIC_PENDING) { |
| 396 active_jobs_.insert(job.release()); | 406 active_jobs_.insert(job.release()); |
| 397 } | 407 } |
| 398 return status; | 408 return status; |
| 399 } | 409 } |
| 400 | 410 |
| 401 void ProofVerifierChromium::OnJobComplete(Job* job) { | 411 void ProofVerifierChromium::OnJobComplete(Job* job) { |
| 402 active_jobs_.erase(job); | 412 active_jobs_.erase(job); |
| 403 delete job; | 413 delete job; |
| 404 } | 414 } |
| 405 | 415 |
| 406 } // namespace net | 416 } // namespace net |
| OLD | NEW |