blob: 842216c0f027877c81d1bf4ef2ca488e522ea239 [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>
Marco Nelissenb4e0c3b2019-09-27 10:21:55 -070032#include <mediadrm/IDrm.h>
33#include <mediadrm/IDrmClient.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070034#include <media/stagefright/MediaErrors.h>
35#include <binder/IServiceManager.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070036#include <media/NdkMediaCrypto.h>
Marco Nelissenb4e0c3b2019-09-27 10:21:55 -070037#include <mediadrm/IMediaDrmService.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070038
39
40using namespace android;
41
42typedef Vector<uint8_t> idvec_t;
43
Jeff Tinker3305b992014-05-14 18:39:25 -070044struct DrmListener: virtual public BnDrmClient
45{
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
Jeff Tinker3305b992014-05-14 18:39:25 -070074 void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
75};
76
Jeff Tinker497ca092014-05-13 09:31:15 -070077struct AMediaDrm {
78 sp<IDrm> mDrm;
79 sp<IDrmClient> mDrmClient;
Jeff Tinker497ca092014-05-13 09:31:15 -070080 List<idvec_t> mIds;
81 KeyedVector<String8, String8> mQueryResults;
82 Vector<uint8_t> mKeyRequest;
83 Vector<uint8_t> mProvisionRequest;
84 String8 mProvisionUrl;
85 String8 mPropertyString;
86 Vector<uint8_t> mPropertyByteArray;
87 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -070088 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -070089};
90
Jeff Tinker3305b992014-05-14 18:39:25 -070091void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
Robert Shih641cf392019-09-10 18:00:42 -070092 if (!mEventListener || !mExpirationUpdateListener || !mKeysChangeListener) {
Edwin Wongad02cc62018-08-23 13:48:27 -070093 ALOGE("No listeners are specified");
Jeff Tinker3305b992014-05-14 18:39:25 -070094 return;
95 }
96
Edwin Wongad02cc62018-08-23 13:48:27 -070097 obj->setDataPosition(0);
98
Jeff Tinker3305b992014-05-14 18:39:25 -070099 AMediaDrmSessionId sessionId = {NULL, 0};
100 int32_t sessionIdSize = obj->readInt32();
Edwin Wongad02cc62018-08-23 13:48:27 -0700101 if (sessionIdSize <= 0) {
102 ALOGE("Invalid session id size");
103 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700104 }
105
Edwin Wongad02cc62018-08-23 13:48:27 -0700106 std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
107 sessionId.ptr = sessionIdData.get();
108 sessionId.length = sessionIdSize;
109 status_t err = obj->read(sessionIdData.get(), sessionId.length);
110 if (err != OK) {
111 ALOGE("Failed to read session id, error=%d", err);
112 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700113 }
114
Edwin Wongad02cc62018-08-23 13:48:27 -0700115 if (DrmPlugin::kDrmPluginEventExpirationUpdate == eventType) {
116 int64_t expiryTimeInMS = obj->readInt64();
117 if (expiryTimeInMS >= 0) {
118 (*mExpirationUpdateListener)(mObj, &sessionId, expiryTimeInMS);
119 } else {
120 ALOGE("Failed to read expiry time, status=%" PRId64 "", expiryTimeInMS);
121 }
122 return;
123 } else if (DrmPlugin::kDrmPluginEventKeysChange == eventType) {
124 int32_t numKeys = 0;
125 err = obj->readInt32(&numKeys);
126 if (err != OK) {
127 ALOGE("Failed to read number of keys status, error=%d", err);
128 return;
129 }
130
131 Vector<AMediaDrmKeyStatus> keysStatus;
132 std::vector<std::unique_ptr<uint8_t[]> > dataPointers;
133 AMediaDrmKeyStatus keyStatus;
134
135 for (size_t i = 0; i < numKeys; ++i) {
136 keyStatus.keyId.ptr = nullptr;
137 keyStatus.keyId.length = 0;
138 int32_t idSize = obj->readInt32();
139 if (idSize > 0) {
140 std::unique_ptr<uint8_t[]> data(new uint8_t[idSize]);
141 err = obj->read(data.get(), idSize);
142 if (err != OK) {
143 ALOGE("Failed to read key data, error=%d", err);
144 return;
145 }
146 keyStatus.keyId.ptr = data.get();
147 keyStatus.keyId.length = idSize;
148 dataPointers.push_back(std::move(data));
149 }
150 keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(obj->readInt32());
151 keysStatus.push(keyStatus);
152 }
153
154 bool hasNewUsableKey = obj->readInt32();
155 (*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
156 return;
157 }
158
159 // Handles AMediaDrmEventListener below:
160 // translates DrmPlugin event types into their NDK equivalents
Jeff Tinker3305b992014-05-14 18:39:25 -0700161 AMediaDrmEventType ndkEventType;
162 switch(eventType) {
163 case DrmPlugin::kDrmPluginEventProvisionRequired:
164 ndkEventType = EVENT_PROVISION_REQUIRED;
165 break;
166 case DrmPlugin::kDrmPluginEventKeyNeeded:
167 ndkEventType = EVENT_KEY_REQUIRED;
168 break;
169 case DrmPlugin::kDrmPluginEventKeyExpired:
170 ndkEventType = EVENT_KEY_EXPIRED;
171 break;
172 case DrmPlugin::kDrmPluginEventVendorDefined:
173 ndkEventType = EVENT_VENDOR_DEFINED;
174 break;
Edwin Wongad02cc62018-08-23 13:48:27 -0700175 case DrmPlugin::kDrmPluginEventSessionReclaimed:
176 ndkEventType = EVENT_SESSION_RECLAIMED;
177 break;
Jeff Tinker3305b992014-05-14 18:39:25 -0700178 default:
179 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
Edwin Wongad02cc62018-08-23 13:48:27 -0700180 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700181 }
182
Edwin Wongad02cc62018-08-23 13:48:27 -0700183 int32_t dataSize = obj->readInt32();
184 uint8_t *data = NULL;
185 if (dataSize > 0) {
186 data = new uint8_t[dataSize];
187 err = obj->read(data, dataSize);
188 if (err == OK) {
189 (*mEventListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
190 } else {
191 ALOGE("Failed to read event data, error=%d", err);
192 }
193 delete [] data;
194 } else {
195 ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
196 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700197}
198
Jeff Tinker497ca092014-05-13 09:31:15 -0700199extern "C" {
200
Marco Nelissene419d7c2014-05-15 14:17:25 -0700201static media_status_t translateStatus(status_t status) {
202 media_status_t result = AMEDIA_ERROR_UNKNOWN;
Jeff Tinker497ca092014-05-13 09:31:15 -0700203 switch (status) {
204 case OK:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700205 result = AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700206 break;
207 case android::ERROR_DRM_NOT_PROVISIONED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700208 result = AMEDIA_DRM_NOT_PROVISIONED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700209 break;
210 case android::ERROR_DRM_RESOURCE_BUSY:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700211 result = AMEDIA_DRM_RESOURCE_BUSY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700212 break;
213 case android::ERROR_DRM_DEVICE_REVOKED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700214 result = AMEDIA_DRM_DEVICE_REVOKED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700215 break;
216 case android::ERROR_DRM_CANNOT_HANDLE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700217 result = AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700218 break;
219 case android::ERROR_DRM_TAMPER_DETECTED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700220 result = AMEDIA_DRM_TAMPER_DETECTED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700221 break;
222 case android::ERROR_DRM_SESSION_NOT_OPENED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700223 result = AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700224 break;
225 case android::ERROR_DRM_NO_LICENSE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700226 result = AMEDIA_DRM_NEED_KEY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700227 break;
228 case android::ERROR_DRM_LICENSE_EXPIRED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700229 result = AMEDIA_DRM_LICENSE_EXPIRED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700230 break;
231 default:
Jeff Tinker497ca092014-05-13 09:31:15 -0700232 break;
233 }
234 return result;
235}
236
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700237static bool ShouldGetAppPackageName(void) {
238 // Check what this device's first API level was.
239 int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
240 if (firstApiLevel == 0) {
241 // First API Level is 0 on factory ROMs, but we can assume the current SDK
242 // version is the first if it's a factory ROM.
243 firstApiLevel = android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
244 }
245 return firstApiLevel >= 29; // Android Q
246}
247
248static status_t GetAppPackageName(String8 *packageName) {
249 sp<IServiceManager> serviceManager = defaultServiceManager();
250 sp<IBinder> binder = serviceManager->getService(String16("permission"));
251
252 sp<IPermissionController> permissionContol = interface_cast<IPermissionController>(binder);
253 if (permissionContol == NULL) {
254 ALOGE("Failed to get permission service");
255 return UNKNOWN_ERROR;
256 }
257
258 Vector<String16> packages;
259 permissionContol->getPackagesForUid(getuid(), packages);
260
261 if (packages.isEmpty()) {
262 ALOGE("Unable to get package name for current UID");
263 return UNKNOWN_ERROR;
264 }
265
266 *packageName = String8(packages[0]);
267 return OK;
268}
269
Jeff Tinker497ca092014-05-13 09:31:15 -0700270static sp<IDrm> CreateDrm() {
271 sp<IServiceManager> sm = defaultServiceManager();
Jeff Tinker30038072016-04-25 13:41:35 -0700272 sp<IBinder> binder = sm->getService(String16("media.drm"));
Jeff Tinker497ca092014-05-13 09:31:15 -0700273
Jeff Tinker30038072016-04-25 13:41:35 -0700274 sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
275 if (service == NULL) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700276 return NULL;
277 }
278
Jeff Tinker30038072016-04-25 13:41:35 -0700279 sp<IDrm> drm = service->makeDrm();
280 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
281 return NULL;
282 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700283 return drm;
284}
285
286
287static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
288 sp<IDrm> drm = CreateDrm();
289
290 if (drm == NULL) {
291 return NULL;
292 }
293
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700294 String8 packageName;
295 if (ShouldGetAppPackageName()) {
296 status_t err = GetAppPackageName(&packageName);
297
298 if (err != OK) {
299 return NULL;
300 }
301 }
302
303 status_t err = drm->createPlugin(uuid, packageName);
Jeff Tinker497ca092014-05-13 09:31:15 -0700304
305 if (err != OK) {
306 return NULL;
307 }
308
309 return drm;
310}
311
Marco Nelissen3425fd52014-05-14 11:12:46 -0700312EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700313bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
314 sp<IDrm> drm = CreateDrm();
315
316 if (drm == NULL) {
317 return false;
318 }
319
320 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
Jeff Tinkerdb3fa5f2019-01-25 22:56:56 -0800321 bool isSupported = false;
322 status_t status = drm->isCryptoSchemeSupported(uuid, mimeStr,
323 DrmPlugin::kSecurityLevelUnknown, &isSupported);
324 return (status == OK) && isSupported;
Jeff Tinker497ca092014-05-13 09:31:15 -0700325}
326
Marco Nelissen3425fd52014-05-14 11:12:46 -0700327EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700328AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
329 AMediaDrm *mObj = new AMediaDrm();
330 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700331
332 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700333 return mObj;
334}
335
Marco Nelissen3425fd52014-05-14 11:12:46 -0700336EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700337void AMediaDrm_release(AMediaDrm *mObj) {
338 if (mObj->mDrm != NULL) {
339 mObj->mDrm->setListener(NULL);
340 mObj->mDrm->destroyPlugin();
341 mObj->mDrm.clear();
342 }
343 delete mObj;
344}
345
Jeff Tinker3305b992014-05-14 18:39:25 -0700346EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700347media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700348 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700349 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700350 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700351
352 if (mObj->mListener.get()) {
353 mObj->mListener->setEventListener(listener);
354 } else {
355 mObj->mListener = new DrmListener(mObj, listener);
356 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700357 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700358 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700359}
Jeff Tinker497ca092014-05-13 09:31:15 -0700360
Edwin Wongad02cc62018-08-23 13:48:27 -0700361EXPORT
362media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
363 AMediaDrmExpirationUpdateListener listener) {
364 if (!mObj || mObj->mDrm == NULL) {
365 return AMEDIA_ERROR_INVALID_OBJECT;
366 }
367
368 if (mObj->mListener.get()) {
369 mObj->mListener->setExpirationUpdateListener(listener);
370 } else {
371 mObj->mListener = new DrmListener(mObj, listener);
372 }
373 mObj->mDrm->setListener(mObj->mListener);
374 return AMEDIA_OK;
375}
376
377EXPORT
378media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
379 AMediaDrmKeysChangeListener listener) {
380 if (!mObj || mObj->mDrm == NULL) {
381 return AMEDIA_ERROR_INVALID_OBJECT;
382 }
383
384 if (mObj->mListener.get()) {
385 mObj->mListener->setKeysChangeListener(listener);
386 } else {
387 mObj->mListener = new DrmListener(mObj, listener);
388 }
389 mObj->mDrm->setListener(mObj->mListener);
390 return AMEDIA_OK;
391}
Jeff Tinker497ca092014-05-13 09:31:15 -0700392
393static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700394 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700395 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700396 return true;
397 }
398 }
399 return false;
400}
401
Marco Nelissen3425fd52014-05-14 11:12:46 -0700402EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700403media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700404 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700405 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700406 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700407 if (!sessionId) {
408 return AMEDIA_ERROR_INVALID_PARAMETER;
409 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700410 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000411 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Jeff Tinker497ca092014-05-13 09:31:15 -0700412 if (status == OK) {
413 mObj->mIds.push_front(session);
414 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700415 sessionId->ptr = iter->array();
416 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700417 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700418 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700419}
420
Marco Nelissen3425fd52014-05-14 11:12:46 -0700421EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700422media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700423 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 (!sessionId) {
427 return AMEDIA_ERROR_INVALID_PARAMETER;
428 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700429
430 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700431 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700432 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700433 }
434 mObj->mDrm->closeSession(*iter);
435 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700436 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700437}
438
Marco Nelissen3425fd52014-05-14 11:12:46 -0700439EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700440media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700441 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
442 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700443 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700444
445 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700446 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700447 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700448 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700449 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700450 }
451
452 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700453 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700454 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700455 }
456
457 Vector<uint8_t> mdInit;
458 mdInit.appendArray(init, initSize);
459 DrmPlugin::KeyType mdKeyType;
460 switch (keyType) {
461 case KEY_TYPE_STREAMING:
462 mdKeyType = DrmPlugin::kKeyType_Streaming;
463 break;
464 case KEY_TYPE_OFFLINE:
465 mdKeyType = DrmPlugin::kKeyType_Offline;
466 break;
467 case KEY_TYPE_RELEASE:
468 mdKeyType = DrmPlugin::kKeyType_Release;
469 break;
470 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700471 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700472 }
473 KeyedVector<String8, String8> mdOptionalParameters;
474 for (size_t i = 0; i < numOptionalParameters; i++) {
475 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
476 String8(optionalParameters[i].mValue));
477 }
478 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700479 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700480 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700481 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700482 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
483 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700484 if (status != OK) {
485 return translateStatus(status);
486 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700487 *keyRequest = mObj->mKeyRequest.array();
488 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700489 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700490 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700491}
492
Marco Nelissen3425fd52014-05-14 11:12:46 -0700493EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700494media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
495 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700496
497 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700498 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700499 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700500 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700501 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700502 }
503
504 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700505 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700506 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700507 }
508 Vector<uint8_t> mdResponse;
509 mdResponse.appendArray(response, responseSize);
510
511 Vector<uint8_t> mdKeySetId;
512 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
513 if (status == OK) {
514 mObj->mIds.push_front(mdKeySetId);
515 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700516 keySetId->ptr = iter->array();
517 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700518 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700519 keySetId->ptr = NULL;
520 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700521 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700522 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700523}
524
Marco Nelissen3425fd52014-05-14 11:12:46 -0700525EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700526media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
527 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700528
529 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700530 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700531 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700532 if (!sessionId || !keySetId) {
533 return AMEDIA_ERROR_INVALID_PARAMETER;
534 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700535 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700536 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700537 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700538 }
539 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700540 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700541 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
542}
543
Marco Nelissen3425fd52014-05-14 11:12:46 -0700544EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700545media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700546 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700547 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700548 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700549 if (!keySetId) {
550 return AMEDIA_ERROR_INVALID_PARAMETER;
551 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700552 List<idvec_t>::iterator iter;
553 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700554 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700555 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700556 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700557 status = mObj->mDrm->removeKeys(keySet);
558 } else {
559 status = mObj->mDrm->removeKeys(*iter);
560 mObj->mIds.erase(iter);
561 }
562 return translateStatus(status);
563}
564
Marco Nelissen3425fd52014-05-14 11:12:46 -0700565EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700566media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
567 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700568
569 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700570 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700571 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700572 if (!sessionId || !numPairs) {
573 return AMEDIA_ERROR_INVALID_PARAMETER;
574 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700575 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700576 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700577 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700578 }
579
580 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
581 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700582 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700583 return translateStatus(status);
584 }
585
Marco Nelissen18a1b592014-05-20 08:45:18 -0700586 if (mObj->mQueryResults.size() > *numPairs) {
587 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700588 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700589 }
590
591 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
592 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700593 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700594 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700595 *numPairs = mObj->mQueryResults.size();
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 Nelissen18a1b592014-05-20 08:45:18 -0700600media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
601 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700602 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 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700605 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700606 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700607 }
608
609 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
610 mObj->mProvisionRequest, mObj->mProvisionUrl);
611 if (status != OK) {
612 return translateStatus(status);
613 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700614 *provisionRequest = mObj->mProvisionRequest.array();
615 *provisionRequestSize = mObj->mProvisionRequest.size();
616 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700617 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700618 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700619}
620
Marco Nelissen3425fd52014-05-14 11:12:46 -0700621EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700622media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700623 const uint8_t *response, size_t responseSize) {
624 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700625 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700626 }
627 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700628 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700629 }
630
631 Vector<uint8_t> mdResponse;
632 mdResponse.appendArray(response, responseSize);
633
634 Vector<uint8_t> unused;
635 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
636}
637
Marco Nelissen3425fd52014-05-14 11:12:46 -0700638EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700639media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700640 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700641
642 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700643 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700644 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700645 if (!numSecureStops) {
646 return AMEDIA_ERROR_INVALID_PARAMETER;
647 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700648 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
649 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700650 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700651 return translateStatus(status);
652 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700653 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700654 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700655 }
656 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
657 size_t i = 0;
658 while (iter != mObj->mSecureStops.end()) {
659 secureStops[i].ptr = iter->array();
660 secureStops[i].length = iter->size();
661 ++iter;
662 ++i;
663 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700664 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700665 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700666}
667
Marco Nelissen3425fd52014-05-14 11:12:46 -0700668EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700669media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700670 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700671
672 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700673 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700674 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700675 if (!ssRelease) {
676 return AMEDIA_ERROR_INVALID_PARAMETER;
677 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700678
679 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700680 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700681 return translateStatus(mObj->mDrm->releaseSecureStops(release));
682}
683
684
Marco Nelissen3425fd52014-05-14 11:12:46 -0700685EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700686media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700687 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700688
689 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->getPropertyString(String8(propertyName),
697 mObj->mPropertyString);
698
699 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700700 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700701 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700702 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700703 }
704 return translateStatus(status);
705}
706
Marco Nelissen3425fd52014-05-14 11:12:46 -0700707EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700708media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700709 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700710 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700711 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700712 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700713 if (!propertyName || !propertyValue) {
714 return AMEDIA_ERROR_INVALID_PARAMETER;
715 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700716
717 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
718 mObj->mPropertyByteArray);
719
720 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700721 propertyValue->ptr = mObj->mPropertyByteArray.array();
722 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700723 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700724 propertyValue->ptr = NULL;
725 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700726 }
727 return translateStatus(status);
728}
729
Marco Nelissen3425fd52014-05-14 11:12:46 -0700730EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700731media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700732 const char *propertyName, const char *value) {
733 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700734 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700735 }
736
737 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
738 String8(value)));
739}
740
Marco Nelissen3425fd52014-05-14 11:12:46 -0700741EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700742media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700743 const char *propertyName, const uint8_t *value, size_t valueSize) {
744
745 Vector<uint8_t> byteArray;
746 byteArray.appendArray(value, valueSize);
747
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700748 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700749 byteArray));
750}
751
752
Marco Nelissene419d7c2014-05-15 14:17:25 -0700753static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700754 const AMediaDrmSessionId &sessionId,
755 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
756 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
757
758 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700759 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700760 }
761 List<idvec_t>::iterator iter;
762 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700763 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700764 }
765
766 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
767 if (status != OK) {
768 return translateStatus(status);
769 }
770
771 Vector<uint8_t> keyIdVec;
772 const size_t kKeyIdSize = 16;
773 keyIdVec.appendArray(keyId, kKeyIdSize);
774
775 Vector<uint8_t> inputVec;
776 inputVec.appendArray(input, dataSize);
777
778 Vector<uint8_t> ivVec;
779 const size_t kIvSize = 16;
780 ivVec.appendArray(iv, kIvSize);
781
782 Vector<uint8_t> outputVec;
783 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800784 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700785 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800786 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700787 }
788 if (status == OK) {
789 memcpy(output, outputVec.array(), outputVec.size());
790 }
791 return translateStatus(status);
792}
793
Marco Nelissen3425fd52014-05-14 11:12:46 -0700794EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700795media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700796 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
797 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700798 if (!sessionId) {
799 return AMEDIA_ERROR_INVALID_PARAMETER;
800 }
801 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700802 input, output, dataSize, true);
803}
804
Marco Nelissen3425fd52014-05-14 11:12:46 -0700805EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700806media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700807 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
808 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700809 if (!sessionId) {
810 return AMEDIA_ERROR_INVALID_PARAMETER;
811 }
812 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700813 input, output, dataSize, false);
814}
815
Marco Nelissen3425fd52014-05-14 11:12:46 -0700816EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700817media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700818 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
819 uint8_t *signature, size_t *signatureSize) {
820
821 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700822 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700823 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700824 if (!sessionId) {
825 return AMEDIA_ERROR_INVALID_PARAMETER;
826 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700827 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700828 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700829 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700830 }
831
832 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
833 if (status != OK) {
834 return translateStatus(status);
835 }
836
837 Vector<uint8_t> keyIdVec;
838 const size_t kKeyIdSize = 16;
839 keyIdVec.appendArray(keyId, kKeyIdSize);
840
841 Vector<uint8_t> messageVec;
842 messageVec.appendArray(message, messageSize);
843
844 Vector<uint8_t> signatureVec;
845 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
846 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700847 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700848 }
849 if (status == OK) {
850 memcpy(signature, signatureVec.array(), signatureVec.size());
851 }
852 return translateStatus(status);
853}
854
Marco Nelissen3425fd52014-05-14 11:12:46 -0700855EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700856media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700857 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
858 const uint8_t *signature, size_t signatureSize) {
859
860 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700861 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700862 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700863 if (!sessionId) {
864 return AMEDIA_ERROR_INVALID_PARAMETER;
865 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700866 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700867 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700868 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700869 }
870
871 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
872 if (status != OK) {
873 return translateStatus(status);
874 }
875
876 Vector<uint8_t> keyIdVec;
877 const size_t kKeyIdSize = 16;
878 keyIdVec.appendArray(keyId, kKeyIdSize);
879
880 Vector<uint8_t> messageVec;
881 messageVec.appendArray(message, messageSize);
882
883 Vector<uint8_t> signatureVec;
884 signatureVec.appendArray(signature, signatureSize);
885
886 bool match;
887 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
888 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700889 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700890 }
891 return translateStatus(status);
892}
893
894} // extern "C"