blob: 25520733244af920c79c14a2507ec671096c9639 [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("");
277 return drm->isCryptoSchemeSupported(uuid, mimeStr);
278}
279
Marco Nelissen3425fd52014-05-14 11:12:46 -0700280EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700281AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
282 AMediaDrm *mObj = new AMediaDrm();
283 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700284
285 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700286 return mObj;
287}
288
Marco Nelissen3425fd52014-05-14 11:12:46 -0700289EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700290void AMediaDrm_release(AMediaDrm *mObj) {
291 if (mObj->mDrm != NULL) {
292 mObj->mDrm->setListener(NULL);
293 mObj->mDrm->destroyPlugin();
294 mObj->mDrm.clear();
295 }
296 delete mObj;
297}
298
Jeff Tinker3305b992014-05-14 18:39:25 -0700299EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700300media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700301 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700302 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700303 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700304
305 if (mObj->mListener.get()) {
306 mObj->mListener->setEventListener(listener);
307 } else {
308 mObj->mListener = new DrmListener(mObj, listener);
309 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700310 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700311 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700312}
Jeff Tinker497ca092014-05-13 09:31:15 -0700313
Edwin Wongad02cc62018-08-23 13:48:27 -0700314EXPORT
315media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
316 AMediaDrmExpirationUpdateListener listener) {
317 if (!mObj || mObj->mDrm == NULL) {
318 return AMEDIA_ERROR_INVALID_OBJECT;
319 }
320
321 if (mObj->mListener.get()) {
322 mObj->mListener->setExpirationUpdateListener(listener);
323 } else {
324 mObj->mListener = new DrmListener(mObj, listener);
325 }
326 mObj->mDrm->setListener(mObj->mListener);
327 return AMEDIA_OK;
328}
329
330EXPORT
331media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
332 AMediaDrmKeysChangeListener listener) {
333 if (!mObj || mObj->mDrm == NULL) {
334 return AMEDIA_ERROR_INVALID_OBJECT;
335 }
336
337 if (mObj->mListener.get()) {
338 mObj->mListener->setKeysChangeListener(listener);
339 } else {
340 mObj->mListener = new DrmListener(mObj, listener);
341 }
342 mObj->mDrm->setListener(mObj->mListener);
343 return AMEDIA_OK;
344}
Jeff Tinker497ca092014-05-13 09:31:15 -0700345
346static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700347 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700348 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700349 return true;
350 }
351 }
352 return false;
353}
354
Marco Nelissen3425fd52014-05-14 11:12:46 -0700355EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700356media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700357 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700358 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700359 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700360 if (!sessionId) {
361 return AMEDIA_ERROR_INVALID_PARAMETER;
362 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700363 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000364 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Jeff Tinker497ca092014-05-13 09:31:15 -0700365 if (status == OK) {
366 mObj->mIds.push_front(session);
367 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700368 sessionId->ptr = iter->array();
369 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700370 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700371 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700372}
373
Marco Nelissen3425fd52014-05-14 11:12:46 -0700374EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700375media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700376 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700377 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700378 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700379 if (!sessionId) {
380 return AMEDIA_ERROR_INVALID_PARAMETER;
381 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700382
383 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700384 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700385 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700386 }
387 mObj->mDrm->closeSession(*iter);
388 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700389 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700390}
391
Marco Nelissen3425fd52014-05-14 11:12:46 -0700392EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700393media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700394 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
395 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700396 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700397
398 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700399 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700400 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700401 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700402 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700403 }
404
405 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700406 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700407 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700408 }
409
410 Vector<uint8_t> mdInit;
411 mdInit.appendArray(init, initSize);
412 DrmPlugin::KeyType mdKeyType;
413 switch (keyType) {
414 case KEY_TYPE_STREAMING:
415 mdKeyType = DrmPlugin::kKeyType_Streaming;
416 break;
417 case KEY_TYPE_OFFLINE:
418 mdKeyType = DrmPlugin::kKeyType_Offline;
419 break;
420 case KEY_TYPE_RELEASE:
421 mdKeyType = DrmPlugin::kKeyType_Release;
422 break;
423 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700424 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700425 }
426 KeyedVector<String8, String8> mdOptionalParameters;
427 for (size_t i = 0; i < numOptionalParameters; i++) {
428 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
429 String8(optionalParameters[i].mValue));
430 }
431 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700432 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700433 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700434 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700435 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
436 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700437 if (status != OK) {
438 return translateStatus(status);
439 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700440 *keyRequest = mObj->mKeyRequest.array();
441 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700442 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700443 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700444}
445
Marco Nelissen3425fd52014-05-14 11:12:46 -0700446EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700447media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
448 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700449
450 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700451 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700452 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700453 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700454 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700455 }
456
457 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700458 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700459 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700460 }
461 Vector<uint8_t> mdResponse;
462 mdResponse.appendArray(response, responseSize);
463
464 Vector<uint8_t> mdKeySetId;
465 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
466 if (status == OK) {
467 mObj->mIds.push_front(mdKeySetId);
468 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700469 keySetId->ptr = iter->array();
470 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700471 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700472 keySetId->ptr = NULL;
473 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700474 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700475 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700476}
477
Marco Nelissen3425fd52014-05-14 11:12:46 -0700478EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700479media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
480 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700481
482 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700483 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700484 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700485 if (!sessionId || !keySetId) {
486 return AMEDIA_ERROR_INVALID_PARAMETER;
487 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700488 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700489 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700490 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700491 }
492 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700493 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700494 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
495}
496
Marco Nelissen3425fd52014-05-14 11:12:46 -0700497EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700498media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700499 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700500 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700501 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700502 if (!keySetId) {
503 return AMEDIA_ERROR_INVALID_PARAMETER;
504 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700505 List<idvec_t>::iterator iter;
506 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700507 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700508 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700509 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700510 status = mObj->mDrm->removeKeys(keySet);
511 } else {
512 status = mObj->mDrm->removeKeys(*iter);
513 mObj->mIds.erase(iter);
514 }
515 return translateStatus(status);
516}
517
Marco Nelissen3425fd52014-05-14 11:12:46 -0700518EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700519media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
520 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700521
522 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700523 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700524 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700525 if (!sessionId || !numPairs) {
526 return AMEDIA_ERROR_INVALID_PARAMETER;
527 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700528 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700529 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700530 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700531 }
532
533 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
534 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700535 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700536 return translateStatus(status);
537 }
538
Marco Nelissen18a1b592014-05-20 08:45:18 -0700539 if (mObj->mQueryResults.size() > *numPairs) {
540 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700541 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700542 }
543
544 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
545 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700546 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700547 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700548 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700549 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700550}
551
Marco Nelissen3425fd52014-05-14 11:12:46 -0700552EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700553media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
554 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700555 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700556 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700557 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700558 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700559 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700560 }
561
562 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
563 mObj->mProvisionRequest, mObj->mProvisionUrl);
564 if (status != OK) {
565 return translateStatus(status);
566 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700567 *provisionRequest = mObj->mProvisionRequest.array();
568 *provisionRequestSize = mObj->mProvisionRequest.size();
569 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700570 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700571 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700572}
573
Marco Nelissen3425fd52014-05-14 11:12:46 -0700574EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700575media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700576 const uint8_t *response, size_t responseSize) {
577 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700578 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700579 }
580 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700581 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700582 }
583
584 Vector<uint8_t> mdResponse;
585 mdResponse.appendArray(response, responseSize);
586
587 Vector<uint8_t> unused;
588 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
589}
590
Marco Nelissen3425fd52014-05-14 11:12:46 -0700591EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700592media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700593 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700594
595 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700596 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700597 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700598 if (!numSecureStops) {
599 return AMEDIA_ERROR_INVALID_PARAMETER;
600 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700601 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
602 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700603 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700604 return translateStatus(status);
605 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700606 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700607 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700608 }
609 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
610 size_t i = 0;
611 while (iter != mObj->mSecureStops.end()) {
612 secureStops[i].ptr = iter->array();
613 secureStops[i].length = iter->size();
614 ++iter;
615 ++i;
616 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700617 *numSecureStops = mObj->mSecureStops.size();
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_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700623 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700624
625 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700626 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700627 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700628 if (!ssRelease) {
629 return AMEDIA_ERROR_INVALID_PARAMETER;
630 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700631
632 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700633 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700634 return translateStatus(mObj->mDrm->releaseSecureStops(release));
635}
636
637
Marco Nelissen3425fd52014-05-14 11:12:46 -0700638EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700639media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700640 const char **propertyValue) {
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 (!propertyName || !propertyValue) {
646 return AMEDIA_ERROR_INVALID_PARAMETER;
647 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700648
649 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
650 mObj->mPropertyString);
651
652 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700653 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700654 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700655 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700656 }
657 return translateStatus(status);
658}
659
Marco Nelissen3425fd52014-05-14 11:12:46 -0700660EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700661media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700662 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700663 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700664 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700665 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700666 if (!propertyName || !propertyValue) {
667 return AMEDIA_ERROR_INVALID_PARAMETER;
668 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700669
670 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
671 mObj->mPropertyByteArray);
672
673 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700674 propertyValue->ptr = mObj->mPropertyByteArray.array();
675 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700676 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700677 propertyValue->ptr = NULL;
678 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700679 }
680 return translateStatus(status);
681}
682
Marco Nelissen3425fd52014-05-14 11:12:46 -0700683EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700684media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700685 const char *propertyName, const char *value) {
686 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700687 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700688 }
689
690 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
691 String8(value)));
692}
693
Marco Nelissen3425fd52014-05-14 11:12:46 -0700694EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700695media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700696 const char *propertyName, const uint8_t *value, size_t valueSize) {
697
698 Vector<uint8_t> byteArray;
699 byteArray.appendArray(value, valueSize);
700
701 return translateStatus(mObj->mDrm->getPropertyByteArray(String8(propertyName),
702 byteArray));
703}
704
705
Marco Nelissene419d7c2014-05-15 14:17:25 -0700706static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700707 const AMediaDrmSessionId &sessionId,
708 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
709 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
710
711 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700712 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700713 }
714 List<idvec_t>::iterator iter;
715 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700716 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700717 }
718
719 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
720 if (status != OK) {
721 return translateStatus(status);
722 }
723
724 Vector<uint8_t> keyIdVec;
725 const size_t kKeyIdSize = 16;
726 keyIdVec.appendArray(keyId, kKeyIdSize);
727
728 Vector<uint8_t> inputVec;
729 inputVec.appendArray(input, dataSize);
730
731 Vector<uint8_t> ivVec;
732 const size_t kIvSize = 16;
733 ivVec.appendArray(iv, kIvSize);
734
735 Vector<uint8_t> outputVec;
736 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800737 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700738 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800739 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700740 }
741 if (status == OK) {
742 memcpy(output, outputVec.array(), outputVec.size());
743 }
744 return translateStatus(status);
745}
746
Marco Nelissen3425fd52014-05-14 11:12:46 -0700747EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700748media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700749 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
750 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700751 if (!sessionId) {
752 return AMEDIA_ERROR_INVALID_PARAMETER;
753 }
754 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700755 input, output, dataSize, true);
756}
757
Marco Nelissen3425fd52014-05-14 11:12:46 -0700758EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700759media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700760 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
761 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700762 if (!sessionId) {
763 return AMEDIA_ERROR_INVALID_PARAMETER;
764 }
765 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700766 input, output, dataSize, false);
767}
768
Marco Nelissen3425fd52014-05-14 11:12:46 -0700769EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700770media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700771 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
772 uint8_t *signature, size_t *signatureSize) {
773
774 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700775 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700776 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700777 if (!sessionId) {
778 return AMEDIA_ERROR_INVALID_PARAMETER;
779 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700780 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700781 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700782 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700783 }
784
785 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
786 if (status != OK) {
787 return translateStatus(status);
788 }
789
790 Vector<uint8_t> keyIdVec;
791 const size_t kKeyIdSize = 16;
792 keyIdVec.appendArray(keyId, kKeyIdSize);
793
794 Vector<uint8_t> messageVec;
795 messageVec.appendArray(message, messageSize);
796
797 Vector<uint8_t> signatureVec;
798 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
799 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700800 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700801 }
802 if (status == OK) {
803 memcpy(signature, signatureVec.array(), signatureVec.size());
804 }
805 return translateStatus(status);
806}
807
Marco Nelissen3425fd52014-05-14 11:12:46 -0700808EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700809media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700810 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
811 const uint8_t *signature, size_t signatureSize) {
812
813 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700814 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700815 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700816 if (!sessionId) {
817 return AMEDIA_ERROR_INVALID_PARAMETER;
818 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700819 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700820 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700821 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700822 }
823
824 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
825 if (status != OK) {
826 return translateStatus(status);
827 }
828
829 Vector<uint8_t> keyIdVec;
830 const size_t kKeyIdSize = 16;
831 keyIdVec.appendArray(keyId, kKeyIdSize);
832
833 Vector<uint8_t> messageVec;
834 messageVec.appendArray(message, messageSize);
835
836 Vector<uint8_t> signatureVec;
837 signatureVec.appendArray(signature, signatureSize);
838
839 bool match;
840 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
841 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700842 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700843 }
844 return translateStatus(status);
845}
846
847} // extern "C"