Home | History | Annotate | Download | only in libmediadrm
      1 /*
      2  * Copyright (C) 2017 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 "CryptoHal"
     19 #include <utils/Log.h>
     20 
     21 #include <android/hardware/drm/1.0/types.h>
     22 #include <android/hidl/manager/1.0/IServiceManager.h>
     23 
     24 #include <binder/IMemory.h>
     25 #include <hidlmemory/FrameworkUtils.h>
     26 #include <media/hardware/CryptoAPI.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 <mediadrm/CryptoHal.h>
     32 
     33 using drm::V1_0::BufferType;
     34 using drm::V1_0::DestinationBuffer;
     35 using drm::V1_0::ICryptoFactory;
     36 using drm::V1_0::ICryptoPlugin;
     37 using drm::V1_0::Mode;
     38 using drm::V1_0::Pattern;
     39 using drm::V1_0::SharedBuffer;
     40 using drm::V1_0::Status;
     41 using drm::V1_0::SubSample;
     42 
     43 using ::android::hardware::hidl_array;
     44 using ::android::hardware::hidl_handle;
     45 using ::android::hardware::hidl_memory;
     46 using ::android::hardware::hidl_string;
     47 using ::android::hardware::hidl_vec;
     48 using ::android::hardware::Return;
     49 using ::android::hardware::Void;
     50 using ::android::hidl::manager::V1_0::IServiceManager;
     51 using ::android::sp;
     52 
     53 typedef drm::V1_2::Status Status_V1_2;
     54 
     55 namespace android {
     56 
     57 static status_t toStatusT(Status status) {
     58     switch (status) {
     59     case Status::OK:
     60         return OK;
     61     case Status::ERROR_DRM_NO_LICENSE:
     62         return ERROR_DRM_NO_LICENSE;
     63     case Status::ERROR_DRM_LICENSE_EXPIRED:
     64         return ERROR_DRM_LICENSE_EXPIRED;
     65     case Status::ERROR_DRM_RESOURCE_BUSY:
     66         return ERROR_DRM_RESOURCE_BUSY;
     67     case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
     68         return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
     69     case Status::ERROR_DRM_SESSION_NOT_OPENED:
     70         return ERROR_DRM_SESSION_NOT_OPENED;
     71     case Status::ERROR_DRM_CANNOT_HANDLE:
     72         return ERROR_DRM_CANNOT_HANDLE;
     73     case Status::ERROR_DRM_DECRYPT:
     74         return ERROR_DRM_DECRYPT;
     75     default:
     76         return UNKNOWN_ERROR;
     77     }
     78 }
     79 
     80 static status_t toStatusT_1_2(Status_V1_2 status) {
     81     switch (status) {
     82     case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
     83         return ERROR_DRM_SESSION_LOST_STATE;;
     84     case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
     85         return ERROR_DRM_FRAME_TOO_LARGE;
     86     case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
     87         return ERROR_DRM_INSUFFICIENT_SECURITY;
     88     default:
     89         return toStatusT(static_cast<Status>(status));
     90     }
     91 }
     92 
     93 static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
     94     hidl_vec<uint8_t> vec;
     95     vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
     96     return vec;
     97 }
     98 
     99 static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
    100     hidl_vec<uint8_t> vec;
    101     vec.resize(size);
    102     memcpy(vec.data(), ptr, size);
    103     return vec;
    104 }
    105 
    106 static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
    107     if (!ptr) {
    108         return hidl_array<uint8_t, 16>();
    109     }
    110     return hidl_array<uint8_t, 16>(ptr);
    111 }
    112 
    113 
    114 static String8 toString8(hidl_string hString) {
    115     return String8(hString.c_str());
    116 }
    117 
    118 
    119 CryptoHal::CryptoHal()
    120     : mFactories(makeCryptoFactories()),
    121       mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
    122       mNextBufferId(0),
    123       mHeapSeqNum(0) {
    124 }
    125 
    126 CryptoHal::~CryptoHal() {
    127 }
    128 
    129 Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
    130     Vector<sp<ICryptoFactory>> factories;
    131 
    132     auto manager = ::IServiceManager::getService();
    133     if (manager != NULL) {
    134         manager->listByInterface(drm::V1_0::ICryptoFactory::descriptor,
    135                 [&factories](const hidl_vec<hidl_string> &registered) {
    136                     for (const auto &instance : registered) {
    137                         auto factory = drm::V1_0::ICryptoFactory::getService(instance);
    138                         if (factory != NULL) {
    139                             ALOGD("found drm (at) 1.0 ICryptoFactory %s", instance.c_str());
    140                             factories.push_back(factory);
    141                         }
    142                     }
    143                 }
    144             );
    145         manager->listByInterface(drm::V1_1::ICryptoFactory::descriptor,
    146                 [&factories](const hidl_vec<hidl_string> &registered) {
    147                     for (const auto &instance : registered) {
    148                         auto factory = drm::V1_1::ICryptoFactory::getService(instance);
    149                         if (factory != NULL) {
    150                             ALOGD("found drm (at) 1.1 ICryptoFactory %s", instance.c_str());
    151                             factories.push_back(factory);
    152                         }
    153                     }
    154                 }
    155             );
    156     }
    157 
    158     if (factories.size() == 0) {
    159         // must be in passthrough mode, load the default passthrough service
    160         auto passthrough = ICryptoFactory::getService();
    161         if (passthrough != NULL) {
    162             ALOGI("makeCryptoFactories: using default passthrough crypto instance");
    163             factories.push_back(passthrough);
    164         } else {
    165             ALOGE("Failed to find any crypto factories");
    166         }
    167     }
    168     return factories;
    169 }
    170 
    171 sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory,
    172         const uint8_t uuid[16], const void *initData, size_t initDataSize) {
    173 
    174     sp<ICryptoPlugin> plugin;
    175     Return<void> hResult = factory->createPlugin(toHidlArray16(uuid),
    176             toHidlVec(initData, initDataSize),
    177             [&](Status status, const sp<ICryptoPlugin>& hPlugin) {
    178                 if (status != Status::OK) {
    179                     ALOGE("Failed to make crypto plugin");
    180                     return;
    181                 }
    182                 plugin = hPlugin;
    183             }
    184         );
    185     return plugin;
    186 }
    187 
    188 
    189 status_t CryptoHal::initCheck() const {
    190     return mInitCheck;
    191 }
    192 
    193 
    194 bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
    195     Mutex::Autolock autoLock(mLock);
    196 
    197     for (size_t i = 0; i < mFactories.size(); i++) {
    198         if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
    199             return true;
    200         }
    201     }
    202     return false;
    203 }
    204 
    205 status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data,
    206         size_t size) {
    207     Mutex::Autolock autoLock(mLock);
    208 
    209     for (size_t i = 0; i < mFactories.size(); i++) {
    210         if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
    211             mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
    212             if (mPlugin != NULL) {
    213                 mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
    214             }
    215         }
    216     }
    217 
    218     if (mPlugin == NULL) {
    219         mInitCheck = ERROR_UNSUPPORTED;
    220     } else {
    221         mInitCheck = OK;
    222     }
    223 
    224     return mInitCheck;
    225 }
    226 
    227 status_t CryptoHal::destroyPlugin() {
    228     Mutex::Autolock autoLock(mLock);
    229 
    230     if (mInitCheck != OK) {
    231         return mInitCheck;
    232     }
    233 
    234     mPlugin.clear();
    235     mPluginV1_2.clear();
    236     return OK;
    237 }
    238 
    239 bool CryptoHal::requiresSecureDecoderComponent(const char *mime) const {
    240     Mutex::Autolock autoLock(mLock);
    241 
    242     if (mInitCheck != OK) {
    243         return false;
    244     }
    245 
    246     Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
    247     if (!hResult.isOk()) {
    248         return false;
    249     }
    250     return hResult;
    251 }
    252 
    253 
    254 /**
    255  * If the heap base isn't set, get the heap base from the IMemory
    256  * and send it to the HAL so it can map a remote heap of the same
    257  * size.  Once the heap base is established, shared memory buffers
    258  * are sent by providing an offset into the heap and a buffer size.
    259  */
    260 int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
    261     using ::android::hardware::fromHeap;
    262     using ::android::hardware::HidlMemory;
    263 
    264     if (heap == NULL) {
    265         ALOGE("setHeapBase(): heap is NULL");
    266         return -1;
    267     }
    268 
    269     Mutex::Autolock autoLock(mLock);
    270 
    271     int32_t seqNum = mHeapSeqNum++;
    272     sp<HidlMemory> hidlMemory = fromHeap(heap);
    273     mHeapBases.add(seqNum, HeapBase(mNextBufferId, heap->getSize()));
    274     Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, mNextBufferId++);
    275     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
    276     return seqNum;
    277 }
    278 
    279 void CryptoHal::clearHeapBase(int32_t seqNum) {
    280     Mutex::Autolock autoLock(mLock);
    281 
    282     /*
    283      * Clear the remote shared memory mapping by setting the shared
    284      * buffer base to a null hidl_memory.
    285      *
    286      * TODO: Add a releaseSharedBuffer method in a future DRM HAL
    287      * API version to make this explicit.
    288      */
    289     ssize_t index = mHeapBases.indexOfKey(seqNum);
    290     if (index >= 0) {
    291         if (mPlugin != NULL) {
    292             uint32_t bufferId = mHeapBases[index].getBufferId();
    293             Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
    294             ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
    295         }
    296         mHeapBases.removeItem(seqNum);
    297     }
    298 }
    299 
    300 status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
    301     ssize_t offset;
    302     size_t size;
    303 
    304     if (memory == NULL || buffer == NULL) {
    305         return UNEXPECTED_NULL;
    306     }
    307 
    308     sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
    309     if (heap == NULL) {
    310         return UNEXPECTED_NULL;
    311     }
    312 
    313     // memory must be in one of the heaps that have been set
    314     if (mHeapBases.indexOfKey(seqNum) < 0) {
    315         return UNKNOWN_ERROR;
    316     }
    317 
    318     // heap must be the same size as the one that was set in setHeapBase
    319     if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) {
    320         android_errorWriteLog(0x534e4554, "76221123");
    321         return UNKNOWN_ERROR;
    322      }
    323 
    324     // memory must be within the address space of the heap
    325     if (memory->pointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset()  ||
    326             heap->getSize() < memory->offset() + memory->size() ||
    327             SIZE_MAX - memory->offset() < memory->size()) {
    328         android_errorWriteLog(0x534e4554, "76221123");
    329         return UNKNOWN_ERROR;
    330     }
    331 
    332     buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId();
    333     buffer->offset = offset >= 0 ? offset : 0;
    334     buffer->size = size;
    335     return OK;
    336 }
    337 
    338 ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
    339         CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
    340         const ICrypto::SourceBuffer &source, size_t offset,
    341         const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
    342         const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
    343     Mutex::Autolock autoLock(mLock);
    344 
    345     if (mInitCheck != OK) {
    346         return mInitCheck;
    347     }
    348 
    349     Mode hMode;
    350     switch(mode) {
    351     case CryptoPlugin::kMode_Unencrypted:
    352         hMode = Mode::UNENCRYPTED ;
    353         break;
    354     case CryptoPlugin::kMode_AES_CTR:
    355         hMode = Mode::AES_CTR;
    356         break;
    357     case CryptoPlugin::kMode_AES_WV:
    358         hMode = Mode::AES_CBC_CTS;
    359         break;
    360     case CryptoPlugin::kMode_AES_CBC:
    361         hMode = Mode::AES_CBC;
    362         break;
    363     default:
    364         return UNKNOWN_ERROR;
    365     }
    366 
    367     Pattern hPattern;
    368     hPattern.encryptBlocks = pattern.mEncryptBlocks;
    369     hPattern.skipBlocks = pattern.mSkipBlocks;
    370 
    371     std::vector<SubSample> stdSubSamples;
    372     for (size_t i = 0; i < numSubSamples; i++) {
    373         SubSample subSample;
    374         subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
    375         subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
    376         stdSubSamples.push_back(subSample);
    377     }
    378     auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
    379 
    380     int32_t heapSeqNum = source.mHeapSeqNum;
    381     bool secure;
    382     ::DestinationBuffer hDestination;
    383     if (destination.mType == kDestinationTypeSharedMemory) {
    384         hDestination.type = BufferType::SHARED_MEMORY;
    385         status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum,
    386                 &hDestination.nonsecureMemory);
    387         if (status != OK) {
    388             return status;
    389         }
    390         secure = false;
    391     } else if (destination.mType == kDestinationTypeNativeHandle) {
    392         hDestination.type = BufferType::NATIVE_HANDLE;
    393         hDestination.secureMemory = hidl_handle(destination.mHandle);
    394         secure = true;
    395     } else {
    396         android_errorWriteLog(0x534e4554, "70526702");
    397         return UNKNOWN_ERROR;
    398     }
    399 
    400     ::SharedBuffer hSource;
    401     status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource);
    402     if (status != OK) {
    403         return status;
    404     }
    405 
    406     status_t err = UNKNOWN_ERROR;
    407     uint32_t bytesWritten = 0;
    408 
    409     Return<void> hResult;
    410 
    411     if (mPluginV1_2 != NULL) {
    412         hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv),
    413                 hMode, hPattern, hSubSamples, hSource, offset, hDestination,
    414                 [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
    415                     if (status == Status_V1_2::OK) {
    416                         bytesWritten = hBytesWritten;
    417                         *errorDetailMsg = toString8(hDetailedError);
    418                     }
    419                     err = toStatusT_1_2(status);
    420                 }
    421             );
    422     } else {
    423         hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv),
    424                 hMode, hPattern, hSubSamples, hSource, offset, hDestination,
    425                 [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
    426                     if (status == Status::OK) {
    427                         bytesWritten = hBytesWritten;
    428                         *errorDetailMsg = toString8(hDetailedError);
    429                     }
    430                     err = toStatusT(status);
    431                 }
    432             );
    433     }
    434 
    435     err = hResult.isOk() ? err : DEAD_OBJECT;
    436     if (err == OK) {
    437         return bytesWritten;
    438     }
    439     return err;
    440 }
    441 
    442 void CryptoHal::notifyResolution(uint32_t width, uint32_t height) {
    443     Mutex::Autolock autoLock(mLock);
    444 
    445     if (mInitCheck != OK) {
    446         return;
    447     }
    448 
    449     mPlugin->notifyResolution(width, height);
    450 }
    451 
    452 status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t> &sessionId) {
    453     Mutex::Autolock autoLock(mLock);
    454 
    455     if (mInitCheck != OK) {
    456         return mInitCheck;
    457     }
    458 
    459     return toStatusT(mPlugin->setMediaDrmSession(toHidlVec(sessionId)));
    460 }
    461 
    462 }  // namespace android
    463