Merges to android Pi release (part 3)

These are a set of CLs merged from the wv cdm repo to the android repo.

* Add CDM status return for decrypt blocked by HDCP.

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/28062 ]

  New status code is kKeyUsageBlockedByPolicy. It is returned by the decrypt()
  call instead of kDecryptError or kNoKey.

  Also shuffled the CDM status returns to define the EME-aligned codes
  first, and added comments to highlight the differences in handling.

  BUG: 37540672

* Change division and mod ops to relocatables

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/28600 ]

  This is similar to I2dad1028acf295288cd10817a2bcff2513c053c9.
  We should be using the relocatable functions instead of the
  native division and mod operations.

* Cleanup Encrypted ClientID in provisioning request

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/28083 ]

  b/36897239

  Staging server does not support it (or the client is not constructing
  it properly).  Leave it disabled pending investigation.

* Certificate Provisioning fixes.

  Author: Gene Morgan <gmorgan@google.com>

  [ Merge of http://go/wvgerrit/28066 ]

  Partial fix for BUG: 37482676
  Partial fix for BUG: 37481392

  Update service certificates, get rid of DEV/QA root certificate.
  Provisioning request and response are base64 (web-safe) encoded.
  Response is optionally JSON-wrapped.

  Change ConfigTestEnv; clearer comments and a closer match to reality.

BUG: 71650075
Test: Not currently passing. Will be addressed in a subsequent
      commit in the chain.

Change-Id: I79d3c4bf1124e5e0d3e4d40baead65a8266ea874
This commit is contained in:
Rahul Frias
2018-01-09 15:43:41 -08:00
parent 387147dffe
commit 11068accd2
30 changed files with 902 additions and 920 deletions

View File

@@ -99,11 +99,6 @@ bool CdmEngine::GetServiceCertificateRequest(CdmKeyMessage* request) {
SignedMessage message;
message.set_type(SignedMessage::SERVICE_CERTIFICATE_REQUEST);
message.SerializeToString(request);
// Convert to base64.
std::vector<uint8_t> request_vector(request->begin(), request->end());
std::string request_b64 = Base64SafeEncodeNoPad(request_vector);
request->swap(request_b64);
return true;
}
@@ -118,16 +113,8 @@ CdmResponseType CdmEngine::ParseServiceCertificateResponse(
return INVALID_PARAMETERS_ENG_24;
}
// The response is base64 encoded - decode it before parsing the string.
std::string padded_response(response);
while (padded_response.size() % 4 != 0) {
padded_response = padded_response + "=";
}
std::vector<uint8_t> raw_message = Base64SafeDecode(padded_response);
std::string raw_string(raw_message.begin(), raw_message.end());
SignedMessage signed_response;
if (!signed_response.ParseFromString(raw_string)) {
if (!signed_response.ParseFromString(response)) {
LOGE(
"CdmEngine::ParseServiceCertificateResponse: cannot parse response");
return PARSE_RESPONSE_ERROR_1;
@@ -157,7 +144,8 @@ CdmResponseType CdmEngine::ParseServiceCertificateResponse(
return PARSE_RESPONSE_ERROR_3;
} else {
LOGE(
"CdmEngine::ParseServiceCertificateResponse: response is wrong type");
"CdmEngine::ParseServiceCertificateResponse: response (%d) is "
"wrong type", signed_response.type());
return PARSE_RESPONSE_ERROR_4;
}
return NO_ERROR;
@@ -1079,8 +1067,11 @@ 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, &usage_entry)) {
uint32_t usage_entry_number = 0;
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
ssid, &license_request,
&license_response, &usage_entry,
&usage_entry_number)) {
usage_property_set_->set_security_level(kLevel3);
usage_property_set_->set_app_id(app_id);
usage_session_.reset(new CdmSession(file_system_));
@@ -1093,8 +1084,10 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
LOGE("CdmEngine::GetUsageInfo: device file init error");
return GET_USAGE_INFO_ERROR_2;
}
if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request,
&license_response, &usage_entry)) {
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
ssid, &license_request,
&license_response, &usage_entry,
&usage_entry_number)) {
// No entry found for that ssid.
return USAGE_INFO_NOT_FOUND;
}
@@ -1120,6 +1113,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
usage_info->clear();
return status;
}
return KEY_MESSAGE;
}
@@ -1135,7 +1129,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
do {
status = GetUsageInfo(app_id, security_level, usage_info);
if (KEY_MESSAGE == status && !usage_info->empty()) return status;
if (KEY_MESSAGE == status && !usage_info->empty()) {
return status;
}
} while (KEY_CANCELED == status);
security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3;
@@ -1172,7 +1168,8 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
}
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> > license_info;
if (!handle.RetrieveUsageInfo(app_id, &license_info)) {
if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id),
&license_info)) {
LOGE("CdmEngine::GetUsageInfo: unable to read usage information");
return GET_USAGE_INFO_ERROR_4;
}
@@ -1262,7 +1259,9 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
DeviceFiles handle(file_system_);
if (handle.Init(static_cast<CdmSecurityLevel>(j))) {
std::vector<std::string> provider_session_tokens;
if (!handle.DeleteAllUsageInfoForApp(app_id, &provider_session_tokens)) {
if (!handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(app_id),
&provider_session_tokens)) {
LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure"
"stops", j);
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
@@ -1338,11 +1337,15 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
std::string app_id;
session->GetApplicationId(&app_id);
std::string provider_session_token;
CdmKeyMessage key_message;
CdmKeyResponse key_response;
std::string usage_entry;
if (!handle.RetrieveUsageInfoByKeySetId(app_id, key_set_id, &key_message,
&key_response, &usage_entry)) {
uint32_t usage_entry_number = 0;
if (!handle.RetrieveUsageInfoByKeySetId(
DeviceFiles::GetUsageInfoFileName(app_id), key_set_id,
&provider_session_token, &key_message, &key_response,
&usage_entry, &usage_entry_number)) {
LOGE("CdmEngine::LoadUsageSession: unable to find usage information");
return LOAD_USAGE_INFO_MISSING;
}

View File

@@ -189,13 +189,14 @@ CdmResponseType CdmSession::RestoreOfflineSession(
int64_t last_playback_time;
int64_t grace_period_end_time;
std::string usage_entry;
uint32_t usage_entry_number = 0;
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_, &usage_entry)) {
&app_parameters_, &usage_entry, &usage_entry_number)) {
LOGE("CdmSession::Init failed to retrieve license. key set id = %s",
key_set_id.c_str());
return GET_LICENSE_ERROR;
@@ -345,6 +346,10 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
license_received_ = true;
key_response_ = key_response;
LOGV("AddKey: provider_session_token (size=%d) =%s",
license_parser_->provider_session_token().size(),
license_parser_->provider_session_token().c_str());
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
sts = StoreLicense();
if (sts != NO_ERROR) return sts;
@@ -598,9 +603,12 @@ CdmResponseType CdmSession::StoreLicense() {
std::string app_id;
GetApplicationId(&app_id);
std::string usage_entry;
uint32_t usage_entry_number = 0;
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
key_response_, app_id, key_set_id_,
usage_entry)) {
key_response_,
DeviceFiles::GetUsageInfoFileName(app_id),
key_set_id_, usage_entry,
usage_entry_number)) {
LOGE("CdmSession::StoreLicense: Unable to store usage info");
return STORE_USAGE_INFO_ERROR;
}
@@ -609,12 +617,14 @@ CdmResponseType CdmSession::StoreLicense() {
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
std::string usage_entry;
uint32_t usage_entry_number = 0;
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_, usage_entry);
policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry,
usage_entry_number);
}
CdmResponseType CdmSession::ReleaseCrypto() {
@@ -632,7 +642,8 @@ bool CdmSession::DeleteLicense() {
std::string app_id;
GetApplicationId(&app_id);
return file_handle_->DeleteUsageInfo(
app_id, license_parser_->provider_session_token());
DeviceFiles::GetUsageInfoFileName(app_id),
license_parser_->provider_session_token());
}
}

View File

@@ -66,7 +66,7 @@ void ExtractAndDecodeSignedMessage(const std::string& provisioning_response,
result->assign(decoded_message.begin(), decoded_message.end());
}
}
} // namespace
namespace wvcdm {
// Protobuf generated classes.
@@ -190,7 +190,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
client_id->set_type(token_type);
#if 0 // TODO(gmorgan) Encrypt ClientIdentification. Pending Design.
if (service_certificate_->HasCertificate()) {
if (service_certificate_->has_certificate()) {
EncryptedClientIdentification* encrypted_client_id =
provisioning_request.mutable_encrypted_client_id();
CdmResponseType status;
@@ -279,9 +279,9 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
FileSystem* file_system, const CdmProvisioningResponse& response,
std::string* cert, std::string* wrapped_key) {
std::string raw_string;
// The response is base64 encoded in a JSON wrapper.
// Extract it and decode it. If errors, return an empty string.
std::string raw_string;
ExtractAndDecodeSignedMessage(response, &raw_string);
if (raw_string.empty()) {

View File

@@ -41,6 +41,8 @@ using video_widevine_client::sdk::
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE;
using video_widevine_client::sdk::
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO;
using video_widevine_client::sdk::
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN;
using video_widevine::SignedDrmDeviceCertificate;
using video_widevine::DrmDeviceCertificate;
@@ -218,7 +220,8 @@ bool DeviceFiles::StoreLicense(
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 CdmUsageEntry& usage_entry) {
const CdmUsageEntry& usage_entry,
const uint32_t usage_entry_number) {
if (!initialized_) {
LOGW("DeviceFiles::StoreLicense: not initialized");
return false;
@@ -260,6 +263,7 @@ bool DeviceFiles::StoreLicense(
app_params->set_value(iter->second);
}
license->set_usage_entry(usage_entry);
license->set_usage_entry_number(usage_entry_number);
std::string serialized_file;
file.SerializeToString(&serialized_file);
@@ -274,7 +278,8 @@ 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, CdmUsageEntry* usage_entry) {
CdmAppParameterMap* app_parameters, CdmUsageEntry* usage_entry,
uint32_t* usage_entry_number) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveLicense: not initialized");
return false;
@@ -329,6 +334,7 @@ bool DeviceFiles::RetrieveLicense(
license.app_parameters(i).value();
}
*usage_entry = license.usage_entry();
*usage_entry_number = license.usage_entry_number();
return true;
}
@@ -422,21 +428,21 @@ bool DeviceFiles::UnreserveLicenseId(const std::string& key_set_id) {
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& usage_info_file_name,
const std::string& key_set_id,
const CdmUsageEntry& usage_entry) {
const std::string& usage_entry,
uint32_t usage_entry_number) {
if (!initialized_) {
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
return false;
}
video_widevine_client::sdk::File file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!FileExists(file_name)) {
if (!FileExists(usage_info_file_name)) {
file.set_type(video_widevine_client::sdk::File::USAGE_INFO);
file.set_version(video_widevine_client::sdk::File::VERSION_1);
} else {
if (!RetrieveHashedFile(file_name, &file)) {
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
LOGW("DeviceFiles::StoreUsageInfo: Unable to parse file");
return false;
}
@@ -451,10 +457,11 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token,
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);
provider_session->set_usage_entry_number(usage_entry_number);
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(file_name, serialized_file);
return StoreFileWithHash(usage_info_file_name, serialized_file);
}
bool DeviceFiles::ListUsageRecords(const std::string& app_id,
@@ -528,15 +535,14 @@ bool DeviceFiles::GetProviderSessionToken(const std::string& app_id,
return false;
}
bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
bool DeviceFiles::DeleteUsageInfo(const std::string& usage_info_file_name,
const std::string& provider_session_token) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteUsageInfo: not initialized");
return false;
}
video_widevine_client::sdk::File file;
std::string file_name = GetUsageInfoFileName(app_id);
if (!RetrieveHashedFile(file_name, &file)) return false;
if (!RetrieveHashedFile(usage_info_file_name, &file)) return false;
UsageInfo* usage_info = file.mutable_usage_info();
int index = 0;
@@ -565,11 +571,11 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& app_id,
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(file_name, serialized_file);
return StoreFileWithHash(usage_info_file_name, serialized_file);
}
bool DeviceFiles::DeleteAllUsageInfoForApp(
const std::string& app_id,
const std::string& usage_info_file_name,
std::vector<std::string>* provider_session_tokens) {
if (!initialized_) {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: not initialized");
@@ -581,22 +587,21 @@ bool DeviceFiles::DeleteAllUsageInfoForApp(
}
provider_session_tokens->clear();
std::string file_name = GetUsageInfoFileName(app_id);
if (!FileExists(file_name)) return true;
if (!FileExists(usage_info_file_name)) return true;
video_widevine_client::sdk::File file;
if (RetrieveHashedFile(file_name, &file)) {
if (RetrieveHashedFile(usage_info_file_name, &file)) {
for (int i = 0; i < file.usage_info().sessions_size(); ++i) {
provider_session_tokens->push_back(file.usage_info().sessions(i).token());
}
} else {
LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to retrieve file");
}
return RemoveFile(file_name);
return RemoveFile(usage_info_file_name);
}
bool DeviceFiles::RetrieveUsageInfo(
const std::string& app_id,
const std::string& usage_info_file_name,
std::vector<std::pair<CdmKeyMessage, CdmKeyResponse> >* usage_info) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
@@ -610,14 +615,14 @@ bool DeviceFiles::RetrieveUsageInfo(
return false;
}
std::string file_name = GetUsageInfoFileName(app_id);
if (!FileExists(file_name) || GetFileSize(file_name) == 0) {
if (!FileExists(usage_info_file_name) ||
GetFileSize(usage_info_file_name) == 0) {
usage_info->resize(0);
return true;
}
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(file_name, &file)) {
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
LOGW("DeviceFiles::RetrieveUsageInfo: Unable to parse file");
return false;
}
@@ -632,19 +637,19 @@ bool DeviceFiles::RetrieveUsageInfo(
return true;
}
bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name,
const std::string& provider_session_token,
CdmKeyMessage* license_request,
CdmKeyResponse* license_response,
CdmUsageEntry* usage_entry) {
std::string* usage_entry,
uint32_t* usage_entry_number) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
return false;
}
std::string file_name = GetUsageInfoFileName(app_id);
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(file_name, &file)) {
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
return false;
}
@@ -654,6 +659,8 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_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();
*usage_entry_number =
file.usage_info().sessions(index).usage_entry_number();
return true;
}
}
@@ -662,28 +669,32 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id,
}
bool DeviceFiles::RetrieveUsageInfoByKeySetId(
const std::string& app_id,
const std::string& usage_info_file_name,
const std::string& key_set_id,
std::string* provider_session_token,
CdmKeyMessage* license_request,
CdmKeyResponse* license_response,
CdmUsageEntry* usage_entry) {
std::string* usage_entry,
uint32_t* usage_entry_number) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfoByKeySetId: not initialized");
return false;
}
std::string file_name = GetUsageInfoFileName(app_id);
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(file_name, &file)) {
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
return false;
}
int index = 0;
for (; index < file.usage_info().sessions_size(); ++index) {
if (file.usage_info().sessions(index).key_set_id() == key_set_id) {
*provider_session_token = file.usage_info().sessions(index).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();
*usage_entry_number =
file.usage_info().sessions(index).usage_entry_number();
return true;
}
}
@@ -691,6 +702,97 @@ bool DeviceFiles::RetrieveUsageInfoByKeySetId(
return false;
}
bool DeviceFiles::StoreUsageInfo(const std::string& usage_info_file_name,
const std::vector<CdmUsageData>& usage_data) {
if (!initialized_) {
LOGW("DeviceFiles::StoreUsageInfo: not initialized");
return false;
}
video_widevine_client::sdk::File file;
file.set_type(video_widevine_client::sdk::File::USAGE_INFO);
file.set_version(video_widevine_client::sdk::File::VERSION_1);
UsageInfo* usage_info = file.mutable_usage_info();
for (size_t i = 0; i < usage_data.size(); ++i) {
UsageInfo_ProviderSession* provider_session = usage_info->add_sessions();
provider_session->set_token(usage_data[i].provider_session_token.data(),
usage_data[i].provider_session_token.size());
provider_session->set_license_request(usage_data[i].license_request.data(),
usage_data[i].license_request.size());
provider_session->set_license(usage_data[i].license.data(),
usage_data[i].license.size());
provider_session->set_key_set_id(usage_data[i].key_set_id.data(),
usage_data[i].key_set_id.size());
provider_session->set_usage_entry(usage_data[i].usage_entry);
provider_session->set_usage_entry_number(usage_data[i].usage_entry_number);
}
std::string serialized_file;
file.SerializeToString(&serialized_file);
return StoreFileWithHash(usage_info_file_name, serialized_file);
}
bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name,
std::vector<CdmUsageData>* usage_data) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageInfo: not initialized");
return false;
}
video_widevine_client::sdk::File file;
if (!RetrieveHashedFile(usage_info_file_name, &file)) {
return false;
}
usage_data->resize(file.usage_info().sessions_size());
for (int i = 0; i < file.usage_info().sessions_size(); ++i) {
(*usage_data)[i].provider_session_token =
file.usage_info().sessions(i).token();
(*usage_data)[i].license_request =
file.usage_info().sessions(i).license_request();
(*usage_data)[i].license = file.usage_info().sessions(i).license();
(*usage_data)[i].key_set_id = file.usage_info().sessions(i).key_set_id();
(*usage_data)[i].usage_entry = file.usage_info().sessions(i).usage_entry();
(*usage_data)[i].usage_entry_number =
file.usage_info().sessions(i).usage_entry_number();
}
return false;
}
bool DeviceFiles::ListUsageInfoFiles(
std::vector<std::string>* usage_info_file_names) {
if (!initialized_) {
LOGW("DeviceFiles::ListUsageInfoFiles: not initialized");
return false;
}
// Get list of filenames
std::vector<std::string> filenames;
if (!ListFiles(&filenames)) {
return false;
}
// Scan list of all filenames and return only usage info filenames
usage_info_file_names->clear();
for (size_t i = 0; i < filenames.size(); i++) {
std::string* name = &filenames[i];
std::size_t pos_prefix = name->find(kUsageInfoFileNamePrefix);
std::size_t pos_suffix = name->find(kUsageInfoFileNameExt);
if (pos_prefix == std::string::npos ||
pos_suffix == std::string::npos) {
// Skip this file - extension does not match
continue;
}
usage_info_file_names->push_back(*name);
}
return true;
}
bool DeviceFiles::StoreHlsAttributes(
const std::string& key_set_id, const CdmHlsMethod method,
const std::vector<uint8_t>& media_segment_iv) {
@@ -790,7 +892,7 @@ bool DeviceFiles::DeleteHlsAttributes(const std::string& key_set_id) {
bool DeviceFiles::StoreUsageTableInfo(
const CdmUsageTableHeader& usage_table_header,
const std::vector<DeviceFiles::UsageEntryInfo>& usage_entry_info) {
const std::vector<CdmUsageEntryInfo>& usage_entry_info) {
if (!initialized_) {
LOGW("DeviceFiles::StoreUsageTableHeader: not initialized");
return false;
@@ -807,23 +909,23 @@ bool DeviceFiles::StoreUsageTableInfo(
for (size_t i = 0; i < usage_entry_info.size(); ++i) {
UsageTableInfo_UsageEntryInfo* info =
usage_table_info->add_usage_entry_info();
info->set_key_set_id(usage_entry_info[i].key_set_id);
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);
info->set_usage_info_file_name(
usage_entry_info[i].usage_info_file_name);
break;
case kStorageUnknown:
default:
LOGW("DeviceFiles::StoreUsageTableHeader: unknown storage type: %d",
usage_entry_info[i].storage_type);
return false;
info->set_storage(
UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN);
break;
}
}
@@ -835,7 +937,7 @@ bool DeviceFiles::StoreUsageTableInfo(
bool DeviceFiles::RetrieveUsageTableInfo(
CdmUsageTableHeader* usage_table_header,
std::vector<DeviceFiles::UsageEntryInfo>* usage_entry_info) {
std::vector<CdmUsageEntryInfo>* usage_entry_info) {
if (!initialized_) {
LOGW("DeviceFiles::RetrieveUsageTableInfo: not initialized");
return false;
@@ -879,21 +981,20 @@ bool DeviceFiles::RetrieveUsageTableInfo(
for (int i = 0; i < usage_table_info.usage_entry_info_size(); ++i) {
const UsageTableInfo_UsageEntryInfo& info =
usage_table_info.usage_entry_info(i);
(*usage_entry_info)[i].key_set_id = info.key_set_id();
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();
(*usage_entry_info)[i].usage_info_file_name =
info.usage_info_file_name();
break;
case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN:
default:
LOGW("DeviceFiles::RetrieveUsageTableInfo: Unknown storage type: %d",
info.storage());
return false;
(*usage_entry_info)[i].storage_type = kStorageUnknown;
break;
}
}

View File

@@ -44,6 +44,7 @@ message License {
// ignored if there is no grace period.
optional int64 grace_period_end_time = 11 [default = 0];
optional bytes usage_entry = 12;
optional int64 usage_entry_number = 13;
}
message UsageInfo {
@@ -53,6 +54,7 @@ message UsageInfo {
optional bytes license = 3;
optional bytes key_set_id = 4;
optional bytes usage_entry = 5;
optional int64 usage_entry_number = 6;
}
repeated ProviderSession sessions = 1;
@@ -72,12 +74,12 @@ message UsageTableInfo {
enum UsageEntryStorage {
LICENSE = 1;
USAGE_INFO = 2;
UNKNOWN = 3;
}
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 key_set_id = 2;
optional bytes usage_info_file_name = 3; // hash of the app_id
}
optional bytes usage_table_header = 1;

View File

@@ -205,8 +205,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
return INVALID_PARAMETERS_LIC_7;
}
// If privacy mode and no service certificate, initiate a
// service certificate request.
// If privacy mode, must have service certificate
if (Properties::UsePrivacyMode(session_id_) &&
!service_certificate_->has_certificate()) {
LOGE("CdmLicense::PrepareKeyRequest: failure with privacy mode - "
@@ -479,8 +478,13 @@ CdmResponseType CdmLicense::HandleKeyResponse(
license.policy().can_persist())
is_offline_ = true;
if (license.id().has_provider_session_token())
LOGV("Get Provider_session_token:");
if (license.id().has_provider_session_token()) {
provider_session_token_ = license.id().provider_session_token();
LOGV("Provider_session_token=%s", provider_session_token_.c_str());
} else {
LOGV("NO Provider_session_token");
}
if (license.policy().has_renewal_server_url()) {
server_url_ = license.policy().renewal_server_url();
@@ -797,6 +801,7 @@ bool CdmLicense::GetClientTokenType(
case kClientTokenOemCert:
default:
// shouldn't happen
LOGE("GetClientTokenType: BAD TOKEN TYPE");
return false;
}
}
@@ -980,7 +985,7 @@ CdmResponseType CdmLicense::PrepareContentId(
if (!init_data.IsEmpty()) {
cenc_content_id->add_pssh(init_data.data());
} else {
LOGE("CdmLicense::PrepareKeyRequest: ISO-CENC init data not available");
LOGE("CdmLicense::PrepareContentId: ISO-CENC init data not available");
return CENC_INIT_DATA_UNAVAILABLE;
}
@@ -994,7 +999,7 @@ CdmResponseType CdmLicense::PrepareContentId(
if (!init_data.IsEmpty()) {
webm_content_id->set_header(init_data.data());
} else {
LOGE("CdmLicense::PrepareKeyRequest: WebM init data not available");
LOGE("CdmLicense::PrepareContentId: WebM init data not available");
return WEBM_INIT_DATA_UNAVAILABLE;
}
@@ -1002,7 +1007,7 @@ CdmResponseType CdmLicense::PrepareContentId(
return PREPARE_WEBM_CONTENT_ID_FAILED;
}
} else {
LOGE("CdmLicense::PrepareKeyRequest: no support for init data type (%s)",
LOGE("CdmLicense::PrepareContentId: no support for init data type (%s)",
init_data.type().c_str());
return UNSUPPORTED_INIT_DATA_FORMAT;
}

View File

@@ -103,7 +103,15 @@ bool LicenseKeys::ApplyStatusChange(CdmKeyStatus new_status,
return keys_changed;
}
CdmKeyStatus LicenseKeys::GetKeyStatus(const KeyId& key_id) {
if (keys_.count(key_id) == 0) {
return kKeyStatusKeyUnknown;
}
return keys_[key_id]->GetKeyStatus();
}
void LicenseKeys::ExtractKeyStatuses(CdmKeyStatusMap* content_keys) {
content_keys->clear();
for (LicenseKeyStatusIterator it = keys_.begin(); it != keys_.end(); ++it) {
if (it->second->IsContentKey()) {
const KeyId key_id = it->first;

View File

@@ -47,6 +47,10 @@ bool PolicyEngine::CanDecryptContent(const KeyId& key_id) {
}
}
CdmKeyStatus PolicyEngine::GetKeyStatus(const KeyId& key_id) {
return license_keys_->GetKeyStatus(key_id);
}
void PolicyEngine::InitDevice(CryptoSession* crypto_session) {
current_resolution_ = HDCP_UNSPECIFIED_VIDEO_RESOLUTION;
next_device_check_ = 0;
@@ -101,7 +105,9 @@ void PolicyEngine::OnTimerEvent() {
// Test to determine if renewal should be attempted.
switch (license_state_) {
case kLicenseStateCanPlay: {
if (HasRenewalDelayExpired(current_time)) renewal_needed = true;
if (HasRenewalDelayExpired(current_time)) {
renewal_needed = true;
}
// HDCP may change, so force a check.
NotifyKeysChange(kKeyStatusUsable);
break;
@@ -113,7 +119,9 @@ void PolicyEngine::OnTimerEvent() {
}
case kLicenseStateWaitingLicenseUpdate: {
if (HasRenewalRetryIntervalExpired(current_time)) renewal_needed = true;
if (HasRenewalRetryIntervalExpired(current_time)) {
renewal_needed = true;
}
break;
}
@@ -429,6 +437,10 @@ bool PolicyEngine::HasRenewalRetryIntervalExpired(int64_t current_time) {
next_renewal_time_ <= current_time;
}
// Apply a key status to the current keys.
// If this represents a new key status, perform a notification callback.
// NOTE: if the new status is kKeyStatusUsable, the HDCP check may result in an
// override to kKeyStatusOutputNotAllowed.
void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
bool keys_changed;
bool has_new_usable_key = false;

View File

@@ -11,110 +11,6 @@
namespace {
// Service certificate for Google/Widevine Provisioning and License servers.
static const unsigned char kRootCertForDev[] = {
0x0a, 0x9c, 0x03, 0x08, 0x00, 0x12, 0x01, 0x00,
0x18, 0xc3, 0x94, 0x88, 0x8b, 0x05, 0x22, 0x8e,
0x03, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01,
0x81, 0x00, 0xc0, 0x00, 0x36, 0x6f, 0x8e, 0xe9,
0xcf, 0x86, 0xdb, 0xcd, 0xdd, 0x4e, 0xfd, 0xcd,
0x45, 0xbf, 0x6d, 0x96, 0x05, 0x00, 0xb8, 0x72,
0xff, 0x9c, 0xb4, 0x39, 0xa8, 0xd8, 0xc0, 0x09,
0x73, 0xc0, 0x24, 0x6a, 0x39, 0x4d, 0x36, 0x3f,
0x9a, 0xe4, 0xb8, 0x76, 0xdc, 0x34, 0xe3, 0xee,
0x5f, 0xdd, 0x13, 0x20, 0x08, 0xdc, 0x4e, 0x6f,
0x4e, 0x9f, 0xc0, 0x36, 0xf9, 0xce, 0xc6, 0xb7,
0xdb, 0xe0, 0x51, 0x2d, 0x30, 0x0b, 0xae, 0x0a,
0x20, 0xd2, 0x29, 0x3c, 0x2c, 0x1d, 0x87, 0x65,
0xeb, 0x5f, 0x93, 0xd7, 0x3f, 0x12, 0x08, 0x50,
0x0e, 0x55, 0xf3, 0xf1, 0x19, 0xee, 0x18, 0x21,
0x6e, 0xea, 0xb6, 0x0a, 0x4a, 0x0b, 0x9c, 0x72,
0x37, 0xeb, 0x0b, 0x68, 0xfc, 0x52, 0x46, 0x62,
0xd0, 0xa2, 0x99, 0x66, 0xe2, 0x2b, 0x74, 0xdd,
0x5c, 0xaf, 0x9a, 0x03, 0xc4, 0x5d, 0x93, 0xfb,
0xcd, 0x45, 0x9a, 0xee, 0xfb, 0x7b, 0x18, 0x94,
0xc1, 0x8c, 0x82, 0x34, 0x7f, 0x02, 0x12, 0x21,
0xfc, 0x40, 0xc1, 0x50, 0xc9, 0xf4, 0x7c, 0xd5,
0x96, 0xbe, 0x55, 0x7f, 0x3c, 0x1d, 0x70, 0x34,
0xb4, 0xa2, 0x03, 0xc4, 0x3f, 0x89, 0x60, 0xe4,
0x24, 0x09, 0x1a, 0x74, 0xc4, 0xb6, 0x39, 0xf0,
0x34, 0x60, 0x8e, 0xa7, 0x5f, 0x02, 0x7f, 0xb9,
0x2a, 0xc5, 0xaa, 0xb2, 0x4c, 0x34, 0xd3, 0x5a,
0x5d, 0xfa, 0x07, 0xf2, 0xb9, 0xb3, 0xc1, 0xba,
0xab, 0xbe, 0x89, 0x99, 0xe3, 0x6d, 0x9b, 0xa9,
0xd3, 0xaf, 0x2a, 0x08, 0x76, 0xf3, 0x0e, 0xc9,
0xe0, 0xb3, 0xbf, 0x51, 0x0c, 0xc5, 0xf4, 0xf3,
0x15, 0x7b, 0x08, 0x11, 0x8f, 0x61, 0x1f, 0x61,
0x64, 0xdb, 0x15, 0x84, 0x5b, 0x8a, 0xd1, 0x28,
0x40, 0xde, 0xc5, 0x32, 0xb5, 0xad, 0xad, 0x65,
0x4c, 0xf5, 0xf7, 0xd1, 0x90, 0x14, 0x5d, 0xc2,
0x85, 0x98, 0xcc, 0xe9, 0xe6, 0x95, 0x42, 0xe1,
0x3e, 0xfc, 0x7f, 0xc4, 0x49, 0xed, 0x9c, 0xe4,
0x49, 0x3f, 0x03, 0x1b, 0x0d, 0xa0, 0xfb, 0xf5,
0x38, 0x49, 0xd2, 0xdf, 0xa3, 0x88, 0xb2, 0x76,
0x93, 0x08, 0x20, 0x18, 0xfe, 0xdc, 0x72, 0x6c,
0x6e, 0xbf, 0x61, 0x37, 0x03, 0xdb, 0xe5, 0x72,
0x68, 0xe0, 0x99, 0x2f, 0xb9, 0xe0, 0x2e, 0xbb,
0x9f, 0x96, 0x36, 0x61, 0xaa, 0x2d, 0xa4, 0x93,
0xe8, 0x50, 0x58, 0xe6, 0x61, 0xe1, 0x14, 0xcf,
0xac, 0x86, 0x98, 0x7f, 0x3c, 0x67, 0x16, 0xce,
0xb8, 0x70, 0x90, 0x3a, 0x5a, 0xd4, 0xe1, 0xe2,
0x35, 0x98, 0xbf, 0x93, 0x41, 0x11, 0xb2, 0x44,
0xb2, 0x64, 0xc2, 0xe7, 0x09, 0x45, 0xb7, 0x6f,
0xb0, 0xbd, 0x6e, 0xe8, 0x67, 0xfa, 0x8d, 0xd4,
0xfa, 0x4b, 0xef, 0xa8, 0x9d, 0x8a, 0x0a, 0xd9,
0x14, 0x77, 0x09, 0x11, 0x9e, 0xc3, 0x50, 0x14,
0x6c, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0x12,
0x80, 0x03, 0x17, 0x01, 0x60, 0x24, 0xe1, 0xfd,
0x75, 0x60, 0x17, 0x5c, 0x5e, 0x6f, 0x9f, 0x7f,
0xdf, 0xee, 0xf0, 0xf7, 0x7d, 0xb2, 0x50, 0x65,
0x36, 0x26, 0x14, 0x19, 0x01, 0x5e, 0x98, 0x94,
0x65, 0x97, 0x83, 0xaa, 0x4a, 0x2b, 0x98, 0x2e,
0x02, 0xf3, 0xb2, 0xc9, 0xb2, 0xed, 0xd3, 0x1b,
0x20, 0x27, 0x9e, 0xe1, 0x25, 0xc7, 0x86, 0xf0,
0x66, 0x68, 0x5d, 0xd2, 0x3d, 0xa7, 0xbb, 0xbc,
0x22, 0xfc, 0x29, 0xfa, 0x17, 0x16, 0xf4, 0xa2,
0x00, 0x10, 0x87, 0xb4, 0x5d, 0x51, 0x45, 0x6b,
0xc8, 0xf4, 0x6b, 0xcc, 0x92, 0x91, 0xe7, 0xa7,
0x93, 0xbc, 0xc7, 0x2e, 0xdc, 0xac, 0x82, 0x2b,
0x85, 0x56, 0x7b, 0xae, 0xf2, 0xd8, 0xda, 0xa6,
0xd7, 0xfa, 0x6d, 0x70, 0x2a, 0x2e, 0xcf, 0x69,
0xef, 0x57, 0x91, 0xa7, 0xaa, 0x40, 0x15, 0x4a,
0x49, 0x1b, 0xbc, 0x36, 0xbb, 0x1c, 0x94, 0x33,
0x36, 0x61, 0x22, 0x9d, 0x22, 0x66, 0xf0, 0x88,
0x5e, 0x7c, 0x3c, 0xa5, 0xff, 0x81, 0xcf, 0x1a,
0x44, 0xa1, 0x2b, 0xdf, 0xc9, 0x3d, 0xd5, 0xc7,
0xc7, 0x3a, 0x75, 0xac, 0x29, 0xfa, 0xfd, 0x5b,
0xda, 0xf5, 0x8f, 0xd9, 0xdf, 0x08, 0xa4, 0x8d,
0x19, 0x4a, 0xa4, 0x79, 0x6e, 0x47, 0xf6, 0x07,
0xe0, 0xbd, 0xbf, 0x30, 0x3a, 0xf9, 0xf5, 0xc0,
0x90, 0x6d, 0x70, 0x27, 0x44, 0xa8, 0x5e, 0x70,
0xcd, 0x43, 0x3e, 0xaf, 0xf0, 0xd7, 0x20, 0xd3,
0x5e, 0x97, 0x2d, 0x32, 0x1a, 0x3d, 0x2d, 0x0f,
0x0f, 0xcf, 0xac, 0x4e, 0x88, 0x75, 0x98, 0x6c,
0xfa, 0xe8, 0x42, 0x58, 0x99, 0xaa, 0x45, 0x0c,
0x41, 0x0c, 0x6e, 0x27, 0x58, 0x57, 0xd2, 0x5b,
0x82, 0x3d, 0x75, 0x2f, 0x9e, 0xf3, 0xe4, 0x00,
0xcf, 0x91, 0x48, 0x25, 0xca, 0x98, 0xf2, 0x91,
0x6b, 0x41, 0xa5, 0xe8, 0xcd, 0x64, 0xa7, 0x2e,
0x78, 0xc7, 0x76, 0x82, 0x3f, 0xf8, 0x57, 0x8a,
0x9d, 0x78, 0x25, 0xad, 0xf3, 0x1a, 0x8b, 0xfc,
0x83, 0x9a, 0x98, 0x87, 0xe4, 0x55, 0x3e, 0x1c,
0xa7, 0x80, 0x8f, 0xd6, 0x76, 0xab, 0x03, 0xc7,
0x05, 0x66, 0xc3, 0xa0, 0x4c, 0x33, 0x1f, 0x39,
0x74, 0x1b, 0x2a, 0xbf, 0xe6, 0xb0, 0x9f, 0x6b,
0xc1, 0xd6, 0xd3, 0xf4, 0x46, 0x9b, 0xf3, 0xab,
0xca, 0x2e, 0x88, 0x3d, 0x84, 0x5f, 0xc9, 0x9b,
0x47, 0xbb, 0x57, 0x64, 0x08, 0x0e, 0x18, 0x74,
0x83, 0x44, 0xd4, 0xc3, 0x18, 0x97, 0xcf, 0x89,
0x6a, 0x49, 0x51, 0xc6, 0xff, 0x8d, 0x39, 0xc5,
0x23, 0xf9, 0xd5, 0x01, 0xd7, 0x2f, 0xa9, 0xa5,
0x5d, 0xa9, 0xf3, 0xc9, 0xfd, 0xc4, 0x52, 0x19,
0x7d, 0xf6, 0xa4, 0x2c, 0x0c, 0xa0, 0x07, 0xdf,
0x7b, 0x44, 0xd7, 0xe5, 0xbf, 0x57, 0x87, 0xc9,
0x8c, 0xfe, 0x30, 0xb2, 0x89, 0x5d, 0x00, 0x03,
0x3b, 0xe5
};
static const unsigned char kRootCertForProd[] = {
0x0a, 0x9c, 0x03, 0x08, 0x00, 0x12, 0x01, 0x00,
0x18, 0xdd, 0x94, 0x88, 0x8b, 0x05, 0x22, 0x8e,
@@ -231,14 +127,8 @@ using video_widevine::SignedDrmDeviceCertificate;
using video_widevine::SignedMessage;
CdmResponseType ServiceCertificate::Init(const std::string& certificate) {
// TODO(tinskip): Get rid of conditional compilation.
#if defined(QA_TEST_SERVER)
std::string root_cert_str(reinterpret_cast<const char*>(&kRootCertForDev[0]),
sizeof(kRootCertForDev));
#else
std::string root_cert_str(reinterpret_cast<const char*>(&kRootCertForProd[0]),
sizeof(kRootCertForProd));
#endif // !defined(QA_TEST_SERVER);
// Load root cert public key. Don't bother verifying it.
SignedDrmDeviceCertificate signed_root_cert;

View File

@@ -229,7 +229,7 @@ std::vector<uint8_t> Base64Decode(const std::string& b64_input) {
}
// Decode for Filename-friendly base64 encoding (RFC4648), commonly referred
// as Base64WebSafeDecode.
// as Base64WebSafeDecode. Add padding if needed.
std::vector<uint8_t> Base64SafeDecode(const std::string& b64_input) {
if (b64_input.empty()) {
return std::vector<uint8_t>();