1 /* 2 * Copyright (C) 2017 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_TAG "drm_hal_vendor_test@1.0" 18 19 #include <openssl/aes.h> 20 #include <random> 21 22 #include "drm_hal_vendor_module_api.h" 23 #include "vendor_modules.h" 24 #include <VtsHalHidlTargetCallbackBase.h> 25 26 #include "android/hardware/drm/1.0/vts/drm_hal_vendor_test.h" 27 28 using std::random_device; 29 using std::mt19937; 30 31 static const uint8_t kInvalidUUID[16] = { 32 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 33 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 34 }; 35 __anonc14513810102null36 static drm_vts::VendorModules* gVendorModules = [] { 37 #if defined(__LP64__) 38 const char* kModulePath = "/data/local/tmp/64/lib"; 39 #else 40 const char* kModulePath = "/data/local/tmp/32/lib"; 41 #endif 42 auto modules = new drm_vts::VendorModules(kModulePath); 43 if (modules->getPathList().size() == 0) { 44 std::cerr << "WARNING: No vendor modules found in " << kModulePath << 45 ", all vendor tests will be skipped" << std::endl; 46 } 47 return modules; 48 }(); 49 50 namespace android { 51 namespace hardware { 52 namespace drm { 53 namespace V1_0 { 54 namespace vts { 55 DrmHalVendorFactoryTest()56 DrmHalVendorFactoryTest::DrmHalVendorFactoryTest() 57 : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>( 58 gVendorModules->getModuleByName(GetParam().instance_))) {} // getModuleByName 59 TEST_P(DrmHalVendorFactoryTest,ValidateConfigurations)60 TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) { 61 const char* kVendorStr = "Vendor module "; 62 size_t count = 0; 63 for (const auto& config : contentConfigurations) { 64 ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name"; 65 ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr 66 << "has no serverUrl"; 67 ASSERT_TRUE(config.initData.size() > 0) << kVendorStr 68 << "has no init data"; 69 ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr 70 << "has no mime type"; 71 ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys"; 72 for (const auto& key : config.keys) { 73 ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr 74 << " has zero length keyId"; 75 ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr 76 << " has zero length key value"; 77 } 78 count++; 79 } 80 EXPECT_NE(0u, count); 81 } 82 83 /** 84 * Ensure the factory doesn't support an invalid scheme UUID 85 */ TEST_P(DrmHalVendorFactoryTest,InvalidPluginNotSupported)86 TEST_P(DrmHalVendorFactoryTest, InvalidPluginNotSupported) { 87 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID)); 88 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID)); 89 } 90 91 /** 92 * Ensure the factory doesn't support an empty UUID 93 */ TEST_P(DrmHalVendorFactoryTest,EmptyPluginUUIDNotSupported)94 TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) { 95 hidl_array<uint8_t, 16> emptyUUID; 96 memset(emptyUUID.data(), 0, 16); 97 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID)); 98 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID)); 99 } 100 101 /** 102 * Check if the factory supports the scheme uuid in the config. 103 */ TEST_P(DrmHalVendorFactoryTest,PluginConfigUUIDSupported)104 TEST_P(DrmHalVendorFactoryTest, PluginConfigUUIDSupported) { 105 RETURN_IF_SKIPPED; 106 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getUUID())); 107 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getUUID())); 108 } 109 110 /** 111 * Ensure empty content type is not supported 112 */ TEST_P(DrmHalVendorFactoryTest,EmptyContentTypeNotSupported)113 TEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) { 114 hidl_string empty; 115 EXPECT_FALSE(drmFactory->isContentTypeSupported(empty)); 116 } 117 118 /** 119 * Ensure invalid content type is not supported 120 */ TEST_P(DrmHalVendorFactoryTest,InvalidContentTypeNotSupported)121 TEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) { 122 hidl_string invalid("abcdabcd"); 123 EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid)); 124 } 125 126 /** 127 * Ensure valid content types in the configs are supported 128 */ TEST_P(DrmHalVendorFactoryTest,ValidContentTypeSupported)129 TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) { 130 RETURN_IF_SKIPPED; 131 for (const auto& config : contentConfigurations) { 132 EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType)); 133 } 134 } 135 136 /** 137 * Ensure vendor drm plugin can be created 138 */ TEST_P(DrmHalVendorFactoryTest,CreateVendorDrmPlugin)139 TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) { 140 RETURN_IF_SKIPPED; 141 hidl_string packageName("android.hardware.drm.test"); 142 auto res = drmFactory->createPlugin( 143 getUUID(), packageName, 144 [&](Status status, const sp<IDrmPlugin>& plugin) { 145 EXPECT_EQ(Status::OK, status); 146 EXPECT_NE(nullptr, plugin.get()); 147 }); 148 EXPECT_OK(res); 149 } 150 151 /** 152 * Ensure vendor crypto plugin can be created 153 */ TEST_P(DrmHalVendorFactoryTest,CreateVendorCryptoPlugin)154 TEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) { 155 RETURN_IF_SKIPPED; 156 hidl_vec<uint8_t> initVec; 157 auto res = cryptoFactory->createPlugin( 158 getUUID(), initVec, 159 [&](Status status, const sp<ICryptoPlugin>& plugin) { 160 EXPECT_EQ(Status::OK, status); 161 EXPECT_NE(nullptr, plugin.get()); 162 }); 163 EXPECT_OK(res); 164 } 165 166 /** 167 * Ensure invalid drm plugin can't be created 168 */ TEST_P(DrmHalVendorFactoryTest,CreateInvalidDrmPlugin)169 TEST_P(DrmHalVendorFactoryTest, CreateInvalidDrmPlugin) { 170 RETURN_IF_SKIPPED; 171 hidl_string packageName("android.hardware.drm.test"); 172 auto res = drmFactory->createPlugin( 173 kInvalidUUID, packageName, 174 [&](Status status, const sp<IDrmPlugin>& plugin) { 175 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 176 EXPECT_EQ(nullptr, plugin.get()); 177 }); 178 EXPECT_OK(res); 179 } 180 181 /** 182 * Ensure invalid crypto plugin can't be created 183 */ TEST_P(DrmHalVendorFactoryTest,CreateInvalidCryptoPlugin)184 TEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) { 185 RETURN_IF_SKIPPED; 186 hidl_vec<uint8_t> initVec; 187 auto res = cryptoFactory->createPlugin( 188 kInvalidUUID, initVec, 189 [&](Status status, const sp<ICryptoPlugin>& plugin) { 190 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 191 EXPECT_EQ(nullptr, plugin.get()); 192 }); 193 EXPECT_OK(res); 194 } 195 196 /** 197 * DrmPlugin tests 198 */ 199 200 /** 201 * Test that a DRM plugin can handle provisioning. While 202 * it is not required that a DRM scheme require provisioning, 203 * it should at least return appropriate status values. If 204 * a provisioning request is returned, it is passed to the 205 * vendor module which should provide a provisioning response 206 * that is delivered back to the HAL. 207 */ 208 TEST_P(DrmHalVendorPluginTest,DoProvisioning)209 TEST_P(DrmHalVendorPluginTest, DoProvisioning) { 210 RETURN_IF_SKIPPED; 211 hidl_string certificateType; 212 hidl_string certificateAuthority; 213 hidl_vec<uint8_t> provisionRequest; 214 hidl_string defaultUrl; 215 auto res = drmPlugin->getProvisionRequest( 216 certificateType, certificateAuthority, 217 [&](Status status, const hidl_vec<uint8_t>& request, 218 const hidl_string& url) { 219 if (status == Status::OK) { 220 EXPECT_NE(request.size(), 0u); 221 provisionRequest = request; 222 defaultUrl = url; 223 } else if (status == Status::ERROR_DRM_CANNOT_HANDLE) { 224 EXPECT_EQ(0u, request.size()); 225 } 226 }); 227 EXPECT_OK(res); 228 229 if (provisionRequest.size() > 0) { 230 vector<uint8_t> response = vendorModule->handleProvisioningRequest( 231 provisionRequest, defaultUrl); 232 ASSERT_NE(0u, response.size()); 233 234 auto res = drmPlugin->provideProvisionResponse( 235 response, [&](Status status, const hidl_vec<uint8_t>&, 236 const hidl_vec<uint8_t>&) { 237 EXPECT_EQ(Status::OK, status); 238 }); 239 EXPECT_OK(res); 240 } 241 } 242 243 /** 244 * The DRM HAL should return BAD_VALUE if an empty provisioning 245 * response is provided. 246 */ TEST_P(DrmHalVendorPluginTest,ProvideEmptyProvisionResponse)247 TEST_P(DrmHalVendorPluginTest, ProvideEmptyProvisionResponse) { 248 RETURN_IF_SKIPPED; 249 hidl_vec<uint8_t> response; 250 auto res = drmPlugin->provideProvisionResponse( 251 response, [&](Status status, const hidl_vec<uint8_t>&, 252 const hidl_vec<uint8_t>&) { 253 EXPECT_EQ(Status::BAD_VALUE, status); 254 }); 255 EXPECT_OK(res); 256 } 257 258 /** 259 * Helper method to open a session and verify that a non-empty 260 * session ID is returned 261 */ openSession()262 SessionId DrmHalVendorPluginTest::openSession() { 263 SessionId sessionId; 264 265 auto res = drmPlugin->openSession([&](Status status, const SessionId& id) { 266 EXPECT_EQ(Status::OK, status); 267 EXPECT_NE(id.size(), 0u); 268 sessionId = id; 269 }); 270 EXPECT_OK(res); 271 return sessionId; 272 } 273 274 /** 275 * Helper method to close a session 276 */ closeSession(const SessionId & sessionId)277 void DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) { 278 Status status = drmPlugin->closeSession(sessionId); 279 EXPECT_EQ(Status::OK, status); 280 } 281 toHidlKeyedVector(const map<string,string> & params)282 KeyedVector DrmHalVendorPluginTest::toHidlKeyedVector( 283 const map<string, string>& params) { 284 std::vector<KeyValue> stdKeyedVector; 285 for (auto it = params.begin(); it != params.end(); ++it) { 286 KeyValue keyValue; 287 keyValue.key = it->first; 288 keyValue.value = it->second; 289 stdKeyedVector.push_back(keyValue); 290 } 291 return KeyedVector(stdKeyedVector); 292 } 293 294 /** 295 * Helper method to load keys for subsequent decrypt tests. 296 * These tests use predetermined key request/response to 297 * avoid requiring a round trip to a license server. 298 */ loadKeys(const SessionId & sessionId,const ContentConfiguration & configuration,const KeyType & type=KeyType::STREAMING)299 hidl_vec<uint8_t> DrmHalVendorPluginTest::loadKeys( 300 const SessionId& sessionId, const ContentConfiguration& configuration, 301 const KeyType& type = KeyType::STREAMING) { 302 hidl_vec<uint8_t> keyRequest; 303 auto res = drmPlugin->getKeyRequest( 304 sessionId, configuration.initData, configuration.mimeType, type, 305 toHidlKeyedVector(configuration.optionalParameters), 306 [&](Status status, const hidl_vec<uint8_t>& request, 307 KeyRequestType type, const hidl_string&) { 308 EXPECT_EQ(Status::OK, status) << "Failed to get " 309 "key request for configuration " 310 << configuration.name; 311 EXPECT_EQ(type, KeyRequestType::INITIAL); 312 EXPECT_NE(request.size(), 0u) << "Expected key request size" 313 " to have length > 0 bytes"; 314 keyRequest = request; 315 }); 316 EXPECT_OK(res); 317 318 /** 319 * Get key response from vendor module 320 */ 321 hidl_vec<uint8_t> keyResponse = 322 vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl); 323 324 EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size " 325 "to have length > 0 bytes"; 326 327 hidl_vec<uint8_t> keySetId; 328 res = drmPlugin->provideKeyResponse( 329 sessionId, keyResponse, 330 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) { 331 EXPECT_EQ(Status::OK, status) << "Failure providing " 332 "key response for configuration " 333 << configuration.name; 334 keySetId = myKeySetId; 335 }); 336 EXPECT_OK(res); 337 return keySetId; 338 } 339 340 /** 341 * Test that a session can be opened and closed 342 */ TEST_P(DrmHalVendorPluginTest,OpenCloseSession)343 TEST_P(DrmHalVendorPluginTest, OpenCloseSession) { 344 RETURN_IF_SKIPPED; 345 auto sessionId = openSession(); 346 closeSession(sessionId); 347 } 348 349 /** 350 * Test that attempting to close an invalid (empty) sessionId 351 * is prohibited with the documented error code. 352 */ TEST_P(DrmHalVendorPluginTest,CloseInvalidSession)353 TEST_P(DrmHalVendorPluginTest, CloseInvalidSession) { 354 RETURN_IF_SKIPPED; 355 SessionId invalidSessionId; 356 Status status = drmPlugin->closeSession(invalidSessionId); 357 EXPECT_EQ(Status::BAD_VALUE, status); 358 } 359 360 /** 361 * Test that attempting to close a valid session twice 362 * is prohibited with the documented error code. 363 */ TEST_P(DrmHalVendorPluginTest,CloseClosedSession)364 TEST_P(DrmHalVendorPluginTest, CloseClosedSession) { 365 RETURN_IF_SKIPPED; 366 auto sessionId = openSession(); 367 closeSession(sessionId); 368 Status status = drmPlugin->closeSession(sessionId); 369 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 370 } 371 372 /** 373 * A get key request should fail if no sessionId is provided 374 */ TEST_P(DrmHalVendorPluginTest,GetKeyRequestNoSession)375 TEST_P(DrmHalVendorPluginTest, GetKeyRequestNoSession) { 376 RETURN_IF_SKIPPED; 377 SessionId invalidSessionId; 378 hidl_vec<uint8_t> initData; 379 hidl_string mimeType = "video/mp4"; 380 KeyedVector optionalParameters; 381 auto res = drmPlugin->getKeyRequest( 382 invalidSessionId, initData, mimeType, KeyType::STREAMING, 383 optionalParameters, 384 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType, 385 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); }); 386 EXPECT_OK(res); 387 } 388 389 /** 390 * Test that an empty sessionID returns BAD_VALUE 391 */ TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptySessionId)392 TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptySessionId) { 393 RETURN_IF_SKIPPED; 394 SessionId session; 395 396 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65, 397 0x79, 0x73, 0x22, 0x3a}; 398 auto res = drmPlugin->provideKeyResponse( 399 session, keyResponse, 400 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 401 EXPECT_EQ(Status::BAD_VALUE, status); 402 EXPECT_EQ(keySetId.size(), 0u); 403 }); 404 EXPECT_OK(res); 405 } 406 407 /** 408 * Test that an empty key response returns BAD_VALUE 409 */ TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptyResponse)410 TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptyResponse) { 411 RETURN_IF_SKIPPED; 412 SessionId session = openSession(); 413 hidl_vec<uint8_t> emptyResponse; 414 auto res = drmPlugin->provideKeyResponse( 415 session, emptyResponse, 416 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 417 EXPECT_EQ(Status::BAD_VALUE, status); 418 EXPECT_EQ(keySetId.size(), 0u); 419 }); 420 EXPECT_OK(res); 421 closeSession(session); 422 } 423 424 /** 425 * Test that a removeKeys on an empty sessionID returns BAD_VALUE 426 */ TEST_P(DrmHalVendorPluginTest,RemoveKeysEmptySessionId)427 TEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) { 428 RETURN_IF_SKIPPED; 429 SessionId sessionId; 430 Status status = drmPlugin->removeKeys(sessionId); 431 EXPECT_TRUE(status == Status::BAD_VALUE); 432 } 433 434 /** 435 * Test that remove keys returns okay on an initialized session 436 * that has no keys. 437 */ TEST_P(DrmHalVendorPluginTest,RemoveKeysNewSession)438 TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) { 439 RETURN_IF_SKIPPED; 440 SessionId sessionId = openSession(); 441 Status status = drmPlugin->removeKeys(sessionId); 442 EXPECT_TRUE(status == Status::OK); 443 closeSession(sessionId); 444 } 445 446 /** 447 * Test that keys are successfully restored to a new session 448 * for all content having a policy that allows offline use. 449 */ TEST_P(DrmHalVendorPluginTest,RestoreKeys)450 TEST_P(DrmHalVendorPluginTest, RestoreKeys) { 451 RETURN_IF_SKIPPED; 452 for (const auto& config : contentConfigurations) { 453 if (config.policy.allowOffline) { 454 auto sessionId = openSession(); 455 hidl_vec<uint8_t> keySetId = 456 loadKeys(sessionId, config, KeyType::OFFLINE); 457 closeSession(sessionId); 458 sessionId = openSession(); 459 EXPECT_NE(0u, keySetId.size()); 460 Status status = drmPlugin->restoreKeys(sessionId, keySetId); 461 EXPECT_EQ(Status::OK, status); 462 closeSession(sessionId); 463 } 464 } 465 } 466 467 /** 468 * Test that restoreKeys fails with a null key set ID. 469 * Error message is expected to be Status::BAD_VALUE. 470 */ TEST_P(DrmHalVendorPluginTest,RestoreKeysNull)471 TEST_P(DrmHalVendorPluginTest, RestoreKeysNull) { 472 RETURN_IF_SKIPPED; 473 SessionId sessionId = openSession(); 474 hidl_vec<uint8_t> nullKeySetId; 475 Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId); 476 EXPECT_EQ(Status::BAD_VALUE, status); 477 closeSession(sessionId); 478 } 479 480 /** 481 * Test that restoreKeys fails to restore keys to a closed 482 * session. Error message is expected to be 483 * Status::ERROR_DRM_SESSION_NOT_OPENED. 484 */ TEST_P(DrmHalVendorPluginTest,RestoreKeysClosedSession)485 TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) { 486 RETURN_IF_SKIPPED; 487 for (const auto& config : contentConfigurations) { 488 if (config.policy.allowOffline) { 489 auto sessionId = openSession(); 490 hidl_vec<uint8_t> keySetId = 491 loadKeys(sessionId, config, KeyType::OFFLINE); 492 EXPECT_NE(0u, keySetId.size()); 493 closeSession(sessionId); 494 sessionId = openSession(); 495 closeSession(sessionId); 496 Status status = drmPlugin->restoreKeys(sessionId, keySetId); 497 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 498 } 499 } 500 } 501 502 /** 503 * Test that the plugin either doesn't support getting 504 * secure stops, or has no secure stops available after 505 * clearing them. 506 */ TEST_P(DrmHalVendorPluginTest,GetSecureStops)507 TEST_P(DrmHalVendorPluginTest, GetSecureStops) { 508 RETURN_IF_SKIPPED; 509 // There may be secure stops, depending on if there were keys 510 // loaded and unloaded previously. Clear them to get to a known 511 // state, then make sure there are none. 512 auto res = drmPlugin->getSecureStops( 513 [&](Status status, const hidl_vec<SecureStop>&) { 514 if (status != Status::OK) { 515 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 516 } 517 }); 518 EXPECT_OK(res); 519 520 res = drmPlugin->getSecureStops( 521 [&](Status status, const hidl_vec<SecureStop>& secureStops) { 522 if (status == Status::OK) { 523 EXPECT_EQ(secureStops.size(), 0u); 524 } else { 525 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 526 } 527 }); 528 EXPECT_OK(res); 529 } 530 531 /** 532 * Test that the clearkey plugin returns BAD_VALUE if 533 * an empty ssid is provided. 534 */ TEST_P(DrmHalVendorPluginTest,GetSecureStopEmptySSID)535 TEST_P(DrmHalVendorPluginTest, GetSecureStopEmptySSID) { 536 RETURN_IF_SKIPPED; 537 SecureStopId ssid; 538 auto res = drmPlugin->getSecureStop( 539 ssid, [&](Status status, const SecureStop&) { 540 EXPECT_EQ(Status::BAD_VALUE, status); 541 }); 542 EXPECT_OK(res); 543 } 544 545 /** 546 * Test that releasing all secure stops either isn't supported 547 * or is completed successfully 548 */ TEST_P(DrmHalVendorPluginTest,ReleaseAllSecureStops)549 TEST_P(DrmHalVendorPluginTest, ReleaseAllSecureStops) { 550 RETURN_IF_SKIPPED; 551 Status status = drmPlugin->releaseAllSecureStops(); 552 EXPECT_TRUE(status == Status::OK || 553 status == Status::ERROR_DRM_CANNOT_HANDLE); 554 } 555 556 /** 557 * Releasing a secure stop without first getting one and sending it to the 558 * server to get a valid SSID should return ERROR_DRM_INVALID_STATE. 559 * This is an optional API so it can also return CANNOT_HANDLE. 560 */ TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopSequenceError)561 TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopSequenceError) { 562 RETURN_IF_SKIPPED; 563 SecureStopId ssid = {1, 2, 3, 4}; 564 Status status = drmPlugin->releaseSecureStop(ssid); 565 EXPECT_TRUE(status == Status::ERROR_DRM_INVALID_STATE || 566 status == Status::ERROR_DRM_CANNOT_HANDLE); 567 } 568 569 /** 570 * Test that releasing a specific secure stop with an empty ssid 571 * return BAD_VALUE. This is an optional API so it can also return 572 * CANNOT_HANDLE. 573 */ TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopEmptySSID)574 TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopEmptySSID) { 575 RETURN_IF_SKIPPED; 576 SecureStopId ssid; 577 Status status = drmPlugin->releaseSecureStop(ssid); 578 EXPECT_TRUE(status == Status::BAD_VALUE || 579 status == Status::ERROR_DRM_CANNOT_HANDLE); 580 } 581 582 /** 583 * The following five tests verify that the properties 584 * defined in the MediaDrm API are supported by 585 * the plugin. 586 */ TEST_P(DrmHalVendorPluginTest,GetVendorProperty)587 TEST_P(DrmHalVendorPluginTest, GetVendorProperty) { 588 RETURN_IF_SKIPPED; 589 auto res = drmPlugin->getPropertyString( 590 "vendor", [&](Status status, const hidl_string& value) { 591 EXPECT_EQ(Status::OK, status); 592 EXPECT_NE(value.size(), 0u); 593 }); 594 EXPECT_OK(res); 595 } 596 TEST_P(DrmHalVendorPluginTest,GetVersionProperty)597 TEST_P(DrmHalVendorPluginTest, GetVersionProperty) { 598 RETURN_IF_SKIPPED; 599 auto res = drmPlugin->getPropertyString( 600 "version", [&](Status status, const hidl_string& value) { 601 EXPECT_EQ(Status::OK, status); 602 EXPECT_NE(value.size(), 0u); 603 }); 604 EXPECT_OK(res); 605 } 606 TEST_P(DrmHalVendorPluginTest,GetDescriptionProperty)607 TEST_P(DrmHalVendorPluginTest, GetDescriptionProperty) { 608 RETURN_IF_SKIPPED; 609 auto res = drmPlugin->getPropertyString( 610 "description", [&](Status status, const hidl_string& value) { 611 EXPECT_EQ(Status::OK, status); 612 EXPECT_NE(value.size(), 0u); 613 }); 614 EXPECT_OK(res); 615 } 616 TEST_P(DrmHalVendorPluginTest,GetAlgorithmsProperty)617 TEST_P(DrmHalVendorPluginTest, GetAlgorithmsProperty) { 618 RETURN_IF_SKIPPED; 619 auto res = drmPlugin->getPropertyString( 620 "algorithms", [&](Status status, const hidl_string& value) { 621 if (status == Status::OK) { 622 EXPECT_NE(value.size(), 0u); 623 } else { 624 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 625 } 626 }); 627 EXPECT_OK(res); 628 } 629 TEST_P(DrmHalVendorPluginTest,GetPropertyUniqueDeviceID)630 TEST_P(DrmHalVendorPluginTest, GetPropertyUniqueDeviceID) { 631 RETURN_IF_SKIPPED; 632 auto res = drmPlugin->getPropertyByteArray( 633 "deviceUniqueId", 634 [&](Status status, const hidl_vec<uint8_t>& value) { 635 if (status == Status::OK) { 636 EXPECT_NE(value.size(), 0u); 637 } else { 638 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 639 } 640 }); 641 EXPECT_OK(res); 642 } 643 644 /** 645 * Test that attempting to read invalid string and byte array 646 * properties returns the documented error code. 647 */ TEST_P(DrmHalVendorPluginTest,GetInvalidStringProperty)648 TEST_P(DrmHalVendorPluginTest, GetInvalidStringProperty) { 649 RETURN_IF_SKIPPED; 650 auto res = drmPlugin->getPropertyString( 651 "invalid", [&](Status status, const hidl_string&) { 652 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 653 }); 654 EXPECT_OK(res); 655 } 656 TEST_P(DrmHalVendorPluginTest,GetInvalidByteArrayProperty)657 TEST_P(DrmHalVendorPluginTest, GetInvalidByteArrayProperty) { 658 RETURN_IF_SKIPPED; 659 auto res = drmPlugin->getPropertyByteArray( 660 "invalid", [&](Status status, const hidl_vec<uint8_t>&) { 661 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 662 }); 663 EXPECT_OK(res); 664 } 665 666 /** 667 * Test that setting invalid string and byte array properties returns 668 * the expected status value. 669 */ TEST_P(DrmHalVendorPluginTest,SetStringPropertyNotSupported)670 TEST_P(DrmHalVendorPluginTest, SetStringPropertyNotSupported) { 671 RETURN_IF_SKIPPED; 672 EXPECT_EQ(drmPlugin->setPropertyString("awefijaeflijwef", "value"), 673 Status::ERROR_DRM_CANNOT_HANDLE); 674 } 675 TEST_P(DrmHalVendorPluginTest,SetByteArrayPropertyNotSupported)676 TEST_P(DrmHalVendorPluginTest, SetByteArrayPropertyNotSupported) { 677 RETURN_IF_SKIPPED; 678 hidl_vec<uint8_t> value; 679 EXPECT_EQ(drmPlugin->setPropertyByteArray("awefijaeflijwef", value), 680 Status::ERROR_DRM_CANNOT_HANDLE); 681 } 682 683 /** 684 * Test that setting an invalid cipher algorithm returns 685 * the expected status value. 686 */ TEST_P(DrmHalVendorPluginTest,SetCipherInvalidAlgorithm)687 TEST_P(DrmHalVendorPluginTest, SetCipherInvalidAlgorithm) { 688 RETURN_IF_SKIPPED; 689 SessionId session = openSession(); 690 hidl_string algorithm; 691 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 692 EXPECT_EQ(Status::BAD_VALUE, status); 693 closeSession(session); 694 } 695 696 /** 697 * Test that setting a cipher algorithm with no session returns 698 * the expected status value. 699 */ TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithmNoSession)700 TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithmNoSession) { 701 RETURN_IF_SKIPPED; 702 SessionId session; 703 hidl_string algorithm = "AES/CBC/NoPadding"; 704 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 705 EXPECT_EQ(Status::BAD_VALUE, status); 706 } 707 708 /** 709 * Test that setting a valid cipher algorithm returns 710 * the expected status value. It is not required that all 711 * vendor modules support this algorithm, but they must 712 * either accept it or return ERROR_DRM_CANNOT_HANDLE 713 */ TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithm)714 TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithm) { 715 RETURN_IF_SKIPPED; 716 SessionId session = openSession(); 717 ; 718 hidl_string algorithm = "AES/CBC/NoPadding"; 719 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 720 EXPECT_TRUE(status == Status::OK || 721 status == Status::ERROR_DRM_CANNOT_HANDLE); 722 closeSession(session); 723 } 724 725 /** 726 * Test that setting an invalid mac algorithm returns 727 * the expected status value. 728 */ TEST_P(DrmHalVendorPluginTest,SetMacInvalidAlgorithm)729 TEST_P(DrmHalVendorPluginTest, SetMacInvalidAlgorithm) { 730 RETURN_IF_SKIPPED; 731 SessionId session = openSession(); 732 hidl_string algorithm; 733 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 734 EXPECT_EQ(Status::BAD_VALUE, status); 735 closeSession(session); 736 } 737 738 /** 739 * Test that setting a mac algorithm with no session returns 740 * the expected status value. 741 */ TEST_P(DrmHalVendorPluginTest,SetMacNullAlgorithmNoSession)742 TEST_P(DrmHalVendorPluginTest, SetMacNullAlgorithmNoSession) { 743 RETURN_IF_SKIPPED; 744 SessionId session; 745 hidl_string algorithm = "HmacSHA256"; 746 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 747 EXPECT_EQ(Status::BAD_VALUE, status); 748 } 749 750 /** 751 * Test that setting a valid mac algorithm returns 752 * the expected status value. It is not required that all 753 * vendor modules support this algorithm, but they must 754 * either accept it or return ERROR_DRM_CANNOT_HANDLE 755 */ TEST_P(DrmHalVendorPluginTest,SetMacAlgorithm)756 TEST_P(DrmHalVendorPluginTest, SetMacAlgorithm) { 757 RETURN_IF_SKIPPED; 758 SessionId session = openSession(); 759 hidl_string algorithm = "HmacSHA256"; 760 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 761 EXPECT_TRUE(status == Status::OK || 762 status == Status::ERROR_DRM_CANNOT_HANDLE); 763 closeSession(session); 764 } 765 766 /** 767 * The Generic* methods provide general purpose crypto operations 768 * that may be used for applications other than DRM. They leverage 769 * the hardware root of trust and secure key distribution mechanisms 770 * of a DRM system to enable app-specific crypto functionality where 771 * the crypto keys are not exposed outside of the trusted execution 772 * environment. 773 * 774 * Generic encrypt/decrypt/sign/verify should fail on invalid 775 * inputs, e.g. empty sessionId 776 */ TEST_P(DrmHalVendorPluginTest,GenericEncryptNoSession)777 TEST_P(DrmHalVendorPluginTest, GenericEncryptNoSession) { 778 RETURN_IF_SKIPPED; 779 SessionId session; 780 hidl_vec<uint8_t> keyId, input, iv; 781 auto res = drmPlugin->encrypt( 782 session, keyId, input, iv, 783 [&](Status status, const hidl_vec<uint8_t>&) { 784 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 785 }); 786 EXPECT_OK(res); 787 } 788 TEST_P(DrmHalVendorPluginTest,GenericDecryptNoSession)789 TEST_P(DrmHalVendorPluginTest, GenericDecryptNoSession) { 790 RETURN_IF_SKIPPED; 791 SessionId session; 792 hidl_vec<uint8_t> keyId, input, iv; 793 auto res = drmPlugin->decrypt( 794 session, keyId, input, iv, 795 [&](Status status, const hidl_vec<uint8_t>&) { 796 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 797 }); 798 EXPECT_OK(res); 799 } 800 TEST_P(DrmHalVendorPluginTest,GenericSignNoSession)801 TEST_P(DrmHalVendorPluginTest, GenericSignNoSession) { 802 RETURN_IF_SKIPPED; 803 SessionId session; 804 hidl_vec<uint8_t> keyId, message; 805 auto res = drmPlugin->sign( 806 session, keyId, message, 807 [&](Status status, const hidl_vec<uint8_t>&) { 808 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 809 }); 810 EXPECT_OK(res); 811 } 812 TEST_P(DrmHalVendorPluginTest,GenericVerifyNoSession)813 TEST_P(DrmHalVendorPluginTest, GenericVerifyNoSession) { 814 RETURN_IF_SKIPPED; 815 SessionId session; 816 hidl_vec<uint8_t> keyId, message, signature; 817 auto res = drmPlugin->verify( 818 session, keyId, message, signature, [&](Status status, bool) { 819 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 820 }); 821 EXPECT_OK(res); 822 } 823 TEST_P(DrmHalVendorPluginTest,GenericSignRSANoSession)824 TEST_P(DrmHalVendorPluginTest, GenericSignRSANoSession) { 825 RETURN_IF_SKIPPED; 826 SessionId session; 827 hidl_string algorithm; 828 hidl_vec<uint8_t> message, wrappedKey; 829 auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey, 830 [&](Status status, const hidl_vec<uint8_t>&) { 831 EXPECT_EQ(Status::BAD_VALUE, status); 832 }); 833 EXPECT_OK(res); 834 } 835 836 /** 837 * Exercise the requiresSecureDecoderComponent method. Additional tests 838 * will verify positive cases with specific vendor content configurations. 839 * Below we just test the negative cases. 840 */ 841 842 /** 843 * Verify that requiresSecureDecoderComponent handles empty mimetype. 844 */ TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderEmptyMimeType)845 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderEmptyMimeType) { 846 RETURN_IF_SKIPPED; 847 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("")); 848 } 849 850 /** 851 * Verify that requiresSecureDecoderComponent handles invalid mimetype. 852 */ TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderInvalidMimeType)853 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) { 854 RETURN_IF_SKIPPED; 855 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("bad")); 856 } 857 858 /** 859 * Verify that requiresSecureDecoderComponent returns true for secure 860 * configurations 861 */ TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderConfig)862 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) { 863 RETURN_IF_SKIPPED; 864 for (const auto& config : contentConfigurations) { 865 for (const auto& key : config.keys) { 866 if (key.isSecure) { 867 EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType)); 868 break; 869 } 870 } 871 } 872 } 873 874 /** 875 * Event Handling tests 876 */ 877 struct ListenerEventArgs { 878 EventType eventType; 879 SessionId sessionId; 880 hidl_vec<uint8_t> data; 881 int64_t expiryTimeInMS; 882 hidl_vec<KeyStatus> keyStatusList; 883 bool hasNewUsableKey; 884 }; 885 886 const char *kCallbackEvent = "SendEvent"; 887 const char *kCallbackExpirationUpdate = "SendExpirationUpdate"; 888 const char *kCallbackKeysChange = "SendKeysChange"; 889 890 class TestDrmPluginListener 891 : public ::testing::VtsHalHidlTargetCallbackBase<ListenerEventArgs>, 892 public IDrmPluginListener { 893 public: TestDrmPluginListener()894 TestDrmPluginListener() { 895 SetWaitTimeoutDefault(std::chrono::milliseconds(500)); 896 } ~TestDrmPluginListener()897 virtual ~TestDrmPluginListener() {} 898 sendEvent(EventType eventType,const hidl_vec<uint8_t> & sessionId,const hidl_vec<uint8_t> & data)899 virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId, 900 const hidl_vec<uint8_t>& data) override { 901 ListenerEventArgs args; 902 args.eventType = eventType; 903 args.sessionId = sessionId; 904 args.data = data; 905 NotifyFromCallback(kCallbackEvent, args); 906 return Void(); 907 } 908 sendExpirationUpdate(const hidl_vec<uint8_t> & sessionId,int64_t expiryTimeInMS)909 virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId, 910 int64_t expiryTimeInMS) override { 911 ListenerEventArgs args; 912 args.sessionId = sessionId; 913 args.expiryTimeInMS = expiryTimeInMS; 914 NotifyFromCallback(kCallbackExpirationUpdate, args); 915 return Void(); 916 } 917 sendKeysChange(const hidl_vec<uint8_t> & sessionId,const hidl_vec<KeyStatus> & keyStatusList,bool hasNewUsableKey)918 virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId, 919 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override { 920 ListenerEventArgs args; 921 args.sessionId = sessionId; 922 args.keyStatusList = keyStatusList; 923 args.hasNewUsableKey = hasNewUsableKey; 924 NotifyFromCallback(kCallbackKeysChange, args); 925 return Void(); 926 } 927 }; 928 929 930 /** 931 * Simulate the plugin sending events. Make sure the listener 932 * gets them. 933 */ TEST_P(DrmHalVendorPluginTest,ListenerEvents)934 TEST_P(DrmHalVendorPluginTest, ListenerEvents) { 935 RETURN_IF_SKIPPED; 936 sp<TestDrmPluginListener> listener = new TestDrmPluginListener(); 937 drmPlugin->setListener(listener); 938 auto sessionId = openSession(); 939 hidl_vec<uint8_t> data = {0, 1, 2}; 940 EventType eventTypes[] = {EventType::PROVISION_REQUIRED, 941 EventType::KEY_NEEDED, 942 EventType::KEY_EXPIRED, 943 EventType::VENDOR_DEFINED, 944 EventType::SESSION_RECLAIMED}; 945 for (auto eventType : eventTypes) { 946 drmPlugin->sendEvent(eventType, sessionId, data); 947 auto result = listener->WaitForCallback(kCallbackEvent); 948 EXPECT_TRUE(result.no_timeout); 949 EXPECT_TRUE(result.args); 950 EXPECT_EQ(eventType, result.args->eventType); 951 EXPECT_EQ(sessionId, result.args->sessionId); 952 EXPECT_EQ(data, result.args->data); 953 } 954 closeSession(sessionId); 955 } 956 957 /** 958 * Simulate the plugin sending expiration updates and make sure 959 * the listener gets them. 960 */ TEST_P(DrmHalVendorPluginTest,ListenerExpirationUpdate)961 TEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) { 962 RETURN_IF_SKIPPED; 963 sp<TestDrmPluginListener> listener = new TestDrmPluginListener(); 964 drmPlugin->setListener(listener); 965 auto sessionId = openSession(); 966 drmPlugin->sendExpirationUpdate(sessionId, 100); 967 auto result = listener->WaitForCallback(kCallbackExpirationUpdate); 968 EXPECT_TRUE(result.no_timeout); 969 EXPECT_TRUE(result.args); 970 EXPECT_EQ(sessionId, result.args->sessionId); 971 EXPECT_EQ(100, result.args->expiryTimeInMS); 972 closeSession(sessionId); 973 } 974 975 /** 976 * Simulate the plugin sending keys change and make sure 977 * the listener gets them. 978 */ TEST_P(DrmHalVendorPluginTest,ListenerKeysChange)979 TEST_P(DrmHalVendorPluginTest, ListenerKeysChange) { 980 RETURN_IF_SKIPPED; 981 sp<TestDrmPluginListener> listener = new TestDrmPluginListener(); 982 drmPlugin->setListener(listener); 983 auto sessionId = openSession(); 984 const hidl_vec<KeyStatus> keyStatusList = { 985 {{1}, KeyStatusType::USABLE}, 986 {{2}, KeyStatusType::EXPIRED}, 987 {{3}, KeyStatusType::OUTPUTNOTALLOWED}, 988 {{4}, KeyStatusType::STATUSPENDING}, 989 {{5}, KeyStatusType::INTERNALERROR}, 990 }; 991 992 drmPlugin->sendKeysChange(sessionId, keyStatusList, true); 993 auto result = listener->WaitForCallback(kCallbackKeysChange); 994 EXPECT_TRUE(result.no_timeout); 995 EXPECT_TRUE(result.args); 996 EXPECT_EQ(sessionId, result.args->sessionId); 997 EXPECT_EQ(keyStatusList, result.args->keyStatusList); 998 closeSession(sessionId); 999 } 1000 1001 /** 1002 * Negative listener tests. Call send methods with no 1003 * listener set. 1004 */ TEST_P(DrmHalVendorPluginTest,NotListening)1005 TEST_P(DrmHalVendorPluginTest, NotListening) { 1006 RETURN_IF_SKIPPED; 1007 sp<TestDrmPluginListener> listener = new TestDrmPluginListener(); 1008 drmPlugin->setListener(listener); 1009 drmPlugin->setListener(nullptr); 1010 1011 SessionId sessionId; 1012 hidl_vec<uint8_t> data; 1013 hidl_vec<KeyStatus> keyStatusList; 1014 drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data); 1015 drmPlugin->sendExpirationUpdate(sessionId, 100); 1016 drmPlugin->sendKeysChange(sessionId, keyStatusList, true); 1017 auto result = listener->WaitForCallbackAny( 1018 {kCallbackEvent, kCallbackExpirationUpdate, kCallbackKeysChange}); 1019 EXPECT_FALSE(result.no_timeout); 1020 } 1021 1022 1023 /** 1024 * CryptoPlugin tests 1025 */ 1026 1027 /** 1028 * Exercise the NotifyResolution API. There is no observable result, 1029 * just call the method for coverage. 1030 */ TEST_P(DrmHalVendorPluginTest,NotifyResolution)1031 TEST_P(DrmHalVendorPluginTest, NotifyResolution) { 1032 RETURN_IF_SKIPPED; 1033 cryptoPlugin->notifyResolution(1920, 1080); 1034 } 1035 1036 /** 1037 * getDecryptMemory allocates memory for decryption, then sets it 1038 * as a shared buffer base in the crypto hal. The allocated and 1039 * mapped IMemory is returned. 1040 * 1041 * @param size the size of the memory segment to allocate 1042 * @param the index of the memory segment which will be used 1043 * to refer to it for decryption. 1044 */ getDecryptMemory(size_t size,size_t index)1045 sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size, 1046 size_t index) { 1047 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); 1048 EXPECT_NE(nullptr, ashmemAllocator.get()); 1049 1050 hidl_memory hidlMemory; 1051 auto res = ashmemAllocator->allocate( 1052 size, [&](bool success, const hidl_memory& memory) { 1053 EXPECT_EQ(success, true); 1054 EXPECT_EQ(memory.size(), size); 1055 hidlMemory = memory; 1056 }); 1057 1058 EXPECT_OK(res); 1059 1060 sp<IMemory> mappedMemory = android::hardware::mapMemory(hidlMemory); 1061 EXPECT_NE(nullptr, mappedMemory.get()); 1062 res = cryptoPlugin->setSharedBufferBase(hidlMemory, index); 1063 EXPECT_OK(res); 1064 return mappedMemory; 1065 } 1066 1067 /** 1068 * Exercise the setMediaDrmSession method. setMediaDrmSession 1069 * is used to associate a drm session with a crypto session. 1070 */ TEST_P(DrmHalVendorPluginTest,SetMediaDrmSession)1071 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSession) { 1072 RETURN_IF_SKIPPED; 1073 auto sessionId = openSession(); 1074 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1075 EXPECT_EQ(Status::OK, status); 1076 closeSession(sessionId); 1077 } 1078 1079 /** 1080 * setMediaDrmSession with a closed session id 1081 */ TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionClosedSession)1082 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionClosedSession) { 1083 RETURN_IF_SKIPPED; 1084 auto sessionId = openSession(); 1085 closeSession(sessionId); 1086 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1087 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 1088 } 1089 1090 /** 1091 * setMediaDrmSession with a empty session id: BAD_VALUE 1092 */ TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionEmptySession)1093 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) { 1094 RETURN_IF_SKIPPED; 1095 SessionId sessionId; 1096 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1097 EXPECT_EQ(Status::BAD_VALUE, status); 1098 } 1099 1100 /** 1101 * Decrypt tests 1102 */ 1103 fillRandom(const sp<IMemory> & memory)1104 void DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) { 1105 random_device rd; 1106 mt19937 rand(rd()); 1107 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) { 1108 auto p = static_cast<uint32_t*>( 1109 static_cast<void*>(memory->getPointer())); 1110 p[i] = rand(); 1111 } 1112 } 1113 queryKeyStatus(SessionId sessionId)1114 hidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) { 1115 hidl_vec<KeyValue> keyStatus; 1116 auto res = drmPlugin->queryKeyStatus(sessionId, 1117 [&](Status status, KeyedVector info) { 1118 EXPECT_EQ(Status::OK, status); 1119 keyStatus = info; 1120 }); 1121 EXPECT_OK(res); 1122 return keyStatus; 1123 } 1124 removeKeys(SessionId sessionId)1125 void DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) { 1126 auto res = drmPlugin->removeKeys(sessionId); 1127 EXPECT_OK(res); 1128 } 1129 decrypt(Mode mode,bool isSecure,const hidl_array<uint8_t,16> & keyId,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const Pattern & pattern,const vector<uint8_t> & key,Status expectedStatus)1130 uint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure, 1131 const hidl_array<uint8_t, 16>& keyId, uint8_t* iv, 1132 const hidl_vec<SubSample>& subSamples, const Pattern& pattern, 1133 const vector<uint8_t>& key, Status expectedStatus) { 1134 const size_t kSegmentIndex = 0; 1135 1136 uint8_t localIv[AES_BLOCK_SIZE]; 1137 memcpy(localIv, iv, AES_BLOCK_SIZE); 1138 1139 size_t totalSize = 0; 1140 for (size_t i = 0; i < subSamples.size(); i++) { 1141 totalSize += subSamples[i].numBytesOfClearData; 1142 totalSize += subSamples[i].numBytesOfEncryptedData; 1143 } 1144 1145 // The first totalSize bytes of shared memory is the encrypted 1146 // input, the second totalSize bytes is the decrypted output. 1147 sp<IMemory> sharedMemory = 1148 getDecryptMemory(totalSize * 2, kSegmentIndex); 1149 1150 SharedBuffer sourceBuffer = { 1151 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; 1152 fillRandom(sharedMemory); 1153 1154 DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY, 1155 {.bufferId = kSegmentIndex, 1156 .offset = totalSize, 1157 .size = totalSize}, 1158 .secureMemory = nullptr}; 1159 uint64_t offset = 0; 1160 uint32_t bytesWritten = 0; 1161 auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern, 1162 subSamples, sourceBuffer, offset, destBuffer, 1163 [&](Status status, uint32_t count, string detailedError) { 1164 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " << 1165 detailedError; 1166 bytesWritten = count; 1167 }); 1168 EXPECT_OK(res); 1169 1170 if (bytesWritten != totalSize) { 1171 return bytesWritten; 1172 } 1173 uint8_t* base = static_cast<uint8_t*>( 1174 static_cast<void*>(sharedMemory->getPointer())); 1175 1176 // generate reference vector 1177 vector<uint8_t> reference(totalSize); 1178 1179 memcpy(localIv, iv, AES_BLOCK_SIZE); 1180 switch (mode) { 1181 case Mode::UNENCRYPTED: 1182 memcpy(&reference[0], base, totalSize); 1183 break; 1184 case Mode::AES_CTR: 1185 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key); 1186 break; 1187 case Mode::AES_CBC: 1188 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key); 1189 break; 1190 case Mode::AES_CBC_CTS: 1191 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported"; 1192 break; 1193 } 1194 1195 // compare reference to decrypted data which is at base + total size 1196 EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]), 1197 static_cast<void*>(base + totalSize), totalSize)) 1198 << "decrypt data mismatch"; 1199 return totalSize; 1200 } 1201 1202 /** 1203 * Decrypt a list of clear+encrypted subsamples using the specified key 1204 * in AES-CTR mode 1205 */ aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1206 void DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src, 1207 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 1208 const vector<uint8_t>& key) { 1209 1210 AES_KEY decryptionKey; 1211 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 1212 1213 size_t offset = 0; 1214 unsigned blockOffset = 0; 1215 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE]; 1216 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE); 1217 1218 for (size_t i = 0; i < subSamples.size(); i++) { 1219 const SubSample& subSample = subSamples[i]; 1220 1221 if (subSample.numBytesOfClearData > 0) { 1222 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData); 1223 offset += subSample.numBytesOfClearData; 1224 } 1225 1226 if (subSample.numBytesOfEncryptedData > 0) { 1227 AES_ctr128_encrypt(src + offset, dest + offset, 1228 subSample.numBytesOfEncryptedData, &decryptionKey, 1229 iv, previousEncryptedCounter, &blockOffset); 1230 offset += subSample.numBytesOfEncryptedData; 1231 } 1232 } 1233 } 1234 1235 /** 1236 * Decrypt a list of clear+encrypted subsamples using the specified key 1237 * in AES-CBC mode 1238 */ aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1239 void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src, 1240 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 1241 const vector<uint8_t>& key) { 1242 AES_KEY decryptionKey; 1243 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 1244 1245 size_t offset = 0; 1246 for (size_t i = 0; i < subSamples.size(); i++) { 1247 const SubSample& subSample = subSamples[i]; 1248 1249 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData); 1250 offset += subSample.numBytesOfClearData; 1251 1252 AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData, 1253 &decryptionKey, iv, 0 /* decrypt */); 1254 offset += subSample.numBytesOfEncryptedData; 1255 } 1256 } 1257 1258 1259 /** 1260 * Test key status with empty session id, should return BAD_VALUE 1261 */ TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusInvalidSession)1262 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) { 1263 RETURN_IF_SKIPPED; 1264 SessionId sessionId; 1265 auto res = drmPlugin->queryKeyStatus(sessionId, 1266 [&](Status status, KeyedVector /* info */) { 1267 EXPECT_EQ(Status::BAD_VALUE, status); 1268 }); 1269 EXPECT_OK(res); 1270 } 1271 1272 1273 /** 1274 * Test key status. There should be no key status prior to loading keys 1275 */ TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusWithNoKeys)1276 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) { 1277 RETURN_IF_SKIPPED; 1278 auto sessionId = openSession(); 1279 auto keyStatus = queryKeyStatus(sessionId); 1280 EXPECT_EQ(0u, keyStatus.size()); 1281 closeSession(sessionId); 1282 } 1283 1284 1285 /** 1286 * Test key status. There should be key status after loading keys. 1287 */ TEST_P(DrmHalVendorDecryptTest,QueryKeyStatus)1288 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) { 1289 RETURN_IF_SKIPPED; 1290 for (const auto& config : contentConfigurations) { 1291 auto sessionId = openSession(); 1292 loadKeys(sessionId, config); 1293 auto keyStatus = queryKeyStatus(sessionId); 1294 EXPECT_NE(0u, keyStatus.size()); 1295 closeSession(sessionId); 1296 } 1297 } 1298 1299 /** 1300 * Positive decrypt test. "Decrypt" a single clear segment and verify. 1301 */ TEST_P(DrmHalVendorDecryptTest,ClearSegmentTest)1302 TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) { 1303 RETURN_IF_SKIPPED; 1304 for (const auto& config : contentConfigurations) { 1305 for (const auto& key : config.keys) { 1306 const size_t kSegmentSize = 1024; 1307 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1308 const Pattern noPattern = {0, 0}; 1309 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize, 1310 .numBytesOfEncryptedData = 0}}; 1311 auto sessionId = openSession(); 1312 loadKeys(sessionId, config); 1313 1314 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1315 EXPECT_EQ(Status::OK, status); 1316 1317 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId), 1318 &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK); 1319 EXPECT_EQ(kSegmentSize, byteCount); 1320 1321 closeSession(sessionId); 1322 } 1323 } 1324 } 1325 1326 /** 1327 * Positive decrypt test. Decrypt a single segment using aes_ctr. 1328 * Verify data matches. 1329 */ TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTest)1330 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) { 1331 RETURN_IF_SKIPPED; 1332 for (const auto& config : contentConfigurations) { 1333 for (const auto& key : config.keys) { 1334 const size_t kSegmentSize = 1024; 1335 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1336 const Pattern noPattern = {0, 0}; 1337 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize, 1338 .numBytesOfEncryptedData = 0}}; 1339 auto sessionId = openSession(); 1340 loadKeys(sessionId, config); 1341 1342 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1343 EXPECT_EQ(Status::OK, status); 1344 1345 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId), 1346 &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK); 1347 EXPECT_EQ(kSegmentSize, byteCount); 1348 1349 closeSession(sessionId); 1350 } 1351 } 1352 } 1353 1354 /** 1355 * Negative decrypt test. Decrypt without loading keys. 1356 */ TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTestNoKeys)1357 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) { 1358 RETURN_IF_SKIPPED; 1359 for (const auto& config : contentConfigurations) { 1360 for (const auto& key : config.keys) { 1361 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1362 const Pattern noPattern = {0, 0}; 1363 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256, 1364 .numBytesOfEncryptedData = 256}}; 1365 auto sessionId = openSession(); 1366 1367 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1368 EXPECT_EQ(Status::OK, status); 1369 1370 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, 1371 toHidlArray(key.keyId), &iv[0], subSamples, noPattern, 1372 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE); 1373 EXPECT_EQ(0u, byteCount); 1374 1375 closeSession(sessionId); 1376 } 1377 } 1378 } 1379 1380 /** 1381 * Test key removal. Load keys then remove them and verify that 1382 * decryption can't be performed. 1383 */ TEST_P(DrmHalVendorDecryptTest,AttemptDecryptWithKeysRemoved)1384 TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) { 1385 RETURN_IF_SKIPPED; 1386 for (const auto& config : contentConfigurations) { 1387 for (const auto& key : config.keys) { 1388 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1389 const Pattern noPattern = {0, 0}; 1390 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256, 1391 .numBytesOfEncryptedData = 256}}; 1392 auto sessionId = openSession(); 1393 1394 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1395 EXPECT_EQ(Status::OK, status); 1396 1397 loadKeys(sessionId, config); 1398 removeKeys(sessionId); 1399 1400 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, 1401 toHidlArray(key.keyId), &iv[0], subSamples, noPattern, 1402 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE); 1403 EXPECT_EQ(0u, byteCount); 1404 1405 closeSession(sessionId); 1406 } 1407 } 1408 } 1409 1410 } // namespace vts 1411 } // namespace V1_0 1412 } // namespace drm 1413 } // namespace hardware 1414 } // namespace android 1415