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 26using namespace android; 27 28// Shared library entry point 29DrmFactory *createDrmFactory() 30{ 31 return new MockDrmFactory(); 32} 33 34// Shared library entry point 35CryptoFactory *createCryptoFactory() 36{ 37 return new MockCryptoFactory(); 38} 39 40const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 41 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; 42 43namespace 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::unprovisionDevice() 316 { 317 ALOGD("MockDrmPlugin::unprovisionDevice()"); 318 return OK; 319 } 320 321 status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const & /* ssid */, 322 Vector<uint8_t> & secureStop) 323 { 324 Mutex::Autolock lock(mLock); 325 ALOGD("MockDrmPlugin::getSecureStop()"); 326 327 // Properties used in mock test, set by cts test app returned from mock plugin 328 // byte[] mock-secure-stop -> first secure stop in list 329 330 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop")); 331 if (index < 0) { 332 ALOGD("Missing 'mock-secure-stop' parameter for mock"); 333 return BAD_VALUE; 334 } else { 335 secureStop = mByteArrayProperties.valueAt(index); 336 } 337 return OK; 338 } 339 340 status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops) 341 { 342 Mutex::Autolock lock(mLock); 343 ALOGD("MockDrmPlugin::getSecureStops()"); 344 345 // Properties used in mock test, set by cts test app returned from mock plugin 346 // byte[] mock-secure-stop1 -> first secure stop in list 347 // byte[] mock-secure-stop2 -> second secure stop in list 348 349 Vector<uint8_t> ss1, ss2; 350 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1")); 351 if (index < 0) { 352 ALOGD("Missing 'mock-secure-stop1' parameter for mock"); 353 return BAD_VALUE; 354 } else { 355 ss1 = mByteArrayProperties.valueAt(index); 356 } 357 358 index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2")); 359 if (index < 0) { 360 ALOGD("Missing 'mock-secure-stop2' parameter for mock"); 361 return BAD_VALUE; 362 } else { 363 ss2 = mByteArrayProperties.valueAt(index); 364 } 365 366 secureStops.push_back(ss1); 367 secureStops.push_back(ss2); 368 return OK; 369 } 370 371 status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease) 372 { 373 Mutex::Autolock lock(mLock); 374 ALOGD("MockDrmPlugin::releaseSecureStops(%s)", 375 vectorToString(ssRelease).string()); 376 377 // Properties used in mock test, set by mock plugin and verifed cts test app 378 // byte[] secure-stop-release -> mock-ssrelease 379 mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease); 380 381 return OK; 382 } 383 384 status_t MockDrmPlugin::releaseAllSecureStops() 385 { 386 Mutex::Autolock lock(mLock); 387 ALOGD("MockDrmPlugin::releaseAllSecureStops()"); 388 return OK; 389 } 390 391 status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const 392 { 393 ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string()); 394 ssize_t index = mStringProperties.indexOfKey(name); 395 if (index < 0) { 396 ALOGD("no property for '%s'", name.string()); 397 return BAD_VALUE; 398 } 399 value = mStringProperties.valueAt(index); 400 return OK; 401 } 402 403 status_t MockDrmPlugin::getPropertyByteArray(String8 const &name, 404 Vector<uint8_t> &value) const 405 { 406 ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string()); 407 ssize_t index = mByteArrayProperties.indexOfKey(name); 408 if (index < 0) { 409 ALOGD("no property for '%s'", name.string()); 410 return BAD_VALUE; 411 } 412 value = mByteArrayProperties.valueAt(index); 413 return OK; 414 } 415 416 status_t MockDrmPlugin::setPropertyString(String8 const &name, 417 String8 const &value) 418 { 419 Mutex::Autolock lock(mLock); 420 ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)", 421 name.string(), value.string()); 422 423 if (name == "mock-send-event") { 424 unsigned code, extra; 425 sscanf(value.string(), "%d %d", &code, &extra); 426 DrmPlugin::EventType eventType = (DrmPlugin::EventType)code; 427 428 Vector<uint8_t> const *pSessionId = NULL; 429 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 430 if (index >= 0) { 431 pSessionId = &mByteArrayProperties[index]; 432 } 433 434 Vector<uint8_t> const *pData = NULL; 435 index = mByteArrayProperties.indexOfKey(String8("mock-event-data")); 436 if (index >= 0) { 437 pData = &mByteArrayProperties[index]; 438 } 439 ALOGD("sending event from mock drm plugin: %d %d %s %s", 440 (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}", 441 pData ? vectorToString(*pData) : "{}"); 442 443 sendEvent(eventType, extra, pSessionId, pData); 444 } else if (name == "mock-send-expiration-update") { 445 int64_t expiryTimeMS; 446 sscanf(value.string(), "%jd", &expiryTimeMS); 447 448 Vector<uint8_t> const *pSessionId = NULL; 449 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 450 if (index >= 0) { 451 pSessionId = &mByteArrayProperties[index]; 452 } 453 454 ALOGD("sending expiration-update from mock drm plugin: %jd %s", 455 expiryTimeMS, pSessionId ? vectorToString(*pSessionId) : "{}"); 456 457 sendExpirationUpdate(pSessionId, expiryTimeMS); 458 } else if (name == "mock-send-keys-change") { 459 Vector<uint8_t> const *pSessionId = NULL; 460 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id")); 461 if (index >= 0) { 462 pSessionId = &mByteArrayProperties[index]; 463 } 464 465 ALOGD("sending keys-change from mock drm plugin: %s", 466 pSessionId ? vectorToString(*pSessionId) : "{}"); 467 468 Vector<DrmPlugin::KeyStatus> keyStatusList; 469 DrmPlugin::KeyStatus keyStatus; 470 uint8_t keyId1[] = {'k', 'e', 'y', '1'}; 471 keyStatus.mKeyId.clear(); 472 keyStatus.mKeyId.appendArray(keyId1, sizeof(keyId1)); 473 keyStatus.mType = DrmPlugin::kKeyStatusType_Usable; 474 keyStatusList.add(keyStatus); 475 476 uint8_t keyId2[] = {'k', 'e', 'y', '2'}; 477 keyStatus.mKeyId.clear(); 478 keyStatus.mKeyId.appendArray(keyId2, sizeof(keyId2)); 479 keyStatus.mType = DrmPlugin::kKeyStatusType_Expired; 480 keyStatusList.add(keyStatus); 481 482 uint8_t keyId3[] = {'k', 'e', 'y', '3'}; 483 keyStatus.mKeyId.clear(); 484 keyStatus.mKeyId.appendArray(keyId3, sizeof(keyId3)); 485 keyStatus.mType = DrmPlugin::kKeyStatusType_OutputNotAllowed; 486 keyStatusList.add(keyStatus); 487 488 uint8_t keyId4[] = {'k', 'e', 'y', '4'}; 489 keyStatus.mKeyId.clear(); 490 keyStatus.mKeyId.appendArray(keyId4, sizeof(keyId4)); 491 keyStatus.mType = DrmPlugin::kKeyStatusType_StatusPending; 492 keyStatusList.add(keyStatus); 493 494 uint8_t keyId5[] = {'k', 'e', 'y', '5'}; 495 keyStatus.mKeyId.clear(); 496 keyStatus.mKeyId.appendArray(keyId5, sizeof(keyId5)); 497 keyStatus.mType = DrmPlugin::kKeyStatusType_InternalError; 498 keyStatusList.add(keyStatus); 499 500 sendKeysChange(pSessionId, &keyStatusList, true); 501 } else { 502 mStringProperties.add(name, value); 503 } 504 return OK; 505 } 506 507 status_t MockDrmPlugin::setPropertyByteArray(String8 const &name, 508 Vector<uint8_t> const &value) 509 { 510 Mutex::Autolock lock(mLock); 511 ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)", 512 name.string(), vectorToString(value).string()); 513 mByteArrayProperties.add(name, value); 514 return OK; 515 } 516 517 status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId, 518 String8 const &algorithm) 519 { 520 Mutex::Autolock lock(mLock); 521 522 ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)", 523 vectorToString(sessionId).string(), algorithm.string()); 524 525 ssize_t index = findSession(sessionId); 526 if (index == kNotFound) { 527 ALOGD("Invalid sessionId"); 528 return BAD_VALUE; 529 } 530 531 if (algorithm == "AES/CBC/NoPadding") { 532 return OK; 533 } 534 return BAD_VALUE; 535 } 536 537 status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId, 538 String8 const &algorithm) 539 { 540 Mutex::Autolock lock(mLock); 541 542 ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)", 543 vectorToString(sessionId).string(), algorithm.string()); 544 545 ssize_t index = findSession(sessionId); 546 if (index == kNotFound) { 547 ALOGD("Invalid sessionId"); 548 return BAD_VALUE; 549 } 550 551 if (algorithm == "HmacSHA256") { 552 return OK; 553 } 554 return BAD_VALUE; 555 } 556 557 status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId, 558 Vector<uint8_t> const &keyId, 559 Vector<uint8_t> const &input, 560 Vector<uint8_t> const &iv, 561 Vector<uint8_t> &output) 562 { 563 Mutex::Autolock lock(mLock); 564 ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", 565 vectorToString(sessionId).string(), 566 vectorToString(keyId).string(), 567 vectorToString(input).string(), 568 vectorToString(iv).string()); 569 570 ssize_t index = findSession(sessionId); 571 if (index == kNotFound) { 572 ALOGD("Invalid sessionId"); 573 return BAD_VALUE; 574 } 575 576 // Properties used in mock test, set by mock plugin and verifed cts test app 577 // byte[] keyId -> mock-keyid 578 // byte[] input -> mock-input 579 // byte[] iv -> mock-iv 580 mByteArrayProperties.add(String8("mock-keyid"), keyId); 581 mByteArrayProperties.add(String8("mock-input"), input); 582 mByteArrayProperties.add(String8("mock-iv"), iv); 583 584 // Properties used in mock test, set by cts test app returned from mock plugin 585 // byte[] mock-output -> output 586 index = mByteArrayProperties.indexOfKey(String8("mock-output")); 587 if (index < 0) { 588 ALOGD("Missing 'mock-request' parameter for mock"); 589 return BAD_VALUE; 590 } else { 591 output = mByteArrayProperties.valueAt(index); 592 } 593 return OK; 594 } 595 596 status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId, 597 Vector<uint8_t> const &keyId, 598 Vector<uint8_t> const &input, 599 Vector<uint8_t> const &iv, 600 Vector<uint8_t> &output) 601 { 602 Mutex::Autolock lock(mLock); 603 ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)", 604 vectorToString(sessionId).string(), 605 vectorToString(keyId).string(), 606 vectorToString(input).string(), 607 vectorToString(iv).string()); 608 609 ssize_t index = findSession(sessionId); 610 if (index == kNotFound) { 611 ALOGD("Invalid sessionId"); 612 return BAD_VALUE; 613 } 614 615 // Properties used in mock test, set by mock plugin and verifed cts test app 616 // byte[] keyId -> mock-keyid 617 // byte[] input -> mock-input 618 // byte[] iv -> mock-iv 619 mByteArrayProperties.add(String8("mock-keyid"), keyId); 620 mByteArrayProperties.add(String8("mock-input"), input); 621 mByteArrayProperties.add(String8("mock-iv"), iv); 622 623 // Properties used in mock test, set by cts test app returned from mock plugin 624 // byte[] mock-output -> output 625 index = mByteArrayProperties.indexOfKey(String8("mock-output")); 626 if (index < 0) { 627 ALOGD("Missing 'mock-request' parameter for mock"); 628 return BAD_VALUE; 629 } else { 630 output = mByteArrayProperties.valueAt(index); 631 } 632 return OK; 633 } 634 635 status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId, 636 Vector<uint8_t> const &keyId, 637 Vector<uint8_t> const &message, 638 Vector<uint8_t> &signature) 639 { 640 Mutex::Autolock lock(mLock); 641 ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)", 642 vectorToString(sessionId).string(), 643 vectorToString(keyId).string(), 644 vectorToString(message).string()); 645 646 ssize_t index = findSession(sessionId); 647 if (index == kNotFound) { 648 ALOGD("Invalid sessionId"); 649 return BAD_VALUE; 650 } 651 652 // Properties used in mock test, set by mock plugin and verifed cts test app 653 // byte[] keyId -> mock-keyid 654 // byte[] message -> mock-message 655 mByteArrayProperties.add(String8("mock-keyid"), keyId); 656 mByteArrayProperties.add(String8("mock-message"), message); 657 658 // Properties used in mock test, set by cts test app returned from mock plugin 659 // byte[] mock-signature -> signature 660 index = mByteArrayProperties.indexOfKey(String8("mock-signature")); 661 if (index < 0) { 662 ALOGD("Missing 'mock-request' parameter for mock"); 663 return BAD_VALUE; 664 } else { 665 signature = mByteArrayProperties.valueAt(index); 666 } 667 return OK; 668 } 669 670 status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId, 671 Vector<uint8_t> const &keyId, 672 Vector<uint8_t> const &message, 673 Vector<uint8_t> const &signature, 674 bool &match) 675 { 676 Mutex::Autolock lock(mLock); 677 ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)", 678 vectorToString(sessionId).string(), 679 vectorToString(keyId).string(), 680 vectorToString(message).string(), 681 vectorToString(signature).string()); 682 683 ssize_t index = findSession(sessionId); 684 if (index == kNotFound) { 685 ALOGD("Invalid sessionId"); 686 return BAD_VALUE; 687 } 688 689 // Properties used in mock test, set by mock plugin and verifed cts test app 690 // byte[] keyId -> mock-keyid 691 // byte[] message -> mock-message 692 // byte[] signature -> mock-signature 693 mByteArrayProperties.add(String8("mock-keyid"), keyId); 694 mByteArrayProperties.add(String8("mock-message"), message); 695 mByteArrayProperties.add(String8("mock-signature"), signature); 696 697 // Properties used in mock test, set by cts test app returned from mock plugin 698 // String mock-match "1" or "0" -> match 699 index = mStringProperties.indexOfKey(String8("mock-match")); 700 if (index < 0) { 701 ALOGD("Missing 'mock-request' parameter for mock"); 702 return BAD_VALUE; 703 } else { 704 match = atol(mStringProperties.valueAt(index).string()); 705 } 706 return OK; 707 } 708 709 status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId, 710 String8 const &algorithm, 711 Vector<uint8_t> const &message, 712 Vector<uint8_t> const &wrappedKey, 713 Vector<uint8_t> &signature) 714 { 715 Mutex::Autolock lock(mLock); 716 ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, " 717 "message=%s, signature=%s)", 718 vectorToString(sessionId).string(), 719 algorithm.string(), 720 vectorToString(message).string(), 721 vectorToString(wrappedKey).string(), 722 vectorToString(signature).string()); 723 724 // Properties used in mock test, set by mock plugin and verifed cts test app 725 // byte[] wrappedKey -> mock-wrappedkey 726 // byte[] message -> mock-message 727 // byte[] signature -> mock-signature 728 mByteArrayProperties.add(String8("mock-sessionid"), sessionId); 729 mStringProperties.add(String8("mock-algorithm"), algorithm); 730 mByteArrayProperties.add(String8("mock-message"), message); 731 mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey); 732 mByteArrayProperties.add(String8("mock-signature"), signature); 733 return OK; 734 } 735 736 ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const 737 { 738 ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size()); 739 for (size_t i = 0; i < mSessions.size(); ++i) { 740 if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) { 741 return i; 742 } 743 } 744 return kNotFound; 745 } 746 747 ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const 748 { 749 ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size()); 750 for (size_t i = 0; i < mKeySets.size(); ++i) { 751 if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) { 752 return i; 753 } 754 } 755 return kNotFound; 756 } 757 758 759 // Conversion utilities 760 String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const 761 { 762 return arrayToString(vector.array(), vector.size()); 763 } 764 765 String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const 766 { 767 String8 result("{ "); 768 for (size_t i = 0; i < len; i++) { 769 result.appendFormat("0x%02x ", array[i]); 770 } 771 result += "}"; 772 return result; 773 } 774 775 String8 MockDrmPlugin::stringMapToString(KeyedVector<String8, String8> map) const 776 { 777 String8 result("{ "); 778 for (size_t i = 0; i < map.size(); i++) { 779 result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "", 780 map.keyAt(i).string(), map.valueAt(i).string()); 781 } 782 return result + " }"; 783 } 784 785 bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) { 786 return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0); 787 } 788 789 // 790 // Crypto Plugin 791 // 792 793 bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const 794 { 795 ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime); 796 return false; 797 } 798 799 ssize_t 800 MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16], 801 Mode mode, const void *srcPtr, const SubSample *subSamples, 802 size_t numSubSamples, void *dstPtr, AString * /* errorDetailMsg */) 803 { 804 ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, src=%p, " 805 "subSamples=%s, dst=%p)", 806 (int)secure, 807 arrayToString(key, sizeof(key)).string(), 808 arrayToString(iv, sizeof(iv)).string(), 809 (int)mode, srcPtr, 810 subSamplesToString(subSamples, numSubSamples).string(), 811 dstPtr); 812 return OK; 813 } 814 815 // Conversion utilities 816 String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const 817 { 818 String8 result("{ "); 819 for (size_t i = 0; i < len; i++) { 820 result.appendFormat("0x%02x ", array[i]); 821 } 822 result += "}"; 823 return result; 824 } 825 826 String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples, 827 size_t numSubSamples) const 828 { 829 String8 result; 830 for (size_t i = 0; i < numSubSamples; i++) { 831 result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i, 832 subSamples[i].mNumBytesOfClearData, 833 subSamples[i].mNumBytesOfEncryptedData); 834 } 835 return result; 836 } 837 838}; 839