Home | History | Annotate | Download | only in default
      1 /*
      2  * Copyright (C) 2019 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 "android.hardware.cas (at) 1.1-DescramblerImpl"
     19 
     20 #include <hidlmemory/mapping.h>
     21 #include <media/cas/DescramblerAPI.h>
     22 #include <media/hardware/CryptoAPI.h>
     23 #include <media/stagefright/foundation/AUtils.h>
     24 #include <utils/Log.h>
     25 
     26 #include "DescramblerImpl.h"
     27 #include "SharedLibrary.h"
     28 #include "TypeConvert.h"
     29 
     30 namespace android {
     31 using hidl::memory::V1_0::IMemory;
     32 
     33 namespace hardware {
     34 namespace cas {
     35 namespace V1_1 {
     36 namespace implementation {
     37 
     38 #define CHECK_SUBSAMPLE_DEF(type)                                                                 \
     39     static_assert(sizeof(SubSample) == sizeof(type::SubSample), "SubSample: size doesn't match"); \
     40     static_assert(offsetof(SubSample, numBytesOfClearData) ==                                     \
     41                           offsetof(type::SubSample, mNumBytesOfClearData),                        \
     42                   "SubSample: numBytesOfClearData offset doesn't match");                         \
     43     static_assert(offsetof(SubSample, numBytesOfEncryptedData) ==                                 \
     44                           offsetof(type::SubSample, mNumBytesOfEncryptedData),                    \
     45                   "SubSample: numBytesOfEncryptedData offset doesn't match")
     46 
     47 CHECK_SUBSAMPLE_DEF(DescramblerPlugin);
     48 CHECK_SUBSAMPLE_DEF(CryptoPlugin);
     49 
     50 DescramblerImpl::DescramblerImpl(const sp<SharedLibrary>& library, DescramblerPlugin* plugin)
     51     : mLibrary(library), mPluginHolder(plugin) {
     52     ALOGV("CTOR: plugin=%p", mPluginHolder.get());
     53 }
     54 
     55 DescramblerImpl::~DescramblerImpl() {
     56     ALOGV("DTOR: plugin=%p", mPluginHolder.get());
     57     release();
     58 }
     59 
     60 Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
     61     ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
     62 
     63     std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
     64     if (holder.get() == nullptr) {
     65         return toStatus(INVALID_OPERATION);
     66     }
     67 
     68     return toStatus(holder->setMediaCasSession(sessionId));
     69 }
     70 
     71 Return<bool> DescramblerImpl::requiresSecureDecoderComponent(const hidl_string& mime) {
     72     std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
     73     if (holder.get() == nullptr) {
     74         return false;
     75     }
     76 
     77     return holder->requiresSecureDecoderComponent(String8(mime.c_str()));
     78 }
     79 
     80 static inline bool validateRangeForSize(uint64_t offset, uint64_t length, uint64_t size) {
     81     return isInRange<uint64_t, uint64_t>(0, size, offset, length);
     82 }
     83 
     84 Return<void> DescramblerImpl::descramble(ScramblingControl scramblingControl,
     85                                          const hidl_vec<SubSample>& subSamples,
     86                                          const SharedBuffer& srcBuffer, uint64_t srcOffset,
     87                                          const DestinationBuffer& dstBuffer, uint64_t dstOffset,
     88                                          descramble_cb _hidl_cb) {
     89     ALOGV("%s", __FUNCTION__);
     90 
     91     // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map
     92     // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
     93     // but the mapped memory's actual size will be smaller than the reported size.
     94     if (srcBuffer.heapBase.size() > SIZE_MAX) {
     95         ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
     96         android_errorWriteLog(0x534e4554, "79376389");
     97         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
     98         return Void();
     99     }
    100 
    101     sp<IMemory> srcMem = mapMemory(srcBuffer.heapBase);
    102 
    103     // Validate if the offset and size in the SharedBuffer is consistent with the
    104     // mapped ashmem, since the offset and size is controlled by client.
    105     if (srcMem == NULL) {
    106         ALOGE("Failed to map src buffer.");
    107         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
    108         return Void();
    109     }
    110     if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
    111         ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
    112               srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
    113         android_errorWriteLog(0x534e4554, "67962232");
    114         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
    115         return Void();
    116     }
    117 
    118     // use 64-bit here to catch bad subsample size that might be overflowing.
    119     uint64_t totalBytesInSubSamples = 0;
    120     for (size_t i = 0; i < subSamples.size(); i++) {
    121         totalBytesInSubSamples +=
    122                 (uint64_t)subSamples[i].numBytesOfClearData + subSamples[i].numBytesOfEncryptedData;
    123     }
    124     // Further validate if the specified srcOffset and requested total subsample size
    125     // is consistent with the source shared buffer size.
    126     if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
    127         ALOGE("Invalid srcOffset and subsample size: "
    128               "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
    129               srcOffset, totalBytesInSubSamples, srcBuffer.size);
    130         android_errorWriteLog(0x534e4554, "67962232");
    131         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
    132         return Void();
    133     }
    134 
    135     void* srcPtr = (uint8_t*)(void*)srcMem->getPointer() + srcBuffer.offset;
    136     void* dstPtr = NULL;
    137     if (dstBuffer.type == BufferType::SHARED_MEMORY) {
    138         // When using shared memory, src buffer is also used as dst,
    139         // we don't map it again here.
    140         dstPtr = srcPtr;
    141 
    142         // In this case the dst and src would be the same buffer, need to validate
    143         // dstOffset against the buffer size too.
    144         if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
    145             ALOGE("Invalid dstOffset and subsample size: "
    146                   "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
    147                   dstOffset, totalBytesInSubSamples, srcBuffer.size);
    148             android_errorWriteLog(0x534e4554, "67962232");
    149             _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
    150             return Void();
    151         }
    152     } else {
    153         native_handle_t* handle =
    154                 const_cast<native_handle_t*>(dstBuffer.secureMemory.getNativeHandle());
    155         dstPtr = static_cast<void*>(handle);
    156     }
    157 
    158     // Get a local copy of the shared_ptr for the plugin. Note that before
    159     // calling the HIDL callback, this shared_ptr must be manually reset,
    160     // since the client side could proceed as soon as the callback is called
    161     // without waiting for this method to go out of scope.
    162     std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
    163     if (holder.get() == nullptr) {
    164         _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL);
    165         return Void();
    166     }
    167 
    168     // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
    169     // to ensure structs are actually idential
    170 
    171     int32_t result =
    172             holder->descramble(dstBuffer.type != BufferType::SHARED_MEMORY,
    173                                (DescramblerPlugin::ScramblingControl)scramblingControl,
    174                                subSamples.size(), (DescramblerPlugin::SubSample*)subSamples.data(),
    175                                srcPtr, srcOffset, dstPtr, dstOffset, NULL);
    176 
    177     holder.reset();
    178     _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL);
    179     return Void();
    180 }
    181 
    182 Return<Status> DescramblerImpl::release() {
    183     ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
    184 
    185     std::shared_ptr<DescramblerPlugin> holder(nullptr);
    186     std::atomic_store(&mPluginHolder, holder);
    187 
    188     return Status::OK;
    189 }
    190 
    191 }  // namespace implementation
    192 }  // namespace V1_1
    193 }  // namespace cas
    194 }  // namespace hardware
    195 }  // namespace android
    196