blob: 6e9945d2c59a448e934e485cd1f7482aec2d2327 [file] [log] [blame]
Jeff Tinker497ca092014-05-13 09:31:15 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Marco Nelissenc7a11b22014-05-30 10:13:25 -070017//#define LOG_NDEBUG 0
Jeff Tinker497ca092014-05-13 09:31:15 -070018#define LOG_TAG "NdkMediaDrm"
19
Edwin Wongad02cc62018-08-23 13:48:27 -070020#include <inttypes.h>
John W. Bruce9c4e0fa2019-05-03 17:12:44 -070021#include <unistd.h>
Edwin Wongad02cc62018-08-23 13:48:27 -070022
Robert Shihce811b42019-11-19 15:52:33 -080023#include <iostream>
24#include <fstream>
25#include <string>
26
Colin Cross7e8d4ba2017-05-04 16:17:42 -070027#include <media/NdkMediaDrm.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070028
Jeff Tinkera69729d2016-02-12 08:47:00 -080029#include <cutils/properties.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070030#include <utils/Log.h>
31#include <utils/StrongPointer.h>
32#include <gui/Surface.h>
33
John W. Bruce9c4e0fa2019-05-03 17:12:44 -070034#include <android-base/properties.h>
Robert Shih28c2ed32019-10-27 22:55:12 -070035#include <mediadrm/DrmUtils.h>
Marco Nelissen13aa1a42019-09-27 10:21:55 -070036#include <mediadrm/IDrm.h>
37#include <mediadrm/IDrmClient.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070038#include <media/stagefright/MediaErrors.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070039#include <media/NdkMediaCrypto.h>
Jeff Tinker497ca092014-05-13 09:31:15 -070040
41
42using namespace android;
43
44typedef Vector<uint8_t> idvec_t;
45
Robert Shiha54e81f2019-08-02 14:15:01 -070046struct DrmListener: virtual public IDrmClient
Jeff Tinker3305b992014-05-14 18:39:25 -070047{
48private:
49 AMediaDrm *mObj;
Edwin Wongad02cc62018-08-23 13:48:27 -070050 AMediaDrmEventListener mEventListener;
51 AMediaDrmExpirationUpdateListener mExpirationUpdateListener;
52 AMediaDrmKeysChangeListener mKeysChangeListener;
Jeff Tinker3305b992014-05-14 18:39:25 -070053
54public:
Edwin Wongad02cc62018-08-23 13:48:27 -070055 DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj),
56 mEventListener(listener), mExpirationUpdateListener(NULL), mKeysChangeListener(NULL) {}
57
58 DrmListener(AMediaDrm *obj, AMediaDrmExpirationUpdateListener listener) : mObj(obj),
59 mEventListener(NULL), mExpirationUpdateListener(listener), mKeysChangeListener(NULL) {}
60
61 DrmListener(AMediaDrm *obj, AMediaDrmKeysChangeListener listener) : mObj(obj),
62 mEventListener(NULL), mExpirationUpdateListener(NULL), mKeysChangeListener(listener) {}
63
64 void setEventListener(AMediaDrmEventListener listener) {
65 mEventListener = listener;
66 }
67
68 void setExpirationUpdateListener(AMediaDrmExpirationUpdateListener listener) {
69 mExpirationUpdateListener = listener;
70 }
71
72 void setKeysChangeListener(AMediaDrmKeysChangeListener listener) {
73 mKeysChangeListener = listener;
74 }
75
Robert Shih61e1c762019-10-31 21:26:58 -070076 void sendEvent(
77 DrmPlugin::EventType eventType,
78 const hardware::hidl_vec<uint8_t> &sessionId,
79 const hardware::hidl_vec<uint8_t> &data) override;
80
81 void sendExpirationUpdate(
82 const hardware::hidl_vec<uint8_t> &sessionId,
83 int64_t expiryTimeInMS) override;
84
85 void sendKeysChange(
86 const hardware::hidl_vec<uint8_t> &sessionId,
87 const std::vector<DrmKeyStatus> &keyStatusList,
88 bool hasNewUsableKey) override;
89
90 void sendSessionLostState(
91 const hardware::hidl_vec<uint8_t> &) override {}
92
Jeff Tinker3305b992014-05-14 18:39:25 -070093};
94
Jeff Tinker497ca092014-05-13 09:31:15 -070095struct AMediaDrm {
96 sp<IDrm> mDrm;
Jeff Tinker497ca092014-05-13 09:31:15 -070097 List<idvec_t> mIds;
98 KeyedVector<String8, String8> mQueryResults;
99 Vector<uint8_t> mKeyRequest;
100 Vector<uint8_t> mProvisionRequest;
101 String8 mProvisionUrl;
102 String8 mPropertyString;
103 Vector<uint8_t> mPropertyByteArray;
104 List<Vector<uint8_t> > mSecureStops;
Jeff Tinker3305b992014-05-14 18:39:25 -0700105 sp<DrmListener> mListener;
Jeff Tinker497ca092014-05-13 09:31:15 -0700106};
107
Robert Shih61e1c762019-10-31 21:26:58 -0700108void DrmListener::sendExpirationUpdate(
109 const hardware::hidl_vec<uint8_t> &sessionId,
110 int64_t expiryTimeInMS) {
111 if (!mExpirationUpdateListener) {
112 ALOGE("No ExpirationUpdateListener specified");
Jeff Tinker3305b992014-05-14 18:39:25 -0700113 return;
114 }
115
Robert Shih61e1c762019-10-31 21:26:58 -0700116 if (expiryTimeInMS >= 0) {
117 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
118 (*mExpirationUpdateListener)(mObj, &asid, expiryTimeInMS);
119 } else {
120 ALOGE("expiry time negative, status=%" PRId64 "", expiryTimeInMS);
121 }
122}
Edwin Wongad02cc62018-08-23 13:48:27 -0700123
Robert Shih61e1c762019-10-31 21:26:58 -0700124void DrmListener::sendKeysChange(
125 const hardware::hidl_vec<uint8_t> &sessionId,
126 const std::vector<DrmKeyStatus> &keyStatusList,
127 bool hasNewUsableKey) {
128 if (!mKeysChangeListener) {
129 ALOGE("No KeysChangeListener specified");
Edwin Wongad02cc62018-08-23 13:48:27 -0700130 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700131 }
132
Robert Shih61e1c762019-10-31 21:26:58 -0700133 Vector<AMediaDrmKeyStatus> keysStatus;
134 for (const auto &drmKeyStatus : keyStatusList) {
Edwin Wongad02cc62018-08-23 13:48:27 -0700135 AMediaDrmKeyStatus keyStatus;
Robert Shih61e1c762019-10-31 21:26:58 -0700136 keyStatus.keyId.ptr = drmKeyStatus.keyId.data();
137 keyStatus.keyId.length = drmKeyStatus.keyId.size();
138 keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(drmKeyStatus.type);
139 keysStatus.push(keyStatus);
140 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700141
Robert Shih61e1c762019-10-31 21:26:58 -0700142 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
143 int32_t numKeys = keyStatusList.size();
144 (*mKeysChangeListener)(mObj, &asid, keysStatus.array(), numKeys, hasNewUsableKey);
145 return;
146}
Edwin Wongad02cc62018-08-23 13:48:27 -0700147
Robert Shih61e1c762019-10-31 21:26:58 -0700148void DrmListener::sendEvent(
149 DrmPlugin::EventType eventType,
150 const hardware::hidl_vec<uint8_t> &sessionId,
151 const hardware::hidl_vec<uint8_t> &data) {
152 if (!mEventListener) {
153 ALOGE("No EventListener specified");
Edwin Wongad02cc62018-08-23 13:48:27 -0700154 return;
155 }
156
157 // Handles AMediaDrmEventListener below:
158 // translates DrmPlugin event types into their NDK equivalents
Jeff Tinker3305b992014-05-14 18:39:25 -0700159 AMediaDrmEventType ndkEventType;
160 switch(eventType) {
161 case DrmPlugin::kDrmPluginEventProvisionRequired:
162 ndkEventType = EVENT_PROVISION_REQUIRED;
163 break;
164 case DrmPlugin::kDrmPluginEventKeyNeeded:
165 ndkEventType = EVENT_KEY_REQUIRED;
166 break;
167 case DrmPlugin::kDrmPluginEventKeyExpired:
168 ndkEventType = EVENT_KEY_EXPIRED;
169 break;
170 case DrmPlugin::kDrmPluginEventVendorDefined:
171 ndkEventType = EVENT_VENDOR_DEFINED;
172 break;
Edwin Wongad02cc62018-08-23 13:48:27 -0700173 case DrmPlugin::kDrmPluginEventSessionReclaimed:
174 ndkEventType = EVENT_SESSION_RECLAIMED;
175 break;
Jeff Tinker3305b992014-05-14 18:39:25 -0700176 default:
Robert Shih61e1c762019-10-31 21:26:58 -0700177 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", eventType);
Edwin Wongad02cc62018-08-23 13:48:27 -0700178 return;
Jeff Tinker3305b992014-05-14 18:39:25 -0700179 }
180
Robert Shih61e1c762019-10-31 21:26:58 -0700181 AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
182 int32_t dataSize = data.size();
183 const uint8_t *dataPtr = data.data();
Edwin Wongad02cc62018-08-23 13:48:27 -0700184 if (dataSize > 0) {
Robert Shih61e1c762019-10-31 21:26:58 -0700185 (*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
Edwin Wongad02cc62018-08-23 13:48:27 -0700186 } else {
Robert Shih61e1c762019-10-31 21:26:58 -0700187 ALOGE("invalid event data size=%d", dataSize);
Edwin Wongad02cc62018-08-23 13:48:27 -0700188 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700189}
190
Jeff Tinker497ca092014-05-13 09:31:15 -0700191extern "C" {
192
Marco Nelissene419d7c2014-05-15 14:17:25 -0700193static media_status_t translateStatus(status_t status) {
194 media_status_t result = AMEDIA_ERROR_UNKNOWN;
Jeff Tinker497ca092014-05-13 09:31:15 -0700195 switch (status) {
196 case OK:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700197 result = AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700198 break;
199 case android::ERROR_DRM_NOT_PROVISIONED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700200 result = AMEDIA_DRM_NOT_PROVISIONED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700201 break;
202 case android::ERROR_DRM_RESOURCE_BUSY:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700203 result = AMEDIA_DRM_RESOURCE_BUSY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700204 break;
205 case android::ERROR_DRM_DEVICE_REVOKED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700206 result = AMEDIA_DRM_DEVICE_REVOKED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700207 break;
208 case android::ERROR_DRM_CANNOT_HANDLE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700209 result = AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700210 break;
211 case android::ERROR_DRM_TAMPER_DETECTED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700212 result = AMEDIA_DRM_TAMPER_DETECTED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700213 break;
214 case android::ERROR_DRM_SESSION_NOT_OPENED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700215 result = AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700216 break;
217 case android::ERROR_DRM_NO_LICENSE:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700218 result = AMEDIA_DRM_NEED_KEY;
Jeff Tinker497ca092014-05-13 09:31:15 -0700219 break;
220 case android::ERROR_DRM_LICENSE_EXPIRED:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700221 result = AMEDIA_DRM_LICENSE_EXPIRED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700222 break;
223 default:
Jeff Tinker497ca092014-05-13 09:31:15 -0700224 break;
225 }
226 return result;
227}
228
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700229static bool ShouldGetAppPackageName(void) {
230 // Check what this device's first API level was.
231 int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
232 if (firstApiLevel == 0) {
233 // First API Level is 0 on factory ROMs, but we can assume the current SDK
234 // version is the first if it's a factory ROM.
235 firstApiLevel = android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
236 }
237 return firstApiLevel >= 29; // Android Q
238}
239
240static status_t GetAppPackageName(String8 *packageName) {
Robert Shihce811b42019-11-19 15:52:33 -0800241 // todo(robertshih): use refactored/renamed libneuralnetworks_packageinfo which is stable
242 std::string appName;
243 std::ifstream cmdline("/proc/self/cmdline");
244 std::getline(cmdline, appName);
245 cmdline.close();
246 if (appName.empty()) {
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700247 return UNKNOWN_ERROR;
248 }
Robert Shihce811b42019-11-19 15:52:33 -0800249 *packageName = String8(appName.c_str());
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700250 return OK;
251}
252
Jeff Tinker497ca092014-05-13 09:31:15 -0700253static sp<IDrm> CreateDrm() {
Robert Shih28c2ed32019-10-27 22:55:12 -0700254 return DrmUtils::MakeDrm();
Jeff Tinker497ca092014-05-13 09:31:15 -0700255}
256
257
258static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) {
259 sp<IDrm> drm = CreateDrm();
260
261 if (drm == NULL) {
262 return NULL;
263 }
264
John W. Bruce9c4e0fa2019-05-03 17:12:44 -0700265 String8 packageName;
266 if (ShouldGetAppPackageName()) {
267 status_t err = GetAppPackageName(&packageName);
268
269 if (err != OK) {
270 return NULL;
271 }
272 }
273
274 status_t err = drm->createPlugin(uuid, packageName);
Jeff Tinker497ca092014-05-13 09:31:15 -0700275
276 if (err != OK) {
277 return NULL;
278 }
279
280 return drm;
281}
282
Marco Nelissen3425fd52014-05-14 11:12:46 -0700283EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700284bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) {
285 sp<IDrm> drm = CreateDrm();
286
287 if (drm == NULL) {
288 return false;
289 }
290
291 String8 mimeStr = mimeType ? String8(mimeType) : String8("");
Jeff Tinkerdb3fa5f2019-01-25 22:56:56 -0800292 bool isSupported = false;
293 status_t status = drm->isCryptoSchemeSupported(uuid, mimeStr,
294 DrmPlugin::kSecurityLevelUnknown, &isSupported);
295 return (status == OK) && isSupported;
Jeff Tinker497ca092014-05-13 09:31:15 -0700296}
297
Marco Nelissen3425fd52014-05-14 11:12:46 -0700298EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700299AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) {
300 AMediaDrm *mObj = new AMediaDrm();
301 mObj->mDrm = CreateDrmFromUUID(uuid);
Edwin Wongad02cc62018-08-23 13:48:27 -0700302
303 mObj->mListener.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700304 return mObj;
305}
306
Marco Nelissen3425fd52014-05-14 11:12:46 -0700307EXPORT
Jeff Tinker497ca092014-05-13 09:31:15 -0700308void AMediaDrm_release(AMediaDrm *mObj) {
309 if (mObj->mDrm != NULL) {
310 mObj->mDrm->setListener(NULL);
311 mObj->mDrm->destroyPlugin();
312 mObj->mDrm.clear();
313 }
314 delete mObj;
315}
316
Jeff Tinker3305b992014-05-14 18:39:25 -0700317EXPORT
Marco Nelissen7c96d532014-05-15 15:26:14 -0700318media_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) {
Jeff Tinker3305b992014-05-14 18:39:25 -0700319 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissen7c96d532014-05-15 15:26:14 -0700320 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker3305b992014-05-14 18:39:25 -0700321 }
Edwin Wongad02cc62018-08-23 13:48:27 -0700322
323 if (mObj->mListener.get()) {
324 mObj->mListener->setEventListener(listener);
325 } else {
326 mObj->mListener = new DrmListener(mObj, listener);
327 }
Jeff Tinker3305b992014-05-14 18:39:25 -0700328 mObj->mDrm->setListener(mObj->mListener);
Marco Nelissen7c96d532014-05-15 15:26:14 -0700329 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700330}
Jeff Tinker497ca092014-05-13 09:31:15 -0700331
Edwin Wongad02cc62018-08-23 13:48:27 -0700332EXPORT
333media_status_t AMediaDrm_setOnExpirationUpdateListener(AMediaDrm *mObj,
334 AMediaDrmExpirationUpdateListener listener) {
335 if (!mObj || mObj->mDrm == NULL) {
336 return AMEDIA_ERROR_INVALID_OBJECT;
337 }
338
339 if (mObj->mListener.get()) {
340 mObj->mListener->setExpirationUpdateListener(listener);
341 } else {
342 mObj->mListener = new DrmListener(mObj, listener);
343 }
344 mObj->mDrm->setListener(mObj->mListener);
345 return AMEDIA_OK;
346}
347
348EXPORT
349media_status_t AMediaDrm_setOnKeysChangeListener(AMediaDrm *mObj,
350 AMediaDrmKeysChangeListener listener) {
351 if (!mObj || mObj->mDrm == NULL) {
352 return AMEDIA_ERROR_INVALID_OBJECT;
353 }
354
355 if (mObj->mListener.get()) {
356 mObj->mListener->setKeysChangeListener(listener);
357 } else {
358 mObj->mListener = new DrmListener(mObj, listener);
359 }
360 mObj->mDrm->setListener(mObj->mListener);
361 return AMEDIA_OK;
362}
Jeff Tinker497ca092014-05-13 09:31:15 -0700363
364static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
Edwin Wong21030442016-10-18 12:34:05 -0700365 for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
Jeff Tinkerc5f013f2017-04-05 10:28:27 -0700366 if (id.length == iter->size() && memcmp(iter->array(), id.ptr, iter->size()) == 0) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700367 return true;
368 }
369 }
370 return false;
371}
372
Marco Nelissen3425fd52014-05-14 11:12:46 -0700373EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700374media_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700375 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700376 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700377 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700378 if (!sessionId) {
379 return AMEDIA_ERROR_INVALID_PARAMETER;
380 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700381 Vector<uint8_t> session;
Jeff Tinker41d279a2018-02-11 19:52:08 +0000382 status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
Rahul Frias814fd712021-02-02 01:42:38 -0800383 if (status != OK) {
384 sessionId->ptr = NULL;
385 sessionId->length = 0;
386 return translateStatus(status);
Jeff Tinker497ca092014-05-13 09:31:15 -0700387 }
Rahul Frias814fd712021-02-02 01:42:38 -0800388 mObj->mIds.push_front(session);
389 List<idvec_t>::iterator iter = mObj->mIds.begin();
390 sessionId->ptr = iter->array();
391 sessionId->length = iter->size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700392 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700393}
394
Marco Nelissen3425fd52014-05-14 11:12:46 -0700395EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700396media_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700397 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700398 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700399 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700400 if (!sessionId) {
401 return AMEDIA_ERROR_INVALID_PARAMETER;
402 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700403
404 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700405 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700406 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700407 }
408 mObj->mDrm->closeSession(*iter);
409 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700410 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700411}
412
Marco Nelissen3425fd52014-05-14 11:12:46 -0700413EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700414media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700415 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
416 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700417 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700418
419 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700420 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700421 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700422 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700423 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700424 }
425
426 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700427 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700428 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700429 }
430
431 Vector<uint8_t> mdInit;
432 mdInit.appendArray(init, initSize);
433 DrmPlugin::KeyType mdKeyType;
434 switch (keyType) {
435 case KEY_TYPE_STREAMING:
436 mdKeyType = DrmPlugin::kKeyType_Streaming;
437 break;
438 case KEY_TYPE_OFFLINE:
439 mdKeyType = DrmPlugin::kKeyType_Offline;
440 break;
441 case KEY_TYPE_RELEASE:
442 mdKeyType = DrmPlugin::kKeyType_Release;
443 break;
444 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700445 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700446 }
447 KeyedVector<String8, String8> mdOptionalParameters;
448 for (size_t i = 0; i < numOptionalParameters; i++) {
449 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
450 String8(optionalParameters[i].mValue));
451 }
452 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700453 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700454 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700455 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700456 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
457 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700458 if (status != OK) {
459 return translateStatus(status);
460 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700461 *keyRequest = mObj->mKeyRequest.array();
462 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700463 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700464 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700465}
466
Marco Nelissen3425fd52014-05-14 11:12:46 -0700467EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700468media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
469 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700470
471 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700472 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700473 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700474 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700475 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700476 }
477
478 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700479 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700480 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700481 }
482 Vector<uint8_t> mdResponse;
483 mdResponse.appendArray(response, responseSize);
484
485 Vector<uint8_t> mdKeySetId;
486 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
487 if (status == OK) {
488 mObj->mIds.push_front(mdKeySetId);
489 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700490 keySetId->ptr = iter->array();
491 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700492 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700493 keySetId->ptr = NULL;
494 keySetId->length = 0;
Rahul Frias814fd712021-02-02 01:42:38 -0800495 return translateStatus(status);
Jeff Tinker497ca092014-05-13 09:31:15 -0700496 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700497 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700498}
499
Marco Nelissen3425fd52014-05-14 11:12:46 -0700500EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700501media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
502 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700503
504 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700505 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700506 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700507 if (!sessionId || !keySetId) {
508 return AMEDIA_ERROR_INVALID_PARAMETER;
509 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700510 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700511 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700512 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700513 }
514 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700515 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700516 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
517}
518
Marco Nelissen3425fd52014-05-14 11:12:46 -0700519EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700520media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700521 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 (!keySetId) {
525 return AMEDIA_ERROR_INVALID_PARAMETER;
526 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700527 List<idvec_t>::iterator iter;
528 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700529 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700530 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700531 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700532 status = mObj->mDrm->removeKeys(keySet);
533 } else {
534 status = mObj->mDrm->removeKeys(*iter);
535 mObj->mIds.erase(iter);
536 }
537 return translateStatus(status);
538}
539
Marco Nelissen3425fd52014-05-14 11:12:46 -0700540EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700541media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
542 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700543
544 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700545 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700546 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700547 if (!sessionId || !numPairs) {
548 return AMEDIA_ERROR_INVALID_PARAMETER;
549 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700550 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700551 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700552 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700553 }
554
555 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
556 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700557 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700558 return translateStatus(status);
559 }
560
Marco Nelissen18a1b592014-05-20 08:45:18 -0700561 if (mObj->mQueryResults.size() > *numPairs) {
562 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700563 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700564 }
565
566 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
567 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700568 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700569 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700570 *numPairs = mObj->mQueryResults.size();
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 Nelissen18a1b592014-05-20 08:45:18 -0700575media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
576 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700577 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 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700580 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700581 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700582 }
583
584 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
585 mObj->mProvisionRequest, mObj->mProvisionUrl);
586 if (status != OK) {
587 return translateStatus(status);
588 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700589 *provisionRequest = mObj->mProvisionRequest.array();
590 *provisionRequestSize = mObj->mProvisionRequest.size();
591 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700592 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700593 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700594}
595
Marco Nelissen3425fd52014-05-14 11:12:46 -0700596EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700597media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700598 const uint8_t *response, size_t responseSize) {
599 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700600 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700601 }
602 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700603 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700604 }
605
606 Vector<uint8_t> mdResponse;
607 mdResponse.appendArray(response, responseSize);
608
609 Vector<uint8_t> unused;
610 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
611}
612
Marco Nelissen3425fd52014-05-14 11:12:46 -0700613EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700614media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700615 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700616
617 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700618 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700619 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700620 if (!numSecureStops) {
621 return AMEDIA_ERROR_INVALID_PARAMETER;
622 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700623 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
624 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700625 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700626 return translateStatus(status);
627 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700628 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700629 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700630 }
631 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
632 size_t i = 0;
633 while (iter != mObj->mSecureStops.end()) {
634 secureStops[i].ptr = iter->array();
635 secureStops[i].length = iter->size();
636 ++iter;
637 ++i;
638 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700639 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700640 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700641}
642
Marco Nelissen3425fd52014-05-14 11:12:46 -0700643EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700644media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700645 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700646
647 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700648 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700649 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700650 if (!ssRelease) {
651 return AMEDIA_ERROR_INVALID_PARAMETER;
652 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700653
654 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700655 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700656 return translateStatus(mObj->mDrm->releaseSecureStops(release));
657}
658
659
Marco Nelissen3425fd52014-05-14 11:12:46 -0700660EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700661media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700662 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700663
664 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700665 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700666 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700667 if (!propertyName || !propertyValue) {
668 return AMEDIA_ERROR_INVALID_PARAMETER;
669 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700670
671 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
672 mObj->mPropertyString);
673
674 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700675 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700676 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700677 *propertyValue = NULL;
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_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700684 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700685 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 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700688 if (!propertyName || !propertyValue) {
689 return AMEDIA_ERROR_INVALID_PARAMETER;
690 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700691
692 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
693 mObj->mPropertyByteArray);
694
695 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700696 propertyValue->ptr = mObj->mPropertyByteArray.array();
697 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700698 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700699 propertyValue->ptr = NULL;
700 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700701 }
702 return translateStatus(status);
703}
704
Marco Nelissen3425fd52014-05-14 11:12:46 -0700705EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700706media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700707 const char *propertyName, const char *value) {
708 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700709 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700710 }
711
712 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
713 String8(value)));
714}
715
Marco Nelissen3425fd52014-05-14 11:12:46 -0700716EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700717media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700718 const char *propertyName, const uint8_t *value, size_t valueSize) {
719
720 Vector<uint8_t> byteArray;
721 byteArray.appendArray(value, valueSize);
722
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700723 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700724 byteArray));
725}
726
727
Marco Nelissene419d7c2014-05-15 14:17:25 -0700728static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700729 const AMediaDrmSessionId &sessionId,
730 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
731 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
732
733 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700734 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700735 }
736 List<idvec_t>::iterator iter;
737 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700738 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700739 }
740
741 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
742 if (status != OK) {
743 return translateStatus(status);
744 }
745
746 Vector<uint8_t> keyIdVec;
747 const size_t kKeyIdSize = 16;
748 keyIdVec.appendArray(keyId, kKeyIdSize);
749
750 Vector<uint8_t> inputVec;
751 inputVec.appendArray(input, dataSize);
752
753 Vector<uint8_t> ivVec;
754 const size_t kIvSize = 16;
755 ivVec.appendArray(iv, kIvSize);
756
757 Vector<uint8_t> outputVec;
758 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800759 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700760 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800761 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700762 }
763 if (status == OK) {
764 memcpy(output, outputVec.array(), outputVec.size());
765 }
766 return translateStatus(status);
767}
768
Marco Nelissen3425fd52014-05-14 11:12:46 -0700769EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700770media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700771 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
772 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700773 if (!sessionId) {
774 return AMEDIA_ERROR_INVALID_PARAMETER;
775 }
776 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700777 input, output, dataSize, true);
778}
779
Marco Nelissen3425fd52014-05-14 11:12:46 -0700780EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700781media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700782 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
783 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700784 if (!sessionId) {
785 return AMEDIA_ERROR_INVALID_PARAMETER;
786 }
787 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700788 input, output, dataSize, false);
789}
790
Marco Nelissen3425fd52014-05-14 11:12:46 -0700791EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700792media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700793 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
794 uint8_t *signature, size_t *signatureSize) {
795
796 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700797 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700798 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700799 if (!sessionId) {
800 return AMEDIA_ERROR_INVALID_PARAMETER;
801 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700802 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700803 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700804 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700805 }
806
807 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
808 if (status != OK) {
809 return translateStatus(status);
810 }
811
812 Vector<uint8_t> keyIdVec;
813 const size_t kKeyIdSize = 16;
814 keyIdVec.appendArray(keyId, kKeyIdSize);
815
816 Vector<uint8_t> messageVec;
817 messageVec.appendArray(message, messageSize);
818
819 Vector<uint8_t> signatureVec;
820 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
821 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700822 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700823 }
824 if (status == OK) {
825 memcpy(signature, signatureVec.array(), signatureVec.size());
826 }
827 return translateStatus(status);
828}
829
Marco Nelissen3425fd52014-05-14 11:12:46 -0700830EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700831media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700832 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
833 const uint8_t *signature, size_t signatureSize) {
834
835 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700836 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700837 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700838 if (!sessionId) {
839 return AMEDIA_ERROR_INVALID_PARAMETER;
840 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700841 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700842 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700843 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700844 }
845
846 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
847 if (status != OK) {
848 return translateStatus(status);
849 }
850
851 Vector<uint8_t> keyIdVec;
852 const size_t kKeyIdSize = 16;
853 keyIdVec.appendArray(keyId, kKeyIdSize);
854
855 Vector<uint8_t> messageVec;
856 messageVec.appendArray(message, messageSize);
857
858 Vector<uint8_t> signatureVec;
859 signatureVec.appendArray(signature, signatureSize);
860
861 bool match;
862 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
863 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700864 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700865 }
866 return translateStatus(status);
867}
868
869} // extern "C"