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