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