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