blob: b6ea183ace60ef4fe6c0c95a85977ee3034651f1 [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 Wong439774e2018-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 Wong439774e2018-08-23 13:48:27 -070045 AMediaDrmEventListener mEventListener;
46 AMediaDrmExpirationUpdateListener mExpirationUpdateListener;
47 AMediaDrmKeysChangeListener mKeysChangeListener;
Jeff Tinker3305b992014-05-14 18:39:25 -070048
49public:
Edwin Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-08-23 13:48:27 -0700177 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700178 }
179
Edwin Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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 Wong439774e2018-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;
Jeff Tinker497ca092014-05-13 09:31:15 -0700433 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700434 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
435 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700436 if (status != OK) {
437 return translateStatus(status);
438 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700439 *keyRequest = mObj->mKeyRequest.array();
440 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700441 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700442 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700443}
444
Marco Nelissen3425fd52014-05-14 11:12:46 -0700445EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700446media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
447 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700448
449 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700450 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700451 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700452 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700453 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700454 }
455
456 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700457 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700458 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700459 }
460 Vector<uint8_t> mdResponse;
461 mdResponse.appendArray(response, responseSize);
462
463 Vector<uint8_t> mdKeySetId;
464 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
465 if (status == OK) {
466 mObj->mIds.push_front(mdKeySetId);
467 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700468 keySetId->ptr = iter->array();
469 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700470 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700471 keySetId->ptr = NULL;
472 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700473 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700474 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700475}
476
Marco Nelissen3425fd52014-05-14 11:12:46 -0700477EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700478media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
479 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700480
481 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700482 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700483 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700484 if (!sessionId || !keySetId) {
485 return AMEDIA_ERROR_INVALID_PARAMETER;
486 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700487 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700488 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700489 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700490 }
491 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700492 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700493 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
494}
495
Marco Nelissen3425fd52014-05-14 11:12:46 -0700496EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700497media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700498 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700499 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700500 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700501 if (!keySetId) {
502 return AMEDIA_ERROR_INVALID_PARAMETER;
503 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700504 List<idvec_t>::iterator iter;
505 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700506 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700507 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700508 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700509 status = mObj->mDrm->removeKeys(keySet);
510 } else {
511 status = mObj->mDrm->removeKeys(*iter);
512 mObj->mIds.erase(iter);
513 }
514 return translateStatus(status);
515}
516
Marco Nelissen3425fd52014-05-14 11:12:46 -0700517EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700518media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
519 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700520
521 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700522 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700523 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700524 if (!sessionId || !numPairs) {
525 return AMEDIA_ERROR_INVALID_PARAMETER;
526 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700527 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700528 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700529 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700530 }
531
532 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
533 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700534 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700535 return translateStatus(status);
536 }
537
Marco Nelissen18a1b592014-05-20 08:45:18 -0700538 if (mObj->mQueryResults.size() > *numPairs) {
539 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700540 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700541 }
542
543 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
544 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700545 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700546 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700547 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700548 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700549}
550
Marco Nelissen3425fd52014-05-14 11:12:46 -0700551EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700552media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
553 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700554 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700555 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700556 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700557 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700558 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700559 }
560
561 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
562 mObj->mProvisionRequest, mObj->mProvisionUrl);
563 if (status != OK) {
564 return translateStatus(status);
565 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700566 *provisionRequest = mObj->mProvisionRequest.array();
567 *provisionRequestSize = mObj->mProvisionRequest.size();
568 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700569 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700570 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700571}
572
Marco Nelissen3425fd52014-05-14 11:12:46 -0700573EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700574media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700575 const uint8_t *response, size_t responseSize) {
576 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700577 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700578 }
579 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700580 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700581 }
582
583 Vector<uint8_t> mdResponse;
584 mdResponse.appendArray(response, responseSize);
585
586 Vector<uint8_t> unused;
587 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
588}
589
Marco Nelissen3425fd52014-05-14 11:12:46 -0700590EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700591media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700592 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700593
594 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700595 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700596 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700597 if (!numSecureStops) {
598 return AMEDIA_ERROR_INVALID_PARAMETER;
599 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700600 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
601 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700602 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700603 return translateStatus(status);
604 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700605 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700606 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700607 }
608 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
609 size_t i = 0;
610 while (iter != mObj->mSecureStops.end()) {
611 secureStops[i].ptr = iter->array();
612 secureStops[i].length = iter->size();
613 ++iter;
614 ++i;
615 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700616 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700617 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700618}
619
Marco Nelissen3425fd52014-05-14 11:12:46 -0700620EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700621media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700622 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700623
624 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700625 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700626 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700627 if (!ssRelease) {
628 return AMEDIA_ERROR_INVALID_PARAMETER;
629 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700630
631 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700632 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700633 return translateStatus(mObj->mDrm->releaseSecureStops(release));
634}
635
636
Marco Nelissen3425fd52014-05-14 11:12:46 -0700637EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700638media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700639 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700640
641 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700642 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700643 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700644 if (!propertyName || !propertyValue) {
645 return AMEDIA_ERROR_INVALID_PARAMETER;
646 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700647
648 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
649 mObj->mPropertyString);
650
651 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700652 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700653 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700654 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700655 }
656 return translateStatus(status);
657}
658
Marco Nelissen3425fd52014-05-14 11:12:46 -0700659EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700660media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700661 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700662 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700663 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700664 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700665 if (!propertyName || !propertyValue) {
666 return AMEDIA_ERROR_INVALID_PARAMETER;
667 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700668
669 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
670 mObj->mPropertyByteArray);
671
672 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700673 propertyValue->ptr = mObj->mPropertyByteArray.array();
674 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700675 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700676 propertyValue->ptr = NULL;
677 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700678 }
679 return translateStatus(status);
680}
681
Marco Nelissen3425fd52014-05-14 11:12:46 -0700682EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700683media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700684 const char *propertyName, const char *value) {
685 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700686 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700687 }
688
689 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
690 String8(value)));
691}
692
Marco Nelissen3425fd52014-05-14 11:12:46 -0700693EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700694media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700695 const char *propertyName, const uint8_t *value, size_t valueSize) {
696
697 Vector<uint8_t> byteArray;
698 byteArray.appendArray(value, valueSize);
699
700 return translateStatus(mObj->mDrm->getPropertyByteArray(String8(propertyName),
701 byteArray));
702}
703
704
Marco Nelissene419d7c2014-05-15 14:17:25 -0700705static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700706 const AMediaDrmSessionId &sessionId,
707 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
708 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
709
710 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700711 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700712 }
713 List<idvec_t>::iterator iter;
714 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700715 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700716 }
717
718 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
719 if (status != OK) {
720 return translateStatus(status);
721 }
722
723 Vector<uint8_t> keyIdVec;
724 const size_t kKeyIdSize = 16;
725 keyIdVec.appendArray(keyId, kKeyIdSize);
726
727 Vector<uint8_t> inputVec;
728 inputVec.appendArray(input, dataSize);
729
730 Vector<uint8_t> ivVec;
731 const size_t kIvSize = 16;
732 ivVec.appendArray(iv, kIvSize);
733
734 Vector<uint8_t> outputVec;
735 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800736 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700737 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800738 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700739 }
740 if (status == OK) {
741 memcpy(output, outputVec.array(), outputVec.size());
742 }
743 return translateStatus(status);
744}
745
Marco Nelissen3425fd52014-05-14 11:12:46 -0700746EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700747media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700748 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
749 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700750 if (!sessionId) {
751 return AMEDIA_ERROR_INVALID_PARAMETER;
752 }
753 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700754 input, output, dataSize, true);
755}
756
Marco Nelissen3425fd52014-05-14 11:12:46 -0700757EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700758media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700759 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
760 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700761 if (!sessionId) {
762 return AMEDIA_ERROR_INVALID_PARAMETER;
763 }
764 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700765 input, output, dataSize, false);
766}
767
Marco Nelissen3425fd52014-05-14 11:12:46 -0700768EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700769media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700770 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
771 uint8_t *signature, size_t *signatureSize) {
772
773 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700774 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700775 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700776 if (!sessionId) {
777 return AMEDIA_ERROR_INVALID_PARAMETER;
778 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700779 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700780 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700781 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700782 }
783
784 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
785 if (status != OK) {
786 return translateStatus(status);
787 }
788
789 Vector<uint8_t> keyIdVec;
790 const size_t kKeyIdSize = 16;
791 keyIdVec.appendArray(keyId, kKeyIdSize);
792
793 Vector<uint8_t> messageVec;
794 messageVec.appendArray(message, messageSize);
795
796 Vector<uint8_t> signatureVec;
797 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
798 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700799 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700800 }
801 if (status == OK) {
802 memcpy(signature, signatureVec.array(), signatureVec.size());
803 }
804 return translateStatus(status);
805}
806
Marco Nelissen3425fd52014-05-14 11:12:46 -0700807EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700808media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700809 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
810 const uint8_t *signature, size_t signatureSize) {
811
812 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700813 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700814 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700815 if (!sessionId) {
816 return AMEDIA_ERROR_INVALID_PARAMETER;
817 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700818 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700819 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700820 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700821 }
822
823 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
824 if (status != OK) {
825 return translateStatus(status);
826 }
827
828 Vector<uint8_t> keyIdVec;
829 const size_t kKeyIdSize = 16;
830 keyIdVec.appendArray(keyId, kKeyIdSize);
831
832 Vector<uint8_t> messageVec;
833 messageVec.appendArray(message, messageSize);
834
835 Vector<uint8_t> signatureVec;
836 signatureVec.appendArray(signature, signatureSize);
837
838 bool match;
839 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
840 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700841 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700842 }
843 return translateStatus(status);
844}
845
846} // extern "C"