diff --git a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h index 33b1aff0..1dcebcd3 100644 --- a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h @@ -194,36 +194,44 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin, // is cleared right before plugin is destructed. wvutil::LoggingUidSetter mLoggingUidSetter; - struct CryptoSession { + class SessionInfo { public: - CryptoSession() - : mOecSessionId(-1), - mCipherAlgorithm(kInvalidCryptoAlgorithm), - mMacAlgorithm(kInvalidCryptoAlgorithm) {} + SessionInfo() {} - CryptoSession(OEMCrypto_SESSION sessionId) - : mOecSessionId(sessionId), - mCipherAlgorithm(kInvalidCryptoAlgorithm), - mMacAlgorithm(kInvalidCryptoAlgorithm) {} + SessionInfo(OEMCrypto_SESSION sessionId) : mOecSessionId(sessionId) {} OEMCrypto_SESSION oecSessionId() const { return mOecSessionId; } - OEMCrypto_Algorithm cipherAlgorithm() const { return mCipherAlgorithm; } - - void setCipherAlgorithm(OEMCrypto_Algorithm newAlgorithm) { - mCipherAlgorithm = newAlgorithm; + wvcdm::CdmEncryptionAlgorithm getEncryptionAlgorithm() const { + return mEncryptionAlgorithm; } - OEMCrypto_Algorithm macAlgorithm() const { return mMacAlgorithm; } + bool hasEncryptionAlgorithm() const { + return mEncryptionAlgorithm != wvcdm::kEncryptionAlgorithmUnknown; + } - void setMacAlgorithm(OEMCrypto_Algorithm newAlgorithm) { - mMacAlgorithm = newAlgorithm; + void setEncryptionAlgorithm(wvcdm::CdmEncryptionAlgorithm newAlgorithm) { + mEncryptionAlgorithm = newAlgorithm; + } + + wvcdm::CdmSigningAlgorithm getSigningAlgorithm() const { + return mSigningAlgorithm; + } + + bool hasSigningAlgorithm() const { + return mSigningAlgorithm != wvcdm::kSigningAlgorithmUnknown; + } + + void setSigningAlgorithm(wvcdm::CdmSigningAlgorithm newAlgorithm) { + mSigningAlgorithm = newAlgorithm; } private: - OEMCrypto_SESSION mOecSessionId; - OEMCrypto_Algorithm mCipherAlgorithm; - OEMCrypto_Algorithm mMacAlgorithm; + OEMCrypto_SESSION mOecSessionId = -1; + wvcdm::CdmEncryptionAlgorithm mEncryptionAlgorithm = + wvcdm::kEncryptionAlgorithmUnknown; + wvcdm::CdmSigningAlgorithm mSigningAlgorithm = + wvcdm::kSigningAlgorithmUnknown; }; class WVClientPropertySet : public wvcdm::CdmClientPropertySet { @@ -397,24 +405,33 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin, android::Mutex mLock; }; - class CryptoSessionMap { + class SessionInfoMap { public: - std::map> clear() { + void clear() { std::unique_lock auto_lock(mLock); - auto copy = mMap; mMap.clear(); - return copy; } - std::shared_ptr get(const CdmSessionId& sid) { + std::vector getKeysAndClear() { std::unique_lock auto_lock(mLock); - if (mMap.count(sid)) { - return mMap[sid]; + std::vector keys; + for (const auto pair : mMap) { + keys.push_back(pair.first); + } + mMap.clear(); + return keys; + } + + std::shared_ptr get(const CdmSessionId& sid) const { + std::unique_lock auto_lock(mLock); + const auto it = mMap.find(sid); + if (it != mMap.end()) { + return it->second; } return nullptr; } - bool empty() { + bool empty() const { std::unique_lock auto_lock(mLock); return mMap.empty(); } @@ -426,17 +443,17 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin, void insert(const CdmSessionId& sid, OEMCrypto_SESSION osid) { std::unique_lock auto_lock(mLock); - mMap[sid] = std::make_shared(osid); + mMap[sid] = std::make_shared(osid); } private: - std::mutex mLock; - std::map> mMap; + mutable std::mutex mLock; + std::map> mMap; }; android::sp const mCDM; WVGenericCryptoInterface* mCrypto; - CryptoSessionMap mCryptoSessions; + SessionInfoMap mSessionInfoMap; std::shared_ptr<::aidl::android::hardware::drm::IDrmPluginListener> mListener; std::string mProvisioningServiceCertificate; diff --git a/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h b/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h index e7349c4d..a882dca6 100644 --- a/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h +++ b/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h @@ -21,48 +21,6 @@ class WVGenericCryptoInterface { WVGenericCryptoInterface() {} virtual ~WVGenericCryptoInterface() {} - virtual OEMCryptoResult selectKey(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length) { - return OEMCrypto_SelectKey(session, key_id, key_id_length, - OEMCrypto_CipherMode_CBCS); - } - - virtual OEMCryptoResult encrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - return OEMCrypto_Generic_Encrypt_V17(session, in_buffer, buffer_length, iv, - algorithm, out_buffer); - } - - virtual OEMCryptoResult decrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - return OEMCrypto_Generic_Decrypt_V17(session, in_buffer, buffer_length, iv, - algorithm, out_buffer); - } - - virtual OEMCryptoResult sign(OEMCrypto_SESSION session, - const uint8_t* in_buffer, size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, size_t* signature_length) { - return OEMCrypto_Generic_Sign_V17(session, in_buffer, buffer_length, algorithm, - signature, signature_length); - } - - virtual OEMCryptoResult verify(OEMCrypto_SESSION session, - const uint8_t* in_buffer, size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length) { - return OEMCrypto_Generic_Verify_V17(session, in_buffer, buffer_length, - algorithm, signature, signature_length); - } - virtual OEMCryptoResult signRSA(const uint8_t* wrapped_rsa_key, size_t wrapped_rsa_key_length, const uint8_t* message, size_t message_length, @@ -76,15 +34,6 @@ class WVGenericCryptoInterface { wrapped_rsa_key, wrapped_rsa_key_length); } - virtual OEMCryptoResult generateRSASignature( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - uint8_t* signature, size_t* signature_length, - RSA_Padding_Scheme padding_scheme) { - return OEMCrypto_GenerateRSASignature(session, message, message_length, - signature, signature_length, - padding_scheme); - } - private: DISALLOW_EVIL_CONSTRUCTORS(WVGenericCryptoInterface); }; diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index d7e73717..4d31e72b 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -162,7 +162,6 @@ WVDrmPlugin::WVDrmPlugin(const android::sp& cdm, : mCdmIdentifierBuilder(useSpoid, *this, appPackageName), mCDM(cdm), mCrypto(crypto), - mCryptoSessions(), mAppPackageName(appPackageName) { Terminator::Register(this); } @@ -174,17 +173,14 @@ WVDrmPlugin::~WVDrmPlugin() { } void WVDrmPlugin::Close() { - typedef std::map>::iterator mapIterator; - auto cryptoSessions = mCryptoSessions.clear(); - for (mapIterator iter = cryptoSessions.begin(); - iter != cryptoSessions.end(); ++iter) { - CdmResponseType res = mCDM->CloseSession(iter->first); + const auto sessionKeys = mSessionInfoMap.getKeysAndClear(); + for (const auto& sessionKey : sessionKeys) { + const CdmResponseType res = mCDM->CloseSession(sessionKey); if (!isCdmResponseTypeSuccess(res)) { - ALOGE("Failed to close session while destroying WVDrmPlugin"); + ALOGE("Failed to close session while destroying WVDrmPlugin: sid = %s", + sessionKey.c_str()); } } - // clear local copy of cryptoSessions map - cryptoSessions.clear(); if (mCdmIdentifierBuilder.is_sealed()) { CdmIdentifier identifier; @@ -219,15 +215,15 @@ WvStatus WVDrmPlugin::openSessionCommon(vector& sessionId) { bool success = false; - // Construct a CryptoSession + // Construct a SessionInfo CdmQueryMap info; res = mCDM->QueryOemCryptoSessionId(cdmSessionId, &info); if (isCdmResponseTypeSuccess(res) && info.count(wvcdm::QUERY_KEY_OEMCRYPTO_SESSION_ID)) { - OEMCrypto_SESSION oecSessionId = + const OEMCrypto_SESSION oecSessionId = std::stoul(info[wvcdm::QUERY_KEY_OEMCRYPTO_SESSION_ID]); - mCryptoSessions.insert(cdmSessionId, oecSessionId); + mSessionInfoMap.insert(cdmSessionId, oecSessionId); success = true; } else { ALOGE("Unable to query key control info."); @@ -325,7 +321,7 @@ SecurityLevel WVDrmPlugin::mapSecurityLevel(const std::string& level) { } CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); CdmResponseType res = mCDM->CloseSession(cdmSessionId); - mCryptoSessions.erase(cdmSessionId); + mSessionInfoMap.erase(cdmSessionId); if (!isCdmResponseTypeSuccess(res)) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } @@ -1223,7 +1219,7 @@ Status WVDrmPlugin::unprovisionDevice() { std::string _value(in_value.c_str()); if (name == "securityLevel") { - if (mCryptoSessions.empty()) { + if (mSessionInfoMap.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 +1259,7 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(Status::BAD_VALUE); } } else if (name == "sessionSharing") { - if (mCryptoSessions.empty()) { + if (mSessionInfoMap.empty()) { if (_value == kEnable) { mPropertySet.set_is_session_sharing_enabled(true); } else if (_value == kDisable) { @@ -1278,7 +1274,7 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } } else if (name == "appId") { - if (mCryptoSessions.empty()) { + if (mSessionInfoMap.empty()) { mPropertySet.set_app_id(_value.c_str()); } else { ALOGE("App tried to set the application id while sessions are opened."); @@ -1286,7 +1282,7 @@ Status WVDrmPlugin::unprovisionDevice() { return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } } else if (name == "origin") { - if (!mCryptoSessions.empty()) { + if (!mSessionInfoMap.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); @@ -1408,46 +1404,42 @@ Status WVDrmPlugin::unprovisionDevice() { ::ndk::ScopedAStatus WVDrmPlugin::setCipherAlgorithm( const vector& in_sessionId, const std::string& in_algorithm) { - if (in_sessionId.size() == 0 || in_algorithm.size() == 0) { + if (in_sessionId.empty() || in_algorithm.empty()) { return toNdkScopedAStatus(Status::BAD_VALUE); } - std::string algo(in_algorithm.c_str()); + const std::string algo(in_algorithm.c_str()); - CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); - if (cryptoSession == nullptr) { + const CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); + shared_ptr sessionInfo = mSessionInfoMap.get(cdmSessionId); + if (!sessionInfo) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } if (algo == "AES/CBC/NoPadding") { - cryptoSession->setCipherAlgorithm(OEMCrypto_AES_CBC_128_NO_PADDING); - } else { - return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); + sessionInfo->setEncryptionAlgorithm(wvcdm::kEncryptionAlgorithmAesCbc128); + return toNdkScopedAStatus(Status::OK); } - - return toNdkScopedAStatus(Status::OK); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); } ::ndk::ScopedAStatus WVDrmPlugin::setMacAlgorithm( const vector& in_sessionId, const std::string& in_algorithm) { - if (in_sessionId.size() == 0 || in_algorithm.size() == 0) { + if (in_sessionId.empty() || in_algorithm.empty()) { return toNdkScopedAStatus(Status::BAD_VALUE); } - std::string algo(in_algorithm.c_str()); + const std::string algo(in_algorithm.c_str()); - CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); - if (cryptoSession == nullptr) { + const CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); + shared_ptr sessionInfo = mSessionInfoMap.get(cdmSessionId); + if (!sessionInfo) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } if (algo == "HmacSHA256") { - cryptoSession->setMacAlgorithm(OEMCrypto_HMAC_SHA256); - } else { - return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); + sessionInfo->setSigningAlgorithm(wvcdm::kSigningAlgorithmHmacSha256); + return toNdkScopedAStatus(Status::OK); } - - return toNdkScopedAStatus(Status::OK); + return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE); } ::ndk::ScopedAStatus WVDrmPlugin::encrypt(const vector& in_sessionId, @@ -1455,43 +1447,32 @@ Status WVDrmPlugin::unprovisionDevice() { const vector& in_input, const vector& in_iv, vector* _aidl_return) { - vector output; - - *_aidl_return = output; - CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); - if (cryptoSession == nullptr) { + _aidl_return->clear(); + const CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); + shared_ptr sessionInfo = mSessionInfoMap.get(cdmSessionId); + if (!sessionInfo) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - if (cryptoSession->cipherAlgorithm() == kInvalidCryptoAlgorithm) { - ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); + if (!sessionInfo->hasEncryptionAlgorithm()) { + ALOGW("Encryption algorithm not set"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), - in_keyId.data(), in_keyId.size()); + std::string output; + const CdmResponseType result = mCDM->GenericEncrypt( + cdmSessionId, KeyId(in_keyId.begin(), in_keyId.end()), + std::string(in_input.begin(), in_input.end()), + std::string(in_iv.begin(), in_iv.end()), + sessionInfo->getEncryptionAlgorithm(), &output); - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return toNdkScopedAStatus(mapAndNotifyOfOEMCryptoResult(in_sessionId, res)); + if (!result.IsOk()) { + ALOGE("Generic encryption failed: %s", result.ToString().c_str()); + return toNdkScopedAStatus( + mapAndNotifyOfCdmResponseType(in_sessionId, result)); } - - output.resize(in_input.size()); - - Status status = Status::OK; - res = mCrypto->encrypt(cryptoSession->oecSessionId(), in_input.data(), - in_input.size(), in_iv.data(), - cryptoSession->cipherAlgorithm(), output.data()); - - *_aidl_return = output; - if (res == OEMCrypto_SUCCESS) { - status = Status::OK; - } else { - ALOGE("OEMCrypto_Generic_Encrypt failed with %u", res); - status = mapAndNotifyOfOEMCryptoResult(in_sessionId, res); - } - return toNdkScopedAStatus(status); + _aidl_return->assign(output.begin(), output.end()); + return toNdkScopedAStatus(Status::OK); } ::ndk::ScopedAStatus WVDrmPlugin::decrypt(const vector& in_sessionId, @@ -1499,105 +1480,63 @@ Status WVDrmPlugin::unprovisionDevice() { const vector& in_input, const vector& in_iv, vector* _aidl_return) { - vector output; - *_aidl_return = output; - - CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); - if (cryptoSession == nullptr) { + _aidl_return->clear(); + const CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); + shared_ptr sessionInfo = mSessionInfoMap.get(cdmSessionId); + if (!sessionInfo) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - if (cryptoSession->cipherAlgorithm() == kInvalidCryptoAlgorithm) { - ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); + if (!sessionInfo->hasEncryptionAlgorithm()) { + ALOGW("Encryption algorithm not set"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), - in_keyId.data(), in_keyId.size()); + std::string output; + const CdmResponseType result = mCDM->GenericDecrypt( + cdmSessionId, KeyId(in_keyId.begin(), in_keyId.end()), + std::string(in_input.begin(), in_input.end()), + std::string(in_iv.begin(), in_iv.end()), + sessionInfo->getEncryptionAlgorithm(), &output); - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return toNdkScopedAStatus(mapAndNotifyOfOEMCryptoResult(in_sessionId, res)); + if (!result.IsOk()) { + ALOGE("Generic decryption failed: %s", result.ToString().c_str()); + return toNdkScopedAStatus( + mapAndNotifyOfCdmResponseType(in_sessionId, result)); } - - output.resize(in_input.size()); - - Status status = Status::OK; - res = mCrypto->decrypt(cryptoSession->oecSessionId(), in_input.data(), - in_input.size(), in_iv.data(), - cryptoSession->cipherAlgorithm(), output.data()); - - *_aidl_return = output; - if (res == OEMCrypto_SUCCESS) { - status = Status::OK; - } else { - ALOGE("OEMCrypto_Generic_Decrypt failed with %u", res); - status = mapAndNotifyOfOEMCryptoResult(in_sessionId, res); - } - return toNdkScopedAStatus(status); + _aidl_return->assign(output.begin(), output.end()); + return toNdkScopedAStatus(Status::OK); } ::ndk::ScopedAStatus WVDrmPlugin::sign(const vector& in_sessionId, const vector& in_keyId, const vector& in_message, vector* _aidl_return) { - vector signature; - *_aidl_return = signature; - - CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); - if (cryptoSession == nullptr) { + _aidl_return->clear(); + const CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); + shared_ptr sessionInfo = mSessionInfoMap.get(cdmSessionId); + if (!sessionInfo) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - if (cryptoSession->macAlgorithm() == kInvalidCryptoAlgorithm) { - ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); + if (!sessionInfo->hasSigningAlgorithm()) { + ALOGW("Signing algorithm not set"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), - in_keyId.data(), in_keyId.size()); + std::string signature; + const CdmResponseType result = + mCDM->GenericSign(cdmSessionId, KeyId(in_keyId.begin(), in_keyId.end()), + std::string(in_message.begin(), in_message.end()), + sessionInfo->getSigningAlgorithm(), &signature); - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return toNdkScopedAStatus(mapAndNotifyOfOEMCryptoResult(in_sessionId, res)); + if (!result.IsOk()) { + ALOGE("Generic signature failed: %s", result.ToString().c_str()); + return toNdkScopedAStatus( + mapAndNotifyOfCdmResponseType(in_sessionId, result)); } - - size_t signatureSize = 0; - - res = mCrypto->sign(cryptoSession->oecSessionId(), in_message.data(), - in_message.size(), cryptoSession->macAlgorithm(), nullptr, - &signatureSize); - - Status status = Status::OK; - if (res != OEMCrypto_ERROR_SHORT_BUFFER) { - ALOGE( - "OEMCrypto_Generic_Sign failed with %u when requesting signature " - "size", - res); - if (res != OEMCrypto_SUCCESS) { - status = mapAndNotifyOfOEMCryptoResult(in_sessionId, res); - } else { - status = Status::ERROR_DRM_UNKNOWN; - } - return toNdkScopedAStatus(status); - } - - signature.resize(signatureSize); - - res = mCrypto->sign(cryptoSession->oecSessionId(), in_message.data(), - in_message.size(), cryptoSession->macAlgorithm(), - signature.data(), &signatureSize); - - *_aidl_return = signature; - if (res == OEMCrypto_SUCCESS) { - status = Status::OK; - } else { - ALOGE("OEMCrypto_Generic_Sign failed with %u", res); - status = mapAndNotifyOfOEMCryptoResult(in_sessionId, res); - } - return toNdkScopedAStatus(status); + _aidl_return->assign(signature.begin(), signature.end()); + return toNdkScopedAStatus(Status::OK); } ::ndk::ScopedAStatus WVDrmPlugin::verify(const vector& in_sessionId, @@ -1605,46 +1544,38 @@ Status WVDrmPlugin::unprovisionDevice() { const vector& in_message, const vector& in_signature, bool* _aidl_return) { - bool match = false; - *_aidl_return = match; - - CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); - const shared_ptr cryptoSession = mCryptoSessions.get(cdmSessionId); - if (cryptoSession == nullptr) { + *_aidl_return = false; + const CdmSessionId cdmSessionId(in_sessionId.begin(), in_sessionId.end()); + shared_ptr sessionInfo = mSessionInfoMap.get(cdmSessionId); + if (!sessionInfo) { return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED); } - if (cryptoSession->macAlgorithm() == kInvalidCryptoAlgorithm) { - ALOGW("Returns UNKNOWN error for legacy status NO_INIT"); + if (!sessionInfo->hasSigningAlgorithm()) { + ALOGW("Signing algorithm not set"); return toNdkScopedAStatus(Status::ERROR_DRM_UNKNOWN); } - OEMCryptoResult res = mCrypto->selectKey(cryptoSession->oecSessionId(), - in_keyId.data(), in_keyId.size()); + const CdmResponseType result = mCDM->GenericVerify( + cdmSessionId, KeyId(in_keyId.begin(), in_keyId.end()), + std::string(in_message.begin(), in_message.end()), + sessionInfo->getSigningAlgorithm(), + std::string(in_signature.begin(), in_signature.end())); - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return toNdkScopedAStatus(mapAndNotifyOfOEMCryptoResult(in_sessionId, res)); + if (result.IsOk()) { + *_aidl_return = true; + return toNdkScopedAStatus(Status::OK); } - res = mCrypto->verify(cryptoSession->oecSessionId(), in_message.data(), - in_message.size(), cryptoSession->macAlgorithm(), - in_signature.data(), in_signature.size()); - - Status status = Status::OK; - if (res == OEMCrypto_SUCCESS) { - match = true; - status = Status::OK; - } else if (res == OEMCrypto_ERROR_SIGNATURE_FAILURE) { - match = false; - status = Status::OK; - } else { - ALOGE("OEMCrypto_Generic_Verify failed with %u", res); - match = false; - status = mapAndNotifyOfOEMCryptoResult(in_sessionId, res); + if (result == wvcdm::UNKNOWN_ERROR && + result.oemc_result() == OEMCrypto_ERROR_SIGNATURE_FAILURE) { + // TODO(b/279245250): Use a better error code. + return toNdkScopedAStatus(Status::OK); } - *_aidl_return = match; - return toNdkScopedAStatus(status); + + ALOGE("Generic verify failed: %s", result.ToString().c_str()); + return toNdkScopedAStatus( + mapAndNotifyOfCdmResponseType(in_sessionId, result)); } ::ndk::ScopedAStatus WVDrmPlugin::signRSA(const vector& in_sessionId, diff --git a/libwvdrmengine/mediadrm/test/WVDrmPlugin_hal_test.cpp b/libwvdrmengine/mediadrm/test/WVDrmPlugin_hal_test.cpp index e1fb9163..c4cd6102 100644 --- a/libwvdrmengine/mediadrm/test/WVDrmPlugin_hal_test.cpp +++ b/libwvdrmengine/mediadrm/test/WVDrmPlugin_hal_test.cpp @@ -265,40 +265,28 @@ class MockCDM : public WvContentDecryptionModule { (const CdmIdentifier &, wvcdm::RequestedSecurityLevel, const std::string &, const std::string &), (override)); + + // Generic crypto API. + MOCK_METHOD(CdmResponseType, GenericEncrypt, + (const CdmSessionId &, const wvcdm::KeyId &, const std::string &, + const std::string &, wvcdm::CdmEncryptionAlgorithm, + std::string *)); + MOCK_METHOD(CdmResponseType, GenericDecrypt, + (const CdmSessionId &, const wvcdm::KeyId &, const std::string &, + const std::string &, wvcdm::CdmEncryptionAlgorithm, + std::string *)); + MOCK_METHOD(CdmResponseType, GenericSign, + (const CdmSessionId &, const wvcdm::KeyId &, const std::string &, + wvcdm::CdmSigningAlgorithm, std::string *)); + MOCK_METHOD(CdmResponseType, GenericVerify, + (const CdmSessionId &, const wvcdm::KeyId &, const std::string &, + wvcdm::CdmSigningAlgorithm, const std::string &)); }; class MockCrypto : public WVGenericCryptoInterface { -public: - MOCK_METHOD(OEMCryptoResult, selectKey, - (const OEMCrypto_SESSION, const uint8_t *, size_t), (override)); - - MOCK_METHOD(OEMCryptoResult, encrypt, - (OEMCrypto_SESSION, const uint8_t *, size_t, const uint8_t *, - OEMCrypto_Algorithm, uint8_t *), - (override)); - - MOCK_METHOD(OEMCryptoResult, decrypt, - (OEMCrypto_SESSION, const uint8_t *, size_t, const uint8_t *, - OEMCrypto_Algorithm, uint8_t *), - (override)); - - MOCK_METHOD(OEMCryptoResult, sign, - (OEMCrypto_SESSION, const uint8_t *, size_t, OEMCrypto_Algorithm, - uint8_t *, size_t *), - (override)); - - MOCK_METHOD(OEMCryptoResult, verify, - (OEMCrypto_SESSION, const uint8_t *, size_t, OEMCrypto_Algorithm, - const uint8_t *, size_t), - (override)); - - MOCK_METHOD(OEMCryptoResult, loadDeviceRSAKey, - (OEMCrypto_SESSION, const uint8_t *, size_t), (override)); - - MOCK_METHOD(OEMCryptoResult, generateRSASignature, - (OEMCrypto_SESSION, const uint8_t *, size_t, uint8_t *, size_t *, - RSA_Padding_Scheme), - (override)); + public: + MOCK_METHOD(OEMCryptoResult, loadDeviceRSAKey, + (OEMCrypto_SESSION, const uint8_t *, size_t), (override)); }; } // anonymous namespace @@ -1904,19 +1892,6 @@ TEST_F(WVDrmPluginHalTest, CallsGenericEncrypt) { iv.assign(ivRaw, ivRaw + KEY_IV_SIZE); std::vector output; - { - InSequence calls; - - EXPECT_CALL(mCrypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(mCrypto, encrypt(4, _, kDataSize, IsIV(ivRaw), - OEMCrypto_AES_CBC_128_NO_PADDING, _)) - .With(Args<1, 2>(ElementsAreArray(inputRaw, kDataSize))) - .Times(1); - } - // Provide expected behavior to support session creation EXPECT_CALL(*mCdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) .Times(AtLeast(1)) @@ -1927,6 +1902,11 @@ TEST_F(WVDrmPluginHalTest, CallsGenericEncrypt) { .Times(AtLeast(1)) .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); + EXPECT_CALL(*mCdm, + GenericEncrypt(mCdmSessionId, _, _, _, + wvcdm::kEncryptionAlgorithmAesCbc128, NotNull())) + .WillOnce(testing::Return(CdmResponseType(wvcdm::NO_ERROR))); + EXPECT_CALL(*mCdm, CloseSession(_)).Times(AtLeast(0)); SessionId sessionId; @@ -1962,19 +1942,6 @@ TEST_F(WVDrmPluginHalTest, CallsGenericDecrypt) { iv.assign(ivRaw, ivRaw + KEY_IV_SIZE); std::vector output; - { - InSequence calls; - - EXPECT_CALL(mCrypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(mCrypto, decrypt(4, _, kDataSize, IsIV(ivRaw), - OEMCrypto_AES_CBC_128_NO_PADDING, _)) - .With(Args<1, 2>(ElementsAreArray(inputRaw, kDataSize))) - .Times(1); - } - // Provide expected behavior to support session creation EXPECT_CALL(*mCdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) .Times(AtLeast(1)) @@ -1985,6 +1952,11 @@ TEST_F(WVDrmPluginHalTest, CallsGenericDecrypt) { .Times(AtLeast(1)) .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); + EXPECT_CALL(*mCdm, + GenericDecrypt(mCdmSessionId, _, _, _, + wvcdm::kEncryptionAlgorithmAesCbc128, NotNull())) + .WillOnce(testing::Return(CdmResponseType(wvcdm::NO_ERROR))); + EXPECT_CALL(*mCdm, CloseSession(_)).Times(AtLeast(0)); SessionId sessionId; @@ -2014,26 +1986,6 @@ TEST_F(WVDrmPluginHalTest, CallsGenericSign) { keyId.assign(keyIdRaw, keyIdRaw + KEY_ID_SIZE); std::vector message; message.assign(messageRaw, messageRaw + kDataSize); - std::vector signature; - - { - InSequence calls; - - EXPECT_CALL(mCrypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(mCrypto, - sign(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, Pointee(0))) - .With(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize))) - .WillOnce(DoAll(SetArgPointee<5>(64), - testing::Return(OEMCrypto_ERROR_SHORT_BUFFER))); - - EXPECT_CALL(mCrypto, - sign(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, Pointee(64))) - .With(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize))) - .Times(1); - } // Provide expected behavior to support session creation EXPECT_CALL(*mCdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) @@ -2045,6 +1997,12 @@ TEST_F(WVDrmPluginHalTest, CallsGenericSign) { .Times(AtLeast(1)) .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); + const std::string kFakeSign = "super secure signature generated"; + EXPECT_CALL(*mCdm, GenericSign(mCdmSessionId, _, _, + wvcdm::kSigningAlgorithmHmacSha256, NotNull())) + .WillOnce(DoAll(SetArgPointee<4>(kFakeSign), + testing::Return(CdmResponseType(wvcdm::NO_ERROR)))); + EXPECT_CALL(*mCdm, CloseSession(_)).Times(AtLeast(0)); SessionId sessionId; @@ -2054,9 +2012,12 @@ TEST_F(WVDrmPluginHalTest, CallsGenericSign) { ret = mPlugin->setMacAlgorithm(sessionId, std::string("HmacSHA256")); EXPECT_TRUE(ret.isOk()); + std::vector signature; ret = mPlugin->sign(sessionId, keyId, message, &signature); EXPECT_TRUE(ret.isOk()); - ASSERT_NE(0u, signature.size()); + + const std::vector kFakeSignVec(kFakeSign.begin(), kFakeSign.end()); + ASSERT_EQ(signature, kFakeSignVec); } TEST_F(WVDrmPluginHalTest, CallsGenericVerify) { @@ -2080,29 +2041,9 @@ TEST_F(WVDrmPluginHalTest, CallsGenericVerify) { std::vector signature; signature.assign(signatureRaw, signatureRaw + kSignatureSize); - { - InSequence calls; - - EXPECT_CALL(mCrypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(mCrypto, verify(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, - kSignatureSize)) - .With(AllOf(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize)), - Args<4, 5>(ElementsAreArray(signatureRaw, kSignatureSize)))) - .WillOnce(testing::Return(OEMCrypto_SUCCESS)); - - EXPECT_CALL(mCrypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(mCrypto, verify(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, - kSignatureSize)) - .With(AllOf(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize)), - Args<4, 5>(ElementsAreArray(signatureRaw, kSignatureSize)))) - .WillOnce(testing::Return(OEMCrypto_ERROR_SIGNATURE_FAILURE)); - } + const wvcdm::CdmResponseType kSignatureOkResponse(wvcdm::NO_ERROR); + const wvcdm::CdmResponseType kSignatureBadResponse( + wvcdm::UNKNOWN_ERROR, OEMCrypto_ERROR_SIGNATURE_FAILURE, "GenericVerify"); // Provide expected behavior to support session creation EXPECT_CALL(*mCdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) @@ -2114,6 +2055,11 @@ TEST_F(WVDrmPluginHalTest, CallsGenericVerify) { .Times(AtLeast(1)) .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); + EXPECT_CALL(*mCdm, GenericVerify(mCdmSessionId, _, _, + wvcdm::kSigningAlgorithmHmacSha256, _)) + .WillOnce(testing::Return(kSignatureOkResponse)) + .WillOnce(testing::Return(kSignatureBadResponse)); + EXPECT_CALL(*mCdm, CloseSession(_)).Times(AtLeast(0)); SessionId sessionId;