| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 TransportSecurityState* transport_security_state, | 57 TransportSecurityState* transport_security_state, |
| 58 CTVerifier* cert_transparency_verifier, | 58 CTVerifier* cert_transparency_verifier, |
| 59 int cert_verify_flags, | 59 int cert_verify_flags, |
| 60 const BoundNetLog& net_log); | 60 const BoundNetLog& net_log); |
| 61 ~Job(); | 61 ~Job(); |
| 62 | 62 |
| 63 // Starts the proof verification. If |QUIC_PENDING| is returned, then | 63 // Starts the proof verification. If |QUIC_PENDING| is returned, then |
| 64 // |callback| will be invoked asynchronously when the verification completes. | 64 // |callback| will be invoked asynchronously when the verification completes. |
| 65 QuicAsyncStatus VerifyProof(const std::string& hostname, | 65 QuicAsyncStatus VerifyProof(const std::string& hostname, |
| 66 const std::string& server_config, | 66 const std::string& server_config, |
| 67 QuicVersion quic_version, |
| 68 base::StringPiece chlo_hash, |
| 67 const std::vector<std::string>& certs, | 69 const std::vector<std::string>& certs, |
| 68 const std::string& cert_sct, | 70 const std::string& cert_sct, |
| 69 const std::string& signature, | 71 const std::string& signature, |
| 70 std::string* error_details, | 72 std::string* error_details, |
| 71 scoped_ptr<ProofVerifyDetails>* verify_details, | 73 scoped_ptr<ProofVerifyDetails>* verify_details, |
| 72 ProofVerifierCallback* callback); | 74 ProofVerifierCallback* callback); |
| 73 | 75 |
| 74 private: | 76 private: |
| 75 enum State { | 77 enum State { |
| 76 STATE_NONE, | 78 STATE_NONE, |
| 77 STATE_VERIFY_CERT, | 79 STATE_VERIFY_CERT, |
| 78 STATE_VERIFY_CERT_COMPLETE, | 80 STATE_VERIFY_CERT_COMPLETE, |
| 79 }; | 81 }; |
| 80 | 82 |
| 81 int DoLoop(int last_io_result); | 83 int DoLoop(int last_io_result); |
| 82 void OnIOComplete(int result); | 84 void OnIOComplete(int result); |
| 83 int DoVerifyCert(int result); | 85 int DoVerifyCert(int result); |
| 84 int DoVerifyCertComplete(int result); | 86 int DoVerifyCertComplete(int result); |
| 85 | 87 |
| 86 bool VerifySignature(const std::string& signed_data, | 88 bool VerifySignature(const std::string& signed_data, |
| 89 QuicVersion quic_version, |
| 90 StringPiece chlo_hash, |
| 87 const std::string& signature, | 91 const std::string& signature, |
| 88 const std::string& cert); | 92 const std::string& cert); |
| 89 | 93 |
| 90 // Proof verifier to notify when this jobs completes. | 94 // Proof verifier to notify when this jobs completes. |
| 91 ProofVerifierChromium* proof_verifier_; | 95 ProofVerifierChromium* proof_verifier_; |
| 92 | 96 |
| 93 // The underlying verifier used for verifying certificates. | 97 // The underlying verifier used for verifying certificates. |
| 94 CertVerifier* verifier_; | 98 CertVerifier* verifier_; |
| 95 scoped_ptr<CertVerifier::Request> cert_verifier_request_; | 99 scoped_ptr<CertVerifier::Request> cert_verifier_request_; |
| 96 | 100 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 // |hostname_| will always be canonicalized to lowercase. | 152 // |hostname_| will always be canonicalized to lowercase. |
| 149 if (hostname_.compare("www.google.com") == 0) { | 153 if (hostname_.compare("www.google.com") == 0) { |
| 150 UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.google", | 154 UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.google", |
| 151 end_time - start_time_); | 155 end_time - start_time_); |
| 152 } | 156 } |
| 153 } | 157 } |
| 154 | 158 |
| 155 QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( | 159 QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( |
| 156 const string& hostname, | 160 const string& hostname, |
| 157 const string& server_config, | 161 const string& server_config, |
| 162 QuicVersion quic_version, |
| 163 StringPiece chlo_hash, |
| 158 const vector<string>& certs, | 164 const vector<string>& certs, |
| 159 const std::string& cert_sct, | 165 const std::string& cert_sct, |
| 160 const string& signature, | 166 const string& signature, |
| 161 std::string* error_details, | 167 std::string* error_details, |
| 162 scoped_ptr<ProofVerifyDetails>* verify_details, | 168 scoped_ptr<ProofVerifyDetails>* verify_details, |
| 163 ProofVerifierCallback* callback) { | 169 ProofVerifierCallback* callback) { |
| 164 DCHECK(error_details); | 170 DCHECK(error_details); |
| 165 DCHECK(verify_details); | 171 DCHECK(verify_details); |
| 166 DCHECK(callback); | 172 DCHECK(callback); |
| 167 | 173 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 // Note that this is a completely synchronous operation: The CT Log Verifier | 207 // Note that this is a completely synchronous operation: The CT Log Verifier |
| 202 // gets all the data it needs for SCT verification and does not do any | 208 // gets all the data it needs for SCT verification and does not do any |
| 203 // external communication. | 209 // external communication. |
| 204 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, | 210 cert_transparency_verifier_->Verify(cert_.get(), std::string(), cert_sct, |
| 205 &verify_details_->ct_verify_result, | 211 &verify_details_->ct_verify_result, |
| 206 net_log_); | 212 net_log_); |
| 207 } | 213 } |
| 208 | 214 |
| 209 // We call VerifySignature first to avoid copying of server_config and | 215 // We call VerifySignature first to avoid copying of server_config and |
| 210 // signature. | 216 // signature. |
| 211 if (!VerifySignature(server_config, signature, certs[0])) { | 217 if (!VerifySignature(server_config, quic_version, chlo_hash, signature, |
| 218 certs[0])) { |
| 212 *error_details = "Failed to verify signature of server config"; | 219 *error_details = "Failed to verify signature of server config"; |
| 213 DLOG(WARNING) << *error_details; | 220 DLOG(WARNING) << *error_details; |
| 214 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; | 221 verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
| 215 *verify_details = std::move(verify_details_); | 222 *verify_details = std::move(verify_details_); |
| 216 return QUIC_FAILURE; | 223 return QUIC_FAILURE; |
| 217 } | 224 } |
| 218 | 225 |
| 219 hostname_ = hostname; | 226 hostname_ = hostname; |
| 220 | 227 |
| 221 next_state_ = STATE_VERIFY_CERT; | 228 next_state_ = STATE_VERIFY_CERT; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 error_string.c_str()); | 343 error_string.c_str()); |
| 337 DLOG(WARNING) << error_details_; | 344 DLOG(WARNING) << error_details_; |
| 338 } | 345 } |
| 339 | 346 |
| 340 // Exit DoLoop and return the result to the caller to VerifyProof. | 347 // Exit DoLoop and return the result to the caller to VerifyProof. |
| 341 DCHECK_EQ(STATE_NONE, next_state_); | 348 DCHECK_EQ(STATE_NONE, next_state_); |
| 342 return result; | 349 return result; |
| 343 } | 350 } |
| 344 | 351 |
| 345 bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data, | 352 bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data, |
| 353 QuicVersion quic_version, |
| 354 StringPiece chlo_hash, |
| 346 const string& signature, | 355 const string& signature, |
| 347 const string& cert) { | 356 const string& cert) { |
| 348 StringPiece spki; | 357 StringPiece spki; |
| 349 if (!asn1::ExtractSPKIFromDERCert(cert, &spki)) { | 358 if (!asn1::ExtractSPKIFromDERCert(cert, &spki)) { |
| 350 DLOG(WARNING) << "ExtractSPKIFromDERCert failed"; | 359 DLOG(WARNING) << "ExtractSPKIFromDERCert failed"; |
| 351 return false; | 360 return false; |
| 352 } | 361 } |
| 353 | 362 |
| 354 crypto::SignatureVerifier verifier; | 363 crypto::SignatureVerifier verifier; |
| 355 | 364 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 signature.size(), reinterpret_cast<const uint8_t*>(spki.data()), | 402 signature.size(), reinterpret_cast<const uint8_t*>(spki.data()), |
| 394 spki.size())) { | 403 spki.size())) { |
| 395 DLOG(WARNING) << "VerifyInit failed"; | 404 DLOG(WARNING) << "VerifyInit failed"; |
| 396 return false; | 405 return false; |
| 397 } | 406 } |
| 398 } else { | 407 } else { |
| 399 LOG(ERROR) << "Unsupported public key type " << type; | 408 LOG(ERROR) << "Unsupported public key type " << type; |
| 400 return false; | 409 return false; |
| 401 } | 410 } |
| 402 | 411 |
| 403 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(kProofSignatureLabel), | 412 if (quic_version <= QUIC_VERSION_30) { |
| 404 sizeof(kProofSignatureLabel)); | 413 verifier.VerifyUpdate( |
| 414 reinterpret_cast<const uint8_t*>(kProofSignatureLabelOld), |
| 415 sizeof(kProofSignatureLabelOld)); |
| 416 } else { |
| 417 verifier.VerifyUpdate( |
| 418 reinterpret_cast<const uint8_t*>(kProofSignatureLabel), |
| 419 sizeof(kProofSignatureLabel)); |
| 420 uint32_t len = chlo_hash.length(); |
| 421 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(&len), sizeof(len)); |
| 422 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(chlo_hash.data()), |
| 423 sizeof(chlo_hash.data())); |
| 424 } |
| 425 |
| 405 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(signed_data.data()), | 426 verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(signed_data.data()), |
| 406 signed_data.size()); | 427 signed_data.size()); |
| 407 | 428 |
| 408 if (!verifier.VerifyFinal()) { | 429 if (!verifier.VerifyFinal()) { |
| 409 DLOG(WARNING) << "VerifyFinal failed"; | 430 DLOG(WARNING) << "VerifyFinal failed"; |
| 410 return false; | 431 return false; |
| 411 } | 432 } |
| 412 | 433 |
| 413 DVLOG(1) << "VerifyFinal success"; | 434 DVLOG(1) << "VerifyFinal success"; |
| 414 return true; | 435 return true; |
| 415 } | 436 } |
| 416 | 437 |
| 417 ProofVerifierChromium::ProofVerifierChromium( | 438 ProofVerifierChromium::ProofVerifierChromium( |
| 418 CertVerifier* cert_verifier, | 439 CertVerifier* cert_verifier, |
| 419 CTPolicyEnforcer* ct_policy_enforcer, | 440 CTPolicyEnforcer* ct_policy_enforcer, |
| 420 TransportSecurityState* transport_security_state, | 441 TransportSecurityState* transport_security_state, |
| 421 CTVerifier* cert_transparency_verifier) | 442 CTVerifier* cert_transparency_verifier) |
| 422 : cert_verifier_(cert_verifier), | 443 : cert_verifier_(cert_verifier), |
| 423 ct_policy_enforcer_(ct_policy_enforcer), | 444 ct_policy_enforcer_(ct_policy_enforcer), |
| 424 transport_security_state_(transport_security_state), | 445 transport_security_state_(transport_security_state), |
| 425 cert_transparency_verifier_(cert_transparency_verifier) {} | 446 cert_transparency_verifier_(cert_transparency_verifier) {} |
| 426 | 447 |
| 427 ProofVerifierChromium::~ProofVerifierChromium() { | 448 ProofVerifierChromium::~ProofVerifierChromium() { |
| 428 STLDeleteElements(&active_jobs_); | 449 STLDeleteElements(&active_jobs_); |
| 429 } | 450 } |
| 430 | 451 |
| 431 QuicAsyncStatus ProofVerifierChromium::VerifyProof( | 452 QuicAsyncStatus ProofVerifierChromium::VerifyProof( |
| 432 const std::string& hostname, | 453 const std::string& hostname, |
| 433 const std::string& server_config, | 454 const std::string& server_config, |
| 455 QuicVersion quic_version, |
| 456 base::StringPiece chlo_hash, |
| 434 const std::vector<std::string>& certs, | 457 const std::vector<std::string>& certs, |
| 435 const std::string& cert_sct, | 458 const std::string& cert_sct, |
| 436 const std::string& signature, | 459 const std::string& signature, |
| 437 const ProofVerifyContext* verify_context, | 460 const ProofVerifyContext* verify_context, |
| 438 std::string* error_details, | 461 std::string* error_details, |
| 439 scoped_ptr<ProofVerifyDetails>* verify_details, | 462 scoped_ptr<ProofVerifyDetails>* verify_details, |
| 440 ProofVerifierCallback* callback) { | 463 ProofVerifierCallback* callback) { |
| 441 if (!verify_context) { | 464 if (!verify_context) { |
| 442 *error_details = "Missing context"; | 465 *error_details = "Missing context"; |
| 443 return QUIC_FAILURE; | 466 return QUIC_FAILURE; |
| 444 } | 467 } |
| 445 const ProofVerifyContextChromium* chromium_context = | 468 const ProofVerifyContextChromium* chromium_context = |
| 446 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); | 469 reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); |
| 447 scoped_ptr<Job> job( | 470 scoped_ptr<Job> job( |
| 448 new Job(this, cert_verifier_, ct_policy_enforcer_, | 471 new Job(this, cert_verifier_, ct_policy_enforcer_, |
| 449 transport_security_state_, cert_transparency_verifier_, | 472 transport_security_state_, cert_transparency_verifier_, |
| 450 chromium_context->cert_verify_flags, chromium_context->net_log)); | 473 chromium_context->cert_verify_flags, chromium_context->net_log)); |
| 451 QuicAsyncStatus status = | 474 QuicAsyncStatus status = job->VerifyProof( |
| 452 job->VerifyProof(hostname, server_config, certs, cert_sct, signature, | 475 hostname, server_config, quic_version, chlo_hash, certs, cert_sct, |
| 453 error_details, verify_details, callback); | 476 signature, error_details, verify_details, callback); |
| 454 if (status == QUIC_PENDING) { | 477 if (status == QUIC_PENDING) { |
| 455 active_jobs_.insert(job.release()); | 478 active_jobs_.insert(job.release()); |
| 456 } | 479 } |
| 457 return status; | 480 return status; |
| 458 } | 481 } |
| 459 | 482 |
| 460 void ProofVerifierChromium::OnJobComplete(Job* job) { | 483 void ProofVerifierChromium::OnJobComplete(Job* job) { |
| 461 active_jobs_.erase(job); | 484 active_jobs_.erase(job); |
| 462 delete job; | 485 delete job; |
| 463 } | 486 } |
| 464 | 487 |
| 465 } // namespace net | 488 } // namespace net |
| OLD | NEW |