diff options
Diffstat (limited to 'chromium/net/quic/crypto/proof_verifier_chromium.cc')
-rw-r--r-- | chromium/net/quic/crypto/proof_verifier_chromium.cc | 167 |
1 files changed, 131 insertions, 36 deletions
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.cc b/chromium/net/quic/crypto/proof_verifier_chromium.cc index 68ad25ca12d..4b118da198c 100644 --- a/chromium/net/quic/crypto/proof_verifier_chromium.cc +++ b/chromium/net/quic/crypto/proof_verifier_chromium.cc @@ -9,6 +9,7 @@ #include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/logging.h" +#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "crypto/signature_verifier.h" #include "net/base/net_errors.h" @@ -30,37 +31,91 @@ using std::vector; namespace net { -ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier, - const BoundNetLog& net_log) - : cert_verifier_(cert_verifier), - next_state_(STATE_NONE), - net_log_(net_log) { -} +// A Job handles the verification of a single proof. It is owned by the +// ProofVerifier. If the verification can not complete synchronously, it +// will notify the ProofVerifier upon completion. +class ProofVerifierChromium::Job { + public: + Job(ProofVerifierChromium* proof_verifier, + CertVerifier* cert_verifier, + const BoundNetLog& net_log); -ProofVerifierChromium::~ProofVerifierChromium() { - verifier_.reset(); + // Starts the proof verification. If |QUIC_PENDING| is returned, then + // |callback| will be invoked asynchronously when the verification completes. + QuicAsyncStatus VerifyProof(const std::string& hostname, + const std::string& server_config, + const std::vector<std::string>& certs, + const std::string& signature, + std::string* error_details, + scoped_ptr<ProofVerifyDetails>* verify_details, + ProofVerifierCallback* callback); + + private: + enum State { + STATE_NONE, + STATE_VERIFY_CERT, + STATE_VERIFY_CERT_COMPLETE, + }; + + int DoLoop(int last_io_result); + void OnIOComplete(int result); + int DoVerifyCert(int result); + int DoVerifyCertComplete(int result); + + bool VerifySignature(const std::string& signed_data, + const std::string& signature, + const std::string& cert); + + // Proof verifier to notify when this jobs completes. + ProofVerifierChromium* proof_verifier_; + + // The underlying verifier used for verifying certificates. + scoped_ptr<SingleRequestCertVerifier> verifier_; + + // |hostname| specifies the hostname for which |certs| is a valid chain. + std::string hostname_; + + scoped_ptr<ProofVerifierCallback> callback_; + scoped_ptr<ProofVerifyDetailsChromium> verify_details_; + std::string error_details_; + + // X509Certificate from a chain of DER encoded certificates. + scoped_refptr<X509Certificate> cert_; + + State next_state_; + + BoundNetLog net_log_; + + DISALLOW_COPY_AND_ASSIGN(Job); +}; + +ProofVerifierChromium::Job::Job(ProofVerifierChromium* proof_verifier, + CertVerifier* cert_verifier, + const BoundNetLog& net_log) + : proof_verifier_(proof_verifier), + verifier_(new SingleRequestCertVerifier(cert_verifier)), + next_state_(STATE_NONE), + net_log_(net_log) { } -ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof( +QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( const string& hostname, const string& server_config, const vector<string>& certs, const string& signature, std::string* error_details, - scoped_ptr<ProofVerifyDetails>* details, + scoped_ptr<ProofVerifyDetails>* verify_details, ProofVerifierCallback* callback) { DCHECK(error_details); - DCHECK(details); + DCHECK(verify_details); DCHECK(callback); - callback_.reset(callback); error_details->clear(); - DCHECK_EQ(STATE_NONE, next_state_); if (STATE_NONE != next_state_) { *error_details = "Certificate is already set and VerifyProof has begun"; - DLOG(WARNING) << *error_details; - return FAILURE; + DLOG(DFATAL) << *error_details; + return QUIC_FAILURE; } verify_details_.reset(new ProofVerifyDetailsChromium); @@ -69,8 +124,8 @@ ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof( *error_details = "Failed to create certificate chain. Certs are empty."; DLOG(WARNING) << *error_details; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; - details->reset(verify_details_.release()); - return FAILURE; + verify_details->reset(verify_details_.release()); + return QUIC_FAILURE; } // Convert certs to X509Certificate. @@ -83,8 +138,8 @@ ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof( *error_details = "Failed to create certificate chain"; DLOG(WARNING) << *error_details; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; - details->reset(verify_details_.release()); - return FAILURE; + verify_details->reset(verify_details_.release()); + return QUIC_FAILURE; } // We call VerifySignature first to avoid copying of server_config and @@ -93,8 +148,8 @@ ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof( *error_details = "Failed to verify signature of server config"; DLOG(WARNING) << *error_details; verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; - details->reset(verify_details_.release()); - return FAILURE; + verify_details->reset(verify_details_.release()); + return QUIC_FAILURE; } hostname_ = hostname; @@ -102,18 +157,19 @@ ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof( next_state_ = STATE_VERIFY_CERT; switch (DoLoop(OK)) { case OK: - details->reset(verify_details_.release()); - return SUCCESS; + verify_details->reset(verify_details_.release()); + return QUIC_SUCCESS; case ERR_IO_PENDING: - return PENDING; + callback_.reset(callback); + return QUIC_PENDING; default: *error_details = error_details_; - details->reset(verify_details_.release()); - return FAILURE; + verify_details->reset(verify_details_.release()); + return QUIC_FAILURE; } } -int ProofVerifierChromium::DoLoop(int last_result) { +int ProofVerifierChromium::Job::DoLoop(int last_result) { int rv = last_result; do { State state = next_state_; @@ -136,32 +192,34 @@ int ProofVerifierChromium::DoLoop(int last_result) { return rv; } -void ProofVerifierChromium::OnIOComplete(int result) { +void ProofVerifierChromium::Job::OnIOComplete(int result) { int rv = DoLoop(result); if (rv != ERR_IO_PENDING) { - scoped_ptr<ProofVerifyDetails> scoped_details(verify_details_.release()); - callback_->Run(rv == OK, error_details_, &scoped_details); - callback_.reset(); + scoped_ptr<ProofVerifierCallback> callback(callback_.release()); + // Callback expects ProofVerifyDetails not ProofVerifyDetailsChromium. + scoped_ptr<ProofVerifyDetails> verify_details(verify_details_.release()); + callback->Run(rv == OK, error_details_, &verify_details); + // Will delete |this|. + proof_verifier_->OnJobComplete(this); } } -int ProofVerifierChromium::DoVerifyCert(int result) { +int ProofVerifierChromium::Job::DoVerifyCert(int result) { next_state_ = STATE_VERIFY_CERT_COMPLETE; int flags = 0; - verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); return verifier_->Verify( cert_.get(), hostname_, flags, SSLConfigService::GetCRLSet().get(), &verify_details_->cert_verify_result, - base::Bind(&ProofVerifierChromium::OnIOComplete, + base::Bind(&ProofVerifierChromium::Job::OnIOComplete, base::Unretained(this)), net_log_); } -int ProofVerifierChromium::DoVerifyCertComplete(int result) { +int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { verifier_.reset(); if (result <= ERR_FAILED) { @@ -176,7 +234,7 @@ int ProofVerifierChromium::DoVerifyCertComplete(int result) { return result; } -bool ProofVerifierChromium::VerifySignature(const string& signed_data, +bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data, const string& signature, const string& cert) { StringPiece spki; @@ -252,4 +310,41 @@ bool ProofVerifierChromium::VerifySignature(const string& signed_data, return true; } +ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier) + : cert_verifier_(cert_verifier) {} + +ProofVerifierChromium::~ProofVerifierChromium() { + STLDeleteElements(&active_jobs_); +} + +QuicAsyncStatus ProofVerifierChromium::VerifyProof( + const std::string& hostname, + const std::string& server_config, + const std::vector<std::string>& certs, + const std::string& signature, + const ProofVerifyContext* verify_context, + std::string* error_details, + scoped_ptr<ProofVerifyDetails>* verify_details, + ProofVerifierCallback* callback) { + if (!verify_context) { + *error_details = "Missing context"; + return QUIC_FAILURE; + } + const ProofVerifyContextChromium* chromium_context = + reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); + scoped_ptr<Job> job(new Job(this, cert_verifier_, chromium_context->net_log)); + QuicAsyncStatus status = job->VerifyProof(hostname, server_config, certs, + signature, error_details, + verify_details, callback); + if (status == QUIC_PENDING) { + active_jobs_.insert(job.release()); + } + return status; +} + +void ProofVerifierChromium::OnJobComplete(Job* job) { + active_jobs_.erase(job); + delete job; +} + } // namespace net |