MediaDrm throws an exception when Secure Stops are requested
Our recommendation to OEMs is that they support a table of at least 50 usage entries in OEMCrypto. If more usage entries are stored, the PSTs get added to the CDM but are LRU'ed out of the OEMCrypto usage table. When the CDM queries those usage entries, OEMCrypto will return a OEMCrypto_ERROR_INVALID_CONTEXT. Rather than return an error and have MediaDrm throw an exception, CDM should delete this PST and return the next usage entry, when queried. [ Merge of https://widevine-internal-review.googlesource.com/#/c/11457/ from Widevine cdm repo ] b/17994711 Change-Id: I00e3f93000096fb434d94333e22958de795a4bb5
This commit is contained in:
@@ -654,16 +654,22 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
CdmUsageInfo* usage_info) {
|
||||
// Return a random usage report from a random security level
|
||||
SecurityLevel security_level = ((rand() % 2) == 0) ? kLevelDefault : kLevel3;
|
||||
CdmResponseType status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
CdmResponseType status = UNKNOWN_ERROR;
|
||||
do {
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
|
||||
if (KEY_MESSAGE == status && !usage_info->empty())
|
||||
return status;
|
||||
} while (KEY_CANCELED == status);
|
||||
|
||||
if (KEY_MESSAGE == status && !usage_info->empty())
|
||||
return status;
|
||||
|
||||
security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3;
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
if (NEED_PROVISIONING == status)
|
||||
return NO_ERROR; // Valid scenario that one of the security
|
||||
// levels has not been provisioned
|
||||
do {
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
if (NEED_PROVISIONING == status)
|
||||
return NO_ERROR; // Valid scenario that one of the security
|
||||
// levels has not been provisioned
|
||||
} while (KEY_CANCELED == status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -716,13 +722,20 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
|
||||
status = usage_session_->GenerateReleaseRequest(&(*usage_info)[0], &server_url);
|
||||
|
||||
if (KEY_MESSAGE != status) {
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %d",
|
||||
status);
|
||||
usage_info->clear();
|
||||
return status;
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
break;
|
||||
case KEY_CANCELED: // usage information not present in
|
||||
usage_session_->DeleteLicense(); // OEMCrypto, delete and try again
|
||||
usage_info->clear();
|
||||
break;
|
||||
default:
|
||||
LOGE("CdmEngine::GetUsageInfo: generate release request error: %d",
|
||||
status);
|
||||
usage_info->clear();
|
||||
break;
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
|
||||
@@ -385,11 +385,11 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
// session keys.
|
||||
CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request,
|
||||
std::string* server_url) {
|
||||
if (!license_parser_->PrepareKeyUpdateRequest(true, key_request,
|
||||
server_url)) {
|
||||
LOGE("CdmSession::GenerateRenewalRequest: ERROR on prepare");
|
||||
return KEY_ERROR;
|
||||
}
|
||||
CdmResponseType status =
|
||||
license_parser_->PrepareKeyUpdateRequest(true, key_request, server_url);
|
||||
|
||||
if (KEY_MESSAGE != status)
|
||||
return status;
|
||||
|
||||
if (is_offline_) {
|
||||
offline_key_renewal_request_ = *key_request;
|
||||
@@ -413,8 +413,11 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request,
|
||||
std::string* server_url) {
|
||||
is_release_ = true;
|
||||
if (!license_parser_->PrepareKeyUpdateRequest(false, key_request, server_url))
|
||||
return UNKNOWN_ERROR;
|
||||
CdmResponseType status =
|
||||
license_parser_->PrepareKeyUpdateRequest(false, key_request, server_url);
|
||||
|
||||
if (KEY_MESSAGE != status)
|
||||
return status;
|
||||
|
||||
if (is_offline_) { // Mark license as being released
|
||||
if (!StoreLicense(DeviceFiles::kLicenseStateReleasing))
|
||||
|
||||
@@ -716,13 +716,19 @@ CdmResponseType CryptoSession::DeactivateUsageInformation(
|
||||
OEMCryptoResult status =
|
||||
OEMCrypto_DeactivateUsageEntry(pst, provider_session_token.length());
|
||||
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
LOGE("CryptoSession::DeactivateUsageInformation: Deactivate Usage Entry "
|
||||
" error=%ld",
|
||||
switch(status) {
|
||||
case OEMCrypto_SUCCESS:
|
||||
return NO_ERROR;
|
||||
case OEMCrypto_ERROR_INVALID_CONTEXT:
|
||||
LOGE("CryptoSession::DeactivateUsageInformation: Deactivate Usage Entry "
|
||||
" invalid context error");
|
||||
return KEY_CANCELED;
|
||||
default:
|
||||
LOGE("CryptoSession::DeactivateUsageInformation: Deactivate Usage Entry "
|
||||
" error=%ld",
|
||||
status);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GenerateUsageReport(
|
||||
|
||||
@@ -476,20 +476,21 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
CdmKeyMessage* signed_request,
|
||||
std::string* server_url) {
|
||||
CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
|
||||
bool is_renewal,
|
||||
CdmKeyMessage* signed_request,
|
||||
std::string* server_url) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmLicense::PrepareKeyUpdateRequest: not initialized");
|
||||
return false;
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (!signed_request) {
|
||||
LOGE("CdmLicense::PrepareKeyUpdateRequest: No signed request provided");
|
||||
return false;
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
if (!server_url) {
|
||||
LOGE("CdmLicense::PrepareKeyUpdateRequest: No server url provided");
|
||||
return false;
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
LicenseRequest license_request;
|
||||
@@ -513,7 +514,7 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
CdmResponseType status =
|
||||
session_->DeactivateUsageInformation(provider_session_token_);
|
||||
if (NO_ERROR != status)
|
||||
return false;
|
||||
return status;
|
||||
}
|
||||
|
||||
std::string usage_report;
|
||||
@@ -526,7 +527,7 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
if (NO_ERROR == status)
|
||||
current_license->set_session_usage_table_entry(usage_report);
|
||||
else
|
||||
return false;
|
||||
return KEY_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +546,7 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
// of the license response.
|
||||
uint32_t nonce;
|
||||
if (!session_->GenerateNonce(&nonce)) {
|
||||
return false;
|
||||
return KEY_ERROR;
|
||||
}
|
||||
license_request.set_key_control_nonce(nonce);
|
||||
LOGD("PrepareKeyUpdateRequest: nonce=%u", nonce);
|
||||
@@ -559,13 +560,13 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
std::string license_request_signature;
|
||||
if (!session_->PrepareRenewalRequest(serialized_license_req,
|
||||
&license_request_signature))
|
||||
return false;
|
||||
return KEY_ERROR;
|
||||
|
||||
if (license_request_signature.empty()) {
|
||||
LOGE(
|
||||
"CdmLicense::PrepareKeyUpdateRequest: empty license request"
|
||||
" signature");
|
||||
return false;
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
// Put serialize license request and signature together
|
||||
@@ -576,7 +577,7 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
|
||||
|
||||
signed_message.SerializeToString(signed_request);
|
||||
*server_url = server_url_;
|
||||
return true;
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
@@ -636,16 +637,16 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
// Extract mac key
|
||||
std::string mac_key_iv;
|
||||
std::string mac_key;
|
||||
if (license.policy().can_renew()) {
|
||||
for (int i = 0; i < license.key_size(); ++i) {
|
||||
if (license.key(i).type() == License_KeyContainer::SIGNING) {
|
||||
mac_key_iv.assign(license.key(i).iv());
|
||||
for (int i = 0; i < license.key_size(); ++i) {
|
||||
if (license.key(i).type() == License_KeyContainer::SIGNING) {
|
||||
mac_key_iv.assign(license.key(i).iv());
|
||||
|
||||
// Strip off PKCS#5 padding
|
||||
mac_key.assign(license.key(i).key().data(), MAC_KEY_SIZE);
|
||||
}
|
||||
// Strip off PKCS#5 padding
|
||||
mac_key.assign(license.key(i).key().data(), MAC_KEY_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
if (license.policy().can_renew() ||
|
||||
(mac_key_iv.size() != 0 || mac_key.size() != 0)) {
|
||||
if (mac_key_iv.size() != KEY_IV_SIZE || mac_key.size() != MAC_KEY_SIZE) {
|
||||
LOGE(
|
||||
"CdmLicense::HandleKeyResponse: mac key/iv size error"
|
||||
|
||||
Reference in New Issue
Block a user