Correct exception returned after RemoveKeys is called.

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

RemoveKeys now resets associated crypto and policy resources,
rather than just closing the crypto session. This results in a
MediaCodec.CryptoException with error code ERROR_NO_KEY
rather than ERROR_SESSION_NOT_OPENED, if decrypt is called
afterwards.

Error SESSION_NOT_FOUND_FOR_DECRYPT is made unique. Error codes
were also synchonized between various branches in the widevine repo.

Bug: 77304819
Test: WV unit/integration tests, VtsHalDrmV1_0Target tests
Change-Id: I6cba2a3e1ce466d58c7727cde2d8f81d9503d655
This commit is contained in:
Rahul Frias
2018-04-07 02:05:07 -07:00
parent f0cd22d4f4
commit d102f8a4d2
11 changed files with 89 additions and 15 deletions

View File

@@ -145,12 +145,10 @@ class CdmSession {
virtual CdmUsageSupportType get_usage_support_type()
{ return usage_support_type_; }
// ReleaseCrypto() - Closes the underlying crypto session but leaves this
// object alive. It is invalid to call any method that requires a crypto
// session after calling this. Since calling this renders this object mostly
// useless, it is preferable to simply delete this object (which will also
// release the underlying crypto session) rather than call this method.
virtual CdmResponseType ReleaseCrypto();
// This method will remove keys by resetting crypto resources and
// policy information. This renders the session mostly useless and it is
// preferable to simply delete this object rather than call this method.
virtual CdmResponseType RemoveKeys();
// Delete current license and matching usage record
bool DeleteLicense();

View File

@@ -324,7 +324,13 @@ enum CdmResponseType {
REMOVE_USAGE_INFO_ERROR_1 = 282,
REMOVE_USAGE_INFO_ERROR_2 = 283,
REMOVE_USAGE_INFO_ERROR_3 = 284,
GET_PROVISIONING_METHOD_ERROR = 285,
INSUFFICIENT_CRYPTO_RESOURCES_6 = 285,
NOT_AN_ENTITLEMENT_SESSION = 286,
NO_MATCHING_ENTITLEMENT_KEY = 287,
LOAD_ENTITLED_CONTENT_KEYS_ERROR = 288,
GET_PROVISIONING_METHOD_ERROR = 289,
SESSION_NOT_FOUND_17 = 290,
SESSION_NOT_FOUND_18 = 291,
};
enum CdmKeyStatus {

View File

@@ -407,7 +407,7 @@ CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
return SESSION_NOT_FOUND_5;
}
session->ReleaseCrypto();
session->RemoveKeys();
return NO_ERROR;
}

View File

@@ -875,8 +875,18 @@ bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
usage_entry_number_);
}
CdmResponseType CdmSession::ReleaseCrypto() {
crypto_session_->Close();
CdmResponseType CdmSession::RemoveKeys() {
CdmResponseType sts;
crypto_session_.reset(new CryptoSession(crypto_metrics_));
// Ignore errors
M_TIME(
sts = crypto_session_->Open(requested_security_level_),
crypto_metrics_,
crypto_session_open_,
sts,
requested_security_level_);
policy_engine_.reset(new PolicyEngine(
session_id_, NULL, crypto_session_.get()));
return NO_ERROR;
}

View File

@@ -1145,7 +1145,7 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
case OEMCrypto_ERROR_KEY_EXPIRED:
return NEED_KEY;
case OEMCrypto_ERROR_INVALID_SESSION:
return SESSION_NOT_FOUND_FOR_DECRYPT;
return SESSION_NOT_FOUND_17;
case OEMCrypto_ERROR_DECRYPT_FAILED:
case OEMCrypto_ERROR_UNKNOWN_FAILURE:
return DECRYPT_ERROR;

View File

@@ -581,8 +581,22 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case REMOVE_USAGE_INFO_ERROR_3: *os << "REMOVE_USAGE_INFO_ERROR_3";
break;
case INSUFFICIENT_CRYPTO_RESOURCES_6:
*os << "INSUFFICIENT_CRYPTO_RESOURCES_6";
break;
case NOT_AN_ENTITLEMENT_SESSION: *os << "NOT_AN_ENTITLEMENT_SESSION";
break;
case NO_MATCHING_ENTITLEMENT_KEY: *os << "NO_MATCHING_ENTITLEMENT_KEY";
break;
case LOAD_ENTITLED_CONTENT_KEYS_ERROR:
*os << "LOAD_ENTITLED_CONTENT_KEYS_ERROR";
break;
case GET_PROVISIONING_METHOD_ERROR: *os << "GET_PROVISIONING_METHOD_ERROR";
break;
case SESSION_NOT_FOUND_17: *os << "SESSION_NOT_FOUND_17";
break;
case SESSION_NOT_FOUND_18: *os << "SESSION_NOT_FOUND_18";
break;
default:
*os << "Unknown CdmResponseType";
break;

View File

@@ -272,7 +272,8 @@ CdmResponseType WvContentDecryptionModule::GetSecureStopIds(
const CdmIdentifier& identifier,
std::vector<CdmSecureStopId>* ssids) {
if (ssids == NULL) {
LOGE("WvContentDecryptionModule::Decrypt: ssid destination not provided");
LOGE("WvContentDecryptionModule::GetSecureStopIds: ssid destination not "
"provided");
return PARAMETER_NULL;
}
@@ -294,7 +295,10 @@ CdmResponseType WvContentDecryptionModule::Decrypt(
// First find the CdmEngine that has the given session_id. If we are using
// key sharing, the shared session will still be in the same CdmEngine.
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
if (!cdm_engine) return SESSION_NOT_FOUND_FOR_DECRYPT;
if (!cdm_engine) {
LOGE("WvContentDecryptionModule::Decrypt: not found");
return SESSION_NOT_FOUND_18;
}
CdmSessionId local_session_id = session_id;
if (validate_key_id && Properties::GetSessionSharingId(session_id) != 0) {

View File

@@ -2485,7 +2485,30 @@ TEST_F(WvCdmRequestLicenseTest, RemoveKeys) {
&session_id_));
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, g_client_auth);
SubSampleInfo* data = &single_encrypted_sub_sample;
std::vector<uint8_t> decrypt_buffer(data->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&data->key_id, &data->encrypt_data.front(), data->encrypt_data.size(),
&data->iv, data->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = data->is_encrypted;
decryption_parameters.is_secure = data->is_secure;
decryption_parameters.subsample_flags = data->subsample_flags;
// Verify that we can decrypt a subsample
EXPECT_EQ(NO_ERROR,
decryptor_.Decrypt(session_id_, data->validate_key_id,
decryption_parameters));
EXPECT_TRUE(std::equal(data->decrypt_data.begin(), data->decrypt_data.end(),
decrypt_buffer.begin()));
// Verify that decryption of a subsample fails after the keys are removed
ASSERT_EQ(NO_ERROR, decryptor_.RemoveKeys(session_id_));
decrypt_buffer.assign(data->encrypt_data.size(), 0);
EXPECT_EQ(NEED_KEY,
decryptor_.Decrypt(session_id_, data->validate_key_id,
decryption_parameters));
ASSERT_EQ(NO_ERROR, decryptor_.CloseSession(session_id_));
}