diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index 58f55668..acd737b7 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -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(); diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index f47e132d..8cc747f0 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -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 { diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 410b7f99..6a331251 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -407,7 +407,7 @@ CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) { return SESSION_NOT_FOUND_5; } - session->ReleaseCrypto(); + session->RemoveKeys(); return NO_ERROR; } diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index ffac81bc..62b7efcc 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -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; } diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index f53ec294..b9064af3 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -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; diff --git a/libwvdrmengine/cdm/core/test/test_printers.cpp b/libwvdrmengine/cdm/core/test/test_printers.cpp index 7a9de407..aceab685 100644 --- a/libwvdrmengine/cdm/core/test/test_printers.cpp +++ b/libwvdrmengine/cdm/core/test/test_printers.cpp @@ -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; diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 8d50d172..4e7c3bb0 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -272,7 +272,8 @@ CdmResponseType WvContentDecryptionModule::GetSecureStopIds( const CdmIdentifier& identifier, std::vector* 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) { diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 05f71f24..c121fcbf 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -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 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_)); } diff --git a/libwvdrmengine/include/WVErrors.h b/libwvdrmengine/include/WVErrors.h index 9d06d7b5..f8ce49e1 100644 --- a/libwvdrmengine/include/WVErrors.h +++ b/libwvdrmengine/include/WVErrors.h @@ -263,11 +263,14 @@ enum { kRemoveUsageInfoError1 = ERROR_DRM_VENDOR_MIN + 274, kRemoveUsageInfoError2 = ERROR_DRM_VENDOR_MIN + 275, kRemoveUsageInfoError3 = ERROR_DRM_VENDOR_MIN + 276, - kGetProvisioningError = ERROR_DRM_VENDOR_MIN + 277, + kInsufficientCryptoResources6 = ERROR_DRM_VENDOR_MIN + 277, + kNotAnEntitlementSession = ERROR_DRM_VENDOR_MIN + 278, + kLoadEntitledContentKeysError = ERROR_DRM_VENDOR_MIN + 279, + kGetProvisioningError = ERROR_DRM_VENDOR_MIN + 280, // This should always follow the last error code. // The offset value should be updated each time a new error code is added. - kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 277, + kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 280, // Used by crypto test mode kErrorTestMode = ERROR_DRM_VENDOR_MAX, diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h index 78105e14..9633561b 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -24,6 +24,7 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::NEED_KEY: case wvcdm::DECRYPT_NOT_READY: case wvcdm::KEY_NOT_FOUND_IN_SESSION: + case wvcdm::NO_MATCHING_ENTITLEMENT_KEY: return android::ERROR_DRM_NO_LICENSE; case wvcdm::NEED_PROVISIONING: return android::ERROR_DRM_NOT_PROVISIONED; @@ -225,6 +226,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::SESSION_NOT_FOUND_8: case wvcdm::SESSION_NOT_FOUND_9: case wvcdm::SESSION_NOT_FOUND_10: + case wvcdm::SESSION_NOT_FOUND_17: + case wvcdm::SESSION_NOT_FOUND_18: return android::ERROR_DRM_SESSION_NOT_OPENED; case wvcdm::SESSION_KEYS_NOT_FOUND: return kSessionKeysNotFound; @@ -507,8 +510,15 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { return kRemoveUsageInfoError2; case wvcdm::REMOVE_USAGE_INFO_ERROR_3: return kRemoveUsageInfoError3; + case wvcdm::INSUFFICIENT_CRYPTO_RESOURCES_6: + return kInsufficientCryptoResources6; + case wvcdm::NOT_AN_ENTITLEMENT_SESSION: + return kNotAnEntitlementSession; + case wvcdm::LOAD_ENTITLED_CONTENT_KEYS_ERROR: + return kLoadEntitledContentKeysError; case wvcdm::GET_PROVISIONING_METHOD_ERROR: return kGetProvisioningError; + } // Return here instead of as a default case so that the compiler will warn diff --git a/libwvdrmengine/include_hidl/mapErrors-inl.h b/libwvdrmengine/include_hidl/mapErrors-inl.h index fabdd6ea..71c83aa3 100644 --- a/libwvdrmengine/include_hidl/mapErrors-inl.h +++ b/libwvdrmengine/include_hidl/mapErrors-inl.h @@ -27,6 +27,7 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::DECRYPT_NOT_READY: case wvcdm::KEY_NOT_FOUND_IN_SESSION: case wvcdm::NEED_KEY: + case wvcdm::NO_MATCHING_ENTITLEMENT_KEY: return Status::ERROR_DRM_NO_LICENSE; case wvcdm::NEED_PROVISIONING: @@ -53,6 +54,8 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::SESSION_NOT_FOUND_8: case wvcdm::SESSION_NOT_FOUND_9: case wvcdm::SESSION_NOT_FOUND_10: + case wvcdm::SESSION_NOT_FOUND_17: + case wvcdm::SESSION_NOT_FOUND_18: return Status::ERROR_DRM_SESSION_NOT_OPENED; case wvcdm::DECRYPT_ERROR: @@ -290,6 +293,9 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::REMOVE_USAGE_INFO_ERROR_1: case wvcdm::REMOVE_USAGE_INFO_ERROR_2: case wvcdm::REMOVE_USAGE_INFO_ERROR_3: + case wvcdm::INSUFFICIENT_CRYPTO_RESOURCES_6: + case wvcdm::NOT_AN_ENTITLEMENT_SESSION: + case wvcdm::LOAD_ENTITLED_CONTENT_KEYS_ERROR: case wvcdm::GET_PROVISIONING_METHOD_ERROR: ALOGW("Returns UNKNOWN error for legacy status: %d", res); return Status::ERROR_DRM_UNKNOWN;