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_clearkey_test (at) 1.0" 18 19 #include <android/hardware/drm/1.0/ICryptoFactory.h> 20 #include <android/hardware/drm/1.0/ICryptoPlugin.h> 21 #include <android/hardware/drm/1.0/IDrmFactory.h> 22 #include <android/hardware/drm/1.0/IDrmPlugin.h> 23 #include <android/hardware/drm/1.0/types.h> 24 #include <android/hidl/allocator/1.0/IAllocator.h> 25 #include <gtest/gtest.h> 26 #include <hidl/HidlSupport.h> 27 #include <hidlmemory/mapping.h> 28 #include <log/log.h> 29 #include <memory> 30 #include <openssl/aes.h> 31 #include <random> 32 33 #include "VtsHalHidlTargetTestBase.h" 34 35 using ::android::hardware::drm::V1_0::BufferType; 36 using ::android::hardware::drm::V1_0::DestinationBuffer; 37 using ::android::hardware::drm::V1_0::ICryptoFactory; 38 using ::android::hardware::drm::V1_0::ICryptoPlugin; 39 using ::android::hardware::drm::V1_0::IDrmFactory; 40 using ::android::hardware::drm::V1_0::IDrmPlugin; 41 using ::android::hardware::drm::V1_0::KeyedVector; 42 using ::android::hardware::drm::V1_0::KeyValue; 43 using ::android::hardware::drm::V1_0::KeyRequestType; 44 using ::android::hardware::drm::V1_0::KeyType; 45 using ::android::hardware::drm::V1_0::Mode; 46 using ::android::hardware::drm::V1_0::Pattern; 47 using ::android::hardware::drm::V1_0::SecureStop; 48 using ::android::hardware::drm::V1_0::SecureStopId; 49 using ::android::hardware::drm::V1_0::SessionId; 50 using ::android::hardware::drm::V1_0::SharedBuffer; 51 using ::android::hardware::drm::V1_0::Status; 52 using ::android::hardware::drm::V1_0::SubSample; 53 54 using ::android::hardware::hidl_array; 55 using ::android::hardware::hidl_string; 56 using ::android::hardware::hidl_memory; 57 using ::android::hardware::hidl_vec; 58 using ::android::hardware::Return; 59 using ::android::hidl::allocator::V1_0::IAllocator; 60 using ::android::hidl::memory::V1_0::IMemory; 61 using ::android::sp; 62 63 using std::string; 64 using std::unique_ptr; 65 using std::random_device; 66 using std::map; 67 using std::mt19937; 68 using std::vector; 69 70 /** 71 * These clearkey tests use white box knowledge of the legacy clearkey 72 * plugin to verify that the HIDL HAL services and interfaces are working. 73 * It is not intended to verify any vendor's HAL implementation. If you 74 * are looking for vendor HAL tests, see drm_hal_vendor_test.cpp 75 */ 76 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) 77 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) 78 79 static const uint8_t kCommonPsshBoxUUID[16] = { 80 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, 81 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B}; 82 83 // To be used in mpd to specify drm scheme for players 84 static const uint8_t kClearKeyUUID[16] = { 85 0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, 86 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E}; 87 88 static const uint8_t kInvalidUUID[16] = { 89 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 90 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80}; 91 92 class DrmHalClearkeyFactoryTest : public ::testing::VtsHalHidlTargetTestBase { 93 public: 94 virtual void SetUp() override { 95 const ::testing::TestInfo* const test_info = 96 ::testing::UnitTest::GetInstance()->current_test_info(); 97 ALOGD("Running test %s.%s", test_info->test_case_name(), 98 test_info->name()); 99 100 drmFactory = 101 ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(); 102 ASSERT_NE(nullptr, drmFactory.get()); 103 cryptoFactory = 104 ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(); 105 ASSERT_NE(nullptr, cryptoFactory.get()); 106 } 107 108 virtual void TearDown() override {} 109 110 protected: 111 sp<IDrmFactory> drmFactory; 112 sp<ICryptoFactory> cryptoFactory; 113 }; 114 115 /** 116 * Ensure the factory supports both Common Pssh Box UUID and Clearkey Scheme UUID 117 */ 118 TEST_F(DrmHalClearkeyFactoryTest, ClearKeyPluginSupported) { 119 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID)); 120 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID)); 121 122 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kClearKeyUUID)); 123 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID)); 124 } 125 126 /** 127 * Ensure the factory doesn't support an invalid scheme UUID 128 */ 129 TEST_F(DrmHalClearkeyFactoryTest, InvalidPluginNotSupported) { 130 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID)); 131 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID)); 132 } 133 134 /** 135 * Ensure the factory doesn't support an empty UUID 136 */ 137 TEST_F(DrmHalClearkeyFactoryTest, EmptyPluginUUIDNotSupported) { 138 hidl_array<uint8_t, 16> emptyUUID; 139 memset(emptyUUID.data(), 0, 16); 140 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID)); 141 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID)); 142 } 143 144 /** 145 * Ensure empty content type is not supported 146 */ 147 TEST_F(DrmHalClearkeyFactoryTest, EmptyContentTypeNotSupported) { 148 hidl_string empty; 149 EXPECT_FALSE(drmFactory->isContentTypeSupported(empty)); 150 } 151 152 /** 153 * Ensure invalid content type is not supported 154 */ 155 TEST_F(DrmHalClearkeyFactoryTest, InvalidContentTypeNotSupported) { 156 hidl_string invalid("abcdabcd"); 157 EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid)); 158 } 159 160 /** 161 * Ensure valid content type is supported 162 */ 163 TEST_F(DrmHalClearkeyFactoryTest, ValidContentTypeSupported) { 164 hidl_string cencType("cenc"); 165 EXPECT_TRUE(drmFactory->isContentTypeSupported(cencType)); 166 } 167 168 /** 169 * Ensure clearkey drm plugin can be created using Common Pssh Box UUID 170 */ 171 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPluginUsingCommonPsshBoxUuid) { 172 hidl_string packageName("android.hardware.drm.test"); 173 auto res = drmFactory->createPlugin( 174 kCommonPsshBoxUUID, packageName, 175 [&](Status status, const sp<IDrmPlugin>& plugin) { 176 EXPECT_EQ(Status::OK, status); 177 EXPECT_NE(nullptr, plugin.get()); 178 }); 179 EXPECT_OK(res); 180 } 181 182 /** 183 * Ensure clearkey drm plugin can be created using ClearKey UUID 184 */ 185 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPluginUsingClearKeyUuid) { 186 hidl_string packageName("android.hardware.drm.test"); 187 auto res = drmFactory->createPlugin( 188 kClearKeyUUID, packageName, 189 [&](Status status, const sp<IDrmPlugin>& plugin) { 190 EXPECT_EQ(Status::OK, status); 191 EXPECT_NE(nullptr, plugin.get()); 192 }); 193 EXPECT_OK(res); 194 } 195 196 /** 197 * Ensure clearkey crypto plugin can be created using Common Pssh Box UUID 198 */ 199 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPluginUsingCommonPsshBoxUuid) { 200 hidl_vec<uint8_t> initVec; 201 auto res = cryptoFactory->createPlugin( 202 kCommonPsshBoxUUID, initVec, 203 [&](Status status, const sp<ICryptoPlugin>& plugin) { 204 EXPECT_EQ(Status::OK, status); 205 EXPECT_NE(nullptr, plugin.get()); 206 }); 207 EXPECT_OK(res); 208 } 209 210 /** 211 * Ensure clearkey crypto plugin can be created using ClearKey UUID 212 */ 213 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPluginUsingClearKeyUuid) { 214 hidl_vec<uint8_t> initVec; 215 auto res = cryptoFactory->createPlugin( 216 kClearKeyUUID, initVec, 217 [&](Status status, const sp<ICryptoPlugin>& plugin) { 218 EXPECT_EQ(Status::OK, status); 219 EXPECT_NE(nullptr, plugin.get()); 220 }); 221 EXPECT_OK(res); 222 } 223 224 /** 225 * Ensure invalid drm plugin can't be created 226 */ 227 TEST_F(DrmHalClearkeyFactoryTest, CreateInvalidDrmPlugin) { 228 hidl_string packageName("android.hardware.drm.test"); 229 auto res = drmFactory->createPlugin( 230 kInvalidUUID, packageName, 231 [&](Status status, const sp<IDrmPlugin>& plugin) { 232 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 233 EXPECT_EQ(nullptr, plugin.get()); 234 }); 235 EXPECT_OK(res); 236 } 237 238 /** 239 * Ensure invalid crypto plugin can't be created 240 */ 241 TEST_F(DrmHalClearkeyFactoryTest, CreateInvalidCryptoPlugin) { 242 hidl_vec<uint8_t> initVec; 243 auto res = cryptoFactory->createPlugin( 244 kInvalidUUID, initVec, 245 [&](Status status, const sp<ICryptoPlugin>& plugin) { 246 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 247 EXPECT_EQ(nullptr, plugin.get()); 248 }); 249 EXPECT_OK(res); 250 } 251 252 class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest { 253 public: 254 virtual void SetUp() override { 255 // Create factories 256 DrmHalClearkeyFactoryTest::SetUp(); 257 258 ASSERT_NE(nullptr, drmFactory.get()); 259 hidl_string packageName("android.hardware.drm.test"); 260 auto res = drmFactory->createPlugin( 261 kClearKeyUUID, packageName, 262 [this](Status status, const sp<IDrmPlugin>& plugin) { 263 EXPECT_EQ(Status::OK, status); 264 ASSERT_NE(nullptr, plugin.get()); 265 drmPlugin = plugin; 266 }); 267 ASSERT_OK(res); 268 269 hidl_vec<uint8_t> initVec; 270 res = cryptoFactory->createPlugin( 271 kClearKeyUUID, initVec, 272 [this](Status status, const sp<ICryptoPlugin>& plugin) { 273 EXPECT_EQ(Status::OK, status); 274 ASSERT_NE(nullptr, plugin.get()); 275 cryptoPlugin = plugin; 276 }); 277 ASSERT_OK(res); 278 } 279 280 virtual void TearDown() override {} 281 282 SessionId openSession(); 283 void closeSession(const SessionId& sessionId); 284 hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type); 285 sp<IMemory> getDecryptMemory(size_t size, size_t index); 286 287 protected: 288 sp<IDrmPlugin> drmPlugin; 289 sp<ICryptoPlugin> cryptoPlugin; 290 }; 291 292 /** 293 * DrmPlugin tests 294 */ 295 296 /** 297 * Test that the plugin can return a provision request. Since 298 * the clearkey plugin doesn't support provisioning, it is 299 * expected to return Status::ERROR_DRM_CANNOT_HANDLE. 300 */ 301 TEST_F(DrmHalClearkeyPluginTest, GetProvisionRequest) { 302 hidl_string certificateType; 303 hidl_string certificateAuthority; 304 auto res = drmPlugin->getProvisionRequest( 305 certificateType, certificateAuthority, 306 [&](Status status, const hidl_vec<uint8_t>&, const hidl_string&) { 307 // clearkey doesn't require provisioning 308 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 309 }); 310 EXPECT_OK(res); 311 } 312 313 /** 314 * The DRM HAL should return BAD_VALUE if an empty provisioning 315 * response is provided. 316 */ 317 TEST_F(DrmHalClearkeyPluginTest, ProvideEmptyProvisionResponse) { 318 hidl_vec<uint8_t> response; 319 auto res = drmPlugin->provideProvisionResponse( 320 response, [&](Status status, const hidl_vec<uint8_t>&, 321 const hidl_vec<uint8_t>&) { 322 EXPECT_EQ(Status::BAD_VALUE, status); 323 }); 324 EXPECT_OK(res); 325 } 326 327 /** 328 * Helper method to open a session and verify that a non-empty 329 * session ID is returned 330 */ 331 SessionId DrmHalClearkeyPluginTest::openSession() { 332 SessionId sessionId; 333 334 auto res = drmPlugin->openSession( 335 [&sessionId](Status status, const SessionId& id) { 336 EXPECT_EQ(Status::OK, status); 337 EXPECT_NE(0u, id.size()); 338 sessionId = id; 339 }); 340 EXPECT_OK(res); 341 return sessionId; 342 } 343 344 /** 345 * Helper method to close a session 346 */ 347 void DrmHalClearkeyPluginTest::closeSession(const SessionId& sessionId) { 348 auto result = drmPlugin->closeSession(sessionId); 349 EXPECT_EQ(Status::OK, result); 350 } 351 352 /** 353 * Helper method to load keys for subsequent decrypt tests. 354 * These tests use predetermined key request/response to 355 * avoid requiring a round trip to a license server. 356 */ 357 hidl_vec<uint8_t> DrmHalClearkeyPluginTest::loadKeys( 358 const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) { 359 hidl_vec<uint8_t> initData = { 360 // BMFF box header (4 bytes size + 'pssh') 361 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68, 362 // full box header (version = 1 flags = 0) 363 0x01, 0x00, 0x00, 0x00, 364 // system id 365 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 366 0x1e, 0x52, 0xe2, 0xfb, 0x4b, 367 // number of key ids 368 0x00, 0x00, 0x00, 0x01, 369 // key id 370 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 371 0x0d, 0x1e, 0xd0, 0x0d, 0x1e, 372 // size of data, must be zero 373 0x00, 0x00, 0x00, 0x00}; 374 375 hidl_vec<uint8_t> expectedKeyRequest = { 376 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65, 377 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, 378 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 379 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d}; 380 381 hidl_vec<uint8_t> knownKeyResponse = { 382 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22, 383 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 384 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 385 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f, 386 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 387 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a}; 388 389 hidl_string mimeType = "video/mp4"; 390 KeyedVector optionalParameters; 391 auto res = drmPlugin->getKeyRequest( 392 sessionId, initData, mimeType, type, optionalParameters, 393 [&](Status status, const hidl_vec<uint8_t>& request, 394 KeyRequestType requestType, const hidl_string&) { 395 EXPECT_EQ(Status::OK, status); 396 EXPECT_EQ(KeyRequestType::INITIAL, requestType); 397 EXPECT_EQ(request, expectedKeyRequest); 398 }); 399 EXPECT_OK(res); 400 401 hidl_vec<uint8_t> keySetId; 402 res = drmPlugin->provideKeyResponse( 403 sessionId, knownKeyResponse, 404 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) { 405 EXPECT_EQ(Status::OK, status); 406 EXPECT_EQ(0u, myKeySetId.size()); 407 keySetId = myKeySetId; 408 }); 409 EXPECT_OK(res); 410 return keySetId; 411 } 412 413 /** 414 * Test that a session can be opened and closed 415 */ 416 TEST_F(DrmHalClearkeyPluginTest, OpenCloseSession) { 417 auto sessionId = openSession(); 418 closeSession(sessionId); 419 } 420 421 /** 422 * Test that attempting to close an invalid (empty) sessionId 423 * is prohibited with the documented error code. 424 */ 425 TEST_F(DrmHalClearkeyPluginTest, CloseInvalidSession) { 426 SessionId invalidSessionId; 427 Status result = drmPlugin->closeSession(invalidSessionId); 428 EXPECT_EQ(Status::BAD_VALUE, result); 429 } 430 431 /** 432 * Test that attempting to close a session that is already closed 433 * is prohibited with the documented error code. 434 */ 435 TEST_F(DrmHalClearkeyPluginTest, CloseClosedSession) { 436 SessionId sessionId = openSession(); 437 closeSession(sessionId); 438 Status result = drmPlugin->closeSession(sessionId); 439 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, result); 440 } 441 442 /** 443 * A get key request should fail if no sessionId is provided 444 */ 445 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestNoSession) { 446 SessionId invalidSessionId; 447 hidl_vec<uint8_t> initData; 448 hidl_string mimeType = "video/mp4"; 449 KeyedVector optionalParameters; 450 auto res = drmPlugin->getKeyRequest( 451 invalidSessionId, initData, mimeType, KeyType::STREAMING, 452 optionalParameters, 453 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType, 454 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); }); 455 EXPECT_OK(res); 456 } 457 458 /** 459 * The clearkey plugin doesn't support offline key requests. 460 * Test that the plugin returns the expected error code in 461 * this case. 462 */ 463 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestOfflineKeyTypeNotSupported) { 464 auto sessionId = openSession(); 465 hidl_vec<uint8_t> initData; 466 hidl_string mimeType = "video/mp4"; 467 KeyedVector optionalParameters; 468 469 auto res = drmPlugin->getKeyRequest( 470 sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters, 471 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType, 472 const hidl_string&) { 473 // Clearkey plugin doesn't support offline key type 474 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 475 }); 476 EXPECT_OK(res); 477 closeSession(sessionId); 478 } 479 480 /** 481 * Test that the plugin returns the documented error for the 482 * case of attempting to generate a key request using an 483 * invalid mime type 484 */ 485 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestBadMime) { 486 auto sessionId = openSession(); 487 hidl_vec<uint8_t> initData; 488 hidl_string mimeType = "video/unknown"; 489 KeyedVector optionalParameters; 490 auto res = drmPlugin->getKeyRequest( 491 sessionId, initData, mimeType, KeyType::STREAMING, 492 optionalParameters, [&](Status status, const hidl_vec<uint8_t>&, 493 KeyRequestType, const hidl_string&) { 494 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 495 }); 496 EXPECT_OK(res); 497 closeSession(sessionId); 498 } 499 500 /** 501 * Test that a closed sessionID returns SESSION_NOT_OPENED 502 */ 503 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseClosedSession) { 504 SessionId session = openSession(); 505 closeSession(session); 506 507 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65, 508 0x79, 0x73, 0x22, 0x3a}; 509 auto res = drmPlugin->provideKeyResponse( 510 session, keyResponse, 511 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 512 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 513 EXPECT_EQ(0u, keySetId.size()); 514 }); 515 EXPECT_OK(res); 516 } 517 518 /** 519 * Test that an empty sessionID returns BAD_VALUE 520 */ 521 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseInvalidSessionId) { 522 SessionId session; 523 524 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65, 525 0x79, 0x73, 0x22, 0x3a}; 526 auto res = drmPlugin->provideKeyResponse( 527 session, keyResponse, 528 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 529 EXPECT_EQ(Status::BAD_VALUE, status); 530 EXPECT_EQ(0u, keySetId.size()); 531 }); 532 EXPECT_OK(res); 533 } 534 535 /** 536 * Test that an empty key response returns BAD_VALUE 537 */ 538 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseEmptyResponse) { 539 SessionId session = openSession(); 540 hidl_vec<uint8_t> emptyResponse; 541 auto res = drmPlugin->provideKeyResponse( 542 session, emptyResponse, 543 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 544 EXPECT_EQ(Status::BAD_VALUE, status); 545 EXPECT_EQ(0u, keySetId.size()); 546 }); 547 EXPECT_OK(res); 548 closeSession(session); 549 } 550 551 /** 552 * Test that a removeKeys on an empty sessionID returns BAD_VALUE 553 */ 554 TEST_F(DrmHalClearkeyPluginTest, RemoveKeysEmptySessionId) { 555 SessionId sessionId; 556 Status status = drmPlugin->removeKeys(sessionId); 557 EXPECT_TRUE(status == Status::BAD_VALUE); 558 } 559 560 /** 561 * Remove keys is not supported for clearkey. 562 */ 563 TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) { 564 SessionId sessionId = openSession(); 565 Status status = drmPlugin->removeKeys(sessionId); 566 // Clearkey plugin doesn't support remove keys 567 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 568 closeSession(sessionId); 569 } 570 571 /** 572 * Test that ClearKey cannot handle key restoring. 573 * Expected message is Status::ERROR_DRM_CANNOT_HANDLE. 574 */ 575 TEST_F(DrmHalClearkeyPluginTest, RestoreKeysCannotHandle) { 576 hidl_vec<uint8_t> keySetId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 577 SessionId sessionId = openSession(); 578 Status status = drmPlugin->restoreKeys(sessionId, keySetId); 579 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 580 closeSession(sessionId); 581 } 582 583 /** 584 * Test that restoreKeys fails with a null key set ID. 585 * Error message is expected to be Status::BAD_VALUE. 586 */ 587 TEST_F(DrmHalClearkeyPluginTest, RestoreKeysNull) { 588 SessionId sessionId = openSession(); 589 hidl_vec<uint8_t> nullKeySetId; 590 Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId); 591 EXPECT_EQ(Status::BAD_VALUE, status); 592 closeSession(sessionId); 593 } 594 595 /** 596 * Test that the clearkey plugin doesn't support getting 597 * secure stops. 598 */ 599 TEST_F(DrmHalClearkeyPluginTest, GetSecureStops) { 600 auto res = drmPlugin->getSecureStops( 601 [&](Status status, const hidl_vec<SecureStop>&) { 602 // Clearkey plugin doesn't support secure stops 603 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 604 }); 605 EXPECT_OK(res); 606 } 607 608 /** 609 * Test that the clearkey plugin returns BAD_VALUE if 610 * an empty ssid is provided. 611 */ 612 TEST_F(DrmHalClearkeyPluginTest, GetSecureStopEmptySSID) { 613 SecureStopId ssid; 614 auto res = drmPlugin->getSecureStop( 615 ssid, [&](Status status, const SecureStop&) { 616 EXPECT_EQ(Status::BAD_VALUE, status); 617 }); 618 EXPECT_OK(res); 619 } 620 621 /** 622 * Test that releasing all secure stops isn't handled by 623 * clearkey. 624 */ 625 TEST_F(DrmHalClearkeyPluginTest, ReleaseAllSecureStops) { 626 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 627 drmPlugin->releaseAllSecureStops()); 628 } 629 630 /** 631 * Test that releasing a specific secure stop with an empty 632 * SSID returns BAD_VALUE. 633 */ 634 TEST_F(DrmHalClearkeyPluginTest, ReleaseSecureStopEmptySSID) { 635 SecureStopId ssid; 636 Status status = drmPlugin->releaseSecureStop(ssid); 637 EXPECT_EQ(Status::BAD_VALUE, status); 638 } 639 640 /** 641 * The following four tests verify that the properties 642 * defined in the MediaDrm API are supported by 643 * the plugin. 644 */ 645 TEST_F(DrmHalClearkeyPluginTest, GetVendorProperty) { 646 auto res = drmPlugin->getPropertyString( 647 "vendor", [&](Status status, const hidl_string& value) { 648 EXPECT_EQ(Status::OK, status); 649 EXPECT_EQ("Google", value); 650 }); 651 EXPECT_OK(res); 652 } 653 654 TEST_F(DrmHalClearkeyPluginTest, GetVersionProperty) { 655 auto res = drmPlugin->getPropertyString( 656 "version", [&](Status status, const hidl_string& value) { 657 EXPECT_EQ(Status::OK, status); 658 EXPECT_EQ("1.0", value); 659 }); 660 EXPECT_OK(res); 661 } 662 663 TEST_F(DrmHalClearkeyPluginTest, GetDescriptionProperty) { 664 auto res = drmPlugin->getPropertyString( 665 "description", [&](Status status, const hidl_string& value) { 666 EXPECT_EQ(Status::OK, status); 667 EXPECT_EQ("ClearKey CDM", value); 668 }); 669 EXPECT_OK(res); 670 } 671 672 TEST_F(DrmHalClearkeyPluginTest, GetAlgorithmsProperty) { 673 auto res = drmPlugin->getPropertyString( 674 "algorithms", [&](Status status, const hidl_string& value) { 675 EXPECT_EQ(Status::OK, status); 676 EXPECT_EQ("", value); 677 }); 678 EXPECT_OK(res); 679 } 680 681 /** 682 * Test that attempting to read invalid string and byte array 683 * properties returns the documented error code. 684 */ 685 TEST_F(DrmHalClearkeyPluginTest, GetInvalidStringProperty) { 686 auto res = drmPlugin->getPropertyString( 687 "invalid", [&](Status status, const hidl_string&) { 688 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 689 }); 690 EXPECT_OK(res); 691 } 692 693 TEST_F(DrmHalClearkeyPluginTest, GetByteArrayPropertyNotSupported) { 694 auto res = drmPlugin->getPropertyByteArray( 695 "deviceUniqueId", [&](Status status, const hidl_vec<uint8_t>&) { 696 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 697 }); 698 EXPECT_OK(res); 699 } 700 701 /** 702 * Clearkey doesn't support setting string or byte array properties, 703 * particularly an undefined one. 704 */ 705 TEST_F(DrmHalClearkeyPluginTest, SetStringPropertyNotSupported) { 706 Status status = drmPlugin->setPropertyString("property", "value"); 707 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 708 } 709 710 TEST_F(DrmHalClearkeyPluginTest, SetByteArrayPropertyNotSupported) { 711 hidl_vec<uint8_t> value; 712 Status status = drmPlugin->setPropertyByteArray("property", value); 713 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 714 } 715 716 /** 717 * Clearkey doesn't support setting cipher algorithms, verify it 718 */ 719 TEST_F(DrmHalClearkeyPluginTest, SetCipherAlgorithmNotSupported) { 720 SessionId session = openSession(); 721 hidl_string algorithm = "AES/CBC/NoPadding"; 722 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 723 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 724 closeSession(session); 725 } 726 727 /** 728 * Setting an empty algorithm should return BAD_VALUE 729 */ 730 TEST_F(DrmHalClearkeyPluginTest, SetCipherEmptyAlgorithm) { 731 SessionId session = openSession(); 732 hidl_string algorithm; 733 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 734 EXPECT_EQ(Status::BAD_VALUE, status); 735 closeSession(session); 736 } 737 738 /** 739 * Setting a cipher algorithm with no session returns BAD_VALUE 740 */ 741 TEST_F(DrmHalClearkeyPluginTest, SetCipherAlgorithmNoSession) { 742 SessionId session; 743 hidl_string algorithm = "AES/CBC/NoPadding"; 744 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 745 EXPECT_EQ(Status::BAD_VALUE, status); 746 } 747 748 /** 749 * Clearkey doesn't support setting mac algorithms, verify it 750 */ 751 TEST_F(DrmHalClearkeyPluginTest, SetMacAlgorithmNotSupported) { 752 SessionId session = openSession(); 753 hidl_string algorithm = "HmacSHA256"; 754 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 755 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 756 closeSession(session); 757 } 758 759 /** 760 * Setting an empty algorithm should return BAD_VALUE 761 */ 762 TEST_F(DrmHalClearkeyPluginTest, SetMacEmptyAlgorithm) { 763 SessionId session = openSession(); 764 hidl_string algorithm; 765 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 766 EXPECT_EQ(Status::BAD_VALUE, status); 767 closeSession(session); 768 } 769 770 /** 771 * Setting a mac algorithm with no session should return BAD_VALUE 772 */ 773 TEST_F(DrmHalClearkeyPluginTest, SetMacAlgorithmNoSession) { 774 SessionId session; 775 hidl_string algorithm = "HmacSHA256"; 776 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 777 EXPECT_EQ(Status::BAD_VALUE, status); 778 } 779 780 /** 781 * The Generic* methods provide general purpose crypto operations 782 * that may be used for applications other than DRM. They leverage 783 * the hardware root of trust and secure key distribution mechanisms 784 * of a DRM system to enable app-specific crypto functionality where 785 * the crypto keys are not exposed outside of the trusted execution 786 * environment. 787 * 788 * Clearkey doesn't support generic encrypt/decrypt/sign/verify. 789 */ 790 TEST_F(DrmHalClearkeyPluginTest, GenericEncryptNotSupported) { 791 SessionId session = openSession(); 792 ; 793 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 794 hidl_vec<uint8_t> input = {1, 2, 3, 4, 5}; 795 hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0); 796 auto res = drmPlugin->encrypt(session, keyId, input, iv, 797 [&](Status status, const hidl_vec<uint8_t>&) { 798 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 799 status); 800 }); 801 EXPECT_OK(res); 802 closeSession(session); 803 } 804 805 TEST_F(DrmHalClearkeyPluginTest, GenericDecryptNotSupported) { 806 SessionId session = openSession(); 807 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 808 hidl_vec<uint8_t> input = {1, 2, 3, 4, 5}; 809 hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0); 810 auto res = drmPlugin->decrypt(session, keyId, input, iv, 811 [&](Status status, const hidl_vec<uint8_t>&) { 812 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 813 status); 814 }); 815 EXPECT_OK(res); 816 closeSession(session); 817 } 818 819 TEST_F(DrmHalClearkeyPluginTest, GenericSignNotSupported) { 820 SessionId session = openSession(); 821 ; 822 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 823 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5}; 824 auto res = drmPlugin->sign(session, keyId, message, 825 [&](Status status, const hidl_vec<uint8_t>&) { 826 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 827 status); 828 }); 829 EXPECT_OK(res); 830 closeSession(session); 831 } 832 833 TEST_F(DrmHalClearkeyPluginTest, GenericVerifyNotSupported) { 834 SessionId session = openSession(); 835 ; 836 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 837 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5}; 838 hidl_vec<uint8_t> signature = {0, 0, 0, 0, 0, 0, 0, 0, 839 0, 0, 0, 0, 0, 0, 0, 0}; 840 auto res = drmPlugin->verify( 841 session, keyId, message, signature, [&](Status status, bool) { 842 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 843 }); 844 EXPECT_OK(res); 845 closeSession(session); 846 } 847 848 TEST_F(DrmHalClearkeyPluginTest, GenericSignRSANotSupported) { 849 SessionId session = openSession(); 850 hidl_string algorithm = "RSASSA-PSS-SHA1"; 851 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5}; 852 hidl_vec<uint8_t> wrappedKey = {0, 0, 0, 0, 0, 0, 0, 0, 853 0, 0, 0, 0, 0, 0, 0, 0}; 854 auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey, 855 [&](Status status, const hidl_vec<uint8_t>&) { 856 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 857 status); 858 }); 859 EXPECT_OK(res); 860 closeSession(session); 861 } 862 863 /** 864 * CryptoPlugin tests 865 */ 866 867 /** 868 * Clearkey doesn't support secure decoder and is expected to 869 * return false. 870 */ 871 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoder) { 872 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("cenc")); 873 } 874 875 /** 876 * Verify that requiresSecureDecoderComponent handles empty mimetype 877 */ 878 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoderEmptyMimeType) { 879 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("")); 880 } 881 882 /** 883 * Exercise the NotifyResolution API. There is no observable result, 884 * just call the method for coverage. 885 */ 886 TEST_F(DrmHalClearkeyPluginTest, NotifyResolution) { 887 cryptoPlugin->notifyResolution(1920, 1080); 888 } 889 890 /** 891 * getDecryptMemory allocates memory for decryption, then sets it 892 * as a shared buffer base in the crypto hal. The allocated and 893 * mapped IMemory is returned. 894 * 895 * @param size the size of the memory segment to allocate 896 * @param the index of the memory segment which will be used 897 * to refer to it for decryption. 898 */ 899 sp<IMemory> DrmHalClearkeyPluginTest::getDecryptMemory(size_t size, 900 size_t index) { 901 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); 902 EXPECT_NE(nullptr, ashmemAllocator.get()); 903 904 hidl_memory hidlMemory; 905 auto res = ashmemAllocator->allocate( 906 size, [&](bool success, const hidl_memory& memory) { 907 EXPECT_EQ(true, success); 908 EXPECT_OK(cryptoPlugin->setSharedBufferBase(memory, index)); 909 hidlMemory = memory; 910 }); 911 EXPECT_OK(res); 912 913 sp<IMemory> mappedMemory = mapMemory(hidlMemory); 914 EXPECT_NE(nullptr, mappedMemory.get()); 915 EXPECT_OK(cryptoPlugin->setSharedBufferBase(hidlMemory, index)); 916 return mappedMemory; 917 } 918 919 /** 920 * Exercise the setMediaDrmSession method. setMediaDrmSession 921 * is used to associate a drm session with a crypto session. 922 */ 923 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSession) { 924 auto sessionId = openSession(); 925 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 926 EXPECT_EQ(Status::OK, status); 927 closeSession(sessionId); 928 } 929 930 /** 931 * setMediaDrmSession with a closed session id 932 */ 933 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionClosedSession) { 934 auto sessionId = openSession(); 935 closeSession(sessionId); 936 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 937 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 938 } 939 940 /** 941 * setMediaDrmSession with an empty session id: BAD_VALUE. An 942 * empty session clears the previously set session and should 943 * return OK. 944 */ 945 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) { 946 SessionId sessionId; 947 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 948 EXPECT_EQ(Status::OK, status); 949 } 950 951 /** 952 * Decrypt tests 953 */ 954 955 class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest { 956 public: 957 void fillRandom(const sp<IMemory>& memory); 958 hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) { 959 EXPECT_EQ(16u, vec.size()); 960 return hidl_array<uint8_t, 16>(&vec[0]); 961 } 962 uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples, 963 const Pattern& pattern, Status status); 964 void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv, 965 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key); 966 void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv, 967 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key); 968 }; 969 970 void DrmHalClearkeyDecryptTest::fillRandom(const sp<IMemory>& memory) { 971 random_device rd; 972 mt19937 rand(rd()); 973 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) { 974 auto p = static_cast<uint32_t*>( 975 static_cast<void*>(memory->getPointer())); 976 p[i] = rand(); 977 } 978 } 979 980 uint32_t DrmHalClearkeyDecryptTest::decrypt(Mode mode, 981 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 982 const Pattern& pattern, Status expectedStatus) { 983 const size_t kSegmentIndex = 0; 984 const vector<uint8_t> keyId = {0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 985 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d, 986 0x1e, 0xd0, 0x0d, 0x1e}; 987 const vector<uint8_t> contentKey = {0x1a, 0x8a, 0x20, 0x95, 0xe4, 988 0xde, 0xb2, 0xd2, 0x9e, 0xc8, 989 0x16, 0xac, 0x7b, 0xae, 0x20, 0x82}; 990 uint8_t localIv[AES_BLOCK_SIZE]; 991 memcpy(localIv, iv, AES_BLOCK_SIZE); 992 993 size_t totalSize = 0; 994 for (size_t i = 0; i < subSamples.size(); i++) { 995 totalSize += subSamples[i].numBytesOfClearData; 996 totalSize += subSamples[i].numBytesOfEncryptedData; 997 } 998 999 // The first totalSize bytes of shared memory is the encrypted 1000 // input, the second totalSize bytes is the decrypted output. 1001 sp<IMemory> sharedMemory = 1002 getDecryptMemory(totalSize * 2, kSegmentIndex); 1003 1004 const SharedBuffer sourceBuffer = { 1005 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; 1006 fillRandom(sharedMemory); 1007 1008 const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY, 1009 {.bufferId = kSegmentIndex, 1010 .offset = totalSize, 1011 .size = totalSize}, 1012 .secureMemory = nullptr}; 1013 const uint64_t offset = 0; 1014 const bool kNotSecure = false; 1015 uint32_t bytesWritten = 0; 1016 auto res = cryptoPlugin->decrypt(kNotSecure, toHidlArray(keyId), localIv, mode, 1017 pattern, subSamples, sourceBuffer, offset, destBuffer, 1018 [&](Status status, uint32_t count, string detailedError) { 1019 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " << 1020 detailedError; 1021 bytesWritten = count; 1022 }); 1023 EXPECT_OK(res); 1024 1025 if (bytesWritten != totalSize) { 1026 return bytesWritten; 1027 } 1028 uint8_t* base = static_cast<uint8_t*>( 1029 static_cast<void*>(sharedMemory->getPointer())); 1030 1031 // generate reference vector 1032 vector<uint8_t> reference(totalSize); 1033 1034 memcpy(localIv, iv, AES_BLOCK_SIZE); 1035 switch (mode) { 1036 case Mode::UNENCRYPTED: 1037 memcpy(&reference[0], base, totalSize); 1038 break; 1039 case Mode::AES_CTR: 1040 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, contentKey); 1041 break; 1042 case Mode::AES_CBC: 1043 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, contentKey); 1044 break; 1045 case Mode::AES_CBC_CTS: 1046 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported"; 1047 break; 1048 } 1049 1050 // compare reference to decrypted data which is at base + total size 1051 EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]), 1052 static_cast<void*>(base + totalSize), totalSize)) 1053 << "decrypt data mismatch"; 1054 return totalSize; 1055 } 1056 1057 /** 1058 * Decrypt a list of clear+encrypted subsamples using the specified key 1059 * in AES-CTR mode 1060 */ 1061 void DrmHalClearkeyDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src, 1062 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 1063 const vector<uint8_t>& key) { 1064 AES_KEY decryptionKey; 1065 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 1066 1067 size_t offset = 0; 1068 unsigned int blockOffset = 0; 1069 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE]; 1070 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE); 1071 1072 for (size_t i = 0; i < subSamples.size(); i++) { 1073 const SubSample& subSample = subSamples[i]; 1074 1075 if (subSample.numBytesOfClearData > 0) { 1076 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData); 1077 offset += subSample.numBytesOfClearData; 1078 } 1079 1080 if (subSample.numBytesOfEncryptedData > 0) { 1081 AES_ctr128_encrypt(src + offset, dest + offset, 1082 subSample.numBytesOfEncryptedData, &decryptionKey, 1083 iv, previousEncryptedCounter, &blockOffset); 1084 offset += subSample.numBytesOfEncryptedData; 1085 } 1086 } 1087 } 1088 1089 /** 1090 * Decrypt a list of clear+encrypted subsamples using the specified key 1091 * in AES-CBC mode 1092 */ 1093 void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src, 1094 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 1095 const vector<uint8_t>& key) { 1096 AES_KEY decryptionKey; 1097 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 1098 1099 size_t offset = 0; 1100 for (size_t i = 0; i < subSamples.size(); i++) { 1101 memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData); 1102 offset += subSamples[i].numBytesOfClearData; 1103 1104 AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData, 1105 &decryptionKey, iv, 0 /* decrypt */); 1106 offset += subSamples[i].numBytesOfEncryptedData; 1107 } 1108 } 1109 1110 /** 1111 * Test query key status 1112 */ 1113 TEST_F(DrmHalClearkeyDecryptTest, TestQueryKeyStatus) { 1114 auto sessionId = openSession(); 1115 auto res = drmPlugin->queryKeyStatus( 1116 sessionId, [&](Status status, KeyedVector /* info */) { EXPECT_EQ(Status::OK, status); }); 1117 EXPECT_OK(res); 1118 1119 closeSession(sessionId); 1120 } 1121 1122 1123 /** 1124 * Positive decrypt test. "Decrypt" a single clear segment 1125 */ 1126 TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) { 1127 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1128 const Pattern noPattern = {0, 0}; 1129 const uint32_t kByteCount = 256; 1130 const vector<SubSample> subSamples = { 1131 {.numBytesOfClearData = kByteCount, 1132 .numBytesOfEncryptedData = 0}}; 1133 auto sessionId = openSession(); 1134 loadKeys(sessionId); 1135 1136 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1137 EXPECT_EQ(Status::OK, status); 1138 1139 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples, 1140 noPattern, Status::OK); 1141 EXPECT_EQ(kByteCount, byteCount); 1142 1143 closeSession(sessionId); 1144 } 1145 1146 /** 1147 * Positive decrypt test. Decrypt a single segment using AES_CTR. 1148 * Verify data matches. 1149 */ 1150 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) { 1151 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1152 const Pattern noPattern = {0, 0}; 1153 const uint32_t kClearBytes = 512; 1154 const uint32_t kEncryptedBytes = 512; 1155 const vector<SubSample> subSamples = { 1156 {.numBytesOfClearData = kClearBytes, 1157 .numBytesOfEncryptedData = kEncryptedBytes 1158 }}; 1159 auto sessionId = openSession(); 1160 loadKeys(sessionId); 1161 1162 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1163 EXPECT_EQ(Status::OK, status); 1164 1165 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples, 1166 noPattern, Status::OK); 1167 EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount); 1168 1169 closeSession(sessionId); 1170 } 1171 /** 1172 * Negative decrypt test. Decrypt without loading keys. 1173 */ 1174 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTestNoKeys) { 1175 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1176 const Pattern noPattern = {0, 0}; 1177 const vector<SubSample> subSamples = { 1178 {.numBytesOfClearData = 256, 1179 .numBytesOfEncryptedData = 256}}; 1180 auto sessionId = openSession(); 1181 1182 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 1183 EXPECT_EQ(Status::OK, status); 1184 1185 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples, 1186 noPattern, Status::ERROR_DRM_NO_LICENSE); 1187 EXPECT_EQ(0u, byteCount); 1188 1189 closeSession(sessionId); 1190 } 1191