diff options
Diffstat (limited to 'drm/libmediadrm/Drm.cpp')
| -rw-r--r-- | drm/libmediadrm/Drm.cpp | 799 |
1 files changed, 0 insertions, 799 deletions
diff --git a/drm/libmediadrm/Drm.cpp b/drm/libmediadrm/Drm.cpp deleted file mode 100644 index 1004eb8b15..0000000000 --- a/drm/libmediadrm/Drm.cpp +++ /dev/null @@ -1,799 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "Drm" -#include <utils/Log.h> - -#include <dirent.h> -#include <dlfcn.h> - -#include <media/DrmPluginPath.h> -#include <media/DrmSessionClientInterface.h> -#include <media/DrmSessionManager.h> -#include <media/Drm.h> -#include <media/drm/DrmAPI.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AString.h> -#include <media/stagefright/foundation/hexdump.h> -#include <media/stagefright/MediaErrors.h> -#include <binder/IServiceManager.h> -#include <binder/IPCThreadState.h> - -namespace android { - -static inline int getCallingPid() { - return IPCThreadState::self()->getCallingPid(); -} - -static bool checkPermission(const char* permissionString) { - if (getpid() == IPCThreadState::self()->getCallingPid()) return true; - bool ok = checkCallingPermission(String16(permissionString)); - if (!ok) ALOGE("Request requires %s", permissionString); - return ok; -} - -KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap; -KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap; -Mutex Drm::mMapLock; -Mutex Drm::mLock; - -static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) { - if (lhs.size() < rhs.size()) { - return true; - } else if (lhs.size() > rhs.size()) { - return false; - } - - return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0; -} - -struct DrmSessionClient : public DrmSessionClientInterface { - explicit DrmSessionClient(Drm* drm) : mDrm(drm) {} - - virtual bool reclaimSession(const Vector<uint8_t>& sessionId) { - sp<Drm> drm = mDrm.promote(); - if (drm == NULL) { - return true; - } - status_t err = drm->closeSession(sessionId); - if (err != OK) { - return false; - } - drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL); - return true; - } - -protected: - virtual ~DrmSessionClient() {} - -private: - wp<Drm> mDrm; - - DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient); -}; - -Drm::Drm() - : mInitCheck(NO_INIT), - mDrmSessionClient(new DrmSessionClient(this)), - mListener(NULL), - mFactory(NULL), - mPlugin(NULL) { -} - -Drm::~Drm() { - DrmSessionManager::Instance()->removeDrm(mDrmSessionClient); - delete mPlugin; - mPlugin = NULL; - closeFactory(); -} - -void Drm::closeFactory() { - delete mFactory; - mFactory = NULL; - mLibrary.clear(); -} - -status_t Drm::initCheck() const { - return mInitCheck; -} - -status_t Drm::setListener(const sp<IDrmClient>& listener) -{ - Mutex::Autolock lock(mEventLock); - if (mListener != NULL){ - IInterface::asBinder(mListener)->unlinkToDeath(this); - } - if (listener != NULL) { - IInterface::asBinder(listener)->linkToDeath(this); - } - mListener = listener; - return NO_ERROR; -} - -void Drm::sendEvent(DrmPlugin::EventType eventType, int extra, - Vector<uint8_t> const *sessionId, - Vector<uint8_t> const *data) -{ - mEventLock.lock(); - sp<IDrmClient> listener = mListener; - mEventLock.unlock(); - - if (listener != NULL) { - Parcel obj; - writeByteArray(obj, sessionId); - writeByteArray(obj, data); - - Mutex::Autolock lock(mNotifyLock); - listener->notify(eventType, extra, &obj); - } -} - -void Drm::sendExpirationUpdate(Vector<uint8_t> const *sessionId, - int64_t expiryTimeInMS) -{ - mEventLock.lock(); - sp<IDrmClient> listener = mListener; - mEventLock.unlock(); - - if (listener != NULL) { - Parcel obj; - writeByteArray(obj, sessionId); - obj.writeInt64(expiryTimeInMS); - - Mutex::Autolock lock(mNotifyLock); - listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj); - } -} - -void Drm::sendKeysChange(Vector<uint8_t> const *sessionId, - Vector<DrmPlugin::KeyStatus> const *keyStatusList, - bool hasNewUsableKey) -{ - mEventLock.lock(); - sp<IDrmClient> listener = mListener; - mEventLock.unlock(); - - if (listener != NULL) { - Parcel obj; - writeByteArray(obj, sessionId); - - size_t nkeys = keyStatusList->size(); - obj.writeInt32(keyStatusList->size()); - for (size_t i = 0; i < nkeys; ++i) { - const DrmPlugin::KeyStatus *keyStatus = &keyStatusList->itemAt(i); - writeByteArray(obj, &keyStatus->mKeyId); - obj.writeInt32(keyStatus->mType); - } - obj.writeInt32(hasNewUsableKey); - - Mutex::Autolock lock(mNotifyLock); - listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj); - } -} - -/* - * Search the plugins directory for a plugin that supports the scheme - * specified by uuid - * - * If found: - * mLibrary holds a strong pointer to the dlopen'd library - * mFactory is set to the library's factory method - * mInitCheck is set to OK - * - * If not found: - * mLibrary is cleared and mFactory are set to NULL - * mInitCheck is set to an error (!OK) - */ -void Drm::findFactoryForScheme(const uint8_t uuid[16]) { - - closeFactory(); - - // lock static maps - Mutex::Autolock autoLock(mMapLock); - - // first check cache - Vector<uint8_t> uuidVector; - uuidVector.appendArray(uuid, sizeof(uuid[0]) * 16); - ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector); - if (index >= 0) { - if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) { - mInitCheck = OK; - return; - } else { - ALOGE("Failed to load from cached library path!"); - mInitCheck = ERROR_UNSUPPORTED; - return; - } - } - - // no luck, have to search - String8 dirPath(getDrmPluginPath()); - DIR* pDir = opendir(dirPath.string()); - - if (pDir == NULL) { - mInitCheck = ERROR_UNSUPPORTED; - ALOGE("Failed to open plugin directory %s", dirPath.string()); - return; - } - - - struct dirent* pEntry; - while ((pEntry = readdir(pDir))) { - - String8 pluginPath = dirPath + "/" + pEntry->d_name; - - if (pluginPath.getPathExtension() == ".so") { - - if (loadLibraryForScheme(pluginPath, uuid)) { - mUUIDToLibraryPathMap.add(uuidVector, pluginPath); - mInitCheck = OK; - closedir(pDir); - return; - } - } - } - - closedir(pDir); - - ALOGE("Failed to find drm plugin"); - mInitCheck = ERROR_UNSUPPORTED; -} - -bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) { - - // get strong pointer to open shared library - ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path); - if (index >= 0) { - mLibrary = mLibraryPathToOpenLibraryMap[index].promote(); - } else { - index = mLibraryPathToOpenLibraryMap.add(path, NULL); - } - - if (!mLibrary.get()) { - mLibrary = new SharedLibrary(path); - if (!*mLibrary) { - return false; - } - - mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary); - } - - typedef DrmFactory *(*CreateDrmFactoryFunc)(); - - CreateDrmFactoryFunc createDrmFactory = - (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory"); - - if (createDrmFactory == NULL || - (mFactory = createDrmFactory()) == NULL || - !mFactory->isCryptoSchemeSupported(uuid)) { - closeFactory(); - return false; - } - return true; -} - -bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { - - Mutex::Autolock autoLock(mLock); - - if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) { - findFactoryForScheme(uuid); - if (mInitCheck != OK) { - return false; - } - } - - if (mimeType != "") { - return mFactory->isContentTypeSupported(mimeType); - } - - return true; -} - -status_t Drm::createPlugin(const uint8_t uuid[16], - const String8& /* appPackageName */) { - Mutex::Autolock autoLock(mLock); - - if (mPlugin != NULL) { - return -EINVAL; - } - - if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) { - findFactoryForScheme(uuid); - } - - if (mInitCheck != OK) { - return mInitCheck; - } - - status_t result = mFactory->createDrmPlugin(uuid, &mPlugin); - if (mPlugin) { - mPlugin->setListener(this); - } else { - ALOGE("Failed to create plugin"); - return UNEXPECTED_NULL; - } - return result; -} - -status_t Drm::destroyPlugin() { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - setListener(NULL); - delete mPlugin; - mPlugin = NULL; - - return OK; -} - -status_t Drm::openSession(Vector<uint8_t> &sessionId) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - status_t err = mPlugin->openSession(sessionId); - if (err == ERROR_DRM_RESOURCE_BUSY) { - bool retry = false; - mLock.unlock(); - // reclaimSession may call back to closeSession, since mLock is shared between Drm - // instances, we should unlock here to avoid deadlock. - retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid()); - mLock.lock(); - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - if (retry) { - err = mPlugin->openSession(sessionId); - } - } - if (err == OK) { - DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId); - } - return err; -} - -status_t Drm::closeSession(Vector<uint8_t> const &sessionId) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - status_t err = mPlugin->closeSession(sessionId); - if (err == OK) { - DrmSessionManager::Instance()->removeSession(sessionId); - } - return err; -} - -status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &initData, - String8 const &mimeType, DrmPlugin::KeyType keyType, - KeyedVector<String8, String8> const &optionalParameters, - Vector<uint8_t> &request, String8 &defaultUrl, - DrmPlugin::KeyRequestType *keyRequestType) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType, - optionalParameters, request, defaultUrl, - keyRequestType); -} - -status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &response, - Vector<uint8_t> &keySetId) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->provideKeyResponse(sessionId, response, keySetId); -} - -status_t Drm::removeKeys(Vector<uint8_t> const &keySetId) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->removeKeys(keySetId); -} - -status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &keySetId) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->restoreKeys(sessionId, keySetId); -} - -status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId, - KeyedVector<String8, String8> &infoMap) const { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->queryKeyStatus(sessionId, infoMap); -} - -status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority, - Vector<uint8_t> &request, String8 &defaultUrl) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->getProvisionRequest(certType, certAuthority, - request, defaultUrl); -} - -status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response, - Vector<uint8_t> &certificate, - Vector<uint8_t> &wrappedKey) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->provideProvisionResponse(response, certificate, wrappedKey); -} - -status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->getSecureStops(secureStops); -} - -status_t Drm::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->getSecureStop(ssid, secureStop); -} - -status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->releaseSecureStops(ssRelease); -} - -status_t Drm::releaseAllSecureStops() { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->releaseAllSecureStops(); -} - -status_t Drm::getPropertyString(String8 const &name, String8 &value ) const { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->getPropertyString(name, value); -} - -status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->getPropertyByteArray(name, value); -} - -status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->setPropertyString(name, value); -} - -status_t Drm::setPropertyByteArray(String8 const &name, - Vector<uint8_t> const &value ) const { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - return mPlugin->setPropertyByteArray(name, value); -} - - -status_t Drm::setCipherAlgorithm(Vector<uint8_t> const &sessionId, - String8 const &algorithm) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->setCipherAlgorithm(sessionId, algorithm); -} - -status_t Drm::setMacAlgorithm(Vector<uint8_t> const &sessionId, - String8 const &algorithm) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->setMacAlgorithm(sessionId, algorithm); -} - -status_t Drm::encrypt(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &keyId, - Vector<uint8_t> const &input, - Vector<uint8_t> const &iv, - Vector<uint8_t> &output) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->encrypt(sessionId, keyId, input, iv, output); -} - -status_t Drm::decrypt(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &keyId, - Vector<uint8_t> const &input, - Vector<uint8_t> const &iv, - Vector<uint8_t> &output) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->decrypt(sessionId, keyId, input, iv, output); -} - -status_t Drm::sign(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &keyId, - Vector<uint8_t> const &message, - Vector<uint8_t> &signature) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->sign(sessionId, keyId, message, signature); -} - -status_t Drm::verify(Vector<uint8_t> const &sessionId, - Vector<uint8_t> const &keyId, - Vector<uint8_t> const &message, - Vector<uint8_t> const &signature, - bool &match) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->verify(sessionId, keyId, message, signature, match); -} - -status_t Drm::signRSA(Vector<uint8_t> const &sessionId, - String8 const &algorithm, - Vector<uint8_t> const &message, - Vector<uint8_t> const &wrappedKey, - Vector<uint8_t> &signature) { - Mutex::Autolock autoLock(mLock); - - if (mInitCheck != OK) { - return mInitCheck; - } - - if (mPlugin == NULL) { - return -EINVAL; - } - - if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) { - return -EPERM; - } - - DrmSessionManager::Instance()->useSession(sessionId); - - return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature); -} - -void Drm::binderDied(const wp<IBinder> &the_late_who __unused) -{ - mEventLock.lock(); - mListener.clear(); - mEventLock.unlock(); - - Mutex::Autolock autoLock(mLock); - delete mPlugin; - mPlugin = NULL; - closeFactory(); -} - -void Drm::writeByteArray(Parcel &obj, Vector<uint8_t> const *array) -{ - if (array && array->size()) { - obj.writeInt32(array->size()); - obj.write(array->array(), array->size()); - } else { - obj.writeInt32(0); - } -} - -} // namespace android |
