blob: 58aa6a3b2b95ef86abfe76e155b885307b597d38 [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
Jeff Tinker3305b992014-05-14 18:39:25 -070075 void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
76};
77
Jeff Tinker497ca092014-05-13 09:31:15 -070078struct AMediaDrm {
79 sp<IDrm> mDrm;
80 sp<IDrmClient> mDrmClient;
Jeff Tinker497ca092014-05-13 09:31:15 -070081 List<idvec_t> mIds;
82 KeyedVector<String8, String8> mQueryResults;
83 Vector<uint8_t> mKeyRequest;
84 Vector<uint8_t> mProvisionRequest;
85 String8 mProvisionUrl;
86 String8 mPropertyString;
87 Vector<uint8_t> mPropertyByteArray;
88 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -070089 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -070090};
91
Jeff Tinker3305b992014-05-14 18:39:25 -070092void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
Robert Shih641cf392019-09-10 18:00:42 -070093 if (!mEventListener || !mExpirationUpdateListener || !mKeysChangeListener) {
Edwin Wongad02cc62018-08-23 13:48:27 -070094 ALOGE("No listeners are specified");
Jeff Tinker3305b992014-05-14 18:39:25 -070095 return;
96 }
97
Edwin Wongad02cc62018-08-23 13:48:27 -070098 obj->setDataPosition(0);
99
Jeff Tinker3305b992014-05-14 18:39:25 -0700100 AMediaDrmSessionId sessionId = {NULL, 0};
101 int32_t sessionIdSize = obj->readInt32();
Edwin Wongad02cc62018-08-23 13:48:27 -0700102 if (sessionIdSize <= 0) {
103 ALOGE("Invalid session id size");
104 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700105 }
106
Edwin Wongad02cc62018-08-23 13:48:27 -0700107 std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
108 sessionId.ptr = sessionIdData.get();
109 sessionId.length = sessionIdSize;
110 status_t err = obj->read(sessionIdData.get(), sessionId.length);
111 if (err != OK) {
112 ALOGE("Failed to read session id, error=%d", err);
113 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700114 }
115
Edwin Wongad02cc62018-08-23 13:48:27 -0700116 if (DrmPlugin::kDrmPluginEventExpirationUpdate == eventType) {
117 int64_t expiryTimeInMS = obj->readInt64();
118 if (expiryTimeInMS >= 0) {
119 (*mExpirationUpdateListener)(mObj, &sessionId, expiryTimeInMS);
120 } else {
121 ALOGE("Failed to read expiry time, status=%" PRId64 "", expiryTimeInMS);
122 }
123 return;
124 } else if (DrmPlugin::kDrmPluginEventKeysChange == eventType) {
125 int32_t numKeys = 0;
126 err = obj->readInt32(&numKeys);
127 if (err != OK) {
128 ALOGE("Failed to read number of keys status, error=%d", err);
129 return;
130 }
131
132 Vector<AMediaDrmKeyStatus> keysStatus;
133 std::vector<std::unique_ptr<uint8_t[]> > dataPointers;
134 AMediaDrmKeyStatus keyStatus;
135
136 for (size_t i = 0; i < numKeys; ++i) {
137 keyStatus.keyId.ptr = nullptr;
138 keyStatus.keyId.length = 0;
139 int32_t idSize = obj->readInt32();
140 if (idSize > 0) {
141 std::unique_ptr<uint8_t[]> data(new uint8_t[idSize]);
142 err = obj->read(data.get(), idSize);
143 if (err != OK) {
144 ALOGE("Failed to read key data, error=%d", err);
145 return;
146 }
147 keyStatus.keyId.ptr = data.get();
148 keyStatus.keyId.length = idSize;
149 dataPointers.push_back(std::move(data));
150 }
151 keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(obj->readInt32());
152 keysStatus.push(keyStatus);
153 }
154
155 bool hasNewUsableKey = obj->readInt32();
156 (*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
157 return;
158 }
159
160 // Handles AMediaDrmEventListener below:
161 // translates DrmPlugin event types into their NDK equivalents
Jeff Tinker3305b992014-05-14 18:39:25 -0700162 AMediaDrmEventType ndkEventType;
163 switch(eventType) {
164 case DrmPlugin::kDrmPluginEventProvisionRequired:
165 ndkEventType = EVENT_PROVISION_REQUIRED;
166 break;
167 case DrmPlugin::kDrmPluginEventKeyNeeded:
168 ndkEventType = EVENT_KEY_REQUIRED;
169 break;
170 case DrmPlugin::kDrmPluginEventKeyExpired:
171 ndkEventType = EVENT_KEY_EXPIRED;
172 break;
173 case DrmPlugin::kDrmPluginEventVendorDefined:
174 ndkEventType = EVENT_VENDOR_DEFINED;
175 break;
Edwin Wongad02cc62018-08-23 13:48:27 -0700176 case DrmPlugin::kDrmPluginEventSessionReclaimed:
177 ndkEventType = EVENT_SESSION_RECLAIMED;
178 break;
Jeff Tinker3305b992014-05-14 18:39:25 -0700179 default:
180 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
Edwin Wongad02cc62018-08-23 13:48:27 -0700181 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700182 }
183
Edwin Wongad02cc62018-08-23 13:48:27 -0700184 int32_t dataSize = obj->readInt32();
185 uint8_t *data = NULL;
186 if (dataSize > 0) {
187 data = new uint8_t[dataSize];
188 err = obj->read(data, dataSize);
189 if (err == OK) {
190 (*mEventListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
191 } else {
192 ALOGE("Failed to read event data, error=%d", err);
193 }
194 delete [] data;
195 } else {
196 ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
197 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700198}
199
Jeff Tinker497ca092014-05-13 09:31:15 -0700200extern "C" {
201
Marco Nelissene419d7c2014-05-15 14:17:25 -0700202static media_status_t translateStatus(status_t status) {
203 media_status_t result = AMEDIA_ERROR_UNKNOWN;
Jeff Tinker497ca092014-05-13 09:31:15 -0700204 switch (status) {
205 case OK:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700206 result = AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700207 break;
208 case android::ERROR_DRM_NOT_PROVISIONED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700209 result = AMEDIA_DRM_NOT_PROVISIONED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700210 break;
211 case android::ERROR_DRM_RESOURCE_BUSY:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700212 result = AMEDIA_DRM_RESOURCE_BUSY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700213 break;
214 case android::ERROR_DRM_DEVICE_REVOKED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700215 result = AMEDIA_DRM_DEVICE_REVOKED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700216 break;
217 case android::ERROR_DRM_CANNOT_HANDLE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700218 result = AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700219 break;
220 case android::ERROR_DRM_TAMPER_DETECTED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700221 result = AMEDIA_DRM_TAMPER_DETECTED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700222 break;
223 case android::ERROR_DRM_SESSION_NOT_OPENED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700224 result = AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700225 break;
226 case android::ERROR_DRM_NO_LICENSE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700227 result = AMEDIA_DRM_NEED_KEY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700228 break;
229 case android::ERROR_DRM_LICENSE_EXPIRED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700230 result = AMEDIA_DRM_LICENSE_EXPIRED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700231 break;
232 default:
Jeff Tinker497ca092014-05-13 09:31:15 -0700233 break;
234 }
235 return result;
236}
237
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700238static bool ShouldGetAppPackageName(void) {
239 // Check what this device's first API level was.
240 int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
241 if (firstApiLevel == 0) {
242 // First API Level is 0 on factory ROMs, but we can assume the current SDK
243 // version is the first if it's a factory ROM.
244 firstApiLevel = android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
245 }
246 return firstApiLevel >= 29; // Android Q
247}
248
249static status_t GetAppPackageName(String8 *packageName) {
250 sp<IServiceManager> serviceManager = defaultServiceManager();
251 sp<IBinder> binder = serviceManager->getService(String16("permission"));
252
253 sp<IPermissionController> permissionContol = interface_cast<IPermissionController>(binder);
254 if (permissionContol == NULL) {
255 ALOGE("Failed to get permission service");
256 return UNKNOWN_ERROR;
257 }
258
259 Vector<String16> packages;
260 permissionContol->getPackagesForUid(getuid(), packages);
261
262 if (packages.isEmpty()) {
263 ALOGE("Unable to get package name for current UID");
264 return UNKNOWN_ERROR;
265 }
266
267 *packageName = String8(packages[0]);
268 return OK;
269}
270
Jeff Tinker497ca092014-05-13 09:31:15 -0700271static sp<IDrm> CreateDrm() {
Robert Shih28c2ed32019-10-27 22:55:12 -0700272 return DrmUtils::MakeDrm();
Jeff Tinker497ca092014-05-13 09:31:15 -0700273}
274
275
276static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
277 sp<IDrm> drm = CreateDrm();
278
279 if (drm == NULL) {
280 return NULL;
281 }
282
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700283 String8 packageName;
284 if (ShouldGetAppPackageName()) {
285 status_t err = GetAppPackageName(&packageName);
286
287 if (err != OK) {
288 return NULL;
289 }
290 }
291
292 status_t err = drm->createPlugin(uuid, packageName);
Jeff Tinker497ca092014-05-13 09:31:15 -0700293
294 if (err != OK) {
295 return NULL;
296 }
297
298 return drm;
299}
300
Marco Nelissen3425fd52014-05-14 11:12:46 -0700301EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700302bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
303 sp<IDrm> drm = CreateDrm();
304
305 if (drm == NULL) {
306 return false;
307 }
308
309 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
Jeff Tinkerdb3fa5f2019-01-25 22:56:56 -0800310 bool isSupported = false;
311 status_t status = drm->isCryptoSchemeSupported(uuid, mimeStr,
312 DrmPlugin::kSecurityLevelUnknown, &isSupported);
313 return (status == OK) && isSupported;
Jeff Tinker497ca092014-05-13 09:31:15 -0700314}
315
Marco Nelissen3425fd52014-05-14 11:12:46 -0700316EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700317AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
318 AMediaDrm *mObj = new AMediaDrm();
319 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700320
321 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700322 return mObj;
323}
324
Marco Nelissen3425fd52014-05-14 11:12:46 -0700325EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700326void AMediaDrm_release(AMediaDrm *mObj) {
327 if (mObj->mDrm != NULL) {
328 mObj->mDrm->setListener(NULL);
329 mObj->mDrm->destroyPlugin();
330 mObj->mDrm.clear();
331 }
332 delete mObj;
333}
334
Jeff Tinker3305b992014-05-14 18:39:25 -0700335EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700336media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700337 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700338 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700339 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700340
341 if (mObj->mListener.get()) {
342 mObj->mListener->setEventListener(listener);
343 } else {
344 mObj->mListener = new DrmListener(mObj, listener);
345 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700346 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700347 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700348}
Jeff Tinker497ca092014-05-13 09:31:15 -0700349
Edwin Wongad02cc62018-08-23 13:48:27 -0700350EXPORT
351media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
352 AMediaDrmExpirationUpdateListener listener) {
353 if (!mObj || mObj->mDrm == NULL) {
354 return AMEDIA_ERROR_INVALID_OBJECT;
355 }
356
357 if (mObj->mListener.get()) {
358 mObj->mListener->setExpirationUpdateListener(listener);
359 } else {
360 mObj->mListener = new DrmListener(mObj, listener);
361 }
362 mObj->mDrm->setListener(mObj->mListener);
363 return AMEDIA_OK;
364}
365
366EXPORT
367media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
368 AMediaDrmKeysChangeListener listener) {
369 if (!mObj || mObj->mDrm == NULL) {
370 return AMEDIA_ERROR_INVALID_OBJECT;
371 }
372
373 if (mObj->mListener.get()) {
374 mObj->mListener->setKeysChangeListener(listener);
375 } else {
376 mObj->mListener = new DrmListener(mObj, listener);
377 }
378 mObj->mDrm->setListener(mObj->mListener);
379 return AMEDIA_OK;
380}
Jeff Tinker497ca092014-05-13 09:31:15 -0700381
382static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700383 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700384 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700385 return true;
386 }
387 }
388 return false;
389}
390
Marco Nelissen3425fd52014-05-14 11:12:46 -0700391EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700392media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700393 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700394 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700395 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700396 if (!sessionId) {
397 return AMEDIA_ERROR_INVALID_PARAMETER;
398 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700399 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000400 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Jeff Tinker497ca092014-05-13 09:31:15 -0700401 if (status == OK) {
402 mObj->mIds.push_front(session);
403 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700404 sessionId->ptr = iter->array();
405 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700406 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700407 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700408}
409
Marco Nelissen3425fd52014-05-14 11:12:46 -0700410EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700411media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700412 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700413 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700414 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700415 if (!sessionId) {
416 return AMEDIA_ERROR_INVALID_PARAMETER;
417 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700418
419 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700420 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700421 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700422 }
423 mObj->mDrm->closeSession(*iter);
424 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700425 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700426}
427
Marco Nelissen3425fd52014-05-14 11:12:46 -0700428EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700429media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700430 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
431 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700432 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700433
434 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700435 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700436 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700437 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700438 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700439 }
440
441 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700442 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700443 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700444 }
445
446 Vector<uint8_t> mdInit;
447 mdInit.appendArray(init, initSize);
448 DrmPlugin::KeyType mdKeyType;
449 switch (keyType) {
450 case KEY_TYPE_STREAMING:
451 mdKeyType = DrmPlugin::kKeyType_Streaming;
452 break;
453 case KEY_TYPE_OFFLINE:
454 mdKeyType = DrmPlugin::kKeyType_Offline;
455 break;
456 case KEY_TYPE_RELEASE:
457 mdKeyType = DrmPlugin::kKeyType_Release;
458 break;
459 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700460 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700461 }
462 KeyedVector<String8, String8> mdOptionalParameters;
463 for (size_t i = 0; i < numOptionalParameters; i++) {
464 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
465 String8(optionalParameters[i].mValue));
466 }
467 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700468 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700469 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700470 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700471 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
472 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700473 if (status != OK) {
474 return translateStatus(status);
475 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700476 *keyRequest = mObj->mKeyRequest.array();
477 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700478 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700479 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700480}
481
Marco Nelissen3425fd52014-05-14 11:12:46 -0700482EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700483media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
484 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700485
486 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700487 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700488 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700489 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700490 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700491 }
492
493 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700494 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700495 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700496 }
497 Vector<uint8_t> mdResponse;
498 mdResponse.appendArray(response, responseSize);
499
500 Vector<uint8_t> mdKeySetId;
501 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
502 if (status == OK) {
503 mObj->mIds.push_front(mdKeySetId);
504 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700505 keySetId->ptr = iter->array();
506 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700507 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700508 keySetId->ptr = NULL;
509 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700510 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700511 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700512}
513
Marco Nelissen3425fd52014-05-14 11:12:46 -0700514EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700515media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
516 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700517
518 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700519 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700520 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700521 if (!sessionId || !keySetId) {
522 return AMEDIA_ERROR_INVALID_PARAMETER;
523 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700524 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700525 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700526 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700527 }
528 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700529 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700530 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
531}
532
Marco Nelissen3425fd52014-05-14 11:12:46 -0700533EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700534media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700535 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700536 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700537 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700538 if (!keySetId) {
539 return AMEDIA_ERROR_INVALID_PARAMETER;
540 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700541 List<idvec_t>::iterator iter;
542 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700543 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700544 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700545 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700546 status = mObj->mDrm->removeKeys(keySet);
547 } else {
548 status = mObj->mDrm->removeKeys(*iter);
549 mObj->mIds.erase(iter);
550 }
551 return translateStatus(status);
552}
553
Marco Nelissen3425fd52014-05-14 11:12:46 -0700554EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700555media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
556 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700557
558 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700559 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700560 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700561 if (!sessionId || !numPairs) {
562 return AMEDIA_ERROR_INVALID_PARAMETER;
563 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700564 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700565 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700566 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700567 }
568
569 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
570 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700571 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700572 return translateStatus(status);
573 }
574
Marco Nelissen18a1b592014-05-20 08:45:18 -0700575 if (mObj->mQueryResults.size() > *numPairs) {
576 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700577 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700578 }
579
580 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
581 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700582 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700583 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700584 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700585 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700586}
587
Marco Nelissen3425fd52014-05-14 11:12:46 -0700588EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700589media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
590 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700591 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700592 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700593 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700594 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700595 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700596 }
597
598 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
599 mObj->mProvisionRequest, mObj->mProvisionUrl);
600 if (status != OK) {
601 return translateStatus(status);
602 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700603 *provisionRequest = mObj->mProvisionRequest.array();
604 *provisionRequestSize = mObj->mProvisionRequest.size();
605 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700606 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700607 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700608}
609
Marco Nelissen3425fd52014-05-14 11:12:46 -0700610EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700611media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700612 const uint8_t *response, size_t responseSize) {
613 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700614 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700615 }
616 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700617 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700618 }
619
620 Vector<uint8_t> mdResponse;
621 mdResponse.appendArray(response, responseSize);
622
623 Vector<uint8_t> unused;
624 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
625}
626
Marco Nelissen3425fd52014-05-14 11:12:46 -0700627EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700628media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700629 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700630
631 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700632 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700633 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700634 if (!numSecureStops) {
635 return AMEDIA_ERROR_INVALID_PARAMETER;
636 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700637 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
638 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700639 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700640 return translateStatus(status);
641 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700642 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700643 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700644 }
645 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
646 size_t i = 0;
647 while (iter != mObj->mSecureStops.end()) {
648 secureStops[i].ptr = iter->array();
649 secureStops[i].length = iter->size();
650 ++iter;
651 ++i;
652 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700653 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700654 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700655}
656
Marco Nelissen3425fd52014-05-14 11:12:46 -0700657EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700658media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700659 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700660
661 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700662 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700663 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700664 if (!ssRelease) {
665 return AMEDIA_ERROR_INVALID_PARAMETER;
666 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700667
668 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700669 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700670 return translateStatus(mObj->mDrm->releaseSecureStops(release));
671}
672
673
Marco Nelissen3425fd52014-05-14 11:12:46 -0700674EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700675media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700676 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700677
678 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700679 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700680 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700681 if (!propertyName || !propertyValue) {
682 return AMEDIA_ERROR_INVALID_PARAMETER;
683 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700684
685 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
686 mObj->mPropertyString);
687
688 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700689 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700690 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700691 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700692 }
693 return translateStatus(status);
694}
695
Marco Nelissen3425fd52014-05-14 11:12:46 -0700696EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700697media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700698 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700699 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700700 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700701 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700702 if (!propertyName || !propertyValue) {
703 return AMEDIA_ERROR_INVALID_PARAMETER;
704 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700705
706 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
707 mObj->mPropertyByteArray);
708
709 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700710 propertyValue->ptr = mObj->mPropertyByteArray.array();
711 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700712 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700713 propertyValue->ptr = NULL;
714 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700715 }
716 return translateStatus(status);
717}
718
Marco Nelissen3425fd52014-05-14 11:12:46 -0700719EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700720media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700721 const char *propertyName, const char *value) {
722 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700723 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700724 }
725
726 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
727 String8(value)));
728}
729
Marco Nelissen3425fd52014-05-14 11:12:46 -0700730EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700731media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700732 const char *propertyName, const uint8_t *value, size_t valueSize) {
733
734 Vector<uint8_t> byteArray;
735 byteArray.appendArray(value, valueSize);
736
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700737 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700738 byteArray));
739}
740
741
Marco Nelissene419d7c2014-05-15 14:17:25 -0700742static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700743 const AMediaDrmSessionId &sessionId,
744 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
745 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
746
747 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700748 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700749 }
750 List<idvec_t>::iterator iter;
751 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700752 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700753 }
754
755 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
756 if (status != OK) {
757 return translateStatus(status);
758 }
759
760 Vector<uint8_t> keyIdVec;
761 const size_t kKeyIdSize = 16;
762 keyIdVec.appendArray(keyId, kKeyIdSize);
763
764 Vector<uint8_t> inputVec;
765 inputVec.appendArray(input, dataSize);
766
767 Vector<uint8_t> ivVec;
768 const size_t kIvSize = 16;
769 ivVec.appendArray(iv, kIvSize);
770
771 Vector<uint8_t> outputVec;
772 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800773 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700774 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800775 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700776 }
777 if (status == OK) {
778 memcpy(output, outputVec.array(), outputVec.size());
779 }
780 return translateStatus(status);
781}
782
Marco Nelissen3425fd52014-05-14 11:12:46 -0700783EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700784media_status_t AMediaDrm_encrypt(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, true);
792}
793
Marco Nelissen3425fd52014-05-14 11:12:46 -0700794EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700795media_status_t AMediaDrm_decrypt(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, false);
803}
804
Marco Nelissen3425fd52014-05-14 11:12:46 -0700805EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700806media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700807 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
808 uint8_t *signature, size_t *signatureSize) {
809
810 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700811 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700812 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700813 if (!sessionId) {
814 return AMEDIA_ERROR_INVALID_PARAMETER;
815 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700816 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700817 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700818 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700819 }
820
821 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
822 if (status != OK) {
823 return translateStatus(status);
824 }
825
826 Vector<uint8_t> keyIdVec;
827 const size_t kKeyIdSize = 16;
828 keyIdVec.appendArray(keyId, kKeyIdSize);
829
830 Vector<uint8_t> messageVec;
831 messageVec.appendArray(message, messageSize);
832
833 Vector<uint8_t> signatureVec;
834 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
835 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700836 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700837 }
838 if (status == OK) {
839 memcpy(signature, signatureVec.array(), signatureVec.size());
840 }
841 return translateStatus(status);
842}
843
Marco Nelissen3425fd52014-05-14 11:12:46 -0700844EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700845media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700846 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
847 const uint8_t *signature, size_t signatureSize) {
848
849 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700850 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700851 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700852 if (!sessionId) {
853 return AMEDIA_ERROR_INVALID_PARAMETER;
854 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700855 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700856 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700857 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700858 }
859
860 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
861 if (status != OK) {
862 return translateStatus(status);
863 }
864
865 Vector<uint8_t> keyIdVec;
866 const size_t kKeyIdSize = 16;
867 keyIdVec.appendArray(keyId, kKeyIdSize);
868
869 Vector<uint8_t> messageVec;
870 messageVec.appendArray(message, messageSize);
871
872 Vector<uint8_t> signatureVec;
873 signatureVec.appendArray(signature, signatureSize);
874
875 bool match;
876 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
877 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700878 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700879 }
880 return translateStatus(status);
881}
882
883} // extern "C"