Files
ce_cdm/core/test/keybox_ota_test.cpp
2024-03-28 19:15:22 -07:00

149 lines
6.0 KiB
C++

// 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 <gtest/gtest.h>
#include <chrono>
#include <memory>
#include <thread>
#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<wvutil::FileSystem> file_system(CreateTestFileSystem());
TestCdmEngine cdm_engine(file_system.get(),
std::shared_ptr<EngineMetrics>(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