Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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 | |
| 5 #include "base/time/time.h" | |
| 6 #include "components/cast_certificate/cast_cert_validator.h" | |
| 7 #include "components/cast_certificate/cast_cert_validator_test_helpers.h" | |
| 8 #include "components/cast_certificate/cast_crl.h" | |
| 9 #include "components/cast_certificate/cast_crl_test_untrusted_root_ca_der-inc.h" | |
| 10 #include "components/cast_certificate/cast_test_untrusted_root_ca_der-inc.h" | |
| 11 #include "components/cast_certificate/proto/test_suite.pb.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 namespace cast_certificate { | |
| 15 namespace { | |
| 16 | |
| 17 // Converts uint64_t UTC time to Exploded time. | |
| 18 base::Time::Exploded ConvertUTC(uint64_t time) { | |
| 19 base::Time utc_time = | |
| 20 base::Time::UnixEpoch() + base::TimeDelta::FromMilliseconds(time); | |
| 21 base::Time::Exploded result; | |
| 22 utc_time.UTCExplode(&result); | |
| 23 return result; | |
| 24 } | |
| 25 // Indicates the expected result of test step's verification. | |
| 26 enum TestStepResult { | |
| 27 RESULT_SUCCESS, | |
| 28 RESULT_FAIL, | |
| 29 }; | |
| 30 | |
| 31 // Verifies that the provided certificate chain is valid at the specified time | |
| 32 // and chains up to a trust anchor. | |
| 33 bool TestVerifyCertificate(TestStepResult expected_result, | |
| 34 const std::vector<std::string> certificate_chain, | |
|
sheretov
2016/07/08 18:07:08
const std::vector<std::string>& certificate_chain
ryanchung
2016/07/08 22:49:29
Done.
| |
| 35 const base::Time::Exploded& time) { | |
| 36 std::unique_ptr<CertVerificationContext> context; | |
| 37 CastDeviceCertPolicy policy; | |
| 38 CRLOptions crl_options; | |
| 39 crl_options.crl_required = false; | |
| 40 bool result = VerifyDeviceCert(certificate_chain, time, &context, &policy, | |
| 41 nullptr, crl_options); | |
| 42 EXPECT_EQ(result, expected_result == RESULT_SUCCESS); | |
|
sheretov
2016/07/08 18:07:08
The logic was a little hard for me to follow: expe
ryanchung
2016/07/08 22:49:29
Done.
Changed the return value to be true iff the
| |
| 43 return result; | |
| 44 } | |
| 45 | |
| 46 // Verifies that the provided Cast CRL signed by a trusted issuer | |
| 47 // and that the CRL can be parsed successfully. | |
| 48 // The validity of the CRL is also checked at the specified time. | |
| 49 bool TestVerifyCRL(TestStepResult expected_result, | |
| 50 const std::string& crl_bundle, | |
| 51 const base::Time::Exploded& time) { | |
| 52 std::unique_ptr<CastCRL> crl = ParseAndVerifyCRL(crl_bundle, time); | |
| 53 if (expected_result == RESULT_SUCCESS) { | |
| 54 EXPECT_NE(crl, nullptr); | |
| 55 } else { | |
| 56 EXPECT_EQ(crl, nullptr); | |
| 57 } | |
| 58 return crl != nullptr; | |
| 59 } | |
| 60 | |
| 61 // Verifies that the certificate chain provided is not revoked according to | |
| 62 // the provided Cast CRL at |cert_time|. | |
| 63 // The provided CRL is verified at |crl_time|. | |
| 64 // If |crl_required| is set, then a valid Cast CRL must be provided. | |
| 65 // Otherwise, a missing CRL is be ignored. | |
| 66 bool TestVerifyRevocation(TestStepResult expected_result, | |
| 67 const std::vector<std::string> certificate_chain, | |
| 68 const std::string& crl_bundle, | |
| 69 const base::Time::Exploded& crl_time, | |
| 70 const base::Time::Exploded& cert_time, | |
| 71 bool crl_required) { | |
| 72 std::unique_ptr<CastCRL> crl; | |
| 73 if (!crl_bundle.empty()) { | |
| 74 crl = ParseAndVerifyCRL(crl_bundle, crl_time); | |
| 75 EXPECT_NE(crl.get(), nullptr); | |
| 76 } | |
| 77 | |
| 78 std::unique_ptr<CertVerificationContext> context; | |
| 79 CastDeviceCertPolicy policy; | |
| 80 CRLOptions crl_options; | |
| 81 crl_options.crl_required = crl_required; | |
| 82 int result = VerifyDeviceCert(certificate_chain, cert_time, &context, &policy, | |
| 83 crl.get(), crl_options); | |
| 84 EXPECT_EQ(result, expected_result == RESULT_SUCCESS); | |
| 85 return result; | |
| 86 } | |
| 87 | |
| 88 // Runs a single test case. | |
| 89 bool RunTest(const DeviceCertTest& test_case) { | |
| 90 bool use_test_trust_anchors = test_case.use_test_trust_anchors(); | |
| 91 if (use_test_trust_anchors) { | |
| 92 ClearCRLTrustAnchorForTest(); | |
| 93 EXPECT_TRUE(SetCRLTrustAnchorForTest(kCastCRLTestRootCaDer, | |
| 94 sizeof(kCastCRLTestRootCaDer))); | |
| 95 EXPECT_TRUE( | |
| 96 SetTrustAnchorForTest(kCastTestRootCaDer, sizeof(kCastTestRootCaDer))); | |
| 97 } | |
| 98 | |
| 99 VerificationResult expected_result = test_case.expected_result(); | |
| 100 | |
| 101 std::vector<std::string> certificate_chain; | |
| 102 for (auto const& cert : test_case.der_cert_path()) { | |
| 103 certificate_chain.push_back(cert); | |
| 104 } | |
| 105 | |
| 106 uint64_t cert_verify_time = test_case.cert_verification_time_millis(); | |
| 107 base::Time::Exploded cert_exploded_time = ConvertUTC(cert_verify_time); | |
| 108 | |
| 109 uint64_t crl_verify_time = test_case.crl_verification_time_millis(); | |
| 110 base::Time::Exploded crl_exploded_time = ConvertUTC(crl_verify_time); | |
| 111 if (crl_verify_time == 0) | |
| 112 crl_exploded_time = cert_exploded_time; | |
| 113 | |
| 114 std::string crl_bundle = test_case.crl_bundle(); | |
| 115 switch (expected_result) { | |
| 116 case PATH_VERIFICATION_FAILED: | |
| 117 return !TestVerifyCertificate(RESULT_FAIL, certificate_chain, | |
| 118 cert_exploded_time); | |
| 119 break; | |
| 120 case CRL_VERIFICATION_FAILED: | |
| 121 return !TestVerifyCRL(RESULT_FAIL, crl_bundle, crl_exploded_time); | |
| 122 break; | |
| 123 case REVOCATION_CHECK_FAILED_WITHOUT_CRL: | |
| 124 return TestVerifyCertificate(RESULT_SUCCESS, certificate_chain, | |
| 125 cert_exploded_time) && | |
| 126 !TestVerifyCRL(RESULT_FAIL, crl_bundle, crl_exploded_time) && | |
| 127 !TestVerifyRevocation(RESULT_FAIL, certificate_chain, crl_bundle, | |
| 128 crl_exploded_time, cert_exploded_time, true); | |
| 129 break; | |
| 130 case REVOCATION_CHECK_FAILED: | |
| 131 return TestVerifyCertificate(RESULT_SUCCESS, certificate_chain, | |
| 132 cert_exploded_time) && | |
| 133 TestVerifyCRL(RESULT_SUCCESS, crl_bundle, crl_exploded_time) && | |
| 134 !TestVerifyRevocation(RESULT_FAIL, certificate_chain, crl_bundle, | |
| 135 crl_exploded_time, cert_exploded_time, | |
| 136 false); | |
| 137 break; | |
| 138 case SUCCESS: | |
| 139 return (crl_bundle.empty() || | |
| 140 TestVerifyCRL(RESULT_SUCCESS, crl_bundle, crl_exploded_time)) && | |
| 141 TestVerifyCertificate(RESULT_SUCCESS, certificate_chain, | |
| 142 cert_exploded_time) && | |
| 143 TestVerifyRevocation(RESULT_SUCCESS, certificate_chain, crl_bundle, | |
| 144 crl_exploded_time, cert_exploded_time, | |
| 145 !crl_bundle.empty()); | |
| 146 break; | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 // Parses the provided test suite provided in wire-format proto | |
| 151 // Each test contains the inputs and the expected output. | |
| 152 // To see the description of the test, execute the test. | |
| 153 // These tests are generated by a test generator in google3. | |
| 154 void RunTestSuite(const std::string& test_suite_file_name) { | |
| 155 std::string testsuite_raw = | |
| 156 cast_certificate::testing::ReadFromFile(test_suite_file_name); | |
| 157 DeviceCertTestSuite test_suite; | |
| 158 EXPECT_TRUE(test_suite.ParseFromString(testsuite_raw)); | |
| 159 uint16_t success = 0; | |
| 160 uint16_t failed = 0; | |
| 161 std::vector<std::string> failed_tests; | |
| 162 | |
| 163 for (auto const& test_case : test_suite.tests()) { | |
| 164 LOG(INFO) << "[ RUN ] " << test_case.description(); | |
| 165 bool result = RunTest(test_case); | |
| 166 EXPECT_TRUE(result); | |
| 167 if (!result) { | |
| 168 LOG(INFO) << "[ FAILED ] " << test_case.description(); | |
| 169 ++failed; | |
| 170 failed_tests.push_back(test_case.description()); | |
| 171 } else { | |
| 172 LOG(INFO) << "[ PASSED ] " << test_case.description(); | |
| 173 ++success; | |
| 174 } | |
| 175 } | |
| 176 LOG(INFO) << "[ PASSED ] " << success << " test(s)."; | |
| 177 if (failed) { | |
| 178 LOG(INFO) << "[ FAILED ] " << failed << " test(s), listed below:"; | |
| 179 for (const auto& failed_test : failed_tests) { | |
| 180 LOG(INFO) << "[ FAILED ] " << failed_test; | |
| 181 } | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 TEST(CastCertificateTest, TestSuite1) { | |
| 186 RunTestSuite("testsuite/testsuite1.pb"); | |
| 187 } | |
| 188 | |
| 189 } // namespace | |
| 190 | |
| 191 } // namespace cast_certificate | |
| OLD | NEW |