tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CTPolicyEnforcerTest.cpp (14320B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "CTPolicyEnforcer.h"
      8 
      9 #include <algorithm>
     10 #include <stdint.h>
     11 
     12 #include "CTLogVerifier.h"
     13 #include "CTVerifyResult.h"
     14 #include "SignedCertificateTimestamp.h"
     15 #include "mozpkix/Time.h"
     16 #include "gtest/gtest.h"
     17 #include "hasht.h"
     18 #include "prtime.h"
     19 
     20 namespace mozilla {
     21 namespace ct {
     22 
     23 using namespace mozilla::pkix;
     24 
     25 class CTPolicyEnforcerTest : public ::testing::Test {
     26 public:
     27  void GetLogId(Buffer& logId, size_t logNo) {
     28    logId.resize(SHA256_LENGTH);
     29    std::fill(logId.begin(), logId.end(), 0);
     30    // Just raw-copy |logId| into the output buffer.
     31    assert(sizeof(logNo) <= logId.size());
     32    memcpy(logId.data(), &logNo, sizeof(logNo));
     33  }
     34 
     35  void AddSct(VerifiedSCTList& verifiedScts, size_t logNo,
     36              CTLogOperatorId operatorId, SCTOrigin origin, uint64_t timestamp,
     37              CTLogState logState = CTLogState::Admissible,
     38              CTLogFormat logFormat = CTLogFormat::RFC6962,
     39              Maybe<uint64_t> leafIndex = Nothing()) {
     40    SignedCertificateTimestamp sct;
     41    sct.version = SignedCertificateTimestamp::Version::V1;
     42    sct.timestamp = timestamp;
     43    sct.leafIndex = leafIndex;
     44    Buffer logId;
     45    GetLogId(logId, logNo);
     46    sct.logId = std::move(logId);
     47    VerifiedSCT verifiedSct(std::move(sct), origin, operatorId, logState,
     48                            logFormat, LOG_TIMESTAMP);
     49    verifiedScts.push_back(std::move(verifiedSct));
     50  }
     51 
     52  void AddMultipleScts(VerifiedSCTList& verifiedScts, size_t logsCount,
     53                       uint8_t operatorsCount, SCTOrigin origin,
     54                       uint64_t timestamp,
     55                       CTLogState logState = CTLogState::Admissible,
     56                       CTLogFormat logFormat = CTLogFormat::RFC6962) {
     57    for (size_t logNo = 0; logNo < logsCount; logNo++) {
     58      CTLogOperatorId operatorId = logNo % operatorsCount;
     59      AddSct(verifiedScts, logNo, operatorId, origin, timestamp, logState,
     60             logFormat);
     61    }
     62  }
     63 
     64  void CheckCompliance(const VerifiedSCTList& verifiedSct,
     65                       Duration certLifetime,
     66                       CTPolicyCompliance expectedCompliance) {
     67    CTPolicyCompliance compliance =
     68        CheckCTPolicyCompliance(verifiedSct, certLifetime);
     69    EXPECT_EQ(expectedCompliance, compliance);
     70  }
     71 
     72 protected:
     73  const size_t LOG_1 = 1;
     74  const size_t LOG_2 = 2;
     75  const size_t LOG_3 = 3;
     76 
     77  const CTLogOperatorId OPERATOR_1 = 1;
     78  const CTLogOperatorId OPERATOR_2 = 2;
     79  const CTLogOperatorId OPERATOR_3 = 3;
     80 
     81  const SCTOrigin ORIGIN_EMBEDDED = SCTOrigin::Embedded;
     82  const SCTOrigin ORIGIN_TLS = SCTOrigin::TLSExtension;
     83  const SCTOrigin ORIGIN_OCSP = SCTOrigin::OCSPResponse;
     84 
     85  // 1 year of cert lifetime requires 3 SCTs for the embedded case.
     86  const Duration DEFAULT_LIFETIME = Duration(365 * Time::ONE_DAY_IN_SECONDS);
     87 
     88  // Date.parse("2015-08-15T00:00:00Z")
     89  const uint64_t TIMESTAMP_1 = 1439596800000L;
     90 
     91  // Date.parse("2016-04-15T00:00:00Z")
     92  const uint64_t LOG_TIMESTAMP = 1460678400000L;
     93 
     94  // Date.parse("2016-04-01T00:00:00Z")
     95  const uint64_t BEFORE_RETIREMENT = 1459468800000L;
     96 
     97  // Date.parse("2016-04-16T00:00:00Z")
     98  const uint64_t AFTER_RETIREMENT = 1460764800000L;
     99 };
    100 
    101 TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithNonEmbeddedSCTs) {
    102  VerifiedSCTList scts;
    103 
    104  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    105  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, TIMESTAMP_1);
    106 
    107  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    108 }
    109 
    110 TEST_F(CTPolicyEnforcerTest, DoesNotConformNotEnoughDiverseNonEmbeddedSCTs) {
    111  VerifiedSCTList scts;
    112 
    113  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    114  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    115 
    116  // The implementation attempts to fulfill the non-embedded compliance case
    117  // first. Because the non-embedded SCTs do not have enough log diversity, the
    118  // implementation then attempts to fulfill the embedded compliance case.
    119  // Because there are no embedded SCTs, it returns a "not enough SCTs" error.
    120  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    121 }
    122 
    123 TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithEmbeddedSCTs) {
    124  VerifiedSCTList scts;
    125 
    126  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    127  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    128  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    129  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, TIMESTAMP_1);
    130 
    131  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    132 }
    133 
    134 TEST_F(CTPolicyEnforcerTest, DoesNotConformNotEnoughDiverseEmbeddedSCTs) {
    135  VerifiedSCTList scts;
    136 
    137  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    138  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    139  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    140  AddSct(scts, LOG_3, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    141 
    142  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotDiverseScts);
    143 }
    144 
    145 TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithPooledNonEmbeddedSCTs) {
    146  VerifiedSCTList scts;
    147 
    148  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_OCSP, TIMESTAMP_1);
    149  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, TIMESTAMP_1);
    150 
    151  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    152 }
    153 
    154 TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyWithPooledEmbeddedSCTs) {
    155  VerifiedSCTList scts;
    156 
    157  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    158  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_OCSP, TIMESTAMP_1);
    159 
    160  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    161 }
    162 
    163 TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughSCTs) {
    164  VerifiedSCTList scts;
    165 
    166  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    167  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, TIMESTAMP_1);
    168 
    169  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    170 }
    171 
    172 TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTPolicyNotEnoughFreshSCTs) {
    173  VerifiedSCTList scts;
    174 
    175  // The results should be the same before and after disqualification,
    176  // regardless of the delivery method.
    177 
    178  // SCT from before disqualification.
    179  scts.clear();
    180  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    181  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, BEFORE_RETIREMENT,
    182         CTLogState::Retired);
    183  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    184  // SCT from after disqualification.
    185  scts.clear();
    186  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    187  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, AFTER_RETIREMENT,
    188         CTLogState::Retired);
    189  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    190 
    191  // Embedded SCT from before disqualification.
    192  scts.clear();
    193  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    194  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_RETIREMENT,
    195         CTLogState::Retired);
    196  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    197 
    198  // Embedded SCT from after disqualification.
    199  scts.clear();
    200  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1);
    201  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, AFTER_RETIREMENT,
    202         CTLogState::Retired);
    203  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    204 }
    205 
    206 TEST_F(CTPolicyEnforcerTest, ConformsWithRetiredLogBeforeDisqualificationDate) {
    207  VerifiedSCTList scts;
    208 
    209  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    210  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    211  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    212  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_RETIREMENT,
    213         CTLogState::Retired);
    214 
    215  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    216 }
    217 
    218 TEST_F(CTPolicyEnforcerTest,
    219       DoesNotConformWithRetiredLogAfterDisqualificationDate) {
    220  VerifiedSCTList scts;
    221 
    222  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    223  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    224  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    225  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, AFTER_RETIREMENT,
    226         CTLogState::Retired);
    227 
    228  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    229 }
    230 
    231 TEST_F(CTPolicyEnforcerTest,
    232       DoesNotConformWithIssuanceDateAfterDisqualificationDate) {
    233  VerifiedSCTList scts;
    234 
    235  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    236  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, AFTER_RETIREMENT,
    237         CTLogState::Retired);
    238  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, AFTER_RETIREMENT);
    239  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, AFTER_RETIREMENT);
    240 
    241  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    242 }
    243 
    244 TEST_F(CTPolicyEnforcerTest,
    245       DoesNotConformToCTPolicyNotEnoughUniqueEmbeddedRetiredLogs) {
    246  VerifiedSCTList scts;
    247 
    248  // Operator #1
    249  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    250  // Operator #2, same retired logs
    251  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_RETIREMENT,
    252         CTLogState::Retired);
    253  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_EMBEDDED, BEFORE_RETIREMENT,
    254         CTLogState::Retired);
    255 
    256  // 3 embedded SCTs required. However, only 2 are from distinct logs.
    257  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotDiverseScts);
    258 }
    259 
    260 TEST_F(CTPolicyEnforcerTest,
    261       ConformsToPolicyExactNumberOfSCTsForValidityPeriod) {
    262  // Test multiple validity periods.
    263  const struct TestData {
    264    Duration certLifetime;
    265    size_t sctsRequired;
    266  } kTestData[] = {{Duration(90 * Time::ONE_DAY_IN_SECONDS), 2},
    267                   {Duration(180 * Time::ONE_DAY_IN_SECONDS), 2},
    268                   {Duration(181 * Time::ONE_DAY_IN_SECONDS), 3},
    269                   {Duration(365 * Time::ONE_DAY_IN_SECONDS), 3}};
    270 
    271  for (size_t i = 0; i < MOZILLA_CT_ARRAY_LENGTH(kTestData); ++i) {
    272    SCOPED_TRACE(i);
    273 
    274    Duration certLifetime = kTestData[i].certLifetime;
    275    size_t sctsRequired = kTestData[i].sctsRequired;
    276 
    277    // Less SCTs than required is not enough.
    278    for (size_t sctsAvailable = 0; sctsAvailable < sctsRequired;
    279         ++sctsAvailable) {
    280      VerifiedSCTList scts;
    281      AddMultipleScts(scts, sctsAvailable, 1, ORIGIN_EMBEDDED, TIMESTAMP_1);
    282 
    283      CTPolicyCompliance compliance =
    284          CheckCTPolicyCompliance(scts, certLifetime);
    285      EXPECT_EQ(CTPolicyCompliance::NotEnoughScts, compliance)
    286          << "i=" << i << " sctsRequired=" << sctsRequired
    287          << " sctsAvailable=" << sctsAvailable;
    288    }
    289 
    290    // Add exactly the required number of SCTs (from 2 operators).
    291    VerifiedSCTList scts;
    292    AddMultipleScts(scts, sctsRequired, 2, ORIGIN_EMBEDDED, TIMESTAMP_1);
    293 
    294    CTPolicyCompliance compliance = CheckCTPolicyCompliance(scts, certLifetime);
    295    EXPECT_EQ(CTPolicyCompliance::Compliant, compliance) << "i=" << i;
    296  }
    297 }
    298 
    299 TEST_F(CTPolicyEnforcerTest, ConformsToCTPolicyWithAtLeastOneRFC6962Log) {
    300  VerifiedSCTList scts;
    301 
    302  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1,
    303         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    304  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, TIMESTAMP_1,
    305         CTLogState::Admissible, CTLogFormat::RFC6962);
    306 
    307  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    308 }
    309 
    310 TEST_F(CTPolicyEnforcerTest,
    311       ConformsToCTPolicyWithAtLeastOneRFC6962LogEmbedded) {
    312  VerifiedSCTList scts;
    313 
    314  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    315  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1,
    316         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    317  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1,
    318         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    319  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, TIMESTAMP_1,
    320         CTLogState::Admissible, CTLogFormat::RFC6962);
    321 
    322  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    323 }
    324 
    325 TEST_F(CTPolicyEnforcerTest, DoesConformToCTPolicyWithNoRFC6962Logs) {
    326  VerifiedSCTList scts;
    327 
    328  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1,
    329         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    330  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, TIMESTAMP_1,
    331         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    332 
    333  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    334 }
    335 
    336 TEST_F(CTPolicyEnforcerTest, DoesConformToCTPolicyWithNoRFC6962LogsEmbedded) {
    337  VerifiedSCTList scts;
    338 
    339  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    340  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1,
    341         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    342  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1,
    343         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    344  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, TIMESTAMP_1,
    345         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    346 
    347  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::Compliant);
    348 }
    349 
    350 TEST_F(CTPolicyEnforcerTest,
    351       DoesNotConformToCTPolicyWithSCTFromTiledLogWithNoLeafIndex) {
    352  VerifiedSCTList scts;
    353 
    354  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_TLS, TIMESTAMP_1,
    355         CTLogState::Admissible, CTLogFormat::Tiled, Nothing());
    356  AddSct(scts, LOG_2, OPERATOR_2, ORIGIN_TLS, TIMESTAMP_1,
    357         CTLogState::Admissible, CTLogFormat::RFC6962);
    358 
    359  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    360 }
    361 
    362 TEST_F(CTPolicyEnforcerTest,
    363       DoesNotConformToCTPolicyWithSCTFromTiledLogWithNoLeafIndexEmbedded) {
    364  VerifiedSCTList scts;
    365 
    366  // 3 embedded SCTs required for DEFAULT_LIFETIME.
    367  AddSct(scts, LOG_1, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1,
    368         CTLogState::Admissible, CTLogFormat::Tiled, Some(23));
    369  AddSct(scts, LOG_2, OPERATOR_1, ORIGIN_EMBEDDED, TIMESTAMP_1,
    370         CTLogState::Admissible, CTLogFormat::Tiled, Nothing());
    371  AddSct(scts, LOG_3, OPERATOR_2, ORIGIN_EMBEDDED, TIMESTAMP_1,
    372         CTLogState::Admissible, CTLogFormat::RFC6962);
    373 
    374  CheckCompliance(scts, DEFAULT_LIFETIME, CTPolicyCompliance::NotEnoughScts);
    375 }
    376 
    377 }  // namespace ct
    378 }  // namespace mozilla