Home | History | Annotate | Download | only in libmediaplayerservice
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "Drm"
     19 #include <utils/Log.h>
     20 
     21 #include <dirent.h>
     22 #include <dlfcn.h>
     23 
     24 #include "Drm.h"
     25 
     26 #include <media/drm/DrmAPI.h>
     27 #include <media/stagefright/foundation/ADebug.h>
     28 #include <media/stagefright/foundation/AString.h>
     29 #include <media/stagefright/foundation/hexdump.h>
     30 #include <media/stagefright/MediaErrors.h>
     31 #include <binder/IServiceManager.h>
     32 #include <binder/IPCThreadState.h>
     33 
     34 namespace android {
     35 
     36 static bool checkPermission(const char* permissionString) {
     37 #ifndef HAVE_ANDROID_OS
     38     return true;
     39 #endif
     40     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     41     bool ok = checkCallingPermission(String16(permissionString));
     42     if (!ok) ALOGE("Request requires %s", permissionString);
     43     return ok;
     44 }
     45 
     46 KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
     47 KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
     48 Mutex Drm::mMapLock;
     49 
     50 static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
     51     if (lhs.size() < rhs.size()) {
     52         return true;
     53     } else if (lhs.size() > rhs.size()) {
     54         return false;
     55     }
     56 
     57     return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
     58 }
     59 
     60 Drm::Drm()
     61     : mInitCheck(NO_INIT),
     62       mListener(NULL),
     63       mFactory(NULL),
     64       mPlugin(NULL) {
     65 }
     66 
     67 Drm::~Drm() {
     68     delete mPlugin;
     69     mPlugin = NULL;
     70     closeFactory();
     71 }
     72 
     73 void Drm::closeFactory() {
     74     delete mFactory;
     75     mFactory = NULL;
     76     mLibrary.clear();
     77 }
     78 
     79 status_t Drm::initCheck() const {
     80     return mInitCheck;
     81 }
     82 
     83 status_t Drm::setListener(const sp<IDrmClient>& listener)
     84 {
     85     Mutex::Autolock lock(mEventLock);
     86     if (mListener != NULL){
     87         mListener->asBinder()->unlinkToDeath(this);
     88     }
     89     if (listener != NULL) {
     90         listener->asBinder()->linkToDeath(this);
     91     }
     92     mListener = listener;
     93     return NO_ERROR;
     94 }
     95 
     96 void Drm::sendEvent(DrmPlugin::EventType eventType, int extra,
     97                     Vector<uint8_t> const *sessionId,
     98                     Vector<uint8_t> const *data)
     99 {
    100     mEventLock.lock();
    101     sp<IDrmClient> listener = mListener;
    102     mEventLock.unlock();
    103 
    104     if (listener != NULL) {
    105         Parcel obj;
    106         if (sessionId && sessionId->size()) {
    107             obj.writeInt32(sessionId->size());
    108             obj.write(sessionId->array(), sessionId->size());
    109         } else {
    110             obj.writeInt32(0);
    111         }
    112 
    113         if (data && data->size()) {
    114             obj.writeInt32(data->size());
    115             obj.write(data->array(), data->size());
    116         } else {
    117             obj.writeInt32(0);
    118         }
    119 
    120         Mutex::Autolock lock(mNotifyLock);
    121         listener->notify(eventType, extra, &obj);
    122     }
    123 }
    124 
    125 /*
    126  * Search the plugins directory for a plugin that supports the scheme
    127  * specified by uuid
    128  *
    129  * If found:
    130  *    mLibrary holds a strong pointer to the dlopen'd library
    131  *    mFactory is set to the library's factory method
    132  *    mInitCheck is set to OK
    133  *
    134  * If not found:
    135  *    mLibrary is cleared and mFactory are set to NULL
    136  *    mInitCheck is set to an error (!OK)
    137  */
    138 void Drm::findFactoryForScheme(const uint8_t uuid[16]) {
    139 
    140     closeFactory();
    141 
    142     // lock static maps
    143     Mutex::Autolock autoLock(mMapLock);
    144 
    145     // first check cache
    146     Vector<uint8_t> uuidVector;
    147     uuidVector.appendArray(uuid, sizeof(uuid));
    148     ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector);
    149     if (index >= 0) {
    150         if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) {
    151             mInitCheck = OK;
    152             return;
    153         } else {
    154             ALOGE("Failed to load from cached library path!");
    155             mInitCheck = ERROR_UNSUPPORTED;
    156             return;
    157         }
    158     }
    159 
    160     // no luck, have to search
    161     String8 dirPath("/vendor/lib/mediadrm");
    162     DIR* pDir = opendir(dirPath.string());
    163 
    164     if (pDir == NULL) {
    165         mInitCheck = ERROR_UNSUPPORTED;
    166         ALOGE("Failed to open plugin directory %s", dirPath.string());
    167         return;
    168     }
    169 
    170 
    171     struct dirent* pEntry;
    172     while ((pEntry = readdir(pDir))) {
    173 
    174         String8 pluginPath = dirPath + "/" + pEntry->d_name;
    175 
    176         if (pluginPath.getPathExtension() == ".so") {
    177 
    178             if (loadLibraryForScheme(pluginPath, uuid)) {
    179                 mUUIDToLibraryPathMap.add(uuidVector, pluginPath);
    180                 mInitCheck = OK;
    181                 closedir(pDir);
    182                 return;
    183             }
    184         }
    185     }
    186 
    187     closedir(pDir);
    188 
    189     ALOGE("Failed to find drm plugin");
    190     mInitCheck = ERROR_UNSUPPORTED;
    191 }
    192 
    193 bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) {
    194 
    195     // get strong pointer to open shared library
    196     ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
    197     if (index >= 0) {
    198         mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
    199     } else {
    200         index = mLibraryPathToOpenLibraryMap.add(path, NULL);
    201     }
    202 
    203     if (!mLibrary.get()) {
    204         mLibrary = new SharedLibrary(path);
    205         if (!*mLibrary) {
    206             return false;
    207         }
    208 
    209         mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
    210     }
    211 
    212     typedef DrmFactory *(*CreateDrmFactoryFunc)();
    213 
    214     CreateDrmFactoryFunc createDrmFactory =
    215         (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory");
    216 
    217     if (createDrmFactory == NULL ||
    218         (mFactory = createDrmFactory()) == NULL ||
    219         !mFactory->isCryptoSchemeSupported(uuid)) {
    220         closeFactory();
    221         return false;
    222     }
    223     return true;
    224 }
    225 
    226 bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
    227 
    228     Mutex::Autolock autoLock(mLock);
    229 
    230     if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
    231         findFactoryForScheme(uuid);
    232         if (mInitCheck != OK) {
    233             return false;
    234         }
    235     }
    236 
    237     if (mimeType != "") {
    238         return mFactory->isContentTypeSupported(mimeType);
    239     }
    240 
    241     return true;
    242 }
    243 
    244 status_t Drm::createPlugin(const uint8_t uuid[16]) {
    245     Mutex::Autolock autoLock(mLock);
    246 
    247     if (mPlugin != NULL) {
    248         return -EINVAL;
    249     }
    250 
    251     if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
    252         findFactoryForScheme(uuid);
    253     }
    254 
    255     if (mInitCheck != OK) {
    256         return mInitCheck;
    257     }
    258 
    259     status_t result = mFactory->createDrmPlugin(uuid, &mPlugin);
    260     mPlugin->setListener(this);
    261     return result;
    262 }
    263 
    264 status_t Drm::destroyPlugin() {
    265     Mutex::Autolock autoLock(mLock);
    266 
    267     if (mInitCheck != OK) {
    268         return mInitCheck;
    269     }
    270 
    271     if (mPlugin == NULL) {
    272         return -EINVAL;
    273     }
    274 
    275     delete mPlugin;
    276     mPlugin = NULL;
    277 
    278     return OK;
    279 }
    280 
    281 status_t Drm::openSession(Vector<uint8_t> &sessionId) {
    282     Mutex::Autolock autoLock(mLock);
    283 
    284     if (mInitCheck != OK) {
    285         return mInitCheck;
    286     }
    287 
    288     if (mPlugin == NULL) {
    289         return -EINVAL;
    290     }
    291 
    292     return mPlugin->openSession(sessionId);
    293 }
    294 
    295 status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
    296     Mutex::Autolock autoLock(mLock);
    297 
    298     if (mInitCheck != OK) {
    299         return mInitCheck;
    300     }
    301 
    302     if (mPlugin == NULL) {
    303         return -EINVAL;
    304     }
    305 
    306     return mPlugin->closeSession(sessionId);
    307 }
    308 
    309 status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
    310                             Vector<uint8_t> const &initData,
    311                             String8 const &mimeType, DrmPlugin::KeyType keyType,
    312                             KeyedVector<String8, String8> const &optionalParameters,
    313                             Vector<uint8_t> &request, String8 &defaultUrl) {
    314     Mutex::Autolock autoLock(mLock);
    315 
    316     if (mInitCheck != OK) {
    317         return mInitCheck;
    318     }
    319 
    320     if (mPlugin == NULL) {
    321         return -EINVAL;
    322     }
    323 
    324     return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
    325                                   optionalParameters, request, defaultUrl);
    326 }
    327 
    328 status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId,
    329                                  Vector<uint8_t> const &response,
    330                                  Vector<uint8_t> &keySetId) {
    331     Mutex::Autolock autoLock(mLock);
    332 
    333     if (mInitCheck != OK) {
    334         return mInitCheck;
    335     }
    336 
    337     if (mPlugin == NULL) {
    338         return -EINVAL;
    339     }
    340 
    341     return mPlugin->provideKeyResponse(sessionId, response, keySetId);
    342 }
    343 
    344 status_t Drm::removeKeys(Vector<uint8_t> const &keySetId) {
    345     Mutex::Autolock autoLock(mLock);
    346 
    347     if (mInitCheck != OK) {
    348         return mInitCheck;
    349     }
    350 
    351     if (mPlugin == NULL) {
    352         return -EINVAL;
    353     }
    354 
    355     return mPlugin->removeKeys(keySetId);
    356 }
    357 
    358 status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId,
    359                           Vector<uint8_t> const &keySetId) {
    360     Mutex::Autolock autoLock(mLock);
    361 
    362     if (mInitCheck != OK) {
    363         return mInitCheck;
    364     }
    365 
    366     if (mPlugin == NULL) {
    367         return -EINVAL;
    368     }
    369 
    370     return mPlugin->restoreKeys(sessionId, keySetId);
    371 }
    372 
    373 status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId,
    374                              KeyedVector<String8, String8> &infoMap) const {
    375     Mutex::Autolock autoLock(mLock);
    376 
    377     if (mInitCheck != OK) {
    378         return mInitCheck;
    379     }
    380 
    381     if (mPlugin == NULL) {
    382         return -EINVAL;
    383     }
    384 
    385     return mPlugin->queryKeyStatus(sessionId, infoMap);
    386 }
    387 
    388 status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority,
    389                                   Vector<uint8_t> &request, String8 &defaultUrl) {
    390     Mutex::Autolock autoLock(mLock);
    391 
    392     if (mInitCheck != OK) {
    393         return mInitCheck;
    394     }
    395 
    396     if (mPlugin == NULL) {
    397         return -EINVAL;
    398     }
    399 
    400     return mPlugin->getProvisionRequest(certType, certAuthority,
    401                                         request, defaultUrl);
    402 }
    403 
    404 status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response,
    405                                        Vector<uint8_t> &certificate,
    406                                        Vector<uint8_t> &wrappedKey) {
    407     Mutex::Autolock autoLock(mLock);
    408 
    409     if (mInitCheck != OK) {
    410         return mInitCheck;
    411     }
    412 
    413     if (mPlugin == NULL) {
    414         return -EINVAL;
    415     }
    416 
    417     return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
    418 }
    419 
    420 status_t Drm::unprovisionDevice() {
    421     Mutex::Autolock autoLock(mLock);
    422 
    423     if (mInitCheck != OK) {
    424         return mInitCheck;
    425     }
    426 
    427     if (mPlugin == NULL) {
    428         return -EINVAL;
    429     }
    430 
    431     if (!checkPermission("android.permission.REMOVE_DRM_CERTIFICATES")) {
    432         return -EPERM;
    433     }
    434 
    435     return mPlugin->unprovisionDevice();
    436 }
    437 
    438 status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
    439     Mutex::Autolock autoLock(mLock);
    440 
    441     if (mInitCheck != OK) {
    442         return mInitCheck;
    443     }
    444 
    445     if (mPlugin == NULL) {
    446         return -EINVAL;
    447     }
    448 
    449     return mPlugin->getSecureStops(secureStops);
    450 }
    451 
    452 status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
    453     Mutex::Autolock autoLock(mLock);
    454 
    455     if (mInitCheck != OK) {
    456         return mInitCheck;
    457     }
    458 
    459     if (mPlugin == NULL) {
    460         return -EINVAL;
    461     }
    462 
    463     return mPlugin->releaseSecureStops(ssRelease);
    464 }
    465 
    466 status_t Drm::getPropertyString(String8 const &name, String8 &value ) const {
    467     Mutex::Autolock autoLock(mLock);
    468 
    469     if (mInitCheck != OK) {
    470         return mInitCheck;
    471     }
    472 
    473     if (mPlugin == NULL) {
    474         return -EINVAL;
    475     }
    476 
    477     return mPlugin->getPropertyString(name, value);
    478 }
    479 
    480 status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
    481     Mutex::Autolock autoLock(mLock);
    482 
    483     if (mInitCheck != OK) {
    484         return mInitCheck;
    485     }
    486 
    487     if (mPlugin == NULL) {
    488         return -EINVAL;
    489     }
    490 
    491     return mPlugin->getPropertyByteArray(name, value);
    492 }
    493 
    494 status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const {
    495     Mutex::Autolock autoLock(mLock);
    496 
    497     if (mInitCheck != OK) {
    498         return mInitCheck;
    499     }
    500 
    501     if (mPlugin == NULL) {
    502         return -EINVAL;
    503     }
    504 
    505     return mPlugin->setPropertyString(name, value);
    506 }
    507 
    508 status_t Drm::setPropertyByteArray(String8 const &name,
    509                                    Vector<uint8_t> const &value ) const {
    510     Mutex::Autolock autoLock(mLock);
    511 
    512     if (mInitCheck != OK) {
    513         return mInitCheck;
    514     }
    515 
    516     if (mPlugin == NULL) {
    517         return -EINVAL;
    518     }
    519 
    520     return mPlugin->setPropertyByteArray(name, value);
    521 }
    522 
    523 
    524 status_t Drm::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
    525                                  String8 const &algorithm) {
    526     Mutex::Autolock autoLock(mLock);
    527 
    528     if (mInitCheck != OK) {
    529         return mInitCheck;
    530     }
    531 
    532     if (mPlugin == NULL) {
    533         return -EINVAL;
    534     }
    535 
    536     return mPlugin->setCipherAlgorithm(sessionId, algorithm);
    537 }
    538 
    539 status_t Drm::setMacAlgorithm(Vector<uint8_t> const &sessionId,
    540                               String8 const &algorithm) {
    541     Mutex::Autolock autoLock(mLock);
    542 
    543     if (mInitCheck != OK) {
    544         return mInitCheck;
    545     }
    546 
    547     if (mPlugin == NULL) {
    548         return -EINVAL;
    549     }
    550 
    551     return mPlugin->setMacAlgorithm(sessionId, algorithm);
    552 }
    553 
    554 status_t Drm::encrypt(Vector<uint8_t> const &sessionId,
    555                       Vector<uint8_t> const &keyId,
    556                       Vector<uint8_t> const &input,
    557                       Vector<uint8_t> const &iv,
    558                       Vector<uint8_t> &output) {
    559     Mutex::Autolock autoLock(mLock);
    560 
    561     if (mInitCheck != OK) {
    562         return mInitCheck;
    563     }
    564 
    565     if (mPlugin == NULL) {
    566         return -EINVAL;
    567     }
    568 
    569     return mPlugin->encrypt(sessionId, keyId, input, iv, output);
    570 }
    571 
    572 status_t Drm::decrypt(Vector<uint8_t> const &sessionId,
    573                       Vector<uint8_t> const &keyId,
    574                       Vector<uint8_t> const &input,
    575                       Vector<uint8_t> const &iv,
    576                       Vector<uint8_t> &output) {
    577     Mutex::Autolock autoLock(mLock);
    578 
    579     if (mInitCheck != OK) {
    580         return mInitCheck;
    581     }
    582 
    583     if (mPlugin == NULL) {
    584         return -EINVAL;
    585     }
    586 
    587     return mPlugin->decrypt(sessionId, keyId, input, iv, output);
    588 }
    589 
    590 status_t Drm::sign(Vector<uint8_t> const &sessionId,
    591                    Vector<uint8_t> const &keyId,
    592                    Vector<uint8_t> const &message,
    593                    Vector<uint8_t> &signature) {
    594     Mutex::Autolock autoLock(mLock);
    595 
    596     if (mInitCheck != OK) {
    597         return mInitCheck;
    598     }
    599 
    600     if (mPlugin == NULL) {
    601         return -EINVAL;
    602     }
    603 
    604     return mPlugin->sign(sessionId, keyId, message, signature);
    605 }
    606 
    607 status_t Drm::verify(Vector<uint8_t> const &sessionId,
    608                      Vector<uint8_t> const &keyId,
    609                      Vector<uint8_t> const &message,
    610                      Vector<uint8_t> const &signature,
    611                      bool &match) {
    612     Mutex::Autolock autoLock(mLock);
    613 
    614     if (mInitCheck != OK) {
    615         return mInitCheck;
    616     }
    617 
    618     if (mPlugin == NULL) {
    619         return -EINVAL;
    620     }
    621 
    622     return mPlugin->verify(sessionId, keyId, message, signature, match);
    623 }
    624 
    625 status_t Drm::signRSA(Vector<uint8_t> const &sessionId,
    626                       String8 const &algorithm,
    627                       Vector<uint8_t> const &message,
    628                       Vector<uint8_t> const &wrappedKey,
    629                       Vector<uint8_t> &signature) {
    630     Mutex::Autolock autoLock(mLock);
    631 
    632     if (mInitCheck != OK) {
    633         return mInitCheck;
    634     }
    635 
    636     if (mPlugin == NULL) {
    637         return -EINVAL;
    638     }
    639 
    640     if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
    641         return -EPERM;
    642     }
    643 
    644     return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
    645 }
    646 
    647 void Drm::binderDied(const wp<IBinder> &the_late_who)
    648 {
    649     delete mPlugin;
    650     mPlugin = NULL;
    651     closeFactory();
    652     mListener.clear();
    653 }
    654 
    655 }  // namespace android
    656