blob: 3af9771ed8765dbd4aa58432178c12409fb8e5cf [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);
Jeff Tinker497ca092014-05-13 09:31:15 -0700383 if (status == OK) {
384 mObj->mIds.push_front(session);
385 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700386 sessionId->ptr = iter->array();
387 sessionId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700388 }
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_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700394 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700395 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700396 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700397 if (!sessionId) {
398 return AMEDIA_ERROR_INVALID_PARAMETER;
399 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700400
401 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700402 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700403 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700404 }
405 mObj->mDrm->closeSession(*iter);
406 mObj->mIds.erase(iter);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700407 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700408}
409
Marco Nelissen3425fd52014-05-14 11:12:46 -0700410EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700411media_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope *scope,
Jeff Tinker497ca092014-05-13 09:31:15 -0700412 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
413 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700414 const uint8_t **keyRequest, size_t *keyRequestSize) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700415
416 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700417 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700418 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700419 if (!mimeType || !scope || !keyRequest || !keyRequestSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700420 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700421 }
422
423 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700424 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700425 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700426 }
427
428 Vector<uint8_t> mdInit;
429 mdInit.appendArray(init, initSize);
430 DrmPlugin::KeyType mdKeyType;
431 switch (keyType) {
432 case KEY_TYPE_STREAMING:
433 mdKeyType = DrmPlugin::kKeyType_Streaming;
434 break;
435 case KEY_TYPE_OFFLINE:
436 mdKeyType = DrmPlugin::kKeyType_Offline;
437 break;
438 case KEY_TYPE_RELEASE:
439 mdKeyType = DrmPlugin::kKeyType_Release;
440 break;
441 default:
Marco Nelissene419d7c2014-05-15 14:17:25 -0700442 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700443 }
444 KeyedVector<String8, String8> mdOptionalParameters;
445 for (size_t i = 0; i < numOptionalParameters; i++) {
446 mdOptionalParameters.add(String8(optionalParameters[i].mKey),
447 String8(optionalParameters[i].mValue));
448 }
449 String8 defaultUrl;
Jeff Tinkerd072c902015-03-16 13:39:29 -0700450 DrmPlugin::KeyRequestType keyRequestType;
Edwin Wongb5c8f212018-07-06 17:29:24 -0700451 mObj->mKeyRequest.clear();
Jeff Tinker497ca092014-05-13 09:31:15 -0700452 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType),
Jeff Tinkerd072c902015-03-16 13:39:29 -0700453 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl,
454 &keyRequestType);
Jeff Tinker497ca092014-05-13 09:31:15 -0700455 if (status != OK) {
456 return translateStatus(status);
457 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700458 *keyRequest = mObj->mKeyRequest.array();
459 *keyRequestSize = mObj->mKeyRequest.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700460 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700461 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700462}
463
Marco Nelissen3425fd52014-05-14 11:12:46 -0700464EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700465media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope *scope,
466 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700467
468 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700469 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700470 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700471 if (!scope || !response || !responseSize || !keySetId) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700472 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700473 }
474
475 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700476 if (!findId(mObj, *scope, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700477 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700478 }
479 Vector<uint8_t> mdResponse;
480 mdResponse.appendArray(response, responseSize);
481
482 Vector<uint8_t> mdKeySetId;
483 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId);
484 if (status == OK) {
485 mObj->mIds.push_front(mdKeySetId);
486 List<idvec_t>::iterator iter = mObj->mIds.begin();
Marco Nelissen18a1b592014-05-20 08:45:18 -0700487 keySetId->ptr = iter->array();
488 keySetId->length = iter->size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700489 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700490 keySetId->ptr = NULL;
491 keySetId->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700492 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700493 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700494}
495
Marco Nelissen3425fd52014-05-14 11:12:46 -0700496EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700497media_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
498 const AMediaDrmKeySetId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700499
500 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700501 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700502 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700503 if (!sessionId || !keySetId) {
504 return AMEDIA_ERROR_INVALID_PARAMETER;
505 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700506 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700507 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700508 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700509 }
510 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700511 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700512 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet));
513}
514
Marco Nelissen3425fd52014-05-14 11:12:46 -0700515EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700516media_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId *keySetId) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700517 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700518 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700519 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700520 if (!keySetId) {
521 return AMEDIA_ERROR_INVALID_PARAMETER;
522 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700523 List<idvec_t>::iterator iter;
524 status_t status;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700525 if (!findId(mObj, *keySetId, iter)) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700526 Vector<uint8_t> keySet;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700527 keySet.appendArray(keySetId->ptr, keySetId->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700528 status = mObj->mDrm->removeKeys(keySet);
529 } else {
530 status = mObj->mDrm->removeKeys(*iter);
531 mObj->mIds.erase(iter);
532 }
533 return translateStatus(status);
534}
535
Marco Nelissen3425fd52014-05-14 11:12:46 -0700536EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700537media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
538 AMediaDrmKeyValue *keyValuePairs, size_t *numPairs) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700539
540 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700541 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700542 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700543 if (!sessionId || !numPairs) {
544 return AMEDIA_ERROR_INVALID_PARAMETER;
545 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700546 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700547 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700548 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700549 }
550
551 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults);
552 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700553 *numPairs = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700554 return translateStatus(status);
555 }
556
Marco Nelissen18a1b592014-05-20 08:45:18 -0700557 if (mObj->mQueryResults.size() > *numPairs) {
558 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700559 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700560 }
561
562 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
563 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
Edwin Wong815c9252017-08-30 17:47:20 -0700564 keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700565 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700566 *numPairs = mObj->mQueryResults.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700567 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700568}
569
Marco Nelissen3425fd52014-05-14 11:12:46 -0700570EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700571media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t **provisionRequest,
572 size_t *provisionRequestSize, const char **serverUrl) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700573 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700574 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700575 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700576 if (!provisionRequest || !provisionRequestSize || !*provisionRequestSize || !serverUrl) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700577 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700578 }
579
580 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""),
581 mObj->mProvisionRequest, mObj->mProvisionUrl);
582 if (status != OK) {
583 return translateStatus(status);
584 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700585 *provisionRequest = mObj->mProvisionRequest.array();
586 *provisionRequestSize = mObj->mProvisionRequest.size();
587 *serverUrl = mObj->mProvisionUrl.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700588 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700589 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700590}
591
Marco Nelissen3425fd52014-05-14 11:12:46 -0700592EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700593media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700594 const uint8_t *response, size_t responseSize) {
595 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700596 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700597 }
598 if (!response || !responseSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700599 return AMEDIA_ERROR_INVALID_PARAMETER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700600 }
601
602 Vector<uint8_t> mdResponse;
603 mdResponse.appendArray(response, responseSize);
604
605 Vector<uint8_t> unused;
606 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused));
607}
608
Marco Nelissen3425fd52014-05-14 11:12:46 -0700609EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700610media_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700611 AMediaDrmSecureStop *secureStops, size_t *numSecureStops) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700612
613 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700614 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700615 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700616 if (!numSecureStops) {
617 return AMEDIA_ERROR_INVALID_PARAMETER;
618 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700619 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops);
620 if (status != OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700621 *numSecureStops = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700622 return translateStatus(status);
623 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700624 if (*numSecureStops < mObj->mSecureStops.size()) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700625 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700626 }
627 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin();
628 size_t i = 0;
629 while (iter != mObj->mSecureStops.end()) {
630 secureStops[i].ptr = iter->array();
631 secureStops[i].length = iter->size();
632 ++iter;
633 ++i;
634 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700635 *numSecureStops = mObj->mSecureStops.size();
Marco Nelissene419d7c2014-05-15 14:17:25 -0700636 return AMEDIA_OK;
Jeff Tinker497ca092014-05-13 09:31:15 -0700637}
638
Marco Nelissen3425fd52014-05-14 11:12:46 -0700639EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700640media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700641 const AMediaDrmSecureStop *ssRelease) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700642
643 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700644 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700645 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700646 if (!ssRelease) {
647 return AMEDIA_ERROR_INVALID_PARAMETER;
648 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700649
650 Vector<uint8_t> release;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700651 release.appendArray(ssRelease->ptr, ssRelease->length);
Jeff Tinker497ca092014-05-13 09:31:15 -0700652 return translateStatus(mObj->mDrm->releaseSecureStops(release));
653}
654
655
Marco Nelissen3425fd52014-05-14 11:12:46 -0700656EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700657media_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700658 const char **propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700659
660 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700661 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700662 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700663 if (!propertyName || !propertyValue) {
664 return AMEDIA_ERROR_INVALID_PARAMETER;
665 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700666
667 status_t status = mObj->mDrm->getPropertyString(String8(propertyName),
668 mObj->mPropertyString);
669
670 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700671 *propertyValue = mObj->mPropertyString.string();
Jeff Tinker497ca092014-05-13 09:31:15 -0700672 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700673 *propertyValue = NULL;
Jeff Tinker497ca092014-05-13 09:31:15 -0700674 }
675 return translateStatus(status);
676}
677
Marco Nelissen3425fd52014-05-14 11:12:46 -0700678EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700679media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj,
Marco Nelissen18a1b592014-05-20 08:45:18 -0700680 const char *propertyName, AMediaDrmByteArray *propertyValue) {
Jeff Tinker497ca092014-05-13 09:31:15 -0700681 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700682 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700683 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700684 if (!propertyName || !propertyValue) {
685 return AMEDIA_ERROR_INVALID_PARAMETER;
686 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700687
688 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName),
689 mObj->mPropertyByteArray);
690
691 if (status == OK) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700692 propertyValue->ptr = mObj->mPropertyByteArray.array();
693 propertyValue->length = mObj->mPropertyByteArray.size();
Jeff Tinker497ca092014-05-13 09:31:15 -0700694 } else {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700695 propertyValue->ptr = NULL;
696 propertyValue->length = 0;
Jeff Tinker497ca092014-05-13 09:31:15 -0700697 }
698 return translateStatus(status);
699}
700
Marco Nelissen3425fd52014-05-14 11:12:46 -0700701EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700702media_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700703 const char *propertyName, const char *value) {
704 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700705 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700706 }
707
708 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName),
709 String8(value)));
710}
711
Marco Nelissen3425fd52014-05-14 11:12:46 -0700712EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700713media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700714 const char *propertyName, const uint8_t *value, size_t valueSize) {
715
716 Vector<uint8_t> byteArray;
717 byteArray.appendArray(value, valueSize);
718
Praveen Chavanc7822ef2018-10-04 10:39:33 -0700719 return translateStatus(mObj->mDrm->setPropertyByteArray(String8(propertyName),
Jeff Tinker497ca092014-05-13 09:31:15 -0700720 byteArray));
721}
722
723
Marco Nelissene419d7c2014-05-15 14:17:25 -0700724static media_status_t encrypt_decrypt_common(AMediaDrm *mObj,
Jeff Tinker497ca092014-05-13 09:31:15 -0700725 const AMediaDrmSessionId &sessionId,
726 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
727 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) {
728
729 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700730 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700731 }
732 List<idvec_t>::iterator iter;
733 if (!findId(mObj, sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700734 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700735 }
736
737 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm));
738 if (status != OK) {
739 return translateStatus(status);
740 }
741
742 Vector<uint8_t> keyIdVec;
743 const size_t kKeyIdSize = 16;
744 keyIdVec.appendArray(keyId, kKeyIdSize);
745
746 Vector<uint8_t> inputVec;
747 inputVec.appendArray(input, dataSize);
748
749 Vector<uint8_t> ivVec;
750 const size_t kIvSize = 16;
751 ivVec.appendArray(iv, kIvSize);
752
753 Vector<uint8_t> outputVec;
754 if (encrypt) {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800755 status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700756 } else {
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800757 status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec);
Jeff Tinker497ca092014-05-13 09:31:15 -0700758 }
759 if (status == OK) {
760 memcpy(output, outputVec.array(), outputVec.size());
761 }
762 return translateStatus(status);
763}
764
Marco Nelissen3425fd52014-05-14 11:12:46 -0700765EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700766media_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700767 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
768 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700769 if (!sessionId) {
770 return AMEDIA_ERROR_INVALID_PARAMETER;
771 }
772 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700773 input, output, dataSize, true);
774}
775
Marco Nelissen3425fd52014-05-14 11:12:46 -0700776EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700777media_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700778 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
779 const uint8_t *input, uint8_t *output, size_t dataSize) {
Marco Nelissen18a1b592014-05-20 08:45:18 -0700780 if (!sessionId) {
781 return AMEDIA_ERROR_INVALID_PARAMETER;
782 }
783 return encrypt_decrypt_common(mObj, *sessionId, cipherAlgorithm, keyId, iv,
Jeff Tinker497ca092014-05-13 09:31:15 -0700784 input, output, dataSize, false);
785}
786
Marco Nelissen3425fd52014-05-14 11:12:46 -0700787EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700788media_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700789 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
790 uint8_t *signature, size_t *signatureSize) {
791
792 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700793 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700794 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700795 if (!sessionId) {
796 return AMEDIA_ERROR_INVALID_PARAMETER;
797 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700798 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700799 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700800 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700801 }
802
803 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
804 if (status != OK) {
805 return translateStatus(status);
806 }
807
808 Vector<uint8_t> keyIdVec;
809 const size_t kKeyIdSize = 16;
810 keyIdVec.appendArray(keyId, kKeyIdSize);
811
812 Vector<uint8_t> messageVec;
813 messageVec.appendArray(message, messageSize);
814
815 Vector<uint8_t> signatureVec;
816 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec);
817 if (signatureVec.size() > *signatureSize) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700818 return AMEDIA_DRM_SHORT_BUFFER;
Jeff Tinker497ca092014-05-13 09:31:15 -0700819 }
820 if (status == OK) {
821 memcpy(signature, signatureVec.array(), signatureVec.size());
822 }
823 return translateStatus(status);
824}
825
Marco Nelissen3425fd52014-05-14 11:12:46 -0700826EXPORT
Marco Nelissen18a1b592014-05-20 08:45:18 -0700827media_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId *sessionId,
Jeff Tinker497ca092014-05-13 09:31:15 -0700828 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
829 const uint8_t *signature, size_t signatureSize) {
830
831 if (!mObj || mObj->mDrm == NULL) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700832 return AMEDIA_ERROR_INVALID_OBJECT;
Jeff Tinker497ca092014-05-13 09:31:15 -0700833 }
Marco Nelissen18a1b592014-05-20 08:45:18 -0700834 if (!sessionId) {
835 return AMEDIA_ERROR_INVALID_PARAMETER;
836 }
Jeff Tinker497ca092014-05-13 09:31:15 -0700837 List<idvec_t>::iterator iter;
Marco Nelissen18a1b592014-05-20 08:45:18 -0700838 if (!findId(mObj, *sessionId, iter)) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700839 return AMEDIA_DRM_SESSION_NOT_OPENED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700840 }
841
842 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm));
843 if (status != OK) {
844 return translateStatus(status);
845 }
846
847 Vector<uint8_t> keyIdVec;
848 const size_t kKeyIdSize = 16;
849 keyIdVec.appendArray(keyId, kKeyIdSize);
850
851 Vector<uint8_t> messageVec;
852 messageVec.appendArray(message, messageSize);
853
854 Vector<uint8_t> signatureVec;
855 signatureVec.appendArray(signature, signatureSize);
856
857 bool match;
858 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match);
859 if (status == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -0700860 return match ? AMEDIA_OK : AMEDIA_DRM_VERIFY_FAILED;
Jeff Tinker497ca092014-05-13 09:31:15 -0700861 }
862 return translateStatus(status);
863}
864
865} // extern "C"