• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "CryptoHalHidl"
19 #include <utils/Log.h>
20 
21 #include <android/hardware/drm/1.0/types.h>
22 #include <android/hidl/manager/1.2/IServiceManager.h>
23 #include <hidl/ServiceManagement.h>
24 #include <hidlmemory/FrameworkUtils.h>
25 #include <media/hardware/CryptoAPI.h>
26 #include <media/stagefright/MediaErrors.h>
27 #include <media/stagefright/foundation/ADebug.h>
28 #include <media/stagefright/foundation/AString.h>
29 #include <media/stagefright/foundation/hexdump.h>
30 #include <mediadrm/CryptoHalHidl.h>
31 #include <mediadrm/DrmUtils.h>
32 
33 using drm::V1_0::BufferType;
34 using drm::V1_0::DestinationBuffer;
35 using drm::V1_0::ICryptoFactory;
36 using drm::V1_0::ICryptoPlugin;
37 using drm::V1_0::Mode;
38 using drm::V1_0::Pattern;
39 using drm::V1_0::SharedBuffer;
40 using drm::V1_0::Status;
41 using drm::V1_0::SubSample;
42 
43 using ::android::sp;
44 using ::android::DrmUtils::toStatusT;
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 typedef drm::V1_2::Status Status_V1_2;
55 
56 namespace android {
57 
toHidlVec(const Vector<uint8_t> & vector)58 static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t>& vector) {
59     hidl_vec<uint8_t> vec;
60     vec.setToExternal(const_cast<uint8_t*>(vector.array()), vector.size());
61     return vec;
62 }
63 
toHidlVec(const void * ptr,size_t size)64 static hidl_vec<uint8_t> toHidlVec(const void* ptr, size_t size) {
65     hidl_vec<uint8_t> vec;
66     vec.resize(size);
67     memcpy(vec.data(), ptr, size);
68     return vec;
69 }
70 
toHidlArray16(const uint8_t * ptr)71 static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t* ptr) {
72     if (!ptr) {
73         return hidl_array<uint8_t, 16>();
74     }
75     return hidl_array<uint8_t, 16>(ptr);
76 }
77 
toString8(hidl_string hString)78 static String8 toString8(hidl_string hString) {
79     return String8(hString.c_str());
80 }
81 
CryptoHalHidl()82 CryptoHalHidl::CryptoHalHidl()
83     : mFactories(makeCryptoFactories()),
84       mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
85       mHeapSeqNum(0) {}
86 
~CryptoHalHidl()87 CryptoHalHidl::~CryptoHalHidl() {}
88 
makeCryptoFactories()89 Vector<sp<ICryptoFactory>> CryptoHalHidl::makeCryptoFactories() {
90     Vector<sp<ICryptoFactory>> factories;
91 
92     auto manager = hardware::defaultServiceManager1_2();
93     if (manager != NULL) {
94         manager->listManifestByInterface(
95                 drm::V1_0::ICryptoFactory::descriptor,
96                 [&factories](const hidl_vec<hidl_string>& registered) {
97                     for (const auto& instance : registered) {
98                         auto factory = drm::V1_0::ICryptoFactory::getService(instance);
99                         if (factory != NULL) {
100                             ALOGD("found drm@1.0 ICryptoFactory %s", instance.c_str());
101                             factories.push_back(factory);
102                         }
103                     }
104                 });
105         manager->listManifestByInterface(
106                 drm::V1_1::ICryptoFactory::descriptor,
107                 [&factories](const hidl_vec<hidl_string>& registered) {
108                     for (const auto& instance : registered) {
109                         auto factory = drm::V1_1::ICryptoFactory::getService(instance);
110                         if (factory != NULL) {
111                             ALOGD("found drm@1.1 ICryptoFactory %s", instance.c_str());
112                             factories.push_back(factory);
113                         }
114                     }
115                 });
116     }
117 
118     if (factories.size() == 0) {
119         // must be in passthrough mode, load the default passthrough service
120         auto passthrough = ICryptoFactory::getService();
121         if (passthrough != NULL) {
122             ALOGI("makeCryptoFactories: using default passthrough crypto instance");
123             factories.push_back(passthrough);
124         } else {
125             ALOGE("Failed to find any crypto factories");
126         }
127     }
128     return factories;
129 }
130 
makeCryptoPlugin(const sp<ICryptoFactory> & factory,const uint8_t uuid[16],const void * initData,size_t initDataSize)131 sp<ICryptoPlugin> CryptoHalHidl::makeCryptoPlugin(const sp<ICryptoFactory>& factory,
132                                                   const uint8_t uuid[16], const void* initData,
133                                                   size_t initDataSize) {
134     sp<ICryptoPlugin> plugin;
135     Return<void> hResult =
136             factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
137                                   [&](Status status, const sp<ICryptoPlugin>& hPlugin) {
138                                       if (status != Status::OK) {
139                                           ALOGE("Failed to make crypto plugin");
140                                           return;
141                                       }
142                                       plugin = hPlugin;
143                                   });
144     if (!hResult.isOk()) {
145         mInitCheck = DEAD_OBJECT;
146     }
147     return plugin;
148 }
149 
initCheck() const150 status_t CryptoHalHidl::initCheck() const {
151     return mInitCheck;
152 }
153 
isCryptoSchemeSupported(const uint8_t uuid[16])154 bool CryptoHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16]) {
155     Mutex::Autolock autoLock(mLock);
156 
157     for (size_t i = 0; i < mFactories.size(); i++) {
158         if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
159             return true;
160         }
161     }
162     return false;
163 }
164 
createPlugin(const uint8_t uuid[16],const void * data,size_t size)165 status_t CryptoHalHidl::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
166     Mutex::Autolock autoLock(mLock);
167 
168     for (size_t i = 0; i < mFactories.size(); i++) {
169         if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
170             mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
171             if (mPlugin != NULL) {
172                 mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
173             }
174         }
175     }
176 
177     if (mInitCheck == NO_INIT) {
178         mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
179     }
180 
181     return mInitCheck;
182 }
183 
destroyPlugin()184 status_t CryptoHalHidl::destroyPlugin() {
185     Mutex::Autolock autoLock(mLock);
186 
187     if (mInitCheck != OK) {
188         return mInitCheck;
189     }
190 
191     mPlugin.clear();
192     mPluginV1_2.clear();
193     mInitCheck = NO_INIT;
194     return OK;
195 }
196 
requiresSecureDecoderComponent(const char * mime) const197 bool CryptoHalHidl::requiresSecureDecoderComponent(const char* mime) const {
198     Mutex::Autolock autoLock(mLock);
199 
200     if (mInitCheck != OK) {
201         return false;
202     }
203 
204     Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
205     if (!hResult.isOk()) {
206         return false;
207     }
208     return hResult;
209 }
210 
211 /**
212  * If the heap base isn't set, get the heap base from the HidlMemory
213  * and send it to the HAL so it can map a remote heap of the same
214  * size.  Once the heap base is established, shared memory buffers
215  * are sent by providing an offset into the heap and a buffer size.
216  */
setHeapBase(const sp<HidlMemory> & heap)217 int32_t CryptoHalHidl::setHeapBase(const sp<HidlMemory>& heap) {
218     if (heap == NULL || mHeapSeqNum < 0) {
219         ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
220         return -1;
221     }
222 
223     Mutex::Autolock autoLock(mLock);
224 
225     if (mInitCheck != OK) {
226         return -1;
227     }
228 
229     int32_t seqNum = mHeapSeqNum++;
230     uint32_t bufferId = static_cast<uint32_t>(seqNum);
231     mHeapSizes.add(seqNum, heap->size());
232     Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
233     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
234     return seqNum;
235 }
236 
clearHeapBase(int32_t seqNum)237 void CryptoHalHidl::clearHeapBase(int32_t seqNum) {
238     Mutex::Autolock autoLock(mLock);
239 
240     /*
241      * Clear the remote shared memory mapping by setting the shared
242      * buffer base to a null hidl_memory.
243      *
244      * TODO: Add a releaseSharedBuffer method in a future DRM HAL
245      * API version to make this explicit.
246      */
247     ssize_t index = mHeapSizes.indexOfKey(seqNum);
248     if (index >= 0) {
249         if (mPlugin != NULL) {
250             uint32_t bufferId = static_cast<uint32_t>(seqNum);
251             Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
252             ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
253         }
254         mHeapSizes.removeItem(seqNum);
255     }
256 }
257 
checkSharedBuffer(const::SharedBuffer & buffer)258 status_t CryptoHalHidl::checkSharedBuffer(const ::SharedBuffer& buffer) {
259     int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
260     // memory must be in one of the heaps that have been set
261     if (mHeapSizes.indexOfKey(seqNum) < 0) {
262         return UNKNOWN_ERROR;
263     }
264 
265     // memory must be within the address space of the heap
266     size_t heapSize = mHeapSizes.valueFor(seqNum);
267     if (heapSize < buffer.offset + buffer.size || SIZE_MAX - buffer.offset < buffer.size) {
268         android_errorWriteLog(0x534e4554, "76221123");
269         return UNKNOWN_ERROR;
270     }
271 
272     return OK;
273 }
274 
decrypt(const uint8_t keyId[16],const uint8_t iv[16],CryptoPlugin::Mode mode,const CryptoPlugin::Pattern & pattern,const drm::V1_0::SharedBuffer & hSource,size_t offset,const CryptoPlugin::SubSample * subSamples,size_t numSubSamples,const drm::V1_0::DestinationBuffer & hDestination,AString * errorDetailMsg)275 ssize_t CryptoHalHidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
276                                CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern,
277                                const drm::V1_0::SharedBuffer& hSource, size_t offset,
278                                const CryptoPlugin::SubSample* subSamples, size_t numSubSamples,
279                                const drm::V1_0::DestinationBuffer& hDestination,
280                                AString* errorDetailMsg) {
281     Mutex::Autolock autoLock(mLock);
282 
283     if (mInitCheck != OK) {
284         return mInitCheck;
285     }
286 
287     Mode hMode;
288     switch (mode) {
289         case CryptoPlugin::kMode_Unencrypted:
290             hMode = Mode::UNENCRYPTED;
291             break;
292         case CryptoPlugin::kMode_AES_CTR:
293             hMode = Mode::AES_CTR;
294             break;
295         case CryptoPlugin::kMode_AES_WV:
296             hMode = Mode::AES_CBC_CTS;
297             break;
298         case CryptoPlugin::kMode_AES_CBC:
299             hMode = Mode::AES_CBC;
300             break;
301         default:
302             return UNKNOWN_ERROR;
303     }
304 
305     Pattern hPattern;
306     hPattern.encryptBlocks = pattern.mEncryptBlocks;
307     hPattern.skipBlocks = pattern.mSkipBlocks;
308 
309     std::vector<SubSample> stdSubSamples;
310     for (size_t i = 0; i < numSubSamples; i++) {
311         SubSample subSample;
312         subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
313         subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
314         stdSubSamples.push_back(subSample);
315     }
316     auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
317 
318     bool secure;
319     if (hDestination.type == BufferType::SHARED_MEMORY) {
320         status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
321         if (status != OK) {
322             return status;
323         }
324         secure = false;
325     } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
326         secure = true;
327     } else {
328         android_errorWriteLog(0x534e4554, "70526702");
329         return UNKNOWN_ERROR;
330     }
331 
332     status_t status = checkSharedBuffer(hSource);
333     if (status != OK) {
334         return status;
335     }
336 
337     status_t err = UNKNOWN_ERROR;
338     uint32_t bytesWritten = 0;
339 
340     Return<void> hResult;
341 
342     mLock.unlock();
343     if (mPluginV1_2 != NULL) {
344         hResult = mPluginV1_2->decrypt_1_2(
345                 secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples,
346                 hSource, offset, hDestination,
347                 [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
348                     if (status == Status_V1_2::OK) {
349                         bytesWritten = hBytesWritten;
350                         if (errorDetailMsg != nullptr) {
351                             *errorDetailMsg = toString8(hDetailedError);
352                         }
353                     }
354                     err = toStatusT(status);
355                 });
356     } else {
357         hResult = mPlugin->decrypt(
358                 secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples,
359                 hSource, offset, hDestination,
360                 [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
361                     if (status == Status::OK) {
362                         bytesWritten = hBytesWritten;
363                         if (errorDetailMsg != nullptr) {
364                             *errorDetailMsg = toString8(hDetailedError);
365                         }
366                     }
367                     err = toStatusT(status);
368                 });
369     }
370 
371     err = hResult.isOk() ? err : DEAD_OBJECT;
372     if (err == OK) {
373         return bytesWritten;
374     }
375     return err;
376 }
377 
notifyResolution(uint32_t width,uint32_t height)378 void CryptoHalHidl::notifyResolution(uint32_t width, uint32_t height) {
379     Mutex::Autolock autoLock(mLock);
380 
381     if (mInitCheck != OK) {
382         return;
383     }
384 
385     auto hResult = mPlugin->notifyResolution(width, height);
386     ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
387 }
388 
setMediaDrmSession(const Vector<uint8_t> & sessionId)389 DrmStatus CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
390     Mutex::Autolock autoLock(mLock);
391 
392     if (mInitCheck != OK) {
393         return mInitCheck;
394     }
395 
396     auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId));
397     return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
398 }
399 
getLogMessages(Vector<drm::V1_4::LogMessage> & logs) const400 status_t CryptoHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
401     Mutex::Autolock autoLock(mLock);
402     return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs);
403 }
404 }  // namespace android
405