OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/api/cast_channel/cast_auth_util.h" | 5 #include "extensions/browser/api/cast_channel/cast_auth_util.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/time/time.h" |
| 11 #include "components/cast_certificate/cast_cert_validator.h" |
10 #include "components/cast_certificate/cast_cert_validator_test_helpers.h" | 12 #include "components/cast_certificate/cast_cert_validator_test_helpers.h" |
| 13 #include "components/cast_certificate/cast_crl.h" |
| 14 #include "components/cast_certificate/proto/test_suite.pb.h" |
11 #include "extensions/common/api/cast_channel/cast_channel.pb.h" | 15 #include "extensions/common/api/cast_channel/cast_channel.pb.h" |
| 16 #include "net/cert/internal/trust_store_in_memory.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
13 | 18 |
14 namespace extensions { | 19 namespace extensions { |
15 namespace api { | 20 namespace api { |
16 namespace cast_channel { | 21 namespace cast_channel { |
17 namespace { | 22 namespace { |
18 | 23 |
19 class CastAuthUtilTest : public testing::Test { | 24 class CastAuthUtilTest : public testing::Test { |
20 public: | 25 public: |
21 CastAuthUtilTest() {} | 26 CastAuthUtilTest() {} |
(...skipping 25 matching lines...) Expand all Loading... |
47 // Mangles a string by inverting the first byte. | 52 // Mangles a string by inverting the first byte. |
48 static void MangleString(std::string* str) { (*str)[0] = ~(*str)[0]; } | 53 static void MangleString(std::string* str) { (*str)[0] = ~(*str)[0]; } |
49 }; | 54 }; |
50 | 55 |
51 // Note on expiration: VerifyCredentials() depends on the system clock. In | 56 // Note on expiration: VerifyCredentials() depends on the system clock. In |
52 // practice this shouldn't be a problem though since the certificate chain | 57 // practice this shouldn't be a problem though since the certificate chain |
53 // being verified doesn't expire until 2032! | 58 // being verified doesn't expire until 2032! |
54 TEST_F(CastAuthUtilTest, VerifySuccess) { | 59 TEST_F(CastAuthUtilTest, VerifySuccess) { |
55 std::string signed_data; | 60 std::string signed_data; |
56 AuthResponse auth_response = CreateAuthResponse(&signed_data); | 61 AuthResponse auth_response = CreateAuthResponse(&signed_data); |
57 AuthResult result = VerifyCredentials(auth_response, signed_data); | 62 base::Time now = base::Time::Now(); |
| 63 AuthResult result = VerifyCredentialsForTest( |
| 64 auth_response, signed_data, cast_certificate::CRLPolicy::CRL_OPTIONAL, |
| 65 nullptr, nullptr, now); |
58 EXPECT_TRUE(result.success()); | 66 EXPECT_TRUE(result.success()); |
59 EXPECT_EQ(AuthResult::POLICY_NONE, result.channel_policies); | 67 EXPECT_EQ(AuthResult::POLICY_NONE, result.channel_policies); |
60 } | 68 } |
61 | 69 |
62 TEST_F(CastAuthUtilTest, VerifyBadCA) { | 70 TEST_F(CastAuthUtilTest, VerifyBadCA) { |
63 std::string signed_data; | 71 std::string signed_data; |
64 AuthResponse auth_response = CreateAuthResponse(&signed_data); | 72 AuthResponse auth_response = CreateAuthResponse(&signed_data); |
65 MangleString(auth_response.mutable_intermediate_certificate(0)); | 73 MangleString(auth_response.mutable_intermediate_certificate(0)); |
66 AuthResult result = VerifyCredentials(auth_response, signed_data); | 74 AuthResult result = VerifyCredentials(auth_response, signed_data); |
67 EXPECT_FALSE(result.success()); | 75 EXPECT_FALSE(result.success()); |
(...skipping 21 matching lines...) Expand all Loading... |
89 | 97 |
90 TEST_F(CastAuthUtilTest, VerifyBadPeerCert) { | 98 TEST_F(CastAuthUtilTest, VerifyBadPeerCert) { |
91 std::string signed_data; | 99 std::string signed_data; |
92 AuthResponse auth_response = CreateAuthResponse(&signed_data); | 100 AuthResponse auth_response = CreateAuthResponse(&signed_data); |
93 MangleString(&signed_data); | 101 MangleString(&signed_data); |
94 AuthResult result = VerifyCredentials(auth_response, signed_data); | 102 AuthResult result = VerifyCredentials(auth_response, signed_data); |
95 EXPECT_FALSE(result.success()); | 103 EXPECT_FALSE(result.success()); |
96 EXPECT_EQ(AuthResult::ERROR_SIGNED_BLOBS_MISMATCH, result.error_type); | 104 EXPECT_EQ(AuthResult::ERROR_SIGNED_BLOBS_MISMATCH, result.error_type); |
97 } | 105 } |
98 | 106 |
| 107 // Indicates the expected result of test step's verification. |
| 108 enum TestStepResult { |
| 109 RESULT_SUCCESS, |
| 110 RESULT_FAIL, |
| 111 }; |
| 112 |
| 113 // Verifies that the certificate chain provided is not revoked according to |
| 114 // the provided Cast CRL at |verification_time|. |
| 115 // The provided CRL is verified at |verification_time|. |
| 116 // If |crl_required| is set, then a valid Cast CRL must be provided. |
| 117 // Otherwise, a missing CRL is be ignored. |
| 118 AuthResult TestVerifyRevocation( |
| 119 const std::vector<std::string>& certificate_chain, |
| 120 const std::string& crl_bundle, |
| 121 const base::Time& verification_time, |
| 122 bool crl_required, |
| 123 net::TrustStore* cast_trust_store, |
| 124 net::TrustStore* crl_trust_store) { |
| 125 AuthResponse response; |
| 126 |
| 127 if (certificate_chain.size() > 0) { |
| 128 response.set_client_auth_certificate(certificate_chain[0]); |
| 129 for (size_t i = 1; i < certificate_chain.size(); ++i) |
| 130 response.add_intermediate_certificate(certificate_chain[i]); |
| 131 } |
| 132 |
| 133 response.set_crl(crl_bundle); |
| 134 |
| 135 cast_certificate::CRLPolicy crl_policy = |
| 136 cast_certificate::CRLPolicy::CRL_REQUIRED; |
| 137 if (!crl_required && crl_bundle.empty()) |
| 138 crl_policy = cast_certificate::CRLPolicy::CRL_OPTIONAL; |
| 139 AuthResult result = |
| 140 VerifyCredentialsForTest(response, "", crl_policy, cast_trust_store, |
| 141 crl_trust_store, verification_time); |
| 142 // This test doesn't set the signature so it will just fail there. |
| 143 EXPECT_FALSE(result.success()); |
| 144 return result; |
| 145 } |
| 146 |
| 147 // Runs a single test case. |
| 148 bool RunTest(const cast_certificate::DeviceCertTest& test_case) { |
| 149 std::unique_ptr<net::TrustStore> crl_trust_store; |
| 150 std::unique_ptr<net::TrustStore> cast_trust_store; |
| 151 if (test_case.use_test_trust_anchors()) { |
| 152 crl_trust_store = cast_certificate::testing::CreateTrustStoreFromFile( |
| 153 "certificates/cast_crl_test_root_ca.pem"); |
| 154 cast_trust_store = cast_certificate::testing::CreateTrustStoreFromFile( |
| 155 "certificates/cast_test_root_ca.pem"); |
| 156 |
| 157 EXPECT_TRUE(crl_trust_store.get()); |
| 158 EXPECT_TRUE(cast_trust_store.get()); |
| 159 } |
| 160 |
| 161 std::vector<std::string> certificate_chain; |
| 162 for (auto const& cert : test_case.der_cert_path()) { |
| 163 certificate_chain.push_back(cert); |
| 164 } |
| 165 |
| 166 // CastAuthUtil verifies the CRL at the same time as the certificate. |
| 167 base::Time verification_time; |
| 168 uint64_t cert_verify_time = test_case.cert_verification_time_seconds(); |
| 169 if (cert_verify_time) { |
| 170 verification_time = cast_certificate::testing::ConvertUnixTimestampSeconds( |
| 171 cert_verify_time); |
| 172 } else { |
| 173 verification_time = cast_certificate::testing::ConvertUnixTimestampSeconds( |
| 174 test_case.crl_verification_time_seconds()); |
| 175 } |
| 176 |
| 177 std::string crl_bundle = test_case.crl_bundle(); |
| 178 AuthResult result; |
| 179 switch (test_case.expected_result()) { |
| 180 case cast_certificate::PATH_VERIFICATION_FAILED: |
| 181 result = TestVerifyRevocation( |
| 182 certificate_chain, crl_bundle, verification_time, false, |
| 183 cast_trust_store.get(), crl_trust_store.get()); |
| 184 EXPECT_EQ(result.error_type, |
| 185 AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA); |
| 186 return result.error_type == |
| 187 AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA; |
| 188 case cast_certificate::CRL_VERIFICATION_FAILED: |
| 189 // Fall-through intended. |
| 190 case cast_certificate::REVOCATION_CHECK_FAILED_WITHOUT_CRL: |
| 191 result = TestVerifyRevocation( |
| 192 certificate_chain, crl_bundle, verification_time, true, |
| 193 cast_trust_store.get(), crl_trust_store.get()); |
| 194 EXPECT_EQ(result.error_type, AuthResult::ERROR_CRL_INVALID); |
| 195 return result.error_type == AuthResult::ERROR_CRL_INVALID; |
| 196 case cast_certificate::CRL_EXPIRED_AFTER_INITIAL_VERIFICATION: |
| 197 // By-pass this test because CRL is always verified at the time the |
| 198 // certificate is verified. |
| 199 return true; |
| 200 case cast_certificate::REVOCATION_CHECK_FAILED: |
| 201 result = TestVerifyRevocation( |
| 202 certificate_chain, crl_bundle, verification_time, true, |
| 203 cast_trust_store.get(), crl_trust_store.get()); |
| 204 EXPECT_EQ(result.error_type, AuthResult::ERROR_CERT_REVOKED); |
| 205 return result.error_type == AuthResult::ERROR_CERT_REVOKED; |
| 206 case cast_certificate::SUCCESS: |
| 207 result = TestVerifyRevocation( |
| 208 certificate_chain, crl_bundle, verification_time, false, |
| 209 cast_trust_store.get(), crl_trust_store.get()); |
| 210 EXPECT_EQ(result.error_type, AuthResult::ERROR_SIGNED_BLOBS_MISMATCH); |
| 211 return result.error_type == AuthResult::ERROR_SIGNED_BLOBS_MISMATCH; |
| 212 case UNSPECIFIED: |
| 213 return false; |
| 214 } |
| 215 return false; |
| 216 } |
| 217 |
| 218 // Parses the provided test suite provided in wire-format proto. |
| 219 // Each test contains the inputs and the expected output. |
| 220 // To see the description of the test, execute the test. |
| 221 // These tests are generated by a test generator in google3. |
| 222 void RunTestSuite(const std::string& test_suite_file_name) { |
| 223 std::string testsuite_raw = |
| 224 cast_certificate::testing::ReadTestFileToString(test_suite_file_name); |
| 225 cast_certificate::DeviceCertTestSuite test_suite; |
| 226 EXPECT_TRUE(test_suite.ParseFromString(testsuite_raw)); |
| 227 uint16_t success = 0; |
| 228 uint16_t failed = 0; |
| 229 std::vector<std::string> failed_tests; |
| 230 |
| 231 for (auto const& test_case : test_suite.tests()) { |
| 232 LOG(INFO) << "[ RUN ] " << test_case.description(); |
| 233 bool result = RunTest(test_case); |
| 234 EXPECT_TRUE(result); |
| 235 if (!result) { |
| 236 LOG(INFO) << "[ FAILED ] " << test_case.description(); |
| 237 ++failed; |
| 238 failed_tests.push_back(test_case.description()); |
| 239 } else { |
| 240 LOG(INFO) << "[ PASSED ] " << test_case.description(); |
| 241 ++success; |
| 242 } |
| 243 } |
| 244 LOG(INFO) << "[ PASSED ] " << success << " test(s)."; |
| 245 if (failed) { |
| 246 LOG(INFO) << "[ FAILED ] " << failed << " test(s), listed below:"; |
| 247 for (const auto& failed_test : failed_tests) { |
| 248 LOG(INFO) << "[ FAILED ] " << failed_test; |
| 249 } |
| 250 } |
| 251 } |
| 252 |
| 253 TEST_F(CastAuthUtilTest, CRLTestSuite) { |
| 254 RunTestSuite("testsuite/testsuite1.pb"); |
| 255 } |
| 256 |
99 } // namespace | 257 } // namespace |
100 } // namespace cast_channel | 258 } // namespace cast_channel |
101 } // namespace api | 259 } // namespace api |
102 } // namespace extensions | 260 } // namespace extensions |
OLD | NEW |