// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine Master // License Agreement. #include #include #include #include #include "create_test_file_system.h" #include "crypto_session.h" #include "oec_device_features.h" #include "properties.h" #include "provisioning_holder.h" #include "test_base.h" #include "test_printers.h" #include "test_sleep.h" #include "url_request.h" using wvcdm::metrics::EngineMetrics; namespace wvcdm { class CdmOtaKeyboxTest : public ::testing::Test { public: void SetUp() override { if (wvoec::global_features.provisioning_method != OEMCrypto_Keybox) { GTEST_SKIP() << "Test for Prov 2.0 devices only."; } ::testing::Test::SetUp(); Properties::Init(); if (wvoec::global_features.provisioning_method != OEMCrypto_Keybox) { GTEST_SKIP() << "Test for Prov 2.0 devices only."; } const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); LOGD("Running test %s.%s", test_info->test_case_name(), test_info->name()); // Some test environments allow the model name of the device to be set // dynamically using an environment variable. The model name will show up // in the license server logs as the part of the device idenfication as // "model_name". std::string model_name = std::string(test_info->test_case_name()) + "." + test_info->name(); int overwrite = 1; // Set value even if already set. setenv("MODEL_NAME", model_name.c_str(), overwrite); // Reset the crypto session factory, so that a default one will be created. // For these tests, we do *not* want to use the test crypto session factory // because it automatically installs the test keybox on initialization. We // do not want that because we are testing keybox provisioning. CryptoSession::SetCryptoSessionFactory(nullptr); } void Provision(TestCdmEngine* cdm_engine) { ConfigTestEnv config = *WvCdmTestBase::default_config_; ProvisioningHolder provisioner(cdm_engine, config); CdmCertificateType cert_type = kCertificateWidevine; constexpr bool binary_provisioning = false; provisioner.Provision(cert_type, binary_provisioning); } }; TEST_F(CdmOtaKeyboxTest, TestThatTheBuildFilesWork) { ASSERT_TRUE(true); } /** Verify that the CDM can open a session with at most two provisioning * steps. Unlike almost all of the other Widevine CDM tests, this test does * **not** install a test keybox before running. For that reason, this test is * expected to fail if the device does not either support Keybox OTA recover or * have an existing keybox or OEM Certificate. For those devices, this test * should be skipped. */ TEST_F(CdmOtaKeyboxTest, BasicTest) { std::unique_ptr file_system(CreateTestFileSystem()); TestCdmEngine cdm_engine(file_system.get(), std::shared_ptr(new EngineMetrics)); // Remove any existing certificate. cdm_engine.Unprovision(kSecurityLevelL1); std::string system_id; CdmResponseType system_id_status = cdm_engine.QueryStatus(kLevelDefault, QUERY_KEY_SYSTEM_ID, &system_id); if (system_id_status == NO_ERROR) { std::cout << " " << "System ID before test: " << system_id << "\n"; } else { std::cout << " " << "Could not find system id before test. "; PrintTo(system_id_status, &std::cout); std::cout << "\n"; } CdmSessionId session_id; ConfigTestEnv config = *WvCdmTestBase::default_config_; CdmResponseType status = cdm_engine.OpenSession(config.key_system(), nullptr, nullptr, &session_id); // If there is no keybox or there is no drm cert, we should get a // NEED_PROVISIONING response. If there is a keybox and a drm cert, there // should be no other error and this test is finished. if (status != NEED_PROVISIONING) { ASSERT_EQ(NO_ERROR, status); std::cout << "Device does not need provisioning. Skipping rest of test.\n"; return; } std::cout << "First provisioning process.\n"; Provision(&cdm_engine); system_id_status = cdm_engine.QueryStatus(kLevelDefault, QUERY_KEY_SYSTEM_ID, &system_id); if (system_id_status == NO_ERROR) { std::cout << " " << "System ID after first provisioning: " << system_id << "\n"; } else { std::cout << " " << "Could not find system id after first provisioning. "; PrintTo(system_id_status, &std::cout); std::cout << "\n"; } // After the first provisioning pass, we try to open a session again. If the // first provisioning was to install a keybox, this provisioning should be to // install a drm cert. If the first provisioning step installed a drm cert, // there should be no other error and this test is finished. status = cdm_engine.OpenSession(config.key_system(), nullptr, nullptr, &session_id); if (status != NEED_PROVISIONING) { ASSERT_EQ(NO_ERROR, status); std::cout << "Device does not need provisioning. Skipping rest of test.\n"; return; } std::cout << "Second provisioning process.\n"; Provision(&cdm_engine); system_id_status = cdm_engine.QueryStatus(kLevelDefault, QUERY_KEY_SYSTEM_ID, &system_id); if (system_id_status == NO_ERROR) { std::cout << " " << "System ID after second provisioning: " << system_id << "\n"; } else { std::cout << " " << "Could not find system id after second provisioning. "; PrintTo(system_id_status, &std::cout); std::cout << "\n"; } // After the second provisioning pass, we should be able to open a session // and continue. status = cdm_engine.OpenSession(config.key_system(), nullptr, nullptr, &session_id); ASSERT_EQ(NO_ERROR, status); // Full recovery will be tested with higher level integration tests. } } // namespace wvcdm