Home | History | Annotate | Download | only in functional
      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