Index: chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc |
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc |
index a8141ab2f83b49817b58a574860ea5f57ffb2078..776aec22d544b6927ec7c38c0b044a5fe361b12f 100644 |
--- a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc |
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc |
@@ -16,7 +16,6 @@ |
#include "base/values.h" |
#include "chrome/common/chrome_features.h" |
#include "content/public/test/test_browser_thread_bundle.h" |
-#include "net/cert/ct_serialization.h" |
#include "net/cert/signed_certificate_timestamp_and_status.h" |
#include "net/test/cert_test_util.h" |
#include "net/test/test_data_directory.h" |
@@ -111,75 +110,123 @@ |
const std::string& origin_string) { |
if (origin_string == "embedded") |
return net::ct::SignedCertificateTimestamp::SCT_EMBEDDED; |
- if (origin_string == "tls-extension") |
+ if (origin_string == "from-tls-extension") |
return net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION; |
- if (origin_string == "ocsp") |
+ if (origin_string == "from-ocsp-response") |
return net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE; |
NOTREACHED(); |
return net::ct::SignedCertificateTimestamp::SCT_EMBEDDED; |
} |
-// Checks that an SCT |sct| appears with status |status| in |report_list|, a |
-// list of SCTs from an Expect-CT report. |
-::testing::AssertionResult FindSCTInReportList( |
- const scoped_refptr<net::ct::SignedCertificateTimestamp>& expected_sct, |
- net::ct::SCTVerifyStatus expected_status, |
+// Checks that an SCT |sct| appears (with the format determined by |
+// |status|) in |report_list|, a list of SCTs from an Expect CT |
+// report. |status| determines the format in that only certain fields |
+// are reported for certain verify statuses; SCTs from unknown logs |
+// contain very little information, for example, to avoid compromising |
+// privacy. |
+void FindSCTInReportList( |
+ const scoped_refptr<net::ct::SignedCertificateTimestamp>& sct, |
+ net::ct::SCTVerifyStatus status, |
const base::ListValue& report_list) { |
- std::string expected_serialized_sct; |
- net::ct::EncodeSignedCertificateTimestamp(expected_sct, |
- &expected_serialized_sct); |
- |
- for (size_t i = 0; i < report_list.GetSize(); i++) { |
+ bool found = false; |
+ for (size_t i = 0; !found && i < report_list.GetSize(); i++) { |
const base::DictionaryValue* report_sct; |
- if (!report_list.GetDictionary(i, &report_sct)) { |
- return ::testing::AssertionFailure() |
- << "Failed to get dictionary value from report SCT list"; |
- } |
- |
- std::string serialized_sct; |
- EXPECT_TRUE(report_sct->GetString("serialized_sct", &serialized_sct)); |
- std::string decoded_serialized_sct; |
- EXPECT_TRUE(base::Base64Decode(serialized_sct, &decoded_serialized_sct)); |
- if (decoded_serialized_sct != expected_serialized_sct) |
- continue; |
- |
- std::string source; |
- EXPECT_TRUE(report_sct->GetString("source", &source)); |
- EXPECT_EQ(expected_sct->origin, SCTOriginStringToOrigin(source)); |
- |
- std::string report_status; |
- EXPECT_TRUE(report_sct->GetString("status", &report_status)); |
- switch (expected_status) { |
+ ASSERT_TRUE(report_list.GetDictionary(i, &report_sct)); |
+ |
+ std::string origin; |
+ ASSERT_TRUE(report_sct->GetString("origin", &origin)); |
+ |
+ switch (status) { |
case net::ct::SCT_STATUS_LOG_UNKNOWN: |
- EXPECT_EQ("unknown", report_status); |
- break; |
+ // SCTs from unknown logs only have an origin. |
+ EXPECT_FALSE(report_sct->HasKey("sct")); |
+ EXPECT_FALSE(report_sct->HasKey("id")); |
+ if (SCTOriginStringToOrigin(origin) == sct->origin) |
+ found = true; |
+ break; |
+ |
case net::ct::SCT_STATUS_INVALID_SIGNATURE: |
case net::ct::SCT_STATUS_INVALID_TIMESTAMP: { |
- EXPECT_EQ("invalid", report_status); |
+ // Invalid SCTs have a log id and an origin and nothing else. |
+ EXPECT_FALSE(report_sct->HasKey("sct")); |
+ std::string id_base64; |
+ ASSERT_TRUE(report_sct->GetString("id", &id_base64)); |
+ std::string id; |
+ ASSERT_TRUE(base::Base64Decode(id_base64, &id)); |
+ if (SCTOriginStringToOrigin(origin) == sct->origin && id == sct->log_id) |
+ found = true; |
break; |
} |
+ |
case net::ct::SCT_STATUS_OK: { |
- EXPECT_EQ("valid", report_status); |
+ // Valid SCTs have the full SCT. |
+ const base::DictionaryValue* report_sct_object; |
+ ASSERT_TRUE(report_sct->GetDictionary("sct", &report_sct_object)); |
+ int version; |
+ ASSERT_TRUE(report_sct_object->GetInteger("sct_version", &version)); |
+ std::string id_base64; |
+ ASSERT_TRUE(report_sct_object->GetString("id", &id_base64)); |
+ std::string id; |
+ ASSERT_TRUE(base::Base64Decode(id_base64, &id)); |
+ std::string extensions_base64; |
+ ASSERT_TRUE( |
+ report_sct_object->GetString("extensions", &extensions_base64)); |
+ std::string extensions; |
+ ASSERT_TRUE(base::Base64Decode(extensions_base64, &extensions)); |
+ std::string signature_data_base64; |
+ ASSERT_TRUE( |
+ report_sct_object->GetString("signature", &signature_data_base64)); |
+ std::string signature_data; |
+ ASSERT_TRUE(base::Base64Decode(signature_data_base64, &signature_data)); |
+ |
+ if (version == sct->version && |
+ SCTOriginStringToOrigin(origin) == sct->origin && |
+ id == sct->log_id && extensions == sct->extensions && |
+ signature_data == sct->signature.signature_data) { |
+ found = true; |
+ } |
break; |
} |
- case net::ct::SCT_STATUS_NONE: |
+ default: |
NOTREACHED(); |
} |
- return ::testing::AssertionSuccess(); |
- } |
- |
- return ::testing::AssertionFailure() << "Failed to find SCT in report list"; |
+ } |
+ EXPECT_TRUE(found); |
} |
// Checks that all |expected_scts| appears in the given lists of SCTs |
// from an Expect CT report. |
void CheckReportSCTs( |
const net::SignedCertificateTimestampAndStatusList& expected_scts, |
- const base::ListValue& scts) { |
- EXPECT_EQ(expected_scts.size(), scts.GetSize()); |
+ const base::ListValue& unknown_scts, |
+ const base::ListValue& invalid_scts, |
+ const base::ListValue& valid_scts) { |
+ EXPECT_EQ( |
+ expected_scts.size(), |
+ unknown_scts.GetSize() + invalid_scts.GetSize() + valid_scts.GetSize()); |
for (const auto& expected_sct : expected_scts) { |
- ASSERT_TRUE( |
- FindSCTInReportList(expected_sct.sct, expected_sct.status, scts)); |
+ switch (expected_sct.status) { |
+ case net::ct::SCT_STATUS_LOG_UNKNOWN: |
+ ASSERT_NO_FATAL_FAILURE(FindSCTInReportList( |
+ expected_sct.sct, net::ct::SCT_STATUS_LOG_UNKNOWN, unknown_scts)); |
+ break; |
+ case net::ct::SCT_STATUS_INVALID_SIGNATURE: |
+ ASSERT_NO_FATAL_FAILURE(FindSCTInReportList( |
+ expected_sct.sct, net::ct::SCT_STATUS_INVALID_SIGNATURE, |
+ invalid_scts)); |
+ break; |
+ case net::ct::SCT_STATUS_INVALID_TIMESTAMP: |
+ ASSERT_NO_FATAL_FAILURE(FindSCTInReportList( |
+ expected_sct.sct, net::ct::SCT_STATUS_INVALID_TIMESTAMP, |
+ invalid_scts)); |
+ break; |
+ case net::ct::SCT_STATUS_OK: |
+ ASSERT_NO_FATAL_FAILURE(FindSCTInReportList( |
+ expected_sct.sct, net::ct::SCT_STATUS_OK, valid_scts)); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
} |
} |
@@ -195,12 +242,8 @@ |
ASSERT_TRUE(value); |
ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY)); |
- base::DictionaryValue* outer_report_dict; |
- ASSERT_TRUE(value->GetAsDictionary(&outer_report_dict)); |
- |
base::DictionaryValue* report_dict; |
- ASSERT_TRUE( |
- outer_report_dict->GetDictionary("expect-ct-report", &report_dict)); |
+ ASSERT_TRUE(value->GetAsDictionary(&report_dict)); |
std::string report_hostname; |
EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname)); |
@@ -226,11 +269,16 @@ |
ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain( |
ssl_info.cert, *report_validated_certificate_chain)); |
- const base::ListValue* report_scts = nullptr; |
- ASSERT_TRUE(report_dict->GetList("scts", &report_scts)); |
- |
- ASSERT_NO_FATAL_FAILURE( |
- CheckReportSCTs(ssl_info.signed_certificate_timestamps, *report_scts)); |
+ const base::ListValue* report_unknown_scts = nullptr; |
+ ASSERT_TRUE(report_dict->GetList("unknown-scts", &report_unknown_scts)); |
+ const base::ListValue* report_invalid_scts = nullptr; |
+ ASSERT_TRUE(report_dict->GetList("invalid-scts", &report_invalid_scts)); |
+ const base::ListValue* report_valid_scts = nullptr; |
+ ASSERT_TRUE(report_dict->GetList("valid-scts", &report_valid_scts)); |
+ |
+ ASSERT_NO_FATAL_FAILURE(CheckReportSCTs( |
+ ssl_info.signed_certificate_timestamps, *report_unknown_scts, |
+ *report_invalid_scts, *report_valid_scts)); |
} |
// A test network delegate that allows the user to specify a callback to |
@@ -409,47 +457,38 @@ |
// Append a variety of SCTs: two of each possible status, with a |
// mixture of different origins. |
- // The particular value of the log ID doesn't matter; it just has to be the |
- // correct length. |
- const char kTestLogId[] = {0xdf, 0x1c, 0x2e, 0xc1, 0x15, 0x00, 0x94, 0x52, |
- 0x47, 0xa9, 0x61, 0x68, 0x32, 0x5d, 0xdc, 0x5c, |
- 0x79, 0x59, 0xe8, 0xf7, 0xc6, 0xd3, 0x88, 0xfc, |
- 0x00, 0x2e, 0x0b, 0xbd, 0x3f, 0x74, 0xd7, 0x01}; |
- const std::string log_id(kTestLogId, sizeof(kTestLogId)); |
- // The values of the extensions and signature data don't matter |
- // either. However, each SCT has to be unique for the test expectation to be |
- // checked properly in CheckExpectCTReport(), so each SCT has a unique |
- // extensions value to make sure the serialized SCTs are unique. |
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, |
- log_id, "extensions1", "signature1", now, |
+ "unknown_log_id1", "extensions1", "signature1", now, |
net::ct::SCT_STATUS_LOG_UNKNOWN, |
&ssl_info.signed_certificate_timestamps); |
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, |
- log_id, "extensions2", "signature2", now, |
+ "unknown_log_id2", "extensions2", "signature2", now, |
net::ct::SCT_STATUS_LOG_UNKNOWN, |
&ssl_info.signed_certificate_timestamps); |
MakeTestSCTAndStatus( |
- net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, log_id, |
- "extensions3", "signature1", now, net::ct::SCT_STATUS_INVALID_TIMESTAMP, |
+ net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, |
+ "invalid_log_id1", "extensions1", "signature1", now, |
+ net::ct::SCT_STATUS_INVALID_TIMESTAMP, |
&ssl_info.signed_certificate_timestamps); |
MakeTestSCTAndStatus( |
- net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, log_id, |
- "extensions4", "signature1", now, net::ct::SCT_STATUS_INVALID_SIGNATURE, |
+ net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, |
+ "invalid_log_id1", "extensions1", "signature1", now, |
+ net::ct::SCT_STATUS_INVALID_SIGNATURE, |
&ssl_info.signed_certificate_timestamps); |
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, |
- log_id, "extensions5", "signature2", now, |
+ "invalid_log_id2", "extensions2", "signature2", now, |
net::ct::SCT_STATUS_INVALID_SIGNATURE, |
&ssl_info.signed_certificate_timestamps); |
MakeTestSCTAndStatus( |
- net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, log_id, |
- "extensions6", "signature1", now, net::ct::SCT_STATUS_OK, |
+ net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, |
+ "valid_log_id1", "extensions1", "signature1", now, net::ct::SCT_STATUS_OK, |
&ssl_info.signed_certificate_timestamps); |
MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, |
- log_id, "extensions7", "signature2", now, |
+ "valid_log_id2", "extensions2", "signature2", now, |
net::ct::SCT_STATUS_OK, |
&ssl_info.signed_certificate_timestamps); |