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