Home | History | Annotate | Download | only in default
      1 /*
      2  * Copyright (C) 2016 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 #define LOG_TAG "android.hardware.drm (at) 1.0-impl"
     17 
     18 #include "CryptoPlugin.h"
     19 #include "TypeConvert.h"
     20 
     21 #include <android/hidl/memory/1.0/IMemory.h>
     22 #include <hidlmemory/mapping.h>
     23 #include <log/log.h>
     24 #include <media/stagefright/foundation/AString.h>
     25 
     26 using android::hardware::hidl_memory;
     27 using android::hidl::memory::V1_0::IMemory;
     28 
     29 namespace android {
     30 namespace hardware {
     31 namespace drm {
     32 namespace V1_0 {
     33 namespace implementation {
     34 
     35     // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
     36     Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
     37             const hidl_string& mime) {
     38         return mLegacyPlugin->requiresSecureDecoderComponent(mime.c_str());
     39     }
     40 
     41     Return<void> CryptoPlugin::notifyResolution(uint32_t width,
     42             uint32_t height) {
     43         mLegacyPlugin->notifyResolution(width, height);
     44         return Void();
     45     }
     46 
     47     Return<Status> CryptoPlugin::setMediaDrmSession(
     48             const hidl_vec<uint8_t>& sessionId) {
     49         return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
     50     }
     51 
     52     Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base,
     53             uint32_t bufferId) {
     54         sp<IMemory> hidlMemory = mapMemory(base);
     55         ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
     56 
     57         // allow mapMemory to return nullptr
     58         mSharedBufferMap[bufferId] = hidlMemory;
     59         return Void();
     60     }
     61 
     62     Return<void> CryptoPlugin::decrypt(bool secure,
     63             const hidl_array<uint8_t, 16>& keyId,
     64             const hidl_array<uint8_t, 16>& iv, Mode mode,
     65             const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
     66             const SharedBuffer& source, uint64_t offset,
     67             const DestinationBuffer& destination,
     68             decrypt_cb _hidl_cb) {
     69 
     70         if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
     71             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
     72             return Void();
     73         }
     74 
     75         if (destination.type == BufferType::SHARED_MEMORY) {
     76             const SharedBuffer& dest = destination.nonsecureMemory;
     77             if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
     78                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set");
     79                 return Void();
     80             }
     81         }
     82 
     83         android::CryptoPlugin::Mode legacyMode;
     84         switch(mode) {
     85         case Mode::UNENCRYPTED:
     86             legacyMode = android::CryptoPlugin::kMode_Unencrypted;
     87             break;
     88         case Mode::AES_CTR:
     89             legacyMode = android::CryptoPlugin::kMode_AES_CTR;
     90             break;
     91         case Mode::AES_CBC_CTS:
     92             legacyMode = android::CryptoPlugin::kMode_AES_WV;
     93             break;
     94         case Mode::AES_CBC:
     95             legacyMode = android::CryptoPlugin::kMode_AES_CBC;
     96             break;
     97         }
     98         android::CryptoPlugin::Pattern legacyPattern;
     99         legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
    100         legacyPattern.mSkipBlocks = pattern.skipBlocks;
    101 
    102         std::unique_ptr<android::CryptoPlugin::SubSample[]> legacySubSamples =
    103                 std::make_unique<android::CryptoPlugin::SubSample[]>(subSamples.size());
    104 
    105         for (size_t i = 0; i < subSamples.size(); i++) {
    106             legacySubSamples[i].mNumBytesOfClearData
    107                 = subSamples[i].numBytesOfClearData;
    108             legacySubSamples[i].mNumBytesOfEncryptedData
    109                 = subSamples[i].numBytesOfEncryptedData;
    110         }
    111 
    112         AString detailMessage;
    113         sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
    114         if (sourceBase == nullptr) {
    115             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
    116             return Void();
    117         }
    118 
    119         if (source.offset + offset + source.size > sourceBase->getSize()) {
    120             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
    121             return Void();
    122         }
    123 
    124         uint8_t *base = static_cast<uint8_t *>
    125                 (static_cast<void *>(sourceBase->getPointer()));
    126         void *srcPtr = static_cast<void *>(base + source.offset + offset);
    127 
    128         void *destPtr = NULL;
    129         if (destination.type == BufferType::SHARED_MEMORY) {
    130             const SharedBuffer& destBuffer = destination.nonsecureMemory;
    131             sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
    132             if (destBase == nullptr) {
    133                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
    134                 return Void();
    135             }
    136 
    137             if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
    138                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
    139                 return Void();
    140             }
    141             destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
    142         } else if (destination.type == BufferType::NATIVE_HANDLE) {
    143             native_handle_t *handle = const_cast<native_handle_t *>(
    144                     destination.secureMemory.getNativeHandle());
    145             destPtr = static_cast<void *>(handle);
    146         }
    147         ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
    148                 legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
    149                 subSamples.size(), destPtr, &detailMessage);
    150 
    151         uint32_t status;
    152         uint32_t bytesWritten;
    153 
    154         if (result >= 0) {
    155             status = android::OK;
    156             bytesWritten = result;
    157         } else {
    158             status = result;
    159             bytesWritten = 0;
    160         }
    161 
    162         _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
    163         return Void();
    164     }
    165 
    166 } // namespace implementation
    167 }  // namespace V1_0
    168 }  // namespace drm
    169 }  // namespace hardware
    170 }  // namespace android
    171