summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-07 19:14:32 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-07 19:14:32 +0000
commit8e3e1a681ee4ea8cc87aff4e7db87890da6e27a4 (patch)
tree12a7b4f8610ee130001fd77961a494b7c30340ab
parent56367df5ff3364060689afc21352c33966bfc2c3 (diff)
downloadchromium_src-8e3e1a681ee4ea8cc87aff4e7db87890da6e27a4.zip
chromium_src-8e3e1a681ee4ea8cc87aff4e7db87890da6e27a4.tar.gz
chromium_src-8e3e1a681ee4ea8cc87aff4e7db87890da6e27a4.tar.bz2
Merge 287275 "Extend ProofVerifierChromium and ProofVerifyDetail..."
> Extend ProofVerifierChromium and ProofVerifyDetailsChromium. > > Original code review: https://codereview.chromium.org/436753002/ > > TBR=agl@chromium.org,rch@chromium.org > BUG=399457 > > Review URL: https://codereview.chromium.org/439133002 TBR=wtc@chromium.org Review URL: https://codereview.chromium.org/447073003 git-svn-id: svn://svn.chromium.org/chrome/branches/2062/src@288105 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/http/http_network_session.cc1
-rw-r--r--net/quic/crypto/proof_verifier_chromium.cc80
-rw-r--r--net/quic/crypto/proof_verifier_chromium.h11
-rw-r--r--net/quic/quic_client_session.cc9
-rw-r--r--net/quic/quic_client_session.h1
-rw-r--r--net/quic/quic_stream_factory.cc4
-rw-r--r--net/quic/quic_stream_factory.h2
-rw-r--r--net/quic/quic_stream_factory_test.cc3
-rw-r--r--net/quic/test_tools/crypto_test_utils_chromium.cc14
9 files changed, 109 insertions, 16 deletions
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index b4e373e..75c8ee4 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -117,6 +117,7 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
net::ClientSocketFactory::GetDefaultFactory(),
params.http_server_properties,
params.cert_verifier,
+ params.transport_security_state,
params.quic_crypto_client_stream_factory,
params.quic_random ? params.quic_random :
QuicRandom::GetInstance(),
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 4b118da..a1365c5c 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/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/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "crypto/signature_verifier.h"
@@ -21,6 +22,7 @@
#include "net/cert/single_request_cert_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
+#include "net/http/transport_security_state.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/ssl/ssl_config_service.h"
@@ -38,6 +40,7 @@ class ProofVerifierChromium::Job {
public:
Job(ProofVerifierChromium* proof_verifier,
CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state,
const BoundNetLog& net_log);
// Starts the proof verification. If |QUIC_PENDING| is returned, then
@@ -72,6 +75,8 @@ class ProofVerifierChromium::Job {
// The underlying verifier used for verifying certificates.
scoped_ptr<SingleRequestCertVerifier> verifier_;
+ TransportSecurityState* transport_security_state_;
+
// |hostname| specifies the hostname for which |certs| is a valid chain.
std::string hostname_;
@@ -89,11 +94,14 @@ class ProofVerifierChromium::Job {
DISALLOW_COPY_AND_ASSIGN(Job);
};
-ProofVerifierChromium::Job::Job(ProofVerifierChromium* proof_verifier,
- CertVerifier* cert_verifier,
- const BoundNetLog& net_log)
+ProofVerifierChromium::Job::Job(
+ ProofVerifierChromium* proof_verifier,
+ CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state,
+ const BoundNetLog& net_log)
: proof_verifier_(proof_verifier),
verifier_(new SingleRequestCertVerifier(cert_verifier)),
+ transport_security_state_(transport_security_state),
next_state_(STATE_NONE),
net_log_(net_log) {
}
@@ -222,6 +230,59 @@ int ProofVerifierChromium::Job::DoVerifyCert(int result) {
int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
verifier_.reset();
+#if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID) && !defined(OS_IOS)
+ // TODO(wtc): The following code was copied from ssl_client_socket_nss.cc.
+ // Convert it to a new function that can be called by both files. These
+ // variables simulate the arguments to the new function.
+ const CertVerifyResult& cert_verify_result =
+ verify_details_->cert_verify_result;
+ bool sni_available = true;
+ const std::string& host = hostname_;
+ TransportSecurityState* transport_security_state = transport_security_state_;
+ std::string* pinning_failure_log = &verify_details_->pinning_failure_log;
+
+ // Take care of any mandates for public key pinning.
+ //
+ // Pinning is only enabled for official builds to make sure that others don't
+ // end up with pins that cannot be easily updated.
+ //
+ // TODO(agl): We might have an issue here where a request for foo.example.com
+ // merges into a SPDY connection to www.example.com, and gets a different
+ // certificate.
+
+ // Perform pin validation if, and only if, all these conditions obtain:
+ //
+ // * a TransportSecurityState object is available;
+ // * the server's certificate chain is valid (or suffers from only a minor
+ // error);
+ // * the server's certificate chain chains up to a known root (i.e. not a
+ // user-installed trust anchor); and
+ // * the build is recent (very old builds should fail open so that users
+ // have some chance to recover).
+ //
+ const CertStatus cert_status = cert_verify_result.cert_status;
+ if (transport_security_state &&
+ (result == OK ||
+ (IsCertificateError(result) && IsCertStatusMinorError(cert_status))) &&
+ cert_verify_result.is_issued_by_known_root &&
+ TransportSecurityState::IsBuildTimely()) {
+ if (transport_security_state->HasPublicKeyPins(host, sni_available)) {
+ if (!transport_security_state->CheckPublicKeyPins(
+ host,
+ sni_available,
+ cert_verify_result.public_key_hashes,
+ pinning_failure_log)) {
+ LOG(ERROR) << *pinning_failure_log;
+ result = ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
+ UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", false);
+ TransportSecurityState::ReportUMAOnPinFailure(host);
+ } else {
+ UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", true);
+ }
+ }
+ }
+#endif
+
if (result <= ERR_FAILED) {
error_details_ = StringPrintf("Failed to verify certificate chain: %s",
ErrorToString(result));
@@ -310,8 +371,12 @@ bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data,
return true;
}
-ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier)
- : cert_verifier_(cert_verifier) {}
+ProofVerifierChromium::ProofVerifierChromium(
+ CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state)
+ : cert_verifier_(cert_verifier),
+ transport_security_state_(transport_security_state) {
+}
ProofVerifierChromium::~ProofVerifierChromium() {
STLDeleteElements(&active_jobs_);
@@ -332,7 +397,10 @@ QuicAsyncStatus ProofVerifierChromium::VerifyProof(
}
const ProofVerifyContextChromium* chromium_context =
reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
- scoped_ptr<Job> job(new Job(this, cert_verifier_, chromium_context->net_log));
+ scoped_ptr<Job> job(new Job(this,
+ cert_verifier_,
+ transport_security_state_,
+ chromium_context->net_log));
QuicAsyncStatus status = job->VerifyProof(hostname, server_config, certs,
signature, error_details,
verify_details, callback);
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index 6f8a231..46632fb 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -22,12 +22,18 @@ namespace net {
class CertVerifier;
class SingleRequestCertVerifier;
+class TransportSecurityState;
// ProofVerifyDetailsChromium is the implementation-specific information that a
// ProofVerifierChromium returns about a certificate verification.
struct ProofVerifyDetailsChromium : public ProofVerifyDetails {
public:
CertVerifyResult cert_verify_result;
+
+ // pinning_failure_log contains a message produced by
+ // TransportSecurityState::DomainState::CheckPublicKeyPins in the event of a
+ // pinning failure. It is a (somewhat) human-readable string.
+ std::string pinning_failure_log;
};
// ProofVerifyContextChromium is the implementation-specific information that a
@@ -44,7 +50,8 @@ struct ProofVerifyContextChromium : public ProofVerifyContext {
// capable of handling multiple simultaneous requests.
class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
public:
- explicit ProofVerifierChromium(CertVerifier* cert_verifier);
+ ProofVerifierChromium(CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state);
virtual ~ProofVerifierChromium();
// ProofVerifier interface
@@ -70,6 +77,8 @@ class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
// Underlying verifier used to verify certificates.
CertVerifier* const cert_verifier_;
+ TransportSecurityState* transport_security_state_;
+
DISALLOW_COPY_AND_ASSIGN(ProofVerifierChromium);
};
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 745692c..40b22cd 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -427,6 +427,7 @@ bool QuicClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
ssl_info->channel_id_sent = false;
ssl_info->security_bits = security_bits;
ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
+ ssl_info->pinning_failure_log = pinning_failure_log_;
return true;
}
@@ -654,12 +655,12 @@ void QuicClientSession::OnProofValid(
void QuicClientSession::OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& verify_details) {
- const CertVerifyResult* cert_verify_result_other =
- &(reinterpret_cast<const ProofVerifyDetailsChromium*>(
- &verify_details))->cert_verify_result;
+ const ProofVerifyDetailsChromium* verify_details_chromium =
+ reinterpret_cast<const ProofVerifyDetailsChromium*>(&verify_details);
CertVerifyResult* result_copy = new CertVerifyResult;
- result_copy->CopyFrom(*cert_verify_result_other);
+ result_copy->CopyFrom(verify_details_chromium->cert_verify_result);
cert_verify_result_.reset(result_copy);
+ pinning_failure_log_ = verify_details_chromium->pinning_failure_log;
}
void QuicClientSession::StartReading() {
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
index 7fbe3db..29281b0 100644
--- a/net/quic/quic_client_session.h
+++ b/net/quic/quic_client_session.h
@@ -227,6 +227,7 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicClientSessionBase {
scoped_refptr<IOBufferWithSize> read_buffer_;
scoped_ptr<QuicServerInfo> server_info_;
scoped_ptr<CertVerifyResult> cert_verify_result_;
+ std::string pinning_failure_log_;
ObserverSet observers_;
StreamRequestQueue stream_requests_;
bool read_pending_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 2fc1b9e..5462d2a 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -450,6 +450,7 @@ QuicStreamFactory::QuicStreamFactory(
ClientSocketFactory* client_socket_factory,
base::WeakPtr<HttpServerProperties> http_server_properties,
CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state,
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
QuicRandom* random_generator,
QuicClock* clock,
@@ -479,7 +480,8 @@ QuicStreamFactory::QuicStreamFactory(
crypto_config_.set_user_agent_id(user_agent_id);
crypto_config_.AddCanonicalSuffix(".c.youtube.com");
crypto_config_.AddCanonicalSuffix(".googlevideo.com");
- crypto_config_.SetProofVerifier(new ProofVerifierChromium(cert_verifier));
+ crypto_config_.SetProofVerifier(
+ new ProofVerifierChromium(cert_verifier, transport_security_state));
base::CPU cpu;
if (cpu.has_aesni() && cpu.has_avx())
crypto_config_.PreferAesGcm();
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index eb82659..b0280e2 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -38,6 +38,7 @@ class QuicRandom;
class QuicServerInfoFactory;
class QuicServerId;
class QuicStreamFactory;
+class TransportSecurityState;
namespace test {
class QuicStreamFactoryPeer;
@@ -91,6 +92,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
ClientSocketFactory* client_socket_factory,
base::WeakPtr<HttpServerProperties> http_server_properties,
CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state,
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
QuicRandom* random_generator,
QuicClock* clock,
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index e88ea4b..ff8e4ce 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -12,6 +12,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+#include "net/http/transport_security_state.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_decrypter.h"
@@ -91,6 +92,7 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<QuicVersion> {
cert_verifier_(CertVerifier::CreateDefault()),
factory_(&host_resolver_, &socket_factory_,
base::WeakPtr<HttpServerProperties>(), cert_verifier_.get(),
+ &transport_security_state_,
&crypto_client_stream_factory_, &random_generator_, clock_,
kDefaultMaxPacketSize, std::string(),
SupportedVersions(GetParam()), true, true, true),
@@ -181,6 +183,7 @@ class QuicStreamFactoryTest : public ::testing::TestWithParam<QuicVersion> {
QuicTestPacketMaker maker_;
MockClock* clock_; // Owned by factory_.
scoped_ptr<CertVerifier> cert_verifier_;
+ TransportSecurityState transport_security_state_;
QuicStreamFactory factory_;
HostPortPair host_port_pair_;
bool is_https_;
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc
index 9deee83..a3c85fb 100644
--- a/net/quic/test_tools/crypto_test_utils_chromium.cc
+++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -10,6 +10,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
+#include "net/http/transport_security_state.h"
#include "net/quic/crypto/proof_source_chromium.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/test/cert_test_util.h"
@@ -21,9 +22,11 @@ namespace test {
class TestProofVerifierChromium : public ProofVerifierChromium {
public:
TestProofVerifierChromium(CertVerifier* cert_verifier,
+ TransportSecurityState* transport_security_state,
const std::string& cert_file)
- : ProofVerifierChromium(cert_verifier),
- cert_verifier_(cert_verifier) {
+ : ProofVerifierChromium(cert_verifier, transport_security_state),
+ cert_verifier_(cert_verifier),
+ transport_security_state_(transport_security_state) {
// Load and install the root for the validated chain.
scoped_refptr<X509Certificate> root_cert =
ImportCertFromFile(GetTestCertsDirectory(), cert_file);
@@ -34,6 +37,7 @@ class TestProofVerifierChromium : public ProofVerifierChromium {
private:
ScopedTestRoot scoped_root_;
scoped_ptr<CertVerifier> cert_verifier_;
+ scoped_ptr<TransportSecurityState> transport_security_state_;
};
// static
@@ -43,8 +47,10 @@ ProofSource* CryptoTestUtils::ProofSourceForTesting() {
// static
ProofVerifier* CryptoTestUtils::ProofVerifierForTesting() {
- TestProofVerifierChromium* proof_verifier = new TestProofVerifierChromium(
- CertVerifier::CreateDefault(), "quic_root.crt");
+ TestProofVerifierChromium* proof_verifier =
+ new TestProofVerifierChromium(CertVerifier::CreateDefault(),
+ new TransportSecurityState,
+ "quic_root.crt");
return proof_verifier;
}