Index: extensions/browser/api/cast_channel/cast_auth_util_unittest.cc |
diff --git a/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc b/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc |
deleted file mode 100644 |
index b658068558b4e3f9daeb7218df6c955f73aa24be..0000000000000000000000000000000000000000 |
--- a/extensions/browser/api/cast_channel/cast_auth_util_unittest.cc |
+++ /dev/null |
@@ -1,339 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "extensions/browser/api/cast_channel/cast_auth_util.h" |
- |
-#include <string> |
- |
-#include "base/macros.h" |
-#include "base/test/scoped_feature_list.h" |
-#include "base/time/time.h" |
-#include "components/cast_certificate/cast_cert_validator.h" |
-#include "components/cast_certificate/cast_cert_validator_test_helpers.h" |
-#include "components/cast_certificate/cast_crl.h" |
-#include "components/cast_certificate/proto/test_suite.pb.h" |
-#include "extensions/common/api/cast_channel/cast_channel.pb.h" |
-#include "net/cert/internal/trust_store_in_memory.h" |
-#include "net/cert/x509_certificate.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace extensions { |
-namespace api { |
-namespace cast_channel { |
-namespace { |
- |
-class CastAuthUtilTest : public testing::Test { |
- public: |
- CastAuthUtilTest() {} |
- ~CastAuthUtilTest() override {} |
- |
- void SetUp() override {} |
- |
- protected: |
- static AuthResponse CreateAuthResponse(std::string* signed_data) { |
- auto chain = cast_certificate::testing::ReadCertificateChainFromFile( |
- "certificates/chromecast_gen1.pem"); |
- CHECK(!chain.empty()); |
- |
- auto signature_data = cast_certificate::testing::ReadSignatureTestData( |
- "signeddata/2ZZBG9_FA8FCA3EF91A.pem"); |
- |
- AuthResponse response; |
- |
- response.set_client_auth_certificate(chain[0]); |
- for (size_t i = 1; i < chain.size(); ++i) |
- response.add_intermediate_certificate(chain[i]); |
- |
- response.set_signature(signature_data.signature_sha1); |
- *signed_data = signature_data.message; |
- |
- return response; |
- } |
- |
- // Mangles a string by inverting the first byte. |
- static void MangleString(std::string* str) { (*str)[0] = ~(*str)[0]; } |
-}; |
- |
-// Note on expiration: VerifyCredentials() depends on the system clock. In |
-// practice this shouldn't be a problem though since the certificate chain |
-// being verified doesn't expire until 2032! |
-TEST_F(CastAuthUtilTest, VerifySuccess) { |
- std::string signed_data; |
- AuthResponse auth_response = CreateAuthResponse(&signed_data); |
- base::Time now = base::Time::Now(); |
- AuthResult result = VerifyCredentialsForTest( |
- auth_response, signed_data, cast_certificate::CRLPolicy::CRL_OPTIONAL, |
- nullptr, nullptr, now); |
- EXPECT_TRUE(result.success()); |
- EXPECT_EQ(AuthResult::POLICY_NONE, result.channel_policies); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyBadCA) { |
- std::string signed_data; |
- AuthResponse auth_response = CreateAuthResponse(&signed_data); |
- MangleString(auth_response.mutable_intermediate_certificate(0)); |
- AuthResult result = VerifyCredentials(auth_response, signed_data); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA, result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyBadClientAuthCert) { |
- std::string signed_data; |
- AuthResponse auth_response = CreateAuthResponse(&signed_data); |
- MangleString(auth_response.mutable_client_auth_certificate()); |
- AuthResult result = VerifyCredentials(auth_response, signed_data); |
- EXPECT_FALSE(result.success()); |
- // TODO(eroman): Not quite right of an error. |
- EXPECT_EQ(AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA, result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyBadSignature) { |
- std::string signed_data; |
- AuthResponse auth_response = CreateAuthResponse(&signed_data); |
- MangleString(auth_response.mutable_signature()); |
- AuthResult result = VerifyCredentials(auth_response, signed_data); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_SIGNED_BLOBS_MISMATCH, result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyBadPeerCert) { |
- std::string signed_data; |
- AuthResponse auth_response = CreateAuthResponse(&signed_data); |
- MangleString(&signed_data); |
- AuthResult result = VerifyCredentials(auth_response, signed_data); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_SIGNED_BLOBS_MISMATCH, result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifySenderNonceMatch) { |
- base::test::ScopedFeatureList scoped_feature_list; |
- scoped_feature_list.InitAndEnableFeature( |
- base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT}); |
- AuthContext context = AuthContext::Create(); |
- AuthResult result = context.VerifySenderNonce(context.nonce()); |
- EXPECT_TRUE(result.success()); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifySenderNonceMismatch) { |
- base::test::ScopedFeatureList scoped_feature_list; |
- scoped_feature_list.InitAndEnableFeature( |
- base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT}); |
- AuthContext context = AuthContext::Create(); |
- std::string received_nonce = "test2"; |
- EXPECT_NE(received_nonce, context.nonce()); |
- AuthResult result = context.VerifySenderNonce(received_nonce); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_SENDER_NONCE_MISMATCH, result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifySenderNonceMissing) { |
- base::test::ScopedFeatureList scoped_feature_list; |
- scoped_feature_list.InitAndEnableFeature( |
- base::Feature{"CastNonceEnforced", base::FEATURE_DISABLED_BY_DEFAULT}); |
- AuthContext context = AuthContext::Create(); |
- std::string received_nonce = ""; |
- EXPECT_FALSE(context.nonce().empty()); |
- AuthResult result = context.VerifySenderNonce(received_nonce); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_SENDER_NONCE_MISMATCH, result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyTLSCertificateSuccess) { |
- auto tls_cert_der = cast_certificate::testing::ReadCertificateChainFromFile( |
- "certificates/test_tls_cert.pem"); |
- |
- scoped_refptr<net::X509Certificate> tls_cert = |
- net::X509Certificate::CreateFromBytes(tls_cert_der[0].data(), |
- tls_cert_der[0].size()); |
- std::string peer_cert_der; |
- AuthResult result = |
- VerifyTLSCertificate(*tls_cert, &peer_cert_der, tls_cert->valid_start()); |
- EXPECT_TRUE(result.success()); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooEarly) { |
- auto tls_cert_der = cast_certificate::testing::ReadCertificateChainFromFile( |
- "certificates/test_tls_cert.pem"); |
- |
- scoped_refptr<net::X509Certificate> tls_cert = |
- net::X509Certificate::CreateFromBytes(tls_cert_der[0].data(), |
- tls_cert_der[0].size()); |
- std::string peer_cert_der; |
- AuthResult result = VerifyTLSCertificate( |
- *tls_cert, &peer_cert_der, |
- tls_cert->valid_start() - base::TimeDelta::FromSeconds(1)); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_TLS_CERT_VALID_START_DATE_IN_FUTURE, |
- result.error_type); |
-} |
- |
-TEST_F(CastAuthUtilTest, VerifyTLSCertificateTooLate) { |
- auto tls_cert_der = cast_certificate::testing::ReadCertificateChainFromFile( |
- "certificates/test_tls_cert.pem"); |
- |
- scoped_refptr<net::X509Certificate> tls_cert = |
- net::X509Certificate::CreateFromBytes(tls_cert_der[0].data(), |
- tls_cert_der[0].size()); |
- std::string peer_cert_der; |
- AuthResult result = VerifyTLSCertificate( |
- *tls_cert, &peer_cert_der, |
- tls_cert->valid_expiry() + base::TimeDelta::FromSeconds(2)); |
- EXPECT_FALSE(result.success()); |
- EXPECT_EQ(AuthResult::ERROR_TLS_CERT_EXPIRED, result.error_type); |
-} |
- |
-// Indicates the expected result of test step's verification. |
-enum TestStepResult { |
- RESULT_SUCCESS, |
- RESULT_FAIL, |
-}; |
- |
-// Verifies that the certificate chain provided is not revoked according to |
-// the provided Cast CRL at |verification_time|. |
-// The provided CRL is verified at |verification_time|. |
-// If |crl_required| is set, then a valid Cast CRL must be provided. |
-// Otherwise, a missing CRL is be ignored. |
-AuthResult TestVerifyRevocation( |
- const std::vector<std::string>& certificate_chain, |
- const std::string& crl_bundle, |
- const base::Time& verification_time, |
- bool crl_required, |
- net::TrustStore* cast_trust_store, |
- net::TrustStore* crl_trust_store) { |
- AuthResponse response; |
- |
- if (certificate_chain.size() > 0) { |
- response.set_client_auth_certificate(certificate_chain[0]); |
- for (size_t i = 1; i < certificate_chain.size(); ++i) |
- response.add_intermediate_certificate(certificate_chain[i]); |
- } |
- |
- response.set_crl(crl_bundle); |
- |
- cast_certificate::CRLPolicy crl_policy = |
- cast_certificate::CRLPolicy::CRL_REQUIRED; |
- if (!crl_required && crl_bundle.empty()) |
- crl_policy = cast_certificate::CRLPolicy::CRL_OPTIONAL; |
- AuthResult result = |
- VerifyCredentialsForTest(response, "", crl_policy, cast_trust_store, |
- crl_trust_store, verification_time); |
- // This test doesn't set the signature so it will just fail there. |
- EXPECT_FALSE(result.success()); |
- return result; |
-} |
- |
-// Runs a single test case. |
-bool RunTest(const cast_certificate::DeviceCertTest& test_case) { |
- std::unique_ptr<net::TrustStore> crl_trust_store; |
- std::unique_ptr<net::TrustStore> cast_trust_store; |
- if (test_case.use_test_trust_anchors()) { |
- crl_trust_store = cast_certificate::testing::CreateTrustStoreFromFile( |
- "certificates/cast_crl_test_root_ca.pem"); |
- cast_trust_store = cast_certificate::testing::CreateTrustStoreFromFile( |
- "certificates/cast_test_root_ca.pem"); |
- |
- EXPECT_TRUE(crl_trust_store.get()); |
- EXPECT_TRUE(cast_trust_store.get()); |
- } |
- |
- std::vector<std::string> certificate_chain; |
- for (auto const& cert : test_case.der_cert_path()) { |
- certificate_chain.push_back(cert); |
- } |
- |
- // CastAuthUtil verifies the CRL at the same time as the certificate. |
- base::Time verification_time; |
- uint64_t cert_verify_time = test_case.cert_verification_time_seconds(); |
- if (cert_verify_time) { |
- verification_time = cast_certificate::testing::ConvertUnixTimestampSeconds( |
- cert_verify_time); |
- } else { |
- verification_time = cast_certificate::testing::ConvertUnixTimestampSeconds( |
- test_case.crl_verification_time_seconds()); |
- } |
- |
- std::string crl_bundle = test_case.crl_bundle(); |
- AuthResult result; |
- switch (test_case.expected_result()) { |
- case cast_certificate::PATH_VERIFICATION_FAILED: |
- result = TestVerifyRevocation( |
- certificate_chain, crl_bundle, verification_time, false, |
- cast_trust_store.get(), crl_trust_store.get()); |
- EXPECT_EQ(result.error_type, |
- AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA); |
- return result.error_type == |
- AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA; |
- case cast_certificate::CRL_VERIFICATION_FAILED: |
- // Fall-through intended. |
- case cast_certificate::REVOCATION_CHECK_FAILED_WITHOUT_CRL: |
- result = TestVerifyRevocation( |
- certificate_chain, crl_bundle, verification_time, true, |
- cast_trust_store.get(), crl_trust_store.get()); |
- EXPECT_EQ(result.error_type, AuthResult::ERROR_CRL_INVALID); |
- return result.error_type == AuthResult::ERROR_CRL_INVALID; |
- case cast_certificate::CRL_EXPIRED_AFTER_INITIAL_VERIFICATION: |
- // By-pass this test because CRL is always verified at the time the |
- // certificate is verified. |
- return true; |
- case cast_certificate::REVOCATION_CHECK_FAILED: |
- result = TestVerifyRevocation( |
- certificate_chain, crl_bundle, verification_time, true, |
- cast_trust_store.get(), crl_trust_store.get()); |
- EXPECT_EQ(result.error_type, AuthResult::ERROR_CERT_REVOKED); |
- return result.error_type == AuthResult::ERROR_CERT_REVOKED; |
- case cast_certificate::SUCCESS: |
- result = TestVerifyRevocation( |
- certificate_chain, crl_bundle, verification_time, false, |
- cast_trust_store.get(), crl_trust_store.get()); |
- EXPECT_EQ(result.error_type, AuthResult::ERROR_SIGNED_BLOBS_MISMATCH); |
- return result.error_type == AuthResult::ERROR_SIGNED_BLOBS_MISMATCH; |
- case UNSPECIFIED: |
- return false; |
- } |
- return false; |
-} |
- |
-// Parses the provided test suite provided in wire-format proto. |
-// Each test contains the inputs and the expected output. |
-// To see the description of the test, execute the test. |
-// These tests are generated by a test generator in google3. |
-void RunTestSuite(const std::string& test_suite_file_name) { |
- std::string testsuite_raw = |
- cast_certificate::testing::ReadTestFileToString(test_suite_file_name); |
- cast_certificate::DeviceCertTestSuite test_suite; |
- EXPECT_TRUE(test_suite.ParseFromString(testsuite_raw)); |
- uint16_t success = 0; |
- uint16_t failed = 0; |
- std::vector<std::string> failed_tests; |
- |
- for (auto const& test_case : test_suite.tests()) { |
- LOG(INFO) << "[ RUN ] " << test_case.description(); |
- bool result = RunTest(test_case); |
- EXPECT_TRUE(result); |
- if (!result) { |
- LOG(INFO) << "[ FAILED ] " << test_case.description(); |
- ++failed; |
- failed_tests.push_back(test_case.description()); |
- } else { |
- LOG(INFO) << "[ PASSED ] " << test_case.description(); |
- ++success; |
- } |
- } |
- LOG(INFO) << "[ PASSED ] " << success << " test(s)."; |
- if (failed) { |
- LOG(INFO) << "[ FAILED ] " << failed << " test(s), listed below:"; |
- for (const auto& failed_test : failed_tests) { |
- LOG(INFO) << "[ FAILED ] " << failed_test; |
- } |
- } |
-} |
- |
-TEST_F(CastAuthUtilTest, CRLTestSuite) { |
- RunTestSuite("testsuite/testsuite1.pb"); |
-} |
- |
-} // namespace |
-} // namespace cast_channel |
-} // namespace api |
-} // namespace extensions |