Drm.cpp revision 8856c8b8777d0e0de11b2de863a336b001024e29
1/* 2 * Copyright (C) 2013 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 "Drm" 19#include <utils/Log.h> 20 21#include <dirent.h> 22#include <dlfcn.h> 23 24#include "Drm.h" 25 26#include <media/drm/DrmAPI.h> 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/foundation/AString.h> 29#include <media/stagefright/foundation/hexdump.h> 30#include <media/stagefright/MediaErrors.h> 31 32namespace android { 33 34KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap; 35KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap; 36Mutex Drm::mMapLock; 37 38static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) { 39 if (lhs.size() < rhs.size()) { 40 return true; 41 } else if (lhs.size() > rhs.size()) { 42 return false; 43 } 44 45 return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0; 46} 47 48Drm::Drm() 49 : mInitCheck(NO_INIT), 50 mFactory(NULL), 51 mPlugin(NULL) { 52} 53 54Drm::~Drm() { 55 delete mPlugin; 56 mPlugin = NULL; 57 closeFactory(); 58} 59 60void Drm::closeFactory() { 61 delete mFactory; 62 mFactory = NULL; 63 mLibrary.clear(); 64} 65 66status_t Drm::initCheck() const { 67 return mInitCheck; 68} 69 70 71/* 72 * Search the plugins directory for a plugin that supports the scheme 73 * specified by uuid 74 * 75 * If found: 76 * mLibrary holds a strong pointer to the dlopen'd library 77 * mFactory is set to the library's factory method 78 * mInitCheck is set to OK 79 * 80 * If not found: 81 * mLibrary is cleared and mFactory are set to NULL 82 * mInitCheck is set to an error (!OK) 83 */ 84void Drm::findFactoryForScheme(const uint8_t uuid[16]) { 85 86 closeFactory(); 87 88 // lock static maps 89 Mutex::Autolock autoLock(mMapLock); 90 91 // first check cache 92 Vector<uint8_t> uuidVector; 93 uuidVector.appendArray(uuid, sizeof(uuid)); 94 ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector); 95 if (index >= 0) { 96 if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) { 97 mInitCheck = OK; 98 return; 99 } else { 100 ALOGE("Failed to load from cached library path!"); 101 mInitCheck = ERROR_UNSUPPORTED; 102 return; 103 } 104 } 105 106 // no luck, have to search 107 String8 dirPath("/vendor/lib/mediadrm"); 108 DIR* pDir = opendir(dirPath.string()); 109 110 if (pDir == NULL) { 111 mInitCheck = ERROR_UNSUPPORTED; 112 ALOGE("Failed to open plugin directory %s", dirPath.string()); 113 return; 114 } 115 116 117 struct dirent* pEntry; 118 while ((pEntry = readdir(pDir))) { 119 120 String8 pluginPath = dirPath + "/" + pEntry->d_name; 121 122 if (pluginPath.getPathExtension() == ".so") { 123 124 if (loadLibraryForScheme(pluginPath, uuid)) { 125 mUUIDToLibraryPathMap.add(uuidVector, pluginPath); 126 mInitCheck = OK; 127 closedir(pDir); 128 return; 129 } 130 } 131 } 132 133 closedir(pDir); 134 135 ALOGE("Failed to find drm plugin"); 136 mInitCheck = ERROR_UNSUPPORTED; 137} 138 139bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) { 140 141 // get strong pointer to open shared library 142 ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path); 143 if (index >= 0) { 144 mLibrary = mLibraryPathToOpenLibraryMap[index].promote(); 145 } else { 146 index = mLibraryPathToOpenLibraryMap.add(path, NULL); 147 } 148 149 if (!mLibrary.get()) { 150 mLibrary = new SharedLibrary(path); 151 if (!*mLibrary) { 152 return false; 153 } 154 155 mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary); 156 } 157 158 typedef DrmFactory *(*CreateDrmFactoryFunc)(); 159 160 CreateDrmFactoryFunc createDrmFactory = 161 (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory"); 162 163 if (createDrmFactory == NULL || 164 (mFactory = createDrmFactory()) == NULL || 165 !mFactory->isCryptoSchemeSupported(uuid)) { 166 closeFactory(); 167 return false; 168 } 169 return true; 170} 171 172bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16]) { 173 Mutex::Autolock autoLock(mLock); 174 175 if (mFactory && mFactory->isCryptoSchemeSupported(uuid)) { 176 return true; 177 } 178 179 findFactoryForScheme(uuid); 180 return (mInitCheck == OK); 181} 182 183status_t Drm::createPlugin(const uint8_t uuid[16]) { 184 Mutex::Autolock autoLock(mLock); 185 186 if (mPlugin != NULL) { 187 return -EINVAL; 188 } 189 190 if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) { 191 findFactoryForScheme(uuid); 192 } 193 194 if (mInitCheck != OK) { 195 return mInitCheck; 196 } 197 198 return mFactory->createDrmPlugin(uuid, &mPlugin); 199} 200 201status_t Drm::destroyPlugin() { 202 Mutex::Autolock autoLock(mLock); 203 204 if (mInitCheck != OK) { 205 return mInitCheck; 206 } 207 208 if (mPlugin == NULL) { 209 return -EINVAL; 210 } 211 212 delete mPlugin; 213 mPlugin = NULL; 214 215 return OK; 216} 217 218status_t Drm::openSession(Vector<uint8_t> &sessionId) { 219 Mutex::Autolock autoLock(mLock); 220 221 if (mInitCheck != OK) { 222 return mInitCheck; 223 } 224 225 if (mPlugin == NULL) { 226 return -EINVAL; 227 } 228 229 return mPlugin->openSession(sessionId); 230} 231 232status_t Drm::closeSession(Vector<uint8_t> const &sessionId) { 233 Mutex::Autolock autoLock(mLock); 234 235 if (mInitCheck != OK) { 236 return mInitCheck; 237 } 238 239 if (mPlugin == NULL) { 240 return -EINVAL; 241 } 242 243 return mPlugin->closeSession(sessionId); 244} 245 246status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId, 247 Vector<uint8_t> const &initData, 248 String8 const &mimeType, DrmPlugin::KeyType keyType, 249 KeyedVector<String8, String8> const &optionalParameters, 250 Vector<uint8_t> &request, String8 &defaultUrl) { 251 Mutex::Autolock autoLock(mLock); 252 253 if (mInitCheck != OK) { 254 return mInitCheck; 255 } 256 257 if (mPlugin == NULL) { 258 return -EINVAL; 259 } 260 261 return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType, 262 optionalParameters, request, defaultUrl); 263} 264 265status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId, 266 Vector<uint8_t> const &response, 267 Vector<uint8_t> &keySetId) { 268 Mutex::Autolock autoLock(mLock); 269 270 if (mInitCheck != OK) { 271 return mInitCheck; 272 } 273 274 if (mPlugin == NULL) { 275 return -EINVAL; 276 } 277 278 return mPlugin->provideKeyResponse(sessionId, response, keySetId); 279} 280 281status_t Drm::removeKeys(Vector<uint8_t> const &keySetId) { 282 Mutex::Autolock autoLock(mLock); 283 284 if (mInitCheck != OK) { 285 return mInitCheck; 286 } 287 288 if (mPlugin == NULL) { 289 return -EINVAL; 290 } 291 292 return mPlugin->removeKeys(keySetId); 293} 294 295status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId, 296 Vector<uint8_t> const &keySetId) { 297 Mutex::Autolock autoLock(mLock); 298 299 if (mInitCheck != OK) { 300 return mInitCheck; 301 } 302 303 if (mPlugin == NULL) { 304 return -EINVAL; 305 } 306 307 return mPlugin->restoreKeys(sessionId, keySetId); 308} 309 310status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId, 311 KeyedVector<String8, String8> &infoMap) const { 312 Mutex::Autolock autoLock(mLock); 313 314 if (mInitCheck != OK) { 315 return mInitCheck; 316 } 317 318 if (mPlugin == NULL) { 319 return -EINVAL; 320 } 321 322 return mPlugin->queryKeyStatus(sessionId, infoMap); 323} 324 325status_t Drm::getProvisionRequest(Vector<uint8_t> &request, String8 &defaultUrl) { 326 Mutex::Autolock autoLock(mLock); 327 328 if (mInitCheck != OK) { 329 return mInitCheck; 330 } 331 332 if (mPlugin == NULL) { 333 return -EINVAL; 334 } 335 336 return mPlugin->getProvisionRequest(request, defaultUrl); 337} 338 339status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response) { 340 Mutex::Autolock autoLock(mLock); 341 342 if (mInitCheck != OK) { 343 return mInitCheck; 344 } 345 346 if (mPlugin == NULL) { 347 return -EINVAL; 348 } 349 350 return mPlugin->provideProvisionResponse(response); 351} 352 353 354status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) { 355 Mutex::Autolock autoLock(mLock); 356 357 if (mInitCheck != OK) { 358 return mInitCheck; 359 } 360 361 if (mPlugin == NULL) { 362 return -EINVAL; 363 } 364 365 return mPlugin->getSecureStops(secureStops); 366} 367 368status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) { 369 Mutex::Autolock autoLock(mLock); 370 371 if (mInitCheck != OK) { 372 return mInitCheck; 373 } 374 375 if (mPlugin == NULL) { 376 return -EINVAL; 377 } 378 379 return mPlugin->releaseSecureStops(ssRelease); 380} 381 382status_t Drm::getPropertyString(String8 const &name, String8 &value ) const { 383 Mutex::Autolock autoLock(mLock); 384 385 if (mInitCheck != OK) { 386 return mInitCheck; 387 } 388 389 if (mPlugin == NULL) { 390 return -EINVAL; 391 } 392 393 return mPlugin->getPropertyString(name, value); 394} 395 396status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const { 397 Mutex::Autolock autoLock(mLock); 398 399 if (mInitCheck != OK) { 400 return mInitCheck; 401 } 402 403 if (mPlugin == NULL) { 404 return -EINVAL; 405 } 406 407 return mPlugin->getPropertyByteArray(name, value); 408} 409 410status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const { 411 Mutex::Autolock autoLock(mLock); 412 413 if (mInitCheck != OK) { 414 return mInitCheck; 415 } 416 417 if (mPlugin == NULL) { 418 return -EINVAL; 419 } 420 421 return mPlugin->setPropertyString(name, value); 422} 423 424status_t Drm::setPropertyByteArray(String8 const &name, 425 Vector<uint8_t> const &value ) const { 426 Mutex::Autolock autoLock(mLock); 427 428 if (mInitCheck != OK) { 429 return mInitCheck; 430 } 431 432 if (mPlugin == NULL) { 433 return -EINVAL; 434 } 435 436 return mPlugin->setPropertyByteArray(name, value); 437} 438 439 440status_t Drm::setCipherAlgorithm(Vector<uint8_t> const &sessionId, 441 String8 const &algorithm) { 442 Mutex::Autolock autoLock(mLock); 443 444 if (mInitCheck != OK) { 445 return mInitCheck; 446 } 447 448 if (mPlugin == NULL) { 449 return -EINVAL; 450 } 451 452 return mPlugin->setCipherAlgorithm(sessionId, algorithm); 453} 454 455status_t Drm::setMacAlgorithm(Vector<uint8_t> const &sessionId, 456 String8 const &algorithm) { 457 Mutex::Autolock autoLock(mLock); 458 459 if (mInitCheck != OK) { 460 return mInitCheck; 461 } 462 463 if (mPlugin == NULL) { 464 return -EINVAL; 465 } 466 467 return mPlugin->setMacAlgorithm(sessionId, algorithm); 468} 469 470status_t Drm::encrypt(Vector<uint8_t> const &sessionId, 471 Vector<uint8_t> const &keyId, 472 Vector<uint8_t> const &input, 473 Vector<uint8_t> const &iv, 474 Vector<uint8_t> &output) { 475 Mutex::Autolock autoLock(mLock); 476 477 if (mInitCheck != OK) { 478 return mInitCheck; 479 } 480 481 if (mPlugin == NULL) { 482 return -EINVAL; 483 } 484 485 return mPlugin->encrypt(sessionId, keyId, input, iv, output); 486} 487 488status_t Drm::decrypt(Vector<uint8_t> const &sessionId, 489 Vector<uint8_t> const &keyId, 490 Vector<uint8_t> const &input, 491 Vector<uint8_t> const &iv, 492 Vector<uint8_t> &output) { 493 Mutex::Autolock autoLock(mLock); 494 495 if (mInitCheck != OK) { 496 return mInitCheck; 497 } 498 499 if (mPlugin == NULL) { 500 return -EINVAL; 501 } 502 503 return mPlugin->decrypt(sessionId, keyId, input, iv, output); 504} 505 506status_t Drm::sign(Vector<uint8_t> const &sessionId, 507 Vector<uint8_t> const &keyId, 508 Vector<uint8_t> const &message, 509 Vector<uint8_t> &signature) { 510 Mutex::Autolock autoLock(mLock); 511 512 if (mInitCheck != OK) { 513 return mInitCheck; 514 } 515 516 if (mPlugin == NULL) { 517 return -EINVAL; 518 } 519 520 return mPlugin->sign(sessionId, keyId, message, signature); 521} 522 523status_t Drm::verify(Vector<uint8_t> const &sessionId, 524 Vector<uint8_t> const &keyId, 525 Vector<uint8_t> const &message, 526 Vector<uint8_t> const &signature, 527 bool &match) { 528 Mutex::Autolock autoLock(mLock); 529 530 if (mInitCheck != OK) { 531 return mInitCheck; 532 } 533 534 if (mPlugin == NULL) { 535 return -EINVAL; 536 } 537 538 return mPlugin->verify(sessionId, keyId, message, signature, match); 539} 540 541} // namespace android 542