diff --git a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h index 7fb97e27..33b1aff0 100644 --- a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h @@ -14,6 +14,7 @@ #include #include +#include #include "OEMCryptoCENC.h" #include "WVGenericCryptoInterface.h" @@ -396,9 +397,46 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin, android::Mutex mLock; }; + class CryptoSessionMap { + public: + std::map> clear() { + std::unique_lock auto_lock(mLock); + auto copy = mMap; + mMap.clear(); + return copy; + } + + std::shared_ptr get(const CdmSessionId& sid) { + std::unique_lock auto_lock(mLock); + if (mMap.count(sid)) { + return mMap[sid]; + } + return nullptr; + } + + bool empty() { + std::unique_lock auto_lock(mLock); + return mMap.empty(); + } + + void erase(const CdmSessionId& sid) { + std::unique_lock auto_lock(mLock); + mMap.erase(sid); + } + + void insert(const CdmSessionId& sid, OEMCrypto_SESSION osid) { + std::unique_lock auto_lock(mLock); + mMap[sid] = std::make_shared(osid); + } + + private: + std::mutex mLock; + std::map> mMap; + }; + android::sp const mCDM; WVGenericCryptoInterface* mCrypto; - std::map mCryptoSessions; + CryptoSessionMap mCryptoSessions; std::shared_ptr<::aidl::android::hardware::drm::IDrmPluginListener> mListener; std::string mProvisioningServiceCertificate; diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index c984eff3..26887da3 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -48,6 +48,7 @@ namespace hardware { namespace drm { namespace widevine { +using std::shared_ptr; using std::string; using std::vector; @@ -171,15 +172,18 @@ WVDrmPlugin::~WVDrmPlugin() { } void WVDrmPlugin::Close() { - typedef std::map::iterator mapIterator; - for (mapIterator iter = mCryptoSessions.begin(); - iter != mCryptoSessions.end(); ++iter) { + typedef std::map>::iterator mapIterator; + auto cryptoSessions = mCryptoSessions.clear(); + for (mapIterator iter = cryptoSessions.begin(); + iter != cryptoSessions.end(); ++iter) { CdmResponseType res = mCDM->CloseSession(iter->first); if (!isCdmResponseTypeSuccess(res)) { ALOGE("Failed to close session while destroying WVDrmPlugin"); } } - mCryptoSessions.clear(); + // clear local copy of cryptoSessions map + cryptoSessions.clear(); + if (mCdmIdentifierBuilder.is_sealed()) { CdmIdentifier identifier; auto status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier); @@ -221,7 +225,7 @@ WvStatus WVDrmPlugin::openSessionCommon(vector& sessionId) { info.count(wvcdm::QUERY_KEY_OEMCRYPTO_SESSION_ID)) { OEMCrypto_SESSION oecSessionId = std::stoul(info[wvcdm::QUERY_KEY_OEMCRYPTO_SESSION_ID]); - mCryptoSessions[cdmSessionId] = CryptoSession(oecSessionId); + mCryptoSessions.insert(cdmSessionId, oecSessionId); success = true; } else { ALOGE("Unable to query key control info."); @@ -1223,7 +1227,7 @@ Status WVDrmPlugin::unprovisionDevice() { std::string _value(in_value.c_str()); if (name == "securityLevel") { - if (mCryptoSessions.size() == 0) { + if (mCryptoSessions.empty()) { if (_value == wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3.c_str()) { mPropertySet.set_security_level(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3); } else if (_value == wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1.c_str()) { @@ -1263,7 +1267,7 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(Status::BAD_VALUE); } } else if (name == "sessionSharing") { - if (mCryptoSessions.size() == 0) { + if (mCryptoSessions.empty()) { if (_value == kEnable) { mPropertySet.set_is_session_sharing_enabled(true); } else if (_value == kDisable) { @@ -1278,7 +1282,7 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } } else if (name == "appId") { - if (mCryptoSessions.size() == 0) { + if (mCryptoSessions.empty()) { mPropertySet.set_app_id(_value.c_str()); } else { ALOGE("App tried to set the application id while sessions are opened."); @@ -1286,7 +1290,7 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } } else if (name == "origin") { - if (mCryptoSessions.size() != 0) { + if (!mCryptoSessions.empty()) { ALOGE("App tried to set the origin while sessions are opened."); ALOGW("Returns UNKNOWN error for legacy status kErrorSessionIsOpen"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); @@ -1414,14 +1418,13 @@ Status WVDrmPlugin::unprovisionDevice() { std::string algo(in_algorithm.c_str()); CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { + shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); + if (cryptoSession == nullptr) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - if (algo == "AES/CBC/NoPadding") { - cryptoSession.setCipherAlgorithm(OEMCrypto_AES_CBC_128_NO_PADDING); + cryptoSession->setCipherAlgorithm(OEMCrypto_AES_CBC_128_NO_PADDING); } else { return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); } @@ -1437,14 +1440,13 @@ Status WVDrmPlugin::unprovisionDevice() { std::string algo(in_algorithm.c_str()); CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { + shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); + if (cryptoSession == nullptr) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - if (algo == "HmacSHA256") { - cryptoSession.setMacAlgorithm(OEMCrypto_HMAC_SHA256); + cryptoSession->setMacAlgorithm(OEMCrypto_HMAC_SHA256); } else { return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); } @@ -1461,18 +1463,17 @@ Status WVDrmPlugin::unprovisionDevice() { *_aidl_return = output; CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { + const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); + if (cryptoSession == nullptr) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.cipherAlgorithm() == kInvalidCryptoAlgorithm) { + if (cryptoSession->cipherAlgorithm() == kInvalidCryptoAlgorithm) { ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), + OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), in_keyId.data(), in_keyId.size()); if (res != OEMCrypto_SUCCESS) { @@ -1483,9 +1484,9 @@ Status WVDrmPlugin::unprovisionDevice() { output.resize(in_input.size()); Status status = Status::OK; - res = mCrypto->encrypt(cryptoSession.oecSessionId(), in_input.data(), + res = mCrypto->encrypt(cryptoSession->oecSessionId(), in_input.data(), in_input.size(), in_iv.data(), - cryptoSession.cipherAlgorithm(), output.data()); + cryptoSession->cipherAlgorithm(), output.data()); *_aidl_return = output; if (res == OEMCrypto_SUCCESS) { @@ -1506,18 +1507,17 @@ Status WVDrmPlugin::unprovisionDevice() { *_aidl_return = output; CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { + const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); + if (cryptoSession == nullptr) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.cipherAlgorithm() == kInvalidCryptoAlgorithm) { + if (cryptoSession->cipherAlgorithm() == kInvalidCryptoAlgorithm) { ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), + OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), in_keyId.data(), in_keyId.size()); if (res != OEMCrypto_SUCCESS) { @@ -1528,9 +1528,9 @@ Status WVDrmPlugin::unprovisionDevice() { output.resize(in_input.size()); Status status = Status::OK; - res = mCrypto->decrypt(cryptoSession.oecSessionId(), in_input.data(), + res = mCrypto->decrypt(cryptoSession->oecSessionId(), in_input.data(), in_input.size(), in_iv.data(), - cryptoSession.cipherAlgorithm(), output.data()); + cryptoSession->cipherAlgorithm(), output.data()); *_aidl_return = output; if (res == OEMCrypto_SUCCESS) { @@ -1550,18 +1550,17 @@ Status WVDrmPlugin::unprovisionDevice() { *_aidl_return = signature; CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { + const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); + if (cryptoSession == nullptr) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.macAlgorithm() == kInvalidCryptoAlgorithm) { + if (cryptoSession->macAlgorithm() == kInvalidCryptoAlgorithm) { ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), + OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), in_keyId.data(), in_keyId.size()); if (res != OEMCrypto_SUCCESS) { @@ -1571,8 +1570,8 @@ Status WVDrmPlugin::unprovisionDevice() { size_t signatureSize = 0; - res = mCrypto->sign(cryptoSession.oecSessionId(), in_message.data(), - in_message.size(), cryptoSession.macAlgorithm(), nullptr, + res = mCrypto->sign(cryptoSession->oecSessionId(), in_message.data(), + in_message.size(), cryptoSession->macAlgorithm(), nullptr, &signatureSize); Status status = Status::OK; @@ -1591,8 +1590,8 @@ Status WVDrmPlugin::unprovisionDevice() { signature.resize(signatureSize); - res = mCrypto->sign(cryptoSession.oecSessionId(), in_message.data(), - in_message.size(), cryptoSession.macAlgorithm(), + res = mCrypto->sign(cryptoSession->oecSessionId(), in_message.data(), + in_message.size(), cryptoSession->macAlgorithm(), signature.data(), &signatureSize); *_aidl_return = signature; @@ -1614,18 +1613,17 @@ Status WVDrmPlugin::unprovisionDevice() { *_aidl_return = match; CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { + const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); + if (cryptoSession == nullptr) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.macAlgorithm() == kInvalidCryptoAlgorithm) { + if (cryptoSession->macAlgorithm() == kInvalidCryptoAlgorithm) { ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), + OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), in_keyId.data(), in_keyId.size()); if (res != OEMCrypto_SUCCESS) { @@ -1633,8 +1631,8 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(mapAndNotifyOfOEMCryptoResult(in_sessionId, res)); } - res = mCrypto->verify(cryptoSession.oecSessionId(), in_message.data(), - in_message.size(), cryptoSession.macAlgorithm(), + res = mCrypto->verify(cryptoSession->oecSessionId(), in_message.data(), + in_message.size(), cryptoSession->macAlgorithm(), in_signature.data(), in_signature.size()); Status status = Status::OK; @@ -1703,7 +1701,7 @@ Status WVDrmPlugin::unprovisionDevice() { } ::ndk::ScopedAStatus WVDrmPlugin::setListener( - const std::shared_ptr<::aidl::android::hardware::drm::IDrmPluginListener>& + const shared_ptr<::aidl::android::hardware::drm::IDrmPluginListener>& in_listener) { mListener = in_listener; ::ndk::ScopedAStatus _aidl_status;