1 /*
2 * Copyright (C) 2013 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 "Drm"
19 #include <utils/Log.h>
20
21 #include <dirent.h>
22 #include <dlfcn.h>
23
24 #include <media/DrmPluginPath.h>
25 #include <media/DrmSessionClientInterface.h>
26 #include <media/DrmSessionManager.h>
27 #include <media/Drm.h>
28 #include <media/drm/DrmAPI.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/AString.h>
31 #include <media/stagefright/foundation/hexdump.h>
32 #include <media/stagefright/MediaErrors.h>
33 #include <binder/IServiceManager.h>
34 #include <binder/IPCThreadState.h>
35
36 namespace android {
37
getCallingPid()38 static inline int getCallingPid() {
39 return IPCThreadState::self()->getCallingPid();
40 }
41
checkPermission(const char * permissionString)42 static bool checkPermission(const char* permissionString) {
43 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
44 bool ok = checkCallingPermission(String16(permissionString));
45 if (!ok) ALOGE("Request requires %s", permissionString);
46 return ok;
47 }
48
49 KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
50 KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
51 Mutex Drm::mMapLock;
52 Mutex Drm::mLock;
53
operator <(const Vector<uint8_t> & lhs,const Vector<uint8_t> & rhs)54 static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
55 if (lhs.size() < rhs.size()) {
56 return true;
57 } else if (lhs.size() > rhs.size()) {
58 return false;
59 }
60
61 return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
62 }
63
64 struct DrmSessionClient : public DrmSessionClientInterface {
DrmSessionClientandroid::DrmSessionClient65 explicit DrmSessionClient(Drm* drm) : mDrm(drm) {}
66
reclaimSessionandroid::DrmSessionClient67 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
68 sp<Drm> drm = mDrm.promote();
69 if (drm == NULL) {
70 return true;
71 }
72 status_t err = drm->closeSession(sessionId);
73 if (err != OK) {
74 return false;
75 }
76 drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL);
77 return true;
78 }
79
80 protected:
~DrmSessionClientandroid::DrmSessionClient81 virtual ~DrmSessionClient() {}
82
83 private:
84 wp<Drm> mDrm;
85
86 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
87 };
88
Drm()89 Drm::Drm()
90 : mInitCheck(NO_INIT),
91 mDrmSessionClient(new DrmSessionClient(this)),
92 mListener(NULL),
93 mFactory(NULL),
94 mPlugin(NULL) {
95 }
96
~Drm()97 Drm::~Drm() {
98 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
99 delete mPlugin;
100 mPlugin = NULL;
101 closeFactory();
102 }
103
closeFactory()104 void Drm::closeFactory() {
105 delete mFactory;
106 mFactory = NULL;
107 mLibrary.clear();
108 }
109
initCheck() const110 status_t Drm::initCheck() const {
111 return mInitCheck;
112 }
113
setListener(const sp<IDrmClient> & listener)114 status_t Drm::setListener(const sp<IDrmClient>& listener)
115 {
116 Mutex::Autolock lock(mEventLock);
117 if (mListener != NULL){
118 IInterface::asBinder(mListener)->unlinkToDeath(this);
119 }
120 if (listener != NULL) {
121 IInterface::asBinder(listener)->linkToDeath(this);
122 }
123 mListener = listener;
124 return NO_ERROR;
125 }
126
sendEvent(DrmPlugin::EventType eventType,int extra,Vector<uint8_t> const * sessionId,Vector<uint8_t> const * data)127 void Drm::sendEvent(DrmPlugin::EventType eventType, int extra,
128 Vector<uint8_t> const *sessionId,
129 Vector<uint8_t> const *data)
130 {
131 mEventLock.lock();
132 sp<IDrmClient> listener = mListener;
133 mEventLock.unlock();
134
135 if (listener != NULL) {
136 Parcel obj;
137 writeByteArray(obj, sessionId);
138 writeByteArray(obj, data);
139
140 Mutex::Autolock lock(mNotifyLock);
141 listener->notify(eventType, extra, &obj);
142 }
143 }
144
sendExpirationUpdate(Vector<uint8_t> const * sessionId,int64_t expiryTimeInMS)145 void Drm::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
146 int64_t expiryTimeInMS)
147 {
148 mEventLock.lock();
149 sp<IDrmClient> listener = mListener;
150 mEventLock.unlock();
151
152 if (listener != NULL) {
153 Parcel obj;
154 writeByteArray(obj, sessionId);
155 obj.writeInt64(expiryTimeInMS);
156
157 Mutex::Autolock lock(mNotifyLock);
158 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
159 }
160 }
161
sendKeysChange(Vector<uint8_t> const * sessionId,Vector<DrmPlugin::KeyStatus> const * keyStatusList,bool hasNewUsableKey)162 void Drm::sendKeysChange(Vector<uint8_t> const *sessionId,
163 Vector<DrmPlugin::KeyStatus> const *keyStatusList,
164 bool hasNewUsableKey)
165 {
166 mEventLock.lock();
167 sp<IDrmClient> listener = mListener;
168 mEventLock.unlock();
169
170 if (listener != NULL) {
171 Parcel obj;
172 writeByteArray(obj, sessionId);
173
174 size_t nkeys = keyStatusList->size();
175 obj.writeInt32(keyStatusList->size());
176 for (size_t i = 0; i < nkeys; ++i) {
177 const DrmPlugin::KeyStatus *keyStatus = &keyStatusList->itemAt(i);
178 writeByteArray(obj, &keyStatus->mKeyId);
179 obj.writeInt32(keyStatus->mType);
180 }
181 obj.writeInt32(hasNewUsableKey);
182
183 Mutex::Autolock lock(mNotifyLock);
184 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
185 }
186 }
187
188 /*
189 * Search the plugins directory for a plugin that supports the scheme
190 * specified by uuid
191 *
192 * If found:
193 * mLibrary holds a strong pointer to the dlopen'd library
194 * mFactory is set to the library's factory method
195 * mInitCheck is set to OK
196 *
197 * If not found:
198 * mLibrary is cleared and mFactory are set to NULL
199 * mInitCheck is set to an error (!OK)
200 */
findFactoryForScheme(const uint8_t uuid[16])201 void Drm::findFactoryForScheme(const uint8_t uuid[16]) {
202
203 closeFactory();
204
205 // lock static maps
206 Mutex::Autolock autoLock(mMapLock);
207
208 // first check cache
209 Vector<uint8_t> uuidVector;
210 uuidVector.appendArray(uuid, sizeof(uuid[0]) * 16);
211 ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector);
212 if (index >= 0) {
213 if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) {
214 mInitCheck = OK;
215 return;
216 } else {
217 ALOGE("Failed to load from cached library path!");
218 mInitCheck = ERROR_UNSUPPORTED;
219 return;
220 }
221 }
222
223 // no luck, have to search
224 String8 dirPath(getDrmPluginPath());
225 DIR* pDir = opendir(dirPath.string());
226
227 if (pDir == NULL) {
228 mInitCheck = ERROR_UNSUPPORTED;
229 ALOGE("Failed to open plugin directory %s", dirPath.string());
230 return;
231 }
232
233
234 struct dirent* pEntry;
235 while ((pEntry = readdir(pDir))) {
236
237 String8 pluginPath = dirPath + "/" + pEntry->d_name;
238
239 if (pluginPath.getPathExtension() == ".so") {
240
241 if (loadLibraryForScheme(pluginPath, uuid)) {
242 mUUIDToLibraryPathMap.add(uuidVector, pluginPath);
243 mInitCheck = OK;
244 closedir(pDir);
245 return;
246 }
247 }
248 }
249
250 closedir(pDir);
251
252 ALOGE("Failed to find drm plugin");
253 mInitCheck = ERROR_UNSUPPORTED;
254 }
255
loadLibraryForScheme(const String8 & path,const uint8_t uuid[16])256 bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) {
257
258 // get strong pointer to open shared library
259 ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
260 if (index >= 0) {
261 mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
262 } else {
263 index = mLibraryPathToOpenLibraryMap.add(path, NULL);
264 }
265
266 if (!mLibrary.get()) {
267 mLibrary = new SharedLibrary(path);
268 if (!*mLibrary) {
269 return false;
270 }
271
272 mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
273 }
274
275 typedef DrmFactory *(*CreateDrmFactoryFunc)();
276
277 CreateDrmFactoryFunc createDrmFactory =
278 (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory");
279
280 if (createDrmFactory == NULL ||
281 (mFactory = createDrmFactory()) == NULL ||
282 !mFactory->isCryptoSchemeSupported(uuid)) {
283 closeFactory();
284 return false;
285 }
286 return true;
287 }
288
isCryptoSchemeSupported(const uint8_t uuid[16],const String8 & mimeType)289 bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
290
291 Mutex::Autolock autoLock(mLock);
292
293 if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
294 findFactoryForScheme(uuid);
295 if (mInitCheck != OK) {
296 return false;
297 }
298 }
299
300 if (mimeType != "") {
301 return mFactory->isContentTypeSupported(mimeType);
302 }
303
304 return true;
305 }
306
createPlugin(const uint8_t uuid[16],const String8 &)307 status_t Drm::createPlugin(const uint8_t uuid[16],
308 const String8& /* appPackageName */) {
309 Mutex::Autolock autoLock(mLock);
310
311 if (mPlugin != NULL) {
312 return -EINVAL;
313 }
314
315 if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
316 findFactoryForScheme(uuid);
317 }
318
319 if (mInitCheck != OK) {
320 return mInitCheck;
321 }
322
323 status_t result = mFactory->createDrmPlugin(uuid, &mPlugin);
324 if (mPlugin) {
325 mPlugin->setListener(this);
326 } else {
327 ALOGE("Failed to create plugin");
328 return UNEXPECTED_NULL;
329 }
330 return result;
331 }
332
destroyPlugin()333 status_t Drm::destroyPlugin() {
334 Mutex::Autolock autoLock(mLock);
335
336 if (mInitCheck != OK) {
337 return mInitCheck;
338 }
339
340 if (mPlugin == NULL) {
341 return -EINVAL;
342 }
343
344 setListener(NULL);
345 delete mPlugin;
346 mPlugin = NULL;
347
348 return OK;
349 }
350
openSession(Vector<uint8_t> & sessionId)351 status_t Drm::openSession(Vector<uint8_t> &sessionId) {
352 Mutex::Autolock autoLock(mLock);
353
354 if (mInitCheck != OK) {
355 return mInitCheck;
356 }
357
358 if (mPlugin == NULL) {
359 return -EINVAL;
360 }
361
362 status_t err = mPlugin->openSession(sessionId);
363 if (err == ERROR_DRM_RESOURCE_BUSY) {
364 bool retry = false;
365 mLock.unlock();
366 // reclaimSession may call back to closeSession, since mLock is shared between Drm
367 // instances, we should unlock here to avoid deadlock.
368 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
369 mLock.lock();
370 if (mInitCheck != OK) {
371 return mInitCheck;
372 }
373
374 if (mPlugin == NULL) {
375 return -EINVAL;
376 }
377 if (retry) {
378 err = mPlugin->openSession(sessionId);
379 }
380 }
381 if (err == OK) {
382 DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId);
383 }
384 return err;
385 }
386
closeSession(Vector<uint8_t> const & sessionId)387 status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
388 Mutex::Autolock autoLock(mLock);
389
390 if (mInitCheck != OK) {
391 return mInitCheck;
392 }
393
394 if (mPlugin == NULL) {
395 return -EINVAL;
396 }
397
398 status_t err = mPlugin->closeSession(sessionId);
399 if (err == OK) {
400 DrmSessionManager::Instance()->removeSession(sessionId);
401 }
402 return err;
403 }
404
getKeyRequest(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & initData,String8 const & mimeType,DrmPlugin::KeyType keyType,KeyedVector<String8,String8> const & optionalParameters,Vector<uint8_t> & request,String8 & defaultUrl,DrmPlugin::KeyRequestType * keyRequestType)405 status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
406 Vector<uint8_t> const &initData,
407 String8 const &mimeType, DrmPlugin::KeyType keyType,
408 KeyedVector<String8, String8> const &optionalParameters,
409 Vector<uint8_t> &request, String8 &defaultUrl,
410 DrmPlugin::KeyRequestType *keyRequestType) {
411 Mutex::Autolock autoLock(mLock);
412
413 if (mInitCheck != OK) {
414 return mInitCheck;
415 }
416
417 if (mPlugin == NULL) {
418 return -EINVAL;
419 }
420
421 DrmSessionManager::Instance()->useSession(sessionId);
422
423 return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
424 optionalParameters, request, defaultUrl,
425 keyRequestType);
426 }
427
provideKeyResponse(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & response,Vector<uint8_t> & keySetId)428 status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId,
429 Vector<uint8_t> const &response,
430 Vector<uint8_t> &keySetId) {
431 Mutex::Autolock autoLock(mLock);
432
433 if (mInitCheck != OK) {
434 return mInitCheck;
435 }
436
437 if (mPlugin == NULL) {
438 return -EINVAL;
439 }
440
441 DrmSessionManager::Instance()->useSession(sessionId);
442
443 return mPlugin->provideKeyResponse(sessionId, response, keySetId);
444 }
445
removeKeys(Vector<uint8_t> const & keySetId)446 status_t Drm::removeKeys(Vector<uint8_t> const &keySetId) {
447 Mutex::Autolock autoLock(mLock);
448
449 if (mInitCheck != OK) {
450 return mInitCheck;
451 }
452
453 if (mPlugin == NULL) {
454 return -EINVAL;
455 }
456
457 return mPlugin->removeKeys(keySetId);
458 }
459
restoreKeys(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keySetId)460 status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId,
461 Vector<uint8_t> const &keySetId) {
462 Mutex::Autolock autoLock(mLock);
463
464 if (mInitCheck != OK) {
465 return mInitCheck;
466 }
467
468 if (mPlugin == NULL) {
469 return -EINVAL;
470 }
471
472 DrmSessionManager::Instance()->useSession(sessionId);
473
474 return mPlugin->restoreKeys(sessionId, keySetId);
475 }
476
queryKeyStatus(Vector<uint8_t> const & sessionId,KeyedVector<String8,String8> & infoMap) const477 status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId,
478 KeyedVector<String8, String8> &infoMap) const {
479 Mutex::Autolock autoLock(mLock);
480
481 if (mInitCheck != OK) {
482 return mInitCheck;
483 }
484
485 if (mPlugin == NULL) {
486 return -EINVAL;
487 }
488
489 DrmSessionManager::Instance()->useSession(sessionId);
490
491 return mPlugin->queryKeyStatus(sessionId, infoMap);
492 }
493
getProvisionRequest(String8 const & certType,String8 const & certAuthority,Vector<uint8_t> & request,String8 & defaultUrl)494 status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority,
495 Vector<uint8_t> &request, String8 &defaultUrl) {
496 Mutex::Autolock autoLock(mLock);
497
498 if (mInitCheck != OK) {
499 return mInitCheck;
500 }
501
502 if (mPlugin == NULL) {
503 return -EINVAL;
504 }
505
506 return mPlugin->getProvisionRequest(certType, certAuthority,
507 request, defaultUrl);
508 }
509
provideProvisionResponse(Vector<uint8_t> const & response,Vector<uint8_t> & certificate,Vector<uint8_t> & wrappedKey)510 status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response,
511 Vector<uint8_t> &certificate,
512 Vector<uint8_t> &wrappedKey) {
513 Mutex::Autolock autoLock(mLock);
514
515 if (mInitCheck != OK) {
516 return mInitCheck;
517 }
518
519 if (mPlugin == NULL) {
520 return -EINVAL;
521 }
522
523 return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
524 }
525
getSecureStops(List<Vector<uint8_t>> & secureStops)526 status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
527 Mutex::Autolock autoLock(mLock);
528
529 if (mInitCheck != OK) {
530 return mInitCheck;
531 }
532
533 if (mPlugin == NULL) {
534 return -EINVAL;
535 }
536
537 return mPlugin->getSecureStops(secureStops);
538 }
539
getSecureStop(Vector<uint8_t> const & ssid,Vector<uint8_t> & secureStop)540 status_t Drm::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
541 Mutex::Autolock autoLock(mLock);
542
543 if (mInitCheck != OK) {
544 return mInitCheck;
545 }
546
547 if (mPlugin == NULL) {
548 return -EINVAL;
549 }
550
551 return mPlugin->getSecureStop(ssid, secureStop);
552 }
553
releaseSecureStops(Vector<uint8_t> const & ssRelease)554 status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
555 Mutex::Autolock autoLock(mLock);
556
557 if (mInitCheck != OK) {
558 return mInitCheck;
559 }
560
561 if (mPlugin == NULL) {
562 return -EINVAL;
563 }
564
565 return mPlugin->releaseSecureStops(ssRelease);
566 }
567
releaseAllSecureStops()568 status_t Drm::releaseAllSecureStops() {
569 Mutex::Autolock autoLock(mLock);
570
571 if (mInitCheck != OK) {
572 return mInitCheck;
573 }
574
575 if (mPlugin == NULL) {
576 return -EINVAL;
577 }
578
579 return mPlugin->releaseAllSecureStops();
580 }
581
getPropertyString(String8 const & name,String8 & value) const582 status_t Drm::getPropertyString(String8 const &name, String8 &value ) const {
583 Mutex::Autolock autoLock(mLock);
584
585 if (mInitCheck != OK) {
586 return mInitCheck;
587 }
588
589 if (mPlugin == NULL) {
590 return -EINVAL;
591 }
592
593 return mPlugin->getPropertyString(name, value);
594 }
595
getPropertyByteArray(String8 const & name,Vector<uint8_t> & value) const596 status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
597 Mutex::Autolock autoLock(mLock);
598
599 if (mInitCheck != OK) {
600 return mInitCheck;
601 }
602
603 if (mPlugin == NULL) {
604 return -EINVAL;
605 }
606
607 return mPlugin->getPropertyByteArray(name, value);
608 }
609
setPropertyString(String8 const & name,String8 const & value) const610 status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const {
611 Mutex::Autolock autoLock(mLock);
612
613 if (mInitCheck != OK) {
614 return mInitCheck;
615 }
616
617 if (mPlugin == NULL) {
618 return -EINVAL;
619 }
620
621 return mPlugin->setPropertyString(name, value);
622 }
623
setPropertyByteArray(String8 const & name,Vector<uint8_t> const & value) const624 status_t Drm::setPropertyByteArray(String8 const &name,
625 Vector<uint8_t> const &value ) const {
626 Mutex::Autolock autoLock(mLock);
627
628 if (mInitCheck != OK) {
629 return mInitCheck;
630 }
631
632 if (mPlugin == NULL) {
633 return -EINVAL;
634 }
635
636 return mPlugin->setPropertyByteArray(name, value);
637 }
638
639
setCipherAlgorithm(Vector<uint8_t> const & sessionId,String8 const & algorithm)640 status_t Drm::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
641 String8 const &algorithm) {
642 Mutex::Autolock autoLock(mLock);
643
644 if (mInitCheck != OK) {
645 return mInitCheck;
646 }
647
648 if (mPlugin == NULL) {
649 return -EINVAL;
650 }
651
652 DrmSessionManager::Instance()->useSession(sessionId);
653
654 return mPlugin->setCipherAlgorithm(sessionId, algorithm);
655 }
656
setMacAlgorithm(Vector<uint8_t> const & sessionId,String8 const & algorithm)657 status_t Drm::setMacAlgorithm(Vector<uint8_t> const &sessionId,
658 String8 const &algorithm) {
659 Mutex::Autolock autoLock(mLock);
660
661 if (mInitCheck != OK) {
662 return mInitCheck;
663 }
664
665 if (mPlugin == NULL) {
666 return -EINVAL;
667 }
668
669 DrmSessionManager::Instance()->useSession(sessionId);
670
671 return mPlugin->setMacAlgorithm(sessionId, algorithm);
672 }
673
encrypt(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & input,Vector<uint8_t> const & iv,Vector<uint8_t> & output)674 status_t Drm::encrypt(Vector<uint8_t> const &sessionId,
675 Vector<uint8_t> const &keyId,
676 Vector<uint8_t> const &input,
677 Vector<uint8_t> const &iv,
678 Vector<uint8_t> &output) {
679 Mutex::Autolock autoLock(mLock);
680
681 if (mInitCheck != OK) {
682 return mInitCheck;
683 }
684
685 if (mPlugin == NULL) {
686 return -EINVAL;
687 }
688
689 DrmSessionManager::Instance()->useSession(sessionId);
690
691 return mPlugin->encrypt(sessionId, keyId, input, iv, output);
692 }
693
decrypt(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & input,Vector<uint8_t> const & iv,Vector<uint8_t> & output)694 status_t Drm::decrypt(Vector<uint8_t> const &sessionId,
695 Vector<uint8_t> const &keyId,
696 Vector<uint8_t> const &input,
697 Vector<uint8_t> const &iv,
698 Vector<uint8_t> &output) {
699 Mutex::Autolock autoLock(mLock);
700
701 if (mInitCheck != OK) {
702 return mInitCheck;
703 }
704
705 if (mPlugin == NULL) {
706 return -EINVAL;
707 }
708
709 DrmSessionManager::Instance()->useSession(sessionId);
710
711 return mPlugin->decrypt(sessionId, keyId, input, iv, output);
712 }
713
sign(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & message,Vector<uint8_t> & signature)714 status_t Drm::sign(Vector<uint8_t> const &sessionId,
715 Vector<uint8_t> const &keyId,
716 Vector<uint8_t> const &message,
717 Vector<uint8_t> &signature) {
718 Mutex::Autolock autoLock(mLock);
719
720 if (mInitCheck != OK) {
721 return mInitCheck;
722 }
723
724 if (mPlugin == NULL) {
725 return -EINVAL;
726 }
727
728 DrmSessionManager::Instance()->useSession(sessionId);
729
730 return mPlugin->sign(sessionId, keyId, message, signature);
731 }
732
verify(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & message,Vector<uint8_t> const & signature,bool & match)733 status_t Drm::verify(Vector<uint8_t> const &sessionId,
734 Vector<uint8_t> const &keyId,
735 Vector<uint8_t> const &message,
736 Vector<uint8_t> const &signature,
737 bool &match) {
738 Mutex::Autolock autoLock(mLock);
739
740 if (mInitCheck != OK) {
741 return mInitCheck;
742 }
743
744 if (mPlugin == NULL) {
745 return -EINVAL;
746 }
747
748 DrmSessionManager::Instance()->useSession(sessionId);
749
750 return mPlugin->verify(sessionId, keyId, message, signature, match);
751 }
752
signRSA(Vector<uint8_t> const & sessionId,String8 const & algorithm,Vector<uint8_t> const & message,Vector<uint8_t> const & wrappedKey,Vector<uint8_t> & signature)753 status_t Drm::signRSA(Vector<uint8_t> const &sessionId,
754 String8 const &algorithm,
755 Vector<uint8_t> const &message,
756 Vector<uint8_t> const &wrappedKey,
757 Vector<uint8_t> &signature) {
758 Mutex::Autolock autoLock(mLock);
759
760 if (mInitCheck != OK) {
761 return mInitCheck;
762 }
763
764 if (mPlugin == NULL) {
765 return -EINVAL;
766 }
767
768 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
769 return -EPERM;
770 }
771
772 DrmSessionManager::Instance()->useSession(sessionId);
773
774 return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
775 }
776
binderDied(const wp<IBinder> & the_late_who __unused)777 void Drm::binderDied(const wp<IBinder> &the_late_who __unused)
778 {
779 mEventLock.lock();
780 mListener.clear();
781 mEventLock.unlock();
782
783 Mutex::Autolock autoLock(mLock);
784 delete mPlugin;
785 mPlugin = NULL;
786 closeFactory();
787 }
788
writeByteArray(Parcel & obj,Vector<uint8_t> const * array)789 void Drm::writeByteArray(Parcel &obj, Vector<uint8_t> const *array)
790 {
791 if (array && array->size()) {
792 obj.writeInt32(array->size());
793 obj.write(array->array(), array->size());
794 } else {
795 obj.writeInt32(0);
796 }
797 }
798
799 } // namespace android
800