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