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