blob: 4967f42737ead65102f79a2166db165a9c879a1b [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
17#define LOG_NDEBUG 0
18#define LOG_TAG "NdkMediaDrm"
19
20#include "NdkMediaDrm.h"
21
22#include <utils/Log.h>
23#include <utils/StrongPointer.h>
24#include <gui/Surface.h>
25
26#include <media/IDrm.h>
27#include <media/IDrmClient.h>
28#include <media/stagefright/MediaErrors.h>
29#include <binder/IServiceManager.h>
30#include <media/IMediaPlayerService.h>
31#include <ndk/NdkMediaCrypto.h>
32
33
34using namespace android;
35
36typedef Vector<uint8_t> idvec_t;
37
Jeff Tinker3305b992014-05-14 18:39:25 -070038struct DrmListener: virtual public BnDrmClient
39{
40private:
41 AMediaDrm *mObj;
42 AMediaDrmEventListener mListener;
43
44public:
45 DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj), mListener(listener) {}
46 void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
47};
48
Jeff Tinker497ca092014-05-13 09:31:15 -070049struct AMediaDrm {
50 sp<IDrm> mDrm;
51 sp<IDrmClient> mDrmClient;
Jeff Tinker497ca092014-05-13 09:31:15 -070052 List<idvec_t> mIds;
53 KeyedVector<String8, String8> mQueryResults;
54 Vector<uint8_t> mKeyRequest;
55 Vector<uint8_t> mProvisionRequest;
56 String8 mProvisionUrl;
57 String8 mPropertyString;
58 Vector<uint8_t> mPropertyByteArray;
59 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -070060 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -070061};
62
Jeff Tinker3305b992014-05-14 18:39:25 -070063void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
64 if (!mListener) {
65 return;
66 }
67
68 AMediaDrmSessionId sessionId = {NULL, 0};
69 int32_t sessionIdSize = obj->readInt32();
70 if (sessionIdSize) {
71 uint8_t *sessionIdData = new uint8_t[sessionIdSize];
72 sessionId.ptr = sessionIdData;
73 sessionId.length = sessionIdSize;
74 obj->read(sessionIdData, sessionId.length);
75 }
76
77 int32_t dataSize = obj->readInt32();
78 uint8_t *data = NULL;
79 if (dataSize) {
80 data = new uint8_t[dataSize];
81 obj->read(data, dataSize);
82 }
83
84 // translate DrmPlugin event types into their NDK equivalents
85 AMediaDrmEventType ndkEventType;
86 switch(eventType) {
87 case DrmPlugin::kDrmPluginEventProvisionRequired:
88 ndkEventType = EVENT_PROVISION_REQUIRED;
89 break;
90 case DrmPlugin::kDrmPluginEventKeyNeeded:
91 ndkEventType = EVENT_KEY_REQUIRED;
92 break;
93 case DrmPlugin::kDrmPluginEventKeyExpired:
94 ndkEventType = EVENT_KEY_EXPIRED;
95 break;
96 case DrmPlugin::kDrmPluginEventVendorDefined:
97 ndkEventType = EVENT_VENDOR_DEFINED;
98 break;
99 default:
100 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
101 return;
102 }
103
104 (*mListener)(mObj, sessionId, ndkEventType, extra, data, dataSize);
105
106 delete [] sessionId.ptr;
107 delete [] data;
108}
109
110
Jeff Tinker497ca092014-05-13 09:31:15 -0700111extern "C" {
112
113static mediadrm_status_t translateStatus(status_t status) {
114 mediadrm_status_t result = MEDIADRM_UNKNOWN_ERROR;
115 switch (status) {
116 case OK:
117 result = MEDIADRM_OK;
118 break;
119 case android::ERROR_DRM_NOT_PROVISIONED:
120 result = MEDIADRM_NOT_PROVISIONED_ERROR;
121 break;
122 case android::ERROR_DRM_RESOURCE_BUSY:
123 result = MEDIADRM_RESOURCE_BUSY_ERROR;
124 break;
125 case android::ERROR_DRM_DEVICE_REVOKED:
126 result = MEDIADRM_DEVICE_REVOKED_ERROR;
127 break;
128 case android::ERROR_DRM_CANNOT_HANDLE:
129 result = MEDIADRM_INVALID_PARAMETER_ERROR;
130 break;
131 case android::ERROR_DRM_TAMPER_DETECTED:
132 result = MEDIADRM_TAMPER_DETECTED_ERROR;
133 break;
134 case android::ERROR_DRM_SESSION_NOT_OPENED:
135 result = MEDIADRM_SESSION_NOT_OPENED_ERROR;
136 break;
137 case android::ERROR_DRM_NO_LICENSE:
138 result = MEDIADRM_NEED_KEY_ERROR;
139 break;
140 case android::ERROR_DRM_LICENSE_EXPIRED:
141 result = MEDIADRM_LICENSE_EXPIRED_ERROR;
142 break;
143 default:
144 result = MEDIADRM_UNKNOWN_ERROR;
145 break;
146 }
147 return result;
148}
149
150static sp<IDrm> CreateDrm() {
151 sp<IServiceManager> sm = defaultServiceManager();
152
153 sp<IBinder> binder =
154 sm->getService(String16("media.player"));
155
156 sp<IMediaPlayerService> service =
157 interface_cast<IMediaPlayerService>(binder);
158
159 if (service == NULL) {
160 return NULL;
161 }
162
163 sp<IDrm> drm = service->makeDrm();
164
165 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
166 return NULL;
167 }
168
169 return drm;
170}
171
172
173static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
174 sp<IDrm> drm = CreateDrm();
175
176 if (drm == NULL) {
177 return NULL;
178 }
179
180 status_t err = drm->createPlugin(uuid);
181
182 if (err != OK) {
183 return NULL;
184 }
185
186 return drm;
187}
188
Marco Nelissen3425fd52014-05-14 11:12:46 -0700189EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700190bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
191 sp<IDrm> drm = CreateDrm();
192
193 if (drm == NULL) {
194 return false;
195 }
196
197 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
198 return drm->isCryptoSchemeSupported(uuid, mimeStr);
199}
200
Marco Nelissen3425fd52014-05-14 11:12:46 -0700201EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700202AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
203 AMediaDrm *mObj = new AMediaDrm();
204 mObj->mDrm = CreateDrmFromUUID(uuid);
205 return mObj;
206}
207
Marco Nelissen3425fd52014-05-14 11:12:46 -0700208EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700209void AMediaDrm_release(AMediaDrm *mObj) {
210 if (mObj->mDrm != NULL) {
211 mObj->mDrm->setListener(NULL);
212 mObj->mDrm->destroyPlugin();
213 mObj->mDrm.clear();
214 }
215 delete mObj;
216}
217
Jeff Tinker3305b992014-05-14 18:39:25 -0700218EXPORT
219mediadrm_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
220 if (!mObj || mObj->mDrm == NULL) {
221 return MEDIADRM_INVALID_OBJECT_ERROR;
222 }
223 mObj->mListener = new DrmListener(mObj, listener);
224 mObj->mDrm->setListener(mObj->mListener);
225 return MEDIADRM_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700226}
Jeff Tinker497ca092014-05-13 09:31:15 -0700227
228
229static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
230 iter = mObj->mIds.begin();
231 while (iter != mObj->mIds.end()) {
232 if (iter->array() == id.ptr && iter->size() == id.length) {
233 return true;
234 }
235 }
236 return false;
237}
238
Marco Nelissen3425fd52014-05-14 11:12:46 -0700239EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700240mediadrm_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId &sessionId) {
241 if (!mObj || mObj->mDrm == NULL) {
242 return MEDIADRM_INVALID_OBJECT_ERROR;
243 }
244 Vector<uint8_t> session;
245 status_t status = mObj->mDrm->openSession(session);
246 if (status == OK) {
247 mObj->mIds.push_front(session);
248 List<idvec_t>::iterator iter = mObj->mIds.begin();
249 sessionId.ptr = iter->array();
250 sessionId.length = iter->size();
251 }
252 return MEDIADRM_OK;
253}
254
Marco Nelissen3425fd52014-05-14 11:12:46 -0700255EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700256mediadrm_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId) {
257 if (!mObj || mObj->mDrm == NULL) {
258 return MEDIADRM_INVALID_OBJECT_ERROR;
259 }
260
261 List<idvec_t>::iterator iter;
262 if (!findId(mObj, sessionId, iter)) {
263 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
264 }
265 mObj->mDrm->closeSession(*iter);
266 mObj->mIds.erase(iter);
267 return MEDIADRM_OK;
268}
269
Marco Nelissen3425fd52014-05-14 11:12:46 -0700270EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700271mediadrm_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope &scope,
272 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
273 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
274 const uint8_t *&keyRequest, size_t &keyRequestSize) {
275
276 if (!mObj || mObj->mDrm == NULL) {
277 return MEDIADRM_INVALID_OBJECT_ERROR;
278 }
279 if (!mimeType) {
280 return MEDIADRM_INVALID_PARAMETER_ERROR;
281 }
282
283 List<idvec_t>::iterator iter;
284 if (!findId(mObj, scope, iter)) {
285 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
286 }
287
288 Vector<uint8_t> mdInit;
289 mdInit.appendArray(init, initSize);
290 DrmPlugin::KeyType mdKeyType;
291 switch (keyType) {
292 case KEY_TYPE_STREAMING:
293 mdKeyType = DrmPlugin::kKeyType_Streaming;
294 break;
295 case KEY_TYPE_OFFLINE:
296 mdKeyType = DrmPlugin::kKeyType_Offline;
297 break;
298 case KEY_TYPE_RELEASE:
299 mdKeyType = DrmPlugin::kKeyType_Release;
300 break;
301 default:
302 return MEDIADRM_INVALID_PARAMETER_ERROR;
303 }
304 KeyedVector<String8, String8> mdOptionalParameters;
305 for (size_t i = 0; i < numOptionalParameters; i++) {
306 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
307 String8(optionalParameters[i].mValue));
308 }
309 String8 defaultUrl;
310 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
311 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl);
312 if (status != OK) {
313 return translateStatus(status);
314 } else {
315 keyRequest = mObj->mKeyRequest.array();
316 keyRequestSize = mObj->mKeyRequest.size();
317 }
318 return MEDIADRM_OK;
319}
320
Marco Nelissen3425fd52014-05-14 11:12:46 -0700321EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700322mediadrm_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope &scope,
323 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId &keySetId) {
324
325 if (!mObj || mObj->mDrm == NULL) {
326 return MEDIADRM_INVALID_OBJECT_ERROR;
327 }
328 if (!response || !responseSize) {
329 return MEDIADRM_INVALID_PARAMETER_ERROR;
330 }
331
332 List<idvec_t>::iterator iter;
333 if (!findId(mObj, scope, iter)) {
334 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
335 }
336 Vector<uint8_t> mdResponse;
337 mdResponse.appendArray(response, responseSize);
338
339 Vector<uint8_t> mdKeySetId;
340 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
341 if (status == OK) {
342 mObj->mIds.push_front(mdKeySetId);
343 List<idvec_t>::iterator iter = mObj->mIds.begin();
344 keySetId.ptr = iter->array();
345 keySetId.length = iter->size();
346 } else {
347 keySetId.ptr = NULL;
348 keySetId.length = 0;
349 }
350 return MEDIADRM_OK;
351}
352
Marco Nelissen3425fd52014-05-14 11:12:46 -0700353EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700354mediadrm_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId,
355 const AMediaDrmKeySetId &keySetId) {
356
357 if (!mObj || mObj->mDrm == NULL) {
358 return MEDIADRM_INVALID_OBJECT_ERROR;
359 }
360 List<idvec_t>::iterator iter;
361 if (!findId(mObj, sessionId, iter)) {
362 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
363 }
364 Vector<uint8_t> keySet;
365 keySet.appendArray(keySetId.ptr, keySetId.length);
366 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
367}
368
Marco Nelissen3425fd52014-05-14 11:12:46 -0700369EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700370mediadrm_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId &keySetId) {
371 if (!mObj || mObj->mDrm == NULL) {
372 return MEDIADRM_INVALID_OBJECT_ERROR;
373 }
374 List<idvec_t>::iterator iter;
375 status_t status;
376 if (!findId(mObj, keySetId, iter)) {
377 Vector<uint8_t> keySet;
378 keySet.appendArray(keySetId.ptr, keySetId.length);
379 status = mObj->mDrm->removeKeys(keySet);
380 } else {
381 status = mObj->mDrm->removeKeys(*iter);
382 mObj->mIds.erase(iter);
383 }
384 return translateStatus(status);
385}
386
Marco Nelissen3425fd52014-05-14 11:12:46 -0700387EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700388mediadrm_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId,
389 AMediaDrmKeyValue *keyValuePairs, size_t &numPairs) {
390
391 if (!mObj || mObj->mDrm == NULL) {
392 return MEDIADRM_INVALID_OBJECT_ERROR;
393 }
394 List<idvec_t>::iterator iter;
395 if (!findId(mObj, sessionId, iter)) {
396 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
397 }
398
399 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
400 if (status != OK) {
401 numPairs = 0;
402 return translateStatus(status);
403 }
404
405 if (mObj->mQueryResults.size() > numPairs) {
406 numPairs = mObj->mQueryResults.size();
407 return MEDIADRM_SHORT_BUFFER;
408 }
409
410 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
411 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
412 keyValuePairs[i].mValue = mObj->mQueryResults.keyAt(i).string();
413 }
414 numPairs = mObj->mQueryResults.size();
415 return MEDIADRM_OK;
416}
417
Marco Nelissen3425fd52014-05-14 11:12:46 -0700418EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700419mediadrm_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t *&provisionRequest,
420 size_t &provisionRequestSize, const char *&serverUrl) {
421 if (!mObj || mObj->mDrm == NULL) {
422 return MEDIADRM_INVALID_OBJECT_ERROR;
423 }
424 if (!provisionRequestSize || !serverUrl) {
425 return MEDIADRM_INVALID_PARAMETER_ERROR;
426 }
427
428 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
429 mObj->mProvisionRequest, mObj->mProvisionUrl);
430 if (status != OK) {
431 return translateStatus(status);
432 } else {
433 provisionRequest = mObj->mProvisionRequest.array();
434 provisionRequestSize = mObj->mProvisionRequest.size();
435 serverUrl = mObj->mProvisionUrl.string();
436 }
437 return MEDIADRM_OK;
438}
439
Marco Nelissen3425fd52014-05-14 11:12:46 -0700440EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700441mediadrm_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
442 const uint8_t *response, size_t responseSize) {
443 if (!mObj || mObj->mDrm == NULL) {
444 return MEDIADRM_INVALID_OBJECT_ERROR;
445 }
446 if (!response || !responseSize) {
447 return MEDIADRM_INVALID_PARAMETER_ERROR;
448 }
449
450 Vector<uint8_t> mdResponse;
451 mdResponse.appendArray(response, responseSize);
452
453 Vector<uint8_t> unused;
454 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
455}
456
Marco Nelissen3425fd52014-05-14 11:12:46 -0700457EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700458mediadrm_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
459 AMediaDrmSecureStop *secureStops, size_t &numSecureStops) {
460
461 if (!mObj || mObj->mDrm == NULL) {
462 return MEDIADRM_INVALID_OBJECT_ERROR;
463 }
464 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
465 if (status != OK) {
466 numSecureStops = 0;
467 return translateStatus(status);
468 }
469 if (numSecureStops < mObj->mSecureStops.size()) {
470 return MEDIADRM_SHORT_BUFFER;
471 }
472 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
473 size_t i = 0;
474 while (iter != mObj->mSecureStops.end()) {
475 secureStops[i].ptr = iter->array();
476 secureStops[i].length = iter->size();
477 ++iter;
478 ++i;
479 }
480 numSecureStops = mObj->mSecureStops.size();
481 return MEDIADRM_OK;
482}
483
Marco Nelissen3425fd52014-05-14 11:12:46 -0700484EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700485mediadrm_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
486 const AMediaDrmSecureStop &ssRelease) {
487
488 if (!mObj || mObj->mDrm == NULL) {
489 return MEDIADRM_INVALID_OBJECT_ERROR;
490 }
491
492 Vector<uint8_t> release;
493 release.appendArray(ssRelease.ptr, ssRelease.length);
494 return translateStatus(mObj->mDrm->releaseSecureStops(release));
495}
496
497
Marco Nelissen3425fd52014-05-14 11:12:46 -0700498EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700499mediadrm_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
500 const char *&propertyValue) {
501
502 if (!mObj || mObj->mDrm == NULL) {
503 return MEDIADRM_INVALID_OBJECT_ERROR;
504 }
505
506 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
507 mObj->mPropertyString);
508
509 if (status == OK) {
510 propertyValue = mObj->mPropertyString.string();
511 } else {
512 propertyValue = NULL;
513 }
514 return translateStatus(status);
515}
516
Marco Nelissen3425fd52014-05-14 11:12:46 -0700517EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700518mediadrm_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
519 const char *propertyName, AMediaDrmByteArray &propertyValue) {
520 if (!mObj || mObj->mDrm == NULL) {
521 return MEDIADRM_INVALID_OBJECT_ERROR;
522 }
523
524 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
525 mObj->mPropertyByteArray);
526
527 if (status == OK) {
528 propertyValue.ptr = mObj->mPropertyByteArray.array();
529 propertyValue.length = mObj->mPropertyByteArray.size();
530 } else {
531 propertyValue.ptr = NULL;
532 propertyValue.length = 0;
533 }
534 return translateStatus(status);
535}
536
Marco Nelissen3425fd52014-05-14 11:12:46 -0700537EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700538mediadrm_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
539 const char *propertyName, const char *value) {
540 if (!mObj || mObj->mDrm == NULL) {
541 return MEDIADRM_INVALID_OBJECT_ERROR;
542 }
543
544 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
545 String8(value)));
546}
547
Marco Nelissen3425fd52014-05-14 11:12:46 -0700548EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700549mediadrm_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
550 const char *propertyName, const uint8_t *value, size_t valueSize) {
551
552 Vector<uint8_t> byteArray;
553 byteArray.appendArray(value, valueSize);
554
555 return translateStatus(mObj->mDrm->getPropertyByteArray(String8(propertyName),
556 byteArray));
557}
558
559
560static mediadrm_status_t encrypt_decrypt_common(AMediaDrm *mObj,
561 const AMediaDrmSessionId &sessionId,
562 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
563 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
564
565 if (!mObj || mObj->mDrm == NULL) {
566 return MEDIADRM_INVALID_OBJECT_ERROR;
567 }
568 List<idvec_t>::iterator iter;
569 if (!findId(mObj, sessionId, iter)) {
570 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
571 }
572
573 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
574 if (status != OK) {
575 return translateStatus(status);
576 }
577
578 Vector<uint8_t> keyIdVec;
579 const size_t kKeyIdSize = 16;
580 keyIdVec.appendArray(keyId, kKeyIdSize);
581
582 Vector<uint8_t> inputVec;
583 inputVec.appendArray(input, dataSize);
584
585 Vector<uint8_t> ivVec;
586 const size_t kIvSize = 16;
587 ivVec.appendArray(iv, kIvSize);
588
589 Vector<uint8_t> outputVec;
590 if (encrypt) {
591 status_t status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
592 } else {
593 status_t status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
594 }
595 if (status == OK) {
596 memcpy(output, outputVec.array(), outputVec.size());
597 }
598 return translateStatus(status);
599}
600
Marco Nelissen3425fd52014-05-14 11:12:46 -0700601EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700602mediadrm_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId,
603 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
604 const uint8_t *input, uint8_t *output, size_t dataSize) {
605 return encrypt_decrypt_common(mObj, sessionId, cipherAlgorithm, keyId, iv,
606 input, output, dataSize, true);
607}
608
Marco Nelissen3425fd52014-05-14 11:12:46 -0700609EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700610mediadrm_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId,
611 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
612 const uint8_t *input, uint8_t *output, size_t dataSize) {
613 return encrypt_decrypt_common(mObj, sessionId, cipherAlgorithm, keyId, iv,
614 input, output, dataSize, false);
615}
616
Marco Nelissen3425fd52014-05-14 11:12:46 -0700617EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700618mediadrm_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId,
619 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
620 uint8_t *signature, size_t *signatureSize) {
621
622 if (!mObj || mObj->mDrm == NULL) {
623 return MEDIADRM_INVALID_OBJECT_ERROR;
624 }
625 List<idvec_t>::iterator iter;
626 if (!findId(mObj, sessionId, iter)) {
627 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
628 }
629
630 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
631 if (status != OK) {
632 return translateStatus(status);
633 }
634
635 Vector<uint8_t> keyIdVec;
636 const size_t kKeyIdSize = 16;
637 keyIdVec.appendArray(keyId, kKeyIdSize);
638
639 Vector<uint8_t> messageVec;
640 messageVec.appendArray(message, messageSize);
641
642 Vector<uint8_t> signatureVec;
643 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
644 if (signatureVec.size() > *signatureSize) {
645 return MEDIADRM_SHORT_BUFFER;
646 }
647 if (status == OK) {
648 memcpy(signature, signatureVec.array(), signatureVec.size());
649 }
650 return translateStatus(status);
651}
652
Marco Nelissen3425fd52014-05-14 11:12:46 -0700653EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700654mediadrm_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId,
655 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
656 const uint8_t *signature, size_t signatureSize) {
657
658 if (!mObj || mObj->mDrm == NULL) {
659 return MEDIADRM_INVALID_OBJECT_ERROR;
660 }
661 List<idvec_t>::iterator iter;
662 if (!findId(mObj, sessionId, iter)) {
663 return MEDIADRM_SESSION_NOT_OPENED_ERROR;
664 }
665
666 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
667 if (status != OK) {
668 return translateStatus(status);
669 }
670
671 Vector<uint8_t> keyIdVec;
672 const size_t kKeyIdSize = 16;
673 keyIdVec.appendArray(keyId, kKeyIdSize);
674
675 Vector<uint8_t> messageVec;
676 messageVec.appendArray(message, messageSize);
677
678 Vector<uint8_t> signatureVec;
679 signatureVec.appendArray(signature, signatureSize);
680
681 bool match;
682 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
683 if (status == OK) {
684 return match ? MEDIADRM_OK : MEDIADRM_VERIFY_FAILED;
685 }
686 return translateStatus(status);
687}
688
689} // extern "C"
690