DrmHal.cpp revision f3a591cc9d604133e2c5cae3d34322b52cd7575d
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 "DrmHal"
19#include <utils/Log.h>
20
21#include <binder/IPCThreadState.h>
22#include <binder/IServiceManager.h>
23#include <dirent.h>
24#include <dlfcn.h>
25
26#include <android/hardware/drm/1.0/IDrmFactory.h>
27#include <android/hardware/drm/1.0/IDrmPlugin.h>
28#include <android/hardware/drm/1.0/types.h>
29
30#include <media/DrmHal.h>
31#include <media/DrmSessionClientInterface.h>
32#include <media/DrmSessionManager.h>
33#include <media/drm/DrmAPI.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/foundation/AString.h>
36#include <media/stagefright/foundation/hexdump.h>
37#include <media/stagefright/MediaErrors.h>
38
39using ::android::hardware::drm::V1_0::EventType;
40using ::android::hardware::drm::V1_0::IDrmFactory;
41using ::android::hardware::drm::V1_0::IDrmPlugin;
42using ::android::hardware::drm::V1_0::KeyedVector;
43using ::android::hardware::drm::V1_0::KeyRequestType;
44using ::android::hardware::drm::V1_0::KeyStatus;
45using ::android::hardware::drm::V1_0::KeyStatusType;
46using ::android::hardware::drm::V1_0::KeyType;
47using ::android::hardware::drm::V1_0::KeyValue;
48using ::android::hardware::drm::V1_0::SecureStop;
49using ::android::hardware::drm::V1_0::Status;
50using ::android::hardware::hidl_array;
51using ::android::hardware::hidl_string;
52using ::android::hardware::hidl_vec;
53using ::android::hardware::Return;
54using ::android::hardware::Void;
55using ::android::sp;
56
57namespace android {
58
59static inline int getCallingPid() {
60    return IPCThreadState::self()->getCallingPid();
61}
62
63static bool checkPermission(const char* permissionString) {
64    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
65    bool ok = checkCallingPermission(String16(permissionString));
66    if (!ok) ALOGE("Request requires %s", permissionString);
67    return ok;
68}
69
70static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
71    Vector<uint8_t> vector;
72    vector.appendArray(vec.data(), vec.size());
73    return *const_cast<const Vector<uint8_t> *>(&vector);
74}
75
76static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
77    hidl_vec<uint8_t> vec;
78    vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
79    return vec;
80}
81
82static String8 toString8(const hidl_string &string) {
83    return String8(string.c_str());
84}
85
86static hidl_string toHidlString(const String8& string) {
87    return hidl_string(string.string());
88}
89
90
91static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
92        keyedVector) {
93    std::vector<KeyValue> stdKeyedVector;
94    for (size_t i = 0; i < keyedVector.size(); i++) {
95        KeyValue keyValue;
96        keyValue.key = toHidlString(keyedVector.keyAt(i));
97        keyValue.value = toHidlString(keyedVector.valueAt(i));
98        stdKeyedVector.push_back(keyValue);
99    }
100    return ::KeyedVector(stdKeyedVector);
101}
102
103static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
104        hKeyedVector) {
105    KeyedVector<String8, String8> keyedVector;
106    for (size_t i = 0; i < hKeyedVector.size(); i++) {
107        keyedVector.add(toString8(hKeyedVector[i].key),
108                toString8(hKeyedVector[i].value));
109    }
110    return keyedVector;
111}
112
113static List<Vector<uint8_t> > toSecureStops(const hidl_vec<SecureStop>&
114        hSecureStops) {
115    List<Vector<uint8_t> > secureStops;
116    for (size_t i = 0; i < hSecureStops.size(); i++) {
117        secureStops.push_back(toVector(hSecureStops[i].opaqueData));
118    }
119    return secureStops;
120}
121
122static status_t toStatusT(Status status) {
123    switch (status) {
124    case Status::OK:
125        return OK;
126        break;
127    case Status::ERROR_DRM_NO_LICENSE:
128        return ERROR_DRM_NO_LICENSE;
129        break;
130    case Status::ERROR_DRM_LICENSE_EXPIRED:
131        return ERROR_DRM_LICENSE_EXPIRED;
132        break;
133    case Status::ERROR_DRM_SESSION_NOT_OPENED:
134        return ERROR_DRM_SESSION_NOT_OPENED;
135        break;
136    case Status::ERROR_DRM_CANNOT_HANDLE:
137        return ERROR_DRM_CANNOT_HANDLE;
138        break;
139    case Status::ERROR_DRM_INVALID_STATE:
140        return ERROR_DRM_TAMPER_DETECTED;
141        break;
142    case Status::BAD_VALUE:
143        return BAD_VALUE;
144        break;
145    case Status::ERROR_DRM_NOT_PROVISIONED:
146        return ERROR_DRM_NOT_PROVISIONED;
147        break;
148    case Status::ERROR_DRM_RESOURCE_BUSY:
149        return ERROR_DRM_RESOURCE_BUSY;
150        break;
151    case Status::ERROR_DRM_DEVICE_REVOKED:
152        return ERROR_DRM_DEVICE_REVOKED;
153        break;
154    case Status::ERROR_DRM_UNKNOWN:
155    default:
156        return ERROR_DRM_UNKNOWN;
157        break;
158    }
159}
160
161
162Mutex DrmHal::mLock;
163
164struct DrmSessionClient : public DrmSessionClientInterface {
165    explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
166
167    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
168        sp<DrmHal> drm = mDrm.promote();
169        if (drm == NULL) {
170            return true;
171        }
172        status_t err = drm->closeSession(sessionId);
173        if (err != OK) {
174            return false;
175        }
176        drm->sendEvent(EventType::SESSION_RECLAIMED,
177                toHidlVec(sessionId), hidl_vec<uint8_t>());
178        return true;
179    }
180
181protected:
182    virtual ~DrmSessionClient() {}
183
184private:
185    wp<DrmHal> mDrm;
186
187    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
188};
189
190DrmHal::DrmHal()
191   : mDrmSessionClient(new DrmSessionClient(this)),
192     mFactory(makeDrmFactory()),
193     mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT) {
194}
195
196DrmHal::~DrmHal() {
197    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
198}
199
200sp<IDrmFactory> DrmHal::makeDrmFactory() {
201    sp<IDrmFactory> factory = IDrmFactory::getService("drm");
202    if (factory == NULL) {
203        ALOGE("Failed to make drm factory");
204    }
205    ALOGD("makeDrmFactory: service is %s",
206            factory->isRemote() ? "Remote" : "Not Remote");
207    return factory;
208}
209
210sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16],
211        const String8& appPackageName) {
212    if (mFactory == NULL){
213        return NULL;
214    }
215
216    sp<IDrmPlugin> plugin;
217    Return<void> hResult = mFactory->createPlugin(uuid, appPackageName.string(),
218            [&](Status status, const sp<IDrmPlugin>& hPlugin) {
219      if (status != Status::OK) {
220        ALOGD("Failed to make drm plugin");
221        return;
222      }
223      plugin = hPlugin;
224    }
225    );
226    return plugin;
227}
228
229status_t DrmHal::initCheck() const {
230    return mInitCheck;
231}
232
233status_t DrmHal::setListener(const sp<IDrmClient>& listener)
234{
235    Mutex::Autolock lock(mEventLock);
236    if (mListener != NULL){
237        IInterface::asBinder(mListener)->unlinkToDeath(this);
238    }
239    if (listener != NULL) {
240        IInterface::asBinder(listener)->linkToDeath(this);
241    }
242    mListener = listener;
243    return NO_ERROR;
244}
245
246Return<void> DrmHal::sendEvent(EventType hEventType,
247        const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
248
249    mEventLock.lock();
250    sp<IDrmClient> listener = mListener;
251    mEventLock.unlock();
252
253    if (listener != NULL) {
254        Parcel obj;
255        writeByteArray(obj, sessionId);
256        writeByteArray(obj, data);
257
258        Mutex::Autolock lock(mNotifyLock);
259        DrmPlugin::EventType eventType;
260        switch(hEventType) {
261        case EventType::PROVISION_REQUIRED:
262            eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
263            break;
264        case EventType::KEY_NEEDED:
265            eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
266            break;
267        case EventType::KEY_EXPIRED:
268            eventType = DrmPlugin::kDrmPluginEventKeyExpired;
269            break;
270        case EventType::VENDOR_DEFINED:
271            eventType = DrmPlugin::kDrmPluginEventVendorDefined;
272            break;
273        default:
274            return Void();
275        }
276        listener->notify(eventType, 0, &obj);
277    }
278    return Void();
279}
280
281Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
282        int64_t expiryTimeInMS) {
283
284    mEventLock.lock();
285    sp<IDrmClient> listener = mListener;
286    mEventLock.unlock();
287
288    if (listener != NULL) {
289        Parcel obj;
290        writeByteArray(obj, sessionId);
291        obj.writeInt64(expiryTimeInMS);
292
293        Mutex::Autolock lock(mNotifyLock);
294        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
295    }
296    return Void();
297}
298
299Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
300        const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
301
302    mEventLock.lock();
303    sp<IDrmClient> listener = mListener;
304    mEventLock.unlock();
305
306    if (listener != NULL) {
307        Parcel obj;
308        writeByteArray(obj, sessionId);
309
310        size_t nKeys = keyStatusList.size();
311        obj.writeInt32(nKeys);
312        for (size_t i = 0; i < nKeys; ++i) {
313            const KeyStatus &keyStatus = keyStatusList[i];
314            writeByteArray(obj, keyStatus.keyId);
315            uint32_t type;
316            switch(keyStatus.type) {
317            case KeyStatusType::USABLE:
318                type = DrmPlugin::kKeyStatusType_Usable;
319                break;
320            case KeyStatusType::EXPIRED:
321                type = DrmPlugin::kKeyStatusType_Expired;
322                break;
323            case KeyStatusType::OUTPUTNOTALLOWED:
324                type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
325                break;
326            case KeyStatusType::STATUSPENDING:
327                type = DrmPlugin::kKeyStatusType_StatusPending;
328                break;
329            case KeyStatusType::INTERNALERROR:
330            default:
331                type = DrmPlugin::kKeyStatusType_InternalError;
332                break;
333            }
334            obj.writeInt32(type);
335        }
336        obj.writeInt32(hasNewUsableKey);
337
338        Mutex::Autolock lock(mNotifyLock);
339        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
340    }
341    return Void();
342}
343
344bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
345    Mutex::Autolock autoLock(mLock);
346    bool result = false;
347
348    if (mFactory != NULL && mFactory->isCryptoSchemeSupported(uuid)) {
349        if (mimeType != "") {
350            result = mFactory->isContentTypeSupported(mimeType.string());
351        }
352    }
353    return result;
354}
355
356status_t DrmHal::createPlugin(const uint8_t uuid[16],
357        const String8& appPackageName) {
358    Mutex::Autolock autoLock(mLock);
359
360    mPlugin = makeDrmPlugin(uuid, appPackageName);
361
362    if (mPlugin == NULL) {
363        mInitCheck = ERROR_UNSUPPORTED;
364    } else {
365        mInitCheck = OK;
366        mPlugin->setListener(this);
367    }
368
369    return mInitCheck;
370}
371
372status_t DrmHal::destroyPlugin() {
373    Mutex::Autolock autoLock(mLock);
374
375    if (mInitCheck != OK) {
376        return mInitCheck;
377    }
378
379    setListener(NULL);
380    mPlugin.clear();
381
382    return OK;
383}
384
385status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
386    Mutex::Autolock autoLock(mLock);
387
388    if (mInitCheck != OK) {
389        return mInitCheck;
390    }
391
392    status_t  err = UNKNOWN_ERROR;
393
394    bool retry = true;
395    do {
396        hidl_vec<uint8_t> hSessionId;
397
398        Return<void> hResult = mPlugin->openSession(
399                [&](Status status, const hidl_vec<uint8_t>& id) {
400                    if (status == Status::OK) {
401                        sessionId = toVector(id);
402                    }
403                    err = toStatusT(status);
404                }
405            );
406
407        if (!hResult.isOk()) {
408            err = DEAD_OBJECT;
409        }
410
411        if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
412            mLock.unlock();
413            // reclaimSession may call back to closeSession, since mLock is
414            // shared between Drm instances, we should unlock here to avoid
415            // deadlock.
416            retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
417            mLock.lock();
418        } else {
419            retry = false;
420        }
421    } while (retry);
422
423    if (err == OK) {
424        DrmSessionManager::Instance()->addSession(getCallingPid(),
425                mDrmSessionClient, sessionId);
426    }
427    return err;
428}
429
430status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
431    Mutex::Autolock autoLock(mLock);
432
433    if (mInitCheck != OK) {
434        return mInitCheck;
435    }
436
437    Status status = mPlugin->closeSession(toHidlVec(sessionId));
438    if (status == Status::OK) {
439        DrmSessionManager::Instance()->removeSession(sessionId);
440    }
441    return toStatusT(status);
442}
443
444status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
445        Vector<uint8_t> const &initData, String8 const &mimeType,
446        DrmPlugin::KeyType keyType, KeyedVector<String8,
447        String8> const &optionalParameters, Vector<uint8_t> &request,
448        String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
449    Mutex::Autolock autoLock(mLock);
450
451    if (mInitCheck != OK) {
452        return mInitCheck;
453    }
454
455    DrmSessionManager::Instance()->useSession(sessionId);
456
457    KeyType hKeyType;
458    if (keyType == DrmPlugin::kKeyType_Streaming) {
459        hKeyType = KeyType::STREAMING;
460    } else if (keyType == DrmPlugin::kKeyType_Offline) {
461        hKeyType = KeyType::OFFLINE;
462    } else if (keyType == DrmPlugin::kKeyType_Release) {
463        hKeyType = KeyType::RELEASE;
464    } else {
465        return BAD_VALUE;
466    }
467
468    ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
469
470    status_t err = UNKNOWN_ERROR;
471
472    Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
473            toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
474            [&](Status status, const hidl_vec<uint8_t>& hRequest,
475                    KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
476
477                if (status == Status::OK) {
478                    request = toVector(hRequest);
479                    defaultUrl = toString8(hDefaultUrl);
480
481                    switch (hKeyRequestType) {
482                    case KeyRequestType::INITIAL:
483                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
484                        break;
485                    case KeyRequestType::RENEWAL:
486                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
487                        break;
488                    case KeyRequestType::RELEASE:
489                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
490                        break;
491                    default:
492                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
493                        break;
494                    }
495                    err = toStatusT(status);
496                }
497            });
498
499    return hResult.isOk() ? err : DEAD_OBJECT;
500}
501
502status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
503        Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
504    Mutex::Autolock autoLock(mLock);
505
506    if (mInitCheck != OK) {
507        return mInitCheck;
508    }
509
510    DrmSessionManager::Instance()->useSession(sessionId);
511
512    status_t err = UNKNOWN_ERROR;
513
514    Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
515            toHidlVec(response),
516            [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
517                if (status == Status::OK) {
518                    keySetId = toVector(hKeySetId);
519                }
520                err = toStatusT(status);
521            }
522        );
523
524    return hResult.isOk() ? err : DEAD_OBJECT;
525}
526
527status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
528    Mutex::Autolock autoLock(mLock);
529
530    if (mInitCheck != OK) {
531        return mInitCheck;
532    }
533
534    return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
535}
536
537status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
538        Vector<uint8_t> const &keySetId) {
539    Mutex::Autolock autoLock(mLock);
540
541    if (mInitCheck != OK) {
542        return mInitCheck;
543    }
544
545    DrmSessionManager::Instance()->useSession(sessionId);
546
547    return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
548                    toHidlVec(keySetId)));
549}
550
551status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
552        KeyedVector<String8, String8> &infoMap) const {
553    Mutex::Autolock autoLock(mLock);
554
555    if (mInitCheck != OK) {
556        return mInitCheck;
557    }
558
559    DrmSessionManager::Instance()->useSession(sessionId);
560
561    ::KeyedVector hInfoMap;
562
563    status_t err = UNKNOWN_ERROR;
564
565    Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
566            [&](Status status, const hidl_vec<KeyValue>& map) {
567                if (status == Status::OK) {
568                    infoMap = toKeyedVector(map);
569                }
570                err = toStatusT(status);
571            }
572        );
573
574    return hResult.isOk() ? err : DEAD_OBJECT;
575}
576
577status_t DrmHal::getProvisionRequest(String8 const &certType,
578        String8 const &certAuthority, Vector<uint8_t> &request,
579        String8 &defaultUrl) {
580    Mutex::Autolock autoLock(mLock);
581
582    if (mInitCheck != OK) {
583        return mInitCheck;
584    }
585
586    status_t err = UNKNOWN_ERROR;
587
588    Return<void> hResult = mPlugin->getProvisionRequest(
589            toHidlString(certType), toHidlString(certAuthority),
590            [&](Status status, const hidl_vec<uint8_t>& hRequest,
591                    const hidl_string& hDefaultUrl) {
592                if (status == Status::OK) {
593                    request = toVector(hRequest);
594                    defaultUrl = toString8(hDefaultUrl);
595                }
596                err = toStatusT(status);
597            }
598        );
599
600    return hResult.isOk() ? err : DEAD_OBJECT;
601}
602
603status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
604        Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
605    Mutex::Autolock autoLock(mLock);
606
607    if (mInitCheck != OK) {
608        return mInitCheck;
609    }
610
611    status_t err = UNKNOWN_ERROR;
612
613    Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
614            [&](Status status, const hidl_vec<uint8_t>& hCertificate,
615                    const hidl_vec<uint8_t>& hWrappedKey) {
616                if (status == Status::OK) {
617                    certificate = toVector(hCertificate);
618                    wrappedKey = toVector(hWrappedKey);
619                }
620                err = toStatusT(status);
621            }
622        );
623
624    return hResult.isOk() ? err : DEAD_OBJECT;
625}
626
627status_t DrmHal::getSecureStops(List<Vector<uint8_t> > &secureStops) {
628    Mutex::Autolock autoLock(mLock);
629
630    if (mInitCheck != OK) {
631        return mInitCheck;
632    }
633
634    status_t err = UNKNOWN_ERROR;
635
636    Return<void> hResult = mPlugin->getSecureStops(
637            [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
638                if (status == Status::OK) {
639                    secureStops = toSecureStops(hSecureStops);
640                }
641                err = toStatusT(status);
642            }
643    );
644
645    return hResult.isOk() ? err : DEAD_OBJECT;
646}
647
648
649status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
650    Mutex::Autolock autoLock(mLock);
651
652    if (mInitCheck != OK) {
653        return mInitCheck;
654    }
655
656    status_t err = UNKNOWN_ERROR;
657
658    Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
659            [&](Status status, const SecureStop& hSecureStop) {
660                if (status == Status::OK) {
661                    secureStop = toVector(hSecureStop.opaqueData);
662                }
663                err = toStatusT(status);
664            }
665    );
666
667    return hResult.isOk() ? err : DEAD_OBJECT;
668}
669
670status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
671    Mutex::Autolock autoLock(mLock);
672
673    if (mInitCheck != OK) {
674        return mInitCheck;
675    }
676
677    return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
678}
679
680status_t DrmHal::releaseAllSecureStops() {
681    Mutex::Autolock autoLock(mLock);
682
683    if (mInitCheck != OK) {
684        return mInitCheck;
685    }
686
687    return toStatusT(mPlugin->releaseAllSecureStops());
688}
689
690status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
691    Mutex::Autolock autoLock(mLock);
692
693    if (mInitCheck != OK) {
694        return mInitCheck;
695    }
696
697    status_t err = UNKNOWN_ERROR;
698
699    Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
700            [&](Status status, const hidl_string& hValue) {
701                if (status == Status::OK) {
702                    value = toString8(hValue);
703                }
704                err = toStatusT(status);
705            }
706    );
707
708    return hResult.isOk() ? err : DEAD_OBJECT;
709}
710
711status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
712    Mutex::Autolock autoLock(mLock);
713
714    if (mInitCheck != OK) {
715        return mInitCheck;
716    }
717
718    status_t err = UNKNOWN_ERROR;
719
720    Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
721            [&](Status status, const hidl_vec<uint8_t>& hValue) {
722                if (status == Status::OK) {
723                    value = toVector(hValue);
724                }
725                err = toStatusT(status);
726            }
727    );
728
729    return hResult.isOk() ? err : DEAD_OBJECT;
730}
731
732status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
733    Mutex::Autolock autoLock(mLock);
734
735    if (mInitCheck != OK) {
736        return mInitCheck;
737    }
738
739    Status status =  mPlugin->setPropertyString(toHidlString(name),
740            toHidlString(value));
741    return toStatusT(status);
742}
743
744status_t DrmHal::setPropertyByteArray(String8 const &name,
745                                   Vector<uint8_t> const &value ) const {
746    Mutex::Autolock autoLock(mLock);
747
748    if (mInitCheck != OK) {
749        return mInitCheck;
750    }
751
752    Status status = mPlugin->setPropertyByteArray(toHidlString(name),
753            toHidlVec(value));
754    return toStatusT(status);
755}
756
757
758status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
759                                 String8 const &algorithm) {
760    Mutex::Autolock autoLock(mLock);
761
762    if (mInitCheck != OK) {
763        return mInitCheck;
764    }
765
766    DrmSessionManager::Instance()->useSession(sessionId);
767
768    Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
769            toHidlString(algorithm));
770    return toStatusT(status);
771}
772
773status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
774                              String8 const &algorithm) {
775    Mutex::Autolock autoLock(mLock);
776
777    if (mInitCheck != OK) {
778        return mInitCheck;
779    }
780
781    DrmSessionManager::Instance()->useSession(sessionId);
782
783    Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
784            toHidlString(algorithm));
785    return toStatusT(status);
786}
787
788status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
789        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
790        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
791    Mutex::Autolock autoLock(mLock);
792
793    if (mInitCheck != OK) {
794        return mInitCheck;
795    }
796
797    DrmSessionManager::Instance()->useSession(sessionId);
798
799    status_t err = UNKNOWN_ERROR;
800
801    Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
802            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
803            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
804                if (status == Status::OK) {
805                    output = toVector(hOutput);
806                }
807                err = toStatusT(status);
808            }
809    );
810
811    return hResult.isOk() ? err : DEAD_OBJECT;
812}
813
814status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
815        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
816        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
817    Mutex::Autolock autoLock(mLock);
818
819    if (mInitCheck != OK) {
820        return mInitCheck;
821    }
822
823    DrmSessionManager::Instance()->useSession(sessionId);
824
825    status_t  err = UNKNOWN_ERROR;
826
827    Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
828            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
829            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
830                if (status == Status::OK) {
831                    output = toVector(hOutput);
832                }
833                err = toStatusT(status);
834            }
835    );
836
837    return hResult.isOk() ? err : DEAD_OBJECT;
838}
839
840status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
841        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
842        Vector<uint8_t> &signature) {
843    Mutex::Autolock autoLock(mLock);
844
845    if (mInitCheck != OK) {
846        return mInitCheck;
847    }
848
849    DrmSessionManager::Instance()->useSession(sessionId);
850
851    status_t err = UNKNOWN_ERROR;
852
853    Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
854            toHidlVec(keyId), toHidlVec(message),
855            [&](Status status, const hidl_vec<uint8_t>& hSignature)  {
856                if (status == Status::OK) {
857                    signature = toVector(hSignature);
858                }
859                err = toStatusT(status);
860            }
861    );
862
863    return hResult.isOk() ? err : DEAD_OBJECT;
864}
865
866status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
867        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
868        Vector<uint8_t> const &signature, bool &match) {
869    Mutex::Autolock autoLock(mLock);
870
871    if (mInitCheck != OK) {
872        return mInitCheck;
873    }
874
875    DrmSessionManager::Instance()->useSession(sessionId);
876
877    status_t err = UNKNOWN_ERROR;
878
879    Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
880            toHidlVec(message), toHidlVec(signature),
881            [&](Status status, bool hMatch) {
882                if (status == Status::OK) {
883                    match = hMatch;
884                } else {
885                    match = false;
886                }
887                err = toStatusT(status);
888            }
889    );
890
891    return hResult.isOk() ? err : DEAD_OBJECT;
892}
893
894status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
895        String8 const &algorithm, Vector<uint8_t> const &message,
896        Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
897    Mutex::Autolock autoLock(mLock);
898
899    if (mInitCheck != OK) {
900        return mInitCheck;
901    }
902
903    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
904        return -EPERM;
905    }
906
907    DrmSessionManager::Instance()->useSession(sessionId);
908
909    status_t err = UNKNOWN_ERROR;
910
911    Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
912            toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
913            [&](Status status, const hidl_vec<uint8_t>& hSignature) {
914                if (status == Status::OK) {
915                    signature = toVector(hSignature);
916                }
917                err = toStatusT(status);
918            }
919        );
920
921    return hResult.isOk() ? err : DEAD_OBJECT;
922}
923
924void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
925{
926    mEventLock.lock();
927    mListener.clear();
928    mEventLock.unlock();
929
930    Mutex::Autolock autoLock(mLock);
931    mPlugin.clear();
932}
933
934void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
935{
936    if (vec.size()) {
937        obj.writeInt32(vec.size());
938        obj.write(vec.data(), vec.size());
939    } else {
940        obj.writeInt32(0);
941    }
942}
943
944}  // namespace android
945