1 /*
2  * Copyright (C) 2020 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 #ifndef DRM_HAL_CLEARKEY_TEST_H
18 #define DRM_HAL_CLEARKEY_TEST_H
19 
20 #include <android/hardware/drm/1.0/ICryptoFactory.h>
21 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
22 #include <android/hardware/drm/1.0/IDrmFactory.h>
23 #include <android/hardware/drm/1.0/IDrmPlugin.h>
24 #include <android/hardware/drm/1.0/types.h>
25 #include <android/hidl/allocator/1.0/IAllocator.h>
26 
27 #include <gtest/gtest.h>
28 #include <hidl/HidlSupport.h>
29 #include <hidl/ServiceManagement.h>
30 #include <hidlmemory/mapping.h>
31 #include <log/log.h>
32 
33 #include "drm_vts_helper.h"
34 
35 using ::android::hidl::allocator::V1_0::IAllocator;
36 using ::android::hidl::memory::V1_0::IMemory;
37 
38 using ::drm_vts::DrmHalTestParam;
39 using ::drm_vts::PrintParamInstanceToString;
40 
41 using std::string;
42 using std::map;
43 using std::vector;
44 
45 /**
46  * These clearkey tests use white box knowledge of the legacy clearkey
47  * plugin to verify that the HIDL HAL services and interfaces are working.
48  * It is not intended to verify any vendor's HAL implementation. If you
49  * are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
50  */
51 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
52 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
53 
54 namespace android {
55 namespace hardware {
56 namespace drm {
57 namespace V1_0 {
58 namespace vts {
59 
60 class DrmHalClearkeyFactoryTest : public ::testing::TestWithParam<DrmHalTestParam> {
61   public:
SetUp()62     void SetUp() override {
63         const ::testing::TestInfo* const test_info =
64                 ::testing::UnitTest::GetInstance()->current_test_info();
65         ALOGD("Running test %s.%s", test_info->test_case_name(),
66               test_info->name());
67 
68         const std::string instanceName = GetParam().instance_;
69         drmFactory = IDrmFactory::getService(instanceName);
70         ASSERT_NE(nullptr, drmFactory.get());
71         cryptoFactory = ICryptoFactory::getService(instanceName);
72         ASSERT_NE(nullptr, cryptoFactory.get());
73 
74         const bool drmClearKey = drmFactory->isCryptoSchemeSupported(kClearKeyUUID);
75         const bool cryptoClearKey = cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID);
76         EXPECT_EQ(drmClearKey, cryptoClearKey);
77         const bool supportsClearKey = drmClearKey && cryptoClearKey;
78 
79         const bool drmCommonPsshBox = drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID);
80         const bool cryptoCommonPsshBox = cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID);
81         EXPECT_EQ(drmCommonPsshBox, cryptoCommonPsshBox);
82         const bool supportsCommonPsshBox = drmCommonPsshBox && cryptoCommonPsshBox;
83 
84         EXPECT_EQ(supportsClearKey, supportsCommonPsshBox);
85         correspondsToThisTest = supportsClearKey && supportsCommonPsshBox;
86 
87         if (instanceName == "clearkey") {
88             EXPECT_TRUE(correspondsToThisTest);
89 
90             // TODO(b/147449315)
91             // Only the clearkey plugged into the "default" instance supports
92             // this test. Currently the "clearkey" instance fails some tests
93             // here.
94             GTEST_SKIP() << "Clearkey tests don't work with 'clearkey' instance yet.";
95         }
96 
97         if (!correspondsToThisTest) {
98             GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
99         }
100     }
101 
102    protected:
103     static constexpr uint8_t kCommonPsshBoxUUID[16] = {
104         0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
105         0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
106 
107     // To be used in mpd to specify drm scheme for players
108     static constexpr uint8_t kClearKeyUUID[16] = {
109         0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
110         0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
111 
112     sp<IDrmFactory> drmFactory;
113     sp<ICryptoFactory> cryptoFactory;
114 
115     bool correspondsToThisTest;
116 };
117 
118 class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {
119    public:
SetUp()120     virtual void SetUp() override {
121         // Create factories
122         DrmHalClearkeyFactoryTest::SetUp();
123 
124         if (!correspondsToThisTest) {
125             GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
126         }
127 
128         ASSERT_NE(nullptr, drmFactory.get());
129         hidl_string packageName("android.hardware.drm.test");
130         auto res = drmFactory->createPlugin(
131                 getUUID(), packageName,
132                 [this](Status status, const sp<IDrmPlugin>& plugin) {
133                     EXPECT_EQ(Status::OK, status);
134                     ASSERT_NE(nullptr, plugin.get());
135                     drmPlugin = plugin;
136                 });
137         ASSERT_OK(res);
138 
139         hidl_vec<uint8_t> initVec;
140         res = cryptoFactory->createPlugin(
141                 getUUID(), initVec,
142                 [this](Status status, const sp<ICryptoPlugin>& plugin) {
143                     EXPECT_EQ(Status::OK, status);
144                     ASSERT_NE(nullptr, plugin.get());
145                     cryptoPlugin = plugin;
146                 });
147         ASSERT_OK(res);
148     }
149 
150     SessionId openSession();
151     void closeSession(const SessionId& sessionId);
152     hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
153     sp<IMemory> getDecryptMemory(size_t size, size_t index);
154 
155    protected:
getUUID()156     hidl_array<uint8_t, 16> getUUID() {
157         if (GetParamUUID() == hidl_array<uint8_t, 16>()) {
158             return kClearKeyUUID;
159         }
160         return GetParamUUID();
161     }
162 
GetParamUUID()163     hidl_array<uint8_t, 16> GetParamUUID() {
164         return GetParam().scheme_;
165     }
166 
167     sp<IDrmPlugin> drmPlugin;
168     sp<ICryptoPlugin> cryptoPlugin;
169 };
170 
171 class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest {
172    public:
SetUp()173      void SetUp() override {
174          DrmHalClearkeyPluginTest::SetUp();
175 
176          if (!correspondsToThisTest) {
177              GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
178          }
179      }
180     void fillRandom(const sp<IMemory>& memory);
toHidlArray(const vector<uint8_t> & vec)181     hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
182         EXPECT_EQ(16u, vec.size());
183         return hidl_array<uint8_t, 16>(&vec[0]);
184     }
185     uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples,
186             const Pattern& pattern, Status status);
187     void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
188             const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
189     void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
190             const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
191     void decryptWithInvalidKeys(hidl_vec<uint8_t>& invalidResponse,
192             vector<uint8_t>& iv, const Pattern& noPattern, const vector<SubSample>& subSamples);
193 };
194 
195 }  // namespace vts
196 }  // namespace V1_0
197 }  // namespace drm
198 }  // namespace hardware
199 }  // namespace android
200 
201 #endif  // DRM_HAL_CLEARKEY_TEST_H
202