blob: 6d7c304fc0d327cc3852c31bd67e9a5f726e8909 [file] [log] [blame]
Chong Zhanga4f67512017-04-24 17:18:25 -07001/*
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@1.0-DescramblerImpl"
19
20#include <hidlmemory/mapping.h>
Henry Fangd3fbe192020-06-08 14:54:41 -070021#include <inttypes.h>
Chong Zhanga4f67512017-04-24 17:18:25 -070022#include <media/cas/DescramblerAPI.h>
Chong Zhang16a3cd02017-10-24 22:42:30 -070023#include <media/hardware/CryptoAPI.h>
Chong Zhang521f6952019-01-04 12:12:25 -080024#include <media/stagefright/foundation/AString.h>
Chong Zhang16a3cd02017-10-24 22:42:30 -070025#include <media/stagefright/foundation/AUtils.h>
Chong Zhanga4f67512017-04-24 17:18:25 -070026#include <utils/Log.h>
27
28#include "DescramblerImpl.h"
29#include "SharedLibrary.h"
30#include "TypeConvert.h"
31
32namespace android {
33using hidl::memory::V1_0::IMemory;
34
35namespace hardware {
36namespace cas {
37namespace V1_0 {
38namespace implementation {
39
40#define CHECK_SUBSAMPLE_DEF(type) \
41static_assert(sizeof(SubSample) == sizeof(type::SubSample), \
42 "SubSample: size doesn't match"); \
43static_assert(offsetof(SubSample, numBytesOfClearData) \
44 == offsetof(type::SubSample, mNumBytesOfClearData), \
45 "SubSample: numBytesOfClearData offset doesn't match"); \
46static_assert(offsetof(SubSample, numBytesOfEncryptedData) \
47 == offsetof(type::SubSample, mNumBytesOfEncryptedData), \
48 "SubSample: numBytesOfEncryptedData offset doesn't match")
49
50CHECK_SUBSAMPLE_DEF(DescramblerPlugin);
51CHECK_SUBSAMPLE_DEF(CryptoPlugin);
52
53DescramblerImpl::DescramblerImpl(
54 const sp<SharedLibrary>& library, DescramblerPlugin *plugin) :
Chong Zhangaddcb3a2018-03-21 15:52:21 -070055 mLibrary(library), mPluginHolder(plugin) {
56 ALOGV("CTOR: plugin=%p", mPluginHolder.get());
Chong Zhanga4f67512017-04-24 17:18:25 -070057}
58
59DescramblerImpl::~DescramblerImpl() {
Chong Zhangaddcb3a2018-03-21 15:52:21 -070060 ALOGV("DTOR: plugin=%p", mPluginHolder.get());
Chong Zhanga4f67512017-04-24 17:18:25 -070061 release();
62}
63
64Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
Tomasz Wasilczyk3e74f0b2023-08-11 16:04:23 +000065 ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).c_str());
Chong Zhanga4f67512017-04-24 17:18:25 -070066
Chong Zhangaddcb3a2018-03-21 15:52:21 -070067 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));
Chong Zhanga4f67512017-04-24 17:18:25 -070073}
74
75Return<bool> DescramblerImpl::requiresSecureDecoderComponent(
76 const hidl_string& mime) {
Chong Zhangaddcb3a2018-03-21 15:52:21 -070077 std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder);
78 if (holder.get() == nullptr) {
79 return false;
80 }
81
Tomasz Wasilczyk11a55db2023-09-13 04:22:26 +000082 return holder->requiresSecureDecoderComponent(mime.c_str());
Chong Zhanga4f67512017-04-24 17:18:25 -070083}
84
Chong Zhang16a3cd02017-10-24 22:42:30 -070085static 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
Chong Zhanga4f67512017-04-24 17:18:25 -070090Return<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
Chong Zhange1ce7452018-05-10 13:53:12 -0700100 // 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) {
Henry Fangd3fbe192020-06-08 14:54:41 -0700104 ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
Chong Zhange1ce7452018-05-10 13:53:12 -0700105 android_errorWriteLog(0x534e4554, "79376389");
106 _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
Chong Zhangaddcb3a2018-03-21 15:52:21 -0700107 return Void();
108 }
109
Chong Zhanga4f67512017-04-24 17:18:25 -0700110 sp<IMemory> srcMem = mapMemory(srcBuffer.heapBase);
Chong Zhang16a3cd02017-10-24 22:42:30 -0700111
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())) {
Henry Fangd3fbe192020-06-08 14:54:41 -0700121 ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
122 "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
Chong Zhang16a3cd02017-10-24 22:42:30 -0700123 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: "
Henry Fangd3fbe192020-06-08 14:54:41 -0700138 "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
139 "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
Chong Zhang16a3cd02017-10-24 22:42:30 -0700140 android_errorWriteLog(0x534e4554, "67962232");
141 _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
142 return Void();
143 }
144
Chong Zhanga4f67512017-04-24 17:18:25 -0700145 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;
Chong Zhang16a3cd02017-10-24 22:42:30 -0700151
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: "
Henry Fangd3fbe192020-06-08 14:54:41 -0700156 "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
157 "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
Chong Zhang16a3cd02017-10-24 22:42:30 -0700158 android_errorWriteLog(0x534e4554, "67962232");
159 _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
160 return Void();
161 }
Chong Zhanga4f67512017-04-24 17:18:25 -0700162 } else {
163 native_handle_t *handle = const_cast<native_handle_t *>(
164 dstBuffer.secureMemory.getNativeHandle());
165 dstPtr = static_cast<void *>(handle);
166 }
Chong Zhange1ce7452018-05-10 13:53:12 -0700167
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
Chong Zhanga4f67512017-04-24 17:18:25 -0700178 // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
179 // to ensure structs are actually idential
180
Chong Zhang521f6952019-01-04 12:12:25 -0800181 AString detailedError;
Chong Zhangaddcb3a2018-03-21 15:52:21 -0700182 int32_t result = holder->descramble(
Chong Zhanga4f67512017-04-24 17:18:25 -0700183 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,
Chong Zhang521f6952019-01-04 12:12:25 -0800191 &detailedError);
Chong Zhanga4f67512017-04-24 17:18:25 -0700192
Chong Zhangaddcb3a2018-03-21 15:52:21 -0700193 holder.reset();
Chong Zhang521f6952019-01-04 12:12:25 -0800194 _hidl_cb(toStatus(result >= 0 ? OK : result), result, detailedError.c_str());
Chong Zhanga4f67512017-04-24 17:18:25 -0700195 return Void();
196}
197
198Return<Status> DescramblerImpl::release() {
Chong Zhangaddcb3a2018-03-21 15:52:21 -0700199 ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
Chong Zhanga4f67512017-04-24 17:18:25 -0700200
Chong Zhangaddcb3a2018-03-21 15:52:21 -0700201 std::shared_ptr<DescramblerPlugin> holder(nullptr);
202 std::atomic_store(&mPluginHolder, holder);
203
Chong Zhanga4f67512017-04-24 17:18:25 -0700204 return Status::OK;
205}
206
207} // namespace implementation
208} // namespace V1_0
209} // namespace cas
210} // namespace hardware
211} // namespace android