• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
DescramblerImpl(const sp<SharedLibrary> & library,DescramblerPlugin * plugin)50 DescramblerImpl::DescramblerImpl(const sp<SharedLibrary>& library, DescramblerPlugin* plugin)
51     : mLibrary(library), mPluginHolder(plugin) {
52     ALOGV("CTOR: plugin=%p", mPluginHolder.get());
53 }
54 
~DescramblerImpl()55 DescramblerImpl::~DescramblerImpl() {
56     ALOGV("DTOR: plugin=%p", mPluginHolder.get());
57     release();
58 }
59 
setMediaCasSession(const HidlCasSessionId & sessionId)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 
requiresSecureDecoderComponent(const hidl_string & mime)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 
validateRangeForSize(uint64_t offset,uint64_t length,uint64_t size)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 
descramble(ScramblingControl scramblingControl,const hidl_vec<SubSample> & subSamples,const SharedBuffer & srcBuffer,uint64_t srcOffset,const DestinationBuffer & dstBuffer,uint64_t dstOffset,descramble_cb _hidl_cb)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 
release()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