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     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