Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: extensions/browser/api/cast_channel/cast_auth_util_unittest.cc

Issue 2926313002: Revert of [cast_channel] Move cast_channel related files from //extensions to //components (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "extensions/browser/api/cast_channel/cast_auth_util.h"
6
7 #include <string>
8
9 #include "base/macros.h"
10 #include "base/test/scoped_feature_list.h"
11 #include "base/time/time.h"
12 #include "components/cast_certificate/cast_cert_validator.h"
13 #include "components/cast_certificate/cast_cert_validator_test_helpers.h"
14 #include "components/cast_certificate/cast_crl.h"
15 #include "components/cast_certificate/proto/test_suite.pb.h"
16 #include "extensions/common/api/cast_channel/cast_channel.pb.h"
17 #include "net/cert/internal/trust_store_in_memory.h"
18 #include "net/cert/x509_certificate.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace extensions {
22 namespace api {
23 namespace cast_channel {
24 namespace {
25
26 class CastAuthUtilTest : public testing::Test {
27 public:
28 CastAuthUtilTest() {}
29 ~CastAuthUtilTest() override {}
30
31 void SetUp() override {}
32
33 protected:
34 static AuthResponse CreateAuthResponse(std::string* signed_data) {
35 auto chain = cast_certificate::testing::ReadCertificateChainFromFile(
36 "certificates/chromecast_gen1.pem");
37 CHECK(!chain.empty());
38
39 auto signature_data = cast_certificate::testing::ReadSignatureTestData(
40 "signeddata/2ZZBG9_FA8FCA3EF91A.pem");
41
42 AuthResponse response;
43
44 response.set_client_auth_certificate(chain[0]);
45 for (size_t i = 1; i < chain.size(); ++i)
46 response.add_intermediate_certificate(chain[i]);
47
48 response.set_signature(signature_data.signature_sha1);
49 *signed_data = signature_data.message;
50
51 return response;
52 }
53
54 // Mangles a string by inverting the first byte.
55 static void MangleString(std::string* str) { (*str)[0] = ~(*str)[0]; }
56 };
57
58 // Note on expiration: VerifyCredentials() depends on the system clock. In
59 // practice this shouldn't be a problem though since the certificate chain
60 // being verified doesn't expire until 2032!
61 TEST_F(CastAuthUtilTest, VerifySuccess) {
62 std::string signed_data;
63 AuthResponse auth_response = CreateAuthResponse(&signed_data);
64 base::Time now = base::Time::Now();
65 AuthResult result = VerifyCredentialsForTest(
66 auth_response, signed_data, cast_certificate::CRLPolicy::CRL_OPTIONAL,
67 nullptr, nullptr, now);
68 EXPECT_TRUE(result.success());
69 EXPECT_EQ(AuthResult::POLICY_NONE, result.channel_policies);
70 }
71
72 TEST_F(CastAuthUtilTest, VerifyBadCA) {
73 std::string signed_data;
74 AuthResponse auth_response = CreateAuthResponse(&signed_data);
75 MangleString(auth_response.mutable_intermediate_certificate(0));
76 AuthResult result = VerifyCredentials(auth_response, signed_data);
77 EXPECT_FALSE(result.success());
78 EXPECT_EQ(AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA, result.error_type);
79 }
80
81 TEST_F(CastAuthUtilTest, VerifyBadClientAuthCert) {
82 std::string signed_data;
83 AuthResponse auth_response = CreateAuthResponse(&signed_data);
84 MangleString(auth_response.mutable_client_auth_certificate());
85 AuthResult result = VerifyCredentials(auth_response, signed_data);
86 EXPECT_FALSE(result.success());
87 // TODO(eroman): Not quite right of an error.
88 EXPECT_EQ(AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA, result.error_type);
89 }
90
91 TEST_F(CastAuthUtilTest, VerifyBadSignature) {
92 std::string signed_data;
93 AuthResponse auth_response = CreateAuthResponse(&signed_data);
94 MangleString(auth_response.mutable_signature());
95 AuthResult result = VerifyCredentials(auth_response, signed_data);
96 EXPECT_FALSE(result.success());
97 EXPECT_EQ(AuthResult::ERROR_SIGNED_BLOBS_MISMATCH, result.error_type);
98 }
99
100 TEST_F(CastAuthUtilTest, VerifyBadPeerCert) {
101 std::string signed_data;
102 AuthResponse auth_response = CreateAuthResponse(&signed_data);
103 MangleString(&signed_data);
104 AuthResult result = VerifyCredentials(auth_response, signed_data);
105 EXPECT_FALSE(result.success());
106 EXPECT_EQ(AuthResult::ERROR_SIGNED_BLOBS_MISMATCH, result.error_type);
107 }
108
109 TEST_F(CastAuthUtilTest, VerifySenderNonceMatch) {
110 base::test::ScopedFeatureList scoped_feature_list;
111 scoped_feature_list.InitAndEnableFeature(
112 base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT});
113 AuthContext context = AuthContext::Create();
114 AuthResult result = context.VerifySenderNonce(context.nonce());
115 EXPECT_TRUE(result.success());
116 }
117
118 TEST_F(CastAuthUtilTest, VerifySenderNonceMismatch) {
119 base::test::ScopedFeatureList scoped_feature_list;
120 scoped_feature_list.InitAndEnableFeature(
121 base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT});
122 AuthContext context = AuthContext::Create();
123 std::string received_nonce = "test2";
124 EXPECT_NE(received_nonce, context.nonce());
125 AuthResult result = context.VerifySenderNonce(received_nonce);
126 EXPECT_FALSE(result.success());
127 EXPECT_EQ(AuthResult::ERROR_SENDER_NONCE_MISMATCH, result.error_type);
128 }
129
130 TEST_F(CastAuthUtilTest, VerifySenderNonceMissing) {
131 base::test::ScopedFeatureList scoped_feature_list;
132 scoped_feature_list.InitAndEnableFeature(
133 base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT});
134 AuthContext context = AuthContext::Create();
135 std::string received_nonce = "";
136 EXPECT_FALSE(context.nonce().empty());
137 AuthResult result = context.VerifySenderNonce(received_nonce);
138 EXPECT_FALSE(result.success());
139 EXPECT_EQ(AuthResult::ERROR_SENDER_NONCE_MISMATCH, result.error_type);
140 }
141
142 TEST_F(CastAuthUtilTest, VerifyTLSCertificateSuccess) {
143 auto tls_cert_der = cast_certificate::testing::ReadCertificateChainFromFile(
144 "certificates/test_tls_cert.pem");
145
146 scoped_refptr<net::X509Certificate> tls_cert =
147 net::X509Certificate::CreateFromBytes(tls_cert_der[0].data(),
148 tls_cert_der[0].size());
149 std::string peer_cert_der;
150 AuthResult result =
151 VerifyTLSCertificate(*tls_cert, &peer_cert_der, tls_cert->valid_start());
152 EXPECT_TRUE(result.success());
153 }
154
155 TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooEarly) {
156 auto tls_cert_der = cast_certificate::testing::ReadCertificateChainFromFile(
157 "certificates/test_tls_cert.pem");
158
159 scoped_refptr<net::X509Certificate> tls_cert =
160 net::X509Certificate::CreateFromBytes(tls_cert_der[0].data(),
161 tls_cert_der[0].size());
162 std::string peer_cert_der;
163 AuthResult result = VerifyTLSCertificate(
164 *tls_cert, &peer_cert_der,
165 tls_cert->valid_start() - base::TimeDelta::FromSeconds(1));
166 EXPECT_FALSE(result.success());
167 EXPECT_EQ(AuthResult::ERROR_TLS_CERT_VALID_START_DATE_IN_FUTURE,
168 result.error_type);
169 }
170
171 TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooLate) {
172 auto tls_cert_der = cast_certificate::testing::ReadCertificateChainFromFile(
173 "certificates/test_tls_cert.pem");
174
175 scoped_refptr<net::X509Certificate> tls_cert =
176 net::X509Certificate::CreateFromBytes(tls_cert_der[0].data(),
177 tls_cert_der[0].size());
178 std::string peer_cert_der;
179 AuthResult result = VerifyTLSCertificate(
180 *tls_cert, &peer_cert_der,
181 tls_cert->valid_expiry() + base::TimeDelta::FromSeconds(2));
182 EXPECT_FALSE(result.success());
183 EXPECT_EQ(AuthResult::ERROR_TLS_CERT_EXPIRED, result.error_type);
184 }
185
186 // Indicates the expected result of test step's verification.
187 enum TestStepResult {
188 RESULT_SUCCESS,
189 RESULT_FAIL,
190 };
191
192 // Verifies that the certificate chain provided is not revoked according to
193 // the provided Cast CRL at |verification_time|.
194 // The provided CRL is verified at |verification_time|.
195 // If |crl_required| is set, then a valid Cast CRL must be provided.
196 // Otherwise, a missing CRL is be ignored.
197 AuthResult TestVerifyRevocation(
198 const std::vector<std::string>& certificate_chain,
199 const std::string& crl_bundle,
200 const base::Time& verification_time,
201 bool crl_required,
202 net::TrustStore* cast_trust_store,
203 net::TrustStore* crl_trust_store) {
204 AuthResponse response;
205
206 if (certificate_chain.size() > 0) {
207 response.set_client_auth_certificate(certificate_chain[0]);
208 for (size_t i = 1; i < certificate_chain.size(); ++i)
209 response.add_intermediate_certificate(certificate_chain[i]);
210 }
211
212 response.set_crl(crl_bundle);
213
214 cast_certificate::CRLPolicy crl_policy =
215 cast_certificate::CRLPolicy::CRL_REQUIRED;
216 if (!crl_required && crl_bundle.empty())
217 crl_policy = cast_certificate::CRLPolicy::CRL_OPTIONAL;
218 AuthResult result =
219 VerifyCredentialsForTest(response, "", crl_policy, cast_trust_store,
220 crl_trust_store, verification_time);
221 // This test doesn't set the signature so it will just fail there.
222 EXPECT_FALSE(result.success());
223 return result;
224 }
225
226 // Runs a single test case.
227 bool RunTest(const cast_certificate::DeviceCertTest& test_case) {
228 std::unique_ptr<net::TrustStore> crl_trust_store;
229 std::unique_ptr<net::TrustStore> cast_trust_store;
230 if (test_case.use_test_trust_anchors()) {
231 crl_trust_store = cast_certificate::testing::CreateTrustStoreFromFile(
232 "certificates/cast_crl_test_root_ca.pem");
233 cast_trust_store = cast_certificate::testing::CreateTrustStoreFromFile(
234 "certificates/cast_test_root_ca.pem");
235
236 EXPECT_TRUE(crl_trust_store.get());
237 EXPECT_TRUE(cast_trust_store.get());
238 }
239
240 std::vector<std::string> certificate_chain;
241 for (auto const& cert : test_case.der_cert_path()) {
242 certificate_chain.push_back(cert);
243 }
244
245 // CastAuthUtil verifies the CRL at the same time as the certificate.
246 base::Time verification_time;
247 uint64_t cert_verify_time = test_case.cert_verification_time_seconds();
248 if (cert_verify_time) {
249 verification_time = cast_certificate::testing::ConvertUnixTimestampSeconds(
250 cert_verify_time);
251 } else {
252 verification_time = cast_certificate::testing::ConvertUnixTimestampSeconds(
253 test_case.crl_verification_time_seconds());
254 }
255
256 std::string crl_bundle = test_case.crl_bundle();
257 AuthResult result;
258 switch (test_case.expected_result()) {
259 case cast_certificate::PATH_VERIFICATION_FAILED:
260 result = TestVerifyRevocation(
261 certificate_chain, crl_bundle, verification_time, false,
262 cast_trust_store.get(), crl_trust_store.get());
263 EXPECT_EQ(result.error_type,
264 AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA);
265 return result.error_type ==
266 AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA;
267 case cast_certificate::CRL_VERIFICATION_FAILED:
268 // Fall-through intended.
269 case cast_certificate::REVOCATION_CHECK_FAILED_WITHOUT_CRL:
270 result = TestVerifyRevocation(
271 certificate_chain, crl_bundle, verification_time, true,
272 cast_trust_store.get(), crl_trust_store.get());
273 EXPECT_EQ(result.error_type, AuthResult::ERROR_CRL_INVALID);
274 return result.error_type == AuthResult::ERROR_CRL_INVALID;
275 case cast_certificate::CRL_EXPIRED_AFTER_INITIAL_VERIFICATION:
276 // By-pass this test because CRL is always verified at the time the
277 // certificate is verified.
278 return true;
279 case cast_certificate::REVOCATION_CHECK_FAILED:
280 result = TestVerifyRevocation(
281 certificate_chain, crl_bundle, verification_time, true,
282 cast_trust_store.get(), crl_trust_store.get());
283 EXPECT_EQ(result.error_type, AuthResult::ERROR_CERT_REVOKED);
284 return result.error_type == AuthResult::ERROR_CERT_REVOKED;
285 case cast_certificate::SUCCESS:
286 result = TestVerifyRevocation(
287 certificate_chain, crl_bundle, verification_time, false,
288 cast_trust_store.get(), crl_trust_store.get());
289 EXPECT_EQ(result.error_type, AuthResult::ERROR_SIGNED_BLOBS_MISMATCH);
290 return result.error_type == AuthResult::ERROR_SIGNED_BLOBS_MISMATCH;
291 case UNSPECIFIED:
292 return false;
293 }
294 return false;
295 }
296
297 // Parses the provided test suite provided in wire-format proto.
298 // Each test contains the inputs and the expected output.
299 // To see the description of the test, execute the test.
300 // These tests are generated by a test generator in google3.
301 void RunTestSuite(const std::string& test_suite_file_name) {
302 std::string testsuite_raw =
303 cast_certificate::testing::ReadTestFileToString(test_suite_file_name);
304 cast_certificate::DeviceCertTestSuite test_suite;
305 EXPECT_TRUE(test_suite.ParseFromString(testsuite_raw));
306 uint16_t success = 0;
307 uint16_t failed = 0;
308 std::vector<std::string> failed_tests;
309
310 for (auto const& test_case : test_suite.tests()) {
311 LOG(INFO) << "[ RUN ] " << test_case.description();
312 bool result = RunTest(test_case);
313 EXPECT_TRUE(result);
314 if (!result) {
315 LOG(INFO) << "[ FAILED ] " << test_case.description();
316 ++failed;
317 failed_tests.push_back(test_case.description());
318 } else {
319 LOG(INFO) << "[ PASSED ] " << test_case.description();
320 ++success;
321 }
322 }
323 LOG(INFO) << "[ PASSED ] " << success << " test(s).";
324 if (failed) {
325 LOG(INFO) << "[ FAILED ] " << failed << " test(s), listed below:";
326 for (const auto& failed_test : failed_tests) {
327 LOG(INFO) << "[ FAILED ] " << failed_test;
328 }
329 }
330 }
331
332 TEST_F(CastAuthUtilTest, CRLTestSuite) {
333 RunTestSuite("testsuite/testsuite1.pb");
334 }
335
336 } // namespace
337 } // namespace cast_channel
338 } // namespace api
339 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/cast_channel/cast_auth_util.cc ('k') | extensions/browser/api/cast_channel/cast_channel_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698