blob: b78373d87cac06990880e596ecc4c7cbae78ea11 [file] [log] [blame]
Jeff Tinker497ca092014-05-13 09:31:15 -07001/*
2 * Copyright (C) 2014 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
Marco Nelissenc7a11b22014-05-30 10:13:25 -070017//#define LOG_NDEBUG 0
Jeff Tinker497ca092014-05-13 09:31:15 -070018#define LOG_TAG "NdkMediaDrm"
19
Edwin Wongad02cc62018-08-23 13:48:27 -070020#include <inttypes.h>
John W. Bruce9c4e0fa2019-05-03 17:12:44 -070021#include <unistd.h>
Edwin Wongad02cc62018-08-23 13:48:27 -070022
Colin Cross7e8d4ba2017-05-04 16:17:42 -070023#include <media/NdkMediaDrm.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070024
Jeff Tinkera69729d2016-02-12 08:47:00 -080025#include <cutils/properties.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070026#include <utils/Log.h>
27#include <utils/StrongPointer.h>
28#include <gui/Surface.h>
29
John W. Bruce9c4e0fa2019-05-03 17:12:44 -070030#include <android-base/properties.h>
31#include <binder/PermissionController.h>
Robert Shih28c2ed32019-10-27 22:55:12 -070032#include <mediadrm/DrmUtils.h>
Marco Nelissen13aa1a42019-09-27 10:21:55 -070033#include <mediadrm/IDrm.h>
34#include <mediadrm/IDrmClient.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070035#include <media/stagefright/MediaErrors.h>
36#include <binder/IServiceManager.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070037#include <media/NdkMediaCrypto.h>
Marco Nelissen13aa1a42019-09-27 10:21:55 -070038#include <mediadrm/IMediaDrmService.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070039
40
41using namespace android;
42
43typedef Vector<uint8_t> idvec_t;
44
Jeff Tinker3305b992014-05-14 18:39:25 -070045struct DrmListener: virtual public BnDrmClient
46{
47private:
48 AMediaDrm *mObj;
Edwin Wongad02cc62018-08-23 13:48:27 -070049 AMediaDrmEventListener mEventListener;
50 AMediaDrmExpirationUpdateListener mExpirationUpdateListener;
51 AMediaDrmKeysChangeListener mKeysChangeListener;
Jeff Tinker3305b992014-05-14 18:39:25 -070052
53public:
Edwin Wongad02cc62018-08-23 13:48:27 -070054 DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj),
55 mEventListener(listener), mExpirationUpdateListener(NULL), mKeysChangeListener(NULL) {}
56
57 DrmListener(AMediaDrm *obj, AMediaDrmExpirationUpdateListener listener) : mObj(obj),
58 mEventListener(NULL), mExpirationUpdateListener(listener), mKeysChangeListener(NULL) {}
59
60 DrmListener(AMediaDrm *obj, AMediaDrmKeysChangeListener listener) : mObj(obj),
61 mEventListener(NULL), mExpirationUpdateListener(NULL), mKeysChangeListener(listener) {}
62
63 void setEventListener(AMediaDrmEventListener listener) {
64 mEventListener = listener;
65 }
66
67 void setExpirationUpdateListener(AMediaDrmExpirationUpdateListener listener) {
68 mExpirationUpdateListener = listener;
69 }
70
71 void setKeysChangeListener(AMediaDrmKeysChangeListener listener) {
72 mKeysChangeListener = listener;
73 }
74
Robert Shih61e1c762019-10-31 21:26:58 -070075 void sendEvent(
76 DrmPlugin::EventType eventType,
77 const hardware::hidl_vec<uint8_t> &sessionId,
78 const hardware::hidl_vec<uint8_t> &data) override;
79
80 void sendExpirationUpdate(
81 const hardware::hidl_vec<uint8_t> &sessionId,
82 int64_t expiryTimeInMS) override;
83
84 void sendKeysChange(
85 const hardware::hidl_vec<uint8_t> &sessionId,
86 const std::vector<DrmKeyStatus> &keyStatusList,
87 bool hasNewUsableKey) override;
88
89 void sendSessionLostState(
90 const hardware::hidl_vec<uint8_t> &) override {}
91
Jeff Tinker3305b992014-05-14 18:39:25 -070092};
93
Jeff Tinker497ca092014-05-13 09:31:15 -070094struct AMediaDrm {
95 sp<IDrm> mDrm;
Jeff Tinker497ca092014-05-13 09:31:15 -070096 List<idvec_t> mIds;
97 KeyedVector<String8, String8> mQueryResults;
98 Vector<uint8_t> mKeyRequest;
99 Vector<uint8_t> mProvisionRequest;
100 String8 mProvisionUrl;
101 String8 mPropertyString;
102 Vector<uint8_t> mPropertyByteArray;
103 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -0700104 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -0700105};
106
Robert Shih61e1c762019-10-31 21:26:58 -0700107void DrmListener::sendExpirationUpdate(
108 const hardware::hidl_vec<uint8_t> &sessionId,
109 int64_t expiryTimeInMS) {
110 if (!mExpirationUpdateListener) {
111 ALOGE("No ExpirationUpdateListener specified");
Jeff Tinker3305b992014-05-14 18:39:25 -0700112 return;
113 }
114
Robert Shih61e1c762019-10-31 21:26:58 -0700115 if (expiryTimeInMS >= 0) {
116 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
117 (*mExpirationUpdateListener)(mObj, &asid, expiryTimeInMS);
118 } else {
119 ALOGE("expiry time negative, status=%" PRId64 "", expiryTimeInMS);
120 }
121}
Edwin Wongad02cc62018-08-23 13:48:27 -0700122
Robert Shih61e1c762019-10-31 21:26:58 -0700123void DrmListener::sendKeysChange(
124 const hardware::hidl_vec<uint8_t> &sessionId,
125 const std::vector<DrmKeyStatus> &keyStatusList,
126 bool hasNewUsableKey) {
127 if (!mKeysChangeListener) {
128 ALOGE("No KeysChangeListener specified");
Edwin Wongad02cc62018-08-23 13:48:27 -0700129 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700130 }
131
Robert Shih61e1c762019-10-31 21:26:58 -0700132 Vector<AMediaDrmKeyStatus> keysStatus;
133 for (const auto &drmKeyStatus : keyStatusList) {
Edwin Wongad02cc62018-08-23 13:48:27 -0700134 AMediaDrmKeyStatus keyStatus;
Robert Shih61e1c762019-10-31 21:26:58 -0700135 keyStatus.keyId.ptr = drmKeyStatus.keyId.data();
136 keyStatus.keyId.length = drmKeyStatus.keyId.size();
137 keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(drmKeyStatus.type);
138 keysStatus.push(keyStatus);
139 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700140
Robert Shih61e1c762019-10-31 21:26:58 -0700141 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
142 int32_t numKeys = keyStatusList.size();
143 (*mKeysChangeListener)(mObj, &asid, keysStatus.array(), numKeys, hasNewUsableKey);
144 return;
145}
Edwin Wongad02cc62018-08-23 13:48:27 -0700146
Robert Shih61e1c762019-10-31 21:26:58 -0700147void DrmListener::sendEvent(
148 DrmPlugin::EventType eventType,
149 const hardware::hidl_vec<uint8_t> &sessionId,
150 const hardware::hidl_vec<uint8_t> &data) {
151 if (!mEventListener) {
152 ALOGE("No EventListener specified");
Edwin Wongad02cc62018-08-23 13:48:27 -0700153 return;
154 }
155
156 // Handles AMediaDrmEventListener below:
157 // translates DrmPlugin event types into their NDK equivalents
Jeff Tinker3305b992014-05-14 18:39:25 -0700158 AMediaDrmEventType ndkEventType;
159 switch(eventType) {
160 case DrmPlugin::kDrmPluginEventProvisionRequired:
161 ndkEventType = EVENT_PROVISION_REQUIRED;
162 break;
163 case DrmPlugin::kDrmPluginEventKeyNeeded:
164 ndkEventType = EVENT_KEY_REQUIRED;
165 break;
166 case DrmPlugin::kDrmPluginEventKeyExpired:
167 ndkEventType = EVENT_KEY_EXPIRED;
168 break;
169 case DrmPlugin::kDrmPluginEventVendorDefined:
170 ndkEventType = EVENT_VENDOR_DEFINED;
171 break;
Edwin Wongad02cc62018-08-23 13:48:27 -0700172 case DrmPlugin::kDrmPluginEventSessionReclaimed:
173 ndkEventType = EVENT_SESSION_RECLAIMED;
174 break;
Jeff Tinker3305b992014-05-14 18:39:25 -0700175 default:
Robert Shih61e1c762019-10-31 21:26:58 -0700176 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", eventType);
Edwin Wongad02cc62018-08-23 13:48:27 -0700177 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700178 }
179
Robert Shih61e1c762019-10-31 21:26:58 -0700180 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
181 int32_t dataSize = data.size();
182 const uint8_t *dataPtr = data.data();
Edwin Wongad02cc62018-08-23 13:48:27 -0700183 if (dataSize > 0) {
Robert Shih61e1c762019-10-31 21:26:58 -0700184 (*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
Edwin Wongad02cc62018-08-23 13:48:27 -0700185 } else {
Robert Shih61e1c762019-10-31 21:26:58 -0700186 ALOGE("invalid event data size=%d", dataSize);
Edwin Wongad02cc62018-08-23 13:48:27 -0700187 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700188}
189
Jeff Tinker497ca092014-05-13 09:31:15 -0700190extern "C" {
191
Marco Nelissene419d7c2014-05-15 14:17:25 -0700192static media_status_t translateStatus(status_t status) {
193 media_status_t result = AMEDIA_ERROR_UNKNOWN;
Jeff Tinker497ca092014-05-13 09:31:15 -0700194 switch (status) {
195 case OK:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700196 result = AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700197 break;
198 case android::ERROR_DRM_NOT_PROVISIONED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700199 result = AMEDIA_DRM_NOT_PROVISIONED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700200 break;
201 case android::ERROR_DRM_RESOURCE_BUSY:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700202 result = AMEDIA_DRM_RESOURCE_BUSY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700203 break;
204 case android::ERROR_DRM_DEVICE_REVOKED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700205 result = AMEDIA_DRM_DEVICE_REVOKED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700206 break;
207 case android::ERROR_DRM_CANNOT_HANDLE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700208 result = AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700209 break;
210 case android::ERROR_DRM_TAMPER_DETECTED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700211 result = AMEDIA_DRM_TAMPER_DETECTED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700212 break;
213 case android::ERROR_DRM_SESSION_NOT_OPENED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700214 result = AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700215 break;
216 case android::ERROR_DRM_NO_LICENSE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700217 result = AMEDIA_DRM_NEED_KEY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700218 break;
219 case android::ERROR_DRM_LICENSE_EXPIRED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700220 result = AMEDIA_DRM_LICENSE_EXPIRED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700221 break;
222 default:
Jeff Tinker497ca092014-05-13 09:31:15 -0700223 break;
224 }
225 return result;
226}
227
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700228static bool ShouldGetAppPackageName(void) {
229 // Check what this device's first API level was.
230 int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
231 if (firstApiLevel == 0) {
232 // First API Level is 0 on factory ROMs, but we can assume the current SDK
233 // version is the first if it's a factory ROM.
234 firstApiLevel = android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
235 }
236 return firstApiLevel >= 29; // Android Q
237}
238
239static status_t GetAppPackageName(String8 *packageName) {
240 sp<IServiceManager> serviceManager = defaultServiceManager();
241 sp<IBinder> binder = serviceManager->getService(String16("permission"));
242
243 sp<IPermissionController> permissionContol = interface_cast<IPermissionController>(binder);
244 if (permissionContol == NULL) {
245 ALOGE("Failed to get permission service");
246 return UNKNOWN_ERROR;
247 }
248
249 Vector<String16> packages;
250 permissionContol->getPackagesForUid(getuid(), packages);
251
252 if (packages.isEmpty()) {
253 ALOGE("Unable to get package name for current UID");
254 return UNKNOWN_ERROR;
255 }
256
257 *packageName = String8(packages[0]);
258 return OK;
259}
260
Jeff Tinker497ca092014-05-13 09:31:15 -0700261static sp<IDrm> CreateDrm() {
Robert Shih28c2ed32019-10-27 22:55:12 -0700262 return DrmUtils::MakeDrm();
Jeff Tinker497ca092014-05-13 09:31:15 -0700263}
264
265
266static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
267 sp<IDrm> drm = CreateDrm();
268
269 if (drm == NULL) {
270 return NULL;
271 }
272
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700273 String8 packageName;
274 if (ShouldGetAppPackageName()) {
275 status_t err = GetAppPackageName(&packageName);
276
277 if (err != OK) {
278 return NULL;
279 }
280 }
281
282 status_t err = drm->createPlugin(uuid, packageName);
Jeff Tinker497ca092014-05-13 09:31:15 -0700283
284 if (err != OK) {
285 return NULL;
286 }
287
288 return drm;
289}
290
Marco Nelissen3425fd52014-05-14 11:12:46 -0700291EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700292bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
293 sp<IDrm> drm = CreateDrm();
294
295 if (drm == NULL) {
296 return false;
297 }
298
299 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
Jeff Tinkerdb3fa5f2019-01-25 22:56:56 -0800300 bool isSupported = false;
301 status_t status = drm->isCryptoSchemeSupported(uuid, mimeStr,
302 DrmPlugin::kSecurityLevelUnknown, &isSupported);
303 return (status == OK) && isSupported;
Jeff Tinker497ca092014-05-13 09:31:15 -0700304}
305
Marco Nelissen3425fd52014-05-14 11:12:46 -0700306EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700307AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
308 AMediaDrm *mObj = new AMediaDrm();
309 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700310
311 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700312 return mObj;
313}
314
Marco Nelissen3425fd52014-05-14 11:12:46 -0700315EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700316void AMediaDrm_release(AMediaDrm *mObj) {
317 if (mObj->mDrm != NULL) {
318 mObj->mDrm->setListener(NULL);
319 mObj->mDrm->destroyPlugin();
320 mObj->mDrm.clear();
321 }
322 delete mObj;
323}
324
Jeff Tinker3305b992014-05-14 18:39:25 -0700325EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700326media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700327 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700328 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700329 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700330
331 if (mObj->mListener.get()) {
332 mObj->mListener->setEventListener(listener);
333 } else {
334 mObj->mListener = new DrmListener(mObj, listener);
335 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700336 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700337 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700338}
Jeff Tinker497ca092014-05-13 09:31:15 -0700339
Edwin Wongad02cc62018-08-23 13:48:27 -0700340EXPORT
341media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
342 AMediaDrmExpirationUpdateListener listener) {
343 if (!mObj || mObj->mDrm == NULL) {
344 return AMEDIA_ERROR_INVALID_OBJECT;
345 }
346
347 if (mObj->mListener.get()) {
348 mObj->mListener->setExpirationUpdateListener(listener);
349 } else {
350 mObj->mListener = new DrmListener(mObj, listener);
351 }
352 mObj->mDrm->setListener(mObj->mListener);
353 return AMEDIA_OK;
354}
355
356EXPORT
357media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
358 AMediaDrmKeysChangeListener listener) {
359 if (!mObj || mObj->mDrm == NULL) {
360 return AMEDIA_ERROR_INVALID_OBJECT;
361 }
362
363 if (mObj->mListener.get()) {
364 mObj->mListener->setKeysChangeListener(listener);
365 } else {
366 mObj->mListener = new DrmListener(mObj, listener);
367 }
368 mObj->mDrm->setListener(mObj->mListener);
369 return AMEDIA_OK;
370}
Jeff Tinker497ca092014-05-13 09:31:15 -0700371
372static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700373 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700374 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700375 return true;
376 }
377 }
378 return false;
379}
380
Marco Nelissen3425fd52014-05-14 11:12:46 -0700381EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700382media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700383 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700384 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700385 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700386 if (!sessionId) {
387 return AMEDIA_ERROR_INVALID_PARAMETER;
388 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700389 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000390 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Jeff Tinker497ca092014-05-13 09:31:15 -0700391 if (status == OK) {
392 mObj->mIds.push_front(session);
393 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700394 sessionId->ptr = iter->array();
395 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700396 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700397 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700398}
399
Marco Nelissen3425fd52014-05-14 11:12:46 -0700400EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700401media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700402 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700403 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700404 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700405 if (!sessionId) {
406 return AMEDIA_ERROR_INVALID_PARAMETER;
407 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700408
409 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700410 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700411 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700412 }
413 mObj->mDrm->closeSession(*iter);
414 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700415 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700416}
417
Marco Nelissen3425fd52014-05-14 11:12:46 -0700418EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700419media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700420 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
421 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700422 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700423
424 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700425 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700426 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700427 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700428 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700429 }
430
431 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700432 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700433 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700434 }
435
436 Vector<uint8_t> mdInit;
437 mdInit.appendArray(init, initSize);
438 DrmPlugin::KeyType mdKeyType;
439 switch (keyType) {
440 case KEY_TYPE_STREAMING:
441 mdKeyType = DrmPlugin::kKeyType_Streaming;
442 break;
443 case KEY_TYPE_OFFLINE:
444 mdKeyType = DrmPlugin::kKeyType_Offline;
445 break;
446 case KEY_TYPE_RELEASE:
447 mdKeyType = DrmPlugin::kKeyType_Release;
448 break;
449 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700450 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700451 }
452 KeyedVector<String8, String8> mdOptionalParameters;
453 for (size_t i = 0; i < numOptionalParameters; i++) {
454 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
455 String8(optionalParameters[i].mValue));
456 }
457 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700458 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700459 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700460 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700461 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
462 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700463 if (status != OK) {
464 return translateStatus(status);
465 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700466 *keyRequest = mObj->mKeyRequest.array();
467 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700468 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700469 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700470}
471
Marco Nelissen3425fd52014-05-14 11:12:46 -0700472EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700473media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
474 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700475
476 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700477 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700478 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700479 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700480 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700481 }
482
483 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700484 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700485 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700486 }
487 Vector<uint8_t> mdResponse;
488 mdResponse.appendArray(response, responseSize);
489
490 Vector<uint8_t> mdKeySetId;
491 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
492 if (status == OK) {
493 mObj->mIds.push_front(mdKeySetId);
494 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700495 keySetId->ptr = iter->array();
496 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700497 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700498 keySetId->ptr = NULL;
499 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700500 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700501 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700502}
503
Marco Nelissen3425fd52014-05-14 11:12:46 -0700504EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700505media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
506 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700507
508 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700509 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700510 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700511 if (!sessionId || !keySetId) {
512 return AMEDIA_ERROR_INVALID_PARAMETER;
513 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700514 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700515 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700516 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700517 }
518 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700519 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700520 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
521}
522
Marco Nelissen3425fd52014-05-14 11:12:46 -0700523EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700524media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700525 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700526 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700527 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700528 if (!keySetId) {
529 return AMEDIA_ERROR_INVALID_PARAMETER;
530 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700531 List<idvec_t>::iterator iter;
532 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700533 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700534 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700535 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700536 status = mObj->mDrm->removeKeys(keySet);
537 } else {
538 status = mObj->mDrm->removeKeys(*iter);
539 mObj->mIds.erase(iter);
540 }
541 return translateStatus(status);
542}
543
Marco Nelissen3425fd52014-05-14 11:12:46 -0700544EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700545media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
546 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700547
548 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700549 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700550 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700551 if (!sessionId || !numPairs) {
552 return AMEDIA_ERROR_INVALID_PARAMETER;
553 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700554 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700555 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700556 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700557 }
558
559 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
560 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700561 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700562 return translateStatus(status);
563 }
564
Marco Nelissen18a1b592014-05-20 08:45:18 -0700565 if (mObj->mQueryResults.size() > *numPairs) {
566 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700567 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700568 }
569
570 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
571 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700572 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700573 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700574 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700575 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700576}
577
Marco Nelissen3425fd52014-05-14 11:12:46 -0700578EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700579media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
580 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700581 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700582 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700583 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700584 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700585 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700586 }
587
588 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
589 mObj->mProvisionRequest, mObj->mProvisionUrl);
590 if (status != OK) {
591 return translateStatus(status);
592 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700593 *provisionRequest = mObj->mProvisionRequest.array();
594 *provisionRequestSize = mObj->mProvisionRequest.size();
595 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700596 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700597 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700598}
599
Marco Nelissen3425fd52014-05-14 11:12:46 -0700600EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700601media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700602 const uint8_t *response, size_t responseSize) {
603 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700604 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700605 }
606 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700607 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700608 }
609
610 Vector<uint8_t> mdResponse;
611 mdResponse.appendArray(response, responseSize);
612
613 Vector<uint8_t> unused;
614 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
615}
616
Marco Nelissen3425fd52014-05-14 11:12:46 -0700617EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700618media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700619 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700620
621 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700622 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700623 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700624 if (!numSecureStops) {
625 return AMEDIA_ERROR_INVALID_PARAMETER;
626 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700627 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
628 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700629 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700630 return translateStatus(status);
631 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700632 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700633 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700634 }
635 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
636 size_t i = 0;
637 while (iter != mObj->mSecureStops.end()) {
638 secureStops[i].ptr = iter->array();
639 secureStops[i].length = iter->size();
640 ++iter;
641 ++i;
642 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700643 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700644 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700645}
646
Marco Nelissen3425fd52014-05-14 11:12:46 -0700647EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700648media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700649 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700650
651 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700652 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700653 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700654 if (!ssRelease) {
655 return AMEDIA_ERROR_INVALID_PARAMETER;
656 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700657
658 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700659 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700660 return translateStatus(mObj->mDrm->releaseSecureStops(release));
661}
662
663
Marco Nelissen3425fd52014-05-14 11:12:46 -0700664EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700665media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700666 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700667
668 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700669 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700670 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700671 if (!propertyName || !propertyValue) {
672 return AMEDIA_ERROR_INVALID_PARAMETER;
673 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700674
675 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
676 mObj->mPropertyString);
677
678 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700679 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700680 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700681 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700682 }
683 return translateStatus(status);
684}
685
Marco Nelissen3425fd52014-05-14 11:12:46 -0700686EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700687media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700688 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700689 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700690 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700691 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700692 if (!propertyName || !propertyValue) {
693 return AMEDIA_ERROR_INVALID_PARAMETER;
694 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700695
696 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
697 mObj->mPropertyByteArray);
698
699 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700700 propertyValue->ptr = mObj->mPropertyByteArray.array();
701 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700702 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700703 propertyValue->ptr = NULL;
704 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700705 }
706 return translateStatus(status);
707}
708
Marco Nelissen3425fd52014-05-14 11:12:46 -0700709EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700710media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700711 const char *propertyName, const char *value) {
712 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700713 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700714 }
715
716 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
717 String8(value)));
718}
719
Marco Nelissen3425fd52014-05-14 11:12:46 -0700720EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700721media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700722 const char *propertyName, const uint8_t *value, size_t valueSize) {
723
724 Vector<uint8_t> byteArray;
725 byteArray.appendArray(value, valueSize);
726
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700727 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700728 byteArray));
729}
730
731
Marco Nelissene419d7c2014-05-15 14:17:25 -0700732static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700733 const AMediaDrmSessionId &sessionId,
734 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
735 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
736
737 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700738 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700739 }
740 List<idvec_t>::iterator iter;
741 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700742 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700743 }
744
745 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
746 if (status != OK) {
747 return translateStatus(status);
748 }
749
750 Vector<uint8_t> keyIdVec;
751 const size_t kKeyIdSize = 16;
752 keyIdVec.appendArray(keyId, kKeyIdSize);
753
754 Vector<uint8_t> inputVec;
755 inputVec.appendArray(input, dataSize);
756
757 Vector<uint8_t> ivVec;
758 const size_t kIvSize = 16;
759 ivVec.appendArray(iv, kIvSize);
760
761 Vector<uint8_t> outputVec;
762 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800763 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700764 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800765 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700766 }
767 if (status == OK) {
768 memcpy(output, outputVec.array(), outputVec.size());
769 }
770 return translateStatus(status);
771}
772
Marco Nelissen3425fd52014-05-14 11:12:46 -0700773EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700774media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700775 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
776 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700777 if (!sessionId) {
778 return AMEDIA_ERROR_INVALID_PARAMETER;
779 }
780 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700781 input, output, dataSize, true);
782}
783
Marco Nelissen3425fd52014-05-14 11:12:46 -0700784EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700785media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700786 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
787 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700788 if (!sessionId) {
789 return AMEDIA_ERROR_INVALID_PARAMETER;
790 }
791 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700792 input, output, dataSize, false);
793}
794
Marco Nelissen3425fd52014-05-14 11:12:46 -0700795EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700796media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700797 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
798 uint8_t *signature, size_t *signatureSize) {
799
800 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700801 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700802 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700803 if (!sessionId) {
804 return AMEDIA_ERROR_INVALID_PARAMETER;
805 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700806 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700807 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700808 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700809 }
810
811 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
812 if (status != OK) {
813 return translateStatus(status);
814 }
815
816 Vector<uint8_t> keyIdVec;
817 const size_t kKeyIdSize = 16;
818 keyIdVec.appendArray(keyId, kKeyIdSize);
819
820 Vector<uint8_t> messageVec;
821 messageVec.appendArray(message, messageSize);
822
823 Vector<uint8_t> signatureVec;
824 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
825 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700826 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700827 }
828 if (status == OK) {
829 memcpy(signature, signatureVec.array(), signatureVec.size());
830 }
831 return translateStatus(status);
832}
833
Marco Nelissen3425fd52014-05-14 11:12:46 -0700834EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700835media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700836 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
837 const uint8_t *signature, size_t signatureSize) {
838
839 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700840 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700841 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700842 if (!sessionId) {
843 return AMEDIA_ERROR_INVALID_PARAMETER;
844 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700845 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700846 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700847 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700848 }
849
850 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
851 if (status != OK) {
852 return translateStatus(status);
853 }
854
855 Vector<uint8_t> keyIdVec;
856 const size_t kKeyIdSize = 16;
857 keyIdVec.appendArray(keyId, kKeyIdSize);
858
859 Vector<uint8_t> messageVec;
860 messageVec.appendArray(message, messageSize);
861
862 Vector<uint8_t> signatureVec;
863 signatureVec.appendArray(signature, signatureSize);
864
865 bool match;
866 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
867 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700868 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700869 }
870 return translateStatus(status);
871}
872
873} // extern "C"