OEMCrypto v16.1

Merge of http://go/wvgerrit/93404

This CL updates the Widevine CDM to support OEMCrypto v16.1

Test: Tested in 16.2 CL
Bug: 141247171
Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
Fred Gylys-Colwell
2020-01-18 10:11:24 -08:00
parent 7e2619e379
commit 7665614b2e
132 changed files with 12331 additions and 9341 deletions

View File

@@ -27,7 +27,6 @@
namespace {
const uint64_t kReleaseSessionTimeToLive = 60; // seconds
const uint32_t kUpdateUsageInformationPeriod = 60; // seconds
const size_t kUsageReportsPerRequest = 1;
wvcdm::CdmOfflineLicenseState MapDeviceFilesLicenseState(
wvcdm::DeviceFiles::LicenseState state) {
@@ -571,7 +570,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
return NO_ERROR;
} else if (query_token == QUERY_KEY_USAGE_SUPPORT) {
bool supports_usage_reporting;
bool got_info = crypto_session->UsageInformationSupport(
const bool got_info = crypto_session->UsageInformationSupport(
security_level, &supports_usage_reporting);
if (!got_info) {
@@ -698,6 +697,24 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
break;
}
return NO_ERROR;
} else if (query_token == QUERY_KEY_MAX_USAGE_TABLE_ENTRIES) {
size_t max_number_of_usage_entries;
if (!crypto_session->GetMaximumUsageTableEntries(
security_level, &max_number_of_usage_entries)) {
LOGW("GetMaxUsageTableEntries failed");
return UNKNOWN_ERROR;
}
*query_response = std::to_string(max_number_of_usage_entries);
} else if (query_token == QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION) {
uint32_t api_minor_version;
if (!crypto_session->GetApiMinorVersion(security_level,
&api_minor_version)) {
LOGW("GetApiMinorVersion failed");
return UNKNOWN_ERROR;
}
*query_response = std::to_string(api_minor_version);
return NO_ERROR;
}
M_TIME(status = crypto_session->Open(security_level),
@@ -804,9 +821,6 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
CdmKeyAllowedUsage* key_usage) {
LOGI("Querying allowed key useage (all sessions): key_id = %s",
key_id.c_str());
CdmResponseType sts;
CdmKeyAllowedUsage found_in_this_session;
bool found = false;
if (!key_usage) {
LOGE("No response destination");
return PARAMETER_NULL;
@@ -816,9 +830,12 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
CdmSessionList sessions;
session_map_.GetSessionList(sessions);
bool found = false;
for (CdmSessionList::iterator iter = sessions.begin(); iter != sessions.end();
++iter) {
sts = (*iter)->QueryKeyAllowedUsage(key_id, &found_in_this_session);
CdmKeyAllowedUsage found_in_this_session;
CdmResponseType sts =
(*iter)->QueryKeyAllowedUsage(key_id, &found_in_this_session);
if (sts == NO_ERROR) {
if (found) {
// Found another key. If usage settings do not match, fail.
@@ -890,8 +907,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
return INVALID_PROVISIONING_REQUEST_PARAM_2;
}
DeleteAllUsageReportsUponFactoryReset();
// TODO(b/141705730): Remove usage entries on provisioning.
if (!cert_provisioning_) {
cert_provisioning_.reset(
new CertificateProvisioning(metrics_->GetCryptoMetrics()));
@@ -1004,6 +1020,8 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
return UNPROVISION_ERROR_1;
}
// TODO(b/141705730): Remove usage entries during unprovisioning.
if (!file_system_->IsGlobal()) {
if (!handle.RemoveCertificate()) {
LOGE("Unable to delete certificate");
@@ -1015,34 +1033,10 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
LOGE("Unable to delete files");
return UNPROVISION_ERROR_3;
}
return DeleteUsageTable(security_level);
return NO_ERROR;
}
}
CdmResponseType CdmEngine::DeleteUsageTable(CdmSecurityLevel security_level) {
LOGI("Deleting usage table: security_level = %d",
static_cast<int>(security_level));
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status;
M_TIME(status = crypto_session->Open(
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault),
metrics_->GetCryptoMetrics(), crypto_session_open_, status,
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
if (NO_ERROR != status) {
LOGE("Error opening crypto session: status = %d", static_cast<int>(status));
return UNPROVISION_ERROR_4;
}
status = crypto_session->DeleteAllUsageReports();
metrics_->GetCryptoMetrics()
->crypto_session_delete_all_usage_reports_.Increment(status);
if (status != NO_ERROR) {
LOGE("Error deleteing usage reports: status = %d",
static_cast<int>(status));
}
return status;
}
CdmResponseType CdmEngine::ListStoredLicenses(
CdmSecurityLevel security_level, std::vector<std::string>* key_set_ids) {
DeviceFiles handle(file_system_);
@@ -1195,9 +1189,6 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
return GET_USAGE_INFO_ERROR_1;
}
CdmKeyMessage license_request;
CdmKeyResponse license_response;
std::string usage_entry;
DeviceFiles::CdmUsageData usage_data;
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), ssid,
&usage_data)) {
@@ -1206,7 +1197,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
status = usage_session_->Init(usage_property_set_.get());
if (NO_ERROR != status) {
LOGE("Session init error");
LOGE("Session init error: status = %d", static_cast<int>(status));
return status;
}
if (!handle.Reset(usage_session_->GetSecurityLevel())) {
@@ -1280,6 +1271,11 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
CdmUsageInfo* usage_info) {
LOGI("Getting usage info: app_id = %s, security_level = %d", app_id.c_str(),
static_cast<int>(requested_security_level));
if (!usage_info) {
LOGE("No usage info destination");
return PARAMETER_NULL;
}
if (!usage_property_set_) {
usage_property_set_.reset(new UsagePropertySet());
}
@@ -1307,20 +1303,15 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
return GET_USAGE_INFO_ERROR_4;
}
if (!usage_info) {
LOGE("No usage info destination");
return PARAMETER_NULL;
}
if (0 == usage_data.size()) {
usage_info->resize(0);
if (usage_data.empty()) {
usage_info->clear();
return NO_ERROR;
}
usage_info->resize(kUsageReportsPerRequest);
size_t index = CdmRandom::RandomInRange(usage_data.size() - 1);
const size_t index = CdmRandom::RandomInRange(usage_data.size() - 1);
status = usage_session_->RestoreUsageSession(usage_data[index], error_detail);
if (KEY_ADDED != status) {
// TODO(b/141704872): Make multiple attempts.
LOGE("RestoreUsageSession failed: index = %zu, status = %d", index,
static_cast<int>(status));
usage_info->clear();
@@ -1367,64 +1358,42 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(
usage_session_.reset(new CdmSession(file_system_, metrics_->AddSession()));
usage_session_->Init(usage_property_set_.get());
switch (usage_session_->get_usage_support_type()) {
case kUsageEntrySupport: {
std::vector<DeviceFiles::CdmUsageData> usage_data;
// Retrieve all usage information but delete only one before
// refetching. This is because deleting the usage entry
// might cause other entries to be shifted and information updated.
do {
if (!handle.RetrieveUsageInfo(
DeviceFiles::GetUsageInfoFileName(app_id), &usage_data)) {
LOGW("Failed to retrieve usage info");
break;
}
if (usage_data.empty()) break;
CdmResponseType res = usage_session_->DeleteUsageEntry(
usage_data[0].usage_entry_number);
if (res != NO_ERROR) {
LOGW("Failed to delete usage entry: status = %d",
static_cast<int>(res));
break;
}
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
usage_data[0].provider_session_token)) {
LOGW("Failed to delete usage info");
break;
}
} while (!usage_data.empty());
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
status = REMOVE_ALL_USAGE_INFO_ERROR_5;
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
std::vector<DeviceFiles::CdmUsageData> usage_data;
// Retrieve all usage information but delete only one before
// refetching. This is because deleting the usage entry
// might cause other entries to be shifted and information updated.
do {
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
&usage_data)) {
LOGW("Failed to retrieve usage info");
break;
}
break;
}
case kUsageTableSupport: {
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
LOGE("Failed to delete secure stops: cdm_security_level = %d",
static_cast<int>(cdm_security_level));
status = REMOVE_ALL_USAGE_INFO_ERROR_1;
} else {
CdmResponseType status2 =
usage_session_->DeleteMultipleUsageInformation(
provider_session_tokens);
if (status2 != NO_ERROR) status = status2;
if (usage_data.empty()) break;
CdmResponseType res =
usage_session_->DeleteUsageEntry(usage_data[0].usage_entry_number);
if (res != NO_ERROR) {
LOGW("Failed to delete usage entry: status = %d",
static_cast<int>(res));
break;
}
break;
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
usage_data[0].provider_session_token)) {
LOGW("Failed to delete usage info");
break;
}
} while (!usage_data.empty());
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
status = REMOVE_ALL_USAGE_INFO_ERROR_5;
}
default:
// Ignore
break;
}
}
usage_session_.reset();
@@ -1479,38 +1448,14 @@ CdmResponseType CdmEngine::RemoveUsageInfo(
continue;
}
switch (usage_session_->get_usage_support_type()) {
case kUsageEntrySupport: {
status = usage_session_->DeleteUsageEntry(usage_entry_number);
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token)) {
status = REMOVE_USAGE_INFO_ERROR_1;
}
usage_session_.reset();
return status;
if (usage_session_->get_usage_support_type() == kUsageEntrySupport) {
status = usage_session_->DeleteUsageEntry(usage_entry_number);
if (!handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token)) {
status = REMOVE_USAGE_INFO_ERROR_1;
}
case kUsageTableSupport: {
std::vector<std::string> provider_session_tokens;
handle.DeleteUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
provider_session_token);
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
status = crypto_session->Open(static_cast<CdmSecurityLevel>(j) ==
kSecurityLevelL3
? kLevel3
: kLevelDefault);
if (status == NO_ERROR) {
crypto_session->UpdateUsageInformation();
status =
crypto_session->DeleteUsageInformation(provider_session_token);
crypto_session->UpdateUsageInformation();
}
return status;
}
default:
// Ignore
break;
usage_session_.reset();
return status;
}
} else {
LOGE("Failed to initialize L%d device files", j);
@@ -1530,6 +1475,7 @@ CdmResponseType CdmEngine::ReleaseUsageInfo(
}
CdmResponseType status = usage_session_->ReleaseKey(message);
// Q: Should this only be reset if release key was successful?
usage_session_.reset();
if (NO_ERROR != status) {
LOGE("ReleaseKey failed: status = %d", status);
@@ -1908,36 +1854,15 @@ void CdmEngine::OnTimerEvent() {
if (is_usage_update_needed &&
(usage_update_period_expired || is_initial_usage_update)) {
bool has_usage_been_updated = false;
// Session list may have changed. Rebuild.
session_map_.GetSessionList(sessions);
for (CdmSessionList::iterator iter = sessions.begin();
iter != sessions.end(); ++iter) {
(*iter)->reset_usage_flags();
switch ((*iter)->get_usage_support_type()) {
case kUsageEntrySupport:
if ((*iter)->has_provider_session_token()) {
(*iter)->UpdateUsageEntryInformation();
}
break;
case kUsageTableSupport:
if (!has_usage_been_updated) {
// usage is updated for all sessions so this needs to be
// called only once per update usage information period
CdmResponseType status = (*iter)->UpdateUsageTableInformation();
if (NO_ERROR != status) {
LOGW("UpdateUsageTableInformation failed: status = %d",
static_cast<int>(status));
} else {
has_usage_been_updated = true;
}
}
break;
default:
// Ignore
break;
if ((*iter)->get_usage_support_type() == kUsageEntrySupport &&
(*iter)->has_provider_session_token()) {
(*iter)->UpdateUsageEntryInformation();
}
}
}
@@ -2004,38 +1929,4 @@ void CdmEngine::CloseExpiredReleaseSessions() {
}
}
void CdmEngine::DeleteAllUsageReportsUponFactoryReset() {
std::string device_base_path_level1 = "";
std::string device_base_path_level3 = "";
Properties::GetDeviceFilesBasePath(kSecurityLevelL1,
&device_base_path_level1);
Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
&device_base_path_level3);
if (!file_system_->Exists(device_base_path_level1) &&
!file_system_->Exists(device_base_path_level3)) {
std::unique_ptr<CryptoSession> crypto_session(
CryptoSession::MakeCryptoSession(metrics_->GetCryptoMetrics()));
CdmResponseType status;
M_TIME(status = crypto_session->Open(
cert_provisioning_requested_security_level_),
metrics_->GetCryptoMetrics(), crypto_session_open_, status,
cert_provisioning_requested_security_level_);
if (NO_ERROR == status) {
status = crypto_session->DeleteAllUsageReports();
metrics_->GetCryptoMetrics()
->crypto_session_delete_all_usage_reports_.Increment(status);
if (NO_ERROR != status) {
LOGW("Failed to delete usage reports: status = %d",
static_cast<int>(status));
}
} else {
LOGW(
"Failed to open crypto session: status = %d\n"
"Usage reports are not removed after factory reset",
static_cast<int>(status));
}
}
}
} // namespace wvcdm