|
|
|
|
@@ -1475,13 +1475,11 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|
|
|
|
|
|
|
|
|
void VerifyKeyRequestResponse(const std::string& server_url,
|
|
|
|
|
const std::string& client_auth) {
|
|
|
|
|
std::string response;
|
|
|
|
|
VerifyKeyRequestResponse(server_url, client_auth, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerifyUsageKeyRequestResponse(const std::string& server_url,
|
|
|
|
|
const std::string& client_auth) {
|
|
|
|
|
std::string response;
|
|
|
|
|
VerifyKeyRequestResponse(server_url, client_auth, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1496,10 +1494,19 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|
|
|
|
const std::string& client_auth,
|
|
|
|
|
bool is_usage,
|
|
|
|
|
std::string* response) {
|
|
|
|
|
VerifyKeyRequestResponse(wvcdm::KEY_ADDED, server_url, client_auth,
|
|
|
|
|
is_usage, response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VerifyKeyRequestResponse(CdmResponseType expected_response,
|
|
|
|
|
const std::string& server_url,
|
|
|
|
|
const std::string& client_auth,
|
|
|
|
|
bool is_usage,
|
|
|
|
|
std::string* response) {
|
|
|
|
|
*response = GetKeyRequestResponse(server_url, client_auth);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(decryptor_.AddKey(session_id_, *response, &key_set_id_),
|
|
|
|
|
wvcdm::KEY_ADDED);
|
|
|
|
|
expected_response);
|
|
|
|
|
EXPECT_EQ(is_usage || license_type_ == kLicenseTypeOffline,
|
|
|
|
|
key_set_id_.size() > 0);
|
|
|
|
|
}
|
|
|
|
|
@@ -3116,6 +3123,156 @@ TEST_F(WvCdmRequestLicenseTest, UsageRemoveAllTest) {
|
|
|
|
|
EXPECT_TRUE(usage_info.empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
|
|
|
|
|
Unprovision();
|
|
|
|
|
|
|
|
|
|
std::string app_id_empty = "";
|
|
|
|
|
std::string app_id_not_empty = "not empty";
|
|
|
|
|
|
|
|
|
|
TestWvCdmClientPropertySet property_set;
|
|
|
|
|
Provision(kLevelDefault);
|
|
|
|
|
|
|
|
|
|
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
|
|
|
|
FileSystem file_system;
|
|
|
|
|
DeviceFiles handle(&file_system);
|
|
|
|
|
EXPECT_TRUE(handle.Init(security_level));
|
|
|
|
|
std::vector<std::string> psts;
|
|
|
|
|
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(
|
|
|
|
|
DeviceFiles::GetUsageInfoFileName(""), &psts));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < N_ELEM(usage_info_sub_samples_icp); ++i) {
|
|
|
|
|
SubSampleInfo* data = usage_info_sub_samples_icp + i;
|
|
|
|
|
property_set.set_app_id(i % 2 == 0 ? app_id_empty : app_id_not_empty);
|
|
|
|
|
decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
|
|
|
|
|
NULL, &session_id_);
|
|
|
|
|
std::string key_id = a2bs_hex(
|
|
|
|
|
"000000427073736800000000" // blob size and pssh
|
|
|
|
|
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
|
|
|
|
|
"08011a0d7769646576696e655f74657374220f73" // pssh data
|
|
|
|
|
"747265616d696e675f636c6970");
|
|
|
|
|
|
|
|
|
|
char ch = 0x33 + i;
|
|
|
|
|
key_id.append(1, ch);
|
|
|
|
|
|
|
|
|
|
GenerateKeyRequest(key_id, kLicenseTypeStreaming, &property_set);
|
|
|
|
|
|
|
|
|
|
// TODO(rfrias): streaming_clip6 is a streaming license without a pst
|
|
|
|
|
if (ch == '6')
|
|
|
|
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, false);
|
|
|
|
|
else
|
|
|
|
|
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
|
|
|
|
|
CdmDecryptionParameters decryption_parameters(
|
|
|
|
|
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
|
|
|
|
|
&data->iv, data->block_offset, &decrypt_buffer[0]);
|
|
|
|
|
decryption_parameters.is_encrypted = data->is_encrypted;
|
|
|
|
|
decryption_parameters.is_secure = data->is_secure;
|
|
|
|
|
decryption_parameters.subsample_flags = data->subsample_flags;
|
|
|
|
|
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
|
|
|
|
|
decryption_parameters));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
|
|
|
|
|
decrypt_buffer.begin()));
|
|
|
|
|
decryptor_.CloseSession(session_id_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CdmUsageInfo usage_info;
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
KEY_MESSAGE,
|
|
|
|
|
decryptor_.GetUsageInfo(app_id_empty, kDefaultCdmIdentifier,
|
|
|
|
|
&usage_info));
|
|
|
|
|
EXPECT_TRUE(usage_info.size() > 0);
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
KEY_MESSAGE,
|
|
|
|
|
decryptor_.GetUsageInfo(app_id_not_empty, kDefaultCdmIdentifier,
|
|
|
|
|
&usage_info));
|
|
|
|
|
EXPECT_TRUE(usage_info.size() > 0);
|
|
|
|
|
|
|
|
|
|
// Read in usage info file
|
|
|
|
|
std::string path;
|
|
|
|
|
EXPECT_TRUE(Properties::GetDeviceFilesBasePath(security_level, &path));
|
|
|
|
|
std::string usage_info_not_empty_app_id_file_name =
|
|
|
|
|
path + DeviceFiles::GetUsageInfoFileName(app_id_not_empty);
|
|
|
|
|
|
|
|
|
|
ssize_t file_size =
|
|
|
|
|
file_system.FileSize(usage_info_not_empty_app_id_file_name);
|
|
|
|
|
EXPECT_LT(4, file_size);
|
|
|
|
|
File* file =
|
|
|
|
|
file_system.Open(usage_info_not_empty_app_id_file_name,
|
|
|
|
|
FileSystem::kReadOnly);
|
|
|
|
|
EXPECT_TRUE(NULL != file);
|
|
|
|
|
std::string file_data;
|
|
|
|
|
file_data.resize(file_size);
|
|
|
|
|
ssize_t bytes = file->Read(&file_data[0], file_data.size());
|
|
|
|
|
EXPECT_EQ(file_size, bytes);
|
|
|
|
|
file->Close();
|
|
|
|
|
|
|
|
|
|
// Corrupt the hash of the usage info file with non-empty app id and write
|
|
|
|
|
// it back out
|
|
|
|
|
memset(&file_data[0]+bytes-4, 0, 4);
|
|
|
|
|
file = file_system.Open(usage_info_not_empty_app_id_file_name,
|
|
|
|
|
FileSystem::kCreate | FileSystem::kTruncate);
|
|
|
|
|
EXPECT_TRUE(NULL != file);
|
|
|
|
|
bytes = file->Write(file_data.data(), file_data.size());
|
|
|
|
|
EXPECT_EQ(file_size, bytes);
|
|
|
|
|
file->Close();
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
NO_ERROR,
|
|
|
|
|
decryptor_.RemoveAllUsageInfo(app_id_not_empty, kDefaultCdmIdentifier));
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
NO_ERROR,
|
|
|
|
|
decryptor_.GetUsageInfo(app_id_not_empty, kDefaultCdmIdentifier,
|
|
|
|
|
&usage_info));
|
|
|
|
|
EXPECT_TRUE(usage_info.empty());
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
KEY_MESSAGE,
|
|
|
|
|
decryptor_.GetUsageInfo(app_id_empty, kDefaultCdmIdentifier,
|
|
|
|
|
&usage_info));
|
|
|
|
|
EXPECT_TRUE(usage_info.size() > 0);
|
|
|
|
|
|
|
|
|
|
// Read in usage info file
|
|
|
|
|
std::string usage_info_empty_app_id_file_name =
|
|
|
|
|
path + DeviceFiles::GetUsageInfoFileName(app_id_empty);
|
|
|
|
|
|
|
|
|
|
file_size = file_system.FileSize(usage_info_empty_app_id_file_name);
|
|
|
|
|
EXPECT_LT(4, file_size);
|
|
|
|
|
file = file_system.Open(usage_info_empty_app_id_file_name,
|
|
|
|
|
FileSystem::kReadOnly);
|
|
|
|
|
EXPECT_TRUE(NULL != file);
|
|
|
|
|
file_data.resize(file_size);
|
|
|
|
|
bytes = file->Read(&file_data[0], file_data.size());
|
|
|
|
|
EXPECT_EQ(file_size, bytes);
|
|
|
|
|
file->Close();
|
|
|
|
|
|
|
|
|
|
// Corrupt the hash of the usage info file with empty app id and write it
|
|
|
|
|
// back out
|
|
|
|
|
memset(&file_data[0]+bytes-4, 0, 4);
|
|
|
|
|
file = file_system.Open(usage_info_empty_app_id_file_name,
|
|
|
|
|
FileSystem::kCreate | FileSystem::kTruncate);
|
|
|
|
|
EXPECT_TRUE(NULL != file);
|
|
|
|
|
bytes = file->Write(file_data.data(), file_data.size());
|
|
|
|
|
EXPECT_EQ(file_size, bytes);
|
|
|
|
|
file->Close();
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
NO_ERROR,
|
|
|
|
|
decryptor_.RemoveAllUsageInfo(app_id_empty, kDefaultCdmIdentifier));
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
NO_ERROR,
|
|
|
|
|
decryptor_.GetUsageInfo(app_id_not_empty, kDefaultCdmIdentifier,
|
|
|
|
|
&usage_info));
|
|
|
|
|
EXPECT_TRUE(usage_info.empty());
|
|
|
|
|
EXPECT_EQ(
|
|
|
|
|
NO_ERROR,
|
|
|
|
|
decryptor_.GetUsageInfo(app_id_empty, kDefaultCdmIdentifier,
|
|
|
|
|
&usage_info));
|
|
|
|
|
EXPECT_TRUE(usage_info.empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvCdmRequestLicenseTest, GetSecureStopIdsTest) {
|
|
|
|
|
Unprovision();
|
|
|
|
|
|
|
|
|
|
@@ -3276,6 +3433,115 @@ TEST_F(WvCdmRequestLicenseTest, GetSecureStopIdsTest) {
|
|
|
|
|
EXPECT_TRUE(retrieved_secure_stop_ids.empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvCdmRequestLicenseTest, UsageRecoveryTest) {
|
|
|
|
|
Unprovision();
|
|
|
|
|
|
|
|
|
|
std::string app_id_empty = "";
|
|
|
|
|
|
|
|
|
|
TestWvCdmClientPropertySet property_set;
|
|
|
|
|
Provision(kLevelDefault);
|
|
|
|
|
|
|
|
|
|
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
|
|
|
|
FileSystem file_system;
|
|
|
|
|
DeviceFiles handle(&file_system);
|
|
|
|
|
EXPECT_TRUE(handle.Init(security_level));
|
|
|
|
|
std::vector<std::string> psts;
|
|
|
|
|
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(
|
|
|
|
|
DeviceFiles::GetUsageInfoFileName(""), &psts));
|
|
|
|
|
|
|
|
|
|
// Fetch a usage license
|
|
|
|
|
SubSampleInfo* data = kUsageLicenseTestVector1[0].sub_sample;
|
|
|
|
|
|
|
|
|
|
property_set.set_app_id(app_id_empty);
|
|
|
|
|
decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
|
|
|
|
|
NULL, &session_id_);
|
|
|
|
|
GenerateKeyRequest(kUsageLicenseTestVector1[0].pssh, kLicenseTypeStreaming,
|
|
|
|
|
&property_set);
|
|
|
|
|
|
|
|
|
|
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
|
|
|
|
|
CdmDecryptionParameters decryption_parameters(
|
|
|
|
|
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
|
|
|
|
|
&data->iv, data->block_offset, &decrypt_buffer[0]);
|
|
|
|
|
decryption_parameters.is_encrypted = data->is_encrypted;
|
|
|
|
|
decryption_parameters.is_secure = data->is_secure;
|
|
|
|
|
decryption_parameters.subsample_flags = data->subsample_flags;
|
|
|
|
|
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
|
|
|
|
|
decryption_parameters));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
|
|
|
|
|
decrypt_buffer.begin()));
|
|
|
|
|
decryptor_.CloseSession(session_id_);
|
|
|
|
|
|
|
|
|
|
std::string path;
|
|
|
|
|
EXPECT_TRUE(Properties::GetDeviceFilesBasePath(security_level, &path));
|
|
|
|
|
std::string usage_info_file_name =
|
|
|
|
|
path + DeviceFiles::GetUsageInfoFileName(app_id_empty);
|
|
|
|
|
|
|
|
|
|
// Read in usage info file
|
|
|
|
|
ssize_t file_size = file_system.FileSize(usage_info_file_name);
|
|
|
|
|
EXPECT_LT(4, file_size);
|
|
|
|
|
File* file =
|
|
|
|
|
file_system.Open(usage_info_file_name, FileSystem::kReadOnly);
|
|
|
|
|
EXPECT_TRUE(NULL != file);
|
|
|
|
|
std::string file_data;
|
|
|
|
|
file_data.resize(file_size);
|
|
|
|
|
ssize_t bytes = file->Read(&file_data[0], file_data.size());
|
|
|
|
|
EXPECT_EQ(file_size, bytes);
|
|
|
|
|
file->Close();
|
|
|
|
|
|
|
|
|
|
// Corrupt the hash of the usage info file and write it back out
|
|
|
|
|
memset(&file_data[0]+bytes-4, 0, 4);
|
|
|
|
|
file = file_system.Open(usage_info_file_name,
|
|
|
|
|
FileSystem::kCreate | FileSystem::kTruncate);
|
|
|
|
|
EXPECT_TRUE(NULL != file);
|
|
|
|
|
bytes = file->Write(file_data.data(), file_data.size());
|
|
|
|
|
EXPECT_EQ(file_size, bytes);
|
|
|
|
|
file->Close();
|
|
|
|
|
|
|
|
|
|
// Fetch a second usage license, this should fail as the usage table is
|
|
|
|
|
// corrupt
|
|
|
|
|
decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
|
|
|
|
|
NULL, &session_id_);
|
|
|
|
|
GenerateKeyRequest(kUsageLicenseTestVector1[1].pssh, kLicenseTypeStreaming,
|
|
|
|
|
&property_set);
|
|
|
|
|
|
|
|
|
|
std::string response;
|
|
|
|
|
VerifyKeyRequestResponse(wvcdm::STORE_USAGE_INFO_ERROR, g_license_server,
|
|
|
|
|
g_client_auth, true, &response);
|
|
|
|
|
|
|
|
|
|
decryptor_.CloseSession(session_id_);
|
|
|
|
|
|
|
|
|
|
// Fetch the second usage license and verify that it is usable
|
|
|
|
|
decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier,
|
|
|
|
|
NULL, &session_id_);
|
|
|
|
|
GenerateKeyRequest(kUsageLicenseTestVector1[1].pssh, kLicenseTypeStreaming,
|
|
|
|
|
&property_set);
|
|
|
|
|
|
|
|
|
|
VerifyUsageKeyRequestResponse(g_license_server, g_client_auth);
|
|
|
|
|
|
|
|
|
|
data = kUsageLicenseTestVector1[1].sub_sample;
|
|
|
|
|
|
|
|
|
|
decrypt_buffer.resize(data->encrypt_data.size());
|
|
|
|
|
decryption_parameters.key_id = &data->key_id;
|
|
|
|
|
decryption_parameters.encrypt_buffer = &data->encrypt_data.front();
|
|
|
|
|
decryption_parameters.encrypt_length = data->encrypt_data.size();
|
|
|
|
|
decryption_parameters.iv = &data->iv;
|
|
|
|
|
decryption_parameters.block_offset = data->block_offset;
|
|
|
|
|
decryption_parameters.decrypt_buffer = &decrypt_buffer[0];
|
|
|
|
|
decryption_parameters.decrypt_buffer_length = data->encrypt_data.size();
|
|
|
|
|
decryption_parameters.is_encrypted = data->is_encrypted;
|
|
|
|
|
decryption_parameters.is_secure = data->is_secure;
|
|
|
|
|
decryption_parameters.subsample_flags = data->subsample_flags;
|
|
|
|
|
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, data->validate_key_id,
|
|
|
|
|
decryption_parameters));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
|
|
|
|
|
decrypt_buffer.begin()));
|
|
|
|
|
decryptor_.CloseSession(session_id_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvCdmRequestLicenseTest, UsageRemoveSecureStopTest) {
|
|
|
|
|
Unprovision();
|
|
|
|
|
|
|
|
|
|
|