Commit 1a79db29 authored by eranm's avatar eranm Committed by Commit bot

Certificate Transparency: Per-profile CT verification

Prepare for auditing Signed Certificate Timestamps (which are tied to
specific certificates) by having a per-profile CT verification.
That would allow auditing SCTs separately for separate profiles.

BUG=506227

Review URL: https://codereview.chromium.org/1440643002

Cr-Commit-Position: refs/heads/master@{#361311}
parent a59ee43b
......@@ -689,7 +689,7 @@ void IOThread::Init() {
tracked_objects::ScopedTracker tracking_profile8(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"466432 IOThread::InitAsync::CreateLogVerifiers::Start"));
std::vector<scoped_refptr<net::CTLogVerifier>> ct_logs(
std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs(
net::ct::CreateLogVerifiersForKnownLogs());
// Add logs from command line
......@@ -708,7 +708,7 @@ void IOThread::Init() {
std::string ct_public_key_data;
CHECK(base::Base64Decode(log_metadata[1], &ct_public_key_data))
<< "Unable to decode CT public key.";
scoped_refptr<net::CTLogVerifier> external_log_verifier(
scoped_refptr<const net::CTLogVerifier> external_log_verifier(
net::CTLogVerifier::Create(ct_public_key_data, log_description,
log_url));
CHECK(external_log_verifier) << "Unable to parse CT public key.";
......@@ -717,6 +717,8 @@ void IOThread::Init() {
}
}
globals_->ct_logs.assign(ct_logs.begin(), ct_logs.end());
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432
// is fixed.
tracked_objects::ScopedTracker tracking_profile9(
......@@ -730,7 +732,7 @@ void IOThread::Init() {
net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier();
globals_->cert_transparency_verifier.reset(ct_verifier);
// Add built-in logs
ct_verifier->AddLogs(ct_logs);
ct_verifier->AddLogs(globals_->ct_logs);
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432
// is fixed.
......
......@@ -60,7 +60,7 @@ class CertPolicyEnforcer;
class CertVerifier;
class ChannelIDService;
class CookieStore;
class CTVerifier;
class CTLogVerifier;
class FtpTransactionFactory;
class HostMappingRules;
class HostResolver;
......@@ -153,6 +153,7 @@ class IOThread : public content::BrowserThreadDelegate {
// used to enforce pinning for system requests and will only use built-in
// pins.
scoped_ptr<net::TransportSecurityState> transport_security_state;
std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs;
scoped_ptr<net::CTVerifier> cert_transparency_verifier;
scoped_ptr<net::CertPolicyEnforcer> cert_policy_enforcer;
scoped_refptr<net::SSLConfigService> ssl_config_service;
......
......@@ -476,8 +476,7 @@ void ProfileImplIOData::InitializeInternal(
main_context->set_host_resolver(
io_thread_globals->host_resolver.get());
main_context->set_cert_transparency_verifier(
io_thread_globals->cert_transparency_verifier.get());
main_context->set_http_auth_handler_factory(
io_thread_globals->http_auth_handler_factory.get());
......
......@@ -68,6 +68,7 @@
#include "net/base/keygen_handler.h"
#include "net/base/network_quality_estimator.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
#include "net/cookies/canonical_cookie.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
......@@ -1138,6 +1139,12 @@ void ProfileIOData::Init(
profile_params_->new_tab_page_interceptor.release());
}
scoped_ptr<net::MultiLogCTVerifier> ct_verifier(
new net::MultiLogCTVerifier());
ct_verifier->AddLogs(io_thread_globals->ct_logs);
main_request_context_->set_cert_transparency_verifier(ct_verifier.get());
cert_transparency_verifier_ = ct_verifier.Pass();
InitializeInternal(
network_delegate.Pass(), profile_params_.get(),
protocol_handlers, request_interceptors.Pass());
......
......@@ -25,6 +25,7 @@
#include "components/content_settings/core/common/content_settings_types.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "net/cert/ct_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_session.h"
......@@ -542,6 +543,7 @@ class ProfileIOData {
mutable scoped_ptr<net::ProxyService> proxy_service_;
mutable scoped_ptr<net::TransportSecurityState> transport_security_state_;
mutable scoped_ptr<net::CTVerifier> cert_transparency_verifier_;
mutable scoped_ptr<net::HttpServerProperties>
http_server_properties_;
#if defined(OS_CHROMEOS)
......
......@@ -395,7 +395,7 @@ void IOSChromeIOThread::Init() {
globals_->transport_security_state.reset(new net::TransportSecurityState());
std::vector<scoped_refptr<net::CTLogVerifier>> ct_logs(
std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs(
net::ct::CreateLogVerifiersForKnownLogs());
net::MultiLogCTVerifier* ct_verifier = new net::MultiLogCTVerifier();
......
......@@ -28,8 +28,9 @@ int log_ids_compare(const char* log_id, const char* lookup_id) {
} // namespace
#if !defined(OS_NACL)
std::vector<scoped_refptr<CTLogVerifier>> CreateLogVerifiersForKnownLogs() {
std::vector<scoped_refptr<CTLogVerifier>> verifiers;
std::vector<scoped_refptr<const CTLogVerifier>>
CreateLogVerifiersForKnownLogs() {
std::vector<scoped_refptr<const CTLogVerifier>> verifiers;
for (size_t i = 0; i < arraysize(kCTLogList); ++i) {
const CTLogInfo& log(kCTLogList[i]);
base::StringPiece key(log.log_key, log.log_key_length);
......
......@@ -21,7 +21,7 @@ namespace ct {
#if !defined(OS_NACL)
// CreateLogVerifiersForKnownLogs returns a vector of CT logs for all the known
// and trusted logs.
NET_EXPORT std::vector<scoped_refptr<CTLogVerifier>>
NET_EXPORT std::vector<scoped_refptr<const CTLogVerifier>>
CreateLogVerifiersForKnownLogs();
#endif
......
......@@ -11,7 +11,7 @@
namespace net {
// static
scoped_refptr<CTLogVerifier> CTLogVerifier::Create(
scoped_refptr<const CTLogVerifier> CTLogVerifier::Create(
const base::StringPiece& public_key,
const base::StringPiece& description,
const base::StringPiece& url) {
......@@ -35,7 +35,7 @@ CTLogVerifier::CTLogVerifier(const base::StringPiece& description,
}
bool CTLogVerifier::Verify(const ct::LogEntry& entry,
const ct::SignedCertificateTimestamp& sct) {
const ct::SignedCertificateTimestamp& sct) const {
if (sct.log_id != key_id()) {
DVLOG(1) << "SCT is not signed by this log.";
return false;
......@@ -60,7 +60,7 @@ bool CTLogVerifier::Verify(const ct::LogEntry& entry,
}
bool CTLogVerifier::VerifySignedTreeHead(
const ct::SignedTreeHead& signed_tree_head) {
const ct::SignedTreeHead& signed_tree_head) const {
if (!SignatureParametersMatch(signed_tree_head.signature))
return false;
......@@ -74,7 +74,7 @@ bool CTLogVerifier::VerifySignedTreeHead(
}
bool CTLogVerifier::SignatureParametersMatch(
const ct::DigitallySigned& signature) {
const ct::DigitallySigned& signature) const {
if (!signature.SignatureParametersMatch(hash_algorithm_,
signature_algorithm_)) {
DVLOG(1) << "Mismatched hash or signature algorithm. Hash: "
......
......@@ -28,8 +28,12 @@ namespace ct {
struct SignedTreeHead;
} // namespace ct
// Class for verifying Signed Certificate Timestamps (SCTs) provided by a
// specific log (whose identity is provided during construction).
// Class for verifying signatures of a single Certificate Transparency
// log, whose identity is provided during construction.
// Currently can verify Signed Certificate Timestamp (SCT) and Signed
// Tree Head (STH) signatures.
// Immutable: Does not hold any state beyond the log information it was
// initialized with.
class NET_EXPORT CTLogVerifier
: public base::RefCountedThreadSafe<CTLogVerifier> {
public:
......@@ -37,7 +41,7 @@ class NET_EXPORT CTLogVerifier
// using |public_key|, which is a DER-encoded SubjectPublicKeyInfo.
// If |public_key| refers to an unsupported public key, returns NULL.
// |description| is a textual description of the log.
static scoped_refptr<CTLogVerifier> Create(
static scoped_refptr<const CTLogVerifier> Create(
const base::StringPiece& public_key,
const base::StringPiece& description,
const base::StringPiece& url);
......@@ -51,10 +55,10 @@ class NET_EXPORT CTLogVerifier
// Verifies that |sct| contains a valid signature for |entry|.
bool Verify(const ct::LogEntry& entry,
const ct::SignedCertificateTimestamp& sct);
const ct::SignedCertificateTimestamp& sct) const;
// Returns true if the signature in |signed_tree_head| verifies.
bool VerifySignedTreeHead(const ct::SignedTreeHead& signed_tree_head);
bool VerifySignedTreeHead(const ct::SignedTreeHead& signed_tree_head) const;
private:
FRIEND_TEST_ALL_PREFIXES(CTLogVerifierTest, VerifySignature);
......@@ -70,11 +74,11 @@ class NET_EXPORT CTLogVerifier
// that |signature| contains the raw signature data (eg: without any
// DigitallySigned struct encoding).
bool VerifySignature(const base::StringPiece& data_to_sign,
const base::StringPiece& signature);
const base::StringPiece& signature) const;
// Returns true if the signature and hash algorithms in |signature|
// match those of the log
bool SignatureParametersMatch(const ct::DigitallySigned& signature);
bool SignatureParametersMatch(const ct::DigitallySigned& signature) const;
std::string key_id_;
std::string description_;
......
......@@ -117,7 +117,7 @@ bool CTLogVerifier::Init(const base::StringPiece& public_key) {
}
bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign,
const base::StringPiece& signature) {
const base::StringPiece& signature) const {
SECItem sig_data;
sig_data.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
signature.data()));
......
......@@ -86,7 +86,7 @@ bool CTLogVerifier::Init(const base::StringPiece& public_key) {
}
bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign,
const base::StringPiece& signature) {
const base::StringPiece& signature) const {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_);
......
......@@ -27,7 +27,7 @@ class CTLogVerifierTest : public ::testing::Test {
}
protected:
scoped_refptr<CTLogVerifier> log_;
scoped_refptr<const CTLogVerifier> log_;
};
TEST_F(CTLogVerifierTest, VerifiesCertSCT) {
......@@ -95,7 +95,7 @@ TEST_F(CTLogVerifierTest, ExcessDataInPublicKey) {
std::string key = ct::GetTestPublicKey();
key += "extra";
scoped_refptr<CTLogVerifier> log =
scoped_refptr<const CTLogVerifier> log =
CTLogVerifier::Create(key, "testlog", "https://ct.example.com");
EXPECT_FALSE(log);
}
......
......@@ -52,7 +52,7 @@ class CTObjectsExtractorTest : public ::testing::Test {
protected:
CertificateList precert_chain_;
scoped_refptr<X509Certificate> test_cert_;
scoped_refptr<CTLogVerifier> log_;
scoped_refptr<const CTLogVerifier> log_;
};
// Test that an SCT can be extracted and the extracted SCT contains the
......
......@@ -21,6 +21,7 @@ class CTLogVerifier;
class X509Certificate;
// Interface for verifying Signed Certificate Timestamps over a certificate.
// The only known (non-test) implementation currently is MultiLogCTVerifier.
class NET_EXPORT CTVerifier {
public:
class NET_EXPORT Observer {
......@@ -30,6 +31,8 @@ class NET_EXPORT CTVerifier {
// Signed Certificate Timestamp, |cert| is the certificate it applies to.
// The certificate is needed to calculate the hash of the log entry,
// necessary for checking inclusion in the log.
// Note: The observer (whose implementation is expected to exist outside
// net/) may store the observed |cert| and |sct|.
virtual void OnSCTVerified(X509Certificate* cert,
const ct::SignedCertificateTimestamp* sct) = 0;
};
......
......@@ -62,7 +62,7 @@ MultiLogCTVerifier::MultiLogCTVerifier() : observer_(nullptr) {
MultiLogCTVerifier::~MultiLogCTVerifier() { }
void MultiLogCTVerifier::AddLogs(
const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers) {
const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers) {
for (const auto& log_verifier : log_verifiers) {
VLOG(1) << "Adding CT log: " << log_verifier->description();
logs_[log_verifier->key_id()] = log_verifier;
......
......@@ -23,15 +23,14 @@ class CTLogVerifier;
// A Certificate Transparency verifier that can verify Signed Certificate
// Timestamps from multiple logs.
// There should be a global instance of this class and for all known logs,
// AddLog should be called with a CTLogVerifier (which is created from the
// log's public key).
// It must be initialized with a list of logs by calling AddLogs.
class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
public:
MultiLogCTVerifier();
~MultiLogCTVerifier() override;
void AddLogs(const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers);
void AddLogs(
const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers);
// CTVerifier implementation:
int Verify(X509Certificate* cert,
......@@ -61,7 +60,7 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
// Mapping from a log's ID to the verifier for this log.
// A log's ID is the SHA-256 of the log's key, as defined in section 3.2.
// of RFC6962.
std::map<std::string, scoped_refptr<CTLogVerifier>> logs_;
std::map<std::string, scoped_refptr<const CTLogVerifier>> logs_;
Observer* observer_;
......
......@@ -50,7 +50,7 @@ class MockSCTObserver : public CTVerifier::Observer {
class MultiLogCTVerifierTest : public ::testing::Test {
public:
void SetUp() override {
scoped_refptr<CTLogVerifier> log(CTLogVerifier::Create(
scoped_refptr<const CTLogVerifier> log(CTLogVerifier::Create(
ct::GetTestPublicKey(), kLogDescription, "https://ct.example.com"));
ASSERT_TRUE(log);
log_verifiers_.push_back(log);
......@@ -206,7 +206,7 @@ class MultiLogCTVerifierTest : public ::testing::Test {
scoped_ptr<MultiLogCTVerifier> verifier_;
scoped_refptr<X509Certificate> chain_;
scoped_refptr<X509Certificate> embedded_sct_chain_;
std::vector<scoped_refptr<CTLogVerifier>> log_verifiers_;
std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers_;
};
TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment