Infrastructure changes to support big usage tables
[ Merge of http://go/wvgerrit/23161 ] The usage table redesign will require storing usage table headers and usage entries in non-secure persistent store. This information will be signed by the TEE to prevent against modification. New Storage and retrieval methods have been added for usage table headers, while usage entries will be stored alongside (offline) licenses and (secure stops/)usage info. b/34327459 Test: All unittests, including newly introduced ones other than some oemcrypto, request_license_test passed. Those tests failed with or without this CL. Change-Id: I9b8d6210e33774b0803f8af1711b2d593d467aec
This commit is contained in:
@@ -854,8 +854,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
std::string usage_entry;
|
||||
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
|
||||
&license_response)) {
|
||||
&license_response, &usage_entry)) {
|
||||
usage_property_set_->set_security_level(kLevel3);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
usage_session_.reset(new CdmSession(file_system_));
|
||||
@@ -869,7 +870,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
return GET_USAGE_INFO_ERROR_2;
|
||||
}
|
||||
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
|
||||
&license_response)) {
|
||||
&license_response, &usage_entry)) {
|
||||
// No entry found for that ssid.
|
||||
return USAGE_INFO_NOT_FOUND;
|
||||
}
|
||||
@@ -1084,8 +1085,9 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
|
||||
CdmKeyMessage key_message;
|
||||
CdmKeyResponse key_response;
|
||||
std::string usage_entry;
|
||||
if (!handle.RetrieveUsageInfoByKeySetId(app_id, key_set_id, &key_message,
|
||||
&key_response)) {
|
||||
&key_response, &usage_entry)) {
|
||||
LOGE("CdmEngine::LoadUsageSession: unable to find usage information");
|
||||
return LOAD_USAGE_INFO_MISSING;
|
||||
}
|
||||
|
||||
@@ -146,13 +146,14 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
int64_t playback_start_time;
|
||||
int64_t last_playback_time;
|
||||
int64_t grace_period_end_time;
|
||||
std::string usage_entry;
|
||||
|
||||
if (!file_handle_->RetrieveLicense(
|
||||
key_set_id, &license_state, &offline_init_data_, &key_request_,
|
||||
&key_response_, &offline_key_renewal_request_,
|
||||
&offline_key_renewal_response_, &offline_release_server_url_,
|
||||
&playback_start_time, &last_playback_time, &grace_period_end_time,
|
||||
&app_parameters_)) {
|
||||
&app_parameters_, &usage_entry)) {
|
||||
LOGE("CdmSession::Init failed to retrieve license. key set id = %s",
|
||||
key_set_id.c_str());
|
||||
return GET_LICENSE_ERROR;
|
||||
@@ -573,8 +574,10 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
std::string usage_entry;
|
||||
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
|
||||
key_response_, app_id, key_set_id_)) {
|
||||
key_response_, app_id, key_set_id_,
|
||||
usage_entry)) {
|
||||
LOGE("CdmSession::StoreLicense: Unable to store usage info");
|
||||
return STORE_USAGE_INFO_ERROR;
|
||||
}
|
||||
@@ -582,12 +585,13 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
}
|
||||
|
||||
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
|
||||
std::string usage_entry;
|
||||
return file_handle_->StoreLicense(
|
||||
key_set_id_, state, offline_init_data_, key_request_, key_response_,
|
||||
offline_key_renewal_request_, offline_key_renewal_response_,
|
||||
offline_release_server_url_, policy_engine_->GetPlaybackStartTime(),
|
||||
policy_engine_->GetLastPlaybackTime(),
|
||||
policy_engine_->GetGracePeriodEndTime(), app_parameters_);
|
||||
policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::ReleaseCrypto() {
|
||||
|
||||
@@ -34,6 +34,12 @@ using video_widevine_client::sdk::License_LicenseState_RELEASING;
|
||||
using video_widevine_client::sdk::NameValue;
|
||||
using video_widevine_client::sdk::UsageInfo;
|
||||
using video_widevine_client::sdk::UsageInfo_ProviderSession;
|
||||
using video_widevine_client::sdk::UsageTableInfo;
|
||||
using video_widevine_client::sdk::UsageTableInfo_UsageEntryInfo;
|
||||
using video_widevine_client::sdk::
|
||||
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE;
|
||||
using video_widevine_client::sdk::
|
||||
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -43,6 +49,7 @@ const char kUsageInfoFileNamePrefix[] = "usage";
|
||||
const char kUsageInfoFileNameExt[] = ".bin";
|
||||
const char kLicenseFileNameExt[] = ".lic";
|
||||
const char kEmptyFileName[] = "";
|
||||
const char kUsageTableFileName[] = "usagetable.bin";
|
||||
const char kWildcard[] = "*";
|
||||
|
||||
bool Hash(const std::string& data, std::string* hash) {
|
||||
@@ -169,7 +176,8 @@ bool DeviceFiles::StoreLicense(
|
||||
const CdmKeyResponse& license_renewal,
|
||||
const std::string& release_server_url, int64_t playback_start_time,
|
||||
int64_t last_playback_time, int64_t grace_period_end_time,
|
||||
const CdmAppParameterMap& app_parameters) {
|
||||
const CdmAppParameterMap& app_parameters,
|
||||
const std::string& usage_entry) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreLicense: not initialized");
|
||||
return false;
|
||||
@@ -210,6 +218,7 @@ bool DeviceFiles::StoreLicense(
|
||||
app_params->set_name(iter->first);
|
||||
app_params->set_value(iter->second);
|
||||
}
|
||||
license->set_usage_entry(usage_entry);
|
||||
|
||||
std::string serialized_file;
|
||||
file.SerializeToString(&serialized_file);
|
||||
@@ -224,7 +233,7 @@ bool DeviceFiles::RetrieveLicense(
|
||||
CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal,
|
||||
std::string* release_server_url, int64_t* playback_start_time,
|
||||
int64_t* last_playback_time, int64_t* grace_period_end_time,
|
||||
CdmAppParameterMap* app_parameters) {
|
||||
CdmAppParameterMap* app_parameters, std::string* usage_entry) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveLicense: not initialized");
|
||||
return false;
|
||||
@@ -278,6 +287,7 @@ bool DeviceFiles::RetrieveLicense(
|
||||
(*app_parameters)[license.app_parameters(i).name()] =
|
||||
license.app_parameters(i).value();
|
||||
}
|
||||
*usage_entry = license.usage_entry();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -340,7 +350,8 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
const CdmKeyMessage& key_request,
|
||||
const CdmKeyResponse& key_response,
|
||||
const std::string& app_id,
|
||||
const std::string& key_set_id) {
|
||||
const std::string& key_set_id,
|
||||
const std::string& usage_entry) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
|
||||
return false;
|
||||
@@ -366,6 +377,7 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
|
||||
provider_session->set_license_request(key_request.data(), key_request.size());
|
||||
provider_session->set_license(key_response.data(), key_response.size());
|
||||
provider_session->set_key_set_id(key_set_id.data(), key_set_id.size());
|
||||
provider_session->set_usage_entry(usage_entry);
|
||||
|
||||
std::string serialized_file;
|
||||
file.SerializeToString(&serialized_file);
|
||||
@@ -479,7 +491,8 @@ bool DeviceFiles::RetrieveUsageInfo(
|
||||
bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
|
||||
const std::string& provider_session_token,
|
||||
CdmKeyMessage* license_request,
|
||||
CdmKeyResponse* license_response) {
|
||||
CdmKeyResponse* license_response,
|
||||
std::string* usage_entry) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
|
||||
return false;
|
||||
@@ -496,6 +509,7 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
|
||||
if (file.usage_info().sessions(index).token() == provider_session_token) {
|
||||
*license_request = file.usage_info().sessions(index).license_request();
|
||||
*license_response = file.usage_info().sessions(index).license();
|
||||
*usage_entry = file.usage_info().sessions(index).usage_entry();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -507,7 +521,8 @@ bool DeviceFiles::RetrieveUsageInfoByKeySetId(
|
||||
const std::string& app_id,
|
||||
const std::string& key_set_id,
|
||||
CdmKeyMessage* license_request,
|
||||
CdmKeyResponse* license_response) {
|
||||
CdmKeyResponse* license_response,
|
||||
std::string* usage_entry) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageInfoByKeySetId: not initialized");
|
||||
return false;
|
||||
@@ -524,6 +539,7 @@ bool DeviceFiles::RetrieveUsageInfoByKeySetId(
|
||||
if (file.usage_info().sessions(index).key_set_id() == key_set_id) {
|
||||
*license_request = file.usage_info().sessions(index).license_request();
|
||||
*license_response = file.usage_info().sessions(index).license();
|
||||
*usage_entry = file.usage_info().sessions(index).usage_entry();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -628,6 +644,118 @@ bool DeviceFiles::DeleteHlsAttributes(const std::string& key_set_id) {
|
||||
return RemoveFile(key_set_id + kHlsAttributesFileNameExt);
|
||||
}
|
||||
|
||||
bool DeviceFiles::StoreUsageTableInfo(
|
||||
const std::string& usage_table_header,
|
||||
const std::vector<DeviceFiles::UsageEntryInfo>& usage_entry_info) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreUsageTableHeader: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill in file information
|
||||
video_widevine_client::sdk::File file;
|
||||
|
||||
file.set_type(video_widevine_client::sdk::File::USAGE_TABLE_INFO);
|
||||
file.set_version(video_widevine_client::sdk::File::VERSION_1);
|
||||
|
||||
UsageTableInfo* usage_table_info = file.mutable_usage_table_info();
|
||||
usage_table_info->set_usage_table_header(usage_table_header);
|
||||
for (size_t i = 0; i < usage_entry_info.size(); ++i) {
|
||||
UsageTableInfo_UsageEntryInfo* info =
|
||||
usage_table_info->add_usage_entry_info();
|
||||
switch (usage_entry_info[i].storage_type) {
|
||||
case kStorageLicense:
|
||||
info->set_storage(
|
||||
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE);
|
||||
info->set_key_set_id(usage_entry_info[i].key_set_id);
|
||||
break;
|
||||
case kStorageUsageInfo:
|
||||
info->set_storage(
|
||||
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO);
|
||||
info->set_provider_session_token(
|
||||
usage_entry_info[i].provider_session_token);
|
||||
info->set_app_id(usage_entry_info[i].app_id);
|
||||
break;
|
||||
default:
|
||||
LOGW("DeviceFiles::StoreUsageTableHeader: unknown storage type: %d",
|
||||
usage_entry_info[i].storage_type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string serialized_file;
|
||||
file.SerializeToString(&serialized_file);
|
||||
|
||||
return StoreFileWithHash(GetUsageTableFileName(), serialized_file);
|
||||
}
|
||||
|
||||
bool DeviceFiles::RetrieveUsageTableInfo(
|
||||
std::string* usage_table_header,
|
||||
std::vector<DeviceFiles::UsageEntryInfo>* usage_entry_info) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveUsageTableInfo: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usage_table_header == NULL) {
|
||||
LOGW(
|
||||
"DeviceFiles::RetrieveUsageTableInfo: usage_table_header not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usage_entry_info == NULL) {
|
||||
LOGW("DeviceFiles::RetrieveUsageTableInfo: usage_entry_info not provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
video_widevine_client::sdk::File file;
|
||||
if (!RetrieveHashedFile(GetUsageTableFileName(), &file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.type() != video_widevine_client::sdk::File::USAGE_TABLE_INFO) {
|
||||
LOGW("DeviceFiles::RetrieveUsageTableInfo: Incorrect file type");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.version() != video_widevine_client::sdk::File::VERSION_1) {
|
||||
LOGW("DeviceFiles::RetrieveUsageTableInfo: Incorrect file version");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file.has_usage_table_info()) {
|
||||
LOGW("DeviceFiles::RetrieveUsageTableInfo: Usage table info not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
const UsageTableInfo& usage_table_info = file.usage_table_info();
|
||||
|
||||
*usage_table_header = usage_table_info.usage_table_header();
|
||||
usage_entry_info->resize(usage_table_info.usage_entry_info_size());
|
||||
for (int i = 0; i < usage_table_info.usage_entry_info_size(); ++i) {
|
||||
const UsageTableInfo_UsageEntryInfo& info =
|
||||
usage_table_info.usage_entry_info(i);
|
||||
switch (info.storage()) {
|
||||
case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE:
|
||||
(*usage_entry_info)[i].storage_type = kStorageLicense;
|
||||
(*usage_entry_info)[i].key_set_id = info.key_set_id();
|
||||
break;
|
||||
case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO:
|
||||
(*usage_entry_info)[i].storage_type = kStorageUsageInfo;
|
||||
(*usage_entry_info)[i].provider_session_token =
|
||||
info.provider_session_token();
|
||||
(*usage_entry_info)[i].app_id = info.app_id();
|
||||
break;
|
||||
default:
|
||||
LOGW("DeviceFiles::RetrieveUsageTableInfo: Unknown storage type: %d",
|
||||
info.storage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceFiles::StoreFileWithHash(const std::string& name,
|
||||
const std::string& serialized_file) {
|
||||
// calculate SHA hash
|
||||
@@ -796,6 +924,10 @@ std::string DeviceFiles::GetCertificateFileName() {
|
||||
return kCertificateFileName;
|
||||
}
|
||||
|
||||
std::string DeviceFiles::GetUsageTableFileName() {
|
||||
return kUsageTableFileName;
|
||||
}
|
||||
|
||||
std::string DeviceFiles::GetHlsAttributesFileNameExtension() {
|
||||
return kHlsAttributesFileNameExt;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ message License {
|
||||
// contains the playback_start_time we should use as an override. This is
|
||||
// ignored if there is no grace period.
|
||||
optional int64 grace_period_end_time = 11 [default = 0];
|
||||
optional bytes usage_entry = 12;
|
||||
}
|
||||
|
||||
message UsageInfo {
|
||||
@@ -51,13 +52,14 @@ message UsageInfo {
|
||||
optional bytes license_request = 2;
|
||||
optional bytes license = 3;
|
||||
optional bytes key_set_id = 4;
|
||||
optional bytes usage_entry = 5;
|
||||
}
|
||||
|
||||
repeated ProviderSession sessions = 1;
|
||||
}
|
||||
|
||||
message HlsAttributes {
|
||||
enum Method {
|
||||
enum Method {
|
||||
AES_128 = 1;
|
||||
SAMPLE_AES = 2;
|
||||
}
|
||||
@@ -65,12 +67,30 @@ message HlsAttributes {
|
||||
optional bytes media_segment_iv = 2;
|
||||
}
|
||||
|
||||
message UsageTableInfo {
|
||||
message UsageEntryInfo {
|
||||
enum UsageEntryStorage {
|
||||
LICENSE = 1;
|
||||
USAGE_INFO = 2;
|
||||
}
|
||||
|
||||
optional UsageEntryStorage storage = 1;
|
||||
optional bytes key_set_id = 2; // used if storage is LICENSE
|
||||
optional bytes provider_session_token = 3; // used if storage is USAGE_INFO
|
||||
optional bytes app_id = 4; // used if storage is USAGE_INFO
|
||||
}
|
||||
|
||||
optional bytes usage_table_header = 1;
|
||||
repeated UsageEntryInfo usage_entry_info = 2;
|
||||
}
|
||||
|
||||
message File {
|
||||
enum FileType {
|
||||
DEVICE_CERTIFICATE = 1;
|
||||
LICENSE = 2;
|
||||
USAGE_INFO = 3;
|
||||
HLS_ATTRIBUTES = 4;
|
||||
USAGE_TABLE_INFO = 5;
|
||||
}
|
||||
|
||||
enum FileVersion {
|
||||
@@ -83,6 +103,7 @@ message File {
|
||||
optional License license = 4;
|
||||
optional UsageInfo usage_info = 5;
|
||||
optional HlsAttributes hls_attributes = 6;
|
||||
optional UsageTableInfo usage_table_info = 7;
|
||||
}
|
||||
|
||||
message HashedFile {
|
||||
|
||||
Reference in New Issue
Block a user