chrome_ct_policy_enforcer_unittest.cc 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/certificate_transparency/chrome_ct_policy_enforcer.h"
  5. #include <memory>
  6. #include <string>
  7. #include <utility>
  8. #include "base/build_time.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/test/scoped_feature_list.h"
  11. #include "base/test/simple_test_clock.h"
  12. #include "base/time/time.h"
  13. #include "base/version.h"
  14. #include "components/certificate_transparency/ct_known_logs.h"
  15. #include "crypto/rsa_private_key.h"
  16. #include "crypto/sha2.h"
  17. #include "net/cert/ct_policy_status.h"
  18. #include "net/cert/x509_certificate.h"
  19. #include "net/cert/x509_util.h"
  20. #include "net/log/net_log_with_source.h"
  21. #include "net/test/cert_test_util.h"
  22. #include "net/test/ct_test_util.h"
  23. #include "net/test/test_data_directory.h"
  24. #include "testing/gmock/include/gmock/gmock.h"
  25. #include "testing/gtest/include/gtest/gtest.h"
  26. using net::ct::CTPolicyCompliance;
  27. using net::ct::SCTList;
  28. using net::ct::SignedCertificateTimestamp;
  29. using net::NetLogWithSource;
  30. using net::X509Certificate;
  31. namespace certificate_transparency {
  32. namespace {
  33. // A log ID that for test purposes counts as a valid Google operated log.
  34. const char kTestGoogleLogID[] =
  35. "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc\x71\x51"
  36. "\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\xfb\xc4";
  37. static_assert(std::size(kTestGoogleLogID) - 1 == crypto::kSHA256Length,
  38. "Incorrect log ID length.");
  39. } // namespace
  40. class ChromeCTPolicyEnforcerTest : public ::testing::Test {
  41. public:
  42. void SetUp() override {
  43. auto enforcer = std::make_unique<ChromeCTPolicyEnforcer>(
  44. base::Time::Now(), GetDisqualifiedLogs(), GetLogsOperatedByGoogle(),
  45. std::map<std::string, OperatorHistoryEntry>());
  46. enforcer->SetClockForTesting(&clock_);
  47. policy_enforcer_ = std::move(enforcer);
  48. std::string der_test_cert(net::ct::GetDerEncodedX509Cert());
  49. chain_ = X509Certificate::CreateFromBytes(
  50. base::as_bytes(base::make_span(der_test_cert)));
  51. ASSERT_TRUE(chain_.get());
  52. google_log_id_ = std::string(kTestGoogleLogID, crypto::kSHA256Length);
  53. policy_enforcer_->SetValidGoogleLogForTesting(google_log_id_);
  54. non_google_log_id_.assign(crypto::kSHA256Length, 1);
  55. clock_.SetNow(base::Time::Now());
  56. }
  57. void FillListWithSCTsOfOrigin(
  58. SignedCertificateTimestamp::Origin desired_origin,
  59. size_t num_scts,
  60. const std::vector<std::string>& desired_log_keys,
  61. bool timestamp_past_2022_policy_date,
  62. SCTList* verified_scts) {
  63. for (size_t i = 0; i < num_scts; ++i) {
  64. scoped_refptr<SignedCertificateTimestamp> sct(
  65. new SignedCertificateTimestamp());
  66. sct->origin = desired_origin;
  67. if (i < desired_log_keys.size())
  68. sct->log_id = desired_log_keys[i];
  69. else
  70. sct->log_id = std::string(crypto::kSHA256Length, static_cast<char>(i));
  71. if (timestamp_past_2022_policy_date) {
  72. EXPECT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 15, 0, 0, 0, 0},
  73. &sct->timestamp));
  74. } else {
  75. EXPECT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 14, 0, 0, 0, 0},
  76. &sct->timestamp));
  77. }
  78. verified_scts->push_back(sct);
  79. }
  80. }
  81. void AddDisqualifiedLogSCT(SignedCertificateTimestamp::Origin desired_origin,
  82. bool timestamp_after_disqualification_date,
  83. bool timestamp_past_2022_policy_date,
  84. SCTList* verified_scts) {
  85. static const char kTestRetiredLogID[] =
  86. "\xcd\xb5\x17\x9b\x7f\xc1\xc0\x46\xfe\xea\x31\x13\x6a\x3f\x8f\x00\x2e"
  87. "\x61\x82\xfa\xf8\x89\x6f\xec\xc8\xb2\xf5\xb5\xab\x60\x49\x00";
  88. static_assert(std::size(kTestRetiredLogID) - 1 == crypto::kSHA256Length,
  89. "Incorrect log ID length.");
  90. base::Time retirement_time;
  91. if (timestamp_past_2022_policy_date) {
  92. ASSERT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 16, 0, 0, 0, 0},
  93. &retirement_time));
  94. } else {
  95. ASSERT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 14, 12, 0, 0, 0},
  96. &retirement_time));
  97. }
  98. policy_enforcer_->SetDisqualifiedLogForTesting(
  99. std::make_pair(std::string(kTestRetiredLogID, 32), retirement_time));
  100. scoped_refptr<SignedCertificateTimestamp> sct(
  101. new SignedCertificateTimestamp());
  102. sct->origin = desired_origin;
  103. sct->log_id = std::string(kTestRetiredLogID, crypto::kSHA256Length);
  104. if (timestamp_after_disqualification_date) {
  105. sct->timestamp = retirement_time + base::Hours(1);
  106. } else {
  107. sct->timestamp = retirement_time - base::Hours(1);
  108. }
  109. verified_scts->push_back(sct);
  110. }
  111. void FillListWithSCTsOfOrigin(
  112. SignedCertificateTimestamp::Origin desired_origin,
  113. size_t num_scts,
  114. bool timestamp_past_2022_policy_date,
  115. SCTList* verified_scts) {
  116. std::vector<std::string> desired_log_ids;
  117. desired_log_ids.push_back(google_log_id_);
  118. FillListWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids,
  119. timestamp_past_2022_policy_date, verified_scts);
  120. }
  121. base::Time CreateTime(const base::Time::Exploded& exploded) {
  122. base::Time result;
  123. if (!base::Time::FromUTCExploded(exploded, &result)) {
  124. ADD_FAILURE() << "Failed FromUTCExploded";
  125. }
  126. return result;
  127. }
  128. void FillOperatorHistoryWithDiverseOperators(
  129. SCTList scts,
  130. std::map<std::string, OperatorHistoryEntry>* operator_history) {
  131. for (size_t i = 0; i < scts.size(); i++) {
  132. OperatorHistoryEntry entry;
  133. entry.current_operator_ = "Operator " + base::NumberToString(i);
  134. (*operator_history)[scts[i]->log_id] = entry;
  135. }
  136. }
  137. protected:
  138. base::SimpleTestClock clock_;
  139. std::unique_ptr<ChromeCTPolicyEnforcer> policy_enforcer_;
  140. scoped_refptr<X509Certificate> chain_;
  141. std::string google_log_id_;
  142. std::string non_google_log_id_;
  143. base::test::ScopedFeatureList scoped_feature_list_;
  144. };
  145. TEST_F(ChromeCTPolicyEnforcerTest,
  146. DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllGoogle) {
  147. SCTList scts;
  148. std::vector<std::string> desired_log_ids(2, google_log_id_);
  149. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  150. desired_log_ids.size(), desired_log_ids, false,
  151. &scts);
  152. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  153. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  154. NetLogWithSource()));
  155. }
  156. TEST_F(ChromeCTPolicyEnforcerTest,
  157. DoesNotConformToCTPolicyNotEnoughDiverseSCTsAllNonGoogle) {
  158. SCTList scts;
  159. std::vector<std::string> desired_log_ids(2, non_google_log_id_);
  160. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  161. desired_log_ids.size(), desired_log_ids, false,
  162. &scts);
  163. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  164. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  165. NetLogWithSource()));
  166. }
  167. TEST_F(ChromeCTPolicyEnforcerTest,
  168. ConformsToPolicyExactNumberOfSCTsForValidityPeriod) {
  169. std::unique_ptr<crypto::RSAPrivateKey> private_key(
  170. crypto::RSAPrivateKey::Create(1024));
  171. ASSERT_TRUE(private_key);
  172. // Test multiple validity periods
  173. base::Time time_2015_3_0_25_11_25_0_0 =
  174. CreateTime({2015, 3, 0, 25, 11, 25, 0, 0});
  175. base::Time time_2016_6_0_6_11_25_0_0 =
  176. CreateTime({2016, 6, 0, 6, 11, 25, 0, 0});
  177. base::Time time_2016_6_0_25_11_25_0_0 =
  178. CreateTime({2016, 6, 0, 25, 11, 25, 0, 0});
  179. base::Time time_2016_6_0_27_11_25_0_0 =
  180. CreateTime({2016, 6, 0, 27, 11, 25, 0, 0});
  181. base::Time time_2017_6_0_25_11_25_0_0 =
  182. CreateTime({2017, 6, 0, 25, 11, 25, 0, 0});
  183. base::Time time_2017_6_0_28_11_25_0_0 =
  184. CreateTime({2017, 6, 0, 28, 11, 25, 0, 0});
  185. base::Time time_2018_6_0_25_11_25_0_0 =
  186. CreateTime({2018, 6, 0, 25, 11, 25, 0, 0});
  187. base::Time time_2018_6_0_27_11_25_0_0 =
  188. CreateTime({2018, 6, 0, 27, 11, 25, 0, 0});
  189. const struct TestData {
  190. base::Time validity_start;
  191. base::Time validity_end;
  192. size_t scts_required;
  193. } kTestData[] = {{// Cert valid for -14 months (nonsensical), needs 2 SCTs.
  194. time_2016_6_0_6_11_25_0_0, time_2015_3_0_25_11_25_0_0, 2},
  195. {// Cert valid for 14 months, needs 2 SCTs.
  196. time_2015_3_0_25_11_25_0_0, time_2016_6_0_6_11_25_0_0, 2},
  197. {// Cert valid for exactly 15 months, needs 3 SCTs.
  198. time_2015_3_0_25_11_25_0_0, time_2016_6_0_25_11_25_0_0, 3},
  199. {// Cert valid for over 15 months, needs 3 SCTs.
  200. time_2015_3_0_25_11_25_0_0, time_2016_6_0_27_11_25_0_0, 3},
  201. {// Cert valid for exactly 27 months, needs 3 SCTs.
  202. time_2015_3_0_25_11_25_0_0, time_2017_6_0_25_11_25_0_0, 3},
  203. {// Cert valid for over 27 months, needs 4 SCTs.
  204. time_2015_3_0_25_11_25_0_0, time_2017_6_0_28_11_25_0_0, 4},
  205. {// Cert valid for exactly 39 months, needs 4 SCTs.
  206. time_2015_3_0_25_11_25_0_0, time_2018_6_0_25_11_25_0_0, 4},
  207. {// Cert valid for over 39 months, needs 5 SCTs.
  208. time_2015_3_0_25_11_25_0_0, time_2018_6_0_27_11_25_0_0, 5}};
  209. for (size_t i = 0; i < std::size(kTestData); ++i) {
  210. SCOPED_TRACE(i);
  211. const base::Time& start = kTestData[i].validity_start;
  212. const base::Time& end = kTestData[i].validity_end;
  213. size_t required_scts = kTestData[i].scts_required;
  214. // Create a self-signed certificate with exactly the validity period.
  215. std::string cert_data;
  216. ASSERT_TRUE(net::x509_util::CreateSelfSignedCert(
  217. private_key->key(), net::x509_util::DIGEST_SHA256, "CN=test",
  218. i * 10 + required_scts, start, end, {}, &cert_data));
  219. scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes(
  220. base::as_bytes(base::make_span(cert_data))));
  221. ASSERT_TRUE(cert);
  222. for (size_t j = 0; j < required_scts - 1; ++j) {
  223. SCTList scts;
  224. std::vector<std::string> desired_logs;
  225. desired_logs.push_back(google_log_id_);
  226. if (j > 0) {
  227. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 1,
  228. desired_logs, false, &scts);
  229. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  230. j - 1, std::vector<std::string>(), false,
  231. &scts);
  232. }
  233. CTPolicyCompliance expected_failure =
  234. j == 1 ? CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS
  235. : CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
  236. EXPECT_EQ(expected_failure, policy_enforcer_->CheckCompliance(
  237. cert.get(), scts, NetLogWithSource()))
  238. << " for: " << (end - start).InDays() << " and " << required_scts
  239. << " scts=" << scts.size() << " j=" << j;
  240. }
  241. SCTList scts;
  242. std::vector<std::string> desired_logs;
  243. desired_logs.push_back(google_log_id_);
  244. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 1,
  245. desired_logs, false, &scts);
  246. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  247. required_scts - 1, std::vector<std::string>(),
  248. false, &scts);
  249. EXPECT_EQ(
  250. CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  251. policy_enforcer_->CheckCompliance(cert.get(), scts, NetLogWithSource()))
  252. << " for: " << (end - start).InDays() << " and " << required_scts
  253. << " scts=" << scts.size();
  254. }
  255. }
  256. TEST_F(ChromeCTPolicyEnforcerTest,
  257. DoesNotConformToCTPolicyNotEnoughUniqueEmbeddedLogs) {
  258. SCTList scts;
  259. std::vector<std::string> desired_logs;
  260. // One Google Log.
  261. desired_logs.clear();
  262. desired_logs.push_back(google_log_id_);
  263. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  264. desired_logs.size(), desired_logs, false, &scts);
  265. // Two distinct non-Google logs.
  266. desired_logs.clear();
  267. desired_logs.emplace_back(crypto::kSHA256Length, 'A');
  268. desired_logs.emplace_back(crypto::kSHA256Length, 'B');
  269. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  270. desired_logs.size(), desired_logs, false, &scts);
  271. // Two unique SCTs from the same non-Google log.
  272. desired_logs.clear();
  273. desired_logs.emplace_back(crypto::kSHA256Length, 'C');
  274. desired_logs.emplace_back(crypto::kSHA256Length, 'C');
  275. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  276. desired_logs.size(), desired_logs, false, &scts);
  277. // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs.
  278. // However, there are only 4 SCTs are from distinct logs.
  279. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
  280. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  281. NetLogWithSource()));
  282. }
  283. TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) {
  284. SCTList scts;
  285. // The results should be the same before and after disqualification,
  286. // regardless of the delivery method.
  287. // SCT from before disqualification.
  288. scts.clear();
  289. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  290. 1, false, &scts);
  291. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  292. false, false, &scts);
  293. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  294. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  295. NetLogWithSource()));
  296. // SCT from after disqualification.
  297. scts.clear();
  298. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  299. 1, false, &scts);
  300. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  301. true, false, &scts);
  302. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  303. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  304. NetLogWithSource()));
  305. // Embedded SCT from before disqualification.
  306. scts.clear();
  307. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  308. 1, false, &scts);
  309. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false, false,
  310. &scts);
  311. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  312. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  313. NetLogWithSource()));
  314. // Embedded SCT from after disqualification.
  315. scts.clear();
  316. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  317. 1, false, &scts);
  318. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true, false,
  319. &scts);
  320. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  321. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  322. NetLogWithSource()));
  323. }
  324. // Subclass of ChromeCTPolicyEnforcerTest that tests both with the pre-2022
  325. // policy and the 2022 policy.
  326. class ChromeCTPolicyEnforcerTestBothPolicies
  327. : public ChromeCTPolicyEnforcerTest,
  328. public ::testing::WithParamInterface<bool> {};
  329. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  330. ConformsToCTPolicyWithNonEmbeddedSCTs) {
  331. SCTList scts;
  332. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  333. 2, GetParam(), &scts);
  334. if (GetParam()) {
  335. std::map<std::string, OperatorHistoryEntry> operator_history;
  336. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  337. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  338. }
  339. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  340. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  341. NetLogWithSource()));
  342. }
  343. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, EnforcementDisabledByBinaryAge) {
  344. SCTList scts;
  345. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  346. 2, GetParam(), &scts);
  347. if (GetParam()) {
  348. std::map<std::string, OperatorHistoryEntry> operator_history;
  349. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  350. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  351. }
  352. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  353. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  354. NetLogWithSource()));
  355. clock_.Advance(base::Days(71));
  356. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY,
  357. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  358. NetLogWithSource()));
  359. }
  360. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  361. ConformsToCTPolicyWithEmbeddedSCTs) {
  362. // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs.
  363. SCTList scts;
  364. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5,
  365. GetParam(), &scts);
  366. if (GetParam()) {
  367. std::map<std::string, OperatorHistoryEntry> operator_history;
  368. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  369. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  370. }
  371. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  372. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  373. NetLogWithSource()));
  374. }
  375. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  376. ConformsToCTPolicyWithPooledNonEmbeddedSCTs) {
  377. SCTList scts;
  378. std::vector<std::string> desired_logs;
  379. // One Google log, delivered via OCSP.
  380. desired_logs.clear();
  381. desired_logs.push_back(google_log_id_);
  382. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE,
  383. desired_logs.size(), desired_logs, GetParam(),
  384. &scts);
  385. // One non-Google log, delivered via TLS.
  386. desired_logs.clear();
  387. desired_logs.push_back(non_google_log_id_);
  388. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  389. desired_logs.size(), desired_logs, GetParam(),
  390. &scts);
  391. if (GetParam()) {
  392. std::map<std::string, OperatorHistoryEntry> operator_history;
  393. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  394. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  395. }
  396. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  397. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  398. NetLogWithSource()));
  399. }
  400. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  401. ConformsToCTPolicyWithPooledEmbeddedSCTs) {
  402. SCTList scts;
  403. std::vector<std::string> desired_logs;
  404. // One Google log, delivered embedded.
  405. desired_logs.clear();
  406. desired_logs.push_back(google_log_id_);
  407. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  408. desired_logs.size(), desired_logs, GetParam(),
  409. &scts);
  410. // One non-Google log, delivered via OCSP.
  411. desired_logs.clear();
  412. desired_logs.push_back(non_google_log_id_);
  413. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE,
  414. desired_logs.size(), desired_logs, GetParam(),
  415. &scts);
  416. if (GetParam()) {
  417. std::map<std::string, OperatorHistoryEntry> operator_history;
  418. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  419. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  420. }
  421. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  422. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  423. NetLogWithSource()));
  424. }
  425. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  426. DoesNotConformToCTPolicyNotEnoughSCTs) {
  427. // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs.
  428. SCTList scts;
  429. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 2,
  430. GetParam(), &scts);
  431. if (GetParam()) {
  432. std::map<std::string, OperatorHistoryEntry> operator_history;
  433. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  434. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  435. }
  436. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
  437. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  438. NetLogWithSource()));
  439. }
  440. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  441. ConformsWithDisqualifiedLogBeforeDisqualificationDate) {
  442. SCTList scts;
  443. std::vector<std::string> desired_log_ids;
  444. desired_log_ids.push_back(google_log_id_);
  445. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 1,
  446. desired_log_ids, GetParam(), &scts);
  447. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  448. GetParam() ? 1 : 3, std::vector<std::string>(),
  449. GetParam(), &scts);
  450. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, false,
  451. GetParam(), &scts);
  452. if (GetParam()) {
  453. std::map<std::string, OperatorHistoryEntry> operator_history;
  454. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  455. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  456. }
  457. // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs.
  458. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  459. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  460. NetLogWithSource()));
  461. }
  462. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  463. DoesNotConformWithDisqualifiedLogAfterDisqualificationDate) {
  464. SCTList scts;
  465. // Add required - 1 valid SCTs (with the old policy 5 are required, with the
  466. // new policy 3).
  467. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  468. GetParam() ? 2 : 4, GetParam(), &scts);
  469. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true,
  470. GetParam(), &scts);
  471. if (GetParam()) {
  472. std::map<std::string, OperatorHistoryEntry> operator_history;
  473. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  474. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  475. }
  476. // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs.
  477. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
  478. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  479. NetLogWithSource()));
  480. }
  481. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  482. DoesNotConformWithIssuanceDateAfterDisqualificationDate) {
  483. SCTList scts;
  484. AddDisqualifiedLogSCT(SignedCertificateTimestamp::SCT_EMBEDDED, true,
  485. GetParam(), &scts);
  486. // Add required - 1 valid SCTs (with the old policy 5 are required, with the
  487. // new policy 3).
  488. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED,
  489. GetParam() ? 2 : 4, GetParam(), &scts);
  490. // Make sure all SCTs are after the disqualification date.
  491. for (size_t i = 1; i < scts.size(); ++i)
  492. scts[i]->timestamp = scts[0]->timestamp;
  493. if (GetParam()) {
  494. std::map<std::string, OperatorHistoryEntry> operator_history;
  495. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  496. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  497. }
  498. // |chain_| is valid for 10 years - over 121 months - so requires 5 SCTs.
  499. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
  500. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  501. NetLogWithSource()));
  502. }
  503. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, UpdateCTLogList) {
  504. SCTList scts;
  505. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  506. 2, GetParam(), &scts);
  507. std::vector<std::pair<std::string, base::Time>> disqualified_logs;
  508. std::vector<std::string> operated_by_google_logs;
  509. std::map<std::string, OperatorHistoryEntry> operator_history;
  510. for (auto sct : scts) {
  511. OperatorHistoryEntry entry;
  512. entry.current_operator_ = "Operator";
  513. operator_history[sct->log_id] = entry;
  514. }
  515. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  516. operated_by_google_logs, operator_history);
  517. // The check should fail with the old policy since the Google Aviator log is
  518. // no longer in the list after the update with an empty list, and with the new
  519. // policy since all logs have the same operator.
  520. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  521. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  522. NetLogWithSource()));
  523. // Update the list again, this time including all the known operated by Google
  524. // logs, and setting operators to different values.
  525. operated_by_google_logs = certificate_transparency::GetLogsOperatedByGoogle();
  526. operated_by_google_logs.emplace_back(kTestGoogleLogID);
  527. std::sort(std::begin(operated_by_google_logs),
  528. std::end(operated_by_google_logs));
  529. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  530. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  531. operated_by_google_logs, operator_history);
  532. // The check should now succeed.
  533. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  534. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  535. NetLogWithSource()));
  536. }
  537. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, TimestampUpdates) {
  538. SCTList scts;
  539. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  540. 1, GetParam(), &scts);
  541. // Clear the log list and set the last updated time to more than 10 weeks ago.
  542. std::vector<std::pair<std::string, base::Time>> disqualified_logs;
  543. std::vector<std::string> operated_by_google_logs;
  544. std::map<std::string, OperatorHistoryEntry> log_operator_history;
  545. FillOperatorHistoryWithDiverseOperators(scts, &log_operator_history);
  546. policy_enforcer_->UpdateCTLogList(base::Time::Now() - base::Days(71),
  547. disqualified_logs, operated_by_google_logs,
  548. log_operator_history);
  549. // The check should return build not timely even though there are not enough
  550. // SCTs.
  551. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY,
  552. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  553. NetLogWithSource()));
  554. // Update the last update time value again, this time with a recent time.
  555. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  556. operated_by_google_logs,
  557. log_operator_history);
  558. // The check should now fail
  559. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  560. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  561. NetLogWithSource()));
  562. }
  563. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies, IsLogDisqualifiedTimestamp) {
  564. // Clear the log list and add 2 disqualified logs, one with a disqualification
  565. // date in the past and one in the future.
  566. // The actual logs are irrelevant for this test, so we use Aviator for the one
  567. // disqualified in the past, and a modified version of it for disqualified in
  568. // the future.
  569. const char kModifiedGoogleAviatorLogID[] =
  570. "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc\x71\x51"
  571. "\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\x4f\xf4";
  572. std::vector<std::pair<std::string, base::Time>> disqualified_logs;
  573. std::vector<std::string> operated_by_google_logs;
  574. std::map<std::string, OperatorHistoryEntry> log_operator_history;
  575. base::Time past_disqualification = base::Time::Now() - base::Hours(1);
  576. base::Time future_disqualification = base::Time::Now() + base::Hours(1);
  577. disqualified_logs.emplace_back(kModifiedGoogleAviatorLogID,
  578. future_disqualification);
  579. disqualified_logs.emplace_back(kTestGoogleLogID, past_disqualification);
  580. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  581. operated_by_google_logs,
  582. log_operator_history);
  583. base::Time disqualification_time;
  584. EXPECT_TRUE(policy_enforcer_->IsLogDisqualified(kTestGoogleLogID,
  585. &disqualification_time));
  586. EXPECT_EQ(disqualification_time, past_disqualification);
  587. EXPECT_FALSE(policy_enforcer_->IsLogDisqualified(kModifiedGoogleAviatorLogID,
  588. &disqualification_time));
  589. EXPECT_EQ(disqualification_time, future_disqualification);
  590. }
  591. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  592. IsLogDisqualifiedReturnsFalseOnUnknownLog) {
  593. // Clear the log list and add a single disqualified log, with a
  594. // disqualification date in the past;
  595. const char kModifiedGoogleAviatorLogID[] =
  596. "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc\x71\x51"
  597. "\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\x4f\xf4";
  598. std::vector<std::pair<std::string, base::Time>> disqualified_logs;
  599. std::vector<std::string> operated_by_google_logs;
  600. std::map<std::string, OperatorHistoryEntry> log_operator_history;
  601. disqualified_logs.emplace_back(kModifiedGoogleAviatorLogID,
  602. base::Time::Now() - base::Days(1));
  603. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  604. operated_by_google_logs,
  605. log_operator_history);
  606. base::Time unused;
  607. // IsLogDisqualified should return false for a log that is not in the
  608. // disqualified list.
  609. EXPECT_FALSE(policy_enforcer_->IsLogDisqualified(kTestGoogleLogID, &unused));
  610. }
  611. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  612. ConformsWithCTPolicyFutureRetirementDateLogs) {
  613. SCTList scts;
  614. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5,
  615. GetParam(), &scts);
  616. std::vector<std::pair<std::string, base::Time>> disqualified_logs;
  617. std::vector<std::string> operated_by_google_logs = {google_log_id_};
  618. std::map<std::string, OperatorHistoryEntry> log_operator_history;
  619. FillOperatorHistoryWithDiverseOperators(scts, &log_operator_history);
  620. // Set all the log operators for these SCTs as disqualified, with a timestamp
  621. // one hour from now.
  622. base::Time retirement_time = base::Time::Now() + base::Hours(1);
  623. // This mirrors how FillListWithSCTsOfOrigin generates log ids.
  624. disqualified_logs.emplace_back(google_log_id_, retirement_time);
  625. for (size_t i = 1; i < 5; ++i) {
  626. disqualified_logs.emplace_back(
  627. std::string(crypto::kSHA256Length, static_cast<char>(i)),
  628. retirement_time);
  629. }
  630. std::sort(std::begin(disqualified_logs), std::end(disqualified_logs));
  631. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  632. operated_by_google_logs,
  633. log_operator_history);
  634. // SCTs should comply since retirement date is in the future.
  635. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  636. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  637. NetLogWithSource()));
  638. }
  639. TEST_P(ChromeCTPolicyEnforcerTestBothPolicies,
  640. DoesNotConformWithCTPolicyPastRetirementDateLogs) {
  641. SCTList scts;
  642. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, 5,
  643. GetParam(), &scts);
  644. std::vector<std::pair<std::string, base::Time>> disqualified_logs;
  645. std::vector<std::string> operated_by_google_logs = {google_log_id_};
  646. std::map<std::string, OperatorHistoryEntry> log_operator_history;
  647. // Set all the log operators for these SCTs as disqualiied, with a timestamp
  648. // one hour ago.
  649. base::Time retirement_time = base::Time::Now() - base::Hours(1);
  650. // This mirrors how FillListWithSCTsOfOrigin generates log ids.
  651. disqualified_logs.emplace_back(google_log_id_, retirement_time);
  652. for (size_t i = 1; i < 5; ++i) {
  653. disqualified_logs.emplace_back(
  654. std::string(crypto::kSHA256Length, static_cast<char>(i)),
  655. retirement_time);
  656. }
  657. std::sort(std::begin(disqualified_logs), std::end(disqualified_logs));
  658. FillOperatorHistoryWithDiverseOperators(scts, &log_operator_history);
  659. policy_enforcer_->UpdateCTLogList(base::Time::Now(), disqualified_logs,
  660. operated_by_google_logs,
  661. log_operator_history);
  662. // SCTs should not comply since retirement date is in the past.
  663. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
  664. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  665. NetLogWithSource()));
  666. }
  667. INSTANTIATE_TEST_SUITE_P(All,
  668. ChromeCTPolicyEnforcerTestBothPolicies,
  669. testing::Bool());
  670. TEST_F(ChromeCTPolicyEnforcerTest, 2022PolicyNotInEffectBeforeTargetDate) {
  671. // Old policy should enforce one Google log requirement.
  672. SCTList scts;
  673. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  674. 2, std::vector<std::string>(), true, &scts);
  675. std::map<std::string, OperatorHistoryEntry> operator_history;
  676. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  677. for (auto sct : scts) {
  678. // Set timestamp to 1 day before new policy comes in effect.
  679. EXPECT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 14, 0, 0, 0, 0},
  680. &sct->timestamp));
  681. }
  682. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  683. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  684. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  685. NetLogWithSource()));
  686. }
  687. TEST_F(ChromeCTPolicyEnforcerTest, 2022PolicyInEffectAfterTargetDate) {
  688. // New policy should allow SCTs from all non-Google operators to comply as
  689. // long as diversity requirement is fulfilled.
  690. SCTList scts;
  691. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  692. 2, std::vector<std::string>(), true, &scts);
  693. std::map<std::string, OperatorHistoryEntry> operator_history;
  694. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  695. for (auto sct : scts) {
  696. // Set timestamp to the day new policy comes in effect.
  697. EXPECT_TRUE(base::Time::FromUTCExploded({2022, 4, 0, 15, 0, 0, 0, 0},
  698. &sct->timestamp));
  699. }
  700. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  701. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  702. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  703. NetLogWithSource()));
  704. }
  705. TEST_F(ChromeCTPolicyEnforcerTest, UpdatedSCTRequirements) {
  706. std::unique_ptr<crypto::RSAPrivateKey> private_key(
  707. crypto::RSAPrivateKey::Create(1024));
  708. ASSERT_TRUE(private_key);
  709. // Test multiple validity periods
  710. base::Time time_2015_3_0_25_11_25_0_0 =
  711. CreateTime({2015, 3, 0, 25, 11, 25, 0, 0});
  712. base::Time time_2015_9_0_20_11_25_0_0 =
  713. CreateTime({2015, 9, 0, 20, 11, 25, 0, 0});
  714. base::Time time_2015_9_0_21_11_25_0_0 =
  715. CreateTime({2015, 9, 0, 21, 11, 25, 0, 0});
  716. base::Time time_2015_9_0_21_11_25_1_0 =
  717. CreateTime({2015, 9, 0, 21, 11, 25, 1, 0});
  718. base::Time time_2016_3_0_25_11_25_0_0 =
  719. CreateTime({2016, 3, 0, 25, 11, 25, 0, 0});
  720. const struct TestData {
  721. base::Time validity_start;
  722. base::Time validity_end;
  723. size_t scts_required;
  724. } kTestData[] = {{// Cert valid for -12 months (nonsensical), needs 2 SCTs.
  725. time_2016_3_0_25_11_25_0_0, time_2015_3_0_25_11_25_0_0, 2},
  726. {// Cert valid for 179 days, needs 2 SCTs.
  727. time_2015_3_0_25_11_25_0_0, time_2015_9_0_20_11_25_0_0, 2},
  728. {// Cert valid for exactly 180 days, needs only 2 SCTs.
  729. time_2015_3_0_25_11_25_0_0, time_2015_9_0_21_11_25_0_0, 2},
  730. {// Cert valid for barely over 180 days, needs 3 SCTs.
  731. time_2015_3_0_25_11_25_0_0, time_2015_9_0_21_11_25_1_0, 3},
  732. {// Cert valid for over 180 days, needs 3 SCTs.
  733. time_2015_3_0_25_11_25_0_0, time_2016_3_0_25_11_25_0_0, 3}};
  734. for (size_t i = 0; i < std::size(kTestData); ++i) {
  735. SCOPED_TRACE(i);
  736. const base::Time& validity_start = kTestData[i].validity_start;
  737. const base::Time& validity_end = kTestData[i].validity_end;
  738. size_t scts_required = kTestData[i].scts_required;
  739. // Create a self-signed certificate with exactly the validity period.
  740. std::string cert_data;
  741. ASSERT_TRUE(net::x509_util::CreateSelfSignedCert(
  742. private_key->key(), net::x509_util::DIGEST_SHA256, "CN=test",
  743. i * 10 + scts_required, validity_start, validity_end, {}, &cert_data));
  744. scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes(
  745. base::as_bytes(base::make_span(cert_data))));
  746. ASSERT_TRUE(cert);
  747. std::map<std::string, OperatorHistoryEntry> operator_history;
  748. for (size_t j = 0; j <= scts_required; ++j) {
  749. SCTList scts;
  750. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_EMBEDDED, j,
  751. std::vector<std::string>(), true, &scts);
  752. // Add different operators to the logs so the SCTs comply with operator
  753. // diversity.
  754. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  755. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  756. CTPolicyCompliance expected;
  757. if (j == scts_required) {
  758. // If the scts provided are as many as are required, the cert should be
  759. // declared as compliant.
  760. expected = CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
  761. } else if (j == 1) {
  762. // If a single SCT is provided, it should trip the diversity check.
  763. expected = CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS;
  764. } else {
  765. // In any other case, the 'not enough' check should trip.
  766. expected = CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS;
  767. }
  768. EXPECT_EQ(expected, policy_enforcer_->CheckCompliance(cert.get(), scts,
  769. NetLogWithSource()))
  770. << " for: " << (validity_end - validity_start).InDays() << " and "
  771. << scts_required << " scts=" << scts.size() << " j=" << j;
  772. }
  773. }
  774. }
  775. TEST_F(ChromeCTPolicyEnforcerTest,
  776. DoesNotConformToCTPolicyAllLogsSameOperator) {
  777. SCTList scts;
  778. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  779. 2, std::vector<std::string>(), true, &scts);
  780. std::map<std::string, OperatorHistoryEntry> operator_history;
  781. for (auto sct : scts) {
  782. OperatorHistoryEntry entry;
  783. entry.current_operator_ = "Operator";
  784. operator_history[sct->log_id] = entry;
  785. }
  786. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  787. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  788. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  789. NetLogWithSource()));
  790. }
  791. TEST_F(ChromeCTPolicyEnforcerTest, ConformsToCTPolicyDifferentOperators) {
  792. SCTList scts;
  793. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  794. 2, std::vector<std::string>(), true, &scts);
  795. std::map<std::string, OperatorHistoryEntry> operator_history;
  796. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  797. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  798. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  799. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  800. NetLogWithSource()));
  801. }
  802. TEST_F(ChromeCTPolicyEnforcerTest, ConformsToPolicyDueToOperatorSwitch) {
  803. SCTList scts;
  804. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  805. 2, std::vector<std::string>(), true, &scts);
  806. std::map<std::string, OperatorHistoryEntry> operator_history;
  807. // Set all logs to the same operator.
  808. for (auto sct : scts) {
  809. OperatorHistoryEntry entry;
  810. entry.current_operator_ = "Same Operator";
  811. operator_history[sct->log_id] = entry;
  812. }
  813. // Set the previous operator of one of the logs to a different one, with an
  814. // end time after the SCT timestamp.
  815. operator_history[scts[1]->log_id].previous_operators_.emplace_back(
  816. "Different Operator", scts[1]->timestamp + base::Seconds(1));
  817. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  818. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
  819. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  820. NetLogWithSource()));
  821. }
  822. TEST_F(ChromeCTPolicyEnforcerTest, DoesNotConformToPolicyDueToOperatorSwitch) {
  823. SCTList scts;
  824. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  825. 2, std::vector<std::string>(), true, &scts);
  826. std::map<std::string, OperatorHistoryEntry> operator_history;
  827. // Set logs to different operators
  828. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  829. // Set the previous operator of one of the logs to the same as the other log,
  830. // with an end time after the SCT timestamp.
  831. operator_history[scts[1]->log_id].previous_operators_.emplace_back(
  832. "Operator 0", scts[1]->timestamp + base::Seconds(1));
  833. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  834. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  835. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  836. NetLogWithSource()));
  837. }
  838. TEST_F(ChromeCTPolicyEnforcerTest, MultipleOperatorSwitches) {
  839. SCTList scts;
  840. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  841. 2, std::vector<std::string>(), true, &scts);
  842. std::map<std::string, OperatorHistoryEntry> operator_history;
  843. // Set logs to different operators
  844. FillOperatorHistoryWithDiverseOperators(scts, &operator_history);
  845. // Set multiple previous operators, the first should be ignored since it
  846. // stopped operating before the SCT timestamp.
  847. operator_history[scts[1]->log_id].previous_operators_.emplace_back(
  848. "Different Operator", scts[1]->timestamp - base::Seconds(1));
  849. operator_history[scts[1]->log_id].previous_operators_.emplace_back(
  850. "Operator 0", scts[1]->timestamp + base::Seconds(1));
  851. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  852. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  853. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  854. NetLogWithSource()));
  855. }
  856. TEST_F(ChromeCTPolicyEnforcerTest, MultipleOperatorSwitchesBeforeSCTTimestamp) {
  857. SCTList scts;
  858. FillListWithSCTsOfOrigin(SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
  859. 2, std::vector<std::string>(), true, &scts);
  860. std::map<std::string, OperatorHistoryEntry> operator_history;
  861. // Set all logs to the same operator.
  862. for (auto sct : scts) {
  863. OperatorHistoryEntry entry;
  864. entry.current_operator_ = "Same Operator";
  865. operator_history[sct->log_id] = entry;
  866. }
  867. // Set multiple previous operators, all of them should be ignored since they
  868. // all stopped operating before the SCT timestamp.
  869. operator_history[scts[1]->log_id].previous_operators_.emplace_back(
  870. "Different Operator", scts[1]->timestamp - base::Seconds(2));
  871. operator_history[scts[1]->log_id].previous_operators_.emplace_back(
  872. "Yet Another Different Operator", scts[1]->timestamp - base::Seconds(1));
  873. policy_enforcer_->SetOperatorHistoryForTesting(operator_history);
  874. EXPECT_EQ(CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
  875. policy_enforcer_->CheckCompliance(chain_.get(), scts,
  876. NetLogWithSource()));
  877. }
  878. } // namespace certificate_transparency