| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 const std::string& server_config, | 71 const std::string& server_config, |
| 72 QuicVersion quic_version, | 72 QuicVersion quic_version, |
| 73 base::StringPiece chlo_hash, | 73 base::StringPiece chlo_hash, |
| 74 const std::vector<std::string>& certs, | 74 const std::vector<std::string>& certs, |
| 75 const std::string& cert_sct, | 75 const std::string& cert_sct, |
| 76 const std::string& signature, | 76 const std::string& signature, |
| 77 std::string* error_details, | 77 std::string* error_details, |
| 78 std::unique_ptr<ProofVerifyDetails>* verify_details, | 78 std::unique_ptr<ProofVerifyDetails>* verify_details, |
| 79 ProofVerifierCallback* callback); | 79 ProofVerifierCallback* callback); |
| 80 | 80 |
| 81 // 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 ProofVerifierCallback* callback); | |
| 90 | |
| 91 private: | 81 private: |
| 92 enum State { | 82 enum State { |
| 93 STATE_NONE, | 83 STATE_NONE, |
| 94 STATE_VERIFY_CERT, | 84 STATE_VERIFY_CERT, |
| 95 STATE_VERIFY_CERT_COMPLETE, | 85 STATE_VERIFY_CERT_COMPLETE, |
| 96 }; | 86 }; |
| 97 | 87 |
| 98 // 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 ProofVerifierCallback* callback); | |
| 110 | |
| 111 int DoLoop(int last_io_result); | 88 int DoLoop(int last_io_result); |
| 112 void OnIOComplete(int result); | 89 void OnIOComplete(int result); |
| 113 int DoVerifyCert(int result); | 90 int DoVerifyCert(int result); |
| 114 int DoVerifyCertComplete(int result); | 91 int DoVerifyCertComplete(int result); |
| 115 | 92 |
| 116 bool VerifySignature(const std::string& signed_data, | 93 bool VerifySignature(const std::string& signed_data, |
| 117 QuicVersion quic_version, | 94 QuicVersion quic_version, |
| 118 StringPiece chlo_hash, | 95 StringPiece chlo_hash, |
| 119 const std::string& signature, | 96 const std::string& signature, |
| 120 const std::string& cert); | 97 const std::string& cert); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 141 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; | 118 std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; |
| 142 std::string error_details_; | 119 std::string error_details_; |
| 143 | 120 |
| 144 // X509Certificate from a chain of DER encoded certificates. | 121 // X509Certificate from a chain of DER encoded certificates. |
| 145 scoped_refptr<X509Certificate> cert_; | 122 scoped_refptr<X509Certificate> cert_; |
| 146 | 123 |
| 147 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is | 124 // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is |
| 148 // passed to CertVerifier::Verify. | 125 // passed to CertVerifier::Verify. |
| 149 int cert_verify_flags_; | 126 int cert_verify_flags_; |
| 150 | 127 |
| 151 // If set to true, enforces policy checking in DoVerifyCertComplete(). | |
| 152 bool enforce_policy_checking_; | |
| 153 | |
| 154 State next_state_; | 128 State next_state_; |
| 155 | 129 |
| 156 base::TimeTicks start_time_; | 130 base::TimeTicks start_time_; |
| 157 | 131 |
| 158 BoundNetLog net_log_; | 132 BoundNetLog net_log_; |
| 159 | 133 |
| 160 DISALLOW_COPY_AND_ASSIGN(Job); | 134 DISALLOW_COPY_AND_ASSIGN(Job); |
| 161 }; | 135 }; |
| 162 | 136 |
| 163 ProofVerifierChromium::Job::Job( | 137 ProofVerifierChromium::Job::Job( |
| 164 ProofVerifierChromium* proof_verifier, | 138 ProofVerifierChromium* proof_verifier, |
| 165 CertVerifier* cert_verifier, | 139 CertVerifier* cert_verifier, |
| 166 CTPolicyEnforcer* ct_policy_enforcer, | 140 CTPolicyEnforcer* ct_policy_enforcer, |
| 167 TransportSecurityState* transport_security_state, | 141 TransportSecurityState* transport_security_state, |
| 168 CTVerifier* cert_transparency_verifier, | 142 CTVerifier* cert_transparency_verifier, |
| 169 int cert_verify_flags, | 143 int cert_verify_flags, |
| 170 const BoundNetLog& net_log) | 144 const BoundNetLog& net_log) |
| 171 : proof_verifier_(proof_verifier), | 145 : proof_verifier_(proof_verifier), |
| 172 verifier_(cert_verifier), | 146 verifier_(cert_verifier), |
| 173 policy_enforcer_(ct_policy_enforcer), | 147 policy_enforcer_(ct_policy_enforcer), |
| 174 transport_security_state_(transport_security_state), | 148 transport_security_state_(transport_security_state), |
| 175 cert_transparency_verifier_(cert_transparency_verifier), | 149 cert_transparency_verifier_(cert_transparency_verifier), |
| 176 cert_verify_flags_(cert_verify_flags), | 150 cert_verify_flags_(cert_verify_flags), |
| 177 enforce_policy_checking_(true), | |
| 178 next_state_(STATE_NONE), | 151 next_state_(STATE_NONE), |
| 179 start_time_(base::TimeTicks::Now()), | 152 start_time_(base::TimeTicks::Now()), |
| 180 net_log_(net_log) { | 153 net_log_(net_log) { |
| 181 CHECK(proof_verifier_); | 154 CHECK(proof_verifier_); |
| 182 CHECK(verifier_); | 155 CHECK(verifier_); |
| 183 CHECK(policy_enforcer_); | 156 CHECK(policy_enforcer_); |
| 184 CHECK(transport_security_state_); | 157 CHECK(transport_security_state_); |
| 185 CHECK(cert_transparency_verifier_); | 158 CHECK(cert_transparency_verifier_); |
| 186 } | 159 } |
| 187 | 160 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 215 error_details->clear(); | 188 error_details->clear(); |
| 216 | 189 |
| 217 if (STATE_NONE != next_state_) { | 190 if (STATE_NONE != next_state_) { |
| 218 *error_details = "Certificate is already set and VerifyProof has begun"; | 191 *error_details = "Certificate is already set and VerifyProof has begun"; |
| 219 DLOG(DFATAL) << *error_details; | 192 DLOG(DFATAL) << *error_details; |
| 220 return QUIC_FAILURE; | 193 return QUIC_FAILURE; |
| 221 } | 194 } |
| 222 | 195 |
| 223 verify_details_.reset(new ProofVerifyDetailsChromium); | 196 verify_details_.reset(new ProofVerifyDetailsChromium); |
| 224 | 197 |
| 225 // Converts |certs| to |cert_|. | 198 if (certs.empty()) { |
| 226 if (!GetX509Certificate(certs, error_details, verify_details)) | 199 *error_details = "Failed to create certificate chain. Certs are empty."; |
| 200 DLOG(WARNING) << *error_details; |
| 201 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| 202 *verify_details = std::move(verify_details_); |
| 227 return QUIC_FAILURE; | 203 return QUIC_FAILURE; |
| 204 } |
| 205 |
| 206 // Convert certs to X509Certificate. |
| 207 vector<StringPiece> cert_pieces(certs.size()); |
| 208 for (unsigned i = 0; i < certs.size(); i++) { |
| 209 cert_pieces[i] = base::StringPiece(certs[i]); |
| 210 } |
| 211 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); |
| 212 if (!cert_.get()) { |
| 213 *error_details = "Failed to create certificate chain"; |
| 214 DLOG(WARNING) << *error_details; |
| 215 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| 216 *verify_details = std::move(verify_details_); |
| 217 return QUIC_FAILURE; |
| 218 } |
| 228 | 219 |
| 229 if (!cert_sct.empty()) { | 220 if (!cert_sct.empty()) { |
| 230 // Note that this is a completely synchronous operation: The CT Log Verifier | 221 // 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 | 222 // gets all the data it needs for SCT verification and does not do any |
| 232 // external communication. | 223 // external communication. |
| 233 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, | 224 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, |
| 234 &verify_details_->ct_verify_result, | 225 &verify_details_->ct_verify_result, |
| 235 net_log_); | 226 net_log_); |
| 236 } | 227 } |
| 237 | 228 |
| 238 // We call VerifySignature first to avoid copying of server_config and | 229 // We call VerifySignature first to avoid copying of server_config and |
| 239 // signature. | 230 // signature. |
| 240 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, | 231 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, |
| 241 certs[0])) { | 232 certs[0])) { |
| 242 *error_details = "Failed to verify signature of server config"; | 233 *error_details = "Failed to verify signature of server config"; |
| 243 DLOG(WARNING) << *error_details; | 234 DLOG(WARNING) << *error_details; |
| 244 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | 235 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| 245 *verify_details = std::move(verify_details_); | 236 *verify_details = std::move(verify_details_); |
| 246 return QUIC_FAILURE; | 237 return QUIC_FAILURE; |
| 247 } | 238 } |
| 248 | 239 |
| 249 DCHECK(enforce_policy_checking_); | |
| 250 return VerifyCert(hostname, port, error_details, verify_details, callback); | |
| 251 } | |
| 252 | |
| 253 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( | |
| 254 const string& hostname, | |
| 255 const vector<string>& certs, | |
| 256 std::string* error_details, | |
| 257 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
| 258 ProofVerifierCallback* callback) { | |
| 259 DCHECK(error_details); | |
| 260 DCHECK(verify_details); | |
| 261 DCHECK(callback); | |
| 262 | |
| 263 error_details->clear(); | |
| 264 | |
| 265 if (STATE_NONE != next_state_) { | |
| 266 *error_details = "Certificate is already set and VerifyCertChain has begun"; | |
| 267 DLOG(DFATAL) << *error_details; | |
| 268 return QUIC_FAILURE; | |
| 269 } | |
| 270 | |
| 271 verify_details_.reset(new ProofVerifyDetailsChromium); | |
| 272 | |
| 273 // Converts |certs| to |cert_|. | |
| 274 if (!GetX509Certificate(certs, error_details, verify_details)) | |
| 275 return QUIC_FAILURE; | |
| 276 | |
| 277 enforce_policy_checking_ = false; | |
| 278 // |port| is not needed because |enforce_policy_checking_| is false. | |
| 279 return VerifyCert(hostname, /*port=*/0, error_details, verify_details, | |
| 280 callback); | |
| 281 } | |
| 282 | |
| 283 bool ProofVerifierChromium::Job::GetX509Certificate( | |
| 284 const vector<string>& certs, | |
| 285 std::string* error_details, | |
| 286 std::unique_ptr<ProofVerifyDetails>* verify_details) { | |
| 287 if (certs.empty()) { | |
| 288 *error_details = "Failed to create certificate chain. Certs are empty."; | |
| 289 DLOG(WARNING) << *error_details; | |
| 290 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
| 291 *verify_details = std::move(verify_details_); | |
| 292 return false; | |
| 293 } | |
| 294 | |
| 295 // Convert certs to X509Certificate. | |
| 296 vector<StringPiece> cert_pieces(certs.size()); | |
| 297 for (unsigned i = 0; i < certs.size(); i++) { | |
| 298 cert_pieces[i] = base::StringPiece(certs[i]); | |
| 299 } | |
| 300 cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); | |
| 301 if (!cert_.get()) { | |
| 302 *error_details = "Failed to create certificate chain"; | |
| 303 DLOG(WARNING) << *error_details; | |
| 304 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | |
| 305 *verify_details = std::move(verify_details_); | |
| 306 return false; | |
| 307 } | |
| 308 return true; | |
| 309 } | |
| 310 | |
| 311 QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( | |
| 312 const string& hostname, | |
| 313 const uint16_t port, | |
| 314 std::string* error_details, | |
| 315 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
| 316 ProofVerifierCallback* callback) { | |
| 317 hostname_ = hostname; | 240 hostname_ = hostname; |
| 318 port_ = port; | 241 port_ = port; |
| 319 | 242 |
| 320 next_state_ = STATE_VERIFY_CERT; | 243 next_state_ = STATE_VERIFY_CERT; |
| 321 switch (DoLoop(OK)) { | 244 switch (DoLoop(OK)) { |
| 322 case OK: | 245 case OK: |
| 323 *verify_details = std::move(verify_details_); | 246 *verify_details = std::move(verify_details_); |
| 324 return QUIC_SUCCESS; | 247 return QUIC_SUCCESS; |
| 325 case ERR_IO_PENDING: | 248 case ERR_IO_PENDING: |
| 326 callback_.reset(callback); | 249 callback_.reset(callback); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 | 308 |
| 386 const CertVerifyResult& cert_verify_result = | 309 const CertVerifyResult& cert_verify_result = |
| 387 verify_details_->cert_verify_result; | 310 verify_details_->cert_verify_result; |
| 388 const CertStatus cert_status = cert_verify_result.cert_status; | 311 const CertStatus cert_status = cert_verify_result.cert_status; |
| 389 verify_details_->ct_verify_result.ct_policies_applied = result == OK; | 312 verify_details_->ct_verify_result.ct_policies_applied = result == OK; |
| 390 verify_details_->ct_verify_result.ev_policy_compliance = | 313 verify_details_->ct_verify_result.ev_policy_compliance = |
| 391 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; | 314 ct::EVPolicyCompliance::EV_POLICY_DOES_NOT_APPLY; |
| 392 | 315 |
| 393 // If the connection was good, check HPKP and CT status simultaneously, | 316 // If the connection was good, check HPKP and CT status simultaneously, |
| 394 // but prefer to treat the HPKP error as more serious, if there was one. | 317 // but prefer to treat the HPKP error as more serious, if there was one. |
| 395 if (enforce_policy_checking_ && | 318 if ((result == OK || |
| 396 (result == OK || | |
| 397 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { | 319 (IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { |
| 398 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { | 320 if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { |
| 399 ct::EVPolicyCompliance ev_policy_compliance = | 321 ct::EVPolicyCompliance ev_policy_compliance = |
| 400 policy_enforcer_->DoesConformToCTEVPolicy( | 322 policy_enforcer_->DoesConformToCTEVPolicy( |
| 401 cert_verify_result.verified_cert.get(), | 323 cert_verify_result.verified_cert.get(), |
| 402 SSLConfigService::GetEVCertsWhitelist().get(), | 324 SSLConfigService::GetEVCertsWhitelist().get(), |
| 403 verify_details_->ct_verify_result.verified_scts, net_log_); | 325 verify_details_->ct_verify_result.verified_scts, net_log_); |
| 404 verify_details_->ct_verify_result.ev_policy_compliance = | 326 verify_details_->ct_verify_result.ev_policy_compliance = |
| 405 ev_policy_compliance; | 327 ev_policy_compliance; |
| 406 if (ev_policy_compliance != | 328 if (ev_policy_compliance != |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 } | 498 } |
| 577 const ProofVerifyContextChromium* chromium_context = | 499 const ProofVerifyContextChromium* chromium_context = |
| 578 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | 500 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); |
| 579 std::unique_ptr<Job> job( | 501 std::unique_ptr<Job> job( |
| 580 new Job(this, cert_verifier_, ct_policy_enforcer_, | 502 new Job(this, cert_verifier_, ct_policy_enforcer_, |
| 581 transport_security_state_, cert_transparency_verifier_, | 503 transport_security_state_, cert_transparency_verifier_, |
| 582 chromium_context->cert_verify_flags, chromium_context->net_log)); | 504 chromium_context->cert_verify_flags, chromium_context->net_log)); |
| 583 QuicAsyncStatus status = job->VerifyProof( | 505 QuicAsyncStatus status = job->VerifyProof( |
| 584 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, | 506 hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, |
| 585 signature, error_details, verify_details, callback); | 507 signature, error_details, verify_details, callback); |
| 586 if (status == QUIC_PENDING) | 508 if (status == QUIC_PENDING) { |
| 587 active_jobs_.insert(job.release()); | 509 active_jobs_.insert(job.release()); |
| 510 } |
| 588 return status; | 511 return status; |
| 589 } | 512 } |
| 590 | 513 |
| 591 QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( | |
| 592 const std::string& hostname, | |
| 593 const std::vector<std::string>& certs, | |
| 594 const ProofVerifyContext* verify_context, | |
| 595 std::string* error_details, | |
| 596 std::unique_ptr<ProofVerifyDetails>* verify_details, | |
| 597 ProofVerifierCallback* callback) { | |
| 598 if (!verify_context) { | |
| 599 *error_details = "Missing context"; | |
| 600 return QUIC_FAILURE; | |
| 601 } | |
| 602 const ProofVerifyContextChromium* chromium_context = | |
| 603 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | |
| 604 std::unique_ptr<Job> job( | |
| 605 new Job(this, cert_verifier_, ct_policy_enforcer_, | |
| 606 transport_security_state_, cert_transparency_verifier_, | |
| 607 chromium_context->cert_verify_flags, chromium_context->net_log)); | |
| 608 QuicAsyncStatus status = job->VerifyCertChain(hostname, certs, error_details, | |
| 609 verify_details, callback); | |
| 610 if (status == QUIC_PENDING) | |
| 611 active_jobs_.insert(job.release()); | |
| 612 return status; | |
| 613 } | |
| 614 | |
| 615 void ProofVerifierChromium::OnJobComplete(Job* job) { | 514 void ProofVerifierChromium::OnJobComplete(Job* job) { |
| 616 active_jobs_.erase(job); | 515 active_jobs_.erase(job); |
| 617 delete job; | 516 delete job; |
| 618 } | 517 } |
| 619 | 518 |
| 620 } // namespace net | 519 } // namespace net |
| OLD | NEW |