Allow selective removal of Usage Table Entries by PST

This is a merge of http://go/wvgerrit/13693 in the Widevine
repository.

This adds level 3 and mock implementation and unit tests for the
OEMCrypto function OEMCrypto_ForceDeleteUsageEntry.  It also plumbs
this function up into CdmEngine, CdmSession, and CryptoSession so that
deleting all usage information for a given app id will now delete the
entries in OEMCrypto, too.

b/18194071

Change-Id: Iaea4034a507b323878657215784edfe95876386a
This commit is contained in:
Fred Gylys-Colwell
2015-03-18 18:09:37 -07:00
parent a7887f60fc
commit d2ba3a3f91
14 changed files with 226 additions and 28 deletions

View File

@@ -732,13 +732,20 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
CdmResponseType status = NO_ERROR;
DeviceFiles handle[kSecurityLevelUnknown - kSecurityLevelL1];
for (int i = 0, j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++i, ++j) {
if (handle[i].Init(static_cast<CdmSecurityLevel>(j))) {
if (!handle[i].DeleteAllUsageInfoForApp(app_id)) {
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
DeviceFiles handle;
if (handle.Init(static_cast<CdmSecurityLevel>(j))) {
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(app_id, &provider_session_tokens)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure"
"stops", j);
status = UNKNOWN_ERROR;
} else {
CdmResponseType status2 = usage_session_->
DeleteMultipleUsageInformation(provider_session_tokens);
if (status2 != NO_ERROR) {
status = status2;
}
}
} else {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to initialize L%d device"

View File

@@ -526,11 +526,16 @@ bool CdmSession::DeleteLicense() {
if (!is_offline_ && license_parser_->provider_session_token().empty())
return false;
if (!license_parser_->provider_session_token().empty()) {
if(crypto_session_->DeleteUsageInformation(
license_parser_->provider_session_token()) != NO_ERROR) {
LOGE("CdmSession::DeleteLicense: error deleting usage info");
}
}
if (!file_handle_->Reset(security_level_)) {
LOGE("CdmSession::DeleteLicense: Unable to initialize device files");
return false;
}
if (is_offline_) {
return file_handle_->DeleteLicense(key_set_id_);
} else {
@@ -590,18 +595,10 @@ void CdmSession::GetApplicationId(std::string* app_id) {
}
}
CdmResponseType CdmSession::DeleteUsageInformation(const std::string& app_id) {
if (!file_handle_->Reset(security_level_)) {
LOGE("CdmSession::StoreLicense: Unable to initialize device files");
return UNKNOWN_ERROR;
}
if (file_handle_->DeleteAllUsageInfoForApp(app_id)) {
return NO_ERROR;
} else {
LOGE("CdmSession::DeleteUsageInformation: failed");
return UNKNOWN_ERROR;
}
CdmResponseType CdmSession::DeleteMultipleUsageInformation(
const std::vector<std::string>& provider_session_tokens) {
return crypto_session_
->DeleteMultipleUsageInformation(provider_session_tokens);
}
CdmResponseType CdmSession::UpdateUsageInformation() {

View File

@@ -846,6 +846,50 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
return NO_ERROR;
}
CdmResponseType CryptoSession::DeleteUsageInformation(
const std::string& provider_session_token) {
CdmResponseType response = NO_ERROR;
LOGV("CryptoSession::DeleteUsageInformation");
OEMCryptoResult status = OEMCrypto_ForceDeleteUsageEntry(
reinterpret_cast<const uint8_t*>(provider_session_token.c_str()),
provider_session_token.length());
if (OEMCrypto_SUCCESS != status) {
LOGE("CryptoSession::DeleteUsageInformation: Delete Usage Table error =%ld",
status);
response = UNKNOWN_ERROR;
}
status = OEMCrypto_UpdateUsageTable();
if (status != OEMCrypto_SUCCESS) {
LOGE("CryptoSession::DeleteUsageInformation: update table error=%ld",
status);
response = UNKNOWN_ERROR;
}
return response;
}
CdmResponseType CryptoSession::DeleteMultipleUsageInformation(
const std::vector<std::string>& provider_session_tokens) {
LOGV("CryptoSession::DeleteMultipleUsageInformation");
CdmResponseType response = NO_ERROR;
for (size_t i=0; i < provider_session_tokens.size(); ++i) {
OEMCryptoResult status = OEMCrypto_ForceDeleteUsageEntry(
reinterpret_cast<const uint8_t*>(provider_session_tokens[i].c_str()),
provider_session_tokens[i].length());
if (OEMCrypto_SUCCESS != status) {
LOGW("CryptoSession::DeleteMultipleUsageInformation: "
"Delete Usage Table error =%ld", status);
response = UNKNOWN_ERROR;
}
}
OEMCryptoResult status = OEMCrypto_UpdateUsageTable();
if (status != OEMCrypto_SUCCESS) {
LOGE("CryptoSession::DeleteMultipleUsageInformation: update table error=%ld",
status);
response = UNKNOWN_ERROR;
}
return response;
}
CdmResponseType CryptoSession::DeleteAllUsageReports() {
LOGV("DeleteAllUsageReports");
OEMCryptoResult status = OEMCrypto_DeleteUsageTable();
@@ -859,8 +903,8 @@ CdmResponseType CryptoSession::DeleteAllUsageReports() {
if (status != OEMCrypto_SUCCESS) {
LOGE("CryptoSession::DeletaAllUsageReports: update table error=%ld",
status);
return UNKNOWN_ERROR;
}
return NO_ERROR;
}

View File

@@ -378,7 +378,6 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
return false;
}
std::string serialized_file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveHashedFile(file_name.c_str(), &serialized_file)) return false;
@@ -418,12 +417,18 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
return StoreFileWithHash(file_name.c_str(), serialized_file);
}
bool DeviceFiles::DeleteAllUsageInfoForApp(const std::string& app_id) {
bool DeviceFiles::DeleteAllUsageInfoForApp(
const std::string& app_id,
std::vector<std::string>* provider_session_tokens) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: not initialized");
return false;
}
if (NULL == provider_session_tokens) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: pst destination not provided");
return false;
}
provider_session_tokens->clear();
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level_, &path)) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to get base path");
@@ -431,7 +436,21 @@ bool DeviceFiles::DeleteAllUsageInfoForApp(const std::string& app_id) {
}
std::string file_name = GetUsageInfoFileName(app_id);
path.append(file_name);
if (!file_->Exists(path)) return true;
std::string serialized_file;
if (RetrieveHashedFile(file_name.c_str(), &serialized_file)) {
video_widevine_client::sdk::File file_proto;
if (!file_proto.ParseFromString(serialized_file)) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to parse file");
} else {
for (int i = 0; i < file_proto.usage_info().sessions_size(); ++i) {
provider_session_tokens->push_back(
file_proto.usage_info().sessions(i).token());
}
}
} else {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to retrieve file");
}
return file_->Remove(path);
}

View File

@@ -325,6 +325,7 @@ class Adapter {
LOOKUP(IsAntiRollbackHwPresent, OEMCrypto_IsAntiRollbackHwPresent);
LOOKUP(GetNumberOfOpenSessions, OEMCrypto_GetNumberOfOpenSessions);
LOOKUP(GetMaxNumberOfSessions, OEMCrypto_GetMaxNumberOfSessions);
LOOKUP(ForceDeleteUsageEntry, OEMCrypto_ForceDeleteUsageEntry);
}
}
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
@@ -924,6 +925,24 @@ extern "C" OEMCryptoResult OEMCrypto_DeleteUsageEntry(
}
}
extern "C" OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(
const uint8_t* pst, size_t pst_length) {
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
const FunctionPointers* fcn1 = kAdapter->get(kLevelDefault);
const FunctionPointers* fcn3 = kAdapter->get(kLevel3);
OEMCryptoResult sts = OEMCrypto_ERROR_NOT_IMPLEMENTED;
if (fcn3 && fcn3->version > 9) {
sts = fcn3->ForceDeleteUsageEntry(pst, pst_length);
}
if (fcn1 && fcn1 != fcn3 && fcn1->version > 9) {
OEMCryptoResult sts1 = fcn1->ForceDeleteUsageEntry(pst, pst_length);
if ((sts1 != OEMCrypto_SUCCESS) && (sts == OEMCrypto_SUCCESS)) {
sts = sts1;
}
}
return sts;
}
extern "C" OEMCryptoResult OEMCrypto_DeleteUsageTable() {
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
const FunctionPointers* fcn1 = kAdapter->get(kLevelDefault);