1 /* 2 * Copyright (C) 2019 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_common (at) 1.2" 18 19 #include <android/hidl/allocator/1.0/IAllocator.h> 20 #include <gtest/gtest.h> 21 #include <hidl/HidlSupport.h> 22 #include <hidlmemory/mapping.h> 23 #include <log/log.h> 24 #include <openssl/aes.h> 25 #include <random> 26 27 #include "drm_hal_clearkey_module.h" 28 #include "drm_hal_common.h" 29 30 using ::android::hardware::drm::V1_0::BufferType; 31 using ::android::hardware::drm::V1_0::DestinationBuffer; 32 using ICryptoPluginV1_0 = ::android::hardware::drm::V1_0::ICryptoPlugin; 33 using IDrmPluginV1_0 = ::android::hardware::drm::V1_0::IDrmPlugin; 34 using ::android::hardware::drm::V1_0::KeyValue; 35 using ::android::hardware::drm::V1_0::SharedBuffer; 36 using StatusV1_0 = ::android::hardware::drm::V1_0::Status; 37 38 using ::android::hardware::drm::V1_1::KeyRequestType; 39 40 using ::android::hardware::drm::V1_2::KeySetId; 41 using ::android::hardware::drm::V1_2::OfflineLicenseState; 42 using StatusV1_2 = ::android::hardware::drm::V1_2::Status; 43 44 using ::android::hardware::hidl_string; 45 using ::android::hardware::hidl_memory; 46 47 using ::android::hidl::allocator::V1_0::IAllocator; 48 49 using std::random_device; 50 using std::mt19937; 51 52 namespace android { 53 namespace hardware { 54 namespace drm { 55 namespace V1_2 { 56 namespace vts { 57 58 const char *kCallbackLostState = "LostState"; 59 const char *kCallbackKeysChange = "KeysChange"; 60 61 drm_vts::VendorModules *DrmHalTest::gVendorModules = nullptr; 62 63 /** 64 * DrmHalPluginListener 65 */ 66 67 Return<void> DrmHalPluginListener::sendSessionLostState(const hidl_vec<uint8_t>& sessionId) { 68 ListenerEventArgs args; 69 args.sessionId = sessionId; 70 NotifyFromCallback(kCallbackLostState, args); 71 return Void(); 72 } 73 74 Return<void> DrmHalPluginListener::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId, 75 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) { 76 ListenerEventArgs args; 77 args.sessionId = sessionId; 78 args.keyStatusList = keyStatusList; 79 args.hasNewUsableKey = hasNewUsableKey; 80 NotifyFromCallback(kCallbackKeysChange, args); 81 return Void(); 82 } 83 84 /** 85 * DrmHalTest 86 */ 87 88 DrmHalTest::DrmHalTest() 89 : vendorModule(GetParam() == "clearkey" 90 ? new DrmHalVTSClearkeyModule() 91 : static_cast<DrmHalVTSVendorModule_V1*>(gVendorModules->getModule(GetParam()))), 92 contentConfigurations(vendorModule->getContentConfigurations()) { 93 } 94 95 void DrmHalTest::SetUp() { 96 const ::testing::TestInfo* const test_info = 97 ::testing::UnitTest::GetInstance()->current_test_info(); 98 99 ALOGD("Running test %s.%s from (vendor) module %s", 100 test_info->test_case_name(), test_info->name(), 101 GetParam().c_str()); 102 103 string name = vendorModule->getServiceName(); 104 drmFactory = VtsHalHidlTargetTestBase::getService<IDrmFactory>(name); 105 if (drmFactory == nullptr) { 106 drmFactory = VtsHalHidlTargetTestBase::getService<IDrmFactory>(); 107 } 108 if (drmFactory != nullptr) { 109 drmPlugin = createDrmPlugin(); 110 } 111 112 cryptoFactory = VtsHalHidlTargetTestBase::getService<ICryptoFactory>(name); 113 if (cryptoFactory == nullptr) { 114 cryptoFactory = VtsHalHidlTargetTestBase::getService<ICryptoFactory>(); 115 } 116 if (cryptoFactory != nullptr) { 117 cryptoPlugin = createCryptoPlugin(); 118 } 119 120 // If drm scheme not installed skip subsequent tests 121 if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) { 122 vendorModule->setInstalled(false); 123 return; 124 } 125 126 ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find " << vendorModule->getServiceName() << " drm (at) 1.2 plugin"; 127 ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find " << vendorModule->getServiceName() << " crypto (at) 1.2 plugin"; 128 129 } 130 131 sp<IDrmPlugin> DrmHalTest::createDrmPlugin() { 132 if (drmFactory == nullptr) { 133 return nullptr; 134 } 135 sp<IDrmPlugin> plugin = nullptr; 136 hidl_string packageName("android.hardware.drm.test"); 137 auto res = drmFactory->createPlugin( 138 getVendorUUID(), packageName, 139 [&](StatusV1_0 status, const sp<IDrmPluginV1_0>& pluginV1_0) { 140 EXPECT_EQ(StatusV1_0::OK, status); 141 plugin = IDrmPlugin::castFrom(pluginV1_0); 142 }); 143 144 if (!res.isOk()) { 145 ALOGE("createDrmPlugin remote call failed"); 146 } 147 return plugin; 148 } 149 150 sp<ICryptoPlugin> DrmHalTest::createCryptoPlugin() { 151 if (cryptoFactory == nullptr) { 152 return nullptr; 153 } 154 sp<ICryptoPlugin> plugin = nullptr; 155 hidl_vec<uint8_t> initVec; 156 auto res = cryptoFactory->createPlugin( 157 getVendorUUID(), initVec, 158 [&](StatusV1_0 status, const sp<ICryptoPluginV1_0>& pluginV1_0) { 159 EXPECT_EQ(StatusV1_0::OK, status); 160 plugin = ICryptoPlugin::castFrom(pluginV1_0); 161 }); 162 if (!res.isOk()) { 163 ALOGE("createCryptoPlugin remote call failed"); 164 } 165 return plugin; 166 } 167 168 hidl_array<uint8_t, 16> DrmHalTest::getVendorUUID() { 169 vector<uint8_t> uuid = vendorModule->getUUID(); 170 return hidl_array<uint8_t, 16>(&uuid[0]); 171 } 172 173 /** 174 * Helper method to open a session and verify that a non-empty 175 * session ID is returned 176 */ 177 SessionId DrmHalTest::openSession() { 178 SessionId sessionId; 179 180 auto res = drmPlugin->openSession([&](StatusV1_0 status, const hidl_vec<unsigned char> &id) { 181 EXPECT_EQ(StatusV1_0::OK, status); 182 EXPECT_NE(id.size(), 0u); 183 sessionId = id; 184 }); 185 EXPECT_OK(res); 186 return sessionId; 187 } 188 189 /** 190 * Helper method to close a session 191 */ 192 void DrmHalTest::closeSession(const SessionId& sessionId) { 193 StatusV1_0 status = drmPlugin->closeSession(sessionId); 194 EXPECT_EQ(StatusV1_0::OK, status); 195 } 196 197 hidl_vec<uint8_t> DrmHalTest::getKeyRequest( 198 const SessionId& sessionId, 199 const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration, 200 const KeyType& type = KeyType::STREAMING) { 201 hidl_vec<uint8_t> keyRequest; 202 auto res = drmPlugin->getKeyRequest_1_2( 203 sessionId, configuration.initData, configuration.mimeType, type, 204 toHidlKeyedVector(configuration.optionalParameters), 205 [&](Status status, const hidl_vec<uint8_t>& request, 206 KeyRequestType requestType, const hidl_string&) { 207 EXPECT_EQ(Status::OK, status) << "Failed to get " 208 "key request for configuration " 209 << configuration.name; 210 if (type == KeyType::RELEASE) { 211 EXPECT_EQ(KeyRequestType::RELEASE, requestType); 212 } else { 213 EXPECT_EQ(KeyRequestType::INITIAL, requestType); 214 } 215 EXPECT_NE(request.size(), 0u) << "Expected key request size" 216 " to have length > 0 bytes"; 217 keyRequest = request; 218 }); 219 EXPECT_OK(res); 220 return keyRequest; 221 } 222 223 DrmHalVTSVendorModule_V1::ContentConfiguration DrmHalTest::getContent(const KeyType& type) const { 224 for (const auto& config : contentConfigurations) { 225 if (type != KeyType::OFFLINE || config.policy.allowOffline) { 226 return config; 227 } 228 } 229 EXPECT_TRUE(false) << "no content configurations found"; 230 return {}; 231 } 232 233 hidl_vec<uint8_t> DrmHalTest::provideKeyResponse( 234 const SessionId& sessionId, 235 const hidl_vec<uint8_t>& keyResponse) { 236 hidl_vec<uint8_t> keySetId; 237 auto res = drmPlugin->provideKeyResponse( 238 sessionId, keyResponse, 239 [&](StatusV1_0 status, const hidl_vec<uint8_t>& myKeySetId) { 240 EXPECT_EQ(StatusV1_0::OK, status) << "Failure providing " 241 "key response for configuration "; 242 keySetId = myKeySetId; 243 }); 244 EXPECT_OK(res); 245 return keySetId; 246 } 247 248 /** 249 * Helper method to load keys for subsequent decrypt tests. 250 * These tests use predetermined key request/response to 251 * avoid requiring a round trip to a license server. 252 */ 253 hidl_vec<uint8_t> DrmHalTest::loadKeys( 254 const SessionId& sessionId, 255 const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration, 256 const KeyType& type) { 257 hidl_vec<uint8_t> keyRequest = getKeyRequest(sessionId, configuration, type); 258 259 /** 260 * Get key response from vendor module 261 */ 262 hidl_vec<uint8_t> keyResponse = 263 vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl); 264 EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size " 265 "to have length > 0 bytes"; 266 267 return provideKeyResponse(sessionId, keyResponse); 268 } 269 270 hidl_vec<uint8_t> DrmHalTest::loadKeys( 271 const SessionId& sessionId, 272 const KeyType& type) { 273 return loadKeys(sessionId, getContent(type), type); 274 } 275 276 KeyedVector DrmHalTest::toHidlKeyedVector( 277 const map<string, string>& params) { 278 std::vector<KeyValue> stdKeyedVector; 279 for (auto it = params.begin(); it != params.end(); ++it) { 280 KeyValue keyValue; 281 keyValue.key = it->first; 282 keyValue.value = it->second; 283 stdKeyedVector.push_back(keyValue); 284 } 285 return KeyedVector(stdKeyedVector); 286 } 287 288 hidl_array<uint8_t, 16> DrmHalTest::toHidlArray(const vector<uint8_t>& vec) { 289 EXPECT_EQ(16u, vec.size()); 290 return hidl_array<uint8_t, 16>(&vec[0]); 291 } 292 293 /** 294 * getDecryptMemory allocates memory for decryption, then sets it 295 * as a shared buffer base in the crypto hal. The allocated and 296 * mapped IMemory is returned. 297 * 298 * @param size the size of the memory segment to allocate 299 * @param the index of the memory segment which will be used 300 * to refer to it for decryption. 301 */ 302 sp<IMemory> DrmHalTest::getDecryptMemory(size_t size, size_t index) { 303 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); 304 EXPECT_NE(nullptr, ashmemAllocator.get()); 305 306 hidl_memory hidlMemory; 307 auto res = ashmemAllocator->allocate( 308 size, [&](bool success, const hidl_memory& memory) { 309 EXPECT_EQ(success, true); 310 EXPECT_EQ(memory.size(), size); 311 hidlMemory = memory; 312 }); 313 314 EXPECT_OK(res); 315 316 sp<IMemory> mappedMemory = mapMemory(hidlMemory); 317 EXPECT_NE(nullptr, mappedMemory.get()); 318 res = cryptoPlugin->setSharedBufferBase(hidlMemory, index); 319 EXPECT_OK(res); 320 return mappedMemory; 321 } 322 323 void DrmHalTest::fillRandom(const sp<IMemory>& memory) { 324 random_device rd; 325 mt19937 rand(rd()); 326 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) { 327 auto p = static_cast<uint32_t*>( 328 static_cast<void*>(memory->getPointer())); 329 p[i] = rand(); 330 } 331 } 332 333 uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, 334 const hidl_array<uint8_t, 16>& keyId, uint8_t* iv, 335 const hidl_vec<SubSample>& subSamples, const Pattern& pattern, 336 const vector<uint8_t>& key, StatusV1_2 expectedStatus) { 337 const size_t kSegmentIndex = 0; 338 339 uint8_t localIv[AES_BLOCK_SIZE]; 340 memcpy(localIv, iv, AES_BLOCK_SIZE); 341 342 size_t totalSize = 0; 343 for (size_t i = 0; i < subSamples.size(); i++) { 344 totalSize += subSamples[i].numBytesOfClearData; 345 totalSize += subSamples[i].numBytesOfEncryptedData; 346 } 347 348 // The first totalSize bytes of shared memory is the encrypted 349 // input, the second totalSize bytes (if exists) is the decrypted output. 350 size_t factor = expectedStatus == StatusV1_2::ERROR_DRM_FRAME_TOO_LARGE ? 1 : 2; 351 sp<IMemory> sharedMemory = 352 getDecryptMemory(totalSize * factor, kSegmentIndex); 353 354 const SharedBuffer sourceBuffer = { 355 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; 356 fillRandom(sharedMemory); 357 358 const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY, 359 {.bufferId = kSegmentIndex, 360 .offset = totalSize, 361 .size = totalSize}, 362 .secureMemory = nullptr}; 363 const uint64_t offset = 0; 364 uint32_t bytesWritten = 0; 365 auto res = cryptoPlugin->decrypt_1_2(isSecure, keyId, localIv, mode, pattern, 366 subSamples, sourceBuffer, offset, destBuffer, 367 [&](StatusV1_2 status, uint32_t count, string detailedError) { 368 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " << 369 detailedError; 370 bytesWritten = count; 371 }); 372 EXPECT_OK(res); 373 374 if (bytesWritten != totalSize) { 375 return bytesWritten; 376 } 377 uint8_t* base = static_cast<uint8_t*>( 378 static_cast<void*>(sharedMemory->getPointer())); 379 380 // generate reference vector 381 vector<uint8_t> reference(totalSize); 382 383 memcpy(localIv, iv, AES_BLOCK_SIZE); 384 switch (mode) { 385 case Mode::UNENCRYPTED: 386 memcpy(&reference[0], base, totalSize); 387 break; 388 case Mode::AES_CTR: 389 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key); 390 break; 391 case Mode::AES_CBC: 392 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key); 393 break; 394 case Mode::AES_CBC_CTS: 395 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported"; 396 break; 397 } 398 399 // compare reference to decrypted data which is at base + total size 400 EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]), 401 static_cast<void*>(base + totalSize), totalSize)) 402 << "decrypt data mismatch"; 403 return totalSize; 404 } 405 406 /** 407 * Decrypt a list of clear+encrypted subsamples using the specified key 408 * in AES-CTR mode 409 */ 410 void DrmHalTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src, 411 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 412 const vector<uint8_t>& key) { 413 AES_KEY decryptionKey; 414 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 415 416 size_t offset = 0; 417 unsigned int blockOffset = 0; 418 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE]; 419 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE); 420 421 for (size_t i = 0; i < subSamples.size(); i++) { 422 const SubSample& subSample = subSamples[i]; 423 424 if (subSample.numBytesOfClearData > 0) { 425 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData); 426 offset += subSample.numBytesOfClearData; 427 } 428 429 if (subSample.numBytesOfEncryptedData > 0) { 430 AES_ctr128_encrypt(src + offset, dest + offset, 431 subSample.numBytesOfEncryptedData, &decryptionKey, 432 iv, previousEncryptedCounter, &blockOffset); 433 offset += subSample.numBytesOfEncryptedData; 434 } 435 } 436 } 437 438 /** 439 * Decrypt a list of clear+encrypted subsamples using the specified key 440 * in AES-CBC mode 441 */ 442 void DrmHalTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src, 443 uint8_t* iv, const hidl_vec<SubSample>& subSamples, 444 const vector<uint8_t>& key) { 445 AES_KEY decryptionKey; 446 AES_set_encrypt_key(&key[0], 128, &decryptionKey); 447 448 size_t offset = 0; 449 for (size_t i = 0; i < subSamples.size(); i++) { 450 memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData); 451 offset += subSamples[i].numBytesOfClearData; 452 453 AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData, 454 &decryptionKey, iv, 0 /* decrypt */); 455 offset += subSamples[i].numBytesOfEncryptedData; 456 } 457 } 458 459 /** 460 * Helper method to test decryption with invalid keys is returned 461 */ 462 void DrmHalClearkeyTest::decryptWithInvalidKeys( 463 hidl_vec<uint8_t>& invalidResponse, 464 vector<uint8_t>& iv, 465 const Pattern& noPattern, 466 const vector<SubSample>& subSamples) { 467 DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(); 468 if (content.keys.empty()) { 469 FAIL() << "no keys"; 470 } 471 472 const auto& key = content.keys[0]; 473 auto sessionId = openSession(); 474 auto res = drmPlugin->provideKeyResponse( 475 sessionId, invalidResponse, 476 [&](StatusV1_0 status, const hidl_vec<uint8_t>& myKeySetId) { 477 EXPECT_EQ(StatusV1_0::OK, status); 478 EXPECT_EQ(0u, myKeySetId.size()); 479 }); 480 EXPECT_OK(res); 481 482 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk()); 483 484 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, 485 toHidlArray(key.keyId), &iv[0], subSamples, noPattern, 486 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE); 487 EXPECT_EQ(0u, byteCount); 488 489 closeSession(sessionId); 490 } 491 492 } // namespace vts 493 } // namespace V1_2 494 } // namespace drm 495 } // namespace hardware 496 } // namespace android 497