diff options
Diffstat (limited to 'chromium/net/cert/multi_log_ct_verifier_unittest.cc')
-rw-r--r-- | chromium/net/cert/multi_log_ct_verifier_unittest.cc | 174 |
1 files changed, 150 insertions, 24 deletions
diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc index b1d1aa889e8..c2ae25e3073 100644 --- a/chromium/net/cert/multi_log_ct_verifier_unittest.cc +++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc @@ -8,6 +8,10 @@ #include "base/file_util.h" #include "base/files/file_path.h" +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_samples.h" +#include "base/metrics/statistics_recorder.h" +#include "base/values.h" #include "net/base/capturing_net_log.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" @@ -16,6 +20,7 @@ #include "net/cert/ct_serialization.h" #include "net/cert/ct_verify_result.h" #include "net/cert/pem_tokenizer.h" +#include "net/cert/sct_status_flags.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/cert/x509_certificate.h" #include "net/test/cert_test_util.h" @@ -27,6 +32,8 @@ namespace net { namespace { const char kLogDescription[] = "somelog"; +const char kSCTCountHistogram[] = + "Net.CertificateTransparency.SCTsPerConnection"; class MultiLogCTVerifierTest : public ::testing::Test { public: @@ -42,6 +49,12 @@ class MultiLogCTVerifierTest : public ::testing::Test { der_test_cert.data(), der_test_cert.length()); ASSERT_TRUE(chain_); + + embedded_sct_chain_ = + CreateCertificateChainFromFile(GetTestCertsDirectory(), + "ct-test-embedded-cert.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_TRUE(embedded_sct_chain_); } bool CheckForSingleVerifiedSCTInResult(const ct::CTVerifyResult& result) { @@ -64,45 +77,121 @@ class MultiLogCTVerifierTest : public ::testing::Test { if (entries.size() != 2) return false; - const CapturingNetLog::CapturedEntry& received(entries[0]); + const CapturingNetLog::CapturedEntry& received = entries[0]; std::string embedded_scts; if (!received.GetStringValue("embedded_scts", &embedded_scts)) return false; if (embedded_scts.empty()) return false; - //XXX(eranm): entries[1] is the NetLog message with the checked SCTs. - //When CapturedEntry has methods to get a dictionary, rather than just - //a string, add more checks here. + const CapturingNetLog::CapturedEntry& parsed = entries[1]; + base::ListValue* verified_scts; + if (!parsed.GetListValue("verified_scts", &verified_scts) || + verified_scts->GetSize() != 1) { + return false; + } + + base::DictionaryValue* the_sct; + if (!verified_scts->GetDictionary(0, &the_sct)) + return false; + + std::string origin; + if (!the_sct->GetString("origin", &origin)) + return false; + if (origin != "embedded_in_certificate") + return false; + + base::ListValue* other_scts; + if (!parsed.GetListValue("invalid_scts", &other_scts) || + !other_scts->empty()) { + return false; + } + + if (!parsed.GetListValue("unknown_logs_scts", &other_scts) || + !other_scts->empty()) { + return false; + } return true; } + std::string GetSCTListWithInvalidSCT() { + std::string sct(ct::GetTestSignedCertificateTimestamp()); + + // Change a byte inside the Log ID part of the SCT so it does + // not match the log used in the tests + sct[15] = 't'; + + std::string sct_list; + ct::EncodeSCTListForTesting(sct, &sct_list); + return sct_list; + } + + bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain, + const BoundNetLog& bound_net_log, + ct::CTVerifyResult* result) { + return verifier_->Verify( + chain, std::string(), std::string(), result, bound_net_log) == + OK; + } + + bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain) { + ct::CTVerifyResult result; + CapturingNetLog net_log; + BoundNetLog bound_net_log = + BoundNetLog::Make(&net_log, NetLog::SOURCE_CONNECT_JOB); + + return verifier_->Verify( + chain, std::string(), std::string(), &result, bound_net_log) == + OK; + } + bool CheckPrecertificateVerification(scoped_refptr<X509Certificate> chain) { ct::CTVerifyResult result; CapturingNetLog net_log; BoundNetLog bound_net_log = BoundNetLog::Make(&net_log, NetLog::SOURCE_CONNECT_JOB); - return (verifier_->Verify(chain, std::string(), std::string(), &result, - bound_net_log) == OK) && - CheckForSingleVerifiedSCTInResult(result) && - CheckForSCTOrigin( - result, ct::SignedCertificateTimestamp::SCT_EMBEDDED) && - CheckForEmbeddedSCTInNetLog(net_log); + return (VerifySinglePrecertificateChain(chain, bound_net_log, &result) && + CheckForSingleVerifiedSCTInResult(result) && + CheckForSCTOrigin(result, + ct::SignedCertificateTimestamp::SCT_EMBEDDED) && + CheckForEmbeddedSCTInNetLog(net_log)); + } + + // Histogram-related helper methods + int GetValueFromHistogram(std::string histogram_name, int sample_index) { + base::Histogram* histogram = static_cast<base::Histogram*>( + base::StatisticsRecorder::FindHistogram(histogram_name)); + + if (histogram == NULL) + return 0; + + scoped_ptr<base::HistogramSamples> samples = histogram->SnapshotSamples(); + return samples->GetCount(sample_index); + } + + int NumConnectionsWithSingleSCT() { + return GetValueFromHistogram(kSCTCountHistogram, 1); + } + + int NumEmbeddedSCTsInHistogram() { + return GetValueFromHistogram("Net.CertificateTransparency.SCTOrigin", + ct::SignedCertificateTimestamp::SCT_EMBEDDED); + } + + int NumValidSCTsInStatusHistogram() { + return GetValueFromHistogram("Net.CertificateTransparency.SCTStatus", + ct::SCT_STATUS_OK); } protected: scoped_ptr<MultiLogCTVerifier> verifier_; scoped_refptr<X509Certificate> chain_; + scoped_refptr<X509Certificate> embedded_sct_chain_; }; TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT) { - scoped_refptr<X509Certificate> chain( - CreateCertificateChainFromFile(GetTestCertsDirectory(), - "ct-test-embedded-cert.pem", - X509Certificate::FORMAT_AUTO)); - ASSERT_TRUE(chain); - ASSERT_TRUE(CheckPrecertificateVerification(chain)); + ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_)); } TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithPreCA) { @@ -151,21 +240,58 @@ TEST_F(MultiLogCTVerifierTest, TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog) { - std::string sct(ct::GetTestSignedCertificateTimestamp()); + std::string sct_list = GetSCTListWithInvalidSCT(); + ct::CTVerifyResult result; - // Change a byte inside the Log ID part of the SCT so it does - // not match the log used in the tests - sct[15] = 't'; + EXPECT_NE(OK, + verifier_->Verify( + chain_, std::string(), sct_list, &result, BoundNetLog())); + EXPECT_EQ(1U, result.unknown_logs_scts.size()); + EXPECT_EQ("", result.unknown_logs_scts[0]->log_description); +} - std::string sct_list; - ASSERT_TRUE(ct::EncodeSCTListForTesting(sct, &sct_list)); +TEST_F(MultiLogCTVerifierTest, CountsValidSCTsInStatusHistogram) { + int num_valid_scts = NumValidSCTsInStatusHistogram(); + + ASSERT_TRUE(VerifySinglePrecertificateChain(embedded_sct_chain_)); + + EXPECT_EQ(num_valid_scts + 1, NumValidSCTsInStatusHistogram()); +} +TEST_F(MultiLogCTVerifierTest, CountsInvalidSCTsInStatusHistogram) { + std::string sct_list = GetSCTListWithInvalidSCT(); ct::CTVerifyResult result; + int num_valid_scts = NumValidSCTsInStatusHistogram(); + int num_invalid_scts = GetValueFromHistogram( + "Net.CertificateTransparency.SCTStatus", ct::SCT_STATUS_LOG_UNKNOWN); + EXPECT_NE(OK, verifier_->Verify(chain_, std::string(), sct_list, &result, BoundNetLog())); - EXPECT_EQ(1U, result.unknown_logs_scts.size()); - EXPECT_EQ("", result.unknown_logs_scts[0]->log_description); + + ASSERT_EQ(num_valid_scts, NumValidSCTsInStatusHistogram()); + ASSERT_EQ(num_invalid_scts + 1, + GetValueFromHistogram("Net.CertificateTransparency.SCTStatus", + ct::SCT_STATUS_LOG_UNKNOWN)); +} + +TEST_F(MultiLogCTVerifierTest, CountsSingleEmbeddedSCTInConnectionsHistogram) { + int old_sct_count = NumConnectionsWithSingleSCT(); + ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_)); + EXPECT_EQ(old_sct_count + 1, NumConnectionsWithSingleSCT()); +} + +TEST_F(MultiLogCTVerifierTest, CountsSingleEmbeddedSCTInOriginsHistogram) { + int old_embedded_count = NumEmbeddedSCTsInHistogram(); + ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_)); + EXPECT_EQ(old_embedded_count + 1, NumEmbeddedSCTsInHistogram()); +} + +TEST_F(MultiLogCTVerifierTest, CountsZeroSCTsCorrectly) { + int connections_without_scts = GetValueFromHistogram(kSCTCountHistogram, 0); + EXPECT_FALSE(VerifySinglePrecertificateChain(chain_)); + ASSERT_EQ(connections_without_scts + 1, + GetValueFromHistogram(kSCTCountHistogram, 0)); } } // namespace |