Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Unified Diff: components/certificate_transparency/single_tree_tracker_unittest.cc

Issue 2017563002: Add Certificate Transparency logs auditing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Simplified STT with throttling, memory pressure handling Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/certificate_transparency/single_tree_tracker_unittest.cc
diff --git a/components/certificate_transparency/single_tree_tracker_unittest.cc b/components/certificate_transparency/single_tree_tracker_unittest.cc
index 43ea4fd446a7c7c450a8f7b0e0159b95a29bbb22..3da78d1cfd6bc6d858153a4f772df9a0221a303d 100644
--- a/components/certificate_transparency/single_tree_tracker_unittest.cc
+++ b/components/certificate_transparency/single_tree_tracker_unittest.cc
@@ -7,16 +7,28 @@
#include <string>
#include <utility>
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/string_piece.h"
#include "base/test/histogram_tester.h"
+#include "components/certificate_transparency/log_dns_client.h"
+#include "components/certificate_transparency/mock_log_dns_traffic.h"
+#include "crypto/sha2.h"
+#include "net/base/network_change_notifier.h"
#include "net/cert/ct_log_verifier.h"
#include "net/cert/ct_serialization.h"
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/signed_tree_head.h"
#include "net/cert/x509_certificate.h"
+#include "net/dns/dns_client.h"
+#include "net/log/net_log.h"
#include "net/test/ct_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+using net::ct::SignedCertificateTimestamp;
+using net::ct::SignedTreeHead;
+
namespace certificate_transparency {
namespace {
@@ -24,8 +36,8 @@ namespace {
const char kCanCheckForInclusionHistogramName[] =
"Net.CertificateTransparency.CanInclusionCheckSCT";
-bool GetOldSignedTreeHead(net::ct::SignedTreeHead* sth) {
- sth->version = net::ct::SignedTreeHead::V1;
+bool GetOldSignedTreeHead(SignedTreeHead* sth) {
+ sth->version = SignedTreeHead::V1;
sth->timestamp = base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(INT64_C(1348589665525));
sth->tree_size = 12u;
@@ -51,6 +63,23 @@ bool GetOldSignedTreeHead(net::ct::SignedTreeHead* sth) {
return DecodeDigitallySigned(&sp, &(sth->signature)) && sp.empty();
}
+// TODO(eranm): Extract common method to net/test/ct_test_util.h
+std::vector<std::string> GetSampleAuditProof(size_t length) {
+ std::vector<std::string> audit_proof(length);
+ // Makes each node of the audit proof different, so that tests are able to
+ // confirm that the audit proof is reconstructed in the correct order.
+ for (size_t i = 0; i < length; ++i) {
+ std::string node(crypto::kSHA256Length, '\0');
+ // Each node is 32 bytes, with each byte having a different value.
+ for (size_t j = 0; j < crypto::kSHA256Length; ++j) {
+ node[j] = static_cast<char>((-127 + i + j) % 128);
+ }
+ audit_proof[i].assign(std::move(node));
+ }
+
+ return audit_proof;
+}
+
} // namespace
class SingleTreeTrackerTest : public ::testing::Test {
@@ -62,19 +91,33 @@ class SingleTreeTrackerTest : public ::testing::Test {
ASSERT_TRUE(log_);
ASSERT_EQ(log_->key_id(), net::ct::GetTestPublicKeyId());
- tree_tracker_.reset(new SingleTreeTracker(log_));
+ net_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock());
+
+ std::unique_ptr<net::DnsClient> dns_client =
+ net::DnsClient::CreateClient(net_log_.net_log());
+
+ log_dns_client_ =
+ base::MakeUnique<LogDnsClient>(std::move(dns_client), net_log_);
+
+ tree_tracker_.reset(new SingleTreeTracker(log_, log_dns_client_.get()));
+
const std::string der_test_cert(net::ct::GetDerEncodedX509Cert());
chain_ = net::X509Certificate::CreateFromBytes(der_test_cert.data(),
der_test_cert.length());
ASSERT_TRUE(chain_.get());
net::ct::GetX509CertSCT(&cert_sct_);
+ cert_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE;
}
protected:
+ base::MessageLoopForIO message_loop_;
scoped_refptr<const net::CTLogVerifier> log_;
+ std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier_;
+ std::unique_ptr<LogDnsClient> log_dns_client_;
std::unique_ptr<SingleTreeTracker> tree_tracker_;
scoped_refptr<net::X509Certificate> chain_;
- scoped_refptr<net::ct::SignedCertificateTimestamp> cert_sct_;
+ scoped_refptr<SignedCertificateTimestamp> cert_sct_;
+ net::BoundNetLog net_log_;
};
// Test that an SCT is classified as pending for a newer STH if the
@@ -104,7 +147,7 @@ TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTNoSTH) {
TEST_F(SingleTreeTrackerTest, CorrectlyClassifiesUnobservedSCTWithRecentSTH) {
base::HistogramTester histograms;
// Provide an STH to the tree_tracker_.
- net::ct::SignedTreeHead sth;
+ SignedTreeHead sth;
net::ct::GetSampleSignedTreeHead(&sth);
tree_tracker_->NewSTHObserved(sth);
@@ -143,7 +186,7 @@ TEST_F(SingleTreeTrackerTest, CorrectlyUpdatesSCTStatusOnNewSTH) {
histograms.ExpectTotalCount(kCanCheckForInclusionHistogramName, 1);
// Provide with a fresh STH
- net::ct::SignedTreeHead sth;
+ SignedTreeHead sth;
net::ct::GetSampleSignedTreeHead(&sth);
tree_tracker_->NewSTHObserved(sth);
@@ -168,7 +211,7 @@ TEST_F(SingleTreeTrackerTest, DoesNotUpdatesSCTStatusOnOldSTH) {
tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
// Provide an old STH for the same log.
- net::ct::SignedTreeHead sth;
+ SignedTreeHead sth;
GetOldSignedTreeHead(&sth);
tree_tracker_->NewSTHObserved(sth);
@@ -184,7 +227,7 @@ TEST_F(SingleTreeTrackerTest, DoesNotUpdatesSCTStatusOnOldSTH) {
TEST_F(SingleTreeTrackerTest, LogsUMAForNewSCTAndOldSTH) {
base::HistogramTester histograms;
// Provide an old STH for the same log.
- net::ct::SignedTreeHead sth;
+ SignedTreeHead sth;
GetOldSignedTreeHead(&sth);
tree_tracker_->NewSTHObserved(sth);
@@ -199,4 +242,118 @@ TEST_F(SingleTreeTrackerTest, LogsUMAForNewSCTAndOldSTH) {
histograms.ExpectBucketCount(kCanCheckForInclusionHistogramName, 1, 1);
}
+// Test that an entry transitions to the "not found" state if the LogDnsClient
+// fails to get a leaf index.
+TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterLeafIndexFetchFailure) {
+ MockLogDnsTraffic mock_dns;
+ mock_dns.InitializeDnsConfig();
+ mock_dns.ExpectRequestAndSocketError(
+ "ASTEWZDDDMBHBVWSAQLIZUSNBMSLMIQMDZNH56TBNXWRMW5XALTA.hash.dns.example."
+ "com",
+ net::Error::ERR_FAILED);
+
+ log_dns_client_ =
+ base::MakeUnique<LogDnsClient>(mock_dns.CreateDnsClient(), net_log_);
+ tree_tracker_.reset(new SingleTreeTracker(log_, log_dns_client_.get()));
+
+ tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get());
+ EXPECT_EQ(
+ SingleTreeTracker::SCT_PENDING_NEWER_STH,
+ tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
+
+ // Provide with a fresh STH
+ SignedTreeHead sth;
+ net::ct::GetSampleSignedTreeHead(&sth);
+ tree_tracker_->NewSTHObserved(sth);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(
+ SingleTreeTracker::SCT_NOT_OBSERVED,
+ tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
+}
+
+// Test that an entry transitions to the "not found" state if the LogDnsClient
+// succeeds to get a leaf index but fails to get an inclusion proof.
+TEST_F(SingleTreeTrackerTest, TestEntryNotPendingAfterInclusionCheckFailure) {
+ MockLogDnsTraffic mock_dns;
+ mock_dns.InitializeDnsConfig();
+ mock_dns.ExpectLeafIndexRequestAndResponse(
+ "ASTEWZDDDMBHBVWSAQLIZUSNBMSLMIQMDZNH56TBNXWRMW5XALTA.hash.dns.example."
+ "com",
+ "12");
+ mock_dns.ExpectRequestAndSocketError("0.12.21.tree.dns.example.com",
+ net::Error::ERR_FAILED);
+
+ log_dns_client_ =
+ base::MakeUnique<LogDnsClient>(mock_dns.CreateDnsClient(), net_log_);
+ tree_tracker_.reset(new SingleTreeTracker(log_, log_dns_client_.get()));
+
+ tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get());
+ EXPECT_EQ(
+ SingleTreeTracker::SCT_PENDING_NEWER_STH,
+ tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
+
+ // Provide with a fresh STH
+ SignedTreeHead sth;
+ net::ct::GetSampleSignedTreeHead(&sth);
+ tree_tracker_->NewSTHObserved(sth);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(
+ SingleTreeTracker::SCT_NOT_OBSERVED,
+ tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
+}
+
+// Test that an entry transitions to the "included" state if the LogDnsClient
+// succeeds to get a leaf index and an inclusion proof.
+TEST_F(SingleTreeTrackerTest, TestEntryIncludedAfterInclusionCheckSuccess) {
+ const std::vector<std::string> audit_proof = GetSampleAuditProof(3);
+
+ MockLogDnsTraffic mock_dns;
+ mock_dns.InitializeDnsConfig();
+ mock_dns.ExpectLeafIndexRequestAndResponse(
+ "ASTEWZDDDMBHBVWSAQLIZUSNBMSLMIQMDZNH56TBNXWRMW5XALTA.hash.dns.example."
+ "com",
+ "12");
+ mock_dns.ExpectAuditProofRequestAndResponse("0.12.21.tree.dns.example.com",
+ audit_proof.begin(),
+ audit_proof.begin() + 2);
+
+ log_dns_client_ =
+ base::MakeUnique<LogDnsClient>(mock_dns.CreateDnsClient(), net_log_);
+ tree_tracker_.reset(new SingleTreeTracker(log_, log_dns_client_.get()));
+
+ tree_tracker_->OnSCTVerified(chain_.get(), cert_sct_.get());
+ EXPECT_EQ(
+ SingleTreeTracker::SCT_PENDING_NEWER_STH,
+ tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
+
+ // Provide with a fresh STH
+ SignedTreeHead sth;
+ net::ct::GetSampleSignedTreeHead(&sth);
+ tree_tracker_->NewSTHObserved(sth);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(
+ SingleTreeTracker::SCT_INCLUDED_IN_LOG,
+ tree_tracker_->GetLogEntryInclusionStatus(chain_.get(), cert_sct_.get()));
+}
+
+// Test that pending entries transition states correctly according to the
+// STHs provided:
+// * Start without an STH.
+// * Add a collection of entries with mixed timestamps (i.e. SCTs not added
+// in the order of their timestamps).
+// * Provide an STH that covers some of the entries, test these are audited.
+// * Provide another STH that covers more of the entries, test that the entries
+// already audited are not audited again and that those that need to be
+// audited are audited, while those that are not covered by that STH are
+// not audited.
+
+// Test that if a request for an entry is throttled, it remains in a
+// pending state.
+
+// Test that if one entry is throttled and the next one audited, the first,
+// throttled, entry is also audited as a follow-up.
+
} // namespace certificate_transparency

Powered by Google App Engine
This is Rietveld 408576698