1 /*
2 * Copyright (C) 2018 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 "hidl_ClearKeyPlugin"
19 #include <utils/Log.h>
20
21 #include <stdio.h>
22 #include <inttypes.h>
23
24 #include "DrmPlugin.h"
25 #include "ClearKeyDrmProperties.h"
26 #include "Session.h"
27 #include "TypeConvert.h"
28 #include "Utils.h"
29
30 namespace {
31 const std::string kKeySetIdPrefix("ckid");
32 const int kKeySetIdLength = 16;
33 const int kSecureStopIdStart = 100;
34 const std::string kOfflineLicense("\"type\":\"persistent-license\"");
35 const std::string kStreaming("Streaming");
36 const std::string kTemporaryLicense("\"type\":\"temporary\"");
37 const std::string kTrue("True");
38
39 const std::string kQueryKeyLicenseType("LicenseType");
40 // Value: "Streaming" or "Offline"
41 const std::string kQueryKeyPlayAllowed("PlayAllowed");
42 // Value: "True" or "False"
43 const std::string kQueryKeyRenewAllowed("RenewAllowed");
44 // Value: "True" or "False"
45
46 const int kSecureStopIdSize = 10;
47
uint32ToVector(uint32_t value)48 std::vector<uint8_t> uint32ToVector(uint32_t value) {
49 // 10 bytes to display max value 4294967295 + one byte null terminator
50 char buffer[kSecureStopIdSize];
51 memset(buffer, 0, kSecureStopIdSize);
52 snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
53 return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
54 }
55
56 }; // unnamed namespace
57
58 namespace android {
59 namespace hardware {
60 namespace drm {
61 namespace V1_2 {
62 namespace clearkey {
63
toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType)64 KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) {
65 switch (keyRequestType) {
66 case KeyRequestType_V1_1::NONE:
67 case KeyRequestType_V1_1::UPDATE:
68 return KeyRequestType::UNKNOWN;
69 default:
70 return static_cast<KeyRequestType>(keyRequestType);
71 }
72 }
73
DrmPlugin(SessionLibrary * sessionLibrary)74 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
75 : mSessionLibrary(sessionLibrary),
76 mOpenSessionOkCount(0),
77 mCloseSessionOkCount(0),
78 mCloseSessionNotOpenedCount(0),
79 mNextSecureStopId(kSecureStopIdStart),
80 mMockError(Status_V1_2::OK) {
81 mPlayPolicy.clear();
82 initProperties();
83 mSecureStops.clear();
84 mReleaseKeysMap.clear();
85 std::srand(std::time(nullptr));
86 }
87
initProperties()88 void DrmPlugin::initProperties() {
89 mStringProperties.clear();
90 mStringProperties[kVendorKey] = kVendorValue;
91 mStringProperties[kVersionKey] = kVersionValue;
92 mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
93 mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
94 mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
95 mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
96
97 std::vector<uint8_t> valueVector;
98 valueVector.clear();
99 valueVector.insert(valueVector.end(),
100 kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
101 mByteArrayProperties[kDeviceIdKey] = valueVector;
102
103 valueVector.clear();
104 valueVector.insert(valueVector.end(),
105 kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
106 mByteArrayProperties[kMetricsKey] = valueVector;
107 }
108
109 // The secure stop in ClearKey implementation is not installed securely.
110 // This function merely creates a test environment for testing secure stops APIs.
111 // The content in this secure stop is implementation dependent, the clearkey
112 // secureStop does not serve as a reference implementation.
installSecureStop(const hidl_vec<uint8_t> & sessionId)113 void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) {
114 ClearkeySecureStop clearkeySecureStop;
115 clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
116 clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
117
118 mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(
119 clearkeySecureStop.id, clearkeySecureStop));
120 }
121
openSession(openSession_cb _hidl_cb)122 Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
123 sp<Session> session = mSessionLibrary->createSession();
124 processMockError(session);
125 std::vector<uint8_t> sessionId = session->sessionId();
126
127 Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
128 _hidl_cb(status, toHidlVec(sessionId));
129 mOpenSessionOkCount++;
130 return Void();
131 }
132
openSession_1_1(SecurityLevel securityLevel,openSession_1_1_cb _hidl_cb)133 Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
134 openSession_1_1_cb _hidl_cb) {
135 sp<Session> session = mSessionLibrary->createSession();
136 processMockError(session);
137 std::vector<uint8_t> sessionId = session->sessionId();
138
139 Status status = setSecurityLevel(sessionId, securityLevel);
140 _hidl_cb(status, toHidlVec(sessionId));
141 mOpenSessionOkCount++;
142 return Void();
143 }
144
closeSession(const hidl_vec<uint8_t> & sessionId)145 Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
146 if (sessionId.size() == 0) {
147 return Status::BAD_VALUE;
148 }
149
150 sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
151 if (session.get()) {
152 if (session->getMockError() != Status_V1_2::OK) {
153 sendSessionLostState(sessionId);
154 return Status::ERROR_DRM_INVALID_STATE;
155 }
156 mCloseSessionOkCount++;
157 mSessionLibrary->destroySession(session);
158 return Status::OK;
159 }
160 mCloseSessionNotOpenedCount++;
161 return Status::ERROR_DRM_SESSION_NOT_OPENED;
162 }
163
getKeyRequestCommon(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,std::vector<uint8_t> * request,KeyRequestType_V1_1 * keyRequestType,std::string * defaultUrl)164 Status_V1_2 DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
165 const hidl_vec<uint8_t>& initData,
166 const hidl_string& mimeType,
167 KeyType keyType,
168 const hidl_vec<KeyValue>& optionalParameters,
169 std::vector<uint8_t> *request,
170 KeyRequestType_V1_1 *keyRequestType,
171 std::string *defaultUrl) {
172 UNUSED(optionalParameters);
173
174 // GetKeyRequestOfflineKeyTypeNotSupported() in vts 1.0 and 1.1 expects
175 // KeyType::OFFLINE to return ERROR_DRM_CANNOT_HANDLE in clearkey plugin.
176 // Those tests pass in an empty initData, we use the empty initData to
177 // signal such specific use case.
178 if (keyType == KeyType::OFFLINE && 0 == initData.size()) {
179 return Status_V1_2::ERROR_DRM_CANNOT_HANDLE;
180 }
181
182 *defaultUrl = "";
183 *keyRequestType = KeyRequestType_V1_1::UNKNOWN;
184 *request = std::vector<uint8_t>();
185
186 if (scope.size() == 0 ||
187 (keyType != KeyType::STREAMING &&
188 keyType != KeyType::OFFLINE &&
189 keyType != KeyType::RELEASE)) {
190 return Status_V1_2::BAD_VALUE;
191 }
192
193 const std::vector<uint8_t> scopeId = toVector(scope);
194 sp<Session> session;
195 if (keyType == KeyType::STREAMING || keyType == KeyType::OFFLINE) {
196 std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
197 session = mSessionLibrary->findSession(sessionId);
198 if (!session.get()) {
199 return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED;
200 } else if (session->getMockError() != Status_V1_2::OK) {
201 return session->getMockError();
202 }
203
204 *keyRequestType = KeyRequestType_V1_1::INITIAL;
205 }
206
207 Status_V1_2 status = static_cast<Status_V1_2>(
208 session->getKeyRequest(initData, mimeType, keyType, request));
209
210 if (keyType == KeyType::RELEASE) {
211 std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end());
212 std::string requestString(request->begin(), request->end());
213 if (requestString.find(kOfflineLicense) != std::string::npos) {
214 std::string emptyResponse;
215 std::string keySetIdString(keySetId.begin(), keySetId.end());
216 if (!mFileHandle.StoreLicense(keySetIdString,
217 DeviceFiles::kLicenseStateReleasing,
218 emptyResponse)) {
219 ALOGE("Problem releasing offline license");
220 return Status_V1_2::ERROR_DRM_UNKNOWN;
221 }
222 if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
223 sp<Session> session = mSessionLibrary->createSession();
224 mReleaseKeysMap[keySetIdString] = session->sessionId();
225 } else {
226 ALOGI("key is in use, ignore release request");
227 }
228 } else {
229 ALOGE("Offline license not found, nothing to release");
230 }
231 *keyRequestType = KeyRequestType_V1_1::RELEASE;
232 }
233 return status;
234 }
235
getKeyRequest(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,getKeyRequest_cb _hidl_cb)236 Return<void> DrmPlugin::getKeyRequest(
237 const hidl_vec<uint8_t>& scope,
238 const hidl_vec<uint8_t>& initData,
239 const hidl_string& mimeType,
240 KeyType keyType,
241 const hidl_vec<KeyValue>& optionalParameters,
242 getKeyRequest_cb _hidl_cb) {
243 UNUSED(optionalParameters);
244
245 KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
246 std::string defaultUrl("");
247 std::vector<uint8_t> request;
248 Status_V1_2 status = getKeyRequestCommon(
249 scope, initData, mimeType, keyType, optionalParameters,
250 &request, &keyRequestType, &defaultUrl);
251
252 _hidl_cb(toStatus_1_0(status), toHidlVec(request),
253 toKeyRequestType_V1_0(keyRequestType),
254 hidl_string(defaultUrl));
255 return Void();
256 }
257
getKeyRequest_1_1(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,getKeyRequest_1_1_cb _hidl_cb)258 Return<void> DrmPlugin::getKeyRequest_1_1(
259 const hidl_vec<uint8_t>& scope,
260 const hidl_vec<uint8_t>& initData,
261 const hidl_string& mimeType,
262 KeyType keyType,
263 const hidl_vec<KeyValue>& optionalParameters,
264 getKeyRequest_1_1_cb _hidl_cb) {
265 UNUSED(optionalParameters);
266
267 KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
268 std::string defaultUrl("");
269 std::vector<uint8_t> request;
270 Status_V1_2 status = getKeyRequestCommon(
271 scope, initData, mimeType, keyType, optionalParameters,
272 &request, &keyRequestType, &defaultUrl);
273
274 _hidl_cb(toStatus_1_0(status), toHidlVec(request),
275 keyRequestType, hidl_string(defaultUrl));
276 return Void();
277 }
278
getKeyRequest_1_2(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,getKeyRequest_1_2_cb _hidl_cb)279 Return<void> DrmPlugin::getKeyRequest_1_2(
280 const hidl_vec<uint8_t>& scope,
281 const hidl_vec<uint8_t>& initData,
282 const hidl_string& mimeType,
283 KeyType keyType,
284 const hidl_vec<KeyValue>& optionalParameters,
285 getKeyRequest_1_2_cb _hidl_cb) {
286 UNUSED(optionalParameters);
287
288 KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
289 std::string defaultUrl("");
290 std::vector<uint8_t> request;
291 Status_V1_2 status = getKeyRequestCommon(
292 scope, initData, mimeType, keyType, optionalParameters,
293 &request, &keyRequestType, &defaultUrl);
294
295 _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl));
296 return Void();
297 }
298
setPlayPolicy()299 void DrmPlugin::setPlayPolicy() {
300 mPlayPolicy.clear();
301
302 KeyValue policy;
303 policy.key = kQueryKeyLicenseType;
304 policy.value = kStreaming;
305 mPlayPolicy.push_back(policy);
306
307 policy.key = kQueryKeyPlayAllowed;
308 policy.value = kTrue;
309 mPlayPolicy.push_back(policy);
310
311 policy.key = kQueryKeyRenewAllowed;
312 mPlayPolicy.push_back(policy);
313 }
314
makeKeySetId(std::string * keySetId)315 bool DrmPlugin::makeKeySetId(std::string* keySetId) {
316 if (!keySetId) {
317 ALOGE("keySetId destination not provided");
318 return false;
319 }
320 std::vector<uint8_t> ksid(kKeySetIdPrefix.begin(), kKeySetIdPrefix.end());
321 ksid.resize(kKeySetIdLength);
322 std::vector<uint8_t> randomData((kKeySetIdLength - kKeySetIdPrefix.size()) / 2, 0);
323
324 while (keySetId->empty()) {
325 for (auto itr = randomData.begin(); itr != randomData.end(); ++itr) {
326 *itr = std::rand() % 0xff;
327 }
328 *keySetId = kKeySetIdPrefix + ByteArrayToHexString(
329 reinterpret_cast<const uint8_t*>(randomData.data()), randomData.size());
330 if (mFileHandle.LicenseExists(*keySetId)) {
331 // collision, regenerate
332 ALOGV("Retry generating KeySetId");
333 keySetId->clear();
334 }
335 }
336 return true;
337 }
338
provideKeyResponse(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & response,provideKeyResponse_cb _hidl_cb)339 Return<void> DrmPlugin::provideKeyResponse(
340 const hidl_vec<uint8_t>& scope,
341 const hidl_vec<uint8_t>& response,
342 provideKeyResponse_cb _hidl_cb) {
343 if (scope.size() == 0 || response.size() == 0) {
344 // Returns empty keySetId
345 _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
346 return Void();
347 }
348
349 std::string responseString(
350 reinterpret_cast<const char*>(response.data()), response.size());
351 const std::vector<uint8_t> scopeId = toVector(scope);
352 std::vector<uint8_t> sessionId;
353 std::string keySetId;
354
355 Status status = Status::OK;
356 bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos;
357 bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0);
358 if (isRelease) {
359 keySetId.assign(scopeId.begin(), scopeId.end());
360
361 auto iter = mReleaseKeysMap.find(std::string(keySetId.begin(), keySetId.end()));
362 if (iter != mReleaseKeysMap.end()) {
363 sessionId.assign(iter->second.begin(), iter->second.end());
364 }
365 } else {
366 sessionId.assign(scopeId.begin(), scopeId.end());
367 // non offline license returns empty keySetId
368 keySetId.clear();
369 }
370
371 sp<Session> session = mSessionLibrary->findSession(sessionId);
372 if (!session.get()) {
373 _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
374 return Void();
375 }
376 setPlayPolicy();
377
378 status = session->provideKeyResponse(response);
379 if (status == Status::OK) {
380 if (isOfflineLicense) {
381 if (isRelease) {
382 mFileHandle.DeleteLicense(keySetId);
383 } else {
384 if (!makeKeySetId(&keySetId)) {
385 _hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>());
386 return Void();
387 }
388
389 bool ok = mFileHandle.StoreLicense(
390 keySetId,
391 DeviceFiles::kLicenseStateActive,
392 std::string(response.begin(), response.end()));
393 if (!ok) {
394 ALOGE("Failed to store offline license");
395 }
396 }
397 }
398
399 // Test calling AMediaDrm listeners.
400 sendEvent(EventType::VENDOR_DEFINED, sessionId, sessionId);
401
402 sendExpirationUpdate(sessionId, 100);
403
404 std::vector<KeyStatus_V1_2> keysStatus;
405 KeyStatus_V1_2 keyStatus;
406
407 std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
408 keyStatus.keyId = keyId1;
409 keyStatus.type = V1_2::KeyStatusType::USABLE;
410 keysStatus.push_back(keyStatus);
411
412 std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
413 keyStatus.keyId = keyId2;
414 keyStatus.type = V1_2::KeyStatusType::EXPIRED;
415 keysStatus.push_back(keyStatus);
416
417 std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 };
418 keyStatus.keyId = keyId3;
419 keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE;
420 keysStatus.push_back(keyStatus);
421
422 sendKeysChange_1_2(sessionId, keysStatus, true);
423
424 installSecureStop(sessionId);
425 } else {
426 ALOGE("provideKeyResponse returns error=%d", status);
427 }
428
429 std::vector<uint8_t> keySetIdVec(keySetId.begin(), keySetId.end());
430 _hidl_cb(status, toHidlVec(keySetIdVec));
431 return Void();
432 }
433
restoreKeys(const hidl_vec<uint8_t> & sessionId,const hidl_vec<uint8_t> & keySetId)434 Return<Status> DrmPlugin::restoreKeys(
435 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& keySetId) {
436 if (sessionId.size() == 0 || keySetId.size() == 0) {
437 return Status::BAD_VALUE;
438 }
439
440 DeviceFiles::LicenseState licenseState;
441 std::string offlineLicense;
442 Status status = Status::OK;
443 if (!mFileHandle.RetrieveLicense(std::string(keySetId.begin(), keySetId.end()),
444 &licenseState, &offlineLicense)) {
445 ALOGE("Failed to restore offline license");
446 return Status::ERROR_DRM_NO_LICENSE;
447 }
448
449 if (DeviceFiles::kLicenseStateUnknown == licenseState ||
450 DeviceFiles::kLicenseStateReleasing == licenseState) {
451 ALOGE("Invalid license state=%d", licenseState);
452 return Status::ERROR_DRM_NO_LICENSE;
453 }
454
455 sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
456 if (!session.get()) {
457 return Status::ERROR_DRM_SESSION_NOT_OPENED;
458 }
459 status = session->provideKeyResponse(std::vector<uint8_t>(offlineLicense.begin(),
460 offlineLicense.end()));
461 if (status != Status::OK) {
462 ALOGE("Failed to restore keys");
463 }
464 return status;
465 }
466
getPropertyString(const hidl_string & propertyName,getPropertyString_cb _hidl_cb)467 Return<void> DrmPlugin::getPropertyString(
468 const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
469 std::string name(propertyName.c_str());
470 std::string value;
471
472 if (name == kVendorKey) {
473 value = mStringProperties[kVendorKey];
474 } else if (name == kVersionKey) {
475 value = mStringProperties[kVersionKey];
476 } else if (name == kPluginDescriptionKey) {
477 value = mStringProperties[kPluginDescriptionKey];
478 } else if (name == kAlgorithmsKey) {
479 value = mStringProperties[kAlgorithmsKey];
480 } else if (name == kListenerTestSupportKey) {
481 value = mStringProperties[kListenerTestSupportKey];
482 } else if (name == kDrmErrorTestKey) {
483 value = mStringProperties[kDrmErrorTestKey];
484 } else {
485 ALOGE("App requested unknown string property %s", name.c_str());
486 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
487 return Void();
488 }
489 _hidl_cb(Status::OK, value.c_str());
490 return Void();
491 }
492
getPropertyByteArray(const hidl_string & propertyName,getPropertyByteArray_cb _hidl_cb)493 Return<void> DrmPlugin::getPropertyByteArray(
494 const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
495 std::map<std::string, std::vector<uint8_t> >::iterator itr =
496 mByteArrayProperties.find(std::string(propertyName.c_str()));
497 if (itr == mByteArrayProperties.end()) {
498 ALOGE("App requested unknown property: %s", propertyName.c_str());
499 _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
500 return Void();
501 }
502 _hidl_cb(Status::OK, itr->second);
503 return Void();
504
505 }
506
setPropertyString(const hidl_string & name,const hidl_string & value)507 Return<Status> DrmPlugin::setPropertyString(
508 const hidl_string& name, const hidl_string& value) {
509 std::string immutableKeys;
510 immutableKeys.append(kAlgorithmsKey + ",");
511 immutableKeys.append(kPluginDescriptionKey + ",");
512 immutableKeys.append(kVendorKey + ",");
513 immutableKeys.append(kVersionKey + ",");
514
515 std::string key = std::string(name.c_str());
516 if (immutableKeys.find(key) != std::string::npos) {
517 ALOGD("Cannot set immutable property: %s", key.c_str());
518 return Status::BAD_VALUE;
519 }
520
521 std::map<std::string, std::string>::iterator itr =
522 mStringProperties.find(key);
523 if (itr == mStringProperties.end()) {
524 ALOGE("Cannot set undefined property string, key=%s", key.c_str());
525 return Status::BAD_VALUE;
526 }
527
528 if (name == kDrmErrorTestKey) {
529 if (value == kResourceContentionValue) {
530 mMockError = Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION;
531 } else if (value == kLostStateValue) {
532 mMockError = Status_V1_2::ERROR_DRM_SESSION_LOST_STATE;
533 } else if (value == kFrameTooLargeValue) {
534 mMockError = Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE;
535 } else if (value == kInvalidStateValue) {
536 mMockError = Status_V1_2::ERROR_DRM_INVALID_STATE;
537 } else {
538 mMockError = Status_V1_2::ERROR_DRM_UNKNOWN;
539 }
540 }
541
542 mStringProperties[key] = std::string(value.c_str());
543 return Status::OK;
544 }
545
setPropertyByteArray(const hidl_string & name,const hidl_vec<uint8_t> & value)546 Return<Status> DrmPlugin::setPropertyByteArray(
547 const hidl_string& name, const hidl_vec<uint8_t>& value) {
548 UNUSED(value);
549 if (name == kDeviceIdKey) {
550 ALOGD("Cannot set immutable property: %s", name.c_str());
551 return Status::BAD_VALUE;
552 } else if (name == kClientIdKey) {
553 mByteArrayProperties[kClientIdKey] = toVector(value);
554 return Status::OK;
555 }
556
557 // Setting of undefined properties is not supported
558 ALOGE("Failed to set property byte array, key=%s", name.c_str());
559 return Status::ERROR_DRM_CANNOT_HANDLE;
560 }
561
queryKeyStatus(const hidl_vec<uint8_t> & sessionId,queryKeyStatus_cb _hidl_cb)562 Return<void> DrmPlugin::queryKeyStatus(
563 const hidl_vec<uint8_t>& sessionId,
564 queryKeyStatus_cb _hidl_cb) {
565
566 if (sessionId.size() == 0) {
567 // Returns empty key status KeyValue pair
568 _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
569 return Void();
570 }
571
572 std::vector<KeyValue> infoMapVec;
573 infoMapVec.clear();
574
575 KeyValue keyValuePair;
576 for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
577 keyValuePair.key = mPlayPolicy[i].key;
578 keyValuePair.value = mPlayPolicy[i].value;
579 infoMapVec.push_back(keyValuePair);
580 }
581 _hidl_cb(Status::OK, toHidlVec(infoMapVec));
582 return Void();
583 }
584
getNumberOfSessions(getNumberOfSessions_cb _hidl_cb)585 Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
586 uint32_t currentSessions = mSessionLibrary->numOpenSessions();
587 uint32_t maxSessions = 10;
588 _hidl_cb(Status::OK, currentSessions, maxSessions);
589 return Void();
590 }
591
getSecurityLevel(const hidl_vec<uint8_t> & sessionId,getSecurityLevel_cb _hidl_cb)592 Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
593 getSecurityLevel_cb _hidl_cb) {
594 if (sessionId.size() == 0) {
595 _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
596 return Void();
597 }
598
599 std::vector<uint8_t> sid = toVector(sessionId);
600 sp<Session> session = mSessionLibrary->findSession(sid);
601 if (!session.get()) {
602 _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
603 return Void();
604 }
605
606 std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
607 mSecurityLevel.find(sid);
608 if (itr == mSecurityLevel.end()) {
609 ALOGE("Session id not found");
610 _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
611 return Void();
612 }
613
614 _hidl_cb(Status::OK, itr->second);
615 return Void();
616 }
617
setSecurityLevel(const hidl_vec<uint8_t> & sessionId,SecurityLevel level)618 Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
619 SecurityLevel level) {
620 if (sessionId.size() == 0) {
621 ALOGE("Invalid empty session id");
622 return Status::BAD_VALUE;
623 }
624
625 if (level > SecurityLevel::SW_SECURE_CRYPTO) {
626 ALOGE("Cannot set security level > max");
627 return Status::ERROR_DRM_CANNOT_HANDLE;
628 }
629
630 std::vector<uint8_t> sid = toVector(sessionId);
631 sp<Session> session = mSessionLibrary->findSession(sid);
632 if (!session.get()) {
633 return Status::ERROR_DRM_SESSION_NOT_OPENED;
634 }
635
636 std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
637 mSecurityLevel.find(sid);
638 if (itr != mSecurityLevel.end()) {
639 mSecurityLevel[sid] = level;
640 } else {
641 if (!mSecurityLevel.insert(
642 std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
643 ALOGE("Failed to set security level");
644 return Status::ERROR_DRM_INVALID_STATE;
645 }
646 }
647 return Status::OK;
648 }
649
getMetrics(getMetrics_cb _hidl_cb)650 Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
651 // Set the open session count metric.
652 DrmMetricGroup::Attribute openSessionOkAttribute = {
653 "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
654 };
655 DrmMetricGroup::Value openSessionMetricValue = {
656 "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
657 };
658 DrmMetricGroup::Metric openSessionMetric = {
659 "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
660 };
661
662 // Set the close session count metric.
663 DrmMetricGroup::Attribute closeSessionOkAttribute = {
664 "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
665 };
666 DrmMetricGroup::Value closeSessionMetricValue = {
667 "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
668 };
669 DrmMetricGroup::Metric closeSessionMetric = {
670 "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
671 };
672
673 // Set the close session, not opened metric.
674 DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
675 "status", DrmMetricGroup::ValueType::INT64_TYPE,
676 (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
677 };
678 DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
679 "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
680 };
681 DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
682 "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
683 };
684
685 DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
686 closeSessionNotOpenedMetric } };
687
688 _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
689 return Void();
690 }
691
getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb)692 Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) {
693 std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
694 std::vector<KeySetId> keySetIds;
695 if (mMockError != Status_V1_2::OK) {
696 _hidl_cb(toStatus_1_0(mMockError), keySetIds);
697 return Void();
698 }
699 for (const auto& name : licenseNames) {
700 std::vector<uint8_t> keySetId(name.begin(), name.end());
701 keySetIds.push_back(keySetId);
702 }
703 _hidl_cb(Status::OK, keySetIds);
704 return Void();
705 }
706
707
removeOfflineLicense(const KeySetId & keySetId)708 Return<Status> DrmPlugin::removeOfflineLicense(const KeySetId& keySetId) {
709 if (mMockError != Status_V1_2::OK) {
710 return toStatus_1_0(mMockError);
711 }
712 std::string licenseName(keySetId.begin(), keySetId.end());
713 if (mFileHandle.DeleteLicense(licenseName)) {
714 return Status::OK;
715 }
716 return Status::BAD_VALUE;
717 }
718
getOfflineLicenseState(const KeySetId & keySetId,getOfflineLicenseState_cb _hidl_cb)719 Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId,
720 getOfflineLicenseState_cb _hidl_cb) {
721 std::string licenseName(keySetId.begin(), keySetId.end());
722 DeviceFiles::LicenseState state;
723 std::string license;
724 OfflineLicenseState hLicenseState;
725 if (mMockError != Status_V1_2::OK) {
726 _hidl_cb(toStatus_1_0(mMockError), OfflineLicenseState::UNKNOWN);
727 } else if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) {
728 switch (state) {
729 case DeviceFiles::kLicenseStateActive:
730 hLicenseState = OfflineLicenseState::USABLE;
731 break;
732 case DeviceFiles::kLicenseStateReleasing:
733 hLicenseState = OfflineLicenseState::INACTIVE;
734 break;
735 case DeviceFiles::kLicenseStateUnknown:
736 hLicenseState = OfflineLicenseState::UNKNOWN;
737 break;
738 }
739 _hidl_cb(Status::OK, hLicenseState);
740 } else {
741 _hidl_cb(Status::BAD_VALUE, OfflineLicenseState::UNKNOWN);
742 }
743 return Void();
744 }
745
getSecureStops(getSecureStops_cb _hidl_cb)746 Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
747 std::vector<SecureStop> stops;
748 for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
749 ClearkeySecureStop clearkeyStop = itr->second;
750 std::vector<uint8_t> stopVec;
751 stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
752 stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
753
754 SecureStop stop;
755 stop.opaqueData = toHidlVec(stopVec);
756 stops.push_back(stop);
757 }
758 _hidl_cb(Status::OK, stops);
759 return Void();
760 }
761
getSecureStop(const hidl_vec<uint8_t> & secureStopId,getSecureStop_cb _hidl_cb)762 Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
763 getSecureStop_cb _hidl_cb) {
764 SecureStop stop;
765 auto itr = mSecureStops.find(toVector(secureStopId));
766 if (itr != mSecureStops.end()) {
767 ClearkeySecureStop clearkeyStop = itr->second;
768 std::vector<uint8_t> stopVec;
769 stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
770 stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
771
772 stop.opaqueData = toHidlVec(stopVec);
773 _hidl_cb(Status::OK, stop);
774 } else {
775 _hidl_cb(Status::BAD_VALUE, stop);
776 }
777
778 return Void();
779 }
780
releaseSecureStop(const hidl_vec<uint8_t> & secureStopId)781 Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
782 return removeSecureStop(secureStopId);
783 }
784
releaseAllSecureStops()785 Return<Status> DrmPlugin::releaseAllSecureStops() {
786 return removeAllSecureStops();
787 }
788
getSecureStopIds(getSecureStopIds_cb _hidl_cb)789 Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
790 std::vector<SecureStopId> ids;
791 for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
792 ids.push_back(itr->first);
793 }
794
795 _hidl_cb(Status::OK, toHidlVec(ids));
796 return Void();
797 }
798
releaseSecureStops(const SecureStopRelease & ssRelease)799 Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
800 if (ssRelease.opaqueData.size() == 0) {
801 return Status::BAD_VALUE;
802 }
803
804 Status status = Status::OK;
805 std::vector<uint8_t> input = toVector(ssRelease.opaqueData);
806
807 // The format of opaqueData is shared between the server
808 // and the drm service. The clearkey implementation consists of:
809 // count - number of secure stops
810 // list of fixed length secure stops
811 size_t countBufferSize = sizeof(uint32_t);
812 uint32_t count = 0;
813 sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
814
815 // Avoid divide by 0 below.
816 if (count == 0) {
817 return Status::BAD_VALUE;
818 }
819
820 size_t secureStopSize = (input.size() - countBufferSize) / count;
821 uint8_t buffer[secureStopSize];
822 size_t offset = countBufferSize; // skip the count
823 for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
824 memcpy(buffer, input.data() + offset, secureStopSize);
825 std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
826
827 status = removeSecureStop(toHidlVec(id));
828 if (Status::OK != status) break;
829 }
830
831 return status;
832 }
833
removeSecureStop(const hidl_vec<uint8_t> & secureStopId)834 Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
835 if (1 != mSecureStops.erase(toVector(secureStopId))) {
836 return Status::BAD_VALUE;
837 }
838 return Status::OK;
839 }
840
removeAllSecureStops()841 Return<Status> DrmPlugin::removeAllSecureStops() {
842 mSecureStops.clear();
843 mNextSecureStopId = kSecureStopIdStart;
844 return Status::OK;
845 }
846
847 } // namespace clearkey
848 } // namespace V1_2
849 } // namespace drm
850 } // namespace hardware
851 } // namespace android
852