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