cast_auth_util_unittest.cc 15 KB

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