Merge from Widevine repo of http://go/wvgerrit/56521 This CL adds a common main routine for integration tests. It sets a default test configuration for the provisioning and license server urls and certificates, and allows the user to set them on the command line. Test: current unit tests still pass. Bug: 72354901 Fix Generic Crypto tests. Change-Id: I604a3d9e15d50da5041794624c4571c0dcb091f5
260 lines
9.0 KiB
C++
260 lines
9.0 KiB
C++
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine Master
|
|
// License Agreement.
|
|
// This file adds some print methods so that when unit tests fail, the
|
|
// will print the name of an enumeration instead of the numeric value.
|
|
|
|
#include "test_base.h"
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <openssl/aes.h>
|
|
#include <openssl/bio.h>
|
|
#include <openssl/cmac.h>
|
|
#include <openssl/err.h>
|
|
|
|
#include "cdm_engine.h"
|
|
#include "crypto_session.h"
|
|
#include "file_store.h"
|
|
#include "log.h"
|
|
#include "oec_device_features.h"
|
|
#include "oec_test_data.h"
|
|
#include "properties.h"
|
|
#include "test_printers.h"
|
|
#include "url_request.h"
|
|
|
|
namespace wvcdm {
|
|
namespace {
|
|
void show_menu(char* prog_name) {
|
|
std::cout << std::endl;
|
|
std::cout << "usage: " << prog_name << " [options]" << std::endl << std::endl;
|
|
std::cout << " enclose multiple arguments in '' when using adb shell"
|
|
<< std::endl;
|
|
std::cout << " e.g. adb shell '" << prog_name << " --server=\"url\"'"
|
|
<< std::endl;
|
|
std::cout << " or adb shell '" << prog_name << " -u\"url\"'" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -v/--verbose" << std::endl;
|
|
std::cout << " increase logging verbosity (may be repeated)" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -f/--no_filter" << std::endl;
|
|
std::cout << " Do not filter out inappropriate tests" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -c/--cast" << std::endl;
|
|
std::cout << " Run tests appropriate for a Cast Receiver" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -i/--license_server_id=<gp/cp/st>" << std::endl;
|
|
std::cout << " specifies which default server settings to use: "
|
|
<< std::endl;
|
|
std::cout << " gp for GooglePlay server" << std::endl;
|
|
std::cout << " cp for Content Protection UAT server" << std::endl;
|
|
std::cout << " st for Content Protection Staging server" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -k/--keyid=<key_id>" << std::endl;
|
|
std::cout << " configure the key id or pssh, in hex format" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -s/--service_certificate=<cert>" << std::endl;
|
|
std::cout << " configure the signed license service certificate" << std::endl;
|
|
std::cout << " Specify the SignedDeviceCertificate (from "
|
|
<< "device_certificate.proto) " << std::endl;
|
|
std::cout << " in hex format." << std::endl;
|
|
std::cout << " Due to the length of the argument use, " << std::endl;
|
|
std::cout << " echo \"/system/bin/request_license_test -s \\\""
|
|
<< "0ABF02...A29914\\\"\" \\" << std::endl;
|
|
std::cout << " > run_request_license_test.sh" << std::endl;
|
|
std::cout << " chmod +x run_request_license_test.sh" << std::endl;
|
|
std::cout << " adb push run_request_license_test.sh /system/bin"
|
|
<< std::endl;
|
|
std::cout << " adb shell sh /system/bin/run_request_license_test.sh"
|
|
<< std::endl << std::endl;
|
|
|
|
std::cout << " -S/--provisioning_certificate=<cert>" << std::endl;
|
|
std::cout << " configure the signed provisioning service certificate" << std::endl
|
|
<< " in hex" << std::endl << std::endl;
|
|
|
|
std::cout << " -u/--license_server_url=<url>" << std::endl;
|
|
std::cout << " configure the license server url, please include http[s]"
|
|
<< " in the url" << std::endl
|
|
<< std::endl;
|
|
|
|
std::cout << " -p/--provisioning_server_url=<url>" << std::endl;
|
|
std::cout << " configure the provisioning server url, please include http[s]"
|
|
<< " in the url" << std::endl
|
|
<< std::endl;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
ConfigTestEnv WvCdmTestBase::default_config_(kContentProtectionUatServer);
|
|
|
|
TestCryptoSession::TestCryptoSession(metrics::CryptoMetrics* crypto_metrics)
|
|
: CryptoSession(crypto_metrics) {
|
|
// The first CryptoSession should have initialized OEMCrypto. This is right
|
|
// after that, so should tell oemcrypto to use a test keybox.
|
|
if (session_count() == 1) {
|
|
WvCdmTestBase::InstallTestRootOfTrust();
|
|
}
|
|
}
|
|
|
|
bool TestCryptoSession::GenerateNonce(uint32_t* nonce) {
|
|
for (int i = 0; !CryptoSession::GenerateNonce(nonce); i++) {
|
|
LOGV("Recovering from nonce flood.");
|
|
if (i > 2) return false;
|
|
sleep(1);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
class TestCryptoSessionFactory : public CryptoSessionFactory {
|
|
CryptoSession* MakeCryptoSession(metrics::CryptoMetrics* crypto_metrics) {
|
|
return new TestCryptoSession(crypto_metrics);
|
|
}
|
|
};
|
|
|
|
void WvCdmTestBase::SetUp() {
|
|
::testing::Test::SetUp();
|
|
Properties::Init();
|
|
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());
|
|
CryptoSession::SetCryptoSessionFactory(new TestCryptoSessionFactory());
|
|
// TODO(fredgc): Add a test version of DeviceFiles.
|
|
}
|
|
|
|
void WvCdmTestBase::InstallTestRootOfTrust() {
|
|
switch (wvoec::global_features.derive_key_method) {
|
|
case wvoec::DeviceFeatures::LOAD_TEST_KEYBOX:
|
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
OEMCrypto_LoadTestKeybox(
|
|
reinterpret_cast<const uint8_t*>(&wvoec::kTestKeybox),
|
|
sizeof(wvoec::kTestKeybox)));
|
|
break;
|
|
case wvoec::DeviceFeatures::LOAD_TEST_RSA_KEY:
|
|
// Rare case: used by devices with baked in DRM cert.
|
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
|
break;
|
|
case wvoec::DeviceFeatures::TEST_PROVISION_30:
|
|
// Can use oem certificate to install test rsa key.
|
|
break;
|
|
default:
|
|
FAIL() << "Cannot run test without test keybox or RSA key installed.";
|
|
}
|
|
}
|
|
|
|
bool WvCdmTestBase::Initialize(int argc, char **argv) {
|
|
Properties::Init();
|
|
bool is_cast_receiver = false;
|
|
bool force_load_test_keybox = false; // TODO(fredgc): obsolete. remove.
|
|
bool filter_tests = true;
|
|
bool show_usage = false;
|
|
|
|
static const struct option long_options[] = {
|
|
{"license_server_id", required_argument, NULL, 'i'},
|
|
{"keyid", required_argument, NULL, 'k'},
|
|
{"service_certificate", required_argument, NULL, 's'},
|
|
{"provisioning_certificate", required_argument, NULL, 'S'},
|
|
{"license_server_url", required_argument, NULL, 'u'},
|
|
{"provisioning_server_url", required_argument, NULL, 'p'},
|
|
{"cast", no_argument, NULL, 'c'},
|
|
{"no_filter", no_argument, NULL, 'f'},
|
|
{"verbose", no_argument, NULL, 'v'},
|
|
{NULL, 0, NULL, '\0'}};
|
|
|
|
int option_index = 0;
|
|
int opt = 0;
|
|
int verbosity = 0;
|
|
while ((opt = getopt_long(argc, argv, "i:k:s:S:u:p:cfv", long_options,
|
|
&option_index)) != -1) {
|
|
switch (opt) {
|
|
case 'i': {
|
|
std::string license_id(optarg);
|
|
if (!license_id.compare("gp")) {
|
|
default_config_ = ConfigTestEnv(kGooglePlayServer);
|
|
} else if (!license_id.compare("cp")) {
|
|
default_config_ = ConfigTestEnv(kContentProtectionUatServer);
|
|
} else if (!license_id.compare("st")) {
|
|
default_config_ = ConfigTestEnv(kContentProtectionStagingServer);
|
|
} else {
|
|
std::cout << "Invalid license server id" << optarg << std::endl;
|
|
show_usage = true;
|
|
}
|
|
break;
|
|
}
|
|
case 'k': {
|
|
std::string key_id(optarg);
|
|
default_config_.set_key_id(key_id);
|
|
break;
|
|
}
|
|
case 's': {
|
|
std::string certificate(a2bs_hex(optarg));
|
|
default_config_.set_license_service_certificate(certificate);
|
|
break;
|
|
}
|
|
case 'S': {
|
|
std::string certificate(a2bs_hex(optarg));
|
|
default_config_.set_provisioning_service_certificate(certificate);
|
|
break;
|
|
}
|
|
case 'u': {
|
|
std::string server(optarg);
|
|
default_config_.set_license_server(server);
|
|
break;
|
|
}
|
|
case 'p': {
|
|
std::string server(optarg);
|
|
default_config_.set_provisioning_server(server);
|
|
break;
|
|
}
|
|
case 'c': {
|
|
is_cast_receiver = true;
|
|
break;
|
|
}
|
|
case 'f': {
|
|
filter_tests = false;
|
|
break;
|
|
}
|
|
case 'v': {
|
|
++verbosity;
|
|
break;
|
|
}
|
|
case '?': {
|
|
show_usage = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (show_usage) {
|
|
show_menu(argv[0]);
|
|
return false;
|
|
}
|
|
|
|
g_cutoff = static_cast<LogPriority>(verbosity);
|
|
|
|
// Displays server url, port and key Id being used
|
|
std::cout << std::endl;
|
|
std::cout << "Default Server: " << default_config_.license_server()
|
|
<< std::endl;
|
|
std::cout << "Default KeyID: " << default_config_.key_id() << std::endl
|
|
<< std::endl;
|
|
|
|
// Figure out which tests are appropriate for OEMCrypto, based on features
|
|
// supported.
|
|
wvoec::global_features.Initialize(is_cast_receiver, force_load_test_keybox);
|
|
// If the user requests --no_filter, we don't change the filter, otherwise, we
|
|
// filter out features that are not supported.
|
|
if (filter_tests) {
|
|
::testing::GTEST_FLAG(filter) =
|
|
wvoec::global_features.RestrictFilter(::testing::GTEST_FLAG(filter));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace wvcdm
|