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 "MockDrmCryptoPlugin" 19 #include <utils/Log.h> 20 21 22 #include "media/drm/DrmAPI.h" 23 #include "MockDrmCryptoPlugin.h" 24 #include "media/stagefright/MediaErrors.h" 25 26 using namespace android; 27 28 // Shared library entry point 29 DrmFactory *createDrmFactory() 30 { 31 return new MockDrmFactory(); 32 } 33 34 // Shared library entry point 35 CryptoFactory *createCryptoFactory() 36 { 37 return new MockCryptoFactory(); 38 } 39 40 const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 41 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; 42 43 namespace android { 44 45 // MockDrmFactory 46 bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) 47 { 48 return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid))); 49 } 50 51 bool MockDrmFactory::isContentTypeSupported(const String8 &mimeType) 52 { 53 if (mimeType != "video/mp4") { 54 return false; 55 } 56 return true; 57 } 58 59 status_t MockDrmFactory::createDrmPlugin(const uint8_t /* uuid */[16], 60 DrmPlugin **plugin) 61 { 62 *plugin = new MockDrmPlugin(); 63 return OK; 64 } 65 66 // MockCryptoFactory 67 bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const 68 { 69 return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid))); 70 } 71 72 status_t MockCryptoFactory::createPlugin(const uint8_t /* uuid */[16], 73 const void * /* data */, 74 size_t /* size */, CryptoPlugin **plugin) 75 { 76 *plugin = new MockCryptoPlugin(); 77 return OK; 78 } 79 80 81 // MockDrmPlugin methods 82 83 status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId) 84 { 85 const size_t kSessionIdSize = 8; 86 87 Mutex::Autolock lock(mLock); 88 for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) { 89 long r = random(); 90 sessionId.appendArray((uint8_t *)&r, sizeof(long)); 91 } 92 mSessions.add(sessionId); 93 94 ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string()); 95 return OK; 96 } 97 98 status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId) 99 { 100 Mutex::Autolock lock(mLock); 101 ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string()); 102 ssize_t index = findSession(sessionId); 103 if (index == kNotFound) { 104 ALOGD("Invalid sessionId"); 105 return BAD_VALUE; 106 } 107 mSessions.removeAt(index); 108 return OK; 109 } 110 111 112 status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId, 113 Vector<uint8_t> const &initData, 114 String8 const &mimeType, KeyType keyType, 115 KeyedVector<String8, String8> const &optionalParameters, 116 Vector<uint8_t> &request, String8 &defaultUrl, 117 KeyRequestType *keyRequestType) 118 { 119 Mutex::Autolock lock(mLock); 120 ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s" 121 ", keyType=%d, optionalParameters=%s))", 122 vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(), 123 keyType, stringMapToString(optionalParameters).string()); 124 125 ssize_t index = findSession(sessionId); 126 if (index == kNotFound) { 127 ALOGD("Invalid sessionId"); 128 return BAD_VALUE; 129 } 130 131 // Properties used in mock test, set by mock plugin and verifed cts test app 132 // byte[] initData -> mock-initdata 133 // string mimeType -> mock-mimetype 134 // string keyType -> mock-keytype 135 // string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2} 136 137 mByteArrayProperties.add(String8("mock-initdata"), initData); 138 mStringProperties.add(String8("mock-mimetype"), mimeType); 139 140 String8 keyTypeStr; 141 keyTypeStr.appendFormat("%d", (int)keyType); 142 mStringProperties.add(String8("mock-keytype"), keyTypeStr); 143 144 String8 params; 145 for (size_t i = 0; i < optionalParameters.size(); i++) { 146 params.appendFormat("%s{%s,%s}", i ? "," : "", 147 optionalParameters.keyAt(i).string(), 148 optionalParameters.valueAt(i).string()); 149 } 150 mStringProperties.add(String8("mock-optparams"), params); 151 152 // Properties used in mock test, set by cts test app returned from mock plugin 153 // byte[] mock-request -> request 154 // string mock-default-url -> defaultUrl 155 // string mock-keyRequestType -> keyRequestType 156 157 index = mByteArrayProperties.indexOfKey(String8("mock-request")); 158 if (index < 0) { 159 ALOGD("Missing 'mock-request' parameter for mock"); 160 return BAD_VALUE; 161 } else { 162 request = mByteArrayProperties.valueAt(index); 163 } 164 165 index = mStringProperties.indexOfKey(String8("mock-defaultUrl")); 166 if (index < 0) { 167 ALOGD("Missing 'mock-defaultUrl' parameter for mock"); 168 return BAD_VALUE; 169 } else { 170 defaultUrl = mStringProperties.valueAt(index); 171 } 172 173 index = mStringProperties.indexOfKey(String8("mock-keyRequestType")); 174 if (index < 0) { 175 ALOGD("Missing 'mock-keyRequestType' parameter for mock"); 176 return BAD_VALUE; 177 } else { 178 *keyRequestType = static_cast<KeyRequestType>( 179 atoi(mStringProperties.valueAt(index).string())); 180 } 181 182 return OK; 183 } 184 185 status_t MockDrmPlugin::provideKeyResponse(Vector<uint8_t> const &sessionId, 186 Vector<uint8_t> const &response, 187 Vector<uint8_t> &keySetId) 188 { 189 Mutex::Autolock lock(mLock); 190 ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)", 191 vectorToString(sessionId).string(), vectorToString(response).string()); 192 ssize_t index = findSession(sessionId); 193 if (index == kNotFound) { 194 ALOGD("Invalid sessionId"); 195 return BAD_VALUE; 196 } 197 if (response.size() == 0) { 198 return BAD_VALUE; 199 } 200 201 // Properties used in mock test, set by mock plugin and verifed cts test app 202 // byte[] response -> mock-response 203 mByteArrayProperties.add(String8("mock-response"), response); 204 205 const size_t kKeySetIdSize = 8; 206 207 for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) { 208 long r = random(); 209 keySetId.appendArray((uint8_t *)&r, sizeof(long)); 210 } 211 mKeySets.add(keySetId); 212 213 return OK; 214 } 215 216 status_t MockDrmPlugin::removeKeys(Vector<uint8_t> const &keySetId) 217 { 218 Mutex::Autolock lock(mLock); 219 ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)", 220 vectorToString(keySetId).string()); 221 222 ssize_t index = findKeySet(keySetId); 223 if (index == kNotFound) { 224 ALOGD("Invalid keySetId"); 225 return BAD_VALUE; 226 } 227 mKeySets.removeAt(index); 228 229 return OK; 230 } 231 232 status_t MockDrmPlugin::restoreKeys(Vector<uint8_t> const &sessionId, 233 Vector<uint8_t> const &keySetId) 234 { 235 Mutex::Autolock lock(mLock); 236 ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)", 237 vectorToString(sessionId).string(), 238 vectorToString(keySetId).string()); 239 ssize_t index = findSession(sessionId); 240 if (index == kNotFound) { 241 ALOGD("Invalid sessionId"); 242 return BAD_VALUE; 243 } 244 245 index = findKeySet(keySetId); 246 if (index == kNotFound) { 247 ALOGD("Invalid keySetId"); 248 return BAD_VALUE; 249 } 250 251 return OK; 252 } 253 254 status_t MockDrmPlugin::queryKeyStatus(Vector<uint8_t> const &sessionId, 255 KeyedVector<String8, String8> &infoMap) const 256 { 257 ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)", 258 vectorToString(sessionId).string()); 259 260 ssize_t index = findSession(sessionId); 261 if (index == kNotFound) { 262 ALOGD("Invalid sessionId"); 263 return BAD_VALUE; 264 } 265 266 infoMap.add(String8("purchaseDuration"), String8("1000")); 267 infoMap.add(String8("licenseDuration"), String8("100")); 268 return OK; 269 } 270 271 status_t MockDrmPlugin::getProvisionRequest(String8 const & /* certType */, 272 String8 const & /* certAuthority */, 273 Vector<uint8_t> &request, 274 String8 &defaultUrl) 275 { 276 Mutex::Autolock lock(mLock); 277 ALOGD("MockDrmPlugin::getProvisionRequest()"); 278 279 // Properties used in mock test, set by cts test app returned from mock plugin 280 // byte[] mock-request -> request 281 // string mock-default-url -> defaultUrl 282 283 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-request")); 284 if (index < 0) { 285 ALOGD("Missing 'mock-request' parameter for mock"); 286 return BAD_VALUE; 287 } else { 288 request = mByteArrayProperties.valueAt(index); 289 } 290 291 index = mStringProperties.indexOfKey(String8("mock-defaultUrl")); 292 if (index < 0) { 293 ALOGD("Missing 'mock-defaultUrl' parameter for mock"); 294 return BAD_VALUE; 295 } else { 296 defaultUrl = mStringProperties.valueAt(index); 297 } 298 return OK; 299 } 300 301 status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response, 302 Vector<uint8_t> & /* certificate */, 303 Vector<uint8_t> & /* wrappedKey */) 304 { 305 Mutex::Autolock lock(mLock); 306 ALOGD("MockDrmPlugin::provideProvisionResponse(%s)", 307 vectorToString(response).string()); 308 309 // Properties used in mock test, set by mock plugin and verifed cts test app 310 // byte[] response -> mock-response 311 312 mByteArrayProperties.add(String8("mock-response"), response); 313 return OK; 314 } 315 316 status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const & /* ssid */, 317 Vector<uint8_t> & secureStop) 318 { 319 Mutex::Autolock lock(mLock); 320 ALOGD("MockDrmPlugin::getSecureStop()"); 321 322 // Properties used in mock test, set by cts test app returned from mock plugin 323 // byte[] mock-secure-stop -> first secure stop in list 324 325 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop")); 326 if (index < 0) { 327 ALOGD("Missing 'mock-secure-stop' parameter for mock"); 328 return BAD_VALUE; 329 } else { 330 secureStop = mByteArrayProperties.valueAt(index); 331 } 332 return OK; 333 } 334 335 status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops) 336 { 337 Mutex::Autolock lock(mLock); 338 ALOGD("MockDrmPlugin::getSecureStops()"); 339 340 // Properties used in mock test, set by cts test app returned from mock plugin 341 // byte[] mock-secure-stop1 -> first secure stop in list 342 // byte[] mock-secure-stop2 -> second secure stop in list 343 344 Vector<uint8_t> ss1, ss2; 345 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1")); 346 if (index < 0) { 347 ALOGD("Missing 'mock-secure-stop1' parameter for mock"); 348 return BAD_VALUE; 349 } else { 350 ss1 = mByteArrayProperties.valueAt(index); 351 } 352 353 index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2")); 354 if (index < 0) { 355 ALOGD("Missing 'mock-secure-stop2' parameter for mock"); 356 return BAD_VALUE; 357 } else { 358 ss2 = mByteArrayProperties.valueAt(index); 359 } 360 361 secureStops.push_back(ss1); 362 secureStops.push_back(ss2); 363 return OK; 364 } 365 366 status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease) 367 { 368 Mutex::Autolock lock(mLock); 369 ALOGD("MockDrmPlugin::releaseSecureStops(%s)", 370 vectorToString(ssRelease).string()); 371 372 // Properties used in mock test, set by mock plugin and verifed cts test app 373 // byte[] secure-stop-release -> mock-ssrelease 374 mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease); 375 376 return OK; 377 } 378 379 status_t MockDrmPlugin::releaseAllSecureStops() 380 { 381 Mutex::Autolock lock(mLock); 382 ALOGD("MockDrmPlugin::releaseAllSecureStops()"); 383 return OK; 384 } 385 386 status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const 387 { 388 ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string()); 389 ssize_t index = mStringProperties.indexOfKey(name); 390 if (index < 0) { 391 ALOGD("no property for '%s'", name.string()); 392 return BAD_VALUE; 393 } 394 value = mStringProperties.valueAt(index); 395 return OK; 396 } 397 398 status_t MockDrmPlugin::getPropertyByteArray(String8 const &name, 399 Vector<uint8_t> &value) const 400 { 401 ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string()); 402 ssize_t index = mByteArrayProperties.indexOfKey(name); 403 if (index < 0) { 404 ALOGD("no property for '%s'", name.string()); 405 return BAD_VALUE; 406 } 407 value = mByteArrayProperties.valueAt(index); 408 return OK; 409 } 410 411 status_t MockDrmPlugin::setPropertyString(String8 const &name, 412 String8 const &value) 413 { 414 Mutex::Autolock lock(mLock); 415 ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)", 416 name.string(), value.string()); 417 418 if (name == "mock-send-event") { 419 unsigned code, extra; 420 sscanf(value.string(), "%d %d", &code, &extra); 421 DrmPlugin::EventType eventType = (DrmPlugin::EventType)code; 422 423 Vector<uint8_t> const *pSessionId = NULL; 424 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 425 if (index >= 0) { 426 pSessionId = &mByteArrayProperties[index]; 427 } 428 429 Vector<uint8_t> const *pData = NULL; 430 index = mByteArrayProperties.indexOfKey(String8("mock-event-data")); 431 if (index >= 0) { 432 pData = &mByteArrayProperties[index]; 433 } 434 ALOGD("sending event from mock drm plugin: %d %d %s %s", 435 (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}", 436 pData ? vectorToString(*pData) : "{}"); 437 438 sendEvent(eventType, extra, pSessionId, pData); 439 } else if (name == "mock-send-expiration-update") { 440 int64_t expiryTimeMS; 441 sscanf(value.string(), "%jd", &expiryTimeMS); 442 443 Vector<uint8_t> const *pSessionId = NULL; 444 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 445 if (index >= 0) { 446 pSessionId = &mByteArrayProperties[index]; 447 } 448 449 ALOGD("sending expiration-update from mock drm plugin: %jd %s", 450 expiryTimeMS, pSessionId ? vectorToString(*pSessionId) : "{}"); 451 452 sendExpirationUpdate(pSessionId, expiryTimeMS); 453 } else if (name == "mock-send-keys-change") { 454 Vector<uint8_t> const *pSessionId = NULL; 455 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 456 if (index >= 0) { 457 pSessionId = &mByteArrayProperties[index]; 458 } 459 460 ALOGD("sending keys-change from mock drm plugin: %s", 461 pSessionId ? vectorToString(*pSessionId) : "{}"); 462 463 Vector<DrmPlugin::KeyStatus> keyStatusList; 464 DrmPlugin::KeyStatus keyStatus; 465 uint8_t keyId1[] = {'k', 'e', 'y', '1'}; 466 keyStatus.mKeyId.clear(); 467 keyStatus.mKeyId.appendArray(keyId1, sizeof(keyId1)); 468 keyStatus.mType = DrmPlugin::kKeyStatusType_Usable; 469 keyStatusList.add(keyStatus); 470 471 uint8_t keyId2[] = {'k', 'e', 'y', '2'}; 472 keyStatus.mKeyId.clear(); 473 keyStatus.mKeyId.appendArray(keyId2, sizeof(keyId2)); 474 keyStatus.mType = DrmPlugin::kKeyStatusType_Expired; 475 keyStatusList.add(keyStatus); 476 477 uint8_t keyId3[] = {'k', 'e', 'y', '3'}; 478 keyStatus.mKeyId.clear(); 479 keyStatus.mKeyId.appendArray(keyId3, sizeof(keyId3)); 480 keyStatus.mType = DrmPlugin::kKeyStatusType_OutputNotAllowed; 481 keyStatusList.add(keyStatus); 482 483 uint8_t keyId4[] = {'k', 'e', 'y', '4'}; 484 keyStatus.mKeyId.clear(); 485 keyStatus.mKeyId.appendArray(keyId4, sizeof(keyId4)); 486 keyStatus.mType = DrmPlugin::kKeyStatusType_StatusPending; 487 keyStatusList.add(keyStatus); 488 489 uint8_t keyId5[] = {'k', 'e', 'y', '5'}; 490 keyStatus.mKeyId.clear(); 491 keyStatus.mKeyId.appendArray(keyId5, sizeof(keyId5)); 492 keyStatus.mType = DrmPlugin::kKeyStatusType_InternalError; 493 keyStatusList.add(keyStatus); 494 495 sendKeysChange(pSessionId, &keyStatusList, true); 496 } else { 497 mStringProperties.add(name, value); 498 } 499 return OK; 500 } 501 502 status_t MockDrmPlugin::setPropertyByteArray(String8 const &name, 503 Vector<uint8_t> const &value) 504 { 505 Mutex::Autolock lock(mLock); 506 ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)", 507 name.string(), vectorToString(value).string()); 508 mByteArrayProperties.add(name, value); 509 return OK; 510 } 511 512 status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId, 513 String8 const &algorithm) 514 { 515 Mutex::Autolock lock(mLock); 516 517 ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)", 518 vectorToString(sessionId).string(), algorithm.string()); 519 520 ssize_t index = findSession(sessionId); 521 if (index == kNotFound) { 522 ALOGD("Invalid sessionId"); 523 return BAD_VALUE; 524 } 525 526 if (algorithm == "AES/CBC/NoPadding") { 527 return OK; 528 } 529 return BAD_VALUE; 530 } 531 532 status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId, 533 String8 const &algorithm) 534 { 535 Mutex::Autolock lock(mLock); 536 537 ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)", 538 vectorToString(sessionId).string(), algorithm.string()); 539 540 ssize_t index = findSession(sessionId); 541 if (index == kNotFound) { 542 ALOGD("Invalid sessionId"); 543 return BAD_VALUE; 544 } 545 546 if (algorithm == "HmacSHA256") { 547 return OK; 548 } 549 return BAD_VALUE; 550 } 551 552 status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId, 553 Vector<uint8_t> const &keyId, 554 Vector<uint8_t> const &input, 555 Vector<uint8_t> const &iv, 556 Vector<uint8_t> &output) 557 { 558 Mutex::Autolock lock(mLock); 559 ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", 560 vectorToString(sessionId).string(), 561 vectorToString(keyId).string(), 562 vectorToString(input).string(), 563 vectorToString(iv).string()); 564 565 ssize_t index = findSession(sessionId); 566 if (index == kNotFound) { 567 ALOGD("Invalid sessionId"); 568 return BAD_VALUE; 569 } 570 571 // Properties used in mock test, set by mock plugin and verifed cts test app 572 // byte[] keyId -> mock-keyid 573 // byte[] input -> mock-input 574 // byte[] iv -> mock-iv 575 mByteArrayProperties.add(String8("mock-keyid"), keyId); 576 mByteArrayProperties.add(String8("mock-input"), input); 577 mByteArrayProperties.add(String8("mock-iv"), iv); 578 579 // Properties used in mock test, set by cts test app returned from mock plugin 580 // byte[] mock-output -> output 581 index = mByteArrayProperties.indexOfKey(String8("mock-output")); 582 if (index < 0) { 583 ALOGD("Missing 'mock-request' parameter for mock"); 584 return BAD_VALUE; 585 } else { 586 output = mByteArrayProperties.valueAt(index); 587 } 588 return OK; 589 } 590 591 status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId, 592 Vector<uint8_t> const &keyId, 593 Vector<uint8_t> const &input, 594 Vector<uint8_t> const &iv, 595 Vector<uint8_t> &output) 596 { 597 Mutex::Autolock lock(mLock); 598 ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", 599 vectorToString(sessionId).string(), 600 vectorToString(keyId).string(), 601 vectorToString(input).string(), 602 vectorToString(iv).string()); 603 604 ssize_t index = findSession(sessionId); 605 if (index == kNotFound) { 606 ALOGD("Invalid sessionId"); 607 return BAD_VALUE; 608 } 609 610 // Properties used in mock test, set by mock plugin and verifed cts test app 611 // byte[] keyId -> mock-keyid 612 // byte[] input -> mock-input 613 // byte[] iv -> mock-iv 614 mByteArrayProperties.add(String8("mock-keyid"), keyId); 615 mByteArrayProperties.add(String8("mock-input"), input); 616 mByteArrayProperties.add(String8("mock-iv"), iv); 617 618 // Properties used in mock test, set by cts test app returned from mock plugin 619 // byte[] mock-output -> output 620 index = mByteArrayProperties.indexOfKey(String8("mock-output")); 621 if (index < 0) { 622 ALOGD("Missing 'mock-request' parameter for mock"); 623 return BAD_VALUE; 624 } else { 625 output = mByteArrayProperties.valueAt(index); 626 } 627 return OK; 628 } 629 630 status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId, 631 Vector<uint8_t> const &keyId, 632 Vector<uint8_t> const &message, 633 Vector<uint8_t> &signature) 634 { 635 Mutex::Autolock lock(mLock); 636 ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)", 637 vectorToString(sessionId).string(), 638 vectorToString(keyId).string(), 639 vectorToString(message).string()); 640 641 ssize_t index = findSession(sessionId); 642 if (index == kNotFound) { 643 ALOGD("Invalid sessionId"); 644 return BAD_VALUE; 645 } 646 647 // Properties used in mock test, set by mock plugin and verifed cts test app 648 // byte[] keyId -> mock-keyid 649 // byte[] message -> mock-message 650 mByteArrayProperties.add(String8("mock-keyid"), keyId); 651 mByteArrayProperties.add(String8("mock-message"), message); 652 653 // Properties used in mock test, set by cts test app returned from mock plugin 654 // byte[] mock-signature -> signature 655 index = mByteArrayProperties.indexOfKey(String8("mock-signature")); 656 if (index < 0) { 657 ALOGD("Missing 'mock-request' parameter for mock"); 658 return BAD_VALUE; 659 } else { 660 signature = mByteArrayProperties.valueAt(index); 661 } 662 return OK; 663 } 664 665 status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId, 666 Vector<uint8_t> const &keyId, 667 Vector<uint8_t> const &message, 668 Vector<uint8_t> const &signature, 669 bool &match) 670 { 671 Mutex::Autolock lock(mLock); 672 ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)", 673 vectorToString(sessionId).string(), 674 vectorToString(keyId).string(), 675 vectorToString(message).string(), 676 vectorToString(signature).string()); 677 678 ssize_t index = findSession(sessionId); 679 if (index == kNotFound) { 680 ALOGD("Invalid sessionId"); 681 return BAD_VALUE; 682 } 683 684 // Properties used in mock test, set by mock plugin and verifed cts test app 685 // byte[] keyId -> mock-keyid 686 // byte[] message -> mock-message 687 // byte[] signature -> mock-signature 688 mByteArrayProperties.add(String8("mock-keyid"), keyId); 689 mByteArrayProperties.add(String8("mock-message"), message); 690 mByteArrayProperties.add(String8("mock-signature"), signature); 691 692 // Properties used in mock test, set by cts test app returned from mock plugin 693 // String mock-match "1" or "0" -> match 694 index = mStringProperties.indexOfKey(String8("mock-match")); 695 if (index < 0) { 696 ALOGD("Missing 'mock-request' parameter for mock"); 697 return BAD_VALUE; 698 } else { 699 match = atol(mStringProperties.valueAt(index).string()); 700 } 701 return OK; 702 } 703 704 status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId, 705 String8 const &algorithm, 706 Vector<uint8_t> const &message, 707 Vector<uint8_t> const &wrappedKey, 708 Vector<uint8_t> &signature) 709 { 710 Mutex::Autolock lock(mLock); 711 ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, " 712 "message=%s, signature=%s)", 713 vectorToString(sessionId).string(), 714 algorithm.string(), 715 vectorToString(message).string(), 716 vectorToString(wrappedKey).string(), 717 vectorToString(signature).string()); 718 719 // Properties used in mock test, set by mock plugin and verifed cts test app 720 // byte[] wrappedKey -> mock-wrappedkey 721 // byte[] message -> mock-message 722 // byte[] signature -> mock-signature 723 mByteArrayProperties.add(String8("mock-sessionid"), sessionId); 724 mStringProperties.add(String8("mock-algorithm"), algorithm); 725 mByteArrayProperties.add(String8("mock-message"), message); 726 mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey); 727 mByteArrayProperties.add(String8("mock-signature"), signature); 728 return OK; 729 } 730 731 ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const 732 { 733 ALOGD("findSession: nsessions=%zu, size=%zu", mSessions.size(), sessionId.size()); 734 for (size_t i = 0; i < mSessions.size(); ++i) { 735 if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) { 736 return i; 737 } 738 } 739 return kNotFound; 740 } 741 742 ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const 743 { 744 ALOGD("findKeySet: nkeySets=%zu, size=%zu", mKeySets.size(), keySetId.size()); 745 for (size_t i = 0; i < mKeySets.size(); ++i) { 746 if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) { 747 return i; 748 } 749 } 750 return kNotFound; 751 } 752 753 754 // Conversion utilities 755 String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const 756 { 757 return arrayToString(vector.array(), vector.size()); 758 } 759 760 String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const 761 { 762 String8 result("{ "); 763 for (size_t i = 0; i < len; i++) { 764 result.appendFormat("0x%02x ", array[i]); 765 } 766 result += "}"; 767 return result; 768 } 769 770 String8 MockDrmPlugin::stringMapToString(const KeyedVector<String8, String8>& map) const 771 { 772 String8 result("{ "); 773 for (size_t i = 0; i < map.size(); i++) { 774 result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "", 775 map.keyAt(i).string(), map.valueAt(i).string()); 776 } 777 return result + " }"; 778 } 779 780 bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) { 781 return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0); 782 } 783 784 // 785 // Crypto Plugin 786 // 787 788 bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const 789 { 790 ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime); 791 return false; 792 } 793 794 ssize_t 795 MockCryptoPlugin::decrypt(bool secure, const uint8_t key[DECRYPT_KEY_SIZE], 796 const uint8_t iv[DECRYPT_KEY_SIZE], Mode mode, 797 const Pattern &pattern, const void *srcPtr, 798 const SubSample *subSamples, size_t numSubSamples, 799 void *dstPtr, AString * /* errorDetailMsg */) 800 { 801 ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, " 802 "pattern:{encryptBlocks=%d, skipBlocks=%d} src=%p, " 803 "subSamples=%s, dst=%p)", 804 (int)secure, 805 arrayToString(key, DECRYPT_KEY_SIZE).string(), 806 arrayToString(iv, DECRYPT_KEY_SIZE).string(), 807 (int)mode, pattern.mEncryptBlocks, pattern.mSkipBlocks, srcPtr, 808 subSamplesToString(subSamples, numSubSamples).string(), 809 dstPtr); 810 return OK; 811 } 812 813 // Conversion utilities 814 String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const 815 { 816 String8 result("{ "); 817 for (size_t i = 0; i < len; i++) { 818 result.appendFormat("0x%02x ", array[i]); 819 } 820 result += "}"; 821 return result; 822 } 823 824 String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples, 825 size_t numSubSamples) const 826 { 827 String8 result; 828 for (size_t i = 0; i < numSubSamples; i++) { 829 result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i, 830 subSamples[i].mNumBytesOfClearData, 831 subSamples[i].mNumBytesOfEncryptedData); 832 } 833 return result; 834 } 835 836 }; 837