File util, generic crypto, and key query

This CL merges several CLs from the widevine repo:

http://go/wvgerrit/18012 Add support for querying allowed usage for key.
http://go/wvgerrit/17971 Add per-origin storage.
http://go/wvgerrit/18152 Add OEMCrypto's generic crypto operations to CDM.
http://go/wvgerrit/17911 QueryKeyControlInfo => QueryOemCryptoSessionId

Note: numbering in wv_cdm_types.h was added in this CL and will be
back ported to wvgerrit in a future CL.

Change-Id: Idb9e9a67e94f62f25dc16c5307f75a08b3430b64
This commit is contained in:
Fred Gylys-Colwell
2016-09-14 12:44:09 -07:00
parent 24124ea6e3
commit eb3f8b786a
56 changed files with 4632 additions and 2083 deletions

View File

@@ -4,6 +4,7 @@
// This is because we need a valid RSA certificate, and will attempt to connect
// to the provisioning server to request one if we don't.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>
@@ -43,6 +44,8 @@ const std::string kWebmMimeType = "video/webm";
class WvCdmEngineTest : public testing::Test {
public:
WvCdmEngineTest() : cdm_engine_(&file_system_) {}
static void SetUpTestCase() {
ConfigTestEnv config(kContentProtectionUatServer);
g_client_auth.assign(config.client_auth());
@@ -52,19 +55,16 @@ class WvCdmEngineTest : public testing::Test {
g_key_id_pssh.assign(a2bs_hex(config.key_id()));
// Extract the key ID from the PSSH box.
InitializationData extractor(CENC_INIT_DATA_FORMAT,
g_key_id_pssh);
InitializationData extractor(CENC_INIT_DATA_FORMAT, g_key_id_pssh);
g_key_id_unwrapped = extractor.data();
}
virtual void SetUp() {
CdmResponseType status =
cdm_engine_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
&session_id_);
cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
if (status == NEED_PROVISIONING) {
Provision();
status = cdm_engine_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL,
&session_id_);
status = cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_);
}
ASSERT_EQ(NO_ERROR, status);
ASSERT_NE("", session_id_) << "Could not open CDM session.";
@@ -81,15 +81,15 @@ class WvCdmEngineTest : public testing::Test {
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR, cdm_engine_.GetProvisioningRequest(
cert_type, cert_authority, EMPTY_ORIGIN,
&prov_request, &provisioning_server_url));
cert_type, cert_authority, &prov_request,
&provisioning_server_url));
UrlRequest url_request(provisioning_server_url);
EXPECT_TRUE(url_request.is_connected());
url_request.PostCertRequestInQueryString(prov_request);
std::string message;
bool ok = url_request.GetResponse(&message);
EXPECT_TRUE(ok);
ASSERT_EQ(NO_ERROR, cdm_engine_.HandleProvisioningResponse(EMPTY_ORIGIN,
message, &cert,
ASSERT_EQ(NO_ERROR, cdm_engine_.HandleProvisioningResponse(message, &cert,
&wrapped_key));
}
@@ -113,9 +113,8 @@ class WvCdmEngineTest : public testing::Test {
void GenerateRenewalRequest() {
CdmKeyRequest request;
EXPECT_EQ(KEY_MESSAGE, cdm_engine_.GenerateRenewalRequest(
session_id_, &request));
EXPECT_EQ(KEY_MESSAGE,
cdm_engine_.GenerateRenewalRequest(session_id_, &request));
key_msg_ = request.message;
server_url_ = request.url;
@@ -177,6 +176,7 @@ class WvCdmEngineTest : public testing::Test {
EXPECT_EQ(KEY_ADDED, cdm_engine_.RenewKey(session_id_, resp));
}
FileSystem file_system_;
CdmEngine cdm_engine_;
std::string key_msg_;
std::string session_id_;

View File

@@ -88,13 +88,12 @@ const std::string kWrappedKey = a2bs_hex(
"E74C92B44F9205D22262FB47948654229DE1920F8EDF96A19A88A1CA1552F8856FB4CBF83B"
"AA3348419159D207F65FCE9C1A500C6818");
const std::string kTestOrigin = "com.google";
class MockDeviceFiles : public DeviceFiles {
public:
MockDeviceFiles() : DeviceFiles(NULL) {}
MOCK_METHOD1(Init, bool(CdmSecurityLevel));
MOCK_METHOD3(RetrieveCertificate, bool(const std::string&, std::string*,
std::string*));
MOCK_METHOD2(RetrieveCertificate, bool(std::string*, std::string*));
};
class MockCryptoSession : public CryptoSession {
@@ -136,7 +135,7 @@ using ::testing::StrEq;
class CdmSessionTest : public ::testing::Test {
protected:
virtual void SetUp() {
cdm_session_.reset(new CdmSession(kTestOrigin));
cdm_session_.reset(new CdmSession(NULL));
// Inject testing mocks.
license_parser_ = new MockCdmLicense(cdm_session_->session_id());
cdm_session_->set_license_parser(license_parser_);
@@ -165,9 +164,8 @@ TEST_F(CdmSessionTest, InitWithCertificate) {
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(StrEq(kTestOrigin), NotNull(),
NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kToken), SetArgPointee<1>(kWrappedKey),
Return(true)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
.InSequence(crypto_session_seq)
@@ -213,9 +211,8 @@ TEST_F(CdmSessionTest, ReInitFail) {
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(StrEq(kTestOrigin), NotNull(),
NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kToken), SetArgPointee<1>(kWrappedKey),
Return(true)));
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
.InSequence(crypto_session_seq)
@@ -249,8 +246,7 @@ TEST_F(CdmSessionTest, InitNeedsProvisioning) {
.InSequence(crypto_session_seq)
.WillOnce(Return(level));
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
EXPECT_CALL(*file_handle_, RetrieveCertificate(StrEq(kTestOrigin), NotNull(),
NotNull()))
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
.WillOnce(Return(false));
Properties::set_use_certificates_as_identification(true);

View File

@@ -1412,19 +1412,24 @@ const std::string kTestOrigin = "com.google";
class MockFile : public File {
public:
MOCK_METHOD2(Open, bool(const std::string&, int flags));
MOCK_METHOD0(Close, void());
MockFile() : File(NULL) {}
~MockFile() {}
MOCK_METHOD2(Read, ssize_t(char*, size_t));
MOCK_METHOD2(Write, ssize_t(const char*, size_t));
MOCK_METHOD0(Close, void());
};
class MockFileSystem : public FileSystem {
public:
MockFileSystem() {}
~MockFileSystem() {}
MOCK_METHOD2(Open, File*(const std::string&, int flags));
MOCK_METHOD0(IsFactoryReset, bool());
MOCK_METHOD1(Exists, bool(const std::string&));
MOCK_METHOD1(Remove, bool(const std::string&));
MOCK_METHOD2(Copy, bool(const std::string&, const std::string&));
MOCK_METHOD2(List, bool(const std::string&, std::vector<std::string>*));
MOCK_METHOD1(CreateDirectory, bool(const std::string));
MOCK_METHOD1(IsDirectory, bool(const std::string&));
MOCK_METHOD1(IsRegularFile, bool(const std::string&));
MOCK_METHOD1(FileSize, ssize_t(const std::string&));
};
@@ -1490,21 +1495,9 @@ class DeviceFilesTest : public ::testing::Test {
class DeviceFilesStoreTest : public DeviceFilesTest,
public ::testing::WithParamInterface<bool> {};
struct CertStorageVariant {
CertStorageVariant(bool dir_exists_value, const std::string& origin_value)
: dir_exists(dir_exists_value), origin(origin_value) {}
class DeviceCertificateStoreTest : public DeviceFilesTest {};
const bool dir_exists;
const std::string origin;
};
class DeviceCertificateStoreTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<CertStorageVariant> {};
class DeviceCertificateTest
: public DeviceFilesTest,
public ::testing::WithParamInterface<std::string> {};
class DeviceCertificateTest : public DeviceFilesTest {};
class DeviceFilesSecurityLevelTest
: public DeviceFilesTest,
@@ -1513,8 +1506,7 @@ class DeviceFilesSecurityLevelTest
class DeviceFilesUsageInfoTest : public DeviceFilesTest,
public ::testing::WithParamInterface<int> {};
MATCHER(IsCreateFileFlagSet, "") { return File::kCreate & arg; }
MATCHER(IsBinaryFileFlagSet, "") { return File::kBinary & arg; }
MATCHER(IsCreateFileFlagSet, "") { return FileSystem::kCreate & arg; }
MATCHER_P(IsStrEq, str, "") {
// Estimating the length of data. We can have gmock provide length
// as well as pointer to data but that will introduce a dependency on tr1
@@ -1586,105 +1578,78 @@ MATCHER_P7(Contains, str1, str2, str3, str4, str5, str6, map7, "") {
data.find(str6) != std::string::npos && map7_entries_present);
}
TEST_P(DeviceCertificateStoreTest, StoreCertificate) {
MockFile file;
CertStorageVariant params = GetParam();
TEST_F(DeviceCertificateStoreTest, StoreCertificate) {
MockFileSystem file_system;
std::string certificate(GenerateRandomData(kCertificateLen));
std::string wrapped_private_key(GenerateRandomData(kWrappedKeyLen));
std::string device_certificate_path =
device_base_path_ + DeviceFiles::GetCertificateFileName(params.origin);
device_base_path_ + DeviceFiles::GetCertificateFileName();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.WillOnce(Return(params.dir_exists));
if (params.dir_exists) {
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
} else {
EXPECT_CALL(file, CreateDirectory(StrEq(device_base_path_)))
.WillOnce(Return(true));
}
EXPECT_CALL(file, Open(StrEq(device_certificate_path),
AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet())))
.WillOnce(Return(true));
MockFile file;
EXPECT_CALL(file_system,
Open(StrEq(device_certificate_path), IsCreateFileFlagSet()))
.WillOnce(Return(&file));
EXPECT_CALL(file, Write(Contains(certificate, wrapped_private_key, 0),
Gt(certificate.size() + wrapped_private_key.size())))
.WillOnce(ReturnArg<1>());
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Read(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
EXPECT_TRUE(device_files.StoreCertificate(params.origin, certificate,
wrapped_private_key));
EXPECT_TRUE(device_files.StoreCertificate(certificate, wrapped_private_key));
}
INSTANTIATE_TEST_CASE_P(
StoreCertificate, DeviceCertificateStoreTest,
::testing::Values(CertStorageVariant(true, EMPTY_ORIGIN),
CertStorageVariant(true, kTestOrigin),
CertStorageVariant(false, EMPTY_ORIGIN),
CertStorageVariant(false, kTestOrigin)));
TEST_P(DeviceCertificateTest, ReadCertificate) {
MockFile file;
std::string origin = GetParam();
TEST_F(DeviceCertificateTest, ReadCertificate) {
MockFileSystem file_system;
std::string device_certificate_path =
device_base_path_ + DeviceFiles::GetCertificateFileName(origin);
device_base_path_ + DeviceFiles::GetCertificateFileName();
std::string data = a2bs_hex(kTestCertificateFileData);
EXPECT_CALL(file, Exists(StrEq(device_certificate_path)))
MockFile file;
EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
.WillOnce(Return(true));
EXPECT_CALL(file, FileSize(StrEq(device_certificate_path)))
EXPECT_CALL(file_system, FileSize(StrEq(device_certificate_path)))
.WillOnce(Return(data.size()));
EXPECT_CALL(file, Open(StrEq(device_certificate_path), IsBinaryFileFlagSet()))
.WillOnce(Return(true));
EXPECT_CALL(file_system, Open(StrEq(device_certificate_path), _))
.WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
Return(data.size())));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Write(_, _)).Times(0);
if (Properties::security_level_path_backward_compatibility_support()) {
EXPECT_CALL(file, List(_, NotNull())).WillOnce(Return(false));
}
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
std::string certificate, wrapped_private_key;
ASSERT_TRUE(device_files.RetrieveCertificate(origin, &certificate,
&wrapped_private_key));
ASSERT_TRUE(
device_files.RetrieveCertificate(&certificate, &wrapped_private_key));
EXPECT_EQ(kTestCertificate, b2a_hex(certificate));
EXPECT_EQ(kTestWrappedPrivateKey, b2a_hex(wrapped_private_key));
}
TEST_P(DeviceCertificateTest, HasCertificate) {
MockFile file;
std::string origin = GetParam();
TEST_F(DeviceCertificateTest, HasCertificate) {
MockFileSystem file_system;
std::string device_certificate_path =
device_base_path_ + DeviceFiles::GetCertificateFileName(origin);
device_base_path_ + DeviceFiles::GetCertificateFileName();
EXPECT_CALL(file, Exists(StrEq(device_certificate_path)))
EXPECT_CALL(file_system, Exists(StrEq(device_certificate_path)))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(file, Open(_, _)).Times(0);
EXPECT_CALL(file_system, Open(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
ASSERT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
// MockFile returns false.
EXPECT_FALSE(device_files.HasCertificate(origin));
EXPECT_FALSE(device_files.HasCertificate());
// MockFile returns true.
EXPECT_TRUE(device_files.HasCertificate(origin));
EXPECT_TRUE(device_files.HasCertificate());
}
INSTANTIATE_TEST_CASE_P(CertificateUseTests, DeviceCertificateTest,
::testing::Values(EMPTY_ORIGIN, kTestOrigin));
TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
MockFile file;
MockFileSystem file_system;
std::string certificate(GenerateRandomData(kCertificateLen));
std::string wrapped_private_key(GenerateRandomData(kWrappedKeyLen));
@@ -1693,55 +1658,39 @@ TEST_P(DeviceFilesSecurityLevelTest, SecurityLevel) {
ASSERT_TRUE(
Properties::GetDeviceFilesBasePath(security_level, &device_base_path));
std::string device_certificate_path =
device_base_path + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
device_base_path + DeviceFiles::GetCertificateFileName();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path)))
.WillOnce(Return(false));
EXPECT_CALL(file, CreateDirectory(StrEq(device_base_path)))
.WillOnce(Return(true));
EXPECT_CALL(file, Open(StrEq(device_certificate_path),
AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet())))
.WillOnce(Return(true));
MockFile file;
EXPECT_CALL(file_system,
Open(StrEq(device_certificate_path), IsCreateFileFlagSet()))
.WillOnce(Return(&file));
EXPECT_CALL(file, Write(Contains(certificate, wrapped_private_key, 0),
Gt(certificate.size() + wrapped_private_key.size())))
.WillOnce(ReturnArg<1>());
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Read(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(security_level));
device_files.SetTestFile(&file);
EXPECT_TRUE(device_files.StoreCertificate(EMPTY_ORIGIN, certificate,
wrapped_private_key));
EXPECT_TRUE(device_files.StoreCertificate(certificate, wrapped_private_key));
}
INSTANTIATE_TEST_CASE_P(SecurityLevel, DeviceFilesSecurityLevelTest,
::testing::Values(kSecurityLevelL1, kSecurityLevelL3));
TEST_P(DeviceFilesStoreTest, StoreLicense) {
MockFile file;
MockFileSystem file_system;
size_t license_num = 0;
std::string license_path = device_base_path_ +
license_test_data[license_num].key_set_id +
DeviceFiles::GetLicenseFileNameExtension();
bool dir_exists = GetParam();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.WillOnce(Return(dir_exists));
if (dir_exists) {
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
} else {
EXPECT_CALL(file, CreateDirectory(StrEq(device_base_path_)))
.WillOnce(Return(true));
}
CdmAppParameterMap app_parameters =
GetAppParameters(license_test_data[license_num].app_parameters);
EXPECT_CALL(file, Open(StrEq(license_path),
AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet())))
.WillOnce(Return(true));
MockFile file;
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
.WillOnce(Return(&file));
EXPECT_CALL(
file, Write(Contains(license_test_data[license_num].pssh_data,
license_test_data[license_num].key_request,
@@ -1755,9 +1704,8 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Read(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
EXPECT_TRUE(device_files.StoreLicense(
license_test_data[license_num].key_set_id,
license_test_data[license_num].license_state,
@@ -1774,11 +1722,8 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, ::testing::Bool());
TEST_F(DeviceFilesTest, StoreLicenses) {
MockFileSystem file_system;
MockFile file;
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.Times(kNumberOfLicenses)
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
for (size_t i = 0; i < kNumberOfLicenses; ++i) {
std::string license_path = device_base_path_ +
@@ -1788,9 +1733,8 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
CdmAppParameterMap app_parameters =
GetAppParameters(license_test_data[i].app_parameters);
EXPECT_CALL(file, Open(StrEq(license_path),
AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet())))
.WillOnce(Return(true));
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
.WillOnce(Return(&file));
EXPECT_CALL(file, Write(Contains(license_test_data[i].pssh_data,
license_test_data[i].key_request,
@@ -1805,9 +1749,8 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
EXPECT_CALL(file, Close()).Times(kNumberOfLicenses);
EXPECT_CALL(file, Read(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
for (size_t i = 0; i < kNumberOfLicenses; i++) {
CdmAppParameterMap app_parameters =
GetAppParameters(license_test_data[i].app_parameters);
@@ -1825,6 +1768,7 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
}
TEST_F(DeviceFilesTest, RetrieveLicenses) {
MockFileSystem file_system;
MockFile file;
for (size_t i = 0; i < kNumberOfLicenses; ++i) {
@@ -1834,10 +1778,12 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
size_t size = license_test_data[i].file_data.size();
EXPECT_CALL(file, Exists(StrEq(license_path))).WillOnce(Return(true));
EXPECT_CALL(file, FileSize(StrEq(license_path))).WillOnce(Return(size));
EXPECT_CALL(file, Open(StrEq(license_path), IsBinaryFileFlagSet()))
EXPECT_CALL(file_system, Exists(StrEq(license_path)))
.WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
.WillOnce(Return(size));
EXPECT_CALL(file_system, Open(StrEq(license_path), _))
.WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(size)))
.WillOnce(
DoAll(SetArrayArgument<0>(license_test_data[i].file_data.begin(),
@@ -1847,9 +1793,8 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
EXPECT_CALL(file, Close()).Times(kNumberOfLicenses);
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
CdmInitData pssh_data;
CdmKeyMessage key_request;
CdmKeyResponse key_response;
@@ -1886,7 +1831,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
}
TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
MockFile file;
MockFileSystem file_system;
LicenseInfo* test_data =
&license_app_parameters_backwards_compatibility_test_data;
@@ -1895,10 +1840,12 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
size_t size = test_data->file_data.size();
EXPECT_CALL(file, Exists(StrEq(license_path))).WillOnce(Return(true));
EXPECT_CALL(file, FileSize(StrEq(license_path))).WillOnce(Return(size));
EXPECT_CALL(file, Open(StrEq(license_path), IsBinaryFileFlagSet()))
.WillOnce(Return(true));
MockFile file;
EXPECT_CALL(file_system, Exists(StrEq(license_path))).WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
.WillOnce(Return(size));
EXPECT_CALL(file_system, Open(StrEq(license_path), _))
.WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(size)))
.WillOnce(DoAll(SetArrayArgument<0>(test_data->file_data.begin(),
test_data->file_data.end()),
@@ -1907,9 +1854,8 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
DeviceFiles::LicenseState license_state;
CdmInitData pssh_data;
CdmKeyMessage key_request;
@@ -1936,102 +1882,16 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
EXPECT_EQ(0u, app_parameters.size());
}
TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) {
if (!Properties::security_level_path_backward_compatibility_support()) {
return;
}
MockFile file;
std::vector<std::string> security_dirs;
EXPECT_TRUE(Properties::GetSecurityLevelDirectories(&security_dirs));
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); ++i) {
pos = device_base_path_.rfind(security_dirs[i]);
if (std::string::npos != pos) break;
}
EXPECT_NE(std::string::npos, pos);
std::string base_path(device_base_path_, 0, pos);
std::vector<std::string> old_files;
std::string new_path;
for (size_t i = 0; i < security_dirs.size(); ++i) {
old_files.push_back(security_dirs[i]);
new_path = base_path + security_dirs[i];
EXPECT_CALL(file, IsRegularFile(StrEq(new_path))).WillOnce(Return(false));
EXPECT_CALL(file, Exists(StrEq(new_path)))
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(StrEq(new_path))).WillOnce(Return(true));
}
std::string old_path =
base_path + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
old_files.push_back(DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN));
EXPECT_CALL(file, IsRegularFile(StrEq(old_path))).WillOnce(Return(true));
EXPECT_CALL(file, Remove(StrEq(old_path))).WillOnce(Return(true));
for (size_t i = 0; i < security_dirs.size(); ++i) {
new_path = base_path + security_dirs[i] +
DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
EXPECT_CALL(file, Copy(StrEq(old_path), StrEq(new_path)))
.WillOnce(Return(true));
}
for (size_t j = 0; j < kNumberOfLicenses; ++j) {
std::string file_name = license_test_data[j].key_set_id +
DeviceFiles::GetLicenseFileNameExtension();
old_path = base_path + file_name;
old_files.push_back(file_name);
EXPECT_CALL(file, IsRegularFile(StrEq(old_path))).WillOnce(Return(true));
EXPECT_CALL(file, Remove(StrEq(old_path))).WillOnce(Return(true));
for (size_t i = 0; i < security_dirs.size(); ++i) {
new_path = base_path + security_dirs[i] + file_name;
EXPECT_CALL(file, Copy(StrEq(old_path), StrEq(new_path)))
.WillOnce(Return(true));
}
}
EXPECT_CALL(file, List(StrEq(base_path), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(old_files), Return(true)));
std::string data = a2bs_hex(kTestCertificateFileData);
new_path =
device_base_path_ + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN);
EXPECT_CALL(file, Exists(StrEq(new_path))).WillOnce(Return(true));
EXPECT_CALL(file, FileSize(_)).WillOnce(Return(data.size()));
EXPECT_CALL(file, Open(_, _)).WillOnce(Return(true));
EXPECT_CALL(file, Read(NotNull(), Eq(data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
Return(data.size())));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files;
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
Properties::Init();
std::string certificate, wrapped_private_key;
ASSERT_TRUE(device_files.RetrieveCertificate(EMPTY_ORIGIN, &certificate,
&wrapped_private_key));
}
TEST_F(DeviceFilesTest, UpdateLicenseState) {
MockFile file;
MockFileSystem file_system;
std::string license_path = device_base_path_ +
license_update_test_data[0].key_set_id +
DeviceFiles::GetLicenseFileNameExtension();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
MockFile file;
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
.Times(2)
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
EXPECT_CALL(file, Open(StrEq(license_path),
AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet())))
.Times(2)
.WillRepeatedly(Return(true));
.WillRepeatedly(Return(&file));
EXPECT_CALL(file, Write(IsStrEq(license_update_test_data[0].file_data),
Eq(license_update_test_data[0].file_data.size())))
.WillOnce(ReturnArg<1>());
@@ -2041,9 +1901,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
EXPECT_CALL(file, Close()).Times(2);
EXPECT_CALL(file, Read(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
EXPECT_TRUE(device_files.StoreLicense(
license_update_test_data[0].key_set_id,
license_update_test_data[0].license_state,
@@ -2072,32 +1931,33 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
}
TEST_F(DeviceFilesTest, DeleteLicense) {
MockFile file;
MockFileSystem file_system;
std::string license_path = device_base_path_ +
license_test_data[0].key_set_id +
DeviceFiles::GetLicenseFileNameExtension();
size_t size = license_test_data[0].file_data.size();
EXPECT_CALL(file, Exists(StrEq(license_path)))
MockFile file;
EXPECT_CALL(file_system, Exists(StrEq(license_path)))
.Times(2)
.WillOnce(Return(true))
.WillOnce(Return(false));
EXPECT_CALL(file, FileSize(StrEq(license_path))).WillOnce(Return(size));
EXPECT_CALL(file, Open(StrEq(license_path), IsBinaryFileFlagSet()))
.WillOnce(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(license_path)))
.WillOnce(Return(size));
EXPECT_CALL(file_system, Open(StrEq(license_path), _))
.WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(size)))
.WillOnce(
DoAll(SetArrayArgument<0>(license_test_data[0].file_data.begin(),
license_test_data[0].file_data.end()),
Return(size)));
EXPECT_CALL(file, Remove(StrEq(license_path))).WillOnce(Return(true));
EXPECT_CALL(file_system, Remove(StrEq(license_path))).WillOnce(Return(true));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
DeviceFiles::LicenseState license_state;
CdmInitData pssh_data;
CdmKeyMessage key_request;
@@ -2135,17 +1995,11 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
TEST_F(DeviceFilesTest, ReserveLicenseIdsDoesNotUseFileSystem) {
// Validate that ReserveLicenseIds does not touch the file system.
MockFile file;
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_))).Times(0);
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
EXPECT_CALL(file, Open(_, _)).Times(0);
EXPECT_CALL(file, Write(_, _)).Times(0);
EXPECT_CALL(file, Close()).Times(0);
EXPECT_CALL(file, Read(_, _)).Times(0);
MockFileSystem file_system;
EXPECT_CALL(file_system, Open(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
for (size_t i = 0; i < kNumberOfLicenses; i++) {
EXPECT_TRUE(device_files.ReserveLicenseId(license_test_data[i].key_set_id));
// Validate that the license IDs are actually reserved.
@@ -2156,6 +2010,7 @@ TEST_F(DeviceFilesTest, ReserveLicenseIdsDoesNotUseFileSystem) {
}
TEST_P(DeviceFilesUsageInfoTest, Read) {
MockFileSystem file_system;
MockFile file;
std::string app_id; // TODO(fredgc): add tests with multiple app_ids.
std::string path =
@@ -2167,28 +2022,24 @@ TEST_P(DeviceFilesUsageInfoTest, Read) {
data = kUsageInfoTestData[index].file_data;
}
if (index >= 0) {
EXPECT_CALL(file, Exists(StrEq(path))).WillRepeatedly(Return(true));
EXPECT_CALL(file, FileSize(StrEq(path)))
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillRepeatedly(Return(data.size()));
EXPECT_CALL(file, Open(StrEq(path), IsBinaryFileFlagSet()))
.WillOnce(Return(true));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
Return(data.size())));
EXPECT_CALL(file, Close()).Times(1);
} else {
EXPECT_CALL(file, Exists(StrEq(path)))
.WillRepeatedly(Return(false));
EXPECT_CALL(file, FileSize(_)).Times(0);
EXPECT_CALL(file, Open(_, _)).Times(0);
EXPECT_CALL(file, Close()).Times(0);
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(false));
EXPECT_CALL(file_system, FileSize(_)).Times(0);
EXPECT_CALL(file_system, Open(_, _)).Times(0);
}
EXPECT_CALL(file, Write(_, _)).Times(0);
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
ASSERT_TRUE(device_files.RetrieveUsageInfo(app_id, &license_info));
@@ -2212,7 +2063,7 @@ TEST_P(DeviceFilesUsageInfoTest, Read) {
}
TEST_P(DeviceFilesUsageInfoTest, Store) {
MockFile file;
MockFileSystem file_system;
std::string app_id; // TODO(fredgc): multiple app ids.
std::string pst(GenerateRandomData(kProviderSessionTokenLen));
std::string license_request(GenerateRandomData(kLicenseRequestLen));
@@ -2226,24 +2077,24 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
if (index >= 0) {
data = kUsageInfoTestData[index].file_data;
}
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
EXPECT_CALL(file, Exists(StrEq(path))).WillRepeatedly(Return(index >= 0));
MockFile file;
EXPECT_CALL(file_system, Exists(StrEq(path)))
.WillRepeatedly(Return(index >= 0));
if (index >= 0) {
EXPECT_CALL(file, FileSize(StrEq(path))).WillOnce(Return(data.size()));
EXPECT_CALL(file, Open(StrEq(path), IsBinaryFileFlagSet()))
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillOnce(Return(data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _))
.Times(2)
.WillRepeatedly(Return(true));
.WillRepeatedly(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
Return(data.size())));
EXPECT_CALL(file, Close()).Times(2);
} else {
EXPECT_CALL(file, FileSize(_)).Times(0);
EXPECT_CALL(file, Open(_, _)).Times(1).WillOnce(Return(true));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file_system, FileSize(_)).Times(0);
EXPECT_CALL(file_system, Open(_, _)).Times(1).WillOnce(Return(&file));
EXPECT_CALL(file, Close());
}
EXPECT_CALL(file,
@@ -2253,9 +2104,8 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
key_set_id.size())))
.WillOnce(ReturnArg<1>());
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
ASSERT_TRUE(
device_files.StoreUsageInfo(pst, license_request, license, app_id,
@@ -2263,6 +2113,7 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
}
TEST_P(DeviceFilesUsageInfoTest, Delete) {
MockFileSystem file_system;
MockFile file;
std::string app_id; // TODO(fredgc): expand tests.
std::string path =
@@ -2282,24 +2133,19 @@ TEST_P(DeviceFilesUsageInfoTest, Delete) {
}
}
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(index >= 0));
EXPECT_CALL(file, Exists(StrEq(path))).WillOnce(Return(index >= 0));
EXPECT_CALL(file, FileSize(StrEq(path))).WillOnce(Return(data.size()));
EXPECT_CALL(file_system, FileSize(StrEq(path))).WillOnce(Return(data.size()));
if (index >= 1) {
EXPECT_CALL(file, Open(StrEq(path), IsBinaryFileFlagSet()))
EXPECT_CALL(file_system, Open(StrEq(path), _))
.Times(2)
.WillRepeatedly(Return(true));
.WillRepeatedly(Return(&file));
EXPECT_CALL(file, Write(Contains(prev_pst, prev_license, prev_data.size()),
Gt(prev_pst.size() + prev_license.size())))
.WillOnce(ReturnArg<1>());
EXPECT_CALL(file, Close()).Times(2);
} else {
EXPECT_CALL(file, Open(StrEq(path), IsBinaryFileFlagSet()))
.WillOnce(Return(true));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file, Write(_, _)).Times(0);
EXPECT_CALL(file, Close()).Times(1);
}
@@ -2307,9 +2153,8 @@ TEST_P(DeviceFilesUsageInfoTest, Delete) {
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
Return(data.size())));
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
if (index >= 1) {
ASSERT_TRUE(device_files.DeleteUsageInfo(app_id, pst));
@@ -2319,36 +2164,33 @@ TEST_P(DeviceFilesUsageInfoTest, Delete) {
}
TEST_P(DeviceFilesUsageInfoTest, DeleteAll) {
MockFileSystem file_system;
MockFile file;
std::string app_id; // TODO(fredgc): expand tests.
std::string path =
device_base_path_ + DeviceFiles::GetUsageInfoFileName(app_id);
int index = GetParam();
EXPECT_CALL(file, IsDirectory(StrEq(device_base_path_)))
.WillRepeatedly(Return(true));
EXPECT_CALL(file, CreateDirectory(_)).Times(0);
EXPECT_CALL(file, Write(_, _)).Times(0);
std::string data;
if (index < 0) {
EXPECT_CALL(file, Exists(StrEq(path))).WillOnce(Return(false));
EXPECT_CALL(file_system, Exists(StrEq(path))).WillOnce(Return(false));
} else {
data = kUsageInfoTestData[index].file_data;
EXPECT_CALL(file, Exists(StrEq(path))).WillRepeatedly(Return(true));
EXPECT_CALL(file, FileSize(StrEq(path))).WillOnce(Return(data.size()));
EXPECT_CALL(file, Open(StrEq(path), IsBinaryFileFlagSet()))
.WillOnce(Return(true));
EXPECT_CALL(file_system, Exists(StrEq(path))).WillRepeatedly(Return(true));
EXPECT_CALL(file_system, FileSize(StrEq(path)))
.WillOnce(Return(data.size()));
EXPECT_CALL(file_system, Open(StrEq(path), _)).WillOnce(Return(&file));
EXPECT_CALL(file, Read(NotNull(), Eq(data.size())))
.WillOnce(DoAll(SetArrayArgument<0>(data.begin(), data.end()),
Return(data.size())));
EXPECT_CALL(file, Close()).Times(1);
EXPECT_CALL(file, Remove(StrEq(path))).WillOnce(Return(true));
EXPECT_CALL(file_system, Remove(StrEq(path))).WillOnce(Return(true));
}
DeviceFiles device_files;
DeviceFiles device_files(&file_system);
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
device_files.SetTestFile(&file);
std::vector<std::string> psts;
ASSERT_TRUE(device_files.DeleteAllUsageInfoForApp(app_id, &psts));

View File

@@ -1,9 +1,8 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#include <gtest/gtest.h>
#include "device_files.h"
#include "file_store.h"
#include "properties.h"
#include "test_vectors.h"
namespace wvcdm {
@@ -18,20 +17,12 @@ const std::string kWildcard = "*";
class FileTest : public testing::Test {
protected:
virtual void SetUp() { CreateTestDir(); }
FileTest() {}
virtual void TearDown() { RemoveTestDir(); }
void CreateTestDir() {
File file;
if (!file.Exists(test_vectors::kTestDir)) {
EXPECT_TRUE(file.CreateDirectory(test_vectors::kTestDir));
}
EXPECT_TRUE(file.Exists(test_vectors::kTestDir));
}
void RemoveTestDir() {
File file;
EXPECT_TRUE(file.Remove(test_vectors::kTestDir));
EXPECT_TRUE(file_system.Remove(test_vectors::kTestDir));
}
std::string GenerateRandomData(uint32_t len) {
@@ -41,64 +32,52 @@ class FileTest : public testing::Test {
}
return data;
}
FileSystem file_system;
};
TEST_F(FileTest, FileExists) {
File file;
EXPECT_TRUE(file.Exists(test_vectors::kExistentFile));
EXPECT_TRUE(file.Exists(test_vectors::kExistentDir));
EXPECT_FALSE(file.Exists(test_vectors::kNonExistentFile));
EXPECT_FALSE(file.Exists(test_vectors::kNonExistentDir));
}
TEST_F(FileTest, CreateDirectory) {
File file;
std::string dir_wo_delimiter =
test_vectors::kTestDir.substr(0, test_vectors::kTestDir.size() - 1);
if (file.Exists(dir_wo_delimiter)) EXPECT_TRUE(file.Remove(dir_wo_delimiter));
EXPECT_FALSE(file.Exists(dir_wo_delimiter));
EXPECT_TRUE(file.CreateDirectory(dir_wo_delimiter));
EXPECT_TRUE(file.Exists(dir_wo_delimiter));
EXPECT_TRUE(file.Remove(dir_wo_delimiter));
EXPECT_TRUE(file.CreateDirectory(test_vectors::kTestDir));
EXPECT_TRUE(file.Exists(test_vectors::kTestDir));
EXPECT_TRUE(file.Remove(test_vectors::kTestDir));
EXPECT_TRUE(file_system.Exists(test_vectors::kExistentFile));
EXPECT_TRUE(file_system.Exists(test_vectors::kExistentDir));
EXPECT_FALSE(file_system.Exists(test_vectors::kNonExistentFile));
EXPECT_FALSE(file_system.Exists(test_vectors::kNonExistentDir));
}
TEST_F(FileTest, RemoveDir) {
File file;
EXPECT_TRUE(file.Remove(test_vectors::kTestDir));
EXPECT_FALSE(file.Exists(test_vectors::kTestDir));
EXPECT_TRUE(file_system.Remove(test_vectors::kTestDir));
EXPECT_FALSE(file_system.Exists(test_vectors::kTestDir));
}
TEST_F(FileTest, OpenFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File handle;
EXPECT_TRUE(handle.Remove(path));
EXPECT_TRUE(file_system.Remove(path));
File file;
EXPECT_TRUE(file.Open(path, File::kCreate));
file.Close();
File* file = file_system.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
file->Close();
EXPECT_TRUE(handle.Exists(path));
EXPECT_TRUE(file_system.Exists(path));
}
TEST_F(FileTest, RemoveDirAndFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
EXPECT_TRUE(file.Open(path, File::kCreate));
file.Close();
EXPECT_TRUE(file.Exists(path));
EXPECT_TRUE(file.Remove(path));
EXPECT_FALSE(file.Exists(path));
File* file = file_system.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
file->Close();
EXPECT_TRUE(file.Open(path, File::kCreate));
file.Close();
EXPECT_TRUE(file.Exists(path));
EXPECT_TRUE(file_system.Exists(path));
EXPECT_TRUE(file_system.Remove(path));
EXPECT_FALSE(file_system.Exists(path));
file = file_system.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
file->Close();
EXPECT_TRUE(file_system.Exists(path));
RemoveTestDir();
EXPECT_FALSE(file.Exists(test_vectors::kTestDir));
EXPECT_FALSE(file.Exists(path));
EXPECT_FALSE(file_system.Exists(test_vectors::kTestDir));
EXPECT_FALSE(file_system.Exists(path));
}
TEST_F(FileTest, RemoveWildcardFiles) {
@@ -107,159 +86,53 @@ TEST_F(FileTest, RemoveWildcardFiles) {
std::string wildcard_path =
test_vectors::kTestDir + kWildcard + kTestFileNameExt;
File file;
EXPECT_TRUE(file.Open(path1, File::kCreate));
file.Close();
EXPECT_TRUE(file.Open(path2, File::kCreate));
file.Close();
EXPECT_TRUE(file.Exists(path1));
EXPECT_TRUE(file.Exists(path2));
EXPECT_TRUE(file.Remove(wildcard_path));
EXPECT_FALSE(file.Exists(path1));
EXPECT_FALSE(file.Exists(path2));
}
File* file = file_system.Open(path1, FileSystem::kCreate);
ASSERT_TRUE(file);
file->Close();
file = file_system.Open(path2, FileSystem::kCreate);
ASSERT_TRUE(file);
file->Close();
TEST_F(FileTest, IsDir) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
EXPECT_TRUE(file.Open(path, File::kCreate));
file.Close();
EXPECT_TRUE(file.Exists(path));
EXPECT_TRUE(file.Exists(test_vectors::kTestDir));
EXPECT_FALSE(file.IsDirectory(path));
EXPECT_TRUE(file.IsDirectory(test_vectors::kTestDir));
}
TEST_F(FileTest, IsRegularFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
EXPECT_TRUE(file.Open(path, File::kCreate));
file.Close();
EXPECT_TRUE(file.Exists(path));
EXPECT_TRUE(file.Exists(test_vectors::kTestDir));
EXPECT_TRUE(file.IsRegularFile(path));
EXPECT_FALSE(file.IsRegularFile(test_vectors::kTestDir));
EXPECT_TRUE(file_system.Exists(path1));
EXPECT_TRUE(file_system.Exists(path2));
EXPECT_TRUE(file_system.Remove(wildcard_path));
EXPECT_FALSE(file_system.Exists(path1));
EXPECT_FALSE(file_system.Exists(path2));
}
TEST_F(FileTest, FileSize) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
file.Remove(path);
file_system.Remove(path);
std::string write_data = GenerateRandomData(600);
File wr_file;
EXPECT_TRUE(wr_file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(wr_file.Write(write_data.data(), write_data.size()));
wr_file.Close();
EXPECT_TRUE(file.Exists(path));
File* file = file_system.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
file->Close();
EXPECT_TRUE(file_system.Exists(path));
EXPECT_EQ(static_cast<ssize_t>(write_data.size()), file.FileSize(path));
}
TEST_F(FileTest, WriteReadTextFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
file.Remove(path);
std::string write_data = "This is a test";
File wr_file;
EXPECT_TRUE(wr_file.Open(path, File::kCreate));
EXPECT_TRUE(wr_file.Write(write_data.data(), write_data.size()));
wr_file.Close();
EXPECT_TRUE(file.Exists(path));
std::string read_data;
read_data.resize(file.FileSize(path));
File rd_file;
EXPECT_TRUE(rd_file.Open(path, File::kReadOnly));
EXPECT_TRUE(rd_file.Read(&read_data[0], read_data.size()));
rd_file.Close();
EXPECT_EQ(write_data, read_data);
EXPECT_EQ(static_cast<ssize_t>(write_data.size()),
file_system.FileSize(path));
}
TEST_F(FileTest, WriteReadBinaryFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
file.Remove(path);
file_system.Remove(path);
std::string write_data = GenerateRandomData(600);
File wr_file;
EXPECT_TRUE(wr_file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(wr_file.Write(write_data.data(), write_data.size()));
wr_file.Close();
EXPECT_TRUE(file.Exists(path));
File* file = file_system.Open(path, FileSystem::kCreate);
ASSERT_TRUE(file);
EXPECT_TRUE(file->Write(write_data.data(), write_data.size()));
file->Close();
EXPECT_TRUE(file_system.Exists(path));
std::string read_data;
read_data.resize(file.FileSize(path));
File rd_file;
EXPECT_TRUE(rd_file.Open(path, File::kReadOnly));
EXPECT_TRUE(rd_file.Read(&read_data[0], read_data.size()));
rd_file.Close();
read_data.resize(file_system.FileSize(path));
file = file_system.Open(path, FileSystem::kReadOnly);
ASSERT_TRUE(file);
EXPECT_TRUE(file->Read(&read_data[0], read_data.size()));
file->Close();
EXPECT_EQ(write_data, read_data);
}
TEST_F(FileTest, CopyFile) {
std::string path = test_vectors::kTestDir + kTestFileName;
File file;
file.Remove(path);
std::string write_data = GenerateRandomData(600);
File wr_file;
EXPECT_TRUE(wr_file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(wr_file.Write(write_data.data(), write_data.size()));
wr_file.Close();
ASSERT_TRUE(file.Exists(path));
std::string path_copy = test_vectors::kTestDir + kTestFileName2;
EXPECT_FALSE(file.Exists(path_copy));
EXPECT_TRUE(file.Copy(path, path_copy));
std::string read_data;
read_data.resize(file.FileSize(path_copy));
File rd_file;
EXPECT_TRUE(rd_file.Open(path_copy, File::kReadOnly));
EXPECT_TRUE(rd_file.Read(&read_data[0], read_data.size()));
rd_file.Close();
EXPECT_EQ(write_data, read_data);
EXPECT_EQ(file.FileSize(path), file.FileSize(path_copy));
}
TEST_F(FileTest, ListEmptyDirectory) {
std::vector<std::string> files;
File file;
EXPECT_TRUE(file.List(test_vectors::kTestDir, &files));
EXPECT_EQ(0u, files.size());
}
TEST_F(FileTest, ListFiles) {
File file;
std::string path = test_vectors::kTestDir + kTestDirName;
EXPECT_TRUE(file.CreateDirectory(path));
path = test_vectors::kTestDir + kTestFileName;
std::string write_data = GenerateRandomData(600);
EXPECT_TRUE(file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(file.Write(write_data.data(), write_data.size()));
file.Close();
EXPECT_TRUE(file.Exists(path));
path = test_vectors::kTestDir + kTestFileName2;
write_data = GenerateRandomData(600);
EXPECT_TRUE(file.Open(path, File::kCreate | File::kBinary));
EXPECT_TRUE(file.Write(write_data.data(), write_data.size()));
file.Close();
EXPECT_TRUE(file.Exists(path));
std::vector<std::string> files;
EXPECT_TRUE(file.List(test_vectors::kTestDir, &files));
EXPECT_EQ(3u, files.size());
for (size_t i = 0; i < files.size(); ++i) {
EXPECT_TRUE(files[i] == kTestDirName || files[i] == kTestFileName ||
files[i] == kTestFileName2);
}
}
} // namespace wvcdm

View File

@@ -0,0 +1,416 @@
// Copyright 2016 Google Inc. All Rights Reserved.
// These tests are for the generic crypto operations. They call on the
// CdmEngine class and exercise the classes below it as well. In
// particular, we assume that the OEMCrypo layer works, and has a valid keybox.
// This is because we need a valid RSA certificate, and will attempt to connect
// to the provisioning server to request one if we don't.
#include <arpa/inet.h>
#include <gtest/gtest.h>
#include <string>
#include "cdm_engine.h"
#include "license_request.h"
#include "log.h"
#include "oec_session_util.h"
#include "../../oemcrypto/mock/src/oemcrypto_key_mock.h"
#include "string_conversions.h"
#include "url_request.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_types.h"
namespace {
const std::string kKeySystem = "com.widevine.alpha";
} // namespace
namespace wvcdm {
class WvGenericOperationsTest : public testing::Test {
public:
virtual void SetUp() {
::testing::Test::SetUp();
// Load test keybox. This keybox will be used by any CryptoSession
// created by the CDM under test.
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox());
// Perform CdmEngine setup
cdm_engine_ = new CdmEngine(&file_system_);
CdmResponseType status =
cdm_engine_->OpenSession(kKeySystem, NULL, NULL, &session_id_);
if (status == NEED_PROVISIONING) {
Provision();
status = cdm_engine_->OpenSession(kKeySystem, NULL, NULL, &session_id_);
}
ASSERT_EQ(NO_ERROR, status);
ASSERT_NE("", session_id_) << "Could not open CDM session.";
ASSERT_TRUE(cdm_engine_->IsOpenSession(session_id_));
// Get OEMCrypto session ID from the CDM
CdmQueryMap query;
cdm_engine_->QueryOemCryptoSessionId(session_id_, &query);
std::istringstream parse_int;
parse_int.str(query[QUERY_KEY_OEMCRYPTO_SESSION_ID]);
parse_int >> oec_session_id_;
// Construct and install keys into the CDM's OEMCrypto session.
OecSessionSetup(oec_session_id_);
EncryptAndLoadKeys();
}
virtual void TearDown() {
oec_util_session_.close();
cdm_engine_->CloseSession(session_id_);
// OEMCrypto_Terminate() will be performed during the test class's
// destruction (specifically by the CryptoSession destructor)
}
void OecSessionSetup(uint32_t oec_session_id) {
buffer_size_ = 160;
oec_util_session_.SetSessionId(oec_session_id);
oec_util_session_.GenerateTestSessionKeys();
MakeFourKeys();
}
enum GenericKeyType {
kGenericEncrypt = 0,
kGenericDecrypt = 1,
kGenericSign = 2,
kGenericVerify = 3
};
virtual void MakeFourKeys(
uint32_t duration = wvoec::kDuration, uint32_t control = 0,
uint32_t nonce = 0, const std::string& pst = "") {
ASSERT_NO_FATAL_FAILURE(
oec_util_session_.FillSimpleMessage(duration, control, nonce, pst));
oec_util_session_.license().keys[kGenericEncrypt].control.control_bits |=
htonl(wvoec_mock::kControlAllowEncrypt);
oec_util_session_.license().keys[kGenericDecrypt].control.control_bits |=
htonl(wvoec_mock::kControlAllowDecrypt);
oec_util_session_.license().keys[kGenericSign].control.control_bits |=
htonl(wvoec_mock::kControlAllowSign);
oec_util_session_.license().keys[kGenericVerify].control.control_bits |=
htonl(wvoec_mock::kControlAllowVerify);
oec_util_session_.license().keys[kGenericSign].key_data_length =
wvcdm::MAC_KEY_SIZE;
oec_util_session_.license().keys[kGenericVerify].key_data_length =
wvcdm::MAC_KEY_SIZE;
clear_buffer_.assign(buffer_size_, 0);
for (size_t i = 0; i < clear_buffer_.size(); i++) {
clear_buffer_[i] = 1 + i % 250;
}
for (size_t i = 0; i < wvcdm::KEY_IV_SIZE; i++) {
iv_[i] = i;
}
}
std::string GetKeyId(GenericKeyType type) {
std::string key_id;
size_t key_id_length = oec_util_session_.license().keys[0].key_id_length;
key_id.assign(
&(oec_util_session_.license().keys[type].key_id[0]),
&(oec_util_session_.license().keys[type].key_id[key_id_length]));
return key_id;
}
std::string GetClearBuffer() {
std::string buffer;
size_t buffer_length = clear_buffer_.size();
buffer.assign(&clear_buffer_[0], &clear_buffer_[buffer_length]);
return buffer;
}
std::string GetEncryptedBuffer() {
std::string buffer;
size_t buffer_length = encrypted_buffer_.size();
buffer.assign(&encrypted_buffer_[0], &encrypted_buffer_[buffer_length]);
return buffer;
}
std::string GetIvBlock() {
std::string buffer;
size_t buffer_length = wvcdm::KEY_IV_SIZE;
buffer.assign(&iv_[0], &iv_[buffer_length]);
return buffer;
}
std::string GetSignatureBuffer() {
std::string buffer;
buffer.resize(SHA256_DIGEST_LENGTH);
return buffer;
}
void EncryptAndLoadKeys() {
ASSERT_NO_FATAL_FAILURE(oec_util_session_.EncryptAndSign());
oec_util_session_.LoadTestKeys();
}
protected:
void Provision() {
CdmProvisioningRequest prov_request;
std::string provisioning_server_url;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR,
cdm_engine_->GetProvisioningRequest(
cert_type, cert_authority, &prov_request,
&provisioning_server_url));
UrlRequest url_request(provisioning_server_url);
EXPECT_TRUE(url_request.is_connected());
url_request.PostCertRequestInQueryString(prov_request);
std::string message;
bool ok = url_request.GetResponse(&message);
EXPECT_TRUE(ok);
ASSERT_EQ(NO_ERROR,
cdm_engine_->HandleProvisioningResponse(message, &cert,
&wrapped_key));
}
// This CryptoSession object handles Initialization and Termination
// calls on OEMCrypto for the duration of the test. CryptoSessions
// created by the CDM will share the OEMCrypto state of this CryptoSession,
// including, for example, a test keybox.
CryptoSession crypto_session_;
FileSystem file_system_;
CdmEngine* cdm_engine_;
std::string key_msg_;
std::string session_id_;
std::string server_url_;
uint32_t oec_session_id_;
wvoec::Session oec_util_session_;
size_t buffer_size_;
vector<uint8_t> clear_buffer_;
vector<uint8_t> encrypted_buffer_;
uint8_t iv_[wvcdm::KEY_IV_SIZE];
};
TEST_F(WvGenericOperationsTest, NormalSessionOpenClose) {
wvoec::Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.close());
}
TEST_F(WvGenericOperationsTest, GenerateSessionKeys) {
wvoec::Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys());
ASSERT_NO_FATAL_FAILURE(s.close());
}
TEST_F(WvGenericOperationsTest, GenericEncryptNoKey) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string out_buffer = GetEncryptedBuffer();
std::string iv = GetIvBlock();
// No key
KeyId key_id("xyz");
cdm_sts = cdm_engine_->GenericEncrypt(session_id_, in_buffer, key_id, iv,
wvcdm::kEncryptionAlgorithmAesCbc128,
&out_buffer);
EXPECT_EQ(KEY_ERROR_1, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericEncryptKeyNotAllowed) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string out_buffer = GetEncryptedBuffer();
std::string iv = GetIvBlock();
// Wrong key
std::string key_id = GetKeyId(kGenericDecrypt);
cdm_sts = cdm_engine_->GenericEncrypt(session_id_, in_buffer, key_id, iv,
wvcdm::kEncryptionAlgorithmAesCbc128,
&out_buffer);
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericEncryptGood) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string out_buffer = GetEncryptedBuffer();
std::string iv = GetIvBlock();
// Good key
std::string key_id = GetKeyId(kGenericEncrypt);
cdm_sts = cdm_engine_->GenericEncrypt(session_id_, in_buffer, key_id, iv,
wvcdm::kEncryptionAlgorithmAesCbc128,
&out_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericDecryptKeyNotAllowed) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string out_buffer = GetEncryptedBuffer();
std::string iv = GetIvBlock();
// Wrong key
std::string key_id = GetKeyId(kGenericEncrypt);
cdm_sts = cdm_engine_->GenericDecrypt(session_id_, in_buffer, key_id, iv,
wvcdm::kEncryptionAlgorithmAesCbc128,
&out_buffer);
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericDecryptGood) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string out_buffer = GetEncryptedBuffer();
std::string iv = GetIvBlock();
// Good key
std::string key_id = GetKeyId(kGenericDecrypt);
cdm_sts = cdm_engine_->GenericDecrypt(session_id_, in_buffer, key_id, iv,
wvcdm::kEncryptionAlgorithmAesCbc128,
&out_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericSignKeyNotAllowed) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string signature_buffer;
// Wrong key
std::string key_id = GetKeyId(kGenericVerify);
cdm_sts = cdm_engine_->GenericSign(session_id_, in_buffer, key_id,
wvcdm::kSigningAlgorithmHmacSha256,
&signature_buffer);
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericSignGood) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string signature_buffer;
// Good key
std::string key_id = GetKeyId(kGenericSign);
cdm_sts = cdm_engine_->GenericSign(session_id_, in_buffer, key_id,
wvcdm::kSigningAlgorithmHmacSha256,
&signature_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericVerifyKeyNotAllowed) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string signature_buffer = GetSignatureBuffer();
// Wrong key
std::string key_id = GetKeyId(kGenericSign);
cdm_sts = cdm_engine_->GenericVerify(session_id_, in_buffer, key_id,
wvcdm::kSigningAlgorithmHmacSha256,
signature_buffer);
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
}
TEST_F(WvGenericOperationsTest, GenericVerifyGood) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string signature_buffer = GetSignatureBuffer();
// Good key - signature not set.
std::string key_id = GetKeyId(kGenericVerify);
cdm_sts = cdm_engine_->GenericVerify(session_id_, in_buffer, key_id,
wvcdm::kSigningAlgorithmHmacSha256,
signature_buffer);
// OEMCrypto error is OEMCrypto_ERROR_SIGNATURE_FAILURE
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
}
class WvGenericOperationsDataTest : public WvGenericOperationsTest {
public:
// Construct keys for encrypt/decrypt and for sign/verify
virtual void MakeFourKeys(
uint32_t duration = wvoec::kDuration, uint32_t control = 0,
uint32_t nonce = 0, const std::string& pst = "") {
ASSERT_NO_FATAL_FAILURE(
oec_util_session_.FillSimpleMessage(duration, control, nonce, pst));
oec_util_session_.license().keys[kGenericEncrypt].control.control_bits |=
htonl(wvoec_mock::kControlAllowEncrypt |
wvoec_mock::kControlAllowDecrypt);
oec_util_session_.license().keys[kGenericSign].control.control_bits |=
htonl(wvoec_mock::kControlAllowSign | wvoec_mock::kControlAllowVerify);
oec_util_session_.license().keys[kGenericSign].key_data_length =
wvcdm::MAC_KEY_SIZE;
clear_buffer_.assign(buffer_size_, 0);
for (size_t i = 0; i < clear_buffer_.size(); i++) {
clear_buffer_[i] = 1 + i % 250;
}
for (size_t i = 0; i < wvcdm::KEY_IV_SIZE; i++) {
iv_[i] = i;
}
}
};
TEST_F(WvGenericOperationsDataTest, GenericEncryptDecrypt) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string encrypted_buffer = GetEncryptedBuffer();
std::string iv = GetIvBlock();
// Encrypt
std::string key_id = GetKeyId(kGenericEncrypt);
cdm_sts = cdm_engine_->GenericEncrypt(
session_id_, in_buffer, key_id, iv, wvcdm::kEncryptionAlgorithmAesCbc128,
&encrypted_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
// Decrypt, use same key as encrypt.
key_id = GetKeyId(kGenericEncrypt);
std::string final_buffer;
final_buffer.resize(in_buffer.size());
cdm_sts = cdm_engine_->GenericDecrypt(
session_id_, encrypted_buffer, key_id, iv,
wvcdm::kEncryptionAlgorithmAesCbc128, &final_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
EXPECT_EQ(0, in_buffer.compare(final_buffer));
}
TEST_F(WvGenericOperationsDataTest, GenericSignVerify) {
CdmResponseType cdm_sts;
std::string in_buffer = GetClearBuffer();
std::string signature_buffer = GetSignatureBuffer();
// Signing key
std::string key_id = GetKeyId(kGenericSign);
cdm_sts = cdm_engine_->GenericSign(session_id_, in_buffer, key_id,
wvcdm::kSigningAlgorithmHmacSha256,
&signature_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
// Verify signature, use same key as sign.
key_id = GetKeyId(kGenericSign);
cdm_sts = cdm_engine_->GenericVerify(session_id_, in_buffer, key_id,
wvcdm::kSigningAlgorithmHmacSha256,
signature_buffer);
EXPECT_EQ(NO_ERROR, cdm_sts);
}
} // namespace wvcdm

View File

@@ -0,0 +1,888 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <vector>
#include "license.h"
#include "license_key_status.h"
namespace wvcdm {
namespace {
static const uint32_t dev_lo_res = 200;
static const uint32_t dev_hi_res = 400;
static const uint32_t dev_top_res = 800;
static const uint32_t key_lo_res_min = 151;
static const uint32_t key_lo_res_max = 300;
static const uint32_t key_hi_res_min = 301;
static const uint32_t key_hi_res_max = 450;
static const uint32_t key_top_res_min = 451;
static const uint32_t key_top_res_max = 650;
// Content Keys
static const KeyId ck_sw_crypto = "c_key_SW_SECURE_CRYPTO";
static const KeyId ck_sw_decode = "c_key_SW_SECURE_DECODE";
static const KeyId ck_hw_crypto = "c_key_HW_SECURE_CRYPTO";
static const KeyId ck_hw_decode = "c_key_HW_SECURE_DECODE";
static const KeyId ck_hw_secure = "c_key_HW_SECURE_ALL";
// Operator Session Keys
static const KeyId osk_decrypt = "os_key_generic_decrypt";
static const KeyId osk_encrypt = "os_key_generic_encrypt";
static const KeyId osk_sign = "os_key_generic_sign";
static const KeyId osk_verify = "os_key_generic_verify";
static const KeyId osk_encrypt_decrypt = "os_key_generic_encrypt_decrypt";
static const KeyId osk_sign_verify = "os_key_generic_sign_verify";
static const KeyId osk_all = "os_key_generic_all";
// HDCP test keys
static const KeyId ck_sw_crypto_NO_HDCP = "ck_sw_crypto_NO_HDCP";
static const KeyId ck_hw_secure_NO_HDCP = "ck_hw_secure_NO_HDCP";
static const KeyId ck_sw_crypto_HDCP_V2_1 = "ck_sw_crypto_HDCP_V2_1";
static const KeyId ck_hw_secure_HDCP_V2_1 = "ck_hw_secure_HDCP_V2_1";
static const KeyId ck_sw_crypto_HDCP_NO_OUTPUT = "ck_sw_crypto_HDCP_NO_OUT";
static const KeyId ck_hw_secure_HDCP_NO_OUTPUT = "ck_hw_secure_HDCP_NO_OUT";
// Constraint test keys
static const KeyId ck_NO_HDCP_lo_res = "ck_NO_HDCP_lo_res";
static const KeyId ck_HDCP_NO_OUTPUT_hi_res = "ck_HDCP_NO_OUTPUT_hi_res";
static const KeyId ck_HDCP_V2_1_max_res = "ck_HDCP_V2_1_max_res";
static const KeyId ck_NO_HDCP_dual_res = "ck_NO_HDCP_dual_res";
} // namespace
// protobuf generated classes.
using video_widevine_server::sdk::License;
using video_widevine_server::sdk::LicenseIdentification;
using video_widevine_server::sdk::STREAMING;
using video_widevine_server::sdk::OFFLINE;
typedef ::video_widevine_server::sdk::License::KeyContainer KeyContainer;
typedef KeyContainer::VideoResolutionConstraint VideoResolutionConstraint;
class LicenseKeysTest : public ::testing::Test {
protected:
enum KeyFlag {
kKeyFlagNull,
kKeyFlagFalse,
kKeyFlagTrue
};
static const KeyFlag kEncryptNull = kKeyFlagNull;
static const KeyFlag kEncryptFalse = kKeyFlagFalse;
static const KeyFlag kEncryptTrue = kKeyFlagTrue;
static const KeyFlag kDecryptNull = kKeyFlagNull;
static const KeyFlag kDecryptFalse = kKeyFlagFalse;
static const KeyFlag kDecryptTrue = kKeyFlagTrue;
static const KeyFlag kSignNull = kKeyFlagNull;
static const KeyFlag kSignFalse = kKeyFlagFalse;
static const KeyFlag kSignTrue = kKeyFlagTrue;
static const KeyFlag kVerifyNull = kKeyFlagNull;
static const KeyFlag kVerifyFalse = kKeyFlagFalse;
static const KeyFlag kVerifyTrue = kKeyFlagTrue;
static const KeyFlag kContentSecureFalse = kKeyFlagFalse;
static const KeyFlag kContentSecureTrue = kKeyFlagTrue;
static const KeyFlag kContentClearFalse = kKeyFlagFalse;
static const KeyFlag kContentClearTrue = kKeyFlagTrue;
virtual void SetUp() {
LicenseIdentification* id = license_.mutable_id();
id->set_version(1);
id->set_type(STREAMING);
}
virtual void AddContentKey(
const KeyId& key_id, bool set_level = false,
KeyContainer::SecurityLevel level = KeyContainer::SW_SECURE_CRYPTO,
bool set_hdcp = false, KeyContainer::OutputProtection::HDCP hdcp_value =
KeyContainer::OutputProtection::HDCP_NONE,
bool set_constraints = false,
std::vector<VideoResolutionConstraint>* constraints = NULL) {
KeyContainer* key = license_.add_key();
key->set_type(KeyContainer::CONTENT);
if (set_level) {
key->set_level(level);
}
if (set_hdcp) {
KeyContainer::OutputProtection* pro = key->mutable_required_protection();
pro->set_hdcp(hdcp_value);
}
if (set_constraints) {
for (std::vector<VideoResolutionConstraint>::iterator
it = constraints->begin(); it != constraints->end(); ++it) {
VideoResolutionConstraint* constraint =
key->add_video_resolution_constraints();
constraint->set_min_resolution_pixels(it->min_resolution_pixels());
constraint->set_max_resolution_pixels(it->max_resolution_pixels());
constraint->mutable_required_protection()->
set_hdcp(it->required_protection().hdcp());
}
}
key->set_id(key_id);
}
virtual void AddOperatorSessionKey(
const KeyId& key_id, bool set_perms = false,
KeyFlag encrypt = kKeyFlagNull, KeyFlag decrypt = kKeyFlagNull,
KeyFlag sign = kKeyFlagNull, KeyFlag verify = kKeyFlagNull) {
KeyContainer* non_content_key = license_.add_key();
non_content_key->set_type(KeyContainer::OPERATOR_SESSION);
non_content_key->set_id(key_id);
if (set_perms) {
KeyContainer::OperatorSessionKeyPermissions* permissions =
non_content_key->mutable_operator_session_key_permissions();
if (encrypt != kKeyFlagNull) {
permissions->set_allow_encrypt(encrypt == kKeyFlagTrue);
}
if (decrypt != kKeyFlagNull) {
permissions->set_allow_decrypt(decrypt == kKeyFlagTrue);
}
if (sign != kKeyFlagNull) {
permissions->set_allow_sign(sign == kKeyFlagTrue);
}
if (verify != kKeyFlagNull) {
permissions->set_allow_signature_verify(verify == kKeyFlagTrue);
}
}
}
virtual void AddSigningKey(const KeyId& key_id) {
KeyContainer* key = license_.add_key();
key->set_type(KeyContainer::SIGNING);
key->set_id(key_id);
}
virtual void ExpectAllowedUsageContent(
const CdmKeyAllowedUsage& key_usage, KeyFlag secure, KeyFlag clear) {
EXPECT_EQ(key_usage.decrypt_to_secure_buffer, secure == kKeyFlagTrue);
EXPECT_EQ(key_usage.decrypt_to_clear_buffer, clear == kKeyFlagTrue);
EXPECT_FALSE(key_usage.generic_encrypt);
EXPECT_FALSE(key_usage.generic_decrypt);
EXPECT_FALSE(key_usage.generic_sign);
EXPECT_FALSE(key_usage.generic_verify);
}
virtual void ExpectAllowedUsageOperator(
const CdmKeyAllowedUsage& key_usage, KeyFlag encrypt, KeyFlag decrypt,
KeyFlag sign, KeyFlag verify) {
EXPECT_FALSE(key_usage.decrypt_to_secure_buffer);
EXPECT_FALSE(key_usage.decrypt_to_clear_buffer);
EXPECT_EQ(key_usage.generic_encrypt, encrypt == kKeyFlagTrue);
EXPECT_EQ(key_usage.generic_decrypt, decrypt == kKeyFlagTrue);
EXPECT_EQ(key_usage.generic_sign, sign == kKeyFlagTrue);
EXPECT_EQ(key_usage.generic_verify, verify == kKeyFlagTrue);
}
virtual int NumContentKeys() {
return content_key_count_;
}
virtual void StageContentKeys() {
content_key_count_ = 0;
AddContentKey(ck_sw_crypto, true, KeyContainer::SW_SECURE_CRYPTO);
content_key_count_++;
AddContentKey(ck_sw_decode, true, KeyContainer::SW_SECURE_DECODE);
content_key_count_++;
AddContentKey(ck_hw_crypto, true, KeyContainer::HW_SECURE_CRYPTO);
content_key_count_++;
AddContentKey(ck_hw_decode, true, KeyContainer::HW_SECURE_DECODE);
content_key_count_++;
AddContentKey(ck_hw_secure, true, KeyContainer::HW_SECURE_ALL);
content_key_count_++;
license_keys_.SetFromLicense(license_);
}
virtual void StageOperatorSessionKeys() {
AddOperatorSessionKey(osk_decrypt, true,
kEncryptNull, kDecryptTrue, kSignNull, kVerifyNull);
AddOperatorSessionKey(osk_encrypt, true,
kEncryptTrue, kDecryptNull, kSignNull, kVerifyNull);
AddOperatorSessionKey(osk_sign, true,
kEncryptNull, kDecryptNull, kSignTrue, kVerifyNull);
AddOperatorSessionKey(osk_verify, true,
kEncryptNull, kDecryptNull, kSignNull, kVerifyTrue);
AddOperatorSessionKey(osk_encrypt_decrypt, true,
kEncryptTrue, kDecryptTrue, kSignNull, kVerifyNull);
AddOperatorSessionKey(osk_sign_verify, true,
kEncryptNull, kDecryptNull, kSignTrue, kVerifyTrue);
AddOperatorSessionKey(osk_all, true,
kEncryptTrue, kDecryptTrue, kSignTrue, kVerifyTrue);
license_keys_.SetFromLicense(license_);
}
virtual void StageHdcpKeys() {
content_key_count_ = 0;
AddContentKey(ck_sw_crypto_NO_HDCP, true, KeyContainer::SW_SECURE_CRYPTO,
true, KeyContainer::OutputProtection::HDCP_NONE);
content_key_count_++;
AddContentKey(ck_hw_secure_NO_HDCP, true, KeyContainer::HW_SECURE_ALL, true,
KeyContainer::OutputProtection::HDCP_NONE);
content_key_count_++;
AddContentKey(ck_sw_crypto_HDCP_V2_1, true, KeyContainer::SW_SECURE_CRYPTO,
true, KeyContainer::OutputProtection::HDCP_V2_1);
content_key_count_++;
AddContentKey(ck_hw_secure_HDCP_V2_1, true, KeyContainer::HW_SECURE_ALL,
true, KeyContainer::OutputProtection::HDCP_V2_1);
content_key_count_++;
AddContentKey(ck_sw_crypto_HDCP_NO_OUTPUT, true,
KeyContainer::SW_SECURE_CRYPTO, true,
KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
content_key_count_++;
AddContentKey(ck_hw_secure_HDCP_NO_OUTPUT, true,
KeyContainer::HW_SECURE_ALL, true,
KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
content_key_count_++;
license_keys_.SetFromLicense(license_);
}
virtual void AddConstraint(
std::vector<VideoResolutionConstraint>& constraints, uint32_t min_res,
uint32_t max_res, bool set_hdcp = false,
KeyContainer::OutputProtection::HDCP hdcp =
KeyContainer::OutputProtection::HDCP_NONE) {
VideoResolutionConstraint constraint;
constraint.set_min_resolution_pixels(min_res);
constraint.set_max_resolution_pixels(max_res);
if (set_hdcp) {
constraint.mutable_required_protection()->set_hdcp(hdcp);
}
constraints.push_back(constraint);
}
virtual void StageConstraintKeys() {
content_key_count_ = 0;
std::vector<VideoResolutionConstraint> constraints;
AddConstraint(constraints, key_lo_res_min, key_lo_res_max);
AddContentKey(ck_NO_HDCP_lo_res, true, KeyContainer::SW_SECURE_CRYPTO, true,
KeyContainer::OutputProtection::HDCP_NONE, true,
&constraints);
content_key_count_++;
constraints.clear();
AddConstraint(constraints, key_hi_res_min, key_hi_res_max);
AddContentKey(
ck_HDCP_NO_OUTPUT_hi_res, true, KeyContainer::SW_SECURE_CRYPTO, true,
KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT, true,
&constraints);
content_key_count_++;
constraints.clear();
AddConstraint(constraints, key_top_res_min, key_top_res_max);
AddContentKey(ck_HDCP_V2_1_max_res, true, KeyContainer::SW_SECURE_CRYPTO,
true, KeyContainer::OutputProtection::HDCP_V2_1, true,
&constraints);
content_key_count_++;
constraints.clear();
AddConstraint(constraints, key_lo_res_min, key_lo_res_max);
AddConstraint(constraints, key_hi_res_min, key_hi_res_max,
KeyContainer::OutputProtection::HDCP_NO_DIGITAL_OUTPUT);
AddContentKey(ck_NO_HDCP_dual_res, true, KeyContainer::HW_SECURE_ALL, true,
KeyContainer::OutputProtection::HDCP_NONE, true,
&constraints);
content_key_count_++;
license_keys_.SetFromLicense(license_);
}
virtual void ExpectKeyStatusesEqual(CdmKeyStatusMap& key_status_map,
CdmKeyStatus expected_status) {
for (CdmKeyStatusMap::iterator it = key_status_map.begin();
it != key_status_map.end(); ++it) {
EXPECT_TRUE(it->second == expected_status);
}
}
virtual void ExpectKeyStatusEqual(CdmKeyStatusMap& key_status_map,
const KeyId& key_id,
CdmKeyStatus expected_status) {
for (CdmKeyStatusMap::iterator it = key_status_map.begin();
it != key_status_map.end(); ++it) {
if (key_id == it->first) {
EXPECT_TRUE(it->second == expected_status);
}
}
}
int content_key_count_;
LicenseKeys license_keys_;
License license_;
};
TEST_F(LicenseKeysTest, Empty) {
EXPECT_TRUE(license_keys_.Empty());
}
TEST_F(LicenseKeysTest, NotEmpty) {
const KeyId c_key = "content_key";
AddContentKey(c_key);
license_keys_.SetFromLicense(license_);
EXPECT_FALSE(license_keys_.Empty());
}
TEST_F(LicenseKeysTest, BadKeyId) {
const KeyId c_key = "content_key";
const KeyId os_key = "op_sess_key";
const KeyId unk_key = "unknown_key";
CdmKeyAllowedUsage allowed_usage;
AddContentKey(c_key);
AddOperatorSessionKey(os_key);
license_keys_.SetFromLicense(license_);
EXPECT_FALSE(license_keys_.IsContentKey(unk_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(unk_key));
EXPECT_TRUE(license_keys_.MeetsConstraints(unk_key));
EXPECT_FALSE(license_keys_.GetAllowedUsage(unk_key, &allowed_usage));
}
TEST_F(LicenseKeysTest, SigningKey) {
const KeyId c_key = "content_key";
const KeyId os_key = "op_sess_key";
const KeyId sign_key = "signing_key";
CdmKeyAllowedUsage allowed_usage;
AddSigningKey(sign_key);
AddContentKey(c_key);
AddOperatorSessionKey(os_key);
license_keys_.SetFromLicense(license_);
EXPECT_FALSE(license_keys_.IsContentKey(sign_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(sign_key));
EXPECT_TRUE(license_keys_.MeetsConstraints(sign_key));
EXPECT_FALSE(license_keys_.GetAllowedUsage(sign_key, &allowed_usage));
}
TEST_F(LicenseKeysTest, ContentKey) {
const KeyId c_key = "content_key";
AddContentKey(c_key);
EXPECT_FALSE(license_keys_.IsContentKey(c_key));
license_keys_.SetFromLicense(license_);
EXPECT_TRUE(license_keys_.IsContentKey(c_key));
}
TEST_F(LicenseKeysTest, OperatorSessionKey) {
const KeyId os_key = "op_sess_key";
EXPECT_FALSE(license_keys_.IsContentKey(os_key));
AddOperatorSessionKey(os_key);
license_keys_.SetFromLicense(license_);
EXPECT_FALSE(license_keys_.IsContentKey(os_key));
}
TEST_F(LicenseKeysTest, CanDecrypt) {
const KeyId os_key = "op_sess_key";
const KeyId c_key = "content_key";
EXPECT_FALSE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
AddOperatorSessionKey(os_key);
AddContentKey(c_key);
license_keys_.SetFromLicense(license_);
EXPECT_FALSE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
bool new_usable_keys = false;
bool any_change = false;
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
any_change = license_keys_.ApplyStatusChange(kKeyStatusExpired,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
}
TEST_F(LicenseKeysTest, AllowedUsageNull) {
const KeyId os_key = "op_sess_key";
const KeyId c_key = "content_key";
const KeyId sign_key = "signing_key";
AddOperatorSessionKey(os_key);
AddContentKey(c_key);
AddSigningKey(sign_key);
license_keys_.SetFromLicense(license_);
CdmKeyAllowedUsage usage_1;
EXPECT_FALSE(license_keys_.GetAllowedUsage(sign_key, &usage_1));
CdmKeyAllowedUsage usage_2;
EXPECT_TRUE(license_keys_.GetAllowedUsage(c_key, &usage_2));
ExpectAllowedUsageContent(usage_2, kContentClearTrue, kContentSecureTrue);
CdmKeyAllowedUsage usage_3;
EXPECT_TRUE(license_keys_.GetAllowedUsage(os_key, &usage_3));
ExpectAllowedUsageContent(usage_3, kContentClearFalse, kContentSecureFalse);
}
TEST_F(LicenseKeysTest, AllowedUsageContent) {
StageContentKeys();
CdmKeyAllowedUsage u_sw_crypto;
EXPECT_TRUE(license_keys_.GetAllowedUsage(ck_sw_crypto, &u_sw_crypto));
ExpectAllowedUsageContent(u_sw_crypto, kContentSecureTrue, kContentClearTrue);
CdmKeyAllowedUsage u_sw_decode;
EXPECT_TRUE(license_keys_.GetAllowedUsage(ck_sw_decode, &u_sw_decode));
ExpectAllowedUsageContent(u_sw_decode, kContentSecureTrue, kContentClearTrue);
CdmKeyAllowedUsage u_hw_crypto;
EXPECT_TRUE(license_keys_.GetAllowedUsage(ck_hw_crypto, &u_hw_crypto));
ExpectAllowedUsageContent(u_hw_crypto, kContentSecureTrue, kContentClearTrue);
CdmKeyAllowedUsage u_hw_decode;
EXPECT_TRUE(license_keys_.GetAllowedUsage(ck_hw_decode, &u_hw_decode));
ExpectAllowedUsageContent(u_hw_decode, kContentSecureTrue,
kContentClearFalse);
CdmKeyAllowedUsage u_hw_secure;
EXPECT_TRUE(license_keys_.GetAllowedUsage(ck_hw_secure, &u_hw_secure));
ExpectAllowedUsageContent(u_hw_secure, kContentSecureTrue,
kContentClearFalse);
}
TEST_F(LicenseKeysTest, AllowedUsageOperatorSession) {
StageOperatorSessionKeys();
CdmKeyAllowedUsage u_encrypt;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_encrypt, &u_encrypt));
ExpectAllowedUsageOperator(u_encrypt, kEncryptTrue, kDecryptFalse, kSignFalse,
kVerifyFalse);
CdmKeyAllowedUsage u_decrypt;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_decrypt, &u_decrypt));
ExpectAllowedUsageOperator(u_decrypt, kEncryptFalse, kDecryptTrue, kSignFalse,
kVerifyFalse);
CdmKeyAllowedUsage u_sign;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_sign, &u_sign));
ExpectAllowedUsageOperator(u_sign, kEncryptFalse, kDecryptFalse, kSignTrue,
kVerifyFalse);
CdmKeyAllowedUsage u_verify;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_verify, &u_verify));
ExpectAllowedUsageOperator(u_verify, kEncryptFalse, kDecryptFalse, kSignFalse,
kVerifyTrue);
CdmKeyAllowedUsage u_encrypt_decrypt;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_encrypt_decrypt,
&u_encrypt_decrypt));
ExpectAllowedUsageOperator(u_encrypt_decrypt, kEncryptTrue, kDecryptTrue,
kSignFalse, kVerifyFalse);
CdmKeyAllowedUsage u_sign_verify;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_sign_verify, &u_sign_verify));
ExpectAllowedUsageOperator(u_sign_verify, kEncryptFalse, kDecryptFalse,
kSignTrue, kVerifyTrue);
CdmKeyAllowedUsage u_all;
EXPECT_TRUE(license_keys_.GetAllowedUsage(osk_all, &u_all));
ExpectAllowedUsageOperator(u_all, kEncryptTrue, kDecryptTrue, kSignTrue,
kVerifyTrue);
}
TEST_F(LicenseKeysTest, ExtractKeyStatuses) {
CdmKeyStatusMap key_status_map;
StageOperatorSessionKeys();
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(0, key_status_map.size());
StageContentKeys();
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusInternalError);
}
TEST_F(LicenseKeysTest, KeyStatusChanges) {
bool new_usable_keys = false;
bool any_change = false;
CdmKeyStatusMap key_status_map;
StageOperatorSessionKeys();
StageContentKeys();
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusInternalError);
// change to pending
any_change = license_keys_.ApplyStatusChange(kKeyStatusPending,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure));
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusPending);
// change to pending (again)
any_change = license_keys_.ApplyStatusChange(kKeyStatusPending,
&new_usable_keys);
EXPECT_FALSE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure));
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusPending);
// change to usable
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure));
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusUsable);
// change to usable (again)
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_FALSE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure));
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusUsable);
// change to expired
any_change = license_keys_.ApplyStatusChange(kKeyStatusExpired,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure));
license_keys_.ExtractKeyStatuses(&key_status_map);
EXPECT_EQ(content_key_count_, key_status_map.size());
ExpectKeyStatusesEqual(key_status_map, kKeyStatusExpired);
}
TEST_F(LicenseKeysTest, HdcpChanges) {
bool new_usable_keys = false;
bool any_change = false;
CdmKeyStatusMap key_status_map;
StageHdcpKeys();
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_V2_1));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_V2_1));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_V2_1));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_V2_1));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_NO_OUTPUT));
license_keys_.ApplyConstraints(100, HDCP_NONE);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_NO_HDCP));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_NO_HDCP));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_NO_OUTPUT));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_NO_HDCP, kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_V2_1,
kKeyStatusOutputNotAllowed);
license_keys_.ApplyConstraints(100, HDCP_V1);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_FALSE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_NO_HDCP));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_NO_HDCP));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_NO_OUTPUT));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_NO_HDCP, kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_HDCP_V2_1,
kKeyStatusOutputNotAllowed);
license_keys_.ApplyConstraints(100, HDCP_V2_2);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_V2_1));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_V2_1));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_NO_OUTPUT));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_HDCP_V2_1,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_HDCP_NO_OUTPUT,
kKeyStatusOutputNotAllowed);
license_keys_.ApplyConstraints(100, HDCP_NO_DIGITAL_OUTPUT);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_V2_1));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_V2_1));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_V2_1));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_V2_1));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_NO_OUTPUT));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_V2_1,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_NO_OUTPUT,
kKeyStatusUsable);
license_keys_.ApplyConstraints(100, HDCP_NONE);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_hw_secure_NO_HDCP));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_hw_secure_HDCP_NO_OUTPUT));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_sw_crypto_NO_HDCP));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_hw_secure_NO_HDCP));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_V2_1));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_sw_crypto_HDCP_NO_OUTPUT));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_hw_secure_HDCP_NO_OUTPUT));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_NO_HDCP,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_NO_OUTPUT,
kKeyStatusOutputNotAllowed);
}
TEST_F(LicenseKeysTest, ConstraintChanges) {
bool new_usable_keys = false;
bool any_change = false;
CdmKeyStatusMap key_status_map;
StageConstraintKeys();
// No constraints set by device
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
// Low-res device, no HDCP support
license_keys_.ApplyConstraints(dev_lo_res, HDCP_NONE);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_NO_HDCP, kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_V2_1,
kKeyStatusOutputNotAllowed);
// Hi-res device, HDCP_V1 support
license_keys_.ApplyConstraints(dev_hi_res, HDCP_V1);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_NO_HDCP, kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_HDCP_V2_1,
kKeyStatusOutputNotAllowed);
// Lo-res device, HDCP V2.2 support
license_keys_.ApplyConstraints(dev_lo_res, HDCP_V2_2);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_HDCP_V2_1,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_sw_crypto_HDCP_NO_OUTPUT,
kKeyStatusOutputNotAllowed);
// Hi-res device, Maximal HDCP support
license_keys_.ApplyConstraints(dev_hi_res, HDCP_NO_DIGITAL_OUTPUT);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_V2_1,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_NO_OUTPUT,
kKeyStatusUsable);
// Lo-res device, no HDCP support
license_keys_.ApplyConstraints(dev_lo_res, HDCP_NONE);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_TRUE(new_usable_keys);
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_TRUE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_NO_HDCP,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_NO_OUTPUT,
kKeyStatusOutputNotAllowed);
// Too-high-res -- all keys rejected
license_keys_.ApplyConstraints(dev_top_res, HDCP_NONE);
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
&new_usable_keys);
EXPECT_TRUE(any_change);
EXPECT_FALSE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_HDCP_V2_1_max_res));
EXPECT_FALSE(license_keys_.CanDecryptContent(ck_NO_HDCP_dual_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_NO_HDCP_lo_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_NO_OUTPUT_hi_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_HDCP_V2_1_max_res));
EXPECT_FALSE(license_keys_.MeetsConstraints(ck_NO_HDCP_dual_res));
license_keys_.ExtractKeyStatuses(&key_status_map);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_NO_HDCP,
kKeyStatusUsable);
ExpectKeyStatusEqual(key_status_map, ck_hw_secure_HDCP_NO_OUTPUT,
kKeyStatusOutputNotAllowed);
}
} // namespace wvcdm

View File

@@ -1,323 +0,0 @@
// Copyright 2012 Google Inc. All Rights Reserved.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "crypto_session.h"
#include "license.h"
#include "max_res_engine.h"
#include "mock_clock.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
namespace wvcdm {
typedef ::video_widevine_server::sdk::License License;
typedef ::video_widevine_server::sdk::License::KeyContainer KeyContainer;
typedef ::video_widevine_server::sdk::License::KeyContainer::OutputProtection
OutputProtection;
typedef ::video_widevine_server::sdk::License::KeyContainer::
VideoResolutionConstraint VideoResolutionConstraint;
typedef ::google::protobuf::RepeatedPtrField<KeyContainer> KeyList;
typedef ::google::protobuf::RepeatedPtrField<VideoResolutionConstraint>
ConstraintList;
using namespace testing;
namespace {
const KeyId kKeyId1 = "357adc89f1673433c36c621f1b5c41ee";
const KeyId kKeyId2 = "3d25f819250789ecfc9ed48cc99af164";
const KeyId kKeyId3 = "fe3cf6b69e76c9a1c877922e1a661707";
const KeyId kKeyId4 = "29a321b9886658078f916fdd41d6f570";
const KeyId kKeyId5 = "cc5b031bcde371031c06822d935b9a63";
const KeyId kKeyId6 = "90ac1332e4efc8acbaf929c8d321f50c";
const uint32_t kMinRes1 = 0;
const uint32_t kMaxRes1 = 2000;
const uint32_t kTargetRes1 = (kMinRes1 + kMaxRes1) / 2;
const uint32_t kMinRes2 = kMaxRes1;
const uint32_t kMaxRes2 = 4000;
const uint32_t kTargetRes2 = (kMinRes2 + kMaxRes2) / 2;
const uint32_t kTargetRes3 = kMaxRes2 + 1000;
const OutputProtection::HDCP kHdcpDefault = OutputProtection::HDCP_V2;
const OutputProtection::HDCP kHdcpConstraint = OutputProtection::HDCP_V2_1;
const int64_t kHdcpInterval = 10;
class HdcpOnlyMockCryptoSession : public CryptoSession {
public:
MOCK_METHOD2(GetHdcpCapabilities, bool(HdcpCapability*, HdcpCapability*));
};
} // namespace
ACTION_P2(IncrementAndReturnPointee, p, a) {
*p += a;
return *p;
}
class MaxResEngineTest : public Test {
protected:
virtual void SetUp() {
mock_clock_ = new NiceMock<MockClock>();
current_time_ = 0;
ON_CALL(*mock_clock_, GetCurrentTime())
.WillByDefault(
IncrementAndReturnPointee(&current_time_, kHdcpInterval));
max_res_engine_.reset(new MaxResEngine(&crypto_session_, mock_clock_));
KeyList* keys = license_.mutable_key();
// Key 1 - Content key w/ ID, no HDCP, no constraints
{
KeyContainer* key1 = keys->Add();
key1->set_type(KeyContainer::CONTENT);
key1->set_id(kKeyId1);
}
// Key 2 - Content key w/ ID, HDCP, no constraints
{
KeyContainer* key2 = keys->Add();
key2->set_type(KeyContainer::CONTENT);
key2->set_id(kKeyId2);
key2->mutable_required_protection()->set_hdcp(kHdcpDefault);
}
// Key 3 - Content key w/ ID, no HDCP, constraints
{
KeyContainer* key3 = keys->Add();
key3->set_type(KeyContainer::CONTENT);
key3->set_id(kKeyId3);
AddConstraints(key3->mutable_video_resolution_constraints());
}
// Key 4 - Content key w/ ID, HDCP, constraints
{
KeyContainer* key4 = keys->Add();
key4->set_type(KeyContainer::CONTENT);
key4->set_id(kKeyId4);
key4->mutable_required_protection()->set_hdcp(kHdcpDefault);
AddConstraints(key4->mutable_video_resolution_constraints());
}
// Key 5 - Content key w/o ID, HDCP, constraints
{
KeyContainer* key5 = keys->Add();
key5->set_type(KeyContainer::CONTENT);
key5->mutable_required_protection()->set_hdcp(kHdcpDefault);
AddConstraints(key5->mutable_video_resolution_constraints());
}
// Key 6 - Non-content key
{
KeyContainer* key6 = keys->Add();
key6->set_type(KeyContainer::OPERATOR_SESSION);
}
}
void AddConstraints(ConstraintList* constraints) {
// Constraint 1 - Low-res and no HDCP
{
VideoResolutionConstraint* constraint1 = constraints->Add();
constraint1->set_min_resolution_pixels(kMinRes1);
constraint1->set_max_resolution_pixels(kMaxRes1);
}
// Constraint 2 - High-res and stricter HDCP
{
VideoResolutionConstraint* constraint2 = constraints->Add();
constraint2->set_min_resolution_pixels(kMinRes2);
constraint2->set_max_resolution_pixels(kMaxRes2);
constraint2->mutable_required_protection()->set_hdcp(kHdcpConstraint);
}
}
MockClock* mock_clock_;
int64_t current_time_;
StrictMock<HdcpOnlyMockCryptoSession> crypto_session_;
scoped_ptr<MaxResEngine> max_res_engine_;
License license_;
};
TEST_F(MaxResEngineTest, IsPermissiveByDefault) {
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
TEST_F(MaxResEngineTest, IsPermissiveWithoutALicense) {
max_res_engine_->SetResolution(1, kTargetRes1);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
TEST_F(MaxResEngineTest, IsPermissiveWithoutAResolution) {
max_res_engine_->SetLicense(license_);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
TEST_F(MaxResEngineTest, HandlesResolutionsBasedOnConstraints) {
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_NO_DIGITAL_OUTPUT),
Return(true)));
max_res_engine_->SetLicense(license_);
max_res_engine_->SetResolution(1, kTargetRes1);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
max_res_engine_->SetResolution(1, kTargetRes2);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
max_res_engine_->SetResolution(1, kTargetRes3);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
TEST_F(MaxResEngineTest, RequestsHdcpImmediatelyAndOnlyAfterInterval) {
int64_t start_time = current_time_;
{
InSequence calls;
EXPECT_CALL(*mock_clock_, GetCurrentTime()).WillOnce(Return(start_time));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillOnce(
DoAll(SetArgPointee<0>(HDCP_V2_2),
Return(true)));
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(start_time + kHdcpInterval / 2))
.WillOnce(Return(start_time + kHdcpInterval));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillOnce(
DoAll(SetArgPointee<0>(HDCP_V2_2),
Return(true)));
}
max_res_engine_->SetLicense(license_);
max_res_engine_->SetResolution(1, kTargetRes1);
max_res_engine_->OnTimerEvent();
max_res_engine_->OnTimerEvent();
max_res_engine_->OnTimerEvent();
}
TEST_F(MaxResEngineTest, DoesNotRequestHdcpWithoutALicense) {
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _)).Times(0);
max_res_engine_->OnTimerEvent();
}
TEST_F(MaxResEngineTest, HandlesConstraintOverridingHdcp) {
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_V2),
Return(true)));
max_res_engine_->SetLicense(license_);
max_res_engine_->SetResolution(1, kTargetRes1);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
max_res_engine_->SetResolution(1, kTargetRes2);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
TEST_F(MaxResEngineTest, HandlesNoHdcp) {
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_NONE),
Return(true)));
max_res_engine_->SetLicense(license_);
max_res_engine_->SetResolution(1, kTargetRes1);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
max_res_engine_->SetResolution(1, kTargetRes2);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
TEST_F(MaxResEngineTest, IgnoresHdcpWithoutAResolution) {
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _)).Times(0);
max_res_engine_->SetLicense(license_);
max_res_engine_->OnTimerEvent();
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId4));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId5));
EXPECT_TRUE(max_res_engine_->CanDecrypt(kKeyId6));
}
} // wvcdm

View File

@@ -0,0 +1,430 @@
// Copyright 2016 Google Inc. All Rights Reserved.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "crypto_session.h"
#include "license.h"
#include "policy_engine.h"
#include "mock_clock.h"
#include "scoped_ptr.h"
#include "wv_cdm_event_listener.h"
#include "wv_cdm_types.h"
// protobuf generated classes.
using video_widevine_server::sdk::License;
using video_widevine_server::sdk::License_Policy;
using video_widevine_server::sdk::STREAMING;
namespace wvcdm {
typedef ::video_widevine_server::sdk::License License;
typedef ::video_widevine_server::sdk::License::KeyContainer KeyContainer;
typedef ::video_widevine_server::sdk::License::KeyContainer::OutputProtection
OutputProtection;
typedef ::video_widevine_server::sdk::License::KeyContainer::
VideoResolutionConstraint VideoResolutionConstraint;
typedef ::google::protobuf::RepeatedPtrField<KeyContainer> KeyList;
typedef ::google::protobuf::RepeatedPtrField<VideoResolutionConstraint>
ConstraintList;
using namespace testing;
namespace {
const CdmSessionId kSessionId = "mock_session_id";
const KeyId kKeyId1 = "1111kKeyId1";
const KeyId kKeyId2 = "2222kKeyId2";
const KeyId kKeyId3 = "3333kKeyId3";
const KeyId kKeyId4 = "4444kKeyId4";
const KeyId kKeyId5 = "5555kKeyId5";
const KeyId kKeyId6 = "6666kKeyId6";
const uint32_t kMinRes1 = 0;
const uint32_t kMaxRes1 = 2000;
const uint32_t kMinRes2 = kMaxRes1;
const uint32_t kMaxRes2 = 4000;
const uint32_t kTargetRes1 = (kMinRes1 + kMaxRes1) / 2;
const uint32_t kTargetRes2 = (kMinRes2 + kMaxRes2) / 2;
const uint32_t kTargetRes3 = kMaxRes2 + 1000;
const int64_t kRentalDuration = 604800; // 7 days
const int64_t kPlaybackDuration = 172800; // 48 hours
const int64_t kStreamingLicenseDuration = 300;
const OutputProtection::HDCP kHdcpV2 = OutputProtection::HDCP_V2;
const OutputProtection::HDCP kHdcpV2_1 = OutputProtection::HDCP_V2_1;
// should match kHdcpCheckInterval in policy_engine.cpp
const int64_t kHdcpInterval = 10;
class HdcpOnlyMockCryptoSession : public CryptoSession {
public:
MOCK_METHOD2(GetHdcpCapabilities, bool(HdcpCapability*, HdcpCapability*));
};
class MockCdmEventListener : public WvCdmEventListener {
public:
MOCK_METHOD1(OnSessionRenewalNeeded, void(const CdmSessionId& session_id));
MOCK_METHOD3(OnSessionKeysChange, void(const CdmSessionId& session_id,
const CdmKeyStatusMap& keys_status,
bool has_new_usable_key));
MOCK_METHOD2(OnExpirationUpdate, void(const CdmSessionId& session_id,
int64_t new_expiry_time_seconds));
};
} // namespace
class PolicyEngineConstraintsTest : public Test {
protected:
virtual void SetUp() {
mock_clock_ = new NiceMock<MockClock>();
current_time_ = 0;
policy_engine_.reset(new PolicyEngine(kSessionId, &mock_event_listener_,
&crypto_session_));
InjectMockClock();
SetupLicense();
}
void AddConstraints(ConstraintList* constraints) {
// Constraint 1 - Low-res and no HDCP
{
VideoResolutionConstraint* c_lo_res_no_hdcp = constraints->Add();
c_lo_res_no_hdcp->set_min_resolution_pixels(kMinRes1);
c_lo_res_no_hdcp->set_max_resolution_pixels(kMaxRes1);
}
// Constraint 2 - High-res and stricter HDCP
{
VideoResolutionConstraint* c_hi_res_hdcp_v2 = constraints->Add();
c_hi_res_hdcp_v2->set_min_resolution_pixels(kMinRes2);
c_hi_res_hdcp_v2->set_max_resolution_pixels(kMaxRes2);
c_hi_res_hdcp_v2->mutable_required_protection()->set_hdcp(kHdcpV2_1);
}
}
void SetupLicense() {
license_.set_license_start_time(current_time_);
LicenseIdentification* id = license_.mutable_id();
id->set_version(1);
id->set_type(STREAMING);
License_Policy* policy = license_.mutable_policy();
policy = license_.mutable_policy();
policy->set_can_play(true);
policy->set_can_persist(false);
policy->set_rental_duration_seconds(kRentalDuration);
policy->set_playback_duration_seconds(kPlaybackDuration);
policy->set_license_duration_seconds(kStreamingLicenseDuration);
KeyList* keys = license_.mutable_key();
// Key 1 - Content key w/ ID, no HDCP, no constraints
{
KeyContainer* key1 = keys->Add();
key1->set_type(KeyContainer::CONTENT);
key1->set_id(kKeyId1);
}
// Key 2 - Content key w/ ID, HDCP, no constraints
{
KeyContainer* key2 = keys->Add();
key2->set_type(KeyContainer::CONTENT);
key2->set_id(kKeyId2);
key2->mutable_required_protection()->set_hdcp(kHdcpV2);
}
// Key 3 - Content key w/ ID, no HDCP, constraints
{
KeyContainer* key3 = keys->Add();
key3->set_type(KeyContainer::CONTENT);
key3->set_id(kKeyId3);
AddConstraints(key3->mutable_video_resolution_constraints());
}
// Key 4 - Content key w/ ID, HDCP, constraints
{
KeyContainer* key4 = keys->Add();
key4->set_type(KeyContainer::CONTENT);
key4->set_id(kKeyId4);
key4->mutable_required_protection()->set_hdcp(kHdcpV2);
AddConstraints(key4->mutable_video_resolution_constraints());
}
// Key 5 - Content key w/o ID, HDCP, constraints
{
KeyContainer* key5 = keys->Add();
key5->set_type(KeyContainer::CONTENT);
key5->mutable_required_protection()->set_hdcp(kHdcpV2);
AddConstraints(key5->mutable_video_resolution_constraints());
}
// Key 6 - Non-content key
{
KeyContainer* key6 = keys->Add();
key6->set_type(KeyContainer::OPERATOR_SESSION);
}
}
void InjectMockClock() {
mock_clock_ = new MockClock();
policy_engine_->set_clock(mock_clock_);
}
void ExpectSessionKeysChange(CdmKeyStatus expected_key_status,
bool expected_has_new_usable_key) {
EXPECT_CALL(mock_event_listener_,
OnSessionKeysChange(
kSessionId, UnorderedElementsAre(
Pair(kKeyId1, expected_key_status),
Pair(kKeyId2, expected_key_status),
Pair(kKeyId3, expected_key_status),
Pair(kKeyId4, expected_key_status)),
expected_has_new_usable_key));
}
void ExpectSessionKeysChanges(const KeyId& k1, CdmKeyStatus expected_1,
const KeyId& k2, CdmKeyStatus expected_2,
const KeyId& k3, CdmKeyStatus expected_3,
const KeyId& k4, CdmKeyStatus expected_4,
bool expected_has_new_usable_key) {
EXPECT_CALL(mock_event_listener_,
OnSessionKeysChange(
kSessionId, UnorderedElementsAre(
Pair(k1, expected_1),
Pair(k2, expected_2),
Pair(k3, expected_3),
Pair(k4, expected_4)),
expected_has_new_usable_key));
}
scoped_ptr<PolicyEngine> policy_engine_;
MockClock* mock_clock_;
int64_t current_time_;
StrictMock<HdcpOnlyMockCryptoSession> crypto_session_;
StrictMock<MockCdmEventListener> mock_event_listener_;
License license_;
};
TEST_F(PolicyEngineConstraintsTest, IsPermissiveWithoutAResolution) {
EXPECT_CALL(*mock_clock_, GetCurrentTime()).Times(2);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(kSessionId, _));
ExpectSessionKeysChange(kKeyStatusUsable, true);
policy_engine_->SetLicense(license_);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
}
TEST_F(PolicyEngineConstraintsTest, HandlesResolutionsBasedOnConstraints) {
{
Sequence time;
for (int i=0; i<4; ++i) {
EXPECT_CALL(*mock_clock_, GetCurrentTime()).InSequence(time)
.WillOnce(Return(i * 10));
}
}
{
Sequence key_change;
ExpectSessionKeysChange(kKeyStatusUsable, true);
ExpectSessionKeysChanges(kKeyId1, kKeyStatusUsable,
kKeyId2, kKeyStatusUsable,
kKeyId3, kKeyStatusOutputNotAllowed,
kKeyId4, kKeyStatusOutputNotAllowed, false);
}
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(kSessionId, _));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_NO_DIGITAL_OUTPUT),
Return(true)));
policy_engine_->SetLicense(license_);
policy_engine_->NotifyResolution(1, kTargetRes1);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
policy_engine_->NotifyResolution(1, kTargetRes2);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
policy_engine_->NotifyResolution(1, kTargetRes3);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
}
TEST_F(PolicyEngineConstraintsTest,
RequestsHdcpImmediatelyAndOnlyAfterInterval) {
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(0))
.WillOnce(Return(5));
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(kSessionId, _));
ExpectSessionKeysChange(kKeyStatusUsable, true);
int64_t start_time = current_time_ + 5;
{
InSequence calls;
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillOnce(
DoAll(SetArgPointee<0>(HDCP_V2_2),
Return(true)));
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(start_time + kHdcpInterval / 2))
.WillOnce(Return(start_time + kHdcpInterval));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillOnce(
DoAll(SetArgPointee<0>(HDCP_V2_2),
Return(true)));
}
policy_engine_->NotifyResolution(1, kTargetRes1);
policy_engine_->SetLicense(license_);
policy_engine_->OnTimerEvent();
policy_engine_->OnTimerEvent();
policy_engine_->OnTimerEvent();
}
TEST_F(PolicyEngineConstraintsTest, DoesNotRequestHdcpWithoutALicense) {
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(0));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _)).Times(0);
policy_engine_->OnTimerEvent();
}
TEST_F(PolicyEngineConstraintsTest, HandlesConstraintOverridingHdcp) {
{
Sequence time;
for (int i=0; i<3; ++i) {
EXPECT_CALL(*mock_clock_, GetCurrentTime()).InSequence(time)
.WillOnce(Return(i * 10));
}
}
{
Sequence key_change;
ExpectSessionKeysChange(kKeyStatusUsable, true);
ExpectSessionKeysChanges(kKeyId1, kKeyStatusUsable,
kKeyId2, kKeyStatusUsable,
kKeyId3, kKeyStatusOutputNotAllowed,
kKeyId4, kKeyStatusOutputNotAllowed, false);
}
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(kSessionId, _));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_V2),
Return(true)));
policy_engine_->SetLicense(license_);
policy_engine_->NotifyResolution(1, kTargetRes1);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
policy_engine_->NotifyResolution(1, kTargetRes2);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
}
TEST_F(PolicyEngineConstraintsTest, HandlesNoHdcp) {
{
Sequence time;
for (int i=0; i<3; ++i) {
EXPECT_CALL(*mock_clock_, GetCurrentTime()).InSequence(time)
.WillOnce(Return(i * 10));
}
}
{
Sequence key_change;
ExpectSessionKeysChanges(kKeyId1, kKeyStatusUsable,
kKeyId2, kKeyStatusOutputNotAllowed,
kKeyId3, kKeyStatusUsable,
kKeyId4, kKeyStatusOutputNotAllowed, false);
ExpectSessionKeysChanges(kKeyId1, kKeyStatusUsable,
kKeyId2, kKeyStatusOutputNotAllowed,
kKeyId3, kKeyStatusOutputNotAllowed,
kKeyId4, kKeyStatusOutputNotAllowed, false);
}
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(kSessionId, _));
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_NONE),
Return(true)));
policy_engine_->SetLicense(license_);
policy_engine_->NotifyResolution(1, kTargetRes1);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
policy_engine_->NotifyResolution(1, kTargetRes2);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
}
TEST_F(PolicyEngineConstraintsTest, IgnoresHdcpWithoutAResolution) {
{
Sequence time;
for (int i=0; i<2; ++i) {
EXPECT_CALL(*mock_clock_, GetCurrentTime()).InSequence(time)
.WillOnce(Return(i * 10));
}
}
ExpectSessionKeysChange(kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(kSessionId, _));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _)).Times(0);
policy_engine_->SetLicense(license_);
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId1));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId2));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId3));
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId4));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId5));
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId6));
}
} // namespace wvcdm

View File

@@ -42,6 +42,7 @@ const char* kRenewalServerUrl =
const KeyId kKeyId = "357adc89f1673433c36c621f1b5c41ee";
const KeyId kAnotherKeyId = "another_key_id";
const KeyId kSomeRandomKeyId = "some_random_key_id";
const KeyId kUnknownKeyId = "some_random_unknown_key_id";
const CdmSessionId kSessionId = "mock_session_id";
int64_t GetLicenseRenewalDelay(int64_t license_duration) {
@@ -60,13 +61,6 @@ class MockCdmEventListener : public WvCdmEventListener {
int64_t new_expiry_time_seconds));
};
class MockMaxResEngine : public MaxResEngine {
public:
MockMaxResEngine() : MaxResEngine(NULL) {}
MOCK_METHOD1(CanDecrypt, bool(const KeyId& key_id));
};
} // namespace
// protobuf generated classes.
@@ -138,11 +132,6 @@ class PolicyEngineTest : public ::testing::Test {
policy_engine_->set_clock(mock_clock_);
}
void InjectMockMaxResEngine() {
mock_max_res_engine_ = new MockMaxResEngine();
policy_engine_->set_max_res_engine(mock_max_res_engine_);
}
void ExpectSessionKeysChange(CdmKeyStatus expected_key_status,
bool expected_has_new_usable_key) {
EXPECT_CALL(mock_event_listener_,
@@ -165,7 +154,6 @@ class PolicyEngineTest : public ::testing::Test {
StrictMock<MockCdmEventListener> mock_event_listener_;
MockClock* mock_clock_;
MockMaxResEngine* mock_max_res_engine_;
scoped_ptr<PolicyEngine> policy_engine_;
License license_;
MockFunction<void(int i)> check_;
@@ -1036,56 +1024,204 @@ TEST_F(PolicyEngineTest, MultipleKeysInLicense) {
EXPECT_FALSE(policy_engine_->CanDecrypt(kSomeRandomKeyId));
}
TEST_F(PolicyEngineTest, KeysOutputNotAllowedByMaxResEngine) {
class PolicyEngineKeyAllowedUsageTest : public PolicyEngineTest {
protected:
enum KeyFlag {
kKeyFlagNull,
kKeyFlagFalse,
kKeyFlagTrue
};
static const KeyFlag kEncryptNull = kKeyFlagNull;
static const KeyFlag kEncryptFalse = kKeyFlagFalse;
static const KeyFlag kEncryptTrue = kKeyFlagTrue;
static const KeyFlag kDecryptNull = kKeyFlagNull;
static const KeyFlag kDecryptFalse = kKeyFlagFalse;
static const KeyFlag kDecryptTrue = kKeyFlagTrue;
static const KeyFlag kSignNull = kKeyFlagNull;
static const KeyFlag kSignFalse = kKeyFlagFalse;
static const KeyFlag kSignTrue = kKeyFlagTrue;
static const KeyFlag kVerifyNull = kKeyFlagNull;
static const KeyFlag kVerifyFalse = kKeyFlagFalse;
static const KeyFlag kVerifyTrue = kKeyFlagTrue;
static const KeyFlag kContentSecureFalse = kKeyFlagFalse;
static const KeyFlag kContentSecureTrue = kKeyFlagTrue;
static const KeyFlag kContentClearFalse = kKeyFlagFalse;
static const KeyFlag kContentClearTrue = kKeyFlagTrue;
void ExpectAllowedContentKeySettings(const CdmKeyAllowedUsage& key_usage,
KeyFlag secure, KeyFlag clear) {
EXPECT_EQ(key_usage.decrypt_to_secure_buffer, secure == kKeyFlagTrue);
EXPECT_EQ(key_usage.decrypt_to_clear_buffer, clear == kKeyFlagTrue);
EXPECT_FALSE(key_usage.generic_encrypt);
EXPECT_FALSE(key_usage.generic_decrypt);
EXPECT_FALSE(key_usage.generic_sign);
EXPECT_FALSE(key_usage.generic_verify);
}
void ExpectAllowedOperatorKeySettings(const CdmKeyAllowedUsage& key_usage,
KeyFlag encrypt, KeyFlag decrypt,
KeyFlag sign, KeyFlag verify) {
EXPECT_FALSE(key_usage.decrypt_to_secure_buffer);
EXPECT_FALSE(key_usage.decrypt_to_clear_buffer);
EXPECT_EQ(key_usage.generic_encrypt, encrypt == kKeyFlagTrue);
EXPECT_EQ(key_usage.generic_decrypt, decrypt == kKeyFlagTrue);
EXPECT_EQ(key_usage.generic_sign, sign == kKeyFlagTrue);
EXPECT_EQ(key_usage.generic_verify, verify == kKeyFlagTrue);
}
void ExpectSecureContentKey(const KeyId& key_id) {
CdmKeyAllowedUsage key_usage;
EXPECT_EQ(NO_ERROR,
policy_engine_->QueryKeyAllowedUsage(key_id, &key_usage));
ExpectAllowedContentKeySettings(key_usage, kContentSecureTrue,
kContentSecureFalse);
}
void ExpectLessSecureContentKey(const KeyId& key_id) {
CdmKeyAllowedUsage key_usage;
EXPECT_EQ(NO_ERROR,
policy_engine_->QueryKeyAllowedUsage(key_id, &key_usage));
ExpectAllowedContentKeySettings(key_usage, kContentSecureTrue,
kContentSecureTrue);
}
void ExpectOperatorSessionKey(const KeyId& key_id, KeyFlag encrypt,
KeyFlag decrypt, KeyFlag sign, KeyFlag verify) {
CdmKeyAllowedUsage key_usage;
EXPECT_EQ(NO_ERROR,
policy_engine_->QueryKeyAllowedUsage(key_id, &key_usage));
ExpectAllowedOperatorKeySettings(key_usage, encrypt, decrypt, sign, verify);
}
void AddOperatorSessionKey(const KeyId& key_id, KeyFlag encrypt,
KeyFlag decrypt, KeyFlag sign, KeyFlag verify) {
License::KeyContainer* non_content_key = license_.add_key();
non_content_key->set_type(License::KeyContainer::OPERATOR_SESSION);
non_content_key->set_id(key_id);
License::KeyContainer::OperatorSessionKeyPermissions* permissions =
non_content_key->mutable_operator_session_key_permissions();
if (encrypt != kKeyFlagNull) {
permissions->set_allow_encrypt(encrypt == kKeyFlagTrue);
}
if (decrypt != kKeyFlagNull) {
permissions->set_allow_decrypt(decrypt == kKeyFlagTrue);
}
if (sign != kKeyFlagNull) {
permissions->set_allow_sign(sign == kKeyFlagTrue);
}
if (verify != kKeyFlagNull) {
permissions->set_allow_signature_verify(verify == kKeyFlagTrue);
}
}
};
TEST_F(PolicyEngineKeyAllowedUsageTest, AllowedUsageBasic) {
const KeyId kGenericKeyId = "oper_session_key";
license_.clear_key();
// most secure
License::KeyContainer* content_key = license_.add_key();
content_key->set_type(License::KeyContainer::CONTENT);
content_key->set_id(kKeyId);
content_key->set_level(License::KeyContainer::HW_SECURE_ALL);
// generic operator session key (sign)
AddOperatorSessionKey(kGenericKeyId, kEncryptNull, kDecryptNull, kSignTrue,
kVerifyNull);
License::KeyContainer* content_key_without_id = license_.add_key();
content_key_without_id->set_type(License::KeyContainer::CONTENT);
// default level - less secure
License::KeyContainer* another_content_key = license_.add_key();
another_content_key->set_type(License::KeyContainer::CONTENT);
another_content_key->set_id(kAnotherKeyId);
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(kLicenseStartTime + 1))
.WillOnce(Return(kLicenseStartTime + 5))
.WillOnce(Return(kLicenseStartTime + 8))
.WillOnce(Return(kLicenseStartTime + 10));
.WillOnce(Return(kLicenseStartTime + 1));
InjectMockMaxResEngine();
EXPECT_CALL(*mock_max_res_engine_, CanDecrypt(kKeyId))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_CALL(*mock_max_res_engine_, CanDecrypt(kAnotherKeyId))
.WillOnce(Return(false))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(true));
InSequence s;
ExpectSessionKeysChange(kKeyStatusOutputNotAllowed,
kKeyStatusOutputNotAllowed, false);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(_, _));
ExpectSessionKeysChange(kKeyStatusUsable, kKeyStatusOutputNotAllowed, true);
ExpectSessionKeysChange(kKeyStatusOutputNotAllowed, kKeyStatusUsable, true);
ExpectSessionKeysChange(kKeyStatusUsable, kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(_, _));
policy_engine_->SetLicense(license_);
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kAnotherKeyId));
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_FALSE(policy_engine_->CanDecrypt(kAnotherKeyId));
ExpectSecureContentKey(kKeyId);
ExpectLessSecureContentKey(kAnotherKeyId);
ExpectOperatorSessionKey(kGenericKeyId, kEncryptNull, kDecryptNull,
kSignTrue, kVerifyNull);
policy_engine_->OnTimerEvent();
EXPECT_FALSE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_TRUE(policy_engine_->CanDecrypt(kAnotherKeyId));
CdmKeyAllowedUsage key_usage;
EXPECT_EQ(KEY_NOT_FOUND_1,
policy_engine_->QueryKeyAllowedUsage(kUnknownKeyId, &key_usage));
}
policy_engine_->OnTimerEvent();
EXPECT_TRUE(policy_engine_->CanDecrypt(kKeyId));
EXPECT_TRUE(policy_engine_->CanDecrypt(kAnotherKeyId));
TEST_F(PolicyEngineKeyAllowedUsageTest, AllowedUsageGeneric) {
const KeyId kGenericEncryptKeyId = "oper_session_key_1";
const KeyId kGenericDecryptKeyId = "oper_session_key_2";
const KeyId kGenericSignKeyId = "oper_session_key_3";
const KeyId kGenericVerifyKeyId = "oper_session_key_4";
const KeyId kGenericFullKeyId = "oper_session_key_5";
const KeyId kGenericExplicitKeyId = "oper_session_key_6";
license_.clear_key();
// more secure
License::KeyContainer* content_key = license_.add_key();
content_key->set_type(License::KeyContainer::CONTENT);
content_key->set_id(kKeyId);
content_key->set_level(License::KeyContainer::HW_SECURE_DECODE);
// less secure
License::KeyContainer* another_content_key = license_.add_key();
another_content_key->set_type(License::KeyContainer::CONTENT);
another_content_key->set_id(kAnotherKeyId);
another_content_key->set_level(License::KeyContainer::HW_SECURE_CRYPTO);
// generic operator session keys
AddOperatorSessionKey(kGenericSignKeyId, kEncryptNull, kDecryptNull,
kSignTrue, kVerifyNull);
AddOperatorSessionKey(kGenericEncryptKeyId, kEncryptTrue, kDecryptNull,
kSignNull, kVerifyNull);
AddOperatorSessionKey(kGenericDecryptKeyId, kEncryptNull, kDecryptTrue,
kSignNull, kVerifyNull);
AddOperatorSessionKey(kGenericVerifyKeyId, kEncryptNull, kDecryptNull,
kSignNull, kVerifyTrue);
AddOperatorSessionKey(kGenericFullKeyId, kEncryptTrue, kDecryptTrue,
kSignTrue, kVerifyTrue);
AddOperatorSessionKey(kGenericExplicitKeyId, kEncryptFalse, kDecryptTrue,
kSignFalse, kVerifyTrue);
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(kLicenseStartTime + 1));
ExpectSessionKeysChange(kKeyStatusUsable, kKeyStatusUsable, true);
EXPECT_CALL(mock_event_listener_, OnExpirationUpdate(_, _));
policy_engine_->SetLicense(license_);
ExpectSecureContentKey(kKeyId);
ExpectLessSecureContentKey(kAnotherKeyId);
ExpectOperatorSessionKey(kGenericEncryptKeyId, kEncryptTrue, kDecryptFalse,
kSignFalse, kVerifyFalse);
ExpectOperatorSessionKey(kGenericDecryptKeyId, kEncryptFalse, kDecryptTrue,
kSignFalse, kVerifyFalse);
ExpectOperatorSessionKey(kGenericSignKeyId, kEncryptFalse, kDecryptFalse,
kSignTrue, kVerifyFalse);
ExpectOperatorSessionKey(kGenericVerifyKeyId, kEncryptFalse, kDecryptFalse,
kSignFalse, kVerifyTrue);
ExpectOperatorSessionKey(kGenericFullKeyId, kEncryptTrue, kDecryptTrue,
kSignTrue, kVerifyTrue);
ExpectOperatorSessionKey(kGenericExplicitKeyId, kEncryptFalse, kDecryptTrue,
kSignFalse, kVerifyTrue);
}
class PolicyEngineQueryTest : public PolicyEngineTest {

View File

@@ -26,59 +26,74 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case DEVICE_REVOKED: *os << "DEVICE_REVOKED";
break;
case INSUFFICIENT_CRYPTO_RESOURCES: *os << "INSUFFICIENT_CRYPTO_RESOURCES";
case INSUFFICIENT_CRYPTO_RESOURCES: *os << "INSUFFICIENT_CRYPTO_RESOURCES";
break;
case ADD_KEY_ERROR: *os << "ADD_KEY_ERROR";
break;
case CERT_PROVISIONING_GET_KEYBOX_ERROR_1: *os << "CERT_PROVISIONING_GET_KEYBOX_ERROR_1";
case CERT_PROVISIONING_GET_KEYBOX_ERROR_1:
*os << "CERT_PROVISIONING_GET_KEYBOX_ERROR_1";
break;
case CERT_PROVISIONING_GET_KEYBOX_ERROR_2: *os << "CERT_PROVISIONING_GET_KEYBOX_ERROR_2";
case CERT_PROVISIONING_GET_KEYBOX_ERROR_2:
*os << "CERT_PROVISIONING_GET_KEYBOX_ERROR_2";
break;
case CERT_PROVISIONING_INVALID_CERT_TYPE: *os << "CERT_PROVISIONING_INVALID_CERT_TYPE";
case CERT_PROVISIONING_INVALID_CERT_TYPE:
*os << "CERT_PROVISIONING_INVALID_CERT_TYPE";
break;
case CERT_PROVISIONING_REQUEST_ERROR_1: *os << "CERT_PROVISIONING_REQUEST_ERROR_1";
case CERT_PROVISIONING_REQUEST_ERROR_1:
*os << "CERT_PROVISIONING_REQUEST_ERROR_1";
break;
case CERT_PROVISIONING_REQUEST_ERROR_2: *os << "CERT_PROVISIONING_REQUEST_ERROR_2";
case CERT_PROVISIONING_REQUEST_ERROR_2:
*os << "CERT_PROVISIONING_REQUEST_ERROR_2";
break;
case CERT_PROVISIONING_REQUEST_ERROR_3: *os << "CERT_PROVISIONING_REQUEST_ERROR_3";
case CERT_PROVISIONING_REQUEST_ERROR_3:
*os << "CERT_PROVISIONING_REQUEST_ERROR_3";
break;
case CERT_PROVISIONING_REQUEST_ERROR_4: *os << "CERT_PROVISIONING_REQUEST_ERROR_4";
case CERT_PROVISIONING_REQUEST_ERROR_4:
*os << "CERT_PROVISIONING_REQUEST_ERROR_4";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_1: *os << "CERT_PROVISIONING_RESPONSE_ERROR_1";
case CERT_PROVISIONING_RESPONSE_ERROR_1:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_1";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_2: *os << "CERT_PROVISIONING_RESPONSE_ERROR_2";
case CERT_PROVISIONING_RESPONSE_ERROR_2:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_2";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_3: *os << "CERT_PROVISIONING_RESPONSE_ERROR_3";
case CERT_PROVISIONING_RESPONSE_ERROR_3:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_3";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_4: *os << "CERT_PROVISIONING_RESPONSE_ERROR_4";
case CERT_PROVISIONING_RESPONSE_ERROR_4:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_4";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_5: *os << "CERT_PROVISIONING_RESPONSE_ERROR_5";
case CERT_PROVISIONING_RESPONSE_ERROR_5:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_5";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_6: *os << "CERT_PROVISIONING_RESPONSE_ERROR_6";
case CERT_PROVISIONING_RESPONSE_ERROR_6:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_6";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_7: *os << "CERT_PROVISIONING_RESPONSE_ERROR_7";
case CERT_PROVISIONING_RESPONSE_ERROR_7:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_7";
break;
case CERT_PROVISIONING_RESPONSE_ERROR_8: *os << "CERT_PROVISIONING_RESPONSE_ERROR_8";
case CERT_PROVISIONING_RESPONSE_ERROR_8:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_8";
break;
case CRYPTO_SESSION_OPEN_ERROR_1: *os << "CRYPTO_SESSION_OPEN_ERROR_1";
case CRYPTO_SESSION_OPEN_ERROR_1: *os << "CRYPTO_SESSION_OPEN_ERROR_1";
break;
case CRYPTO_SESSION_OPEN_ERROR_2: *os << "CRYPTO_SESSION_OPEN_ERROR_2";
case CRYPTO_SESSION_OPEN_ERROR_2: *os << "CRYPTO_SESSION_OPEN_ERROR_2";
break;
case CRYPTO_SESSION_OPEN_ERROR_3: *os << "CRYPTO_SESSION_OPEN_ERROR_3";
case CRYPTO_SESSION_OPEN_ERROR_3: *os << "CRYPTO_SESSION_OPEN_ERROR_3";
break;
case CRYPTO_SESSION_OPEN_ERROR_4: *os << "CRYPTO_SESSION_OPEN_ERROR_4";
case CRYPTO_SESSION_OPEN_ERROR_4: *os << "CRYPTO_SESSION_OPEN_ERROR_4";
break;
case CRYPTO_SESSION_OPEN_ERROR_5: *os << "CRYPTO_SESSION_OPEN_ERROR_5";
case CRYPTO_SESSION_OPEN_ERROR_5: *os << "CRYPTO_SESSION_OPEN_ERROR_5";
break;
case DECRYPT_NOT_READY: *os << "DECRYPT_NOT_READY";
break;
case DEVICE_CERTIFICATE_ERROR_1: *os << "DEVICE_CERTIFICATE_ERROR_1";
case DEVICE_CERTIFICATE_ERROR_1: *os << "DEVICE_CERTIFICATE_ERROR_1";
break;
case DEVICE_CERTIFICATE_ERROR_2: *os << "DEVICE_CERTIFICATE_ERROR_2";
case DEVICE_CERTIFICATE_ERROR_2: *os << "DEVICE_CERTIFICATE_ERROR_2";
break;
case DEVICE_CERTIFICATE_ERROR_3: *os << "DEVICE_CERTIFICATE_ERROR_3";
case DEVICE_CERTIFICATE_ERROR_3: *os << "DEVICE_CERTIFICATE_ERROR_3";
break;
case DEVICE_CERTIFICATE_ERROR_4: *os << "DEVICE_CERTIFICATE_ERROR_4";
case DEVICE_CERTIFICATE_ERROR_4: *os << "DEVICE_CERTIFICATE_ERROR_4";
break;
case EMPTY_KEY_DATA_1: *os << "EMPTY_KEY_DATA_1";
break;
@@ -96,25 +111,27 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case EMPTY_LICENSE_RENEWAL: *os << "EMPTY_LICENSE_RENEWAL";
break;
case EMPTY_LICENSE_RESPONSE_1: *os << "EMPTY_LICENSE_RESPONSE_1";
case EMPTY_LICENSE_RESPONSE_1: *os << "EMPTY_LICENSE_RESPONSE_1";
break;
case EMPTY_LICENSE_RESPONSE_2: *os << "EMPTY_LICENSE_RESPONSE_2";
case EMPTY_LICENSE_RESPONSE_2: *os << "EMPTY_LICENSE_RESPONSE_2";
break;
case EMPTY_PROVISIONING_CERTIFICATE_1: *os << "EMPTY_PROVISIONING_CERTIFICATE_1";
case EMPTY_PROVISIONING_CERTIFICATE_1:
*os << "EMPTY_PROVISIONING_CERTIFICATE_1";
break;
case EMPTY_PROVISIONING_RESPONSE: *os << "EMPTY_PROVISIONING_RESPONSE";
case EMPTY_PROVISIONING_RESPONSE: *os << "EMPTY_PROVISIONING_RESPONSE";
break;
case EMPTY_SESSION_ID: *os << "EMPTY_SESSION_ID";
break;
case GENERATE_DERIVED_KEYS_ERROR: *os << "GENERATE_DERIVED_KEYS_ERROR";
case GENERATE_DERIVED_KEYS_ERROR: *os << "GENERATE_DERIVED_KEYS_ERROR";
break;
case LICENSE_RENEWAL_NONCE_GENERATION_ERROR: *os << "LICENSE_RENEWAL_NONCE_GENERATION_ERROR";
case LICENSE_RENEWAL_NONCE_GENERATION_ERROR:
*os << "LICENSE_RENEWAL_NONCE_GENERATION_ERROR";
break;
case GENERATE_USAGE_REPORT_ERROR: *os << "GENERATE_USAGE_REPORT_ERROR";
case GENERATE_USAGE_REPORT_ERROR: *os << "GENERATE_USAGE_REPORT_ERROR";
break;
case GET_LICENSE_ERROR: *os << "GET_LICENSE_ERROR";
break;
case GET_RELEASED_LICENSE_ERROR: *os << "GET_RELEASED_LICENSE_ERROR";
case GET_RELEASED_LICENSE_ERROR: *os << "GET_RELEASED_LICENSE_ERROR";
break;
case GET_USAGE_INFO_ERROR_1: *os << "GET_USAGE_INFO_ERROR_1";
break;
@@ -126,51 +143,60 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case INIT_DATA_NOT_FOUND: *os << "INIT_DATA_NOT_FOUND";
break;
case INVALID_CRYPTO_SESSION_1: *os << "INVALID_CRYPTO_SESSION_1";
case INVALID_CRYPTO_SESSION_1: *os << "INVALID_CRYPTO_SESSION_1";
break;
case INVALID_CRYPTO_SESSION_2: *os << "INVALID_CRYPTO_SESSION_2";
case INVALID_CRYPTO_SESSION_2: *os << "INVALID_CRYPTO_SESSION_2";
break;
case INVALID_CRYPTO_SESSION_3: *os << "INVALID_CRYPTO_SESSION_3";
case INVALID_CRYPTO_SESSION_3: *os << "INVALID_CRYPTO_SESSION_3";
break;
case INVALID_CRYPTO_SESSION_4: *os << "INVALID_CRYPTO_SESSION_4";
case INVALID_CRYPTO_SESSION_4: *os << "INVALID_CRYPTO_SESSION_4";
break;
case INVALID_CRYPTO_SESSION_5: *os << "INVALID_CRYPTO_SESSION_5";
case INVALID_CRYPTO_SESSION_5: *os << "INVALID_CRYPTO_SESSION_5";
break;
case INVALID_DECRYPT_PARAMETERS_ENG_1: *os << "INVALID_DECRYPT_PARAMETERS_ENG_1";
case INVALID_DECRYPT_PARAMETERS_ENG_1:
*os << "INVALID_DECRYPT_PARAMETERS_ENG_1";
break;
case INVALID_DECRYPT_PARAMETERS_ENG_2: *os << "INVALID_DECRYPT_PARAMETERS_ENG_2";
case INVALID_DECRYPT_PARAMETERS_ENG_2:
*os << "INVALID_DECRYPT_PARAMETERS_ENG_2";
break;
case INVALID_DECRYPT_PARAMETERS_ENG_3: *os << "INVALID_DECRYPT_PARAMETERS_ENG_3";
case INVALID_DECRYPT_PARAMETERS_ENG_3:
*os << "INVALID_DECRYPT_PARAMETERS_ENG_3";
break;
case INVALID_DECRYPT_PARAMETERS_ENG_4: *os << "INVALID_DECRYPT_PARAMETERS_ENG_4";
case INVALID_DECRYPT_PARAMETERS_ENG_4:
*os << "INVALID_DECRYPT_PARAMETERS_ENG_4";
break;
case INVALID_DEVICE_CERTIFICATE_TYPE: *os << "INVALID_DEVICE_CERTIFICATE_TYPE";
case INVALID_DEVICE_CERTIFICATE_TYPE:
*os << "INVALID_DEVICE_CERTIFICATE_TYPE";
break;
case INVALID_KEY_SYSTEM: *os << "INVALID_KEY_SYSTEM";
break;
case INVALID_LICENSE_RESPONSE: *os << "INVALID_LICENSE_RESPONSE";
case INVALID_LICENSE_RESPONSE: *os << "INVALID_LICENSE_RESPONSE";
break;
case INVALID_LICENSE_TYPE: *os << "INVALID_LICENSE_TYPE";
break;
case INVALID_PARAMETERS_ENG_1: *os << "INVALID_PARAMETERS_ENG_1";
case INVALID_PARAMETERS_ENG_1: *os << "INVALID_PARAMETERS_ENG_1";
break;
case INVALID_PARAMETERS_ENG_2: *os << "INVALID_PARAMETERS_ENG_2";
case INVALID_PARAMETERS_ENG_2: *os << "INVALID_PARAMETERS_ENG_2";
break;
case INVALID_PARAMETERS_ENG_3: *os << "INVALID_PARAMETERS_ENG_3";
case INVALID_PARAMETERS_ENG_3: *os << "INVALID_PARAMETERS_ENG_3";
break;
case INVALID_PARAMETERS_ENG_4: *os << "INVALID_PARAMETERS_ENG_4";
case INVALID_PARAMETERS_ENG_4: *os << "INVALID_PARAMETERS_ENG_4";
break;
case INVALID_PARAMETERS_LIC_1: *os << "INVALID_PARAMETERS_LIC_1";
case INVALID_PARAMETERS_LIC_1: *os << "INVALID_PARAMETERS_LIC_1";
break;
case INVALID_PARAMETERS_LIC_2: *os << "INVALID_PARAMETERS_LIC_2";
case INVALID_PARAMETERS_LIC_2: *os << "INVALID_PARAMETERS_LIC_2";
break;
case INVALID_PROVISIONING_PARAMETERS_1: *os << "INVALID_PROVISIONING_PARAMETERS_1";
case INVALID_PROVISIONING_PARAMETERS_1:
*os << "INVALID_PROVISIONING_PARAMETERS_1";
break;
case INVALID_PROVISIONING_PARAMETERS_2: *os << "INVALID_PROVISIONING_PARAMETERS_2";
case INVALID_PROVISIONING_PARAMETERS_2:
*os << "INVALID_PROVISIONING_PARAMETERS_2";
break;
case INVALID_PROVISIONING_REQUEST_PARAM_1: *os << "INVALID_PROVISIONING_REQUEST_PARAM_1";
case INVALID_PROVISIONING_REQUEST_PARAM_1:
*os << "INVALID_PROVISIONING_REQUEST_PARAM_1";
break;
case INVALID_PROVISIONING_REQUEST_PARAM_2: *os << "INVALID_PROVISIONING_REQUEST_PARAM_2";
case INVALID_PROVISIONING_REQUEST_PARAM_2:
*os << "INVALID_PROVISIONING_REQUEST_PARAM_2";
break;
case INVALID_QUERY_KEY: *os << "INVALID_QUERY_KEY";
break;
@@ -188,22 +214,28 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case LICENSE_ID_NOT_FOUND: *os << "LICENSE_ID_NOT_FOUND";
break;
case LICENSE_PARSER_INIT_ERROR: *os << "LICENSE_PARSER_INIT_ERROR";
case LICENSE_PARSER_INIT_ERROR: *os << "LICENSE_PARSER_INIT_ERROR";
break;
case LICENSE_PARSER_NOT_INITIALIZED_1: *os << "LICENSE_PARSER_NOT_INITIALIZED_1";
case LICENSE_PARSER_NOT_INITIALIZED_1:
*os << "LICENSE_PARSER_NOT_INITIALIZED_1";
break;
case LICENSE_PARSER_NOT_INITIALIZED_2: *os << "LICENSE_PARSER_NOT_INITIALIZED_2";
case LICENSE_PARSER_NOT_INITIALIZED_2:
*os << "LICENSE_PARSER_NOT_INITIALIZED_2";
break;
case LICENSE_PARSER_NOT_INITIALIZED_3: *os << "LICENSE_PARSER_NOT_INITIALIZED_3";
case LICENSE_PARSER_NOT_INITIALIZED_3:
*os << "LICENSE_PARSER_NOT_INITIALIZED_3";
break;
case LICENSE_RESPONSE_NOT_SIGNED: *os << "LICENSE_RESPONSE_NOT_SIGNED";
case LICENSE_RESPONSE_NOT_SIGNED: *os << "LICENSE_RESPONSE_NOT_SIGNED";
break;
break;
case LICENSE_RESPONSE_PARSE_ERROR_1: *os << "LICENSE_RESPONSE_PARSE_ERROR_1";
case LICENSE_RESPONSE_PARSE_ERROR_1:
*os << "LICENSE_RESPONSE_PARSE_ERROR_1";
break;
case LICENSE_RESPONSE_PARSE_ERROR_2: *os << "LICENSE_RESPONSE_PARSE_ERROR_2";
case LICENSE_RESPONSE_PARSE_ERROR_2:
*os << "LICENSE_RESPONSE_PARSE_ERROR_2";
break;
case LICENSE_RESPONSE_PARSE_ERROR_3: *os << "LICENSE_RESPONSE_PARSE_ERROR_3";
case LICENSE_RESPONSE_PARSE_ERROR_3:
*os << "LICENSE_RESPONSE_PARSE_ERROR_3";
break;
case LOAD_KEY_ERROR: *os << "LOAD_KEY_ERROR";
break;
@@ -211,31 +243,34 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case REFRESH_KEYS_ERROR: *os << "REFRESH_KEYS_ERROR";
break;
case RELEASE_ALL_USAGE_INFO_ERROR_1: *os << "RELEASE_ALL_USAGE_INFO_ERROR_1";
case RELEASE_ALL_USAGE_INFO_ERROR_1:
*os << "RELEASE_ALL_USAGE_INFO_ERROR_1";
break;
case RELEASE_ALL_USAGE_INFO_ERROR_2: *os << "RELEASE_ALL_USAGE_INFO_ERROR_2";
case RELEASE_ALL_USAGE_INFO_ERROR_2:
*os << "RELEASE_ALL_USAGE_INFO_ERROR_2";
break;
case RELEASE_KEY_ERROR: *os << "RELEASE_KEY_ERROR";
break;
case RELEASE_KEY_REQUEST_ERROR: *os << "RELEASE_KEY_REQUEST_ERROR";
case RELEASE_KEY_REQUEST_ERROR: *os << "RELEASE_KEY_REQUEST_ERROR";
break;
case RELEASE_LICENSE_ERROR_1: *os << "RELEASE_LICENSE_ERROR_1";
break;
case RELEASE_LICENSE_ERROR_2: *os << "RELEASE_LICENSE_ERROR_2";
break;
case RELEASE_USAGE_INFO_ERROR: *os << "RELEASE_USAGE_INFO_ERROR";
case RELEASE_USAGE_INFO_ERROR: *os << "RELEASE_USAGE_INFO_ERROR";
break;
case RENEW_KEY_ERROR_1: *os << "RENEW_KEY_ERROR_1";
break;
case RENEW_KEY_ERROR_2: *os << "RENEW_KEY_ERROR_2";
break;
case LICENSE_RENEWAL_SIGNING_ERROR: *os << "LICENSE_RENEWAL_SIGNING_ERROR";
case LICENSE_RENEWAL_SIGNING_ERROR: *os << "LICENSE_RENEWAL_SIGNING_ERROR";
break;
case RESTORE_OFFLINE_LICENSE_ERROR_2: *os << "RESTORE_OFFLINE_LICENSE_ERROR_2";
case RESTORE_OFFLINE_LICENSE_ERROR_2:
*os << "RESTORE_OFFLINE_LICENSE_ERROR_2";
break;
case SESSION_INIT_ERROR_2: *os << "SESSION_INIT_ERROR_2";
break;
case SESSION_INIT_GET_KEYBOX_ERROR: *os << "SESSION_INIT_GET_KEYBOX_ERROR";
case SESSION_INIT_GET_KEYBOX_ERROR: *os << "SESSION_INIT_GET_KEYBOX_ERROR";
break;
case SESSION_NOT_FOUND_1: *os << "SESSION_NOT_FOUND_1";
break;
@@ -257,7 +292,7 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case SESSION_NOT_FOUND_10: *os << "SESSION_NOT_FOUND_10";
break;
case SESSION_NOT_FOUND_FOR_DECRYPT: *os << "SESSION_NOT_FOUND_FOR_DECRYPT";
case SESSION_NOT_FOUND_FOR_DECRYPT: *os << "SESSION_NOT_FOUND_FOR_DECRYPT";
break;
case SESSION_KEYS_NOT_FOUND: *os << "SESSION_KEYS_NOT_FOUND";
break;
@@ -284,68 +319,134 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case LICENSE_RENEWAL_SERVICE_CERTIFICATE_GENERATION_ERROR:
*os << "LICENSE_RENEWAL_SERVICE_CERTIFICATE_GENERATION_ERROR";
break;
case EMPTY_PROVISIONING_CERTIFICATE_2: *os << "EMPTY_PROVISIONING_CERTIFICATE_2";
case EMPTY_PROVISIONING_CERTIFICATE_2:
*os << "EMPTY_PROVISIONING_CERTIFICATE_2";
break;
case PARSE_SERVICE_CERTIFICATE_ERROR: *os << "PARSE_SERVICE_CERTIFICATE_ERROR";
case PARSE_SERVICE_CERTIFICATE_ERROR:
*os << "PARSE_SERVICE_CERTIFICATE_ERROR";
break;
case SERVICE_CERTIFICATE_TYPE_ERROR: *os << "SERVICE_CERTIFICATE_TYPE_ERROR";
case SERVICE_CERTIFICATE_TYPE_ERROR:
*os << "SERVICE_CERTIFICATE_TYPE_ERROR";
break;
case CLIENT_ID_GENERATE_RANDOM_ERROR: *os << "CLIENT_ID_GENERATE_RANDOM_ERROR";
case CLIENT_ID_GENERATE_RANDOM_ERROR:
*os << "CLIENT_ID_GENERATE_RANDOM_ERROR";
break;
case CLIENT_ID_AES_INIT_ERROR: *os << "CLIENT_ID_AES_INIT_ERROR";
case CLIENT_ID_AES_INIT_ERROR: *os << "CLIENT_ID_AES_INIT_ERROR";
break;
case CLIENT_ID_AES_ENCRYPT_ERROR: *os << "CLIENT_ID_AES_ENCRYPT_ERROR";
case CLIENT_ID_AES_ENCRYPT_ERROR: *os << "CLIENT_ID_AES_ENCRYPT_ERROR";
break;
case CLIENT_ID_RSA_INIT_ERROR: *os << "CLIENT_ID_RSA_INIT_ERROR";
case CLIENT_ID_RSA_INIT_ERROR: *os << "CLIENT_ID_RSA_INIT_ERROR";
break;
case CLIENT_ID_RSA_ENCRYPT_ERROR: *os << "CLIENT_ID_RSA_ENCRYPT_ERROR";
case CLIENT_ID_RSA_ENCRYPT_ERROR: *os << "CLIENT_ID_RSA_ENCRYPT_ERROR";
break;
case INVALID_QUERY_STATUS: *os << "INVALID_QUERY_STATUS";
break;
case LICENSE_PARSER_NOT_INITIALIZED_4: *os << "LICENSE_PARSER_NOT_INITIALIZED_4";
case LICENSE_PARSER_NOT_INITIALIZED_4:
*os << "LICENSE_PARSER_NOT_INITIALIZED_4";
break;
case INVALID_PARAMETERS_LIC_3: *os << "INVALID_PARAMETERS_LIC_3";
case INVALID_PARAMETERS_LIC_3: *os << "INVALID_PARAMETERS_LIC_3";
break;
case INVALID_PARAMETERS_LIC_4: *os << "INVALID_PARAMETERS_LIC_4";
case INVALID_PARAMETERS_LIC_4: *os << "INVALID_PARAMETERS_LIC_4";
break;
case INVALID_PARAMETERS_LIC_6: *os << "INVALID_PARAMETERS_LIC_6";
case INVALID_PARAMETERS_LIC_6: *os << "INVALID_PARAMETERS_LIC_6";
break;
case INVALID_PARAMETERS_LIC_7: *os << "INVALID_PARAMETERS_LIC_7";
case INVALID_PARAMETERS_LIC_7: *os << "INVALID_PARAMETERS_LIC_7";
break;
case LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR:
*os << "LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR";
break;
case CENC_INIT_DATA_UNAVAILABLE: *os << "CENC_INIT_DATA_UNAVAILABLE";
case CENC_INIT_DATA_UNAVAILABLE: *os << "CENC_INIT_DATA_UNAVAILABLE";
break;
case PREPARE_CENC_CONTENT_ID_FAILED: *os << "PREPARE_CENC_CONTENT_ID_FAILED";
case PREPARE_CENC_CONTENT_ID_FAILED:
*os << "PREPARE_CENC_CONTENT_ID_FAILED";
break;
case WEBM_INIT_DATA_UNAVAILABLE: *os << "WEBM_INIT_DATA_UNAVAILABLE";
case WEBM_INIT_DATA_UNAVAILABLE: *os << "WEBM_INIT_DATA_UNAVAILABLE";
break;
case PREPARE_WEBM_CONTENT_ID_FAILED: *os << "PREPARE_WEBM_CONTENT_ID_FAILED";
case PREPARE_WEBM_CONTENT_ID_FAILED:
*os << "PREPARE_WEBM_CONTENT_ID_FAILED";
break;
case UNSUPPORTED_INIT_DATA_FORMAT: *os << "UNSUPPORTED_INIT_DATA_FORMAT";
case UNSUPPORTED_INIT_DATA_FORMAT: *os << "UNSUPPORTED_INIT_DATA_FORMAT";
break;
case LICENSE_REQUEST_NONCE_GENERATION_ERROR: *os << "LICENSE_REQUEST_NONCE_GENERATION_ERROR";
case LICENSE_REQUEST_NONCE_GENERATION_ERROR:
*os << "LICENSE_REQUEST_NONCE_GENERATION_ERROR";
break;
case LICENSE_REQUEST_SIGNING_ERROR: *os << "LICENSE_REQUEST_SIGNING_ERROR";
case LICENSE_REQUEST_SIGNING_ERROR: *os << "LICENSE_REQUEST_SIGNING_ERROR";
break;
case EMPTY_LICENSE_REQUEST: *os << "EMPTY_LICENSE_REQUEST";
break;
case DUPLICATE_SESSION_ID_SPECIFIED: *os << "DUPLICATE_SESSION_ID_SPECIFIED";
case DUPLICATE_SESSION_ID_SPECIFIED:
*os << "DUPLICATE_SESSION_ID_SPECIFIED";
break;
case LICENSE_RENEWAL_PROHIBITED: *os << "LICENSE_RENEWAL_PROHIBITED";
case LICENSE_RENEWAL_PROHIBITED: *os << "LICENSE_RENEWAL_PROHIBITED";
break;
case SESSION_FILE_HANDLE_INIT_ERROR: *os << "SESSION_FILE_HANDLE_INIT_ERROR";
case SESSION_FILE_HANDLE_INIT_ERROR:
*os << "SESSION_FILE_HANDLE_INIT_ERROR";
break;
case INCORRECT_CRYPTO_MODE: *os << "INCORRECT_CRYPTO_MODE";
break;
case INVALID_PARAMETERS_ENG_5: *os << "INVALID_PARAMETERS_ENG_5";
break;
case DECRYPT_ERROR: *os << "DECRYPT_ERROR";
break;
case INSUFFICIENT_OUTPUT_PROTECTION:
*os << "INSUFFICIENT_OUTPUT_PROTECTION";
break;
case SESSION_NOT_FOUND_12: *os << "SESSION_NOT_FOUND_12";
break;
case KEY_NOT_FOUND_1: *os << "KEY_NOT_FOUND_1";
break;
case KEY_NOT_FOUND_2: *os << "KEY_NOT_FOUND_2";
break;
case KEY_CONFLICT_1: *os << "KEY_CONFLICT_1";
break;
case INVALID_PARAMETERS_ENG_6: *os << "INVALID_PARAMETERS_ENG_6";
break;
case INVALID_PARAMETERS_ENG_7: *os << "INVALID_PARAMETERS_ENG_7";
break;
case INVALID_PARAMETERS_ENG_8: *os << "INVALID_PARAMETERS_ENG_8";
break;
case INVALID_PARAMETERS_ENG_9: *os << "INVALID_PARAMETERS_ENG_9";
break;
case INVALID_PARAMETERS_ENG_10: *os << "INVALID_PARAMETERS_ENG_10";
break;
case INVALID_PARAMETERS_ENG_11: *os << "INVALID_PARAMETERS_ENG_11";
break;
case INVALID_PARAMETERS_ENG_12: *os << "INVALID_PARAMETERS_ENG_12";
break;
case SESSION_NOT_FOUND_13: *os << "SESSION_NOT_FOUND_13";
break;
case SESSION_NOT_FOUND_14: *os << "SESSION_NOT_FOUND_14";
break;
case SESSION_NOT_FOUND_15: *os << "SESSION_NOT_FOUND_15";
break;
case SESSION_NOT_FOUND_16: *os << "SESSION_NOT_FOUND_16";
break;
case KEY_NOT_FOUND_3: *os << "KEY_NOT_FOUND_3";
break;
case KEY_NOT_FOUND_4: *os << "KEY_NOT_FOUND_4";
break;
case KEY_NOT_FOUND_5: *os << "KEY_NOT_FOUND_5";
break;
case KEY_NOT_FOUND_6: *os << "KEY_NOT_FOUND_6";
break;
case KEY_ERROR_1: *os << "KEY_ERROR_1";
break;
case KEY_ERROR_2: *os << "KEY_ERROR_2";
break;
case KEY_ERROR_3: *os << "KEY_ERROR_3";
break;
case KEY_ERROR_4: *os << "KEY_ERROR_4";
break;
case INVALID_PARAMETERS_ENG_13: *os << "INVALID_PARAMETERS_ENG_13";
break;
case INVALID_PARAMETERS_ENG_14: *os << "INVALID_PARAMETERS_ENG_14";
break;
case INVALID_PARAMETERS_ENG_15: *os << "INVALID_PARAMETERS_ENG_15";
break;
case INVALID_PARAMETERS_ENG_16: *os << "INVALID_PARAMETERS_ENG_16";
break;
default:
*os << "Unknown CdmResponseType";
*os << "Unknown CdmResponseType";
break;
}
}
@@ -368,7 +469,7 @@ void PrintTo(const enum CdmLicenseType& value, ::std::ostream* os) {
void PrintTo(const enum CdmSecurityLevel& value, ::std::ostream* os) {
switch (value) {
case kSecurityLevelUninitialized: *os << "kSecurityLevelUninitialized";
case kSecurityLevelUninitialized: *os << "kSecurityLevelUninitialized";
break;
case kSecurityLevelL1: *os << "kSecurityLevelL1";
break;
@@ -391,7 +492,7 @@ void PrintTo(const enum CdmCertificateType& value, ::std::ostream* os) {
case kCertificateX509: *os << "kCertificateX509";
break;
default:
*os << "Unknown CdmCertificateType";
*os << "Unknown CdmCertificateType";
break;
}
};