Recover when stored information is corrupted am: a20034e3a2

am: 0dc79e547f

Change-Id: I68795d284dfcde4ccd8484bdccf3ddf3a9ee0882
This commit is contained in:
Rahul Frias
2018-06-06 20:56:39 -07:00
committed by android-build-merger
2 changed files with 174 additions and 0 deletions

View File

@@ -1203,6 +1203,9 @@ bool DeviceFiles::RetrieveHashedFile(
if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) { if (bytes != static_cast<ssize_t>(serialized_hash_file.size())) {
LOGW("DeviceFiles::RetrieveHashedFile: read failed"); LOGW("DeviceFiles::RetrieveHashedFile: read failed");
// Remove the corrupted file so the caller will not get the same error
// when trying to access the file repeatedly, causing the system to stall.
file_system_->Remove(path);
return false; return false;
} }
@@ -1212,6 +1215,9 @@ bool DeviceFiles::RetrieveHashedFile(
HashedFile hash_file; HashedFile hash_file;
if (!hash_file.ParseFromString(serialized_hash_file)) { if (!hash_file.ParseFromString(serialized_hash_file)) {
LOGW("DeviceFiles::RetrieveHashedFile: Unable to parse hash file"); LOGW("DeviceFiles::RetrieveHashedFile: Unable to parse hash file");
// Remove the corrupted file so the caller will not get the same error
// when trying to access the file repeatedly, causing the system to stall.
file_system_->Remove(path);
return false; return false;
} }
@@ -1231,6 +1237,9 @@ bool DeviceFiles::RetrieveHashedFile(
if (!deserialized_file->ParseFromString(hash_file.file())) { if (!deserialized_file->ParseFromString(hash_file.file())) {
LOGW("DeviceFiles::RetrieveHashedFile: Unable to parse file"); LOGW("DeviceFiles::RetrieveHashedFile: Unable to parse file");
// Remove the corrupted file so the caller will not get the same error
// when trying to access the file repeatedly, causing the system to stall.
file_system_->Remove(path);
return false; return false;
} }
return true; return true;

View File

@@ -13,6 +13,7 @@
#include "cdm_identifier.h" #include "cdm_identifier.h"
#include "config_test_env.h" #include "config_test_env.h"
#include "device_files.h" #include "device_files.h"
#include "device_files.pb.h"
#include "file_store.h" #include "file_store.h"
#include "file_utils.h" #include "file_utils.h"
#include "license_protocol.pb.h" #include "license_protocol.pb.h"
@@ -3419,6 +3420,170 @@ TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest) {
EXPECT_TRUE(usage_info.empty()); EXPECT_TRUE(usage_info.empty());
} }
TEST_F(WvCdmRequestLicenseTest, RemoveCorruptedUsageInfoTest2) {
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();
video_widevine_client::sdk::HashedFile hash_file;
EXPECT_TRUE(hash_file.ParseFromString(file_data));
size_t pos = file_data.find(hash_file.hash());
EXPECT_NE(std::string::npos, pos);
EXPECT_NE(0u, pos);
// Corrupt the protobuf key field of the hash of the usage info file
// with non-empty app id and write it back out
file_data[pos-1] = 0xff;
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();
EXPECT_TRUE(hash_file.ParseFromString(file_data));
pos = file_data.find(hash_file.hash());
EXPECT_NE(std::string::npos, pos);
EXPECT_NE(0u, pos);
// Corrupt the protobuf key field of the hash of the usage info file
// with empty app id and write it back out
file_data[pos-1] = 0xff;
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) { TEST_F(WvCdmRequestLicenseTest, GetSecureStopIdsTest) {
Unprovision(); Unprovision();