791 lines
20 KiB
C++
791 lines
20 KiB
C++
/*
|
|
* 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/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 {
|
|
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("/vendor/lib/mediadrm");
|
|
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]) {
|
|
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);
|
|
mPlugin->setListener(this);
|
|
return result;
|
|
}
|
|
|
|
status_t Drm::destroyPlugin() {
|
|
Mutex::Autolock autoLock(mLock);
|
|
|
|
if (mInitCheck != OK) {
|
|
return mInitCheck;
|
|
}
|
|
|
|
if (mPlugin == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
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
|