summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2013-07-31 10:55:33 +0100
committerBen Murdoch <benm@google.com>2013-07-31 10:55:33 +0100
commitd3868032626d59662ff73b372b5d584c1d144c53 (patch)
treeb53968078879cdade155a2e869a58b2ec568a06d /net
parente5b4422c968a7a35d5d4fbae38f8786f61e98bc8 (diff)
downloadchromium_org-d3868032626d59662ff73b372b5d584c1d144c53.tar.gz
Merge from Chromium at DEPS revision r214391
This commit was generated by merge_to_master.py. Change-Id: Iad15fada300ebc6cf9cbcebfc484b1a5f5f372e5
Diffstat (limited to 'net')
-rw-r--r--net/http/transport_security_state_static.h1
-rw-r--r--net/http/transport_security_state_static.json1
-rw-r--r--net/net.gyp1
-rw-r--r--net/net.target.darwin-arm.mk1
-rw-r--r--net/net.target.darwin-mips.mk1
-rw-r--r--net/net.target.darwin-x86.mk1
-rw-r--r--net/net.target.linux-arm.mk1
-rw-r--r--net/net.target.linux-mips.mk1
-rw-r--r--net/net.target.linux-x86.mk1
-rw-r--r--net/quic/crypto/crypto_handshake.cc12
-rw-r--r--net/quic/crypto/crypto_handshake.h12
-rw-r--r--net/quic/crypto/proof_test.cc167
-rw-r--r--net/quic/crypto/proof_verifier.cc15
-rw-r--r--net/quic/crypto/proof_verifier.h68
-rw-r--r--net/quic/crypto/proof_verifier_chromium.cc67
-rw-r--r--net/quic/crypto/proof_verifier_chromium.h29
-rw-r--r--net/quic/quic_crypto_client_stream.cc93
-rw-r--r--net/quic/quic_crypto_client_stream.h51
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc23
19 files changed, 352 insertions, 194 deletions
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h
index 830974392f..cf43609ce8 100644
--- a/net/http/transport_security_state_static.h
+++ b/net/http/transport_security_state_static.h
@@ -831,6 +831,7 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{18, true, "\015rapidresearch\002me", true, kNoPins, DOMAIN_NOT_PINNED },
{14, true, "\010surkatty\003org", true, kNoPins, DOMAIN_NOT_PINNED },
{21, true, "\017securityheaders\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {10, true, "\005haste\002ch", true, kNoPins, DOMAIN_NOT_PINNED },
};
static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 4ca4aca448..e0528c499a 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -621,6 +621,7 @@
{ "name": "rapidresearch.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "surkatty.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "securityheaders.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "haste.ch", "include_subdomains": true, "mode": "force-https" },
// Entries that are only valid if the client supports SNI.
{ "name": "gmail.com", "mode": "force-https", "pins": "google", "snionly": true },
diff --git a/net/net.gyp b/net/net.gyp
index 657a772083..2a9d78aa66 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -762,6 +762,7 @@
'quic/crypto/proof_source.h',
'quic/crypto/proof_source_chromium.cc',
'quic/crypto/proof_source_chromium.h',
+ 'quic/crypto/proof_verifier.cc',
'quic/crypto/proof_verifier_chromium.cc',
'quic/crypto/proof_verifier_chromium.h',
'quic/crypto/quic_decrypter.cc',
diff --git a/net/net.target.darwin-arm.mk b/net/net.target.darwin-arm.mk
index 0b2fee4157..0b23ed3479 100644
--- a/net/net.target.darwin-arm.mk
+++ b/net/net.target.darwin-arm.mk
@@ -298,6 +298,7 @@ LOCAL_SRC_FILES := \
net/quic/crypto/null_encrypter.cc \
net/quic/crypto/p256_key_exchange_openssl.cc \
net/quic/crypto/proof_source_chromium.cc \
+ net/quic/crypto/proof_verifier.cc \
net/quic/crypto/proof_verifier_chromium.cc \
net/quic/crypto/quic_decrypter.cc \
net/quic/crypto/quic_encrypter.cc \
diff --git a/net/net.target.darwin-mips.mk b/net/net.target.darwin-mips.mk
index d239f35241..85e56d53ed 100644
--- a/net/net.target.darwin-mips.mk
+++ b/net/net.target.darwin-mips.mk
@@ -298,6 +298,7 @@ LOCAL_SRC_FILES := \
net/quic/crypto/null_encrypter.cc \
net/quic/crypto/p256_key_exchange_openssl.cc \
net/quic/crypto/proof_source_chromium.cc \
+ net/quic/crypto/proof_verifier.cc \
net/quic/crypto/proof_verifier_chromium.cc \
net/quic/crypto/quic_decrypter.cc \
net/quic/crypto/quic_encrypter.cc \
diff --git a/net/net.target.darwin-x86.mk b/net/net.target.darwin-x86.mk
index 4deda275aa..b351009261 100644
--- a/net/net.target.darwin-x86.mk
+++ b/net/net.target.darwin-x86.mk
@@ -298,6 +298,7 @@ LOCAL_SRC_FILES := \
net/quic/crypto/null_encrypter.cc \
net/quic/crypto/p256_key_exchange_openssl.cc \
net/quic/crypto/proof_source_chromium.cc \
+ net/quic/crypto/proof_verifier.cc \
net/quic/crypto/proof_verifier_chromium.cc \
net/quic/crypto/quic_decrypter.cc \
net/quic/crypto/quic_encrypter.cc \
diff --git a/net/net.target.linux-arm.mk b/net/net.target.linux-arm.mk
index 0b2fee4157..0b23ed3479 100644
--- a/net/net.target.linux-arm.mk
+++ b/net/net.target.linux-arm.mk
@@ -298,6 +298,7 @@ LOCAL_SRC_FILES := \
net/quic/crypto/null_encrypter.cc \
net/quic/crypto/p256_key_exchange_openssl.cc \
net/quic/crypto/proof_source_chromium.cc \
+ net/quic/crypto/proof_verifier.cc \
net/quic/crypto/proof_verifier_chromium.cc \
net/quic/crypto/quic_decrypter.cc \
net/quic/crypto/quic_encrypter.cc \
diff --git a/net/net.target.linux-mips.mk b/net/net.target.linux-mips.mk
index d239f35241..85e56d53ed 100644
--- a/net/net.target.linux-mips.mk
+++ b/net/net.target.linux-mips.mk
@@ -298,6 +298,7 @@ LOCAL_SRC_FILES := \
net/quic/crypto/null_encrypter.cc \
net/quic/crypto/p256_key_exchange_openssl.cc \
net/quic/crypto/proof_source_chromium.cc \
+ net/quic/crypto/proof_verifier.cc \
net/quic/crypto/proof_verifier_chromium.cc \
net/quic/crypto/quic_decrypter.cc \
net/quic/crypto/quic_encrypter.cc \
diff --git a/net/net.target.linux-x86.mk b/net/net.target.linux-x86.mk
index 4deda275aa..b351009261 100644
--- a/net/net.target.linux-x86.mk
+++ b/net/net.target.linux-x86.mk
@@ -298,6 +298,7 @@ LOCAL_SRC_FILES := \
net/quic/crypto/null_encrypter.cc \
net/quic/crypto/p256_key_exchange_openssl.cc \
net/quic/crypto/proof_source_chromium.cc \
+ net/quic/crypto/proof_verifier.cc \
net/quic/crypto/proof_verifier_chromium.cc \
net/quic/crypto/quic_decrypter.cc \
net/quic/crypto/quic_encrypter.cc \
diff --git a/net/quic/crypto/crypto_handshake.cc b/net/quic/crypto/crypto_handshake.cc
index 00cc342060..ad4366dcf6 100644
--- a/net/quic/crypto/crypto_handshake.cc
+++ b/net/quic/crypto/crypto_handshake.cc
@@ -500,9 +500,9 @@ uint64 QuicCryptoClientConfig::CachedState::generation_counter() const {
return generation_counter_;
}
-const CertVerifyResult*
-QuicCryptoClientConfig::CachedState::cert_verify_result() const {
- return &cert_verify_result_;
+const ProofVerifyDetails*
+QuicCryptoClientConfig::CachedState::proof_verify_details() const {
+ return proof_verify_details_.get();
}
void QuicCryptoClientConfig::CachedState::set_source_address_token(
@@ -510,9 +510,9 @@ void QuicCryptoClientConfig::CachedState::set_source_address_token(
source_address_token_ = token.as_string();
}
-void QuicCryptoClientConfig::CachedState::SetCertVerifyResult(
- const CertVerifyResult& cert_verify_result) {
- cert_verify_result_.CopyFrom(cert_verify_result);
+void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
+ ProofVerifyDetails* details) {
+ proof_verify_details_.reset(details);
}
void QuicCryptoClientConfig::SetDefaults() {
diff --git a/net/quic/crypto/crypto_handshake.h b/net/quic/crypto/crypto_handshake.h
index d2f11f8c17..fdc92a0fc3 100644
--- a/net/quic/crypto/crypto_handshake.h
+++ b/net/quic/crypto/crypto_handshake.h
@@ -15,6 +15,7 @@
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/crypto/proof_verifier.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -281,10 +282,12 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const std::string& signature() const;
bool proof_valid() const;
uint64 generation_counter() const;
- const CertVerifyResult* cert_verify_result() const;
+ const ProofVerifyDetails* proof_verify_details() const;
void set_source_address_token(base::StringPiece token);
- void SetCertVerifyResult(const CertVerifyResult& cert_verify_result);
+
+ // SetProofVerifyDetails takes ownership of |details|.
+ void SetProofVerifyDetails(ProofVerifyDetails* details);
private:
std::string server_config_id_; // An opaque id from the server.
@@ -301,10 +304,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// server_config_valid_ to false.
uint64 generation_counter_;
- // The result of certificate verification.
- // TODO(rtenneti): should we change CertVerifyResult to be
- // RefCountedThreadSafe object to avoid copying.
- CertVerifyResult cert_verify_result_;
+ scoped_ptr<ProofVerifyDetails> proof_verify_details_;
// scfg contains the cached, parsed value of |server_config|.
mutable scoped_ptr<CryptoHandshakeMessage> scfg_;
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index 3258c12a8f..8facb82374 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -89,6 +89,68 @@ TEST(Proof, Verify) {
#endif // 0
}
+// TestProofVerifierCallback is a simple callback for a ProofVerifier that
+// signals a TestCompletionCallback when called and stores the results from the
+// ProofVerifier in pointers passed to the constructor.
+class TestProofVerifierCallback : public ProofVerifierCallback {
+ public:
+ TestProofVerifierCallback(TestCompletionCallback* comp_callback,
+ bool* ok,
+ std::string* error_details)
+ : comp_callback_(comp_callback),
+ ok_(ok),
+ error_details_(error_details) {}
+
+ virtual void Run(bool ok,
+ const std::string& error_details,
+ scoped_ptr<ProofVerifyDetails>* details) OVERRIDE {
+ *ok_ = ok;
+ *error_details_ = error_details;
+
+ comp_callback_->callback().Run(0);
+ }
+
+ private:
+ TestCompletionCallback* const comp_callback_;
+ bool* const ok_;
+ std::string* const error_details_;
+};
+
+// RunVerification runs |verifier->VerifyProof| and asserts that the result
+// matches |expected_ok|.
+static void RunVerification(ProofVerifier* verifier,
+ const std::string& hostname,
+ const std::string& server_config,
+ const vector<std::string>& certs,
+ const std::string& proof,
+ bool expected_ok) {
+ scoped_ptr<ProofVerifyDetails> details;
+ TestCompletionCallback comp_callback;
+ bool ok;
+ std::string error_details;
+ TestProofVerifierCallback* callback =
+ new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
+
+ ProofVerifier::Status status = verifier->VerifyProof(
+ hostname, server_config, certs, proof, &error_details, &details,
+ callback);
+
+ switch (status) {
+ case ProofVerifier::FAILURE:
+ ASSERT_FALSE(expected_ok);
+ ASSERT_NE("", error_details);
+ return;
+ case ProofVerifier::SUCCESS:
+ ASSERT_TRUE(expected_ok);
+ ASSERT_EQ("", error_details);
+ return;
+ case ProofVerifier::PENDING:
+ comp_callback.WaitForResult();
+ ASSERT_EQ(expected_ok, ok);
+ break;
+ }
+}
+
static string PEMCertFileToDER(const string& file_name) {
base::FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> cert =
@@ -227,48 +289,26 @@ TEST(Proof, VerifyRSAKnownAnswerTest) {
for (size_t i = 0; i < signatures.size(); i++) {
const string& signature = signatures[i];
- int rv;
- TestCompletionCallback callback;
- rv = verifier->VerifyProof(hostname, server_config, certs, signature,
- &error_details, &cert_verify_result,
- callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(OK, rv);
- ASSERT_EQ("", error_details);
- ASSERT_FALSE(IsCertStatusError(cert_verify_result.cert_status));
-
- rv = verifier->VerifyProof("foo.com", server_config, certs, signature,
- &error_details, &cert_verify_result,
- callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
-
- rv = verifier->VerifyProof(hostname, server_config.substr(1, string::npos),
- certs, signature, &error_details,
- &cert_verify_result, callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+
+ RunVerification(
+ verifier.get(), hostname, server_config, certs, signature, true);
+ RunVerification(
+ verifier.get(), "foo.com", server_config, certs, signature, false);
+ RunVerification(
+ verifier.get(), hostname, server_config.substr(1, string::npos),
+ certs, signature, false);
const string corrupt_signature = "1" + signature;
- rv = verifier->VerifyProof(hostname, server_config, certs,
- corrupt_signature, &error_details,
- &cert_verify_result, callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+ RunVerification(
+ verifier.get(), hostname, server_config, certs, corrupt_signature,
+ false);
vector<string> wrong_certs;
for (size_t i = 1; i < certs.size(); i++) {
wrong_certs.push_back(certs[i]);
}
- rv = verifier->VerifyProof("foo.com", server_config, wrong_certs, signature,
- &error_details, &cert_verify_result,
- callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+ RunVerification(verifier.get(), hostname, server_config, wrong_certs,
+ signature, false);
}
}
@@ -340,60 +380,35 @@ TEST(Proof, MAYBE_VerifyECDSAKnownAnswerTest) {
for (size_t i = 0; i < signatures.size(); i++) {
const string& signature = signatures[i];
- int rv;
- TestCompletionCallback callback;
- rv = verifier->VerifyProof(hostname, server_config, certs, signature,
- &error_details, &cert_verify_result,
- callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(OK, rv);
- ASSERT_EQ("", error_details);
- ASSERT_FALSE(IsCertStatusError(cert_verify_result.cert_status));
-
- rv = verifier->VerifyProof("foo.com", server_config, certs, signature,
- &error_details, &cert_verify_result,
- callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
-
- rv = verifier->VerifyProof(hostname, server_config.substr(1, string::npos),
- certs, signature, &error_details,
- &cert_verify_result, callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+
+ RunVerification(
+ verifier.get(), hostname, server_config, certs, signature, true);
+ RunVerification(
+ verifier.get(), "foo.com", server_config, certs, signature, false);
+ RunVerification(
+ verifier.get(), hostname, server_config.substr(1, string::npos),
+ certs, signature, false);
// An ECDSA signature is DER-encoded. Corrupt the last byte so that the
// signature can still be DER-decoded correctly.
string corrupt_signature = signature;
corrupt_signature[corrupt_signature.size() - 1] += 1;
- rv = verifier->VerifyProof(hostname, server_config, certs,
- corrupt_signature, &error_details,
- &cert_verify_result, callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+ RunVerification(
+ verifier.get(), hostname, server_config, certs, corrupt_signature,
+ false);
// Prepending a "1" makes the DER invalid.
const string bad_der_signature1 = "1" + signature;
- rv = verifier->VerifyProof(hostname, server_config, certs,
- bad_der_signature1, &error_details,
- &cert_verify_result, callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+ RunVerification(
+ verifier.get(), hostname, server_config, certs, bad_der_signature1,
+ false);
vector<string> wrong_certs;
for (size_t i = 1; i < certs.size(); i++) {
wrong_certs.push_back(certs[i]);
}
- rv = verifier->VerifyProof("foo.com", server_config, wrong_certs, signature,
- &error_details, &cert_verify_result,
- callback.callback());
- rv = callback.GetResult(rv);
- ASSERT_EQ(ERR_FAILED, rv);
- ASSERT_NE("", error_details);
+ RunVerification(
+ verifier.get(), hostname, server_config, wrong_certs, signature, false);
}
}
diff --git a/net/quic/crypto/proof_verifier.cc b/net/quic/crypto/proof_verifier.cc
new file mode 100644
index 0000000000..7bccba2bdb
--- /dev/null
+++ b/net/quic/crypto/proof_verifier.cc
@@ -0,0 +1,15 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/crypto/proof_verifier.h"
+
+namespace net {
+
+ProofVerifyDetails::~ProofVerifyDetails() {}
+
+ProofVerifierCallback::~ProofVerifierCallback() {}
+
+ProofVerifier::~ProofVerifier() {}
+
+} // namespace net
diff --git a/net/quic/crypto/proof_verifier.h b/net/quic/crypto/proof_verifier.h
index eb96898950..f469c55295 100644
--- a/net/quic/crypto/proof_verifier.h
+++ b/net/quic/crypto/proof_verifier.h
@@ -15,32 +15,68 @@ namespace net {
class CertVerifyResult;
+// ProofVerifyDetails is an abstract class that acts as a container for any
+// implementation specific details that a ProofVerifier wishes to return. These
+// details are saved in the CachedInfo for the origin in question.
+class ProofVerifyDetails {
+ public:
+ virtual ~ProofVerifyDetails();
+};
+
+// ProofVerifierCallback provides a generic mechanism for a ProofVerifier to
+// call back after an asynchronous verification.
+class NET_EXPORT_PRIVATE ProofVerifierCallback {
+ public:
+ virtual ~ProofVerifierCallback();
+
+ // Run is called on the original thread to mark the completion of an
+ // asynchonous verification. If |ok| is true then the certificate is valid
+ // and |*error_details| is unused. Otherwise, |*error_details| contains a
+ // description of the error. |details| contains implementation-specific
+ // details of the verification. |Run| may take ownership of |details| by
+ // calling |release| on it.
+ virtual void Run(bool ok,
+ const std::string& error_details,
+ scoped_ptr<ProofVerifyDetails>* details) = 0;
+};
+
// A ProofVerifier checks the signature on a server config, and the certificate
// chain that backs the public key.
class NET_EXPORT_PRIVATE ProofVerifier {
public:
- virtual ~ProofVerifier() {}
+ // Status enumerates the possible results of verifying a proof.
+ enum Status {
+ SUCCESS = 0,
+ FAILURE = 1,
+ // PENDING results from a verification which will occur asynchonously. When
+ // the verification is complete, |callback|'s |Run| method will be called.
+ PENDING = 2,
+ };
+
+ virtual ~ProofVerifier();
// VerifyProof checks that |signature| is a valid signature of
// |server_config| by the public key in the leaf certificate of |certs|, and
- // that |certs| is a valid chain for |hostname|. On success, it returns OK.
- // On failure, it returns ERR_FAILED and sets |*error_details| to a
- // description of the problem. This function may also return ERR_IO_PENDING,
- // in which case the |callback| will be run on the calling thread with the
- // final OK/ERR_FAILED result when the proof is verified.
+ // that |certs| is a valid chain for |hostname|. On success, it returns
+ // SUCCESS. On failure, it returns ERROR and sets |*error_details| to a
+ // description of the problem. In either case it may set |*details|, which the
+ // caller takes ownership of.
+ //
+ // This function may also return PENDING, in which case the ProofVerifier
+ // will call back, on the original thread, via |callback| when complete.
+ //
+ // This function takes ownership of |callback|. It will be deleted even if
+ // the call returns immediately.
//
// The signature uses SHA-256 as the hash function and PSS padding in the
// case of RSA.
- //
- // Note: this is just for testing. The CN of the certificate is ignored and
- // wildcards in the SANs are not supported.
- virtual int VerifyProof(const std::string& hostname,
- const std::string& server_config,
- const std::vector<std::string>& certs,
- const std::string& signature,
- std::string* error_details,
- CertVerifyResult* cert_verify_result,
- const CompletionCallback& callback) = 0;
+ virtual Status 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>* details,
+ ProofVerifierCallback* callback) = 0;
};
} // namespace net
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 6f547882eb..c8b197b3d0 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -33,8 +33,6 @@ namespace net {
ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier,
const BoundNetLog& net_log)
: cert_verifier_(cert_verifier),
- cert_verify_result_(NULL),
- error_details_(NULL),
next_state_(STATE_NONE),
net_log_(net_log) {
}
@@ -43,29 +41,36 @@ ProofVerifierChromium::~ProofVerifierChromium() {
verifier_.reset();
}
-int ProofVerifierChromium::VerifyProof(const string& hostname,
- const string& server_config,
- const vector<string>& certs,
- const string& signature,
- std::string* error_details,
- CertVerifyResult* cert_verify_result,
- const CompletionCallback& callback) {
+ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof(
+ const string& hostname,
+ const string& server_config,
+ const vector<string>& certs,
+ const string& signature,
+ std::string* error_details,
+ scoped_ptr<ProofVerifyDetails>* details,
+ ProofVerifierCallback* callback) {
DCHECK(error_details);
- DCHECK(cert_verify_result);
+ DCHECK(details);
+ DCHECK(callback);
+
+ callback_.reset(callback);
error_details->clear();
- cert_verify_result->Reset();
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 ERR_FAILED;
+ return FAILURE;
}
+ verify_details_.reset(new ProofVerifyDetailsChromium);
+
if (certs.empty()) {
*error_details = "Failed to create certificate chain. Certs are empty.";
DLOG(WARNING) << *error_details;
- return ERR_FAILED;
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+ details->reset(verify_details_.release());
+ return FAILURE;
}
// Convert certs to X509Certificate.
@@ -77,8 +82,9 @@ int ProofVerifierChromium::VerifyProof(const string& hostname,
if (!cert_.get()) {
*error_details = "Failed to create certificate chain";
DLOG(WARNING) << *error_details;
- cert_verify_result->cert_status = CERT_STATUS_INVALID;
- return ERR_FAILED;
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+ details->reset(verify_details_.release());
+ return FAILURE;
}
// We call VerifySignature first to avoid copying of server_config and
@@ -86,16 +92,25 @@ int ProofVerifierChromium::VerifyProof(const string& hostname,
if (!VerifySignature(server_config, signature, certs[0])) {
*error_details = "Failed to verify signature of server config";
DLOG(WARNING) << *error_details;
- return ERR_FAILED;
+ verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+ details->reset(verify_details_.release());
+ return FAILURE;
}
hostname_ = hostname;
- callback_ = callback;
- error_details_ = error_details;
- cert_verify_result_ = cert_verify_result;
next_state_ = STATE_VERIFY_CERT;
- return DoLoop(OK);
+ switch (DoLoop(OK)) {
+ case OK:
+ details->reset(verify_details_.release());
+ return SUCCESS;
+ case ERR_IO_PENDING:
+ return PENDING;
+ default:
+ *error_details = error_details_;
+ details->reset(verify_details_.release());
+ return FAILURE;
+ }
}
int ProofVerifierChromium::DoLoop(int last_result) {
@@ -124,7 +139,9 @@ int ProofVerifierChromium::DoLoop(int last_result) {
void ProofVerifierChromium::OnIOComplete(int result) {
int rv = DoLoop(result);
if (rv != ERR_IO_PENDING) {
- base::ResetAndReturn(&callback_).Run(rv);
+ scoped_ptr<ProofVerifyDetails> scoped_details(verify_details_.release());
+ callback_->Run(rv == OK, error_details_, &scoped_details);
+ callback_.reset();
}
}
@@ -138,7 +155,7 @@ int ProofVerifierChromium::DoVerifyCert(int result) {
hostname_,
flags,
SSLConfigService::GetCRLSet().get(),
- cert_verify_result_,
+ &verify_details_->cert_verify_result,
base::Bind(&ProofVerifierChromium::OnIOComplete,
base::Unretained(this)),
net_log_);
@@ -148,9 +165,9 @@ int ProofVerifierChromium::DoVerifyCertComplete(int result) {
verifier_.reset();
if (result <= ERR_FAILED) {
- *error_details_ = StringPrintf("Failed to verify certificate chain: %s",
- ErrorToString(result));
- DLOG(WARNING) << *error_details_;
+ error_details_ = StringPrintf("Failed to verify certificate chain: %s",
+ ErrorToString(result));
+ DLOG(WARNING) << error_details_;
result = ERR_FAILED;
}
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index 134f62baa1..4969cc8aa5 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -23,6 +23,13 @@ namespace net {
class CertVerifier;
class SingleRequestCertVerifier;
+// ProofVerifyDetailsChromium is the implementation-specific information that a
+// ProofVerifierChromium returns about a certificate verification.
+struct ProofVerifyDetailsChromium : public ProofVerifyDetails {
+ public:
+ CertVerifyResult cert_verify_result;
+};
+
// ProofVerifierChromium implements the QUIC ProofVerifier interface.
// TODO(rtenneti): Add support for multiple requests for one ProofVerifier.
class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
@@ -32,13 +39,13 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
virtual ~ProofVerifierChromium();
// ProofVerifier interface
- virtual int VerifyProof(const std::string& hostname,
- const std::string& server_config,
- const std::vector<std::string>& certs,
- const std::string& signature,
- std::string* error_details,
- CertVerifyResult* cert_verify_result,
- const CompletionCallback& callback) OVERRIDE;
+ virtual Status 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>* details,
+ ProofVerifierCallback* callback) OVERRIDE;
private:
enum State {
@@ -63,11 +70,9 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
// |hostname| specifies the hostname for which |certs| is a valid chain.
std::string hostname_;
- CompletionCallback callback_;
-
- // The result of certificate verification.
- CertVerifyResult* cert_verify_result_;
- std::string* error_details_;
+ 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_;
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index 78b39e759e..69c63a5664 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -10,6 +10,7 @@
#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/crypto/null_encrypter.h"
#include "net/quic/crypto/proof_verifier.h"
+#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
#include "net/ssl/ssl_connection_status_flags.h"
@@ -17,30 +18,63 @@
namespace net {
+QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
+ QuicCryptoClientStream* stream)
+ : stream_(stream) {}
+
+QuicCryptoClientStream::ProofVerifierCallbackImpl::
+ ~ProofVerifierCallbackImpl() {}
+
+void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
+ bool ok,
+ const string& error_details,
+ scoped_ptr<ProofVerifyDetails>* details) {
+ if (stream_ == NULL) {
+ return;
+ }
+
+ stream_->verify_ok_ = ok;
+ stream_->verify_error_details_ = error_details;
+ stream_->verify_details_.reset(details->release());
+ stream_->proof_verify_callback_ = NULL;
+ stream_->DoHandshakeLoop(NULL);
+
+ // The ProofVerifier owns this object and will delete it when this method
+ // returns.
+}
+
+void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
+ stream_ = NULL;
+}
+
+
QuicCryptoClientStream::QuicCryptoClientStream(
const string& server_hostname,
QuicSession* session,
QuicCryptoClientConfig* crypto_config)
: QuicCryptoStream(session),
- weak_factory_(this),
next_state_(STATE_IDLE),
num_client_hellos_(0),
crypto_config_(crypto_config),
server_hostname_(server_hostname),
- generation_counter_(0) {
+ generation_counter_(0),
+ proof_verify_callback_(NULL) {
}
QuicCryptoClientStream::~QuicCryptoClientStream() {
+ if (proof_verify_callback_) {
+ proof_verify_callback_->Cancel();
+ }
}
void QuicCryptoClientStream::OnHandshakeMessage(
const CryptoHandshakeMessage& message) {
- DoHandshakeLoop(&message, OK);
+ DoHandshakeLoop(&message);
}
bool QuicCryptoClientStream::CryptoConnect() {
next_state_ = STATE_SEND_CHLO;
- DoHandshakeLoop(NULL, OK);
+ DoHandshakeLoop(NULL);
return true;
}
@@ -57,7 +91,8 @@ bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) {
return false;
}
const CertVerifyResult* cert_verify_result =
- cached->cert_verify_result();
+ &(reinterpret_cast<const ProofVerifyDetailsChromium*>(
+ cached->proof_verify_details()))->cert_verify_result;
ssl_info->cert_status = cert_verify_result->cert_status;
ssl_info->cert = cert_verify_result->verified_cert;
@@ -95,8 +130,7 @@ bool QuicCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) {
static const int kMaxClientHellos = 3;
void QuicCryptoClientStream::DoHandshakeLoop(
- const CryptoHandshakeMessage* in,
- int result) {
+ const CryptoHandshakeMessage* in) {
CryptoHandshakeMessage out;
QuicErrorCode error;
string error_details;
@@ -112,7 +146,6 @@ void QuicCryptoClientStream::DoHandshakeLoop(
next_state_ = STATE_IDLE;
switch (state) {
case STATE_SEND_CHLO: {
- DCHECK_EQ(OK, result);
// Send the client hello in plaintext.
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
if (num_client_hellos_ > kMaxClientHellos) {
@@ -171,7 +204,6 @@ void QuicCryptoClientStream::DoHandshakeLoop(
return;
}
case STATE_RECV_REJ:
- DCHECK_EQ(OK, result);
// We sent a dummy CHLO because we didn't have enough information to
// perform a handshake, or we sent a full hello that the server
// rejected. Here we hope to have a REJ that contains the information
@@ -205,25 +237,40 @@ void QuicCryptoClientStream::DoHandshakeLoop(
DCHECK(verifier);
next_state_ = STATE_VERIFY_PROOF_COMPLETE;
generation_counter_ = cached->generation_counter();
- result = verifier->VerifyProof(
+
+ ProofVerifierCallbackImpl* proof_verify_callback =
+ new ProofVerifierCallbackImpl(this);
+
+ verify_ok_ = false;
+
+ ProofVerifier::Status status = verifier->VerifyProof(
server_hostname_,
cached->server_config(),
cached->certs(),
cached->signature(),
- &error_details_,
- &cert_verify_result_,
- base::Bind(&QuicCryptoClientStream::OnVerifyProofComplete,
- weak_factory_.GetWeakPtr()));
- if (result == ERR_IO_PENDING) {
- DVLOG(1) << "Doing VerifyProof";
- return;
+ &error_details,
+ &verify_details_,
+ proof_verify_callback);
+
+ switch (status) {
+ case ProofVerifier::PENDING:
+ proof_verify_callback_ = proof_verify_callback;
+ DVLOG(1) << "Doing VerifyProof";
+ return;
+ case ProofVerifier::FAILURE:
+ CloseConnectionWithDetails(
+ QUIC_PROOF_INVALID, "Proof invalid: " + error_details);
+ return;
+ case ProofVerifier::SUCCESS:
+ verify_ok_ = true;
+ break;
}
break;
}
case STATE_VERIFY_PROOF_COMPLETE:
- if (result != OK) {
+ if (!verify_ok_) {
CloseConnectionWithDetails(
- QUIC_PROOF_INVALID, "Proof invalid: " + error_details_);
+ QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
return;
}
// Check if generation_counter has changed between STATE_VERIFY_PROOF
@@ -232,7 +279,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(
next_state_ = STATE_VERIFY_PROOF;
} else {
cached->SetProofValid();
- cached->SetCertVerifyResult(cert_verify_result_);
+ cached->SetProofVerifyDetails(verify_details_.release());
next_state_ = STATE_SEND_CHLO;
}
break;
@@ -305,10 +352,4 @@ void QuicCryptoClientStream::DoHandshakeLoop(
}
}
-void QuicCryptoClientStream::OnVerifyProofComplete(int result) {
- DCHECK_EQ(STATE_VERIFY_PROOF_COMPLETE, next_state_);
- DVLOG(1) << "VerifyProof completed: " << result;
- DoHandshakeLoop(NULL, result);
-}
-
} // namespace net
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h
index 4686fedf1a..50cfbb8679 100644
--- a/net/quic/quic_crypto_client_stream.h
+++ b/net/quic/quic_crypto_client_stream.h
@@ -10,11 +10,13 @@
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/crypto/proof_verifier.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_crypto_stream.h"
namespace net {
+class ProofVerifyDetails;
class QuicSession;
class SSLInfo;
@@ -47,7 +49,29 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
bool GetSSLInfo(SSLInfo* ssl_info);
private:
+ // ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
+ // The ProofVerifier calls this class with the result of proof verification
+ // when verification is performed asynchronously.
+ class ProofVerifierCallbackImpl : public ProofVerifierCallback {
+ public:
+ explicit ProofVerifierCallbackImpl(QuicCryptoClientStream* stream);
+ virtual ~ProofVerifierCallbackImpl();
+
+ // ProofVerifierCallback interface.
+ virtual void Run(bool ok,
+ const string& error_details,
+ scoped_ptr<ProofVerifyDetails>* details) OVERRIDE;
+
+ // Cancel causes any future callbacks to be ignored. It must be called on
+ // the same thread as the callback will be made on.
+ void Cancel();
+
+ private:
+ QuicCryptoClientStream* stream_;
+ };
+
friend class test::CryptoTestUtils;
+ friend class ProofVerifierCallbackImpl;
enum State {
STATE_IDLE,
@@ -59,17 +83,8 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
};
// DoHandshakeLoop performs a step of the handshake state machine. Note that
- // |in| is NULL for the first call. OnVerifyProofComplete passes the |result|
- // it has received from VerifyProof call (from all other places |result| is
- // set to OK).
- void DoHandshakeLoop(const CryptoHandshakeMessage* in, int result);
-
- // OnVerifyProofComplete is passed as the callback method to VerifyProof.
- // ProofVerifier calls this method with the result of proof verification when
- // verification is performed asynchronously.
- void OnVerifyProofComplete(int result);
-
- base::WeakPtrFactory<QuicCryptoClientStream> weak_factory_;
+ // |in| may be NULL if the call did not result from a received message
+ void DoHandshakeLoop(const CryptoHandshakeMessage* in);
State next_state_;
// num_client_hellos_ contains the number of client hello messages that this
@@ -86,13 +101,15 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
// Generation counter from QuicCryptoClientConfig's CachedState.
uint64 generation_counter_;
- // The result of certificate verification.
- // TODO(rtenneti): should we change CertVerifyResult to be
- // RefCountedThreadSafe object to avoid copying.
- CertVerifyResult cert_verify_result_;
+ // proof_verify_callback_ contains the callback object that we passed to an
+ // asynchronous proof verification. The ProofVerifier owns this object.
+ ProofVerifierCallbackImpl* proof_verify_callback_;
- // Error details for ProofVerifier's VerifyProof call.
- std::string error_details_;
+ // These members are used to store the result of an asynchronous proof
+ // verification.
+ bool verify_ok_;
+ string verify_error_details_;
+ scoped_ptr<ProofVerifyDetails> verify_details_;
DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
};
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index ef9a164053..eb260781a0 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -24,16 +24,19 @@ namespace {
class RecordingProofVerifier : public net::ProofVerifier {
public:
// ProofVerifier interface.
- virtual int VerifyProof(const string& hostname,
- const string& server_config,
- const vector<string>& certs,
- const string& signature,
- string* error_details,
- net::CertVerifyResult* cert_verify_result,
- const net::CompletionCallback& callback) OVERRIDE {
+ virtual net::ProofVerifier::Status VerifyProof(
+ const string& hostname,
+ const string& server_config,
+ const vector<string>& certs,
+ const string& signature,
+ string* error_details,
+ scoped_ptr<net::ProofVerifyDetails>* details,
+ net::ProofVerifierCallback* callback) OVERRIDE {
+ delete callback;
+
common_name_.clear();
if (certs.empty()) {
- return net::ERR_FAILED;
+ return FAILURE;
}
// Convert certs to X509Certificate.
@@ -44,11 +47,11 @@ class RecordingProofVerifier : public net::ProofVerifier {
scoped_refptr<net::X509Certificate> cert =
net::X509Certificate::CreateFromDERCertChain(cert_pieces);
if (!cert.get()) {
- return net::ERR_FAILED;
+ return FAILURE;
}
common_name_ = cert->subject().GetDisplayName();
- return net::OK;
+ return SUCCESS;
}
const string& common_name() const { return common_name_; }