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 
     56         // allow mapMemory to return nullptr
     57         mSharedBufferMap[bufferId] = hidlMemory;
     58         return Void();
     59     }
     60 
     61     Return<void> CryptoPlugin::decrypt(bool secure,
     62             const hidl_array<uint8_t, 16>& keyId,
     63             const hidl_array<uint8_t, 16>& iv, Mode mode,
     64             const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
     65             const SharedBuffer& source, uint64_t offset,
     66             const DestinationBuffer& destination,
     67             decrypt_cb _hidl_cb) {
     68 
     69         if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
     70             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
     71             return Void();
     72         }
     73 
     74         if (destination.type == BufferType::SHARED_MEMORY) {
     75             const SharedBuffer& dest = destination.nonsecureMemory;
     76             if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
     77                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set");
     78                 return Void();
     79             }
     80         }
     81 
     82         android::CryptoPlugin::Mode legacyMode;
     83         switch(mode) {
     84         case Mode::UNENCRYPTED:
     85             legacyMode = android::CryptoPlugin::kMode_Unencrypted;
     86             break;
     87         case Mode::AES_CTR:
     88             legacyMode = android::CryptoPlugin::kMode_AES_CTR;
     89             break;
     90         case Mode::AES_CBC_CTS:
     91             legacyMode = android::CryptoPlugin::kMode_AES_WV;
     92             break;
     93         case Mode::AES_CBC:
     94             legacyMode = android::CryptoPlugin::kMode_AES_CBC;
     95             break;
     96         }
     97         android::CryptoPlugin::Pattern legacyPattern;
     98         legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
     99         legacyPattern.mSkipBlocks = pattern.skipBlocks;
    100 
    101         std::unique_ptr<android::CryptoPlugin::SubSample[]> legacySubSamples =
    102                 std::make_unique<android::CryptoPlugin::SubSample[]>(subSamples.size());
    103 
    104         for (size_t i = 0; i < subSamples.size(); i++) {
    105             legacySubSamples[i].mNumBytesOfClearData
    106                 = subSamples[i].numBytesOfClearData;
    107             legacySubSamples[i].mNumBytesOfEncryptedData
    108                 = subSamples[i].numBytesOfEncryptedData;
    109         }
    110 
    111         AString detailMessage;
    112         sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
    113         if (sourceBase == nullptr) {
    114             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
    115             return Void();
    116         }
    117 
    118         if (source.offset + offset + source.size > sourceBase->getSize()) {
    119             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
    120             return Void();
    121         }
    122 
    123         uint8_t *base = static_cast<uint8_t *>
    124                 (static_cast<void *>(sourceBase->getPointer()));
    125         void *srcPtr = static_cast<void *>(base + source.offset + offset);
    126 
    127         void *destPtr = NULL;
    128         if (destination.type == BufferType::SHARED_MEMORY) {
    129             const SharedBuffer& destBuffer = destination.nonsecureMemory;
    130             sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
    131             if (destBase == nullptr) {
    132                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
    133                 return Void();
    134             }
    135 
    136             if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
    137                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
    138                 return Void();
    139             }
    140             destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
    141         } else if (destination.type == BufferType::NATIVE_HANDLE) {
    142             native_handle_t *handle = const_cast<native_handle_t *>(
    143                     destination.secureMemory.getNativeHandle());
    144             destPtr = static_cast<void *>(handle);
    145         }
    146         ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
    147                 legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
    148                 subSamples.size(), destPtr, &detailMessage);
    149 
    150         uint32_t status;
    151         uint32_t bytesWritten;
    152 
    153         if (result >= 0) {
    154             status = android::OK;
    155             bytesWritten = result;
    156         } else {
    157             status = result;
    158             bytesWritten = 0;
    159         }
    160 
    161         _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
    162         return Void();
    163     }
    164 
    165 } // namespace implementation
    166 }  // namespace V1_0
    167 }  // namespace drm
    168 }  // namespace hardware
    169 }  // namespace android
    170