summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreranm <eranm@chromium.org>2015-07-02 13:05:15 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-02 20:05:52 +0000
commitb68c27e0dfd59fe943aba065d724fcb8b565a679 (patch)
tree0c0a5367f155f2439f6d70a1db0440d6351d3f56
parentee74ae9a813bd6ab3556cbe0f9a3e9a33809a438 (diff)
downloadchromium_src-b68c27e0dfd59fe943aba065d724fcb8b565a679.zip
chromium_src-b68c27e0dfd59fe943aba065d724fcb8b565a679.tar.gz
chromium_src-b68c27e0dfd59fe943aba065d724fcb8b565a679.tar.bz2
Certificate Transparency: Add observer for Signed Certificate Timestamps
This will allow hooking a monitor that will check inclusion of certificates that were accompanied by SCTs in CT logs. BUG=506227 Review URL: https://codereview.chromium.org/1216153010 Cr-Commit-Position: refs/heads/master@{#337250}
-rw-r--r--net/cert/ct_verifier.h21
-rw-r--r--net/cert/multi_log_ct_verifier.cc40
-rw-r--r--net/cert/multi_log_ct_verifier.h13
-rw-r--r--net/cert/multi_log_ct_verifier_unittest.cc32
-rw-r--r--net/socket/ssl_client_socket_unittest.cc1
5 files changed, 83 insertions, 24 deletions
diff --git a/net/cert/ct_verifier.h b/net/cert/ct_verifier.h
index 290a047..4063104 100644
--- a/net/cert/ct_verifier.h
+++ b/net/cert/ct_verifier.h
@@ -5,20 +5,35 @@
#ifndef NET_CERT_CT_VERIFIER_H_
#define NET_CERT_CT_VERIFIER_H_
+#include <string>
+
#include "net/base/net_export.h"
namespace net {
namespace ct {
struct CTVerifyResult;
+struct SignedCertificateTimestamp;
} // namespace ct
class BoundNetLog;
+class CTLogVerifier;
class X509Certificate;
// Interface for verifying Signed Certificate Timestamps over a certificate.
class NET_EXPORT CTVerifier {
public:
+ class NET_EXPORT Observer {
+ public:
+ // Called for each Signed Certificate Timestamp from a known log that vas
+ // verified successfully (i.e. the signature verifies). |sct| is the
+ // 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.
+ virtual void OnSCTVerified(X509Certificate* cert,
+ const ct::SignedCertificateTimestamp* sct) = 0;
+ };
+
virtual ~CTVerifier() {}
// Verifies SCTs embedded in the certificate itself, SCTs embedded in a
@@ -36,6 +51,12 @@ class NET_EXPORT CTVerifier {
const std::string& sct_list_from_tls_extension,
ct::CTVerifyResult* result,
const BoundNetLog& net_log) = 0;
+
+ // Registers |observer| to receive notifications of validated SCTs. Does not
+ // take ownership of the observer as the observer may be performing
+ // URLRequests which have to be cancelled before this object is destroyed.
+ // Setting |observer| to nullptr has the effect of stopping all notifications.
+ virtual void SetObserver(Observer* observer) = 0;
};
} // namespace net
diff --git a/net/cert/multi_log_ct_verifier.cc b/net/cert/multi_log_ct_verifier.cc
index 2de8fcf..7e421b2 100644
--- a/net/cert/multi_log_ct_verifier.cc
+++ b/net/cert/multi_log_ct_verifier.cc
@@ -56,7 +56,8 @@ void LogNumSCTsToUMA(const ct::CTVerifyResult& result) {
} // namespace
-MultiLogCTVerifier::MultiLogCTVerifier() { }
+MultiLogCTVerifier::MultiLogCTVerifier() : observer_(nullptr) {
+}
MultiLogCTVerifier::~MultiLogCTVerifier() { }
@@ -68,6 +69,10 @@ void MultiLogCTVerifier::AddLogs(
}
}
+void MultiLogCTVerifier::SetObserver(Observer* observer) {
+ observer_ = observer;
+}
+
int MultiLogCTVerifier::Verify(
X509Certificate* cert,
const std::string& stapled_ocsp_response,
@@ -91,15 +96,11 @@ int MultiLogCTVerifier::Verify(
ct::LogEntry precert_entry;
has_verified_scts =
- ct::GetPrecertLogEntry(
- cert->os_cert_handle(),
- cert->GetIntermediateCertificates().front(),
- &precert_entry) &&
- VerifySCTs(
- embedded_scts,
- precert_entry,
- ct::SignedCertificateTimestamp::SCT_EMBEDDED,
- result);
+ ct::GetPrecertLogEntry(cert->os_cert_handle(),
+ cert->GetIntermediateCertificates().front(),
+ &precert_entry) &&
+ VerifySCTs(embedded_scts, precert_entry,
+ ct::SignedCertificateTimestamp::SCT_EMBEDDED, cert, result);
}
std::string sct_list_from_ocsp;
@@ -123,16 +124,12 @@ int MultiLogCTVerifier::Verify(
ct::LogEntry x509_entry;
if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) {
has_verified_scts |= VerifySCTs(
- sct_list_from_ocsp,
- x509_entry,
- ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE,
- result);
+ sct_list_from_ocsp, x509_entry,
+ ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, cert, result);
has_verified_scts |= VerifySCTs(
- sct_list_from_tls_extension,
- x509_entry,
- ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
- result);
+ sct_list_from_tls_extension, x509_entry,
+ ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, cert, result);
}
NetLog::ParametersCallback net_log_checked_callback =
@@ -154,6 +151,7 @@ bool MultiLogCTVerifier::VerifySCTs(
const std::string& encoded_sct_list,
const ct::LogEntry& expected_entry,
ct::SignedCertificateTimestamp::Origin origin,
+ X509Certificate* cert,
ct::CTVerifyResult* result) {
if (logs_.empty())
return false;
@@ -178,7 +176,7 @@ bool MultiLogCTVerifier::VerifySCTs(
}
decoded_sct->origin = origin;
- verified |= VerifySingleSCT(decoded_sct, expected_entry, result);
+ verified |= VerifySingleSCT(decoded_sct, expected_entry, cert, result);
}
return verified;
@@ -187,8 +185,8 @@ bool MultiLogCTVerifier::VerifySCTs(
bool MultiLogCTVerifier::VerifySingleSCT(
scoped_refptr<ct::SignedCertificateTimestamp> sct,
const ct::LogEntry& expected_entry,
+ X509Certificate* cert,
ct::CTVerifyResult* result) {
-
// Assume this SCT is untrusted until proven otherwise.
const auto& it = logs_.find(sct->log_id);
if (it == logs_.end()) {
@@ -217,6 +215,8 @@ bool MultiLogCTVerifier::VerifySingleSCT(
LogSCTStatusToUMA(ct::SCT_STATUS_OK);
result->verified_scts.push_back(sct);
+ if (observer_)
+ observer_->OnSCTVerified(cert, sct.get());
return true;
}
diff --git a/net/cert/multi_log_ct_verifier.h b/net/cert/multi_log_ct_verifier.h
index b18b680..4546606 100644
--- a/net/cert/multi_log_ct_verifier.h
+++ b/net/cert/multi_log_ct_verifier.h
@@ -40,6 +40,8 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
ct::CTVerifyResult* result,
const BoundNetLog& net_log) override;
+ void SetObserver(Observer* observer) override;
+
private:
// Verify a list of SCTs from |encoded_sct_list| over |expected_entry|,
// placing the verification results in |result|. The SCTs in the list
@@ -47,19 +49,22 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
bool VerifySCTs(const std::string& encoded_sct_list,
const ct::LogEntry& expected_entry,
ct::SignedCertificateTimestamp::Origin origin,
+ X509Certificate* cert,
ct::CTVerifyResult* result);
// Verifies a single, parsed SCT against all logs.
- bool VerifySingleSCT(
- scoped_refptr<ct::SignedCertificateTimestamp> sct,
- const ct::LogEntry& expected_entry,
- ct::CTVerifyResult* result);
+ bool VerifySingleSCT(scoped_refptr<ct::SignedCertificateTimestamp> sct,
+ const ct::LogEntry& expected_entry,
+ X509Certificate* cert,
+ ct::CTVerifyResult* result);
// 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_;
+ Observer* observer_;
+
DISALLOW_COPY_AND_ASSIGN(MultiLogCTVerifier);
};
diff --git a/net/cert/multi_log_ct_verifier_unittest.cc b/net/cert/multi_log_ct_verifier_unittest.cc
index 104335a..a994eb2 100644
--- a/net/cert/multi_log_ct_verifier_unittest.cc
+++ b/net/cert/multi_log_ct_verifier_unittest.cc
@@ -26,8 +26,12 @@
#include "net/log/test_net_log_entry.h"
#include "net/test/cert_test_util.h"
#include "net/test/ct_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using testing::_;
+using testing::Mock;
+
namespace net {
namespace {
@@ -36,6 +40,13 @@ const char kLogDescription[] = "somelog";
const char kSCTCountHistogram[] =
"Net.CertificateTransparency.SCTsPerConnection";
+class MockSCTObserver : public CTVerifier::Observer {
+ public:
+ MOCK_METHOD2(OnSCTVerified,
+ void(X509Certificate* cert,
+ const ct::SignedCertificateTimestamp* sct));
+};
+
class MultiLogCTVerifierTest : public ::testing::Test {
public:
void SetUp() override {
@@ -301,6 +312,27 @@ TEST_F(MultiLogCTVerifierTest, CountsZeroSCTsCorrectly) {
GetValueFromHistogram(kSCTCountHistogram, 0));
}
+TEST_F(MultiLogCTVerifierTest, NotifiesOfValidSCT) {
+ MockSCTObserver observer;
+ verifier_->SetObserver(&observer);
+
+ EXPECT_CALL(observer, OnSCTVerified(embedded_sct_chain_.get(), _));
+ ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_));
+}
+
+TEST_F(MultiLogCTVerifierTest, StopsNotifyingCorrectly) {
+ MockSCTObserver observer;
+ verifier_->SetObserver(&observer);
+
+ EXPECT_CALL(observer, OnSCTVerified(embedded_sct_chain_.get(), _)).Times(1);
+ ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_));
+ Mock::VerifyAndClearExpectations(&observer);
+
+ EXPECT_CALL(observer, OnSCTVerified(embedded_sct_chain_.get(), _)).Times(0);
+ verifier_->SetObserver(nullptr);
+ ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_));
+}
+
} // namespace
} // namespace net
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index c93473f..8eec657 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -683,6 +683,7 @@ class MockCTVerifier : public CTVerifier {
const std::string&,
ct::CTVerifyResult*,
const BoundNetLog&));
+ MOCK_METHOD1(SetObserver, void(CTVerifier::Observer*));
};
class SSLClientSocketTest : public PlatformTest {