Merge "Revert "Core CDM: Removed ability to add secure stop entry.""

This commit is contained in:
Alex Dale
2022-12-01 23:47:43 +00:00
committed by Android (Google) Code Review
4 changed files with 862 additions and 87 deletions

View File

@@ -484,8 +484,9 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
LOGE("CDM does not support secure stop licenses");
return ADD_KEY_ERROR;
}
sts = usage_table_header_->AddEntry(crypto_session_.get(), key_set_id_,
key_response, &usage_entry_number_);
sts = usage_table_header_->AddEntry(
crypto_session_.get(), /* is_persistent */ true, key_set_id_,
/* usage_info_filename */ "", key_response, &usage_entry_number_);
crypto_metrics_->usage_table_header_add_entry_.Increment(sts);
if (sts != NO_ERROR) return sts;
provider_session_token_ = std::move(provider_session_token);

View File

@@ -96,12 +96,17 @@ bool RetrieveOfflineLicense(DeviceFiles* device_files,
return true;
}
bool EntryIsUsageInfo(const CdmUsageEntryInfo& info) {
// Used for stl filters.
return info.storage_type == kStorageUsageInfo;
}
bool EntryIsOfflineLicense(const CdmUsageEntryInfo& info) {
// Used for stl filters.
return info.storage_type == kStorageLicense;
}
bool IsValidCdmSecurityLevelForUsageTable(CdmSecurityLevel security_level) {
bool IsValidCdmSecurityLevelForUsageInfo(CdmSecurityLevel security_level) {
return security_level == kSecurityLevelL1 ||
security_level == kSecurityLevelL3;
}
@@ -129,7 +134,7 @@ bool UsageTableHeader::Init(CdmSecurityLevel security_level,
CdmSecurityLevelToString(security_level));
return false;
}
if (!IsValidCdmSecurityLevelForUsageTable(security_level)) {
if (!IsValidCdmSecurityLevelForUsageInfo(security_level)) {
LOGE("Invalid security level provided: security_level = %s",
CdmSecurityLevelToString(security_level));
return false;
@@ -221,9 +226,11 @@ bool UsageTableHeader::CreateNewTable(CryptoSession* const crypto_session) {
}
CdmResponseType UsageTableHeader::AddEntry(
CryptoSession* crypto_session, const CdmKeySetId& key_set_id,
CryptoSession* crypto_session, bool persistent_license,
const CdmKeySetId& key_set_id, const std::string& usage_info_file_name,
const CdmKeyResponse& license_message, uint32_t* usage_entry_number) {
LOGD("key_set_id = %s, current_size = %zu", IdToString(key_set_id),
LOGD("key_set_id = %s, type = %s, current_size = %zu", IdToString(key_set_id),
persistent_license ? "OfflineLicense" : "Streaming",
usage_entry_info_.size());
metrics::CryptoMetrics* metrics = crypto_session->GetCryptoMetrics();
@@ -244,11 +251,15 @@ CdmResponseType UsageTableHeader::AddEntry(
status = RelocateNewEntry(crypto_session, usage_entry_number);
if (status != NO_ERROR) return status;
SetOfflineEntryInfo(*usage_entry_number, key_set_id, license_message);
if (persistent_license) {
SetOfflineEntryInfo(*usage_entry_number, key_set_id, license_message);
} else {
SetUsageInfoEntryInfo(*usage_entry_number, key_set_id,
usage_info_file_name);
}
status = RefitTable(crypto_session);
if (status != NO_ERROR) {
// Clear new entry on failure.
usage_entry_info_[*usage_entry_number].Clear();
return status;
}
@@ -369,6 +380,12 @@ CdmResponseType UsageTableHeader::InvalidateEntryInternal(
return NO_ERROR;
}
size_t UsageTableHeader::UsageInfoCount() const {
LOGV("Locking to count usage info (streaming license) entries");
return std::count_if(usage_entry_info_.cbegin(), usage_entry_info_.cend(),
EntryIsUsageInfo);
}
size_t UsageTableHeader::OfflineEntryCount() const {
LOGV("Locking to count offline license entries");
return std::count_if(usage_entry_info_.cbegin(), usage_entry_info_.cend(),
@@ -424,8 +441,8 @@ bool UsageTableHeader::CapacityCheck(CryptoSession* const crypto_session) {
}
uint32_t temporary_usage_entry_number;
status = AddEntry(local_crypto_session, kDummyKeySetId, kEmptyString,
&temporary_usage_entry_number);
status = AddEntry(local_crypto_session, true, kDummyKeySetId, kEmptyString,
kEmptyString, &temporary_usage_entry_number);
if (status != NO_ERROR) {
LOGE("Failed to add entry for capacity test: sts = %d",
static_cast<int>(status));
@@ -579,6 +596,17 @@ void UsageTableHeader::SetOfflineEntryInfo(
}
}
void UsageTableHeader::SetUsageInfoEntryInfo(
const uint32_t usage_entry_number, const std::string& key_set_id,
const std::string& usage_info_file_name) {
CdmUsageEntryInfo& entry_info = usage_entry_info_[usage_entry_number];
entry_info.Clear();
entry_info.storage_type = kStorageUsageInfo;
entry_info.key_set_id = key_set_id;
entry_info.last_use_time = GetCurrentTime();
entry_info.usage_info_file_name = usage_info_file_name;
}
CdmResponseType UsageTableHeader::RefitTable(
CryptoSession* const crypto_session) {
// Remove all unoccupied entries at end of the table.
@@ -679,39 +707,57 @@ CdmResponseType UsageTableHeader::GetEntry(uint32_t usage_entry_number,
usage_entry_number < usage_entry_info_.size()
? usage_entry_info_[usage_entry_number].storage_type
: kStorageTypeUnknown));
if (usage_entry_number >= usage_entry_info_.size()) {
LOGE("Entry out of bounds: usage_entry_number = %u, table_size = %zu",
usage_entry_number, usage_entry_info_.size());
return USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE;
uint32_t entry_number;
switch (usage_entry_info_[usage_entry_number].storage_type) {
case kStorageLicense: {
DeviceFiles::CdmLicenseData license_data;
DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError;
if (!device_files->RetrieveLicense(
usage_entry_info_[usage_entry_number].key_set_id, &license_data,
&sub_error_code)) {
LOGE("Failed to retrieve license: status = %d",
static_cast<int>(sub_error_code));
return USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED;
}
entry_number = license_data.usage_entry_number;
*usage_entry = std::move(license_data.usage_entry);
break;
}
case kStorageUsageInfo: {
std::string provider_session_token;
CdmKeyMessage license_request;
CdmKeyResponse license;
std::string drm_certificate;
CryptoWrappedKey wrapped_private_key;
if (!device_files->RetrieveUsageInfoByKeySetId(
usage_entry_info_[usage_entry_number].usage_info_file_name,
usage_entry_info_[usage_entry_number].key_set_id,
&provider_session_token, &license_request, &license, usage_entry,
&entry_number, &drm_certificate, &wrapped_private_key)) {
LOGE("Failed to retrieve usage information");
return USAGE_GET_ENTRY_RETRIEVE_USAGE_INFO_FAILED;
}
break;
}
case kStorageTypeUnknown:
default:
LOGE(
"Cannot retrieve usage information with unknown storage type: "
"storage_type = %d",
static_cast<int>(usage_entry_info_[usage_entry_number].storage_type));
return USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE;
}
CdmUsageEntryInfo& entry_info = usage_entry_info_[usage_entry_number];
if (entry_info.storage_type != kStorageLicense) {
LOGE(
"Cannot retrieve information not associated without a license: "
"usage_entry_number = %u",
usage_entry_number);
return USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE;
}
// Retrieve license.
DeviceFiles::CdmLicenseData license_data;
DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError;
if (!device_files->RetrieveLicense(
usage_entry_info_[usage_entry_number].key_set_id, &license_data,
&sub_error_code)) {
LOGE("Failed to retrieve license: status = %d",
static_cast<int>(sub_error_code));
return USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED;
}
// Validate entry number.
if (usage_entry_number != license_data.usage_entry_number) {
if (usage_entry_number != entry_number) {
LOGE(
"Usage entry number mismatch: expected_usage_entry_number = %u, "
"retrieved_usage_entry_number = %u",
usage_entry_number, license_data.usage_entry_number);
usage_entry_number, entry_number);
return USAGE_ENTRY_NUMBER_MISMATCH;
}
*usage_entry = std::move(license_data.usage_entry);
return NO_ERROR;
}
@@ -723,37 +769,66 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number,
usage_entry_number < usage_entry_info_.size()
? usage_entry_info_[usage_entry_number].storage_type
: kStorageTypeUnknown));
if (usage_entry_number >= usage_entry_info_.size()) {
LOGE("Entry out of bounds: usage_entry_number = %u, table_size = %zu",
usage_entry_number, usage_entry_info_.size());
return USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE;
}
CdmUsageEntryInfo& entry_info = usage_entry_info_[usage_entry_number];
if (entry_info.storage_type != kStorageLicense) {
LOGE(
"Cannot store information not associated without a license: "
"usage_entry_number = %u",
usage_entry_number);
return USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE;
}
// Retrieve existing.
DeviceFiles::CdmLicenseData license_data;
DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError;
if (!device_files->RetrieveLicense(
usage_entry_info_[usage_entry_number].key_set_id, &license_data,
&sub_error_code)) {
LOGE("Failed to retrieve license: status = %s",
DeviceFiles::ResponseTypeToString(sub_error_code));
return USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED;
}
// Update.
license_data.usage_entry = usage_entry;
license_data.usage_entry_number = usage_entry_number;
if (!device_files->StoreLicense(license_data, &sub_error_code)) {
LOGE("Failed to store license: status = %s",
DeviceFiles::ResponseTypeToString(sub_error_code));
return USAGE_STORE_LICENSE_FAILED;
switch (usage_entry_info_[usage_entry_number].storage_type) {
case kStorageLicense: {
DeviceFiles::CdmLicenseData license_data;
DeviceFiles::ResponseType sub_error_code = DeviceFiles::kNoError;
if (!device_files->RetrieveLicense(
usage_entry_info_[usage_entry_number].key_set_id, &license_data,
&sub_error_code)) {
LOGE("Failed to retrieve license: status = %s",
DeviceFiles::ResponseTypeToString(sub_error_code));
return USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED;
}
// Update.
license_data.usage_entry = usage_entry;
license_data.usage_entry_number = usage_entry_number;
if (!device_files->StoreLicense(license_data, &sub_error_code)) {
LOGE("Failed to store license: status = %s",
DeviceFiles::ResponseTypeToString(sub_error_code));
return USAGE_STORE_LICENSE_FAILED;
}
break;
}
case kStorageUsageInfo: {
CdmUsageEntry entry;
uint32_t entry_number;
std::string provider_session_token, init_data, key_request, key_response,
key_renewal_request;
std::string drm_certificate;
CryptoWrappedKey wrapped_private_key;
if (!device_files->RetrieveUsageInfoByKeySetId(
usage_entry_info_[usage_entry_number].usage_info_file_name,
usage_entry_info_[usage_entry_number].key_set_id,
&provider_session_token, &key_request, &key_response, &entry,
&entry_number, &drm_certificate, &wrapped_private_key)) {
LOGE("Failed to retrieve usage information");
return USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED;
}
device_files->DeleteUsageInfo(
usage_entry_info_[usage_entry_number].usage_info_file_name,
provider_session_token);
if (!device_files->StoreUsageInfo(
provider_session_token, key_request, key_response,
usage_entry_info_[usage_entry_number].usage_info_file_name,
usage_entry_info_[usage_entry_number].key_set_id, usage_entry,
usage_entry_number, drm_certificate, wrapped_private_key)) {
LOGE("Failed to store usage information");
return USAGE_STORE_USAGE_INFO_FAILED;
}
break;
}
case kStorageTypeUnknown:
default:
LOGE(
"Cannot retrieve usage information with unknown storage type: "
"storage_type = %d",
static_cast<int>(usage_entry_info_[usage_entry_number].storage_type));
return USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE;
}
return NO_ERROR;
}