blob: 5989ca2cc26994adfaacbca229951872fda5d753 [file] [log] [blame]
Kyle Zhang6605add2022-01-13 17:51:23 +00001/*
2 * Copyright (C) 2021 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 "CryptoHalAidl"
19
20#include <aidlcommonsupport/NativeHandle.h>
21#include <android/binder_auto_utils.h>
22#include <android/binder_manager.h>
23#include <media/hardware/CryptoAPI.h>
24#include <media/stagefright/MediaErrors.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AString.h>
27#include <media/stagefright/foundation/hexdump.h>
28#include <mediadrm/CryptoHalAidl.h>
29#include <mediadrm/DrmUtils.h>
30
31using ::aidl::android::hardware::drm::BufferType;
32using ::aidl::android::hardware::drm::DecryptResult;
33using DestinationBufferAidl = ::aidl::android::hardware::drm::DestinationBuffer;
34using ::aidl::android::hardware::drm::Mode;
35using ::aidl::android::hardware::drm::Pattern;
36using SharedBufferAidl = ::aidl::android::hardware::drm::SharedBuffer;
37using ::aidl::android::hardware::drm::Status;
38using ::aidl::android::hardware::drm::SubSample;
39using ::aidl::android::hardware::drm::Uuid;
40
41using ::aidl::android::hardware::common::Ashmem;
42
43using ::android::sp;
Kyle Zhang96af9572022-02-05 06:38:53 +000044using ::android::DrmUtils::statusAidlToStatusT;
Kyle Zhang6605add2022-01-13 17:51:23 +000045using ::android::hardware::hidl_array;
46using ::android::hardware::hidl_handle;
47using ::android::hardware::hidl_memory;
48using ::android::hardware::hidl_string;
49using ::android::hardware::hidl_vec;
50using ::android::hardware::HidlMemory;
51using ::android::hardware::Return;
52using ::android::hardware::Void;
53
54using ::aidl::android::hardware::drm::Uuid;
55// -------Hidl interface related-----------------
56// TODO: replace before removing hidl interface
57
58using BufferTypeHidl = ::android::hardware::drm::V1_0::BufferType;
59using SharedBufferHidl = ::android::hardware::drm::V1_0::SharedBuffer;
60using DestinationBufferHidl = ::android::hardware::drm::V1_0::DestinationBuffer;
61
62// -------Hidl interface related end-------------
63
64namespace android {
65
66static Uuid toAidlUuid(const uint8_t* uuid) {
67 Uuid uuidAidl;
68 uuidAidl.uuid = std::vector<uint8_t>(uuid, uuid + 16);
69 return uuidAidl;
70}
71
72template <typename Byte = uint8_t>
73static std::vector<Byte> toStdVec(const Vector<uint8_t>& vector) {
74 auto v = reinterpret_cast<const Byte*>(vector.array());
75 std::vector<Byte> vec(v, v + vector.size());
76 return vec;
77}
78
79// -------Hidl interface related-----------------
80// TODO: replace before removing hidl interface
81status_t CryptoHalAidl::checkSharedBuffer(const SharedBufferHidl& buffer) {
82 int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
83 // memory must be in one of the heaps that have been set
84 if (mHeapSizes.indexOfKey(seqNum) < 0) {
85 return UNKNOWN_ERROR;
86 }
87
88 // memory must be within the address space of the heap
89 size_t heapSize = mHeapSizes.valueFor(seqNum);
90 if (heapSize < buffer.offset + buffer.size || SIZE_MAX - buffer.offset < buffer.size) {
91 android_errorWriteLog(0x534e4554, "76221123");
92 return UNKNOWN_ERROR;
93 }
94
95 return OK;
96}
97
98static SharedBufferAidl hidlSharedBufferToAidlSharedBuffer(const SharedBufferHidl& buffer) {
99 SharedBufferAidl aidlsb;
100 aidlsb.bufferId = buffer.bufferId;
101 aidlsb.offset = buffer.offset;
102 aidlsb.size = buffer.size;
103 return aidlsb;
104}
105
106static DestinationBufferAidl hidlDestinationBufferToAidlDestinationBuffer(
107 const DestinationBufferHidl& buffer) {
108 DestinationBufferAidl aidldb;
109 // skip negative convert check as count of enum elements are 2
110 aidldb.type = static_cast<BufferType>((int32_t)buffer.type);
111 aidldb.nonsecureMemory = hidlSharedBufferToAidlSharedBuffer(buffer.nonsecureMemory);
Robert Shihcc4a2ce2022-02-03 08:27:08 -0800112 auto handle = buffer.secureMemory.getNativeHandle();
113 if (handle) {
114 aidldb.secureMemory = ::android::makeToAidl(handle);
115 } else {
116 aidldb.secureMemory = {.fds = {}, .ints = {}};
117 }
Kyle Zhang6605add2022-01-13 17:51:23 +0000118 return aidldb;
119}
120
121static hidl_vec<uint8_t> toHidlVec(const void* ptr, size_t size) {
122 hidl_vec<uint8_t> vec;
123 vec.resize(size);
124 memcpy(vec.data(), ptr, size);
125 return vec;
126}
127
128static const Vector<uint8_t> toVector(const std::vector<uint8_t>& vec) {
129 Vector<uint8_t> vector;
130 vector.appendArray(vec.data(), vec.size());
131 return *const_cast<const Vector<uint8_t>*>(&vector);
132}
133
134static String8 toString8(const std::string& string) {
135 return String8(string.c_str());
136}
137
Robert Shihcc4a2ce2022-02-03 08:27:08 -0800138static std::vector<uint8_t> toStdVec(const uint8_t* ptr, size_t n) {
139 if (!ptr) {
140 return std::vector<uint8_t>();
141 }
142 return std::vector<uint8_t>(ptr, ptr + n);
143}
144
Kyle Zhang6605add2022-01-13 17:51:23 +0000145// -------Hidl interface related end--------------
146
147CryptoHalAidl::CryptoHalAidl()
148 : mFactories(makeCryptoFactories()),
149 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
150 mHeapSeqNum(0) {}
151
152CryptoHalAidl::~CryptoHalAidl() {}
153
154std::vector<std::shared_ptr<ICryptoFactoryAidl>> CryptoHalAidl::makeCryptoFactories() {
155 std::vector<std::shared_ptr<ICryptoFactoryAidl>> factories;
156 AServiceManager_forEachDeclaredInstance(
157 ICryptoFactoryAidl::descriptor, static_cast<void*>(&factories),
158 [](const char* instance, void* context) {
159 auto fullName = std::string(ICryptoFactoryAidl::descriptor) + "/" + std::string(instance);
160 auto factory = ICryptoFactoryAidl::fromBinder(
161 ::ndk::SpAIBinder(AServiceManager_getService(fullName.c_str())));
162 if (factory == nullptr) {
163 ALOGE("not found ICryptoFactoryAidl. Instance name:[%s]", fullName.c_str());
164 return;
165 }
166
167 ALOGI("found ICryptoFactoryAidl. Instance name:[%s]", fullName.c_str());
168 static_cast<std::vector<std::shared_ptr<ICryptoFactoryAidl>>*>(context)
169 ->emplace_back(factory);
170 });
171
172 return factories;
173}
174
175status_t CryptoHalAidl::initCheck() const {
176 return mInitCheck;
177}
178
179bool CryptoHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16]) {
180 Mutex::Autolock autoLock(mLock);
181
182 bool isSupported = false;
183 Uuid uuidAidl = toAidlUuid(uuid);
184 for (size_t i = 0; i < mFactories.size(); i++) {
185 if (mFactories[i]->isCryptoSchemeSupported(uuidAidl, &isSupported).isOk()) {
186 if (isSupported) break;
187 }
188 }
189 return isSupported;
190}
191
192status_t CryptoHalAidl::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
193 Mutex::Autolock autoLock(mLock);
194
195 bool isSupported = false;
196 Uuid uuidAidl = toAidlUuid(uuid);
197 std::vector<uint8_t> dataAidl = toStdVec(toVector(toHidlVec(data, size)));
198 for (size_t i = 0; i < mFactories.size(); i++) {
199 if (mFactories[i]->isCryptoSchemeSupported(uuidAidl, &isSupported).isOk() && isSupported) {
200 mPlugin = makeCryptoPlugin(mFactories[i], uuidAidl, dataAidl);
201 // Reserve place for future plugins with new versions
202
203 break;
204 }
205 }
206
207 if (mInitCheck == NO_INIT) {
208 mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
209 }
210
211 return mInitCheck;
212}
213
214std::shared_ptr<ICryptoPluginAidl> CryptoHalAidl::makeCryptoPlugin(
215 const std::shared_ptr<ICryptoFactoryAidl>& factory, const Uuid& uuidAidl,
216 const std::vector<uint8_t> initData) {
217 std::shared_ptr<ICryptoPluginAidl> pluginAidl;
218 if (factory->createPlugin(uuidAidl, initData, &pluginAidl).isOk()) {
219 ALOGI("Create ICryptoPluginAidl. UUID:[%s]", uuidAidl.toString().c_str());
220 } else {
221 mInitCheck = DEAD_OBJECT;
222 ALOGE("Failed to create ICryptoPluginAidl. UUID:[%s]", uuidAidl.toString().c_str());
223 }
224
225 return pluginAidl;
226}
227
228status_t CryptoHalAidl::destroyPlugin() {
229 Mutex::Autolock autoLock(mLock);
230
231 if (mInitCheck != OK) {
232 return mInitCheck;
233 }
234
235 mPlugin.reset();
236 return OK;
237}
238
239bool CryptoHalAidl::requiresSecureDecoderComponent(const char* mime) const {
240 Mutex::Autolock autoLock(mLock);
241
242 if (mInitCheck != OK) {
243 return false;
244 }
245
246 std::string mimeStr = std::string(mime);
247 bool result;
248 if (!mPlugin->requiresSecureDecoderComponent(mimeStr, &result).isOk()) {
249 ALOGE("Failed to requiresSecureDecoderComponent. mime:[%s]", mime);
250 return false;
251 }
252
253 return result;
254}
255
256void CryptoHalAidl::notifyResolution(uint32_t width, uint32_t height) {
257 Mutex::Autolock autoLock(mLock);
258
259 if (mInitCheck != OK) {
260 return;
261 }
262
263 // Check negative width and height after type conversion
264 // Log error and return if any is negative
265 if ((int32_t)width < 0 || (int32_t)height < 0) {
266 ALOGE("Negative width: %d or height %d in notifyResolution", width, height);
267 return;
268 }
269
270 ::ndk::ScopedAStatus status = mPlugin->notifyResolution(width, height);
271 if (!status.isOk()) {
272 ALOGE("notifyResolution txn failed status code: %d", status.getServiceSpecificError());
273 }
274}
275
276status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
277 Mutex::Autolock autoLock(mLock);
278
279 if (mInitCheck != OK) {
280 return mInitCheck;
281 }
282
283 auto err = mPlugin->setMediaDrmSession(toStdVec(sessionId));
Kyle Zhang96af9572022-02-05 06:38:53 +0000284 return statusAidlToStatusT(err);
Kyle Zhang6605add2022-01-13 17:51:23 +0000285}
286
287ssize_t CryptoHalAidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
288 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern,
289 const SharedBufferHidl& hSource, size_t offset,
290 const CryptoPlugin::SubSample* subSamples, size_t numSubSamples,
291 const DestinationBufferHidl& hDestination, AString* errorDetailMsg) {
292 Mutex::Autolock autoLock(mLock);
293
294 if (mInitCheck != OK) {
295 return mInitCheck;
296 }
297
298 Mode aMode;
299 switch (mode) {
300 case CryptoPlugin::kMode_Unencrypted:
301 aMode = Mode::UNENCRYPTED;
302 break;
303 case CryptoPlugin::kMode_AES_CTR:
304 aMode = Mode::AES_CTR;
305 break;
306 case CryptoPlugin::kMode_AES_WV:
307 aMode = Mode::AES_CBC_CTS;
308 break;
309 case CryptoPlugin::kMode_AES_CBC:
310 aMode = Mode::AES_CBC;
311 break;
312 default:
313 return UNKNOWN_ERROR;
314 }
315
316 Pattern aPattern;
317 aPattern.encryptBlocks = pattern.mEncryptBlocks;
318 aPattern.skipBlocks = pattern.mSkipBlocks;
319
320 std::vector<SubSample> stdSubSamples;
321 for (size_t i = 0; i < numSubSamples; i++) {
322 SubSample subSample;
323 subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
324 subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
325 stdSubSamples.push_back(subSample);
326 }
327
328 bool secure;
329 if (hDestination.type == BufferTypeHidl::SHARED_MEMORY) {
330 status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
331 if (status != OK) {
332 return status;
333 }
334 secure = false;
335 } else if (hDestination.type == BufferTypeHidl::NATIVE_HANDLE) {
336 secure = true;
337 } else {
338 android_errorWriteLog(0x534e4554, "70526702");
339 return UNKNOWN_ERROR;
340 }
341
342 status_t status = checkSharedBuffer(hSource);
343 if (status != OK) {
344 return status;
345 }
346
347 status_t err = UNKNOWN_ERROR;
348 mLock.unlock();
349
Robert Shihcc4a2ce2022-02-03 08:27:08 -0800350 std::vector<uint8_t> keyIdAidl(toStdVec(keyId, 16));
351 std::vector<uint8_t> ivAidl(toStdVec(iv, 16));
Kyle Zhang6605add2022-01-13 17:51:23 +0000352 DecryptResult result;
Kyle Zhang96af9572022-02-05 06:38:53 +0000353 ::ndk::ScopedAStatus statusAidl = mPlugin->decrypt(secure,
354 keyIdAidl, ivAidl, aMode, aPattern, stdSubSamples,
Kyle Zhang6605add2022-01-13 17:51:23 +0000355 hidlSharedBufferToAidlSharedBuffer(hSource), offset,
Kyle Zhang96af9572022-02-05 06:38:53 +0000356 hidlDestinationBufferToAidlDestinationBuffer(hDestination), &result);
Kyle Zhang6605add2022-01-13 17:51:23 +0000357
Kyle Zhang96af9572022-02-05 06:38:53 +0000358 err = statusAidlToStatusT(statusAidl);
Kyle Zhang6605add2022-01-13 17:51:23 +0000359 *errorDetailMsg = toString8(result.detailedError);
360 if (err != OK) {
361 ALOGE("Failed on decrypt, error message:%s, bytes written:%d", result.detailedError.c_str(),
362 result.bytesWritten);
363 return err;
364 }
365
366 return result.bytesWritten;
367}
368
369int32_t CryptoHalAidl::setHeap(const sp<HidlMemory>& heap) {
370 if (heap == NULL || mHeapSeqNum < 0) {
371 ALOGE("setHeap(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
372 return -1;
373 }
374
375 Mutex::Autolock autoLock(mLock);
376
377 int32_t seqNum = mHeapSeqNum++;
378 uint32_t bufferId = static_cast<uint32_t>(seqNum);
379 mHeapSizes.add(seqNum, heap->size());
380
381 Ashmem memAidl;
382 memAidl.fd.set(heap->handle()->data[0]);
383 memAidl.size = heap->size();
384
385 ALOGE_IF(!mPlugin->setSharedBufferBase(memAidl, bufferId).isOk(),
386 "setSharedBufferBase(): remote call failed");
387 return seqNum;
388}
389
390void CryptoHalAidl::unsetHeap(int32_t seqNum) {
391 Mutex::Autolock autoLock(mLock);
392
393 /*
394 * Clear the remote shared memory mapping by setting the shared
395 * buffer base to a null hidl_memory.
396 *
397 * TODO: Add a releaseSharedBuffer method in a future DRM HAL
398 * API version to make this explicit.
399 */
400 ssize_t index = mHeapSizes.indexOfKey(seqNum);
401 if (index >= 0) {
402 if (mPlugin != NULL) {
403 uint32_t bufferId = static_cast<uint32_t>(seqNum);
404 Ashmem memAidl;
405 memAidl.fd.set(-1);
406 memAidl.size = 0;
407 ALOGE_IF(!mPlugin->setSharedBufferBase(memAidl, bufferId).isOk(),
408 "setSharedBufferBase(): remote call failed");
409 }
410 mHeapSizes.removeItem(seqNum);
411 }
412}
413
414status_t CryptoHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
415 Mutex::Autolock autoLock(mLock);
416 // Need to convert logmessage
417
Kyle Zhang96af9572022-02-05 06:38:53 +0000418 return DrmUtils::GetLogMessagesAidl<ICryptoPluginAidl>(mPlugin, logs);
Kyle Zhang6605add2022-01-13 17:51:23 +0000419}
420} // namespace android