blob: 2deb1a49bb172fb00226cba731f0cf87686cb47f [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>
21
Colin Cross7e8d4ba2017-05-04 16:17:42 -070022#include <media/NdkMediaDrm.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070023
Jeff Tinkera69729d2016-02-12 08:47:00 -080024#include <cutils/properties.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070025#include <utils/Log.h>
26#include <utils/StrongPointer.h>
27#include <gui/Surface.h>
28
29#include <media/IDrm.h>
30#include <media/IDrmClient.h>
31#include <media/stagefright/MediaErrors.h>
32#include <binder/IServiceManager.h>
Jeff Tinkera69729d2016-02-12 08:47:00 -080033#include <media/IMediaDrmService.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070034#include <media/NdkMediaCrypto.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070035
36
37using namespace android;
38
39typedef Vector<uint8_t> idvec_t;
40
Jeff Tinker3305b992014-05-14 18:39:25 -070041struct DrmListener: virtual public BnDrmClient
42{
43private:
44 AMediaDrm *mObj;
Edwin Wongad02cc62018-08-23 13:48:27 -070045 AMediaDrmEventListener mEventListener;
46 AMediaDrmExpirationUpdateListener mExpirationUpdateListener;
47 AMediaDrmKeysChangeListener mKeysChangeListener;
Jeff Tinker3305b992014-05-14 18:39:25 -070048
49public:
Edwin Wongad02cc62018-08-23 13:48:27 -070050 DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj),
51 mEventListener(listener), mExpirationUpdateListener(NULL), mKeysChangeListener(NULL) {}
52
53 DrmListener(AMediaDrm *obj, AMediaDrmExpirationUpdateListener listener) : mObj(obj),
54 mEventListener(NULL), mExpirationUpdateListener(listener), mKeysChangeListener(NULL) {}
55
56 DrmListener(AMediaDrm *obj, AMediaDrmKeysChangeListener listener) : mObj(obj),
57 mEventListener(NULL), mExpirationUpdateListener(NULL), mKeysChangeListener(listener) {}
58
59 void setEventListener(AMediaDrmEventListener listener) {
60 mEventListener = listener;
61 }
62
63 void setExpirationUpdateListener(AMediaDrmExpirationUpdateListener listener) {
64 mExpirationUpdateListener = listener;
65 }
66
67 void setKeysChangeListener(AMediaDrmKeysChangeListener listener) {
68 mKeysChangeListener = listener;
69 }
70
Jeff Tinker3305b992014-05-14 18:39:25 -070071 void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
72};
73
Jeff Tinker497ca092014-05-13 09:31:15 -070074struct AMediaDrm {
75 sp<IDrm> mDrm;
76 sp<IDrmClient> mDrmClient;
Jeff Tinker497ca092014-05-13 09:31:15 -070077 List<idvec_t> mIds;
78 KeyedVector<String8, String8> mQueryResults;
79 Vector<uint8_t> mKeyRequest;
80 Vector<uint8_t> mProvisionRequest;
81 String8 mProvisionUrl;
82 String8 mPropertyString;
83 Vector<uint8_t> mPropertyByteArray;
84 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -070085 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -070086};
87
Jeff Tinker3305b992014-05-14 18:39:25 -070088void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
Edwin Wongad02cc62018-08-23 13:48:27 -070089 if (!mEventListener && !mExpirationUpdateListener && !mKeysChangeListener) {
90 ALOGE("No listeners are specified");
Jeff Tinker3305b992014-05-14 18:39:25 -070091 return;
92 }
93
Edwin Wongad02cc62018-08-23 13:48:27 -070094 obj->setDataPosition(0);
95
Jeff Tinker3305b992014-05-14 18:39:25 -070096 AMediaDrmSessionId sessionId = {NULL, 0};
97 int32_t sessionIdSize = obj->readInt32();
Edwin Wongad02cc62018-08-23 13:48:27 -070098 if (sessionIdSize <= 0) {
99 ALOGE("Invalid session id size");
100 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700101 }
102
Edwin Wongad02cc62018-08-23 13:48:27 -0700103 std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
104 sessionId.ptr = sessionIdData.get();
105 sessionId.length = sessionIdSize;
106 status_t err = obj->read(sessionIdData.get(), sessionId.length);
107 if (err != OK) {
108 ALOGE("Failed to read session id, error=%d", err);
109 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700110 }
111
Edwin Wongad02cc62018-08-23 13:48:27 -0700112 if (DrmPlugin::kDrmPluginEventExpirationUpdate == eventType) {
113 int64_t expiryTimeInMS = obj->readInt64();
114 if (expiryTimeInMS >= 0) {
115 (*mExpirationUpdateListener)(mObj, &sessionId, expiryTimeInMS);
116 } else {
117 ALOGE("Failed to read expiry time, status=%" PRId64 "", expiryTimeInMS);
118 }
119 return;
120 } else if (DrmPlugin::kDrmPluginEventKeysChange == eventType) {
121 int32_t numKeys = 0;
122 err = obj->readInt32(&numKeys);
123 if (err != OK) {
124 ALOGE("Failed to read number of keys status, error=%d", err);
125 return;
126 }
127
128 Vector<AMediaDrmKeyStatus> keysStatus;
129 std::vector<std::unique_ptr<uint8_t[]> > dataPointers;
130 AMediaDrmKeyStatus keyStatus;
131
132 for (size_t i = 0; i < numKeys; ++i) {
133 keyStatus.keyId.ptr = nullptr;
134 keyStatus.keyId.length = 0;
135 int32_t idSize = obj->readInt32();
136 if (idSize > 0) {
137 std::unique_ptr<uint8_t[]> data(new uint8_t[idSize]);
138 err = obj->read(data.get(), idSize);
139 if (err != OK) {
140 ALOGE("Failed to read key data, error=%d", err);
141 return;
142 }
143 keyStatus.keyId.ptr = data.get();
144 keyStatus.keyId.length = idSize;
145 dataPointers.push_back(std::move(data));
146 }
147 keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(obj->readInt32());
148 keysStatus.push(keyStatus);
149 }
150
151 bool hasNewUsableKey = obj->readInt32();
152 (*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
153 return;
154 }
155
156 // Handles AMediaDrmEventListener below:
157 // translates DrmPlugin event types into their NDK equivalents
Jeff Tinker3305b992014-05-14 18:39:25 -0700158 AMediaDrmEventType ndkEventType;
159 switch(eventType) {
160 case DrmPlugin::kDrmPluginEventProvisionRequired:
161 ndkEventType = EVENT_PROVISION_REQUIRED;
162 break;
163 case DrmPlugin::kDrmPluginEventKeyNeeded:
164 ndkEventType = EVENT_KEY_REQUIRED;
165 break;
166 case DrmPlugin::kDrmPluginEventKeyExpired:
167 ndkEventType = EVENT_KEY_EXPIRED;
168 break;
169 case DrmPlugin::kDrmPluginEventVendorDefined:
170 ndkEventType = EVENT_VENDOR_DEFINED;
171 break;
Edwin Wongad02cc62018-08-23 13:48:27 -0700172 case DrmPlugin::kDrmPluginEventSessionReclaimed:
173 ndkEventType = EVENT_SESSION_RECLAIMED;
174 break;
Jeff Tinker3305b992014-05-14 18:39:25 -0700175 default:
176 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
Edwin Wongad02cc62018-08-23 13:48:27 -0700177 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700178 }
179
Edwin Wongad02cc62018-08-23 13:48:27 -0700180 int32_t dataSize = obj->readInt32();
181 uint8_t *data = NULL;
182 if (dataSize > 0) {
183 data = new uint8_t[dataSize];
184 err = obj->read(data, dataSize);
185 if (err == OK) {
186 (*mEventListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
187 } else {
188 ALOGE("Failed to read event data, error=%d", err);
189 }
190 delete [] data;
191 } else {
192 ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
193 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700194}
195
Jeff Tinker497ca092014-05-13 09:31:15 -0700196extern "C" {
197
Marco Nelissene419d7c2014-05-15 14:17:25 -0700198static media_status_t translateStatus(status_t status) {
199 media_status_t result = AMEDIA_ERROR_UNKNOWN;
Jeff Tinker497ca092014-05-13 09:31:15 -0700200 switch (status) {
201 case OK:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700202 result = AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700203 break;
204 case android::ERROR_DRM_NOT_PROVISIONED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700205 result = AMEDIA_DRM_NOT_PROVISIONED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700206 break;
207 case android::ERROR_DRM_RESOURCE_BUSY:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700208 result = AMEDIA_DRM_RESOURCE_BUSY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700209 break;
210 case android::ERROR_DRM_DEVICE_REVOKED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700211 result = AMEDIA_DRM_DEVICE_REVOKED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700212 break;
213 case android::ERROR_DRM_CANNOT_HANDLE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700214 result = AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700215 break;
216 case android::ERROR_DRM_TAMPER_DETECTED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700217 result = AMEDIA_DRM_TAMPER_DETECTED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700218 break;
219 case android::ERROR_DRM_SESSION_NOT_OPENED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700220 result = AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700221 break;
222 case android::ERROR_DRM_NO_LICENSE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700223 result = AMEDIA_DRM_NEED_KEY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700224 break;
225 case android::ERROR_DRM_LICENSE_EXPIRED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700226 result = AMEDIA_DRM_LICENSE_EXPIRED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700227 break;
228 default:
Jeff Tinker497ca092014-05-13 09:31:15 -0700229 break;
230 }
231 return result;
232}
233
234static sp<IDrm> CreateDrm() {
235 sp<IServiceManager> sm = defaultServiceManager();
Jeff Tinker30038072016-04-25 13:41:35 -0700236 sp<IBinder> binder = sm->getService(String16("media.drm"));
Jeff Tinker497ca092014-05-13 09:31:15 -0700237
Jeff Tinker30038072016-04-25 13:41:35 -0700238 sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
239 if (service == NULL) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700240 return NULL;
241 }
242
Jeff Tinker30038072016-04-25 13:41:35 -0700243 sp<IDrm> drm = service->makeDrm();
244 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
245 return NULL;
246 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700247 return drm;
248}
249
250
251static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
252 sp<IDrm> drm = CreateDrm();
253
254 if (drm == NULL) {
255 return NULL;
256 }
257
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800258 String8 nullPackageName;
259 status_t err = drm->createPlugin(uuid, nullPackageName);
Jeff Tinker497ca092014-05-13 09:31:15 -0700260
261 if (err != OK) {
262 return NULL;
263 }
264
265 return drm;
266}
267
Marco Nelissen3425fd52014-05-14 11:12:46 -0700268EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700269bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
270 sp<IDrm> drm = CreateDrm();
271
272 if (drm == NULL) {
273 return false;
274 }
275
276 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
Jeff Tinkerdb3fa5f2019-01-25 22:56:56 -0800277 bool isSupported = false;
278 status_t status = drm->isCryptoSchemeSupported(uuid, mimeStr,
279 DrmPlugin::kSecurityLevelUnknown, &isSupported);
280 return (status == OK) && isSupported;
Jeff Tinker497ca092014-05-13 09:31:15 -0700281}
282
Marco Nelissen3425fd52014-05-14 11:12:46 -0700283EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700284AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
285 AMediaDrm *mObj = new AMediaDrm();
286 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700287
288 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700289 return mObj;
290}
291
Marco Nelissen3425fd52014-05-14 11:12:46 -0700292EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700293void AMediaDrm_release(AMediaDrm *mObj) {
294 if (mObj->mDrm != NULL) {
295 mObj->mDrm->setListener(NULL);
296 mObj->mDrm->destroyPlugin();
297 mObj->mDrm.clear();
298 }
299 delete mObj;
300}
301
Jeff Tinker3305b992014-05-14 18:39:25 -0700302EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700303media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700304 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700305 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700306 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700307
308 if (mObj->mListener.get()) {
309 mObj->mListener->setEventListener(listener);
310 } else {
311 mObj->mListener = new DrmListener(mObj, listener);
312 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700313 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700314 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700315}
Jeff Tinker497ca092014-05-13 09:31:15 -0700316
Edwin Wongad02cc62018-08-23 13:48:27 -0700317EXPORT
318media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
319 AMediaDrmExpirationUpdateListener listener) {
320 if (!mObj || mObj->mDrm == NULL) {
321 return AMEDIA_ERROR_INVALID_OBJECT;
322 }
323
324 if (mObj->mListener.get()) {
325 mObj->mListener->setExpirationUpdateListener(listener);
326 } else {
327 mObj->mListener = new DrmListener(mObj, listener);
328 }
329 mObj->mDrm->setListener(mObj->mListener);
330 return AMEDIA_OK;
331}
332
333EXPORT
334media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
335 AMediaDrmKeysChangeListener listener) {
336 if (!mObj || mObj->mDrm == NULL) {
337 return AMEDIA_ERROR_INVALID_OBJECT;
338 }
339
340 if (mObj->mListener.get()) {
341 mObj->mListener->setKeysChangeListener(listener);
342 } else {
343 mObj->mListener = new DrmListener(mObj, listener);
344 }
345 mObj->mDrm->setListener(mObj->mListener);
346 return AMEDIA_OK;
347}
Jeff Tinker497ca092014-05-13 09:31:15 -0700348
349static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700350 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700351 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700352 return true;
353 }
354 }
355 return false;
356}
357
Marco Nelissen3425fd52014-05-14 11:12:46 -0700358EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700359media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700360 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700361 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700362 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700363 if (!sessionId) {
364 return AMEDIA_ERROR_INVALID_PARAMETER;
365 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700366 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000367 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Jeff Tinker497ca092014-05-13 09:31:15 -0700368 if (status == OK) {
369 mObj->mIds.push_front(session);
370 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700371 sessionId->ptr = iter->array();
372 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700373 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700374 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700375}
376
Marco Nelissen3425fd52014-05-14 11:12:46 -0700377EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700378media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700379 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700380 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700381 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700382 if (!sessionId) {
383 return AMEDIA_ERROR_INVALID_PARAMETER;
384 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700385
386 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700387 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700388 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700389 }
390 mObj->mDrm->closeSession(*iter);
391 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700392 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700393}
394
Marco Nelissen3425fd52014-05-14 11:12:46 -0700395EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700396media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700397 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
398 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700399 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700400
401 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 (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700405 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700406 }
407
408 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700409 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700410 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700411 }
412
413 Vector<uint8_t> mdInit;
414 mdInit.appendArray(init, initSize);
415 DrmPlugin::KeyType mdKeyType;
416 switch (keyType) {
417 case KEY_TYPE_STREAMING:
418 mdKeyType = DrmPlugin::kKeyType_Streaming;
419 break;
420 case KEY_TYPE_OFFLINE:
421 mdKeyType = DrmPlugin::kKeyType_Offline;
422 break;
423 case KEY_TYPE_RELEASE:
424 mdKeyType = DrmPlugin::kKeyType_Release;
425 break;
426 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700427 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700428 }
429 KeyedVector<String8, String8> mdOptionalParameters;
430 for (size_t i = 0; i < numOptionalParameters; i++) {
431 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
432 String8(optionalParameters[i].mValue));
433 }
434 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700435 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700436 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700437 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700438 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
439 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700440 if (status != OK) {
441 return translateStatus(status);
442 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700443 *keyRequest = mObj->mKeyRequest.array();
444 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700445 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700446 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700447}
448
Marco Nelissen3425fd52014-05-14 11:12:46 -0700449EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700450media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
451 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700452
453 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700454 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700455 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700456 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700457 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700458 }
459
460 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700461 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700462 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700463 }
464 Vector<uint8_t> mdResponse;
465 mdResponse.appendArray(response, responseSize);
466
467 Vector<uint8_t> mdKeySetId;
468 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
469 if (status == OK) {
470 mObj->mIds.push_front(mdKeySetId);
471 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700472 keySetId->ptr = iter->array();
473 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700474 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700475 keySetId->ptr = NULL;
476 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700477 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700478 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700479}
480
Marco Nelissen3425fd52014-05-14 11:12:46 -0700481EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700482media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
483 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700484
485 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700486 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700487 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700488 if (!sessionId || !keySetId) {
489 return AMEDIA_ERROR_INVALID_PARAMETER;
490 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700491 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700492 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700493 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700494 }
495 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700496 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700497 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
498}
499
Marco Nelissen3425fd52014-05-14 11:12:46 -0700500EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700501media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700502 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700503 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700504 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700505 if (!keySetId) {
506 return AMEDIA_ERROR_INVALID_PARAMETER;
507 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700508 List<idvec_t>::iterator iter;
509 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700510 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700511 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700512 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700513 status = mObj->mDrm->removeKeys(keySet);
514 } else {
515 status = mObj->mDrm->removeKeys(*iter);
516 mObj->mIds.erase(iter);
517 }
518 return translateStatus(status);
519}
520
Marco Nelissen3425fd52014-05-14 11:12:46 -0700521EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700522media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
523 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700524
525 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700526 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700527 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700528 if (!sessionId || !numPairs) {
529 return AMEDIA_ERROR_INVALID_PARAMETER;
530 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700531 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700532 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700533 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700534 }
535
536 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
537 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700538 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700539 return translateStatus(status);
540 }
541
Marco Nelissen18a1b592014-05-20 08:45:18 -0700542 if (mObj->mQueryResults.size() > *numPairs) {
543 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700544 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700545 }
546
547 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
548 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700549 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700550 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700551 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700552 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700553}
554
Marco Nelissen3425fd52014-05-14 11:12:46 -0700555EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700556media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
557 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700558 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 (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700562 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700563 }
564
565 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
566 mObj->mProvisionRequest, mObj->mProvisionUrl);
567 if (status != OK) {
568 return translateStatus(status);
569 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700570 *provisionRequest = mObj->mProvisionRequest.array();
571 *provisionRequestSize = mObj->mProvisionRequest.size();
572 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700573 }
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 Nelissene419d7c2014-05-15 14:17:25 -0700578media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700579 const uint8_t *response, size_t responseSize) {
580 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 }
583 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700584 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700585 }
586
587 Vector<uint8_t> mdResponse;
588 mdResponse.appendArray(response, responseSize);
589
590 Vector<uint8_t> unused;
591 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
592}
593
Marco Nelissen3425fd52014-05-14 11:12:46 -0700594EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700595media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700596 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700597
598 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700599 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700600 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700601 if (!numSecureStops) {
602 return AMEDIA_ERROR_INVALID_PARAMETER;
603 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700604 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
605 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700606 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700607 return translateStatus(status);
608 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700609 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700610 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700611 }
612 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
613 size_t i = 0;
614 while (iter != mObj->mSecureStops.end()) {
615 secureStops[i].ptr = iter->array();
616 secureStops[i].length = iter->size();
617 ++iter;
618 ++i;
619 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700620 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700621 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700622}
623
Marco Nelissen3425fd52014-05-14 11:12:46 -0700624EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700625media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700626 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700627
628 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700629 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700630 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700631 if (!ssRelease) {
632 return AMEDIA_ERROR_INVALID_PARAMETER;
633 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700634
635 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700636 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700637 return translateStatus(mObj->mDrm->releaseSecureStops(release));
638}
639
640
Marco Nelissen3425fd52014-05-14 11:12:46 -0700641EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700642media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700643 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700644
645 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700646 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700647 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700648 if (!propertyName || !propertyValue) {
649 return AMEDIA_ERROR_INVALID_PARAMETER;
650 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700651
652 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
653 mObj->mPropertyString);
654
655 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700656 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700657 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700658 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700659 }
660 return translateStatus(status);
661}
662
Marco Nelissen3425fd52014-05-14 11:12:46 -0700663EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700664media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700665 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700666 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700667 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700668 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700669 if (!propertyName || !propertyValue) {
670 return AMEDIA_ERROR_INVALID_PARAMETER;
671 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700672
673 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
674 mObj->mPropertyByteArray);
675
676 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700677 propertyValue->ptr = mObj->mPropertyByteArray.array();
678 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700679 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700680 propertyValue->ptr = NULL;
681 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700682 }
683 return translateStatus(status);
684}
685
Marco Nelissen3425fd52014-05-14 11:12:46 -0700686EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700687media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700688 const char *propertyName, const char *value) {
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 }
692
693 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
694 String8(value)));
695}
696
Marco Nelissen3425fd52014-05-14 11:12:46 -0700697EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700698media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700699 const char *propertyName, const uint8_t *value, size_t valueSize) {
700
701 Vector<uint8_t> byteArray;
702 byteArray.appendArray(value, valueSize);
703
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700704 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700705 byteArray));
706}
707
708
Marco Nelissene419d7c2014-05-15 14:17:25 -0700709static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700710 const AMediaDrmSessionId &sessionId,
711 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
712 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
713
714 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700715 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700716 }
717 List<idvec_t>::iterator iter;
718 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700719 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700720 }
721
722 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
723 if (status != OK) {
724 return translateStatus(status);
725 }
726
727 Vector<uint8_t> keyIdVec;
728 const size_t kKeyIdSize = 16;
729 keyIdVec.appendArray(keyId, kKeyIdSize);
730
731 Vector<uint8_t> inputVec;
732 inputVec.appendArray(input, dataSize);
733
734 Vector<uint8_t> ivVec;
735 const size_t kIvSize = 16;
736 ivVec.appendArray(iv, kIvSize);
737
738 Vector<uint8_t> outputVec;
739 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800740 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700741 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800742 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700743 }
744 if (status == OK) {
745 memcpy(output, outputVec.array(), outputVec.size());
746 }
747 return translateStatus(status);
748}
749
Marco Nelissen3425fd52014-05-14 11:12:46 -0700750EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700751media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700752 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
753 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700754 if (!sessionId) {
755 return AMEDIA_ERROR_INVALID_PARAMETER;
756 }
757 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700758 input, output, dataSize, true);
759}
760
Marco Nelissen3425fd52014-05-14 11:12:46 -0700761EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700762media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700763 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
764 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700765 if (!sessionId) {
766 return AMEDIA_ERROR_INVALID_PARAMETER;
767 }
768 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700769 input, output, dataSize, false);
770}
771
Marco Nelissen3425fd52014-05-14 11:12:46 -0700772EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700773media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700774 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
775 uint8_t *signature, size_t *signatureSize) {
776
777 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700778 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700779 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700780 if (!sessionId) {
781 return AMEDIA_ERROR_INVALID_PARAMETER;
782 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700783 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700784 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700785 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700786 }
787
788 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
789 if (status != OK) {
790 return translateStatus(status);
791 }
792
793 Vector<uint8_t> keyIdVec;
794 const size_t kKeyIdSize = 16;
795 keyIdVec.appendArray(keyId, kKeyIdSize);
796
797 Vector<uint8_t> messageVec;
798 messageVec.appendArray(message, messageSize);
799
800 Vector<uint8_t> signatureVec;
801 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
802 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700803 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700804 }
805 if (status == OK) {
806 memcpy(signature, signatureVec.array(), signatureVec.size());
807 }
808 return translateStatus(status);
809}
810
Marco Nelissen3425fd52014-05-14 11:12:46 -0700811EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700812media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700813 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
814 const uint8_t *signature, size_t signatureSize) {
815
816 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700817 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700818 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700819 if (!sessionId) {
820 return AMEDIA_ERROR_INVALID_PARAMETER;
821 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700822 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700823 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700824 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700825 }
826
827 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
828 if (status != OK) {
829 return translateStatus(status);
830 }
831
832 Vector<uint8_t> keyIdVec;
833 const size_t kKeyIdSize = 16;
834 keyIdVec.appendArray(keyId, kKeyIdSize);
835
836 Vector<uint8_t> messageVec;
837 messageVec.appendArray(message, messageSize);
838
839 Vector<uint8_t> signatureVec;
840 signatureVec.appendArray(signature, signatureSize);
841
842 bool match;
843 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
844 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700845 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700846 }
847 return translateStatus(status);
848}
849
850} // extern "C"