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, 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 |cert_time|. | |
115 // The provided CRL is verified at |crl_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& crl_time, | |
122 const base::Time& cert_time, | |
123 bool crl_required, | |
124 net::TrustStore* cast_trust_store, | |
125 net::TrustStore* crl_trust_store) { | |
126 AuthResponse response; | |
127 | |
128 if (certificate_chain.size() > 0) { | |
129 response.set_client_auth_certificate(certificate_chain[0]); | |
130 for (size_t i = 1; i < certificate_chain.size(); ++i) | |
131 response.add_intermediate_certificate(certificate_chain[i]); | |
132 } | |
133 | |
134 response.set_crl(crl_bundle); | |
135 | |
136 cast_certificate::CRLPolicy crl_policy = | |
137 cast_certificate::CRLPolicy::CRL_REQUIRED; | |
138 if (!crl_required && crl_bundle.empty()) | |
139 crl_policy = cast_certificate::CRLPolicy::CRL_OPTIONAL; | |
140 AuthResult result = | |
141 VerifyCredentialsForTest(response, "", crl_policy, cast_trust_store, | |
142 crl_trust_store, cert_time, crl_time); | |
143 // This test doesn't set the signature so it will just fail there. | |
144 EXPECT_FALSE(result.success()); | |
145 return result; | |
146 } | |
147 | |
148 // Runs a single test case. | |
149 bool RunTest(const cast_certificate::DeviceCertTest& test_case) { | |
150 std::unique_ptr<net::TrustStore> crl_trust_store; | |
151 std::unique_ptr<net::TrustStore> cast_trust_store; | |
152 if (test_case.use_test_trust_anchors()) { | |
153 crl_trust_store = cast_certificate::testing::CreateTrustStoreFromFile( | |
154 "certificates/cast_crl_test_root_ca.pem"); | |
155 cast_trust_store = cast_certificate::testing::CreateTrustStoreFromFile( | |
156 "certificates/cast_test_root_ca.pem"); | |
157 | |
158 EXPECT_TRUE(crl_trust_store.get()); | |
159 EXPECT_TRUE(cast_trust_store.get()); | |
160 } | |
161 | |
162 std::vector<std::string> certificate_chain; | |
163 for (auto const& cert : test_case.der_cert_path()) { | |
164 certificate_chain.push_back(cert); | |
165 } | |
166 | |
167 base::Time cert_verification_time = | |
168 cast_certificate::testing::ConvertUnixTimestampSeconds( | |
169 test_case.cert_verification_time_seconds()); | |
170 | |
171 uint64_t crl_verify_time = test_case.crl_verification_time_seconds(); | |
172 base::Time crl_verification_time = | |
173 cast_certificate::testing::ConvertUnixTimestampSeconds(crl_verify_time); | |
174 if (crl_verify_time == 0) | |
175 crl_verification_time = cert_verification_time; | |
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, crl_verification_time, | |
183 cert_verification_time, false, cast_trust_store.get(), | |
184 crl_trust_store.get()); | |
185 EXPECT_EQ(result.error_type, | |
186 AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA); | |
187 return result.error_type == | |
188 AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA; | |
189 break; | |
eroman
2016/09/22 22:02:51
nit: I suggest omitting the break when there is al
ryanchung
2016/09/22 22:43:35
Done. Removed breaks here and in cast_crl_unittest
| |
190 case cast_certificate::CRL_VERIFICATION_FAILED: | |
191 // Fall-through intended. | |
192 case cast_certificate::REVOCATION_CHECK_FAILED_WITHOUT_CRL: | |
193 result = TestVerifyRevocation( | |
194 certificate_chain, crl_bundle, crl_verification_time, | |
195 cert_verification_time, true, cast_trust_store.get(), | |
196 crl_trust_store.get()); | |
197 EXPECT_EQ(result.error_type, AuthResult::ERROR_CRL_INVALID); | |
198 return result.error_type == AuthResult::ERROR_CRL_INVALID; | |
199 break; | |
200 case cast_certificate::REVOCATION_CHECK_FAILED: | |
201 result = TestVerifyRevocation( | |
202 certificate_chain, crl_bundle, crl_verification_time, | |
203 cert_verification_time, true, cast_trust_store.get(), | |
204 crl_trust_store.get()); | |
205 EXPECT_EQ(result.error_type, AuthResult::ERROR_CERT_REVOKED); | |
206 return result.error_type == AuthResult::ERROR_CERT_REVOKED; | |
207 break; | |
208 case cast_certificate::SUCCESS: | |
209 result = TestVerifyRevocation( | |
210 certificate_chain, crl_bundle, crl_verification_time, | |
211 cert_verification_time, false, cast_trust_store.get(), | |
212 crl_trust_store.get()); | |
213 EXPECT_EQ(result.error_type, AuthResult::ERROR_SIGNED_BLOBS_MISMATCH); | |
214 return result.error_type == AuthResult::ERROR_SIGNED_BLOBS_MISMATCH; | |
215 break; | |
216 case UNSPECIFIED: | |
217 return false; | |
218 break; | |
219 } | |
220 return false; | |
221 } | |
222 | |
223 // Parses the provided test suite provided in wire-format proto. | |
224 // Each test contains the inputs and the expected output. | |
225 // To see the description of the test, execute the test. | |
226 // These tests are generated by a test generator in google3. | |
227 void RunTestSuite(const std::string& test_suite_file_name) { | |
228 std::string testsuite_raw = | |
229 cast_certificate::testing::ReadTestFileToString(test_suite_file_name); | |
230 cast_certificate::DeviceCertTestSuite test_suite; | |
231 EXPECT_TRUE(test_suite.ParseFromString(testsuite_raw)); | |
232 uint16_t success = 0; | |
233 uint16_t failed = 0; | |
234 std::vector<std::string> failed_tests; | |
235 | |
236 for (auto const& test_case : test_suite.tests()) { | |
237 LOG(INFO) << "[ RUN ] " << test_case.description(); | |
238 bool result = RunTest(test_case); | |
239 EXPECT_TRUE(result); | |
240 if (!result) { | |
241 LOG(INFO) << "[ FAILED ] " << test_case.description(); | |
242 ++failed; | |
243 failed_tests.push_back(test_case.description()); | |
244 } else { | |
245 LOG(INFO) << "[ PASSED ] " << test_case.description(); | |
246 ++success; | |
247 } | |
248 } | |
249 LOG(INFO) << "[ PASSED ] " << success << " test(s)."; | |
250 if (failed) { | |
251 LOG(INFO) << "[ FAILED ] " << failed << " test(s), listed below:"; | |
252 for (const auto& failed_test : failed_tests) { | |
253 LOG(INFO) << "[ FAILED ] " << failed_test; | |
254 } | |
255 } | |
256 } | |
257 | |
258 TEST_F(CastAuthUtilTest, CRLTestSuite) { | |
259 RunTestSuite("testsuite/testsuite1.pb"); | |
260 } | |
261 | |
99 } // namespace | 262 } // namespace |
100 } // namespace cast_channel | 263 } // namespace cast_channel |
101 } // namespace api | 264 } // namespace api |
102 } // namespace extensions | 265 } // namespace extensions |
OLD | NEW |