blob: 8a959822c64e91526df5dc15aca816f87b97378f [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>
Jeff Tinker497ca092014-05-13 09:31:15 -070038
39
40using namespace android;
41
42typedef Vector<uint8_t> idvec_t;
43
Robert Shiha54e81f2019-08-02 14:15:01 -070044struct DrmListener: virtual public IDrmClient
Jeff Tinker3305b992014-05-14 18:39:25 -070045{
46private:
47 AMediaDrm *mObj;
Edwin Wongad02cc62018-08-23 13:48:27 -070048 AMediaDrmEventListener mEventListener;
49 AMediaDrmExpirationUpdateListener mExpirationUpdateListener;
50 AMediaDrmKeysChangeListener mKeysChangeListener;
Jeff Tinker3305b992014-05-14 18:39:25 -070051
52public:
Edwin Wongad02cc62018-08-23 13:48:27 -070053 DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj),
54 mEventListener(listener), mExpirationUpdateListener(NULL), mKeysChangeListener(NULL) {}
55
56 DrmListener(AMediaDrm *obj, AMediaDrmExpirationUpdateListener listener) : mObj(obj),
57 mEventListener(NULL), mExpirationUpdateListener(listener), mKeysChangeListener(NULL) {}
58
59 DrmListener(AMediaDrm *obj, AMediaDrmKeysChangeListener listener) : mObj(obj),
60 mEventListener(NULL), mExpirationUpdateListener(NULL), mKeysChangeListener(listener) {}
61
62 void setEventListener(AMediaDrmEventListener listener) {
63 mEventListener = listener;
64 }
65
66 void setExpirationUpdateListener(AMediaDrmExpirationUpdateListener listener) {
67 mExpirationUpdateListener = listener;
68 }
69
70 void setKeysChangeListener(AMediaDrmKeysChangeListener listener) {
71 mKeysChangeListener = listener;
72 }
73
Robert Shih61e1c762019-10-31 21:26:58 -070074 void sendEvent(
75 DrmPlugin::EventType eventType,
76 const hardware::hidl_vec<uint8_t> &sessionId,
77 const hardware::hidl_vec<uint8_t> &data) override;
78
79 void sendExpirationUpdate(
80 const hardware::hidl_vec<uint8_t> &sessionId,
81 int64_t expiryTimeInMS) override;
82
83 void sendKeysChange(
84 const hardware::hidl_vec<uint8_t> &sessionId,
85 const std::vector<DrmKeyStatus> &keyStatusList,
86 bool hasNewUsableKey) override;
87
88 void sendSessionLostState(
89 const hardware::hidl_vec<uint8_t> &) override {}
90
Jeff Tinker3305b992014-05-14 18:39:25 -070091};
92
Jeff Tinker497ca092014-05-13 09:31:15 -070093struct AMediaDrm {
94 sp<IDrm> mDrm;
Jeff Tinker497ca092014-05-13 09:31:15 -070095 List<idvec_t> mIds;
96 KeyedVector<String8, String8> mQueryResults;
97 Vector<uint8_t> mKeyRequest;
98 Vector<uint8_t> mProvisionRequest;
99 String8 mProvisionUrl;
100 String8 mPropertyString;
101 Vector<uint8_t> mPropertyByteArray;
102 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -0700103 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -0700104};
105
Robert Shih61e1c762019-10-31 21:26:58 -0700106void DrmListener::sendExpirationUpdate(
107 const hardware::hidl_vec<uint8_t> &sessionId,
108 int64_t expiryTimeInMS) {
109 if (!mExpirationUpdateListener) {
110 ALOGE("No ExpirationUpdateListener specified");
Jeff Tinker3305b992014-05-14 18:39:25 -0700111 return;
112 }
113
Robert Shih61e1c762019-10-31 21:26:58 -0700114 if (expiryTimeInMS >= 0) {
115 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
116 (*mExpirationUpdateListener)(mObj, &asid, expiryTimeInMS);
117 } else {
118 ALOGE("expiry time negative, status=%" PRId64 "", expiryTimeInMS);
119 }
120}
Edwin Wongad02cc62018-08-23 13:48:27 -0700121
Robert Shih61e1c762019-10-31 21:26:58 -0700122void DrmListener::sendKeysChange(
123 const hardware::hidl_vec<uint8_t> &sessionId,
124 const std::vector<DrmKeyStatus> &keyStatusList,
125 bool hasNewUsableKey) {
126 if (!mKeysChangeListener) {
127 ALOGE("No KeysChangeListener specified");
Edwin Wongad02cc62018-08-23 13:48:27 -0700128 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700129 }
130
Robert Shih61e1c762019-10-31 21:26:58 -0700131 Vector<AMediaDrmKeyStatus> keysStatus;
132 for (const auto &drmKeyStatus : keyStatusList) {
Edwin Wongad02cc62018-08-23 13:48:27 -0700133 AMediaDrmKeyStatus keyStatus;
Robert Shih61e1c762019-10-31 21:26:58 -0700134 keyStatus.keyId.ptr = drmKeyStatus.keyId.data();
135 keyStatus.keyId.length = drmKeyStatus.keyId.size();
136 keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(drmKeyStatus.type);
137 keysStatus.push(keyStatus);
138 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700139
Robert Shih61e1c762019-10-31 21:26:58 -0700140 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
141 int32_t numKeys = keyStatusList.size();
142 (*mKeysChangeListener)(mObj, &asid, keysStatus.array(), numKeys, hasNewUsableKey);
143 return;
144}
Edwin Wongad02cc62018-08-23 13:48:27 -0700145
Robert Shih61e1c762019-10-31 21:26:58 -0700146void DrmListener::sendEvent(
147 DrmPlugin::EventType eventType,
148 const hardware::hidl_vec<uint8_t> &sessionId,
149 const hardware::hidl_vec<uint8_t> &data) {
150 if (!mEventListener) {
151 ALOGE("No EventListener specified");
Edwin Wongad02cc62018-08-23 13:48:27 -0700152 return;
153 }
154
155 // Handles AMediaDrmEventListener below:
156 // translates DrmPlugin event types into their NDK equivalents
Jeff Tinker3305b992014-05-14 18:39:25 -0700157 AMediaDrmEventType ndkEventType;
158 switch(eventType) {
159 case DrmPlugin::kDrmPluginEventProvisionRequired:
160 ndkEventType = EVENT_PROVISION_REQUIRED;
161 break;
162 case DrmPlugin::kDrmPluginEventKeyNeeded:
163 ndkEventType = EVENT_KEY_REQUIRED;
164 break;
165 case DrmPlugin::kDrmPluginEventKeyExpired:
166 ndkEventType = EVENT_KEY_EXPIRED;
167 break;
168 case DrmPlugin::kDrmPluginEventVendorDefined:
169 ndkEventType = EVENT_VENDOR_DEFINED;
170 break;
Edwin Wongad02cc62018-08-23 13:48:27 -0700171 case DrmPlugin::kDrmPluginEventSessionReclaimed:
172 ndkEventType = EVENT_SESSION_RECLAIMED;
173 break;
Jeff Tinker3305b992014-05-14 18:39:25 -0700174 default:
Robert Shih61e1c762019-10-31 21:26:58 -0700175 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", eventType);
Edwin Wongad02cc62018-08-23 13:48:27 -0700176 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700177 }
178
Robert Shih61e1c762019-10-31 21:26:58 -0700179 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
180 int32_t dataSize = data.size();
181 const uint8_t *dataPtr = data.data();
Edwin Wongad02cc62018-08-23 13:48:27 -0700182 if (dataSize > 0) {
Robert Shih61e1c762019-10-31 21:26:58 -0700183 (*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
Edwin Wongad02cc62018-08-23 13:48:27 -0700184 } else {
Robert Shih61e1c762019-10-31 21:26:58 -0700185 ALOGE("invalid event data size=%d", dataSize);
Edwin Wongad02cc62018-08-23 13:48:27 -0700186 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700187}
188
Jeff Tinker497ca092014-05-13 09:31:15 -0700189extern "C" {
190
Marco Nelissene419d7c2014-05-15 14:17:25 -0700191static media_status_t translateStatus(status_t status) {
192 media_status_t result = AMEDIA_ERROR_UNKNOWN;
Jeff Tinker497ca092014-05-13 09:31:15 -0700193 switch (status) {
194 case OK:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700195 result = AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700196 break;
197 case android::ERROR_DRM_NOT_PROVISIONED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700198 result = AMEDIA_DRM_NOT_PROVISIONED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700199 break;
200 case android::ERROR_DRM_RESOURCE_BUSY:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700201 result = AMEDIA_DRM_RESOURCE_BUSY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700202 break;
203 case android::ERROR_DRM_DEVICE_REVOKED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700204 result = AMEDIA_DRM_DEVICE_REVOKED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700205 break;
206 case android::ERROR_DRM_CANNOT_HANDLE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700207 result = AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700208 break;
209 case android::ERROR_DRM_TAMPER_DETECTED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700210 result = AMEDIA_DRM_TAMPER_DETECTED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700211 break;
212 case android::ERROR_DRM_SESSION_NOT_OPENED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700213 result = AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700214 break;
215 case android::ERROR_DRM_NO_LICENSE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700216 result = AMEDIA_DRM_NEED_KEY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700217 break;
218 case android::ERROR_DRM_LICENSE_EXPIRED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700219 result = AMEDIA_DRM_LICENSE_EXPIRED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700220 break;
221 default:
Jeff Tinker497ca092014-05-13 09:31:15 -0700222 break;
223 }
224 return result;
225}
226
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700227static bool ShouldGetAppPackageName(void) {
228 // Check what this device's first API level was.
229 int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
230 if (firstApiLevel == 0) {
231 // First API Level is 0 on factory ROMs, but we can assume the current SDK
232 // version is the first if it's a factory ROM.
233 firstApiLevel = android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
234 }
235 return firstApiLevel >= 29; // Android Q
236}
237
238static status_t GetAppPackageName(String8 *packageName) {
239 sp<IServiceManager> serviceManager = defaultServiceManager();
240 sp<IBinder> binder = serviceManager->getService(String16("permission"));
241
242 sp<IPermissionController> permissionContol = interface_cast<IPermissionController>(binder);
243 if (permissionContol == NULL) {
244 ALOGE("Failed to get permission service");
245 return UNKNOWN_ERROR;
246 }
247
248 Vector<String16> packages;
249 permissionContol->getPackagesForUid(getuid(), packages);
250
251 if (packages.isEmpty()) {
252 ALOGE("Unable to get package name for current UID");
253 return UNKNOWN_ERROR;
254 }
255
256 *packageName = String8(packages[0]);
257 return OK;
258}
259
Jeff Tinker497ca092014-05-13 09:31:15 -0700260static sp<IDrm> CreateDrm() {
Robert Shih28c2ed32019-10-27 22:55:12 -0700261 return DrmUtils::MakeDrm();
Jeff Tinker497ca092014-05-13 09:31:15 -0700262}
263
264
265static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
266 sp<IDrm> drm = CreateDrm();
267
268 if (drm == NULL) {
269 return NULL;
270 }
271
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700272 String8 packageName;
273 if (ShouldGetAppPackageName()) {
274 status_t err = GetAppPackageName(&packageName);
275
276 if (err != OK) {
277 return NULL;
278 }
279 }
280
281 status_t err = drm->createPlugin(uuid, packageName);
Jeff Tinker497ca092014-05-13 09:31:15 -0700282
283 if (err != OK) {
284 return NULL;
285 }
286
287 return drm;
288}
289
Marco Nelissen3425fd52014-05-14 11:12:46 -0700290EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700291bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
292 sp<IDrm> drm = CreateDrm();
293
294 if (drm == NULL) {
295 return false;
296 }
297
298 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
Jeff Tinkerdb3fa5f2019-01-25 22:56:56 -0800299 bool isSupported = false;
300 status_t status = drm->isCryptoSchemeSupported(uuid, mimeStr,
301 DrmPlugin::kSecurityLevelUnknown, &isSupported);
302 return (status == OK) && isSupported;
Jeff Tinker497ca092014-05-13 09:31:15 -0700303}
304
Marco Nelissen3425fd52014-05-14 11:12:46 -0700305EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700306AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
307 AMediaDrm *mObj = new AMediaDrm();
308 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700309
310 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700311 return mObj;
312}
313
Marco Nelissen3425fd52014-05-14 11:12:46 -0700314EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700315void AMediaDrm_release(AMediaDrm *mObj) {
316 if (mObj->mDrm != NULL) {
317 mObj->mDrm->setListener(NULL);
318 mObj->mDrm->destroyPlugin();
319 mObj->mDrm.clear();
320 }
321 delete mObj;
322}
323
Jeff Tinker3305b992014-05-14 18:39:25 -0700324EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700325media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700326 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700327 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700328 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700329
330 if (mObj->mListener.get()) {
331 mObj->mListener->setEventListener(listener);
332 } else {
333 mObj->mListener = new DrmListener(mObj, listener);
334 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700335 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700336 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700337}
Jeff Tinker497ca092014-05-13 09:31:15 -0700338
Edwin Wongad02cc62018-08-23 13:48:27 -0700339EXPORT
340media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
341 AMediaDrmExpirationUpdateListener listener) {
342 if (!mObj || mObj->mDrm == NULL) {
343 return AMEDIA_ERROR_INVALID_OBJECT;
344 }
345
346 if (mObj->mListener.get()) {
347 mObj->mListener->setExpirationUpdateListener(listener);
348 } else {
349 mObj->mListener = new DrmListener(mObj, listener);
350 }
351 mObj->mDrm->setListener(mObj->mListener);
352 return AMEDIA_OK;
353}
354
355EXPORT
356media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
357 AMediaDrmKeysChangeListener listener) {
358 if (!mObj || mObj->mDrm == NULL) {
359 return AMEDIA_ERROR_INVALID_OBJECT;
360 }
361
362 if (mObj->mListener.get()) {
363 mObj->mListener->setKeysChangeListener(listener);
364 } else {
365 mObj->mListener = new DrmListener(mObj, listener);
366 }
367 mObj->mDrm->setListener(mObj->mListener);
368 return AMEDIA_OK;
369}
Jeff Tinker497ca092014-05-13 09:31:15 -0700370
371static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700372 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700373 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700374 return true;
375 }
376 }
377 return false;
378}
379
Marco Nelissen3425fd52014-05-14 11:12:46 -0700380EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700381media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700382 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700383 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700384 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700385 if (!sessionId) {
386 return AMEDIA_ERROR_INVALID_PARAMETER;
387 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700388 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000389 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Jeff Tinker497ca092014-05-13 09:31:15 -0700390 if (status == OK) {
391 mObj->mIds.push_front(session);
392 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700393 sessionId->ptr = iter->array();
394 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700395 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700396 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700397}
398
Marco Nelissen3425fd52014-05-14 11:12:46 -0700399EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700400media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700401 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700402 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700403 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700404 if (!sessionId) {
405 return AMEDIA_ERROR_INVALID_PARAMETER;
406 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700407
408 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700409 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700410 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700411 }
412 mObj->mDrm->closeSession(*iter);
413 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700414 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700415}
416
Marco Nelissen3425fd52014-05-14 11:12:46 -0700417EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700418media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700419 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
420 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700421 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700422
423 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700424 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700425 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700426 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700427 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700428 }
429
430 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700431 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700432 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700433 }
434
435 Vector<uint8_t> mdInit;
436 mdInit.appendArray(init, initSize);
437 DrmPlugin::KeyType mdKeyType;
438 switch (keyType) {
439 case KEY_TYPE_STREAMING:
440 mdKeyType = DrmPlugin::kKeyType_Streaming;
441 break;
442 case KEY_TYPE_OFFLINE:
443 mdKeyType = DrmPlugin::kKeyType_Offline;
444 break;
445 case KEY_TYPE_RELEASE:
446 mdKeyType = DrmPlugin::kKeyType_Release;
447 break;
448 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700449 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700450 }
451 KeyedVector<String8, String8> mdOptionalParameters;
452 for (size_t i = 0; i < numOptionalParameters; i++) {
453 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
454 String8(optionalParameters[i].mValue));
455 }
456 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700457 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700458 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700459 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700460 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
461 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700462 if (status != OK) {
463 return translateStatus(status);
464 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700465 *keyRequest = mObj->mKeyRequest.array();
466 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700467 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700468 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700469}
470
Marco Nelissen3425fd52014-05-14 11:12:46 -0700471EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700472media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
473 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700474
475 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700476 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700477 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700478 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700479 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700480 }
481
482 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700483 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700484 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700485 }
486 Vector<uint8_t> mdResponse;
487 mdResponse.appendArray(response, responseSize);
488
489 Vector<uint8_t> mdKeySetId;
490 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
491 if (status == OK) {
492 mObj->mIds.push_front(mdKeySetId);
493 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700494 keySetId->ptr = iter->array();
495 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700496 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700497 keySetId->ptr = NULL;
498 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700499 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700500 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700501}
502
Marco Nelissen3425fd52014-05-14 11:12:46 -0700503EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700504media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
505 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700506
507 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700508 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700509 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700510 if (!sessionId || !keySetId) {
511 return AMEDIA_ERROR_INVALID_PARAMETER;
512 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700513 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700514 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700515 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700516 }
517 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700518 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700519 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
520}
521
Marco Nelissen3425fd52014-05-14 11:12:46 -0700522EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700523media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700524 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700525 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700526 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700527 if (!keySetId) {
528 return AMEDIA_ERROR_INVALID_PARAMETER;
529 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700530 List<idvec_t>::iterator iter;
531 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700532 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700533 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700534 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700535 status = mObj->mDrm->removeKeys(keySet);
536 } else {
537 status = mObj->mDrm->removeKeys(*iter);
538 mObj->mIds.erase(iter);
539 }
540 return translateStatus(status);
541}
542
Marco Nelissen3425fd52014-05-14 11:12:46 -0700543EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700544media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
545 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700546
547 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700548 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700549 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700550 if (!sessionId || !numPairs) {
551 return AMEDIA_ERROR_INVALID_PARAMETER;
552 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700553 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700554 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700555 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700556 }
557
558 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
559 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700560 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700561 return translateStatus(status);
562 }
563
Marco Nelissen18a1b592014-05-20 08:45:18 -0700564 if (mObj->mQueryResults.size() > *numPairs) {
565 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700566 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700567 }
568
569 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
570 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700571 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700572 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700573 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700574 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700575}
576
Marco Nelissen3425fd52014-05-14 11:12:46 -0700577EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700578media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
579 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700580 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700581 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700582 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700583 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700584 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700585 }
586
587 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
588 mObj->mProvisionRequest, mObj->mProvisionUrl);
589 if (status != OK) {
590 return translateStatus(status);
591 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700592 *provisionRequest = mObj->mProvisionRequest.array();
593 *provisionRequestSize = mObj->mProvisionRequest.size();
594 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700595 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700596 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700597}
598
Marco Nelissen3425fd52014-05-14 11:12:46 -0700599EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700600media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700601 const uint8_t *response, size_t responseSize) {
602 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700603 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700604 }
605 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700606 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700607 }
608
609 Vector<uint8_t> mdResponse;
610 mdResponse.appendArray(response, responseSize);
611
612 Vector<uint8_t> unused;
613 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
614}
615
Marco Nelissen3425fd52014-05-14 11:12:46 -0700616EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700617media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700618 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700619
620 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700621 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700622 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700623 if (!numSecureStops) {
624 return AMEDIA_ERROR_INVALID_PARAMETER;
625 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700626 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
627 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700628 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700629 return translateStatus(status);
630 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700631 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700632 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700633 }
634 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
635 size_t i = 0;
636 while (iter != mObj->mSecureStops.end()) {
637 secureStops[i].ptr = iter->array();
638 secureStops[i].length = iter->size();
639 ++iter;
640 ++i;
641 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700642 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700643 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700644}
645
Marco Nelissen3425fd52014-05-14 11:12:46 -0700646EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700647media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700648 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700649
650 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700651 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700652 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700653 if (!ssRelease) {
654 return AMEDIA_ERROR_INVALID_PARAMETER;
655 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700656
657 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700658 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700659 return translateStatus(mObj->mDrm->releaseSecureStops(release));
660}
661
662
Marco Nelissen3425fd52014-05-14 11:12:46 -0700663EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700664media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700665 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700666
667 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700668 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700669 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700670 if (!propertyName || !propertyValue) {
671 return AMEDIA_ERROR_INVALID_PARAMETER;
672 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700673
674 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
675 mObj->mPropertyString);
676
677 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700678 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700679 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700680 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700681 }
682 return translateStatus(status);
683}
684
Marco Nelissen3425fd52014-05-14 11:12:46 -0700685EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700686media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700687 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700688 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700689 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700690 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700691 if (!propertyName || !propertyValue) {
692 return AMEDIA_ERROR_INVALID_PARAMETER;
693 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700694
695 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
696 mObj->mPropertyByteArray);
697
698 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700699 propertyValue->ptr = mObj->mPropertyByteArray.array();
700 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700701 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700702 propertyValue->ptr = NULL;
703 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700704 }
705 return translateStatus(status);
706}
707
Marco Nelissen3425fd52014-05-14 11:12:46 -0700708EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700709media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700710 const char *propertyName, const char *value) {
711 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700712 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700713 }
714
715 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
716 String8(value)));
717}
718
Marco Nelissen3425fd52014-05-14 11:12:46 -0700719EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700720media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700721 const char *propertyName, const uint8_t *value, size_t valueSize) {
722
723 Vector<uint8_t> byteArray;
724 byteArray.appendArray(value, valueSize);
725
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700726 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700727 byteArray));
728}
729
730
Marco Nelissene419d7c2014-05-15 14:17:25 -0700731static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700732 const AMediaDrmSessionId &sessionId,
733 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
734 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
735
736 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700737 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700738 }
739 List<idvec_t>::iterator iter;
740 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700741 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700742 }
743
744 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
745 if (status != OK) {
746 return translateStatus(status);
747 }
748
749 Vector<uint8_t> keyIdVec;
750 const size_t kKeyIdSize = 16;
751 keyIdVec.appendArray(keyId, kKeyIdSize);
752
753 Vector<uint8_t> inputVec;
754 inputVec.appendArray(input, dataSize);
755
756 Vector<uint8_t> ivVec;
757 const size_t kIvSize = 16;
758 ivVec.appendArray(iv, kIvSize);
759
760 Vector<uint8_t> outputVec;
761 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800762 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700763 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800764 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700765 }
766 if (status == OK) {
767 memcpy(output, outputVec.array(), outputVec.size());
768 }
769 return translateStatus(status);
770}
771
Marco Nelissen3425fd52014-05-14 11:12:46 -0700772EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700773media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700774 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
775 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700776 if (!sessionId) {
777 return AMEDIA_ERROR_INVALID_PARAMETER;
778 }
779 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700780 input, output, dataSize, true);
781}
782
Marco Nelissen3425fd52014-05-14 11:12:46 -0700783EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700784media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700785 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
786 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700787 if (!sessionId) {
788 return AMEDIA_ERROR_INVALID_PARAMETER;
789 }
790 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700791 input, output, dataSize, false);
792}
793
Marco Nelissen3425fd52014-05-14 11:12:46 -0700794EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700795media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700796 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
797 uint8_t *signature, size_t *signatureSize) {
798
799 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700800 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700801 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700802 if (!sessionId) {
803 return AMEDIA_ERROR_INVALID_PARAMETER;
804 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700805 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700806 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700807 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700808 }
809
810 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
811 if (status != OK) {
812 return translateStatus(status);
813 }
814
815 Vector<uint8_t> keyIdVec;
816 const size_t kKeyIdSize = 16;
817 keyIdVec.appendArray(keyId, kKeyIdSize);
818
819 Vector<uint8_t> messageVec;
820 messageVec.appendArray(message, messageSize);
821
822 Vector<uint8_t> signatureVec;
823 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
824 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700825 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700826 }
827 if (status == OK) {
828 memcpy(signature, signatureVec.array(), signatureVec.size());
829 }
830 return translateStatus(status);
831}
832
Marco Nelissen3425fd52014-05-14 11:12:46 -0700833EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700834media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700835 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
836 const uint8_t *signature, size_t signatureSize) {
837
838 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700839 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700840 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700841 if (!sessionId) {
842 return AMEDIA_ERROR_INVALID_PARAMETER;
843 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700844 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700845 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700846 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700847 }
848
849 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
850 if (status != OK) {
851 return translateStatus(status);
852 }
853
854 Vector<uint8_t> keyIdVec;
855 const size_t kKeyIdSize = 16;
856 keyIdVec.appendArray(keyId, kKeyIdSize);
857
858 Vector<uint8_t> messageVec;
859 messageVec.appendArray(message, messageSize);
860
861 Vector<uint8_t> signatureVec;
862 signatureVec.appendArray(signature, signatureSize);
863
864 bool match;
865 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
866 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700867 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700868 }
869 return translateStatus(status);
870}
871
872} // extern "C"