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

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

Powered by Google App Engine
This is Rietveld 408576698