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 EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk()); 349 } 350 351 /** 352 * Helper method to load keys for subsequent decrypt tests. 353 * These tests use predetermined key request/response to 354 * avoid requiring a round trip to a license server. 355 */ 356 hidl_vec<uint8_t> DrmHalClearkeyPluginTest::loadKeys( 357 const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) { 358 hidl_vec<uint8_t> initData = { 359 // BMFF box header (4 bytes size + 'pssh') 360 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68, 361 // full box header (version = 1 flags = 0) 362 0x01, 0x00, 0x00, 0x00, 363 // system id 364 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 365 0x1e, 0x52, 0xe2, 0xfb, 0x4b, 366 // number of key ids 367 0x00, 0x00, 0x00, 0x01, 368 // key id 369 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 370 0x0d, 0x1e, 0xd0, 0x0d, 0x1e, 371 // size of data, must be zero 372 0x00, 0x00, 0x00, 0x00}; 373 374 hidl_vec<uint8_t> expectedKeyRequest = { 375 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65, 376 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, 377 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 378 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d}; 379 380 hidl_vec<uint8_t> knownKeyResponse = { 381 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22, 382 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 383 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 384 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f, 385 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 386 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a}; 387 388 hidl_string mimeType = "video/mp4"; 389 KeyedVector optionalParameters; 390 auto res = drmPlugin->getKeyRequest( 391 sessionId, initData, mimeType, type, optionalParameters, 392 [&](Status status, const hidl_vec<uint8_t>& request, 393 KeyRequestType requestType, const hidl_string&) { 394 EXPECT_EQ(Status::OK, status); 395 EXPECT_EQ(KeyRequestType::INITIAL, requestType); 396 EXPECT_EQ(request, expectedKeyRequest); 397 }); 398 EXPECT_OK(res); 399 400 hidl_vec<uint8_t> keySetId; 401 res = drmPlugin->provideKeyResponse( 402 sessionId, knownKeyResponse, 403 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) { 404 EXPECT_EQ(Status::OK, status); 405 EXPECT_EQ(0u, myKeySetId.size()); 406 keySetId = myKeySetId; 407 }); 408 EXPECT_OK(res); 409 return keySetId; 410 } 411 412 /** 413 * Test that a session can be opened and closed 414 */ 415 TEST_F(DrmHalClearkeyPluginTest, OpenCloseSession) { 416 auto sessionId = openSession(); 417 closeSession(sessionId); 418 } 419 420 /** 421 * Test that attempting to close an invalid (empty) sessionId 422 * is prohibited with the documented error code. 423 */ 424 TEST_F(DrmHalClearkeyPluginTest, CloseInvalidSession) { 425 SessionId invalidSessionId; 426 Status result = drmPlugin->closeSession(invalidSessionId); 427 EXPECT_EQ(Status::BAD_VALUE, result); 428 } 429 430 /** 431 * Test that attempting to close a session that is already closed 432 * is prohibited with the documented error code. 433 */ 434 TEST_F(DrmHalClearkeyPluginTest, CloseClosedSession) { 435 SessionId sessionId = openSession(); 436 closeSession(sessionId); 437 Status result = drmPlugin->closeSession(sessionId); 438 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, result); 439 } 440 441 /** 442 * A get key request should fail if no sessionId is provided 443 */ 444 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestNoSession) { 445 SessionId invalidSessionId; 446 hidl_vec<uint8_t> initData; 447 hidl_string mimeType = "video/mp4"; 448 KeyedVector optionalParameters; 449 auto res = drmPlugin->getKeyRequest( 450 invalidSessionId, initData, mimeType, KeyType::STREAMING, 451 optionalParameters, 452 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType, 453 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); }); 454 EXPECT_OK(res); 455 } 456 457 /** 458 * The clearkey plugin doesn't support offline key requests. 459 * Test that the plugin returns the expected error code in 460 * this case. 461 */ 462 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestOfflineKeyTypeNotSupported) { 463 auto sessionId = openSession(); 464 hidl_vec<uint8_t> initData; 465 hidl_string mimeType = "video/mp4"; 466 KeyedVector optionalParameters; 467 468 auto res = drmPlugin->getKeyRequest( 469 sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters, 470 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType, 471 const hidl_string&) { 472 // Clearkey plugin doesn't support offline key type 473 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 474 }); 475 EXPECT_OK(res); 476 closeSession(sessionId); 477 } 478 479 /** 480 * Test that the plugin returns the documented error for the 481 * case of attempting to generate a key request using an 482 * invalid mime type 483 */ 484 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestBadMime) { 485 auto sessionId = openSession(); 486 hidl_vec<uint8_t> initData; 487 hidl_string mimeType = "video/unknown"; 488 KeyedVector optionalParameters; 489 auto res = drmPlugin->getKeyRequest( 490 sessionId, initData, mimeType, KeyType::STREAMING, 491 optionalParameters, [&](Status status, const hidl_vec<uint8_t>&, 492 KeyRequestType, const hidl_string&) { 493 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 494 }); 495 EXPECT_OK(res); 496 closeSession(sessionId); 497 } 498 499 /** 500 * Test that a closed sessionID returns SESSION_NOT_OPENED 501 */ 502 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseClosedSession) { 503 SessionId session = openSession(); 504 closeSession(session); 505 506 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65, 507 0x79, 0x73, 0x22, 0x3a}; 508 auto res = drmPlugin->provideKeyResponse( 509 session, keyResponse, 510 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 511 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 512 EXPECT_EQ(0u, keySetId.size()); 513 }); 514 EXPECT_OK(res); 515 } 516 517 /** 518 * Test that an empty sessionID returns BAD_VALUE 519 */ 520 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseInvalidSessionId) { 521 SessionId session; 522 523 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65, 524 0x79, 0x73, 0x22, 0x3a}; 525 auto res = drmPlugin->provideKeyResponse( 526 session, keyResponse, 527 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 528 EXPECT_EQ(Status::BAD_VALUE, status); 529 EXPECT_EQ(0u, keySetId.size()); 530 }); 531 EXPECT_OK(res); 532 } 533 534 /** 535 * Test that an empty key response returns BAD_VALUE 536 */ 537 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseEmptyResponse) { 538 SessionId session = openSession(); 539 hidl_vec<uint8_t> emptyResponse; 540 auto res = drmPlugin->provideKeyResponse( 541 session, emptyResponse, 542 [&](Status status, const hidl_vec<uint8_t>& keySetId) { 543 EXPECT_EQ(Status::BAD_VALUE, status); 544 EXPECT_EQ(0u, keySetId.size()); 545 }); 546 EXPECT_OK(res); 547 closeSession(session); 548 } 549 550 /** 551 * Test that a removeKeys on an empty sessionID returns BAD_VALUE 552 */ 553 TEST_F(DrmHalClearkeyPluginTest, RemoveKeysEmptySessionId) { 554 SessionId sessionId; 555 Status status = drmPlugin->removeKeys(sessionId); 556 EXPECT_TRUE(status == Status::BAD_VALUE); 557 } 558 559 /** 560 * Remove keys is not supported for clearkey. 561 */ 562 TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) { 563 SessionId sessionId = openSession(); 564 Status status = drmPlugin->removeKeys(sessionId); 565 // Clearkey plugin doesn't support remove keys 566 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 567 closeSession(sessionId); 568 } 569 570 /** 571 * Test that ClearKey cannot handle key restoring. 572 * Expected message is Status::ERROR_DRM_CANNOT_HANDLE. 573 */ 574 TEST_F(DrmHalClearkeyPluginTest, RestoreKeysCannotHandle) { 575 hidl_vec<uint8_t> keySetId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 576 SessionId sessionId = openSession(); 577 Status status = drmPlugin->restoreKeys(sessionId, keySetId); 578 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 579 closeSession(sessionId); 580 } 581 582 /** 583 * Test that restoreKeys fails with a null key set ID. 584 * Error message is expected to be Status::BAD_VALUE. 585 */ 586 TEST_F(DrmHalClearkeyPluginTest, RestoreKeysNull) { 587 SessionId sessionId = openSession(); 588 hidl_vec<uint8_t> nullKeySetId; 589 Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId); 590 EXPECT_EQ(Status::BAD_VALUE, status); 591 closeSession(sessionId); 592 } 593 594 /** 595 * Test that the clearkey plugin doesn't support getting 596 * secure stops. 597 */ 598 TEST_F(DrmHalClearkeyPluginTest, GetSecureStops) { 599 auto res = drmPlugin->getSecureStops( 600 [&](Status status, const hidl_vec<SecureStop>&) { 601 // Clearkey plugin doesn't support secure stops 602 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 603 }); 604 EXPECT_OK(res); 605 } 606 607 /** 608 * Test that the clearkey plugin returns BAD_VALUE if 609 * an empty ssid is provided. 610 */ 611 TEST_F(DrmHalClearkeyPluginTest, GetSecureStopEmptySSID) { 612 SecureStopId ssid; 613 auto res = drmPlugin->getSecureStop( 614 ssid, [&](Status status, const SecureStop&) { 615 EXPECT_EQ(Status::BAD_VALUE, status); 616 }); 617 EXPECT_OK(res); 618 } 619 620 /** 621 * Test that releasing all secure stops isn't handled by 622 * clearkey. 623 */ 624 TEST_F(DrmHalClearkeyPluginTest, ReleaseAllSecureStops) { 625 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 626 drmPlugin->releaseAllSecureStops()); 627 } 628 629 /** 630 * Test that releasing a specific secure stop with an empty 631 * SSID returns BAD_VALUE. 632 */ 633 TEST_F(DrmHalClearkeyPluginTest, ReleaseSecureStopEmptySSID) { 634 SecureStopId ssid; 635 Status status = drmPlugin->releaseSecureStop(ssid); 636 EXPECT_EQ(Status::BAD_VALUE, status); 637 } 638 639 /** 640 * The following four tests verify that the properties 641 * defined in the MediaDrm API are supported by 642 * the plugin. 643 */ 644 TEST_F(DrmHalClearkeyPluginTest, GetVendorProperty) { 645 auto res = drmPlugin->getPropertyString( 646 "vendor", [&](Status status, const hidl_string& value) { 647 EXPECT_EQ(Status::OK, status); 648 EXPECT_EQ("Google", value); 649 }); 650 EXPECT_OK(res); 651 } 652 653 TEST_F(DrmHalClearkeyPluginTest, GetVersionProperty) { 654 auto res = drmPlugin->getPropertyString( 655 "version", [&](Status status, const hidl_string& value) { 656 EXPECT_EQ(Status::OK, status); 657 EXPECT_EQ("1.0", value); 658 }); 659 EXPECT_OK(res); 660 } 661 662 TEST_F(DrmHalClearkeyPluginTest, GetDescriptionProperty) { 663 auto res = drmPlugin->getPropertyString( 664 "description", [&](Status status, const hidl_string& value) { 665 EXPECT_EQ(Status::OK, status); 666 EXPECT_EQ("ClearKey CDM", value); 667 }); 668 EXPECT_OK(res); 669 } 670 671 TEST_F(DrmHalClearkeyPluginTest, GetAlgorithmsProperty) { 672 auto res = drmPlugin->getPropertyString( 673 "algorithms", [&](Status status, const hidl_string& value) { 674 EXPECT_EQ(Status::OK, status); 675 EXPECT_EQ("", value); 676 }); 677 EXPECT_OK(res); 678 } 679 680 /** 681 * Test that attempting to read invalid string and byte array 682 * properties returns the documented error code. 683 */ 684 TEST_F(DrmHalClearkeyPluginTest, GetInvalidStringProperty) { 685 auto res = drmPlugin->getPropertyString( 686 "invalid", [&](Status status, const hidl_string&) { 687 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 688 }); 689 EXPECT_OK(res); 690 } 691 692 TEST_F(DrmHalClearkeyPluginTest, GetByteArrayPropertyNotSupported) { 693 auto res = drmPlugin->getPropertyByteArray( 694 "deviceUniqueId", [&](Status status, const hidl_vec<uint8_t>&) { 695 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 696 }); 697 EXPECT_OK(res); 698 } 699 700 /** 701 * Clearkey doesn't support setting string or byte array properties, 702 * particularly an undefined one. 703 */ 704 TEST_F(DrmHalClearkeyPluginTest, SetStringPropertyNotSupported) { 705 Status status = drmPlugin->setPropertyString("property", "value"); 706 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 707 } 708 709 TEST_F(DrmHalClearkeyPluginTest, SetByteArrayPropertyNotSupported) { 710 hidl_vec<uint8_t> value; 711 Status status = drmPlugin->setPropertyByteArray("property", value); 712 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 713 } 714 715 /** 716 * Clearkey doesn't support setting cipher algorithms, verify it 717 */ 718 TEST_F(DrmHalClearkeyPluginTest, SetCipherAlgorithmNotSupported) { 719 SessionId session = openSession(); 720 hidl_string algorithm = "AES/CBC/NoPadding"; 721 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 722 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 723 closeSession(session); 724 } 725 726 /** 727 * Setting an empty algorithm should return BAD_VALUE 728 */ 729 TEST_F(DrmHalClearkeyPluginTest, SetCipherEmptyAlgorithm) { 730 SessionId session = openSession(); 731 hidl_string algorithm; 732 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 733 EXPECT_EQ(Status::BAD_VALUE, status); 734 closeSession(session); 735 } 736 737 /** 738 * Setting a cipher algorithm with no session returns BAD_VALUE 739 */ 740 TEST_F(DrmHalClearkeyPluginTest, SetCipherAlgorithmNoSession) { 741 SessionId session; 742 hidl_string algorithm = "AES/CBC/NoPadding"; 743 Status status = drmPlugin->setCipherAlgorithm(session, algorithm); 744 EXPECT_EQ(Status::BAD_VALUE, status); 745 } 746 747 /** 748 * Clearkey doesn't support setting mac algorithms, verify it 749 */ 750 TEST_F(DrmHalClearkeyPluginTest, SetMacAlgorithmNotSupported) { 751 SessionId session = openSession(); 752 hidl_string algorithm = "HmacSHA256"; 753 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 754 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 755 closeSession(session); 756 } 757 758 /** 759 * Setting an empty algorithm should return BAD_VALUE 760 */ 761 TEST_F(DrmHalClearkeyPluginTest, SetMacEmptyAlgorithm) { 762 SessionId session = openSession(); 763 hidl_string algorithm; 764 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 765 EXPECT_EQ(Status::BAD_VALUE, status); 766 closeSession(session); 767 } 768 769 /** 770 * Setting a mac algorithm with no session should return BAD_VALUE 771 */ 772 TEST_F(DrmHalClearkeyPluginTest, SetMacAlgorithmNoSession) { 773 SessionId session; 774 hidl_string algorithm = "HmacSHA256"; 775 Status status = drmPlugin->setMacAlgorithm(session, algorithm); 776 EXPECT_EQ(Status::BAD_VALUE, status); 777 } 778 779 /** 780 * The Generic* methods provide general purpose crypto operations 781 * that may be used for applications other than DRM. They leverage 782 * the hardware root of trust and secure key distribution mechanisms 783 * of a DRM system to enable app-specific crypto functionality where 784 * the crypto keys are not exposed outside of the trusted execution 785 * environment. 786 * 787 * Clearkey doesn't support generic encrypt/decrypt/sign/verify. 788 */ 789 TEST_F(DrmHalClearkeyPluginTest, GenericEncryptNotSupported) { 790 SessionId session = openSession(); 791 792 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 793 hidl_vec<uint8_t> input = {1, 2, 3, 4, 5}; 794 hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0); 795 auto res = drmPlugin->encrypt(session, keyId, input, iv, 796 [&](Status status, const hidl_vec<uint8_t>&) { 797 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 798 status); 799 }); 800 EXPECT_OK(res); 801 closeSession(session); 802 } 803 804 TEST_F(DrmHalClearkeyPluginTest, GenericDecryptNotSupported) { 805 SessionId session = openSession(); 806 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 807 hidl_vec<uint8_t> input = {1, 2, 3, 4, 5}; 808 hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0); 809 auto res = drmPlugin->decrypt(session, keyId, input, iv, 810 [&](Status status, const hidl_vec<uint8_t>&) { 811 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 812 status); 813 }); 814 EXPECT_OK(res); 815 closeSession(session); 816 } 817 818 TEST_F(DrmHalClearkeyPluginTest, GenericSignNotSupported) { 819 SessionId session = openSession(); 820 821 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 822 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5}; 823 auto res = drmPlugin->sign(session, keyId, message, 824 [&](Status status, const hidl_vec<uint8_t>&) { 825 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 826 status); 827 }); 828 EXPECT_OK(res); 829 closeSession(session); 830 } 831 832 TEST_F(DrmHalClearkeyPluginTest, GenericVerifyNotSupported) { 833 SessionId session = openSession(); 834 835 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; 836 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5}; 837 hidl_vec<uint8_t> signature = {0, 0, 0, 0, 0, 0, 0, 0, 838 0, 0, 0, 0, 0, 0, 0, 0}; 839 auto res = drmPlugin->verify( 840 session, keyId, message, signature, [&](Status status, bool) { 841 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status); 842 }); 843 EXPECT_OK(res); 844 closeSession(session); 845 } 846 847 TEST_F(DrmHalClearkeyPluginTest, GenericSignRSANotSupported) { 848 SessionId session = openSession(); 849 hidl_string algorithm = "RSASSA-PSS-SHA1"; 850 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5}; 851 hidl_vec<uint8_t> wrappedKey = {0, 0, 0, 0, 0, 0, 0, 0, 852 0, 0, 0, 0, 0, 0, 0, 0}; 853 auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey, 854 [&](Status status, const hidl_vec<uint8_t>&) { 855 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, 856 status); 857 }); 858 EXPECT_OK(res); 859 closeSession(session); 860 } 861 862 /** 863 * CryptoPlugin tests 864 */ 865 866 /** 867 * Clearkey doesn't support secure decoder and is expected to 868 * return false. 869 */ 870 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoder) { 871 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("cenc")); 872 } 873 874 /** 875 * Verify that requiresSecureDecoderComponent handles empty mimetype 876 */ 877 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoderEmptyMimeType) { 878 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("")); 879 } 880 881 /** 882 * Exercise the NotifyResolution API. There is no observable result, 883 * just call the method for coverage. 884 */ 885 TEST_F(DrmHalClearkeyPluginTest, NotifyResolution) { 886 cryptoPlugin->notifyResolution(1920, 1080); 887 } 888 889 /** 890 * getDecryptMemory allocates memory for decryption, then sets it 891 * as a shared buffer base in the crypto hal. The allocated and 892 * mapped IMemory is returned. 893 * 894 * @param size the size of the memory segment to allocate 895 * @param the index of the memory segment which will be used 896 * to refer to it for decryption. 897 */ 898 sp<IMemory> DrmHalClearkeyPluginTest::getDecryptMemory(size_t size, 899 size_t index) { 900 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); 901 EXPECT_NE(nullptr, ashmemAllocator.get()); 902 903 hidl_memory hidlMemory; 904 auto res = ashmemAllocator->allocate( 905 size, [&](bool success, const hidl_memory& memory) { 906 EXPECT_EQ(true, success); 907 EXPECT_OK(cryptoPlugin->setSharedBufferBase(memory, index)); 908 hidlMemory = memory; 909 }); 910 EXPECT_OK(res); 911 912 sp<IMemory> mappedMemory = mapMemory(hidlMemory); 913 EXPECT_NE(nullptr, mappedMemory.get()); 914 EXPECT_OK(cryptoPlugin->setSharedBufferBase(hidlMemory, index)); 915 return mappedMemory; 916 } 917 918 /** 919 * Exercise the setMediaDrmSession method. setMediaDrmSession 920 * is used to associate a drm session with a crypto session. 921 */ 922 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSession) { 923 auto sessionId = openSession(); 924 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 925 closeSession(sessionId); 926 } 927 928 /** 929 * setMediaDrmSession with a closed session id 930 */ 931 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionClosedSession) { 932 auto sessionId = openSession(); 933 closeSession(sessionId); 934 Status status = cryptoPlugin->setMediaDrmSession(sessionId); 935 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status); 936 } 937 938 /** 939 * setMediaDrmSession with an empty session id: BAD_VALUE. An 940 * empty session clears the previously set session and should 941 * return OK. 942 */ 943 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) { 944 SessionId sessionId; 945 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 946 } 947 948 /** 949 * Decrypt tests 950 */ 951 952 class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest { 953 public: 954 void fillRandom(const sp<IMemory>& memory); 955 hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) { 956 EXPECT_EQ(16u, vec.size()); 957 return hidl_array<uint8_t, 16>(&vec[0]); 958 } 959 uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples, 960 const Pattern& pattern, Status status); 961 void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv, 962 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key); 963 void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv, 964 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key); 965 void decryptWithInvalidKeys(hidl_vec<uint8_t>& invalidResponse, 966 vector<uint8_t>& iv, const Pattern& noPattern, const vector<SubSample>& subSamples); 967 }; 968 969 void DrmHalClearkeyDecryptTest::fillRandom(const sp<IMemory>& memory) { 970 random_device rd; 971 mt19937 rand(rd()); 972 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) { 973 auto p = static_cast<uint32_t*>( 974 static_cast<void*>(memory->getPointer())); 975 p[i] = rand(); 976 } 977 } 978 979 uint32_t DrmHalClearkeyDecryptTest::decrypt(Mode mode, 980 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 981 const Pattern& pattern, Status expectedStatus) { 982 const size_t kSegmentIndex = 0; 983 const vector<uint8_t> keyId = {0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 984 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d, 985 0x1e, 0xd0, 0x0d, 0x1e}; 986 const vector<uint8_t> contentKey = {0x1a, 0x8a, 0x20, 0x95, 0xe4, 987 0xde, 0xb2, 0xd2, 0x9e, 0xc8, 988 0x16, 0xac, 0x7b, 0xae, 0x20, 0x82}; 989 uint8_t localIv[AES_BLOCK_SIZE]; 990 memcpy(localIv, iv, AES_BLOCK_SIZE); 991 992 size_t totalSize = 0; 993 for (size_t i = 0; i < subSamples.size(); i++) { 994 totalSize += subSamples[i].numBytesOfClearData; 995 totalSize += subSamples[i].numBytesOfEncryptedData; 996 } 997 998 // The first totalSize bytes of shared memory is the encrypted 999 // input, the second totalSize bytes is the decrypted output. 1000 sp<IMemory> sharedMemory = 1001 getDecryptMemory(totalSize * 2, kSegmentIndex); 1002 1003 const SharedBuffer sourceBuffer = { 1004 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; 1005 fillRandom(sharedMemory); 1006 1007 const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY, 1008 {.bufferId = kSegmentIndex, 1009 .offset = totalSize, 1010 .size = totalSize}, 1011 .secureMemory = nullptr}; 1012 const uint64_t offset = 0; 1013 const bool kNotSecure = false; 1014 uint32_t bytesWritten = 0; 1015 auto res = cryptoPlugin->decrypt(kNotSecure, toHidlArray(keyId), localIv, mode, 1016 pattern, subSamples, sourceBuffer, offset, destBuffer, 1017 [&](Status status, uint32_t count, string detailedError) { 1018 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " << 1019 detailedError; 1020 bytesWritten = count; 1021 }); 1022 EXPECT_OK(res); 1023 1024 if (bytesWritten != totalSize) { 1025 return bytesWritten; 1026 } 1027 uint8_t* base = static_cast<uint8_t*>( 1028 static_cast<void*>(sharedMemory->getPointer())); 1029 1030 // generate reference vector 1031 vector<uint8_t> reference(totalSize); 1032 1033 memcpy(localIv, iv, AES_BLOCK_SIZE); 1034 switch (mode) { 1035 case Mode::UNENCRYPTED: 1036 memcpy(&reference[0], base, totalSize); 1037 break; 1038 case Mode::AES_CTR: 1039 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, contentKey); 1040 break; 1041 case Mode::AES_CBC: 1042 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, contentKey); 1043 break; 1044 case Mode::AES_CBC_CTS: 1045 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported"; 1046 break; 1047 } 1048 1049 // compare reference to decrypted data which is at base + total size 1050 EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]), 1051 static_cast<void*>(base + totalSize), totalSize)) 1052 << "decrypt data mismatch"; 1053 return totalSize; 1054 } 1055 1056 /** 1057 * Decrypt a list of clear+encrypted subsamples using the specified key 1058 * in AES-CTR mode 1059 */ 1060 void DrmHalClearkeyDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src, 1061 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 1062 const vector<uint8_t>& key) { 1063 AES_KEY decryptionKey; 1064 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 1065 1066 size_t offset = 0; 1067 unsigned int blockOffset = 0; 1068 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE]; 1069 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE); 1070 1071 for (size_t i = 0; i < subSamples.size(); i++) { 1072 const SubSample& subSample = subSamples[i]; 1073 1074 if (subSample.numBytesOfClearData > 0) { 1075 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData); 1076 offset += subSample.numBytesOfClearData; 1077 } 1078 1079 if (subSample.numBytesOfEncryptedData > 0) { 1080 AES_ctr128_encrypt(src + offset, dest + offset, 1081 subSample.numBytesOfEncryptedData, &decryptionKey, 1082 iv, previousEncryptedCounter, &blockOffset); 1083 offset += subSample.numBytesOfEncryptedData; 1084 } 1085 } 1086 } 1087 1088 /** 1089 * Decrypt a list of clear+encrypted subsamples using the specified key 1090 * in AES-CBC mode 1091 */ 1092 void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src, 1093 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 1094 const vector<uint8_t>& key) { 1095 AES_KEY decryptionKey; 1096 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 1097 1098 size_t offset = 0; 1099 for (size_t i = 0; i < subSamples.size(); i++) { 1100 memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData); 1101 offset += subSamples[i].numBytesOfClearData; 1102 1103 AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData, 1104 &decryptionKey, iv, 0 /* decrypt */); 1105 offset += subSamples[i].numBytesOfEncryptedData; 1106 } 1107 } 1108 1109 /** 1110 * Test query key status 1111 */ 1112 TEST_F(DrmHalClearkeyDecryptTest, TestQueryKeyStatus) { 1113 auto sessionId = openSession(); 1114 auto res = drmPlugin->queryKeyStatus( 1115 sessionId, [&](Status status, KeyedVector /* info */) { EXPECT_EQ(Status::OK, status); }); 1116 EXPECT_OK(res); 1117 1118 closeSession(sessionId); 1119 } 1120 1121 /** 1122 * Positive decrypt test. "Decrypt" a single clear segment 1123 */ 1124 TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) { 1125 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1126 const Pattern noPattern = {0, 0}; 1127 const uint32_t kByteCount = 256; 1128 const vector<SubSample> subSamples = { 1129 {.numBytesOfClearData = kByteCount, 1130 .numBytesOfEncryptedData = 0}}; 1131 auto sessionId = openSession(); 1132 loadKeys(sessionId); 1133 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 1134 1135 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples, 1136 noPattern, Status::OK); 1137 EXPECT_EQ(kByteCount, byteCount); 1138 1139 closeSession(sessionId); 1140 } 1141 1142 /** 1143 * Positive decrypt test. Decrypt a single segment using AES_CTR. 1144 * Verify data matches. 1145 */ 1146 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) { 1147 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1148 const Pattern noPattern = {0, 0}; 1149 const uint32_t kClearBytes = 512; 1150 const uint32_t kEncryptedBytes = 512; 1151 const vector<SubSample> subSamples = { 1152 {.numBytesOfClearData = kClearBytes, 1153 .numBytesOfEncryptedData = kEncryptedBytes}}; 1154 auto sessionId = openSession(); 1155 loadKeys(sessionId); 1156 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 1157 1158 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples, 1159 noPattern, Status::OK); 1160 EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount); 1161 1162 closeSession(sessionId); 1163 } 1164 1165 /** 1166 * Negative decrypt test. Decrypt without loading keys. 1167 */ 1168 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTestNoKeys) { 1169 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1170 const Pattern noPattern = {0, 0}; 1171 const vector<SubSample> subSamples = { 1172 {.numBytesOfClearData = 256, 1173 .numBytesOfEncryptedData = 256}}; 1174 auto sessionId = openSession(); 1175 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 1176 1177 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples, 1178 noPattern, Status::ERROR_DRM_NO_LICENSE); 1179 EXPECT_EQ(0u, byteCount); 1180 1181 closeSession(sessionId); 1182 } 1183 1184 /** 1185 * Helper method to test decryption with invalid keys is returned 1186 */ 1187 void DrmHalClearkeyDecryptTest::decryptWithInvalidKeys( 1188 hidl_vec<uint8_t>& invalidResponse, 1189 vector<uint8_t>& iv, 1190 const Pattern& noPattern, 1191 const vector<SubSample>& subSamples) { 1192 auto sessionId = openSession(); 1193 1194 auto res = drmPlugin->provideKeyResponse( 1195 sessionId, invalidResponse, 1196 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) { 1197 EXPECT_EQ(Status::OK, status); 1198 EXPECT_EQ(0u, myKeySetId.size()); 1199 }); 1200 EXPECT_OK(res); 1201 1202 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 1203 1204 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples, 1205 noPattern, Status::ERROR_DRM_NO_LICENSE); 1206 EXPECT_EQ(0u, byteCount); 1207 1208 closeSession(sessionId); 1209 } 1210 1211 /** 1212 * Negative decrypt test. Decrypt with invalid key. 1213 */ 1214 TEST_F(DrmHalClearkeyDecryptTest, DecryptWithEmptyKey) { 1215 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1216 const Pattern noPattern = {0, 0}; 1217 const uint32_t kClearBytes = 512; 1218 const uint32_t kEncryptedBytes = 512; 1219 const vector<SubSample> subSamples = { 1220 {.numBytesOfClearData = kClearBytes, 1221 .numBytesOfEncryptedData = kEncryptedBytes}}; 1222 1223 // base 64 encoded JSON response string, must not contain padding character '=' 1224 const hidl_string emptyKeyResponse = 1225 "{\"keys\":[" \ 1226 "{" \ 1227 "\"kty\":\"oct\"" \ 1228 "\"alg\":\"A128KW2\"" \ 1229 "\"k\":\"SGVsbG8gRnJpZW5kIQ\"" \ 1230 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAyAy\"" \ 1231 "}" \ 1232 "{" \ 1233 "\"kty\":\"oct\"," \ 1234 "\"alg\":\"A128KW2\"" \ 1235 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \ 1236 // empty key follows 1237 "\"k\":\"R\"" \ 1238 "}]" \ 1239 "}"; 1240 const size_t kEmptyKeyResponseSize = emptyKeyResponse.size(); 1241 1242 hidl_vec<uint8_t> invalidResponse; 1243 invalidResponse.resize(kEmptyKeyResponseSize); 1244 memcpy(invalidResponse.data(), emptyKeyResponse.c_str(), kEmptyKeyResponseSize); 1245 decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples); 1246 } 1247 1248 /** 1249 * Negative decrypt test. Decrypt with a key exceeds AES_BLOCK_SIZE. 1250 */ 1251 TEST_F(DrmHalClearkeyDecryptTest, DecryptWithKeyTooLong) { 1252 vector<uint8_t> iv(AES_BLOCK_SIZE, 0); 1253 const Pattern noPattern = {0, 0}; 1254 const uint32_t kClearBytes = 512; 1255 const uint32_t kEncryptedBytes = 512; 1256 const vector<SubSample> subSamples = { 1257 {.numBytesOfClearData = kClearBytes, 1258 .numBytesOfEncryptedData = kEncryptedBytes}}; 1259 1260 // base 64 encoded JSON response string, must not contain padding character '=' 1261 const hidl_string keyTooLongResponse = 1262 "{\"keys\":[" \ 1263 "{" \ 1264 "\"kty\":\"oct\"," \ 1265 "\"alg\":\"A128KW2\"" \ 1266 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \ 1267 // key too long 1268 "\"k\":\"V2lubmllIHRoZSBwb29oIVdpbm5pZSB0aGUgcG9vaCE=\"" \ 1269 "}]" \ 1270 "}"; 1271 const size_t kKeyTooLongResponseSize = keyTooLongResponse.size(); 1272 1273 hidl_vec<uint8_t> invalidResponse; 1274 invalidResponse.resize(kKeyTooLongResponseSize); 1275 memcpy(invalidResponse.data(), keyTooLongResponse.c_str(), kKeyTooLongResponseSize); 1276 decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples); 1277 } 1278