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 29 namespace { 30 const int kSecureStopIdStart = 100; 31 const std::string kStreaming("Streaming"); 32 const std::string kOffline("Offline"); 33 const std::string kTrue("True"); 34 35 const std::string kQueryKeyLicenseType("LicenseType"); 36 // Value: "Streaming" or "Offline" 37 const std::string kQueryKeyPlayAllowed("PlayAllowed"); 38 // Value: "True" or "False" 39 const std::string kQueryKeyRenewAllowed("RenewAllowed"); 40 // Value: "True" or "False" 41 42 const int kSecureStopIdSize = 10; 43 44 std::vector<uint8_t> uint32ToVector(uint32_t value) { 45 // 10 bytes to display max value 4294967295 + one byte null terminator 46 char buffer[kSecureStopIdSize]; 47 memset(buffer, 0, kSecureStopIdSize); 48 snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value); 49 return std::vector<uint8_t>(buffer, buffer + sizeof(buffer)); 50 } 51 52 }; // unnamed namespace 53 54 namespace android { 55 namespace hardware { 56 namespace drm { 57 namespace V1_1 { 58 namespace clearkey { 59 60 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary) 61 : mSessionLibrary(sessionLibrary), 62 mOpenSessionOkCount(0), 63 mCloseSessionOkCount(0), 64 mCloseSessionNotOpenedCount(0), 65 mNextSecureStopId(kSecureStopIdStart) { 66 mPlayPolicy.clear(); 67 initProperties(); 68 mSecureStops.clear(); 69 } 70 71 void DrmPlugin::initProperties() { 72 mStringProperties.clear(); 73 mStringProperties[kVendorKey] = kVendorValue; 74 mStringProperties[kVersionKey] = kVersionValue; 75 mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue; 76 mStringProperties[kAlgorithmsKey] = kAlgorithmsValue; 77 mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue; 78 79 std::vector<uint8_t> valueVector; 80 valueVector.clear(); 81 valueVector.insert(valueVector.end(), 82 kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t)); 83 mByteArrayProperties[kDeviceIdKey] = valueVector; 84 85 valueVector.clear(); 86 valueVector.insert(valueVector.end(), 87 kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t)); 88 mByteArrayProperties[kMetricsKey] = valueVector; 89 } 90 91 // The secure stop in ClearKey implementation is not installed securely. 92 // This function merely creates a test environment for testing secure stops APIs. 93 // The content in this secure stop is implementation dependent, the clearkey 94 // secureStop does not serve as a reference implementation. 95 void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) { 96 ClearkeySecureStop clearkeySecureStop; 97 clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId); 98 clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end()); 99 100 mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>( 101 clearkeySecureStop.id, clearkeySecureStop)); 102 } 103 104 Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) { 105 sp<Session> session = mSessionLibrary->createSession(); 106 std::vector<uint8_t> sessionId = session->sessionId(); 107 108 Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO); 109 _hidl_cb(status, toHidlVec(sessionId)); 110 mOpenSessionOkCount++; 111 return Void(); 112 } 113 114 Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel, 115 openSession_1_1_cb _hidl_cb) { 116 sp<Session> session = mSessionLibrary->createSession(); 117 std::vector<uint8_t> sessionId = session->sessionId(); 118 119 Status status = setSecurityLevel(sessionId, securityLevel); 120 _hidl_cb(status, toHidlVec(sessionId)); 121 mOpenSessionOkCount++; 122 return Void(); 123 } 124 125 Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) { 126 if (sessionId.size() == 0) { 127 return Status::BAD_VALUE; 128 } 129 130 sp<Session> session = mSessionLibrary->findSession(toVector(sessionId)); 131 if (session.get()) { 132 mCloseSessionOkCount++; 133 mSessionLibrary->destroySession(session); 134 return Status::OK; 135 } 136 mCloseSessionNotOpenedCount++; 137 return Status::ERROR_DRM_SESSION_NOT_OPENED; 138 } 139 140 Status DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope, 141 const hidl_vec<uint8_t>& initData, 142 const hidl_string& mimeType, 143 KeyType keyType, 144 const hidl_vec<KeyValue>& optionalParameters, 145 std::vector<uint8_t> *request, 146 KeyRequestType *keyRequestType, 147 std::string *defaultUrl) { 148 UNUSED(optionalParameters); 149 150 *defaultUrl = ""; 151 *keyRequestType = KeyRequestType::UNKNOWN; 152 *request = std::vector<uint8_t>(); 153 154 if (scope.size() == 0) { 155 return Status::BAD_VALUE; 156 } 157 158 if (keyType != KeyType::STREAMING) { 159 return Status::ERROR_DRM_CANNOT_HANDLE; 160 } 161 162 sp<Session> session = mSessionLibrary->findSession(toVector(scope)); 163 if (!session.get()) { 164 return Status::ERROR_DRM_SESSION_NOT_OPENED; 165 } 166 167 Status status = session->getKeyRequest(initData, mimeType, request); 168 *keyRequestType = KeyRequestType::INITIAL; 169 return status; 170 } 171 172 Return<void> DrmPlugin::getKeyRequest( 173 const hidl_vec<uint8_t>& scope, 174 const hidl_vec<uint8_t>& initData, 175 const hidl_string& mimeType, 176 KeyType keyType, 177 const hidl_vec<KeyValue>& optionalParameters, 178 getKeyRequest_cb _hidl_cb) { 179 UNUSED(optionalParameters); 180 181 KeyRequestType keyRequestType = KeyRequestType::UNKNOWN; 182 std::string defaultUrl(""); 183 std::vector<uint8_t> request; 184 Status status = getKeyRequestCommon( 185 scope, initData, mimeType, keyType, optionalParameters, 186 &request, &keyRequestType, &defaultUrl); 187 188 _hidl_cb(status, toHidlVec(request), 189 static_cast<drm::V1_0::KeyRequestType>(keyRequestType), 190 hidl_string(defaultUrl)); 191 return Void(); 192 } 193 194 Return<void> DrmPlugin::getKeyRequest_1_1( 195 const hidl_vec<uint8_t>& scope, 196 const hidl_vec<uint8_t>& initData, 197 const hidl_string& mimeType, 198 KeyType keyType, 199 const hidl_vec<KeyValue>& optionalParameters, 200 getKeyRequest_1_1_cb _hidl_cb) { 201 UNUSED(optionalParameters); 202 203 KeyRequestType keyRequestType = KeyRequestType::UNKNOWN; 204 std::string defaultUrl(""); 205 std::vector<uint8_t> request; 206 Status status = getKeyRequestCommon( 207 scope, initData, mimeType, keyType, optionalParameters, 208 &request, &keyRequestType, &defaultUrl); 209 210 _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl)); 211 return Void(); 212 } 213 214 void DrmPlugin::setPlayPolicy() { 215 mPlayPolicy.clear(); 216 217 KeyValue policy; 218 policy.key = kQueryKeyLicenseType; 219 policy.value = kStreaming; 220 mPlayPolicy.push_back(policy); 221 222 policy.key = kQueryKeyPlayAllowed; 223 policy.value = kTrue; 224 mPlayPolicy.push_back(policy); 225 226 policy.key = kQueryKeyRenewAllowed; 227 mPlayPolicy.push_back(policy); 228 } 229 230 Return<void> DrmPlugin::provideKeyResponse( 231 const hidl_vec<uint8_t>& scope, 232 const hidl_vec<uint8_t>& response, 233 provideKeyResponse_cb _hidl_cb) { 234 if (scope.size() == 0 || response.size() == 0) { 235 // Returns empty keySetId 236 _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>()); 237 return Void(); 238 } 239 240 sp<Session> session = mSessionLibrary->findSession(toVector(scope)); 241 if (!session.get()) { 242 _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>()); 243 return Void(); 244 } 245 246 setPlayPolicy(); 247 std::vector<uint8_t> keySetId; 248 Status status = session->provideKeyResponse(response); 249 if (status == Status::OK) { 250 // This is for testing AMediaDrm_setOnEventListener only. 251 sendEvent(EventType::VENDOR_DEFINED, 0, scope); 252 keySetId.clear(); 253 } 254 255 installSecureStop(scope); 256 257 // Returns status and empty keySetId 258 _hidl_cb(status, toHidlVec(keySetId)); 259 return Void(); 260 } 261 262 Return<void> DrmPlugin::getPropertyString( 263 const hidl_string& propertyName, getPropertyString_cb _hidl_cb) { 264 std::string name(propertyName.c_str()); 265 std::string value; 266 267 if (name == kVendorKey) { 268 value = mStringProperties[kVendorKey]; 269 } else if (name == kVersionKey) { 270 value = mStringProperties[kVersionKey]; 271 } else if (name == kPluginDescriptionKey) { 272 value = mStringProperties[kPluginDescriptionKey]; 273 } else if (name == kAlgorithmsKey) { 274 value = mStringProperties[kAlgorithmsKey]; 275 } else if (name == kListenerTestSupportKey) { 276 value = mStringProperties[kListenerTestSupportKey]; 277 } else { 278 ALOGE("App requested unknown string property %s", name.c_str()); 279 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, ""); 280 return Void(); 281 } 282 _hidl_cb(Status::OK, value.c_str()); 283 return Void(); 284 } 285 286 Return<void> DrmPlugin::getPropertyByteArray( 287 const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) { 288 std::map<std::string, std::vector<uint8_t> >::iterator itr = 289 mByteArrayProperties.find(std::string(propertyName.c_str())); 290 if (itr == mByteArrayProperties.end()) { 291 ALOGE("App requested unknown property: %s", propertyName.c_str()); 292 _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>()); 293 return Void(); 294 } 295 _hidl_cb(Status::OK, itr->second); 296 return Void(); 297 298 } 299 300 Return<Status> DrmPlugin::setPropertyString( 301 const hidl_string& name, const hidl_string& value) { 302 std::string immutableKeys; 303 immutableKeys.append(kAlgorithmsKey + ","); 304 immutableKeys.append(kPluginDescriptionKey + ","); 305 immutableKeys.append(kVendorKey + ","); 306 immutableKeys.append(kVersionKey + ","); 307 308 std::string key = std::string(name.c_str()); 309 if (immutableKeys.find(key) != std::string::npos) { 310 ALOGD("Cannot set immutable property: %s", key.c_str()); 311 return Status::BAD_VALUE; 312 } 313 314 std::map<std::string, std::string>::iterator itr = 315 mStringProperties.find(key); 316 if (itr == mStringProperties.end()) { 317 ALOGE("Cannot set undefined property string, key=%s", key.c_str()); 318 return Status::BAD_VALUE; 319 } 320 321 mStringProperties[key] = std::string(value.c_str()); 322 return Status::OK; 323 } 324 325 Return<Status> DrmPlugin::setPropertyByteArray( 326 const hidl_string& name, const hidl_vec<uint8_t>& value) { 327 UNUSED(value); 328 if (name == kDeviceIdKey) { 329 ALOGD("Cannot set immutable property: %s", name.c_str()); 330 return Status::BAD_VALUE; 331 } 332 333 // Setting of undefined properties is not supported 334 ALOGE("Failed to set property byte array, key=%s", name.c_str()); 335 return Status::ERROR_DRM_CANNOT_HANDLE; 336 } 337 338 Return<void> DrmPlugin::queryKeyStatus( 339 const hidl_vec<uint8_t>& sessionId, 340 queryKeyStatus_cb _hidl_cb) { 341 342 if (sessionId.size() == 0) { 343 // Returns empty key status KeyValue pair 344 _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>()); 345 return Void(); 346 } 347 348 std::vector<KeyValue> infoMapVec; 349 infoMapVec.clear(); 350 351 KeyValue keyValuePair; 352 for (size_t i = 0; i < mPlayPolicy.size(); ++i) { 353 keyValuePair.key = mPlayPolicy[i].key; 354 keyValuePair.value = mPlayPolicy[i].value; 355 infoMapVec.push_back(keyValuePair); 356 } 357 _hidl_cb(Status::OK, toHidlVec(infoMapVec)); 358 return Void(); 359 } 360 361 Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) { 362 uint32_t currentSessions = mSessionLibrary->numOpenSessions(); 363 uint32_t maxSessions = 10; 364 _hidl_cb(Status::OK, currentSessions, maxSessions); 365 return Void(); 366 } 367 368 Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId, 369 getSecurityLevel_cb _hidl_cb) { 370 if (sessionId.size() == 0) { 371 _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN); 372 return Void(); 373 } 374 375 std::vector<uint8_t> sid = toVector(sessionId); 376 sp<Session> session = mSessionLibrary->findSession(sid); 377 if (!session.get()) { 378 _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN); 379 return Void(); 380 } 381 382 std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr = 383 mSecurityLevel.find(sid); 384 if (itr == mSecurityLevel.end()) { 385 ALOGE("Session id not found"); 386 _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN); 387 return Void(); 388 } 389 390 _hidl_cb(Status::OK, itr->second); 391 return Void(); 392 } 393 394 Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId, 395 SecurityLevel level) { 396 if (sessionId.size() == 0) { 397 ALOGE("Invalid empty session id"); 398 return Status::BAD_VALUE; 399 } 400 401 if (level > SecurityLevel::SW_SECURE_CRYPTO) { 402 ALOGE("Cannot set security level > max"); 403 return Status::ERROR_DRM_CANNOT_HANDLE; 404 } 405 406 std::vector<uint8_t> sid = toVector(sessionId); 407 sp<Session> session = mSessionLibrary->findSession(sid); 408 if (!session.get()) { 409 return Status::ERROR_DRM_SESSION_NOT_OPENED; 410 } 411 412 std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr = 413 mSecurityLevel.find(sid); 414 if (itr != mSecurityLevel.end()) { 415 mSecurityLevel[sid] = level; 416 } else { 417 if (!mSecurityLevel.insert( 418 std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) { 419 ALOGE("Failed to set security level"); 420 return Status::ERROR_DRM_INVALID_STATE; 421 } 422 } 423 return Status::OK; 424 } 425 426 Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) { 427 // Set the open session count metric. 428 DrmMetricGroup::Attribute openSessionOkAttribute = { 429 "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, "" 430 }; 431 DrmMetricGroup::Value openSessionMetricValue = { 432 "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, "" 433 }; 434 DrmMetricGroup::Metric openSessionMetric = { 435 "open_session", { openSessionOkAttribute }, { openSessionMetricValue } 436 }; 437 438 // Set the close session count metric. 439 DrmMetricGroup::Attribute closeSessionOkAttribute = { 440 "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, "" 441 }; 442 DrmMetricGroup::Value closeSessionMetricValue = { 443 "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, "" 444 }; 445 DrmMetricGroup::Metric closeSessionMetric = { 446 "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue } 447 }; 448 449 // Set the close session, not opened metric. 450 DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = { 451 "status", DrmMetricGroup::ValueType::INT64_TYPE, 452 (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, "" 453 }; 454 DrmMetricGroup::Value closeSessionNotOpenedMetricValue = { 455 "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, "" 456 }; 457 DrmMetricGroup::Metric closeSessionNotOpenedMetric = { 458 "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue } 459 }; 460 461 DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric, 462 closeSessionNotOpenedMetric } }; 463 464 _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics})); 465 return Void(); 466 } 467 468 Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) { 469 std::vector<SecureStop> stops; 470 for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) { 471 ClearkeySecureStop clearkeyStop = itr->second; 472 std::vector<uint8_t> stopVec; 473 stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end()); 474 stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end()); 475 476 SecureStop stop; 477 stop.opaqueData = toHidlVec(stopVec); 478 stops.push_back(stop); 479 } 480 _hidl_cb(Status::OK, stops); 481 return Void(); 482 } 483 484 Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId, 485 getSecureStop_cb _hidl_cb) { 486 SecureStop stop; 487 auto itr = mSecureStops.find(toVector(secureStopId)); 488 if (itr != mSecureStops.end()) { 489 ClearkeySecureStop clearkeyStop = itr->second; 490 std::vector<uint8_t> stopVec; 491 stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end()); 492 stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end()); 493 494 stop.opaqueData = toHidlVec(stopVec); 495 _hidl_cb(Status::OK, stop); 496 } else { 497 _hidl_cb(Status::BAD_VALUE, stop); 498 } 499 500 return Void(); 501 } 502 503 Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) { 504 return removeSecureStop(secureStopId); 505 } 506 507 Return<Status> DrmPlugin::releaseAllSecureStops() { 508 return removeAllSecureStops(); 509 } 510 511 Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) { 512 std::vector<SecureStopId> ids; 513 for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) { 514 ids.push_back(itr->first); 515 } 516 517 _hidl_cb(Status::OK, toHidlVec(ids)); 518 return Void(); 519 } 520 521 Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) { 522 if (ssRelease.opaqueData.size() == 0) { 523 return Status::BAD_VALUE; 524 } 525 526 Status status = Status::OK; 527 std::vector<uint8_t> input = toVector(ssRelease.opaqueData); 528 529 // The format of opaqueData is shared between the server 530 // and the drm service. The clearkey implementation consists of: 531 // count - number of secure stops 532 // list of fixed length secure stops 533 size_t countBufferSize = sizeof(uint32_t); 534 uint32_t count = 0; 535 sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count); 536 537 // Avoid divide by 0 below. 538 if (count == 0) { 539 return Status::BAD_VALUE; 540 } 541 542 size_t secureStopSize = (input.size() - countBufferSize) / count; 543 uint8_t buffer[secureStopSize]; 544 size_t offset = countBufferSize; // skip the count 545 for (size_t i = 0; i < count; ++i, offset += secureStopSize) { 546 memcpy(buffer, input.data() + offset, secureStopSize); 547 std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize); 548 549 status = removeSecureStop(toHidlVec(id)); 550 if (Status::OK != status) break; 551 } 552 553 return status; 554 } 555 556 Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) { 557 if (1 != mSecureStops.erase(toVector(secureStopId))) { 558 return Status::BAD_VALUE; 559 } 560 return Status::OK; 561 } 562 563 Return<Status> DrmPlugin::removeAllSecureStops() { 564 mSecureStops.clear(); 565 mNextSecureStopId = kSecureStopIdStart; 566 return Status::OK; 567 } 568 569 } // namespace clearkey 570 } // namespace V1_1 571 } // namespace drm 572 } // namespace hardware 573 } // namespace android 574