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