Index: net/quic/crypto/proof_verifier_chromium.cc |
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc |
index 096374a747255b451000cf3afccf034083a13368..fdcd2161ab302b19b3e0e802453175c57ca150da 100644 |
--- a/net/quic/crypto/proof_verifier_chromium.cc |
+++ b/net/quic/crypto/proof_verifier_chromium.cc |
@@ -78,6 +78,17 @@ class ProofVerifierChromium::Job { |
std::unique_ptr<ProofVerifyDetails>* verify_details, |
ProofVerifierCallback* callback); |
+ // Starts the certificate chain verification of |certs|. If |QUIC_PENDING| is |
+ // returned, then |callback| will be invoked asynchronously when the |
+ // verification completes. |
+ QuicAsyncStatus VerifyCertChain( |
+ const std::string& hostname, |
+ const uint16_t port, |
+ const std::vector<std::string>& certs, |
+ std::string* error_details, |
+ std::unique_ptr<ProofVerifyDetails>* verify_details, |
+ ProofVerifierCallback* callback); |
+ |
private: |
enum State { |
STATE_NONE, |
@@ -85,6 +96,19 @@ class ProofVerifierChromium::Job { |
STATE_VERIFY_CERT_COMPLETE, |
}; |
+ // Convert |certs| to |cert_|(X509Certificate). Returns true if successful. |
+ bool GetX509Certificate(const vector<string>& certs, |
+ std::string* error_details, |
+ std::unique_ptr<ProofVerifyDetails>* verify_details); |
+ |
+ // Start the cert verification. |
+ QuicAsyncStatus VerifyCert( |
+ const string& hostname, |
+ const uint16_t port, |
+ std::string* error_details, |
+ std::unique_ptr<ProofVerifyDetails>* verify_details, |
+ ProofVerifierCallback* callback); |
+ |
int DoLoop(int last_io_result); |
void OnIOComplete(int result); |
int DoVerifyCert(int result); |
@@ -125,6 +149,9 @@ class ProofVerifierChromium::Job { |
// passed to CertVerifier::Verify. |
int cert_verify_flags_; |
+ // If set to true, enforces policy checking in DoVerifyCertComplete(). |
+ bool enforce_policy_checking_; |
ramant (doing other things)
2016/07/07 19:31:49
Hi Ryan,
As we had discussed offline, added this
|
+ |
State next_state_; |
base::TimeTicks start_time_; |
@@ -148,6 +175,7 @@ ProofVerifierChromium::Job::Job( |
transport_security_state_(transport_security_state), |
cert_transparency_verifier_(cert_transparency_verifier), |
cert_verify_flags_(cert_verify_flags), |
+ enforce_policy_checking_(true), |
next_state_(STATE_NONE), |
start_time_(base::TimeTicks::Now()), |
net_log_(net_log) { |
@@ -195,25 +223,8 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( |
verify_details_.reset(new ProofVerifyDetailsChromium); |
- if (certs.empty()) { |
- *error_details = "Failed to create certificate chain. Certs are empty."; |
- DLOG(WARNING) << *error_details; |
- verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
- *verify_details = std::move(verify_details_); |
- return QUIC_FAILURE; |
- } |
- |
- // Convert certs to X509Certificate. |
- vector<StringPiece> cert_pieces(certs.size()); |
- for (unsigned i = 0; i < certs.size(); i++) { |
- cert_pieces[i] = base::StringPiece(certs[i]); |
- } |
- cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); |
- if (!cert_.get()) { |
- *error_details = "Failed to create certificate chain"; |
- DLOG(WARNING) << *error_details; |
- verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
- *verify_details = std::move(verify_details_); |
+ // Converts |certs| to |cert_|. |
+ if (!GetX509Certificate(certs, error_details, verify_details)) { |
return QUIC_FAILURE; |
} |
@@ -237,6 +248,74 @@ QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof( |
return QUIC_FAILURE; |
} |
+ DCHECK(enforce_policy_checking_); |
+ return VerifyCert(hostname, port, error_details, verify_details, callback); |
+} |
+ |
+QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( |
+ const string& hostname, |
+ const uint16_t port, |
+ const vector<string>& certs, |
+ std::string* error_details, |
+ std::unique_ptr<ProofVerifyDetails>* verify_details, |
+ ProofVerifierCallback* callback) { |
+ DCHECK(error_details); |
+ DCHECK(verify_details); |
+ DCHECK(callback); |
+ |
+ error_details->clear(); |
+ |
+ if (STATE_NONE != next_state_) { |
+ *error_details = "Certificate is already set and VerifyCertChain has begun"; |
+ DLOG(DFATAL) << *error_details; |
+ return QUIC_FAILURE; |
+ } |
+ |
+ verify_details_.reset(new ProofVerifyDetailsChromium); |
+ |
+ // Converts |certs| to |cert_|. |
+ if (!GetX509Certificate(certs, error_details, verify_details)) { |
+ return QUIC_FAILURE; |
+ } |
+ |
+ enforce_policy_checking_ = false; |
+ return VerifyCert(hostname, port, error_details, verify_details, callback); |
+} |
+ |
+bool ProofVerifierChromium::Job::GetX509Certificate( |
+ const vector<string>& certs, |
+ std::string* error_details, |
+ std::unique_ptr<ProofVerifyDetails>* verify_details) { |
+ if (certs.empty()) { |
+ *error_details = "Failed to create certificate chain. Certs are empty."; |
+ DLOG(WARNING) << *error_details; |
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
+ *verify_details = std::move(verify_details_); |
+ return false; |
+ } |
+ |
+ // Convert certs to X509Certificate. |
+ vector<StringPiece> cert_pieces(certs.size()); |
+ for (unsigned i = 0; i < certs.size(); i++) { |
+ cert_pieces[i] = base::StringPiece(certs[i]); |
+ } |
+ cert_ = X509Certificate::CreateFromDERCertChain(cert_pieces); |
+ if (!cert_.get()) { |
+ *error_details = "Failed to create certificate chain"; |
+ DLOG(WARNING) << *error_details; |
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID; |
+ *verify_details = std::move(verify_details_); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( |
+ const string& hostname, |
+ const uint16_t port, |
+ std::string* error_details, |
+ std::unique_ptr<ProofVerifyDetails>* verify_details, |
+ ProofVerifierCallback* callback) { |
hostname_ = hostname; |
port_ = port; |
@@ -315,7 +394,8 @@ int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { |
// If the connection was good, check HPKP and CT status simultaneously, |
// but prefer to treat the HPKP error as more serious, if there was one. |
- if ((result == OK || |
+ if (enforce_policy_checking_ && |
+ (result == OK || |
(IsCertificateError(result) && IsCertStatusMinorError(cert_status)))) { |
if ((cert_verify_result.cert_status & CERT_STATUS_IS_EV)) { |
ct::EVPolicyCompliance ev_policy_compliance = |
@@ -511,6 +591,32 @@ QuicAsyncStatus ProofVerifierChromium::VerifyProof( |
return status; |
} |
+QuicAsyncStatus ProofVerifierChromium::VerifyCertChain( |
+ const std::string& hostname, |
+ const uint16_t port, |
+ const std::vector<std::string>& certs, |
+ const ProofVerifyContext* verify_context, |
+ std::string* error_details, |
+ std::unique_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); |
+ std::unique_ptr<Job> job( |
+ new Job(this, cert_verifier_, ct_policy_enforcer_, |
+ transport_security_state_, cert_transparency_verifier_, |
+ chromium_context->cert_verify_flags, chromium_context->net_log)); |
+ QuicAsyncStatus status = job->VerifyCertChain( |
+ hostname, port, certs, error_details, verify_details, callback); |
+ if (status == QUIC_PENDING) { |
+ active_jobs_.insert(job.release()); |
+ } |
Ryan Hamilton
2016/07/07 21:36:12
nit: no {}s
ramant (doing other things)
2016/07/07 22:18:27
Done. Used no {}s in chromium specific files. They
|
+ return status; |
+} |
+ |
void ProofVerifierChromium::OnJobComplete(Job* job) { |
active_jobs_.erase(job); |
delete job; |