Loading drm/libmediadrm/CryptoHal.cpp +50 −21 Original line number Diff line number Diff line Loading @@ -30,16 +30,16 @@ #include <media/stagefright/MediaErrors.h> #include <mediadrm/CryptoHal.h> using drm::V1_0::BufferType; using drm::V1_0::DestinationBuffer; using drm::V1_0::ICryptoFactory; using drm::V1_0::ICryptoPlugin; using drm::V1_0::Mode; using drm::V1_0::Pattern; using drm::V1_0::SharedBuffer; using drm::V1_0::Status; using drm::V1_0::SubSample; using ::android::hardware::drm::V1_0::BufferType; using ::android::hardware::drm::V1_0::DestinationBuffer; using ::android::hardware::drm::V1_0::ICryptoFactory; using ::android::hardware::drm::V1_0::ICryptoPlugin; using ::android::hardware::drm::V1_0::Mode; using ::android::hardware::drm::V1_0::Pattern; using ::android::hardware::drm::V1_0::SharedBuffer; using ::android::hardware::drm::V1_0::Status; using ::android::hardware::drm::V1_0::SubSample; using ::android::hardware::hidl_array; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_memory; Loading @@ -50,6 +50,7 @@ using ::android::hardware::Void; using ::android::hidl::manager::V1_0::IServiceManager; using ::android::sp; typedef drm::V1_2::Status Status_V1_2; namespace android { Loading @@ -76,6 +77,18 @@ static status_t toStatusT(Status status) { } } static status_t toStatusT_1_2(Status_V1_2 status) { switch (status) { case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE: return ERROR_DRM_SESSION_LOST_STATE;; case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: return ERROR_DRM_FRAME_TOO_LARGE; case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: return ERROR_DRM_INSUFFICIENT_SECURITY; default: return toStatusT(static_cast<Status>(status)); } } static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) { hidl_vec<uint8_t> vec; Loading Loading @@ -196,6 +209,9 @@ status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data, for (size_t i = 0; i < mFactories.size(); i++) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size); if (mPlugin != NULL) { mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin); } } } Loading @@ -216,6 +232,7 @@ status_t CryptoHal::destroyPlugin() { } mPlugin.clear(); mPluginV1_2.clear(); return OK; } Loading Loading @@ -389,8 +406,22 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], status_t err = UNKNOWN_ERROR; uint32_t bytesWritten = 0; Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, Return<void> hResult; if (mPluginV1_2 != NULL) { hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status_V1_2::OK) { bytesWritten = hBytesWritten; *errorDetailMsg = toString8(hDetailedError); } err = toStatusT_1_2(status); } ); } else { hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status::OK) { bytesWritten = hBytesWritten; Loading @@ -399,11 +430,9 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], err = toStatusT(status); } ); if (!hResult.isOk()) { err = DEAD_OBJECT; } err = hResult.isOk() ? err : DEAD_OBJECT; if (err == OK) { return bytesWritten; } Loading drm/libmediadrm/DrmHal.cpp +149 −81 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ using drm::V1_0::KeyedVector; using drm::V1_0::KeyStatusType; using drm::V1_0::KeyRequestType; using drm::V1_0::KeyType; using drm::V1_0::KeyValue; using drm::V1_0::SecureStop; Loading @@ -60,6 +61,9 @@ using ::android::hidl::manager::V1_0::IServiceManager; using ::android::os::PersistableBundle; using ::android::sp; typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1; typedef drm::V1_2::Status Status_V1_2; namespace { // This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant Loading Loading @@ -239,7 +243,7 @@ static status_t toStatusT(Status status) { return ERROR_DRM_CANNOT_HANDLE; break; case Status::ERROR_DRM_INVALID_STATE: return ERROR_DRM_TAMPER_DETECTED; return ERROR_DRM_INVALID_STATE; break; case Status::BAD_VALUE: return BAD_VALUE; Loading @@ -260,6 +264,19 @@ static status_t toStatusT(Status status) { } } static status_t toStatusT_1_2(Status_V1_2 status) { switch (status) { case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION: return ERROR_DRM_RESOURCE_CONTENTION; case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: return ERROR_DRM_FRAME_TOO_LARGE; case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: return ERROR_DRM_INSUFFICIENT_SECURITY; default: return toStatusT(static_cast<Status>(status)); } } Mutex DrmHal::mLock; Loading Loading @@ -319,8 +336,11 @@ void DrmHal::cleanup() { setListener(NULL); mInitCheck = NO_INIT; if (mPlugin != NULL) { if (mPluginV1_2 != NULL) { if (!mPluginV1_2->setListener(NULL).isOk()) { mInitCheck = DEAD_OBJECT; } } else if (mPlugin != NULL) { if (!mPlugin->setListener(NULL).isOk()) { mInitCheck = DEAD_OBJECT; } Loading Loading @@ -532,6 +552,22 @@ Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId, return Void(); } Return<void> DrmHal::sendSessionLostState( const hidl_vec<uint8_t>& sessionId) { mEventLock.lock(); sp<IDrmClient> listener = mListener; mEventLock.unlock(); if (listener != NULL) { Parcel obj; writeByteArray(obj, sessionId); Mutex::Autolock lock(mNotifyLock); listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj); } return Void(); } bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { Mutex::Autolock autoLock(mLock); Loading Loading @@ -567,17 +603,23 @@ status_t DrmHal::createPlugin(const uint8_t uuid[16], if (mPlugin == NULL) { mInitCheck = ERROR_UNSUPPORTED; } else { if (!mPlugin->setListener(this).isOk()) { mPlugin = NULL; mPluginV1_1 = NULL; mPluginV1_2 = NULL; mInitCheck = DEAD_OBJECT; } else { mInitCheck = OK; if (mPluginV1_2 != NULL) { if (!mPluginV1_2->setListener(this).isOk()) { mInitCheck = DEAD_OBJECT; } } else if (!mPlugin->setListener(this).isOk()) { mInitCheck = DEAD_OBJECT; } if (mInitCheck != OK) { mPlugin.clear(); mPluginV1_1.clear(); mPluginV1_2.clear(); } } return mInitCheck; } Loading Loading @@ -694,6 +736,39 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) { return DEAD_OBJECT; } static DrmPlugin::KeyRequestType toKeyRequestType( KeyRequestType keyRequestType) { switch (keyRequestType) { case KeyRequestType::INITIAL: return DrmPlugin::kKeyRequestType_Initial; break; case KeyRequestType::RENEWAL: return DrmPlugin::kKeyRequestType_Renewal; break; case KeyRequestType::RELEASE: return DrmPlugin::kKeyRequestType_Release; break; default: return DrmPlugin::kKeyRequestType_Unknown; break; } } static DrmPlugin::KeyRequestType toKeyRequestType_1_1( KeyRequestType_V1_1 keyRequestType) { switch (keyRequestType) { case KeyRequestType_V1_1::NONE: return DrmPlugin::kKeyRequestType_None; break; case KeyRequestType_V1_1::UPDATE: return DrmPlugin::kKeyRequestType_Update; break; default: return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType)); break; } } status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId, Vector<uint8_t> const &initData, String8 const &mimeType, DrmPlugin::KeyType keyType, KeyedVector<String8, Loading @@ -720,73 +795,51 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId, ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters); status_t err = UNKNOWN_ERROR; Return<void> hResult; if (mPluginV1_1 != NULL) { Return<void> hResult = mPluginV1_1->getKeyRequest_1_1( if (mPluginV1_2 != NULL) { hResult = mPluginV1_2->getKeyRequest_1_2( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest, KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) { if (status == Status_V1_2::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); *keyRequestType = toKeyRequestType_1_1(hKeyRequestType); } err = toStatusT_1_2(status); }); } else if (mPluginV1_1 != NULL) { hResult = mPluginV1_1->getKeyRequest_1_1( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status status, const hidl_vec<uint8_t>& hRequest, drm::V1_1::KeyRequestType hKeyRequestType, KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) { if (status == Status::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); switch (hKeyRequestType) { case drm::V1_1::KeyRequestType::INITIAL: *keyRequestType = DrmPlugin::kKeyRequestType_Initial; break; case drm::V1_1::KeyRequestType::RENEWAL: *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; break; case drm::V1_1::KeyRequestType::RELEASE: *keyRequestType = DrmPlugin::kKeyRequestType_Release; break; case drm::V1_1::KeyRequestType::NONE: *keyRequestType = DrmPlugin::kKeyRequestType_None; break; case drm::V1_1::KeyRequestType::UPDATE: *keyRequestType = DrmPlugin::kKeyRequestType_Update; break; default: *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; break; *keyRequestType = toKeyRequestType_1_1(hKeyRequestType); } err = toStatusT(status); } }); return hResult.isOk() ? err : DEAD_OBJECT; } Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, } else { hResult = mPlugin->getKeyRequest( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status status, const hidl_vec<uint8_t>& hRequest, drm::V1_0::KeyRequestType hKeyRequestType, KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) { if (status == Status::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); switch (hKeyRequestType) { case drm::V1_0::KeyRequestType::INITIAL: *keyRequestType = DrmPlugin::kKeyRequestType_Initial; break; case drm::V1_0::KeyRequestType::RENEWAL: *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; break; case drm::V1_0::KeyRequestType::RELEASE: *keyRequestType = DrmPlugin::kKeyRequestType_Release; break; default: *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; break; *keyRequestType = toKeyRequestType(hKeyRequestType); } err = toStatusT(status); } }); } err = hResult.isOk() ? err : DEAD_OBJECT; keyRequestTimer.SetAttribute(err); Loading Loading @@ -868,7 +921,21 @@ status_t DrmHal::getProvisionRequest(String8 const &certType, INIT_CHECK(); status_t err = UNKNOWN_ERROR; Return<void> hResult; if (mPluginV1_2 != NULL) { Return<void> hResult = mPluginV1_2->getProvisionRequest_1_2( toHidlString(certType), toHidlString(certAuthority), [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest, const hidl_string& hDefaultUrl) { if (status == Status_V1_2::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); } err = toStatusT_1_2(status); } ); } else { Return<void> hResult = mPlugin->getProvisionRequest( toHidlString(certType), toHidlString(certAuthority), [&](Status status, const hidl_vec<uint8_t>& hRequest, Loading @@ -880,6 +947,7 @@ status_t DrmHal::getProvisionRequest(String8 const &certType, err = toStatusT(status); } ); } err = hResult.isOk() ? err : DEAD_OBJECT; mMetrics.mGetProvisionRequestCounter.Increment(err); Loading drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp +48 −17 Original line number Diff line number Diff line Loading @@ -42,10 +42,42 @@ Return<void> CryptoPlugin::setSharedBufferBase( return Void(); } Return<void> CryptoPlugin::decrypt( bool secure, const hidl_array<uint8_t, 16>& keyId, const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern, const hidl_vec<SubSample>& subSamples, const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination, decrypt_cb _hidl_cb) { Status status = Status::ERROR_DRM_UNKNOWN; hidl_string detailedError; uint32_t bytesWritten = 0; Return<void> hResult = decrypt_1_2( secure, keyId, iv, mode, pattern, subSamples, source, offset, destination, [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) { status = toStatus_1_0(hStatus); if (status == Status::OK) { bytesWritten = hBytesWritten; detailedError = hDetailedError; } } ); status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE; _hidl_cb(status, bytesWritten, detailedError); return Void(); } // Returns negative values for error code and positive values for the size of // decrypted data. In theory, the output size can be larger than the input // size, but in practice this will never happen for AES-CTR. Return<void> CryptoPlugin::decrypt( Return<void> CryptoPlugin::decrypt_1_2( bool secure, const hidl_array<uint8_t, KEY_ID_SIZE>& keyId, const hidl_array<uint8_t, KEY_IV_SIZE>& iv, Loading @@ -55,17 +87,17 @@ Return<void> CryptoPlugin::decrypt( const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination, decrypt_cb _hidl_cb) { decrypt_1_2_cb _hidl_cb) { UNUSED(pattern); if (secure) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Secure decryption is not supported with ClearKey."); return Void(); } if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set"); return Void(); } Loading @@ -73,7 +105,7 @@ Return<void> CryptoPlugin::decrypt( if (destination.type == BufferType::SHARED_MEMORY) { const SharedBuffer& dest = destination.nonsecureMemory; if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set"); return Void(); } Loading @@ -81,12 +113,12 @@ Return<void> CryptoPlugin::decrypt( sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId]; if (sourceBase == nullptr) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); return Void(); } if (source.offset + offset + source.size > sourceBase->getSize()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } Loading @@ -98,12 +130,12 @@ Return<void> CryptoPlugin::decrypt( const SharedBuffer& destBuffer = destination.nonsecureMemory; sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId]; if (destBase == nullptr) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); return Void(); } if (destBuffer.offset + destBuffer.size > destBase->getSize()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset); Loading @@ -128,7 +160,7 @@ Return<void> CryptoPlugin::decrypt( if (mode == Mode::UNENCRYPTED) { if (haveEncryptedSubsamples) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Encrypted subsamples found in allegedly unencrypted data."); return Void(); } Loading @@ -144,22 +176,21 @@ Return<void> CryptoPlugin::decrypt( } } _hidl_cb(Status::OK, static_cast<ssize_t>(offset), ""); _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), ""); return Void(); } else if (mode == Mode::AES_CTR) { size_t bytesDecrypted; Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr, Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr, static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted); if (res == Status::OK) { _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), ""); if (res == Status_V1_2::OK) { _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), ""); return Void(); } else { _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res), "Decryption Error"); _hidl_cb(res, 0, "Decryption Error"); return Void(); } } else { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Selected encryption mode is not supported by the ClearKey DRM Plugin."); return Void(); } Loading drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp +71 −19 File changed.Preview size limit exceeded, changes collapsed. Show changes drm/mediadrm/plugins/clearkey/hidl/Session.cpp +8 −3 Original line number Diff line number Diff line Loading @@ -68,25 +68,30 @@ Status Session::provideKeyResponse(const std::vector<uint8_t>& response) { } } Status Session::decrypt( Status_V1_2 Session::decrypt( const KeyId keyId, const Iv iv, const uint8_t* srcPtr, uint8_t* destPtr, const std::vector<SubSample> subSamples, size_t* bytesDecryptedOut) { Mutex::Autolock lock(mMapLock); if (getMockError() != Status_V1_2::OK) { return getMockError(); } std::vector<uint8_t> keyIdVector; keyIdVector.clear(); keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize); std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr; itr = mKeyMap.find(keyIdVector); if (itr == mKeyMap.end()) { return Status::ERROR_DRM_NO_LICENSE; return Status_V1_2::ERROR_DRM_NO_LICENSE; } AesCtrDecryptor decryptor; return decryptor.decrypt( Status status = decryptor.decrypt( itr->second /*key*/, iv, srcPtr, destPtr, subSamples, subSamples.size(), bytesDecryptedOut); return static_cast<Status_V1_2>(status); } } // namespace clearkey Loading Loading
drm/libmediadrm/CryptoHal.cpp +50 −21 Original line number Diff line number Diff line Loading @@ -30,16 +30,16 @@ #include <media/stagefright/MediaErrors.h> #include <mediadrm/CryptoHal.h> using drm::V1_0::BufferType; using drm::V1_0::DestinationBuffer; using drm::V1_0::ICryptoFactory; using drm::V1_0::ICryptoPlugin; using drm::V1_0::Mode; using drm::V1_0::Pattern; using drm::V1_0::SharedBuffer; using drm::V1_0::Status; using drm::V1_0::SubSample; using ::android::hardware::drm::V1_0::BufferType; using ::android::hardware::drm::V1_0::DestinationBuffer; using ::android::hardware::drm::V1_0::ICryptoFactory; using ::android::hardware::drm::V1_0::ICryptoPlugin; using ::android::hardware::drm::V1_0::Mode; using ::android::hardware::drm::V1_0::Pattern; using ::android::hardware::drm::V1_0::SharedBuffer; using ::android::hardware::drm::V1_0::Status; using ::android::hardware::drm::V1_0::SubSample; using ::android::hardware::hidl_array; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_memory; Loading @@ -50,6 +50,7 @@ using ::android::hardware::Void; using ::android::hidl::manager::V1_0::IServiceManager; using ::android::sp; typedef drm::V1_2::Status Status_V1_2; namespace android { Loading @@ -76,6 +77,18 @@ static status_t toStatusT(Status status) { } } static status_t toStatusT_1_2(Status_V1_2 status) { switch (status) { case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE: return ERROR_DRM_SESSION_LOST_STATE;; case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: return ERROR_DRM_FRAME_TOO_LARGE; case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: return ERROR_DRM_INSUFFICIENT_SECURITY; default: return toStatusT(static_cast<Status>(status)); } } static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) { hidl_vec<uint8_t> vec; Loading Loading @@ -196,6 +209,9 @@ status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data, for (size_t i = 0; i < mFactories.size(); i++) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size); if (mPlugin != NULL) { mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin); } } } Loading @@ -216,6 +232,7 @@ status_t CryptoHal::destroyPlugin() { } mPlugin.clear(); mPluginV1_2.clear(); return OK; } Loading Loading @@ -389,8 +406,22 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], status_t err = UNKNOWN_ERROR; uint32_t bytesWritten = 0; Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, Return<void> hResult; if (mPluginV1_2 != NULL) { hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status_V1_2::OK) { bytesWritten = hBytesWritten; *errorDetailMsg = toString8(hDetailedError); } err = toStatusT_1_2(status); } ); } else { hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status::OK) { bytesWritten = hBytesWritten; Loading @@ -399,11 +430,9 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], err = toStatusT(status); } ); if (!hResult.isOk()) { err = DEAD_OBJECT; } err = hResult.isOk() ? err : DEAD_OBJECT; if (err == OK) { return bytesWritten; } Loading
drm/libmediadrm/DrmHal.cpp +149 −81 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ using drm::V1_0::KeyedVector; using drm::V1_0::KeyStatusType; using drm::V1_0::KeyRequestType; using drm::V1_0::KeyType; using drm::V1_0::KeyValue; using drm::V1_0::SecureStop; Loading @@ -60,6 +61,9 @@ using ::android::hidl::manager::V1_0::IServiceManager; using ::android::os::PersistableBundle; using ::android::sp; typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1; typedef drm::V1_2::Status Status_V1_2; namespace { // This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant Loading Loading @@ -239,7 +243,7 @@ static status_t toStatusT(Status status) { return ERROR_DRM_CANNOT_HANDLE; break; case Status::ERROR_DRM_INVALID_STATE: return ERROR_DRM_TAMPER_DETECTED; return ERROR_DRM_INVALID_STATE; break; case Status::BAD_VALUE: return BAD_VALUE; Loading @@ -260,6 +264,19 @@ static status_t toStatusT(Status status) { } } static status_t toStatusT_1_2(Status_V1_2 status) { switch (status) { case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION: return ERROR_DRM_RESOURCE_CONTENTION; case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: return ERROR_DRM_FRAME_TOO_LARGE; case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: return ERROR_DRM_INSUFFICIENT_SECURITY; default: return toStatusT(static_cast<Status>(status)); } } Mutex DrmHal::mLock; Loading Loading @@ -319,8 +336,11 @@ void DrmHal::cleanup() { setListener(NULL); mInitCheck = NO_INIT; if (mPlugin != NULL) { if (mPluginV1_2 != NULL) { if (!mPluginV1_2->setListener(NULL).isOk()) { mInitCheck = DEAD_OBJECT; } } else if (mPlugin != NULL) { if (!mPlugin->setListener(NULL).isOk()) { mInitCheck = DEAD_OBJECT; } Loading Loading @@ -532,6 +552,22 @@ Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId, return Void(); } Return<void> DrmHal::sendSessionLostState( const hidl_vec<uint8_t>& sessionId) { mEventLock.lock(); sp<IDrmClient> listener = mListener; mEventLock.unlock(); if (listener != NULL) { Parcel obj; writeByteArray(obj, sessionId); Mutex::Autolock lock(mNotifyLock); listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj); } return Void(); } bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { Mutex::Autolock autoLock(mLock); Loading Loading @@ -567,17 +603,23 @@ status_t DrmHal::createPlugin(const uint8_t uuid[16], if (mPlugin == NULL) { mInitCheck = ERROR_UNSUPPORTED; } else { if (!mPlugin->setListener(this).isOk()) { mPlugin = NULL; mPluginV1_1 = NULL; mPluginV1_2 = NULL; mInitCheck = DEAD_OBJECT; } else { mInitCheck = OK; if (mPluginV1_2 != NULL) { if (!mPluginV1_2->setListener(this).isOk()) { mInitCheck = DEAD_OBJECT; } } else if (!mPlugin->setListener(this).isOk()) { mInitCheck = DEAD_OBJECT; } if (mInitCheck != OK) { mPlugin.clear(); mPluginV1_1.clear(); mPluginV1_2.clear(); } } return mInitCheck; } Loading Loading @@ -694,6 +736,39 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) { return DEAD_OBJECT; } static DrmPlugin::KeyRequestType toKeyRequestType( KeyRequestType keyRequestType) { switch (keyRequestType) { case KeyRequestType::INITIAL: return DrmPlugin::kKeyRequestType_Initial; break; case KeyRequestType::RENEWAL: return DrmPlugin::kKeyRequestType_Renewal; break; case KeyRequestType::RELEASE: return DrmPlugin::kKeyRequestType_Release; break; default: return DrmPlugin::kKeyRequestType_Unknown; break; } } static DrmPlugin::KeyRequestType toKeyRequestType_1_1( KeyRequestType_V1_1 keyRequestType) { switch (keyRequestType) { case KeyRequestType_V1_1::NONE: return DrmPlugin::kKeyRequestType_None; break; case KeyRequestType_V1_1::UPDATE: return DrmPlugin::kKeyRequestType_Update; break; default: return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType)); break; } } status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId, Vector<uint8_t> const &initData, String8 const &mimeType, DrmPlugin::KeyType keyType, KeyedVector<String8, Loading @@ -720,73 +795,51 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId, ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters); status_t err = UNKNOWN_ERROR; Return<void> hResult; if (mPluginV1_1 != NULL) { Return<void> hResult = mPluginV1_1->getKeyRequest_1_1( if (mPluginV1_2 != NULL) { hResult = mPluginV1_2->getKeyRequest_1_2( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest, KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) { if (status == Status_V1_2::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); *keyRequestType = toKeyRequestType_1_1(hKeyRequestType); } err = toStatusT_1_2(status); }); } else if (mPluginV1_1 != NULL) { hResult = mPluginV1_1->getKeyRequest_1_1( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status status, const hidl_vec<uint8_t>& hRequest, drm::V1_1::KeyRequestType hKeyRequestType, KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) { if (status == Status::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); switch (hKeyRequestType) { case drm::V1_1::KeyRequestType::INITIAL: *keyRequestType = DrmPlugin::kKeyRequestType_Initial; break; case drm::V1_1::KeyRequestType::RENEWAL: *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; break; case drm::V1_1::KeyRequestType::RELEASE: *keyRequestType = DrmPlugin::kKeyRequestType_Release; break; case drm::V1_1::KeyRequestType::NONE: *keyRequestType = DrmPlugin::kKeyRequestType_None; break; case drm::V1_1::KeyRequestType::UPDATE: *keyRequestType = DrmPlugin::kKeyRequestType_Update; break; default: *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; break; *keyRequestType = toKeyRequestType_1_1(hKeyRequestType); } err = toStatusT(status); } }); return hResult.isOk() ? err : DEAD_OBJECT; } Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, } else { hResult = mPlugin->getKeyRequest( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status status, const hidl_vec<uint8_t>& hRequest, drm::V1_0::KeyRequestType hKeyRequestType, KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) { if (status == Status::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); switch (hKeyRequestType) { case drm::V1_0::KeyRequestType::INITIAL: *keyRequestType = DrmPlugin::kKeyRequestType_Initial; break; case drm::V1_0::KeyRequestType::RENEWAL: *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; break; case drm::V1_0::KeyRequestType::RELEASE: *keyRequestType = DrmPlugin::kKeyRequestType_Release; break; default: *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; break; *keyRequestType = toKeyRequestType(hKeyRequestType); } err = toStatusT(status); } }); } err = hResult.isOk() ? err : DEAD_OBJECT; keyRequestTimer.SetAttribute(err); Loading Loading @@ -868,7 +921,21 @@ status_t DrmHal::getProvisionRequest(String8 const &certType, INIT_CHECK(); status_t err = UNKNOWN_ERROR; Return<void> hResult; if (mPluginV1_2 != NULL) { Return<void> hResult = mPluginV1_2->getProvisionRequest_1_2( toHidlString(certType), toHidlString(certAuthority), [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest, const hidl_string& hDefaultUrl) { if (status == Status_V1_2::OK) { request = toVector(hRequest); defaultUrl = toString8(hDefaultUrl); } err = toStatusT_1_2(status); } ); } else { Return<void> hResult = mPlugin->getProvisionRequest( toHidlString(certType), toHidlString(certAuthority), [&](Status status, const hidl_vec<uint8_t>& hRequest, Loading @@ -880,6 +947,7 @@ status_t DrmHal::getProvisionRequest(String8 const &certType, err = toStatusT(status); } ); } err = hResult.isOk() ? err : DEAD_OBJECT; mMetrics.mGetProvisionRequestCounter.Increment(err); Loading
drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp +48 −17 Original line number Diff line number Diff line Loading @@ -42,10 +42,42 @@ Return<void> CryptoPlugin::setSharedBufferBase( return Void(); } Return<void> CryptoPlugin::decrypt( bool secure, const hidl_array<uint8_t, 16>& keyId, const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern, const hidl_vec<SubSample>& subSamples, const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination, decrypt_cb _hidl_cb) { Status status = Status::ERROR_DRM_UNKNOWN; hidl_string detailedError; uint32_t bytesWritten = 0; Return<void> hResult = decrypt_1_2( secure, keyId, iv, mode, pattern, subSamples, source, offset, destination, [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) { status = toStatus_1_0(hStatus); if (status == Status::OK) { bytesWritten = hBytesWritten; detailedError = hDetailedError; } } ); status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE; _hidl_cb(status, bytesWritten, detailedError); return Void(); } // Returns negative values for error code and positive values for the size of // decrypted data. In theory, the output size can be larger than the input // size, but in practice this will never happen for AES-CTR. Return<void> CryptoPlugin::decrypt( Return<void> CryptoPlugin::decrypt_1_2( bool secure, const hidl_array<uint8_t, KEY_ID_SIZE>& keyId, const hidl_array<uint8_t, KEY_IV_SIZE>& iv, Loading @@ -55,17 +87,17 @@ Return<void> CryptoPlugin::decrypt( const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination, decrypt_cb _hidl_cb) { decrypt_1_2_cb _hidl_cb) { UNUSED(pattern); if (secure) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Secure decryption is not supported with ClearKey."); return Void(); } if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set"); return Void(); } Loading @@ -73,7 +105,7 @@ Return<void> CryptoPlugin::decrypt( if (destination.type == BufferType::SHARED_MEMORY) { const SharedBuffer& dest = destination.nonsecureMemory; if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set"); return Void(); } Loading @@ -81,12 +113,12 @@ Return<void> CryptoPlugin::decrypt( sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId]; if (sourceBase == nullptr) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); return Void(); } if (source.offset + offset + source.size > sourceBase->getSize()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } Loading @@ -98,12 +130,12 @@ Return<void> CryptoPlugin::decrypt( const SharedBuffer& destBuffer = destination.nonsecureMemory; sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId]; if (destBase == nullptr) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); return Void(); } if (destBuffer.offset + destBuffer.size > destBase->getSize()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset); Loading @@ -128,7 +160,7 @@ Return<void> CryptoPlugin::decrypt( if (mode == Mode::UNENCRYPTED) { if (haveEncryptedSubsamples) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Encrypted subsamples found in allegedly unencrypted data."); return Void(); } Loading @@ -144,22 +176,21 @@ Return<void> CryptoPlugin::decrypt( } } _hidl_cb(Status::OK, static_cast<ssize_t>(offset), ""); _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), ""); return Void(); } else if (mode == Mode::AES_CTR) { size_t bytesDecrypted; Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr, Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr, static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted); if (res == Status::OK) { _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), ""); if (res == Status_V1_2::OK) { _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), ""); return Void(); } else { _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res), "Decryption Error"); _hidl_cb(res, 0, "Decryption Error"); return Void(); } } else { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Selected encryption mode is not supported by the ClearKey DRM Plugin."); return Void(); } Loading
drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp +71 −19 File changed.Preview size limit exceeded, changes collapsed. Show changes
drm/mediadrm/plugins/clearkey/hidl/Session.cpp +8 −3 Original line number Diff line number Diff line Loading @@ -68,25 +68,30 @@ Status Session::provideKeyResponse(const std::vector<uint8_t>& response) { } } Status Session::decrypt( Status_V1_2 Session::decrypt( const KeyId keyId, const Iv iv, const uint8_t* srcPtr, uint8_t* destPtr, const std::vector<SubSample> subSamples, size_t* bytesDecryptedOut) { Mutex::Autolock lock(mMapLock); if (getMockError() != Status_V1_2::OK) { return getMockError(); } std::vector<uint8_t> keyIdVector; keyIdVector.clear(); keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize); std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr; itr = mKeyMap.find(keyIdVector); if (itr == mKeyMap.end()) { return Status::ERROR_DRM_NO_LICENSE; return Status_V1_2::ERROR_DRM_NO_LICENSE; } AesCtrDecryptor decryptor; return decryptor.decrypt( Status status = decryptor.decrypt( itr->second /*key*/, iv, srcPtr, destPtr, subSamples, subSamples.size(), bytesDecryptedOut); return static_cast<Status_V1_2>(status); } } // namespace clearkey Loading