NdkMediaDrm.cpp revision 3305b99ec3804c740aecd2ab6d1edd5c6137b7c6
1/* 2 * Copyright (C) 2014 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 "NdkMediaDrm" 19 20#include "NdkMediaDrm.h" 21 22#include <utils/Log.h> 23#include <utils/StrongPointer.h> 24#include <gui/Surface.h> 25 26#include <media/IDrm.h> 27#include <media/IDrmClient.h> 28#include <media/stagefright/MediaErrors.h> 29#include <binder/IServiceManager.h> 30#include <media/IMediaPlayerService.h> 31#include <ndk/NdkMediaCrypto.h> 32 33 34using namespace android; 35 36typedef Vector<uint8_t> idvec_t; 37 38struct DrmListener: virtual public BnDrmClient 39{ 40private: 41 AMediaDrm *mObj; 42 AMediaDrmEventListener mListener; 43 44public: 45 DrmListener(AMediaDrm *obj, AMediaDrmEventListener listener) : mObj(obj), mListener(listener) {} 46 void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj); 47}; 48 49struct AMediaDrm { 50 sp<IDrm> mDrm; 51 sp<IDrmClient> mDrmClient; 52 List<idvec_t> mIds; 53 KeyedVector<String8, String8> mQueryResults; 54 Vector<uint8_t> mKeyRequest; 55 Vector<uint8_t> mProvisionRequest; 56 String8 mProvisionUrl; 57 String8 mPropertyString; 58 Vector<uint8_t> mPropertyByteArray; 59 List<Vector<uint8_t> > mSecureStops; 60 sp<DrmListener> mListener; 61}; 62 63void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) { 64 if (!mListener) { 65 return; 66 } 67 68 AMediaDrmSessionId sessionId = {NULL, 0}; 69 int32_t sessionIdSize = obj->readInt32(); 70 if (sessionIdSize) { 71 uint8_t *sessionIdData = new uint8_t[sessionIdSize]; 72 sessionId.ptr = sessionIdData; 73 sessionId.length = sessionIdSize; 74 obj->read(sessionIdData, sessionId.length); 75 } 76 77 int32_t dataSize = obj->readInt32(); 78 uint8_t *data = NULL; 79 if (dataSize) { 80 data = new uint8_t[dataSize]; 81 obj->read(data, dataSize); 82 } 83 84 // translate DrmPlugin event types into their NDK equivalents 85 AMediaDrmEventType ndkEventType; 86 switch(eventType) { 87 case DrmPlugin::kDrmPluginEventProvisionRequired: 88 ndkEventType = EVENT_PROVISION_REQUIRED; 89 break; 90 case DrmPlugin::kDrmPluginEventKeyNeeded: 91 ndkEventType = EVENT_KEY_REQUIRED; 92 break; 93 case DrmPlugin::kDrmPluginEventKeyExpired: 94 ndkEventType = EVENT_KEY_EXPIRED; 95 break; 96 case DrmPlugin::kDrmPluginEventVendorDefined: 97 ndkEventType = EVENT_VENDOR_DEFINED; 98 break; 99 default: 100 ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType); 101 return; 102 } 103 104 (*mListener)(mObj, sessionId, ndkEventType, extra, data, dataSize); 105 106 delete [] sessionId.ptr; 107 delete [] data; 108} 109 110 111extern "C" { 112 113static mediadrm_status_t translateStatus(status_t status) { 114 mediadrm_status_t result = MEDIADRM_UNKNOWN_ERROR; 115 switch (status) { 116 case OK: 117 result = MEDIADRM_OK; 118 break; 119 case android::ERROR_DRM_NOT_PROVISIONED: 120 result = MEDIADRM_NOT_PROVISIONED_ERROR; 121 break; 122 case android::ERROR_DRM_RESOURCE_BUSY: 123 result = MEDIADRM_RESOURCE_BUSY_ERROR; 124 break; 125 case android::ERROR_DRM_DEVICE_REVOKED: 126 result = MEDIADRM_DEVICE_REVOKED_ERROR; 127 break; 128 case android::ERROR_DRM_CANNOT_HANDLE: 129 result = MEDIADRM_INVALID_PARAMETER_ERROR; 130 break; 131 case android::ERROR_DRM_TAMPER_DETECTED: 132 result = MEDIADRM_TAMPER_DETECTED_ERROR; 133 break; 134 case android::ERROR_DRM_SESSION_NOT_OPENED: 135 result = MEDIADRM_SESSION_NOT_OPENED_ERROR; 136 break; 137 case android::ERROR_DRM_NO_LICENSE: 138 result = MEDIADRM_NEED_KEY_ERROR; 139 break; 140 case android::ERROR_DRM_LICENSE_EXPIRED: 141 result = MEDIADRM_LICENSE_EXPIRED_ERROR; 142 break; 143 default: 144 result = MEDIADRM_UNKNOWN_ERROR; 145 break; 146 } 147 return result; 148} 149 150static sp<IDrm> CreateDrm() { 151 sp<IServiceManager> sm = defaultServiceManager(); 152 153 sp<IBinder> binder = 154 sm->getService(String16("media.player")); 155 156 sp<IMediaPlayerService> service = 157 interface_cast<IMediaPlayerService>(binder); 158 159 if (service == NULL) { 160 return NULL; 161 } 162 163 sp<IDrm> drm = service->makeDrm(); 164 165 if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) { 166 return NULL; 167 } 168 169 return drm; 170} 171 172 173static sp<IDrm> CreateDrmFromUUID(const AMediaUUID uuid) { 174 sp<IDrm> drm = CreateDrm(); 175 176 if (drm == NULL) { 177 return NULL; 178 } 179 180 status_t err = drm->createPlugin(uuid); 181 182 if (err != OK) { 183 return NULL; 184 } 185 186 return drm; 187} 188 189EXPORT 190bool AMediaDrm_isCryptoSchemeSupported(const AMediaUUID uuid, const char *mimeType) { 191 sp<IDrm> drm = CreateDrm(); 192 193 if (drm == NULL) { 194 return false; 195 } 196 197 String8 mimeStr = mimeType ? String8(mimeType) : String8(""); 198 return drm->isCryptoSchemeSupported(uuid, mimeStr); 199} 200 201EXPORT 202AMediaDrm* AMediaDrm_createByUUID(const AMediaUUID uuid) { 203 AMediaDrm *mObj = new AMediaDrm(); 204 mObj->mDrm = CreateDrmFromUUID(uuid); 205 return mObj; 206} 207 208EXPORT 209void AMediaDrm_release(AMediaDrm *mObj) { 210 if (mObj->mDrm != NULL) { 211 mObj->mDrm->setListener(NULL); 212 mObj->mDrm->destroyPlugin(); 213 mObj->mDrm.clear(); 214 } 215 delete mObj; 216} 217 218EXPORT 219mediadrm_status_t AMediaDrm_setOnEventListener(AMediaDrm *mObj, AMediaDrmEventListener listener) { 220 if (!mObj || mObj->mDrm == NULL) { 221 return MEDIADRM_INVALID_OBJECT_ERROR; 222 } 223 mObj->mListener = new DrmListener(mObj, listener); 224 mObj->mDrm->setListener(mObj->mListener); 225 return MEDIADRM_OK; 226} 227 228 229static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) { 230 iter = mObj->mIds.begin(); 231 while (iter != mObj->mIds.end()) { 232 if (iter->array() == id.ptr && iter->size() == id.length) { 233 return true; 234 } 235 } 236 return false; 237} 238 239EXPORT 240mediadrm_status_t AMediaDrm_openSession(AMediaDrm *mObj, AMediaDrmSessionId &sessionId) { 241 if (!mObj || mObj->mDrm == NULL) { 242 return MEDIADRM_INVALID_OBJECT_ERROR; 243 } 244 Vector<uint8_t> session; 245 status_t status = mObj->mDrm->openSession(session); 246 if (status == OK) { 247 mObj->mIds.push_front(session); 248 List<idvec_t>::iterator iter = mObj->mIds.begin(); 249 sessionId.ptr = iter->array(); 250 sessionId.length = iter->size(); 251 } 252 return MEDIADRM_OK; 253} 254 255EXPORT 256mediadrm_status_t AMediaDrm_closeSession(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId) { 257 if (!mObj || mObj->mDrm == NULL) { 258 return MEDIADRM_INVALID_OBJECT_ERROR; 259 } 260 261 List<idvec_t>::iterator iter; 262 if (!findId(mObj, sessionId, iter)) { 263 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 264 } 265 mObj->mDrm->closeSession(*iter); 266 mObj->mIds.erase(iter); 267 return MEDIADRM_OK; 268} 269 270EXPORT 271mediadrm_status_t AMediaDrm_getKeyRequest(AMediaDrm *mObj, const AMediaDrmScope &scope, 272 const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType, 273 const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters, 274 const uint8_t *&keyRequest, size_t &keyRequestSize) { 275 276 if (!mObj || mObj->mDrm == NULL) { 277 return MEDIADRM_INVALID_OBJECT_ERROR; 278 } 279 if (!mimeType) { 280 return MEDIADRM_INVALID_PARAMETER_ERROR; 281 } 282 283 List<idvec_t>::iterator iter; 284 if (!findId(mObj, scope, iter)) { 285 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 286 } 287 288 Vector<uint8_t> mdInit; 289 mdInit.appendArray(init, initSize); 290 DrmPlugin::KeyType mdKeyType; 291 switch (keyType) { 292 case KEY_TYPE_STREAMING: 293 mdKeyType = DrmPlugin::kKeyType_Streaming; 294 break; 295 case KEY_TYPE_OFFLINE: 296 mdKeyType = DrmPlugin::kKeyType_Offline; 297 break; 298 case KEY_TYPE_RELEASE: 299 mdKeyType = DrmPlugin::kKeyType_Release; 300 break; 301 default: 302 return MEDIADRM_INVALID_PARAMETER_ERROR; 303 } 304 KeyedVector<String8, String8> mdOptionalParameters; 305 for (size_t i = 0; i < numOptionalParameters; i++) { 306 mdOptionalParameters.add(String8(optionalParameters[i].mKey), 307 String8(optionalParameters[i].mValue)); 308 } 309 String8 defaultUrl; 310 status_t status = mObj->mDrm->getKeyRequest(*iter, mdInit, String8(mimeType), 311 mdKeyType, mdOptionalParameters, mObj->mKeyRequest, defaultUrl); 312 if (status != OK) { 313 return translateStatus(status); 314 } else { 315 keyRequest = mObj->mKeyRequest.array(); 316 keyRequestSize = mObj->mKeyRequest.size(); 317 } 318 return MEDIADRM_OK; 319} 320 321EXPORT 322mediadrm_status_t AMediaDrm_provideKeyResponse(AMediaDrm *mObj, const AMediaDrmScope &scope, 323 const uint8_t *response, size_t responseSize, AMediaDrmKeySetId &keySetId) { 324 325 if (!mObj || mObj->mDrm == NULL) { 326 return MEDIADRM_INVALID_OBJECT_ERROR; 327 } 328 if (!response || !responseSize) { 329 return MEDIADRM_INVALID_PARAMETER_ERROR; 330 } 331 332 List<idvec_t>::iterator iter; 333 if (!findId(mObj, scope, iter)) { 334 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 335 } 336 Vector<uint8_t> mdResponse; 337 mdResponse.appendArray(response, responseSize); 338 339 Vector<uint8_t> mdKeySetId; 340 status_t status = mObj->mDrm->provideKeyResponse(*iter, mdResponse, mdKeySetId); 341 if (status == OK) { 342 mObj->mIds.push_front(mdKeySetId); 343 List<idvec_t>::iterator iter = mObj->mIds.begin(); 344 keySetId.ptr = iter->array(); 345 keySetId.length = iter->size(); 346 } else { 347 keySetId.ptr = NULL; 348 keySetId.length = 0; 349 } 350 return MEDIADRM_OK; 351} 352 353EXPORT 354mediadrm_status_t AMediaDrm_restoreKeys(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId, 355 const AMediaDrmKeySetId &keySetId) { 356 357 if (!mObj || mObj->mDrm == NULL) { 358 return MEDIADRM_INVALID_OBJECT_ERROR; 359 } 360 List<idvec_t>::iterator iter; 361 if (!findId(mObj, sessionId, iter)) { 362 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 363 } 364 Vector<uint8_t> keySet; 365 keySet.appendArray(keySetId.ptr, keySetId.length); 366 return translateStatus(mObj->mDrm->restoreKeys(*iter, keySet)); 367} 368 369EXPORT 370mediadrm_status_t AMediaDrm_removeKeys(AMediaDrm *mObj, const AMediaDrmSessionId &keySetId) { 371 if (!mObj || mObj->mDrm == NULL) { 372 return MEDIADRM_INVALID_OBJECT_ERROR; 373 } 374 List<idvec_t>::iterator iter; 375 status_t status; 376 if (!findId(mObj, keySetId, iter)) { 377 Vector<uint8_t> keySet; 378 keySet.appendArray(keySetId.ptr, keySetId.length); 379 status = mObj->mDrm->removeKeys(keySet); 380 } else { 381 status = mObj->mDrm->removeKeys(*iter); 382 mObj->mIds.erase(iter); 383 } 384 return translateStatus(status); 385} 386 387EXPORT 388mediadrm_status_t AMediaDrm_queryKeyStatus(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId, 389 AMediaDrmKeyValue *keyValuePairs, size_t &numPairs) { 390 391 if (!mObj || mObj->mDrm == NULL) { 392 return MEDIADRM_INVALID_OBJECT_ERROR; 393 } 394 List<idvec_t>::iterator iter; 395 if (!findId(mObj, sessionId, iter)) { 396 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 397 } 398 399 status_t status = mObj->mDrm->queryKeyStatus(*iter, mObj->mQueryResults); 400 if (status != OK) { 401 numPairs = 0; 402 return translateStatus(status); 403 } 404 405 if (mObj->mQueryResults.size() > numPairs) { 406 numPairs = mObj->mQueryResults.size(); 407 return MEDIADRM_SHORT_BUFFER; 408 } 409 410 for (size_t i = 0; i < mObj->mQueryResults.size(); i++) { 411 keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string(); 412 keyValuePairs[i].mValue = mObj->mQueryResults.keyAt(i).string(); 413 } 414 numPairs = mObj->mQueryResults.size(); 415 return MEDIADRM_OK; 416} 417 418EXPORT 419mediadrm_status_t AMediaDrm_getProvisionRequest(AMediaDrm *mObj, const uint8_t *&provisionRequest, 420 size_t &provisionRequestSize, const char *&serverUrl) { 421 if (!mObj || mObj->mDrm == NULL) { 422 return MEDIADRM_INVALID_OBJECT_ERROR; 423 } 424 if (!provisionRequestSize || !serverUrl) { 425 return MEDIADRM_INVALID_PARAMETER_ERROR; 426 } 427 428 status_t status = mObj->mDrm->getProvisionRequest(String8(""), String8(""), 429 mObj->mProvisionRequest, mObj->mProvisionUrl); 430 if (status != OK) { 431 return translateStatus(status); 432 } else { 433 provisionRequest = mObj->mProvisionRequest.array(); 434 provisionRequestSize = mObj->mProvisionRequest.size(); 435 serverUrl = mObj->mProvisionUrl.string(); 436 } 437 return MEDIADRM_OK; 438} 439 440EXPORT 441mediadrm_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *mObj, 442 const uint8_t *response, size_t responseSize) { 443 if (!mObj || mObj->mDrm == NULL) { 444 return MEDIADRM_INVALID_OBJECT_ERROR; 445 } 446 if (!response || !responseSize) { 447 return MEDIADRM_INVALID_PARAMETER_ERROR; 448 } 449 450 Vector<uint8_t> mdResponse; 451 mdResponse.appendArray(response, responseSize); 452 453 Vector<uint8_t> unused; 454 return translateStatus(mObj->mDrm->provideProvisionResponse(mdResponse, unused, unused)); 455} 456 457EXPORT 458mediadrm_status_t AMediaDrm_getSecureStops(AMediaDrm *mObj, 459 AMediaDrmSecureStop *secureStops, size_t &numSecureStops) { 460 461 if (!mObj || mObj->mDrm == NULL) { 462 return MEDIADRM_INVALID_OBJECT_ERROR; 463 } 464 status_t status = mObj->mDrm->getSecureStops(mObj->mSecureStops); 465 if (status != OK) { 466 numSecureStops = 0; 467 return translateStatus(status); 468 } 469 if (numSecureStops < mObj->mSecureStops.size()) { 470 return MEDIADRM_SHORT_BUFFER; 471 } 472 List<Vector<uint8_t> >::iterator iter = mObj->mSecureStops.begin(); 473 size_t i = 0; 474 while (iter != mObj->mSecureStops.end()) { 475 secureStops[i].ptr = iter->array(); 476 secureStops[i].length = iter->size(); 477 ++iter; 478 ++i; 479 } 480 numSecureStops = mObj->mSecureStops.size(); 481 return MEDIADRM_OK; 482} 483 484EXPORT 485mediadrm_status_t AMediaDrm_releaseSecureStops(AMediaDrm *mObj, 486 const AMediaDrmSecureStop &ssRelease) { 487 488 if (!mObj || mObj->mDrm == NULL) { 489 return MEDIADRM_INVALID_OBJECT_ERROR; 490 } 491 492 Vector<uint8_t> release; 493 release.appendArray(ssRelease.ptr, ssRelease.length); 494 return translateStatus(mObj->mDrm->releaseSecureStops(release)); 495} 496 497 498EXPORT 499mediadrm_status_t AMediaDrm_getPropertyString(AMediaDrm *mObj, const char *propertyName, 500 const char *&propertyValue) { 501 502 if (!mObj || mObj->mDrm == NULL) { 503 return MEDIADRM_INVALID_OBJECT_ERROR; 504 } 505 506 status_t status = mObj->mDrm->getPropertyString(String8(propertyName), 507 mObj->mPropertyString); 508 509 if (status == OK) { 510 propertyValue = mObj->mPropertyString.string(); 511 } else { 512 propertyValue = NULL; 513 } 514 return translateStatus(status); 515} 516 517EXPORT 518mediadrm_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *mObj, 519 const char *propertyName, AMediaDrmByteArray &propertyValue) { 520 if (!mObj || mObj->mDrm == NULL) { 521 return MEDIADRM_INVALID_OBJECT_ERROR; 522 } 523 524 status_t status = mObj->mDrm->getPropertyByteArray(String8(propertyName), 525 mObj->mPropertyByteArray); 526 527 if (status == OK) { 528 propertyValue.ptr = mObj->mPropertyByteArray.array(); 529 propertyValue.length = mObj->mPropertyByteArray.size(); 530 } else { 531 propertyValue.ptr = NULL; 532 propertyValue.length = 0; 533 } 534 return translateStatus(status); 535} 536 537EXPORT 538mediadrm_status_t AMediaDrm_setPropertyString(AMediaDrm *mObj, 539 const char *propertyName, const char *value) { 540 if (!mObj || mObj->mDrm == NULL) { 541 return MEDIADRM_INVALID_OBJECT_ERROR; 542 } 543 544 return translateStatus(mObj->mDrm->setPropertyString(String8(propertyName), 545 String8(value))); 546} 547 548EXPORT 549mediadrm_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj, 550 const char *propertyName, const uint8_t *value, size_t valueSize) { 551 552 Vector<uint8_t> byteArray; 553 byteArray.appendArray(value, valueSize); 554 555 return translateStatus(mObj->mDrm->getPropertyByteArray(String8(propertyName), 556 byteArray)); 557} 558 559 560static mediadrm_status_t encrypt_decrypt_common(AMediaDrm *mObj, 561 const AMediaDrmSessionId &sessionId, 562 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv, 563 const uint8_t *input, uint8_t *output, size_t dataSize, bool encrypt) { 564 565 if (!mObj || mObj->mDrm == NULL) { 566 return MEDIADRM_INVALID_OBJECT_ERROR; 567 } 568 List<idvec_t>::iterator iter; 569 if (!findId(mObj, sessionId, iter)) { 570 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 571 } 572 573 status_t status = mObj->mDrm->setCipherAlgorithm(*iter, String8(cipherAlgorithm)); 574 if (status != OK) { 575 return translateStatus(status); 576 } 577 578 Vector<uint8_t> keyIdVec; 579 const size_t kKeyIdSize = 16; 580 keyIdVec.appendArray(keyId, kKeyIdSize); 581 582 Vector<uint8_t> inputVec; 583 inputVec.appendArray(input, dataSize); 584 585 Vector<uint8_t> ivVec; 586 const size_t kIvSize = 16; 587 ivVec.appendArray(iv, kIvSize); 588 589 Vector<uint8_t> outputVec; 590 if (encrypt) { 591 status_t status = mObj->mDrm->encrypt(*iter, keyIdVec, inputVec, ivVec, outputVec); 592 } else { 593 status_t status = mObj->mDrm->decrypt(*iter, keyIdVec, inputVec, ivVec, outputVec); 594 } 595 if (status == OK) { 596 memcpy(output, outputVec.array(), outputVec.size()); 597 } 598 return translateStatus(status); 599} 600 601EXPORT 602mediadrm_status_t AMediaDrm_encrypt(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId, 603 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv, 604 const uint8_t *input, uint8_t *output, size_t dataSize) { 605 return encrypt_decrypt_common(mObj, sessionId, cipherAlgorithm, keyId, iv, 606 input, output, dataSize, true); 607} 608 609EXPORT 610mediadrm_status_t AMediaDrm_decrypt(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId, 611 const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv, 612 const uint8_t *input, uint8_t *output, size_t dataSize) { 613 return encrypt_decrypt_common(mObj, sessionId, cipherAlgorithm, keyId, iv, 614 input, output, dataSize, false); 615} 616 617EXPORT 618mediadrm_status_t AMediaDrm_sign(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId, 619 const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize, 620 uint8_t *signature, size_t *signatureSize) { 621 622 if (!mObj || mObj->mDrm == NULL) { 623 return MEDIADRM_INVALID_OBJECT_ERROR; 624 } 625 List<idvec_t>::iterator iter; 626 if (!findId(mObj, sessionId, iter)) { 627 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 628 } 629 630 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm)); 631 if (status != OK) { 632 return translateStatus(status); 633 } 634 635 Vector<uint8_t> keyIdVec; 636 const size_t kKeyIdSize = 16; 637 keyIdVec.appendArray(keyId, kKeyIdSize); 638 639 Vector<uint8_t> messageVec; 640 messageVec.appendArray(message, messageSize); 641 642 Vector<uint8_t> signatureVec; 643 status = mObj->mDrm->sign(*iter, keyIdVec, messageVec, signatureVec); 644 if (signatureVec.size() > *signatureSize) { 645 return MEDIADRM_SHORT_BUFFER; 646 } 647 if (status == OK) { 648 memcpy(signature, signatureVec.array(), signatureVec.size()); 649 } 650 return translateStatus(status); 651} 652 653EXPORT 654mediadrm_status_t AMediaDrm_verify(AMediaDrm *mObj, const AMediaDrmSessionId &sessionId, 655 const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize, 656 const uint8_t *signature, size_t signatureSize) { 657 658 if (!mObj || mObj->mDrm == NULL) { 659 return MEDIADRM_INVALID_OBJECT_ERROR; 660 } 661 List<idvec_t>::iterator iter; 662 if (!findId(mObj, sessionId, iter)) { 663 return MEDIADRM_SESSION_NOT_OPENED_ERROR; 664 } 665 666 status_t status = mObj->mDrm->setMacAlgorithm(*iter, String8(macAlgorithm)); 667 if (status != OK) { 668 return translateStatus(status); 669 } 670 671 Vector<uint8_t> keyIdVec; 672 const size_t kKeyIdSize = 16; 673 keyIdVec.appendArray(keyId, kKeyIdSize); 674 675 Vector<uint8_t> messageVec; 676 messageVec.appendArray(message, messageSize); 677 678 Vector<uint8_t> signatureVec; 679 signatureVec.appendArray(signature, signatureSize); 680 681 bool match; 682 status = mObj->mDrm->verify(*iter, keyIdVec, messageVec, signatureVec, match); 683 if (status == OK) { 684 return match ? MEDIADRM_OK : MEDIADRM_VERIFY_FAILED; 685 } 686 return translateStatus(status); 687} 688 689} // extern "C" 690 691