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@1.1"
18
19 #include <android/hardware/drm/1.1/ICryptoFactory.h>
20 #include <android/hardware/drm/1.0/ICryptoPlugin.h>
21 #include <android/hardware/drm/1.1/IDrmFactory.h>
22 #include <android/hardware/drm/1.0/IDrmPlugin.h>
23 #include <android/hardware/drm/1.1/IDrmPlugin.h>
24 #include <android/hardware/drm/1.0/types.h>
25 #include <android/hardware/drm/1.1/types.h>
26 #include <android/hidl/allocator/1.0/IAllocator.h>
27 #include <android/hidl/manager/1.0/IServiceManager.h>
28 #include <gtest/gtest.h>
29 #include <hidl/HidlSupport.h>
30 #include <hidl/ServiceManagement.h>
31 #include <hidlmemory/mapping.h>
32 #include <log/log.h>
33 #include <memory>
34 #include <openssl/aes.h>
35 #include <random>
36
37 #include "VtsHalHidlTargetTestBase.h"
38 #include "VtsHalHidlTargetTestEnvBase.h"
39
40 namespace drm = ::android::hardware::drm;
41 using ::android::hardware::drm::V1_0::BufferType;
42 using ::android::hardware::drm::V1_0::DestinationBuffer;
43 using ::android::hardware::drm::V1_0::ICryptoPlugin;
44 using ::android::hardware::drm::V1_0::KeyedVector;
45 using ::android::hardware::drm::V1_0::KeyValue;
46 using ::android::hardware::drm::V1_0::KeyType;
47 using ::android::hardware::drm::V1_0::Mode;
48 using ::android::hardware::drm::V1_0::Pattern;
49 using ::android::hardware::drm::V1_0::SecureStop;
50 using ::android::hardware::drm::V1_0::SecureStopId;
51 using ::android::hardware::drm::V1_0::SessionId;
52 using ::android::hardware::drm::V1_0::SharedBuffer;
53 using ::android::hardware::drm::V1_0::Status;
54 using ::android::hardware::drm::V1_0::SubSample;
55 using ::android::hardware::drm::V1_0::SubSample;
56
57 using ::android::hardware::drm::V1_1::DrmMetricGroup;
58 using ::android::hardware::drm::V1_1::HdcpLevel;
59 using ::android::hardware::drm::V1_1::ICryptoFactory;
60 using ::android::hardware::drm::V1_1::IDrmFactory;
61 using ::android::hardware::drm::V1_1::IDrmPlugin;
62 using ::android::hardware::drm::V1_1::KeyRequestType;
63 using ::android::hardware::drm::V1_1::SecureStopRelease;
64 using ::android::hardware::drm::V1_1::SecurityLevel;
65 using ::android::hardware::drm::V1_1::SecurityLevel;
66
67 using ::android::hardware::hidl_array;
68 using ::android::hardware::hidl_string;
69 using ::android::hardware::hidl_memory;
70 using ::android::hardware::hidl_vec;
71 using ::android::hardware::Return;
72 using ::android::hidl::allocator::V1_0::IAllocator;
73 using ::android::hidl::memory::V1_0::IMemory;
74 using ::android::sp;
75
76 using std::string;
77 using std::unique_ptr;
78 using std::random_device;
79 using std::map;
80 using std::mt19937;
81 using std::vector;
82
83 /**
84 * These clearkey tests use white box knowledge of the legacy clearkey
85 * plugin to verify that the HIDL HAL services and interfaces are working.
86 * It is not intended to verify any vendor's HAL implementation. If you
87 * are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
88 */
89 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
90 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
91
92 // To be used in mpd to specify drm scheme for players
93 static const uint8_t kClearKeyUUID[16] = {
94 0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
95 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
96
97 // Test environment for drm
98 class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
99 public:
100 // get the test environment singleton
Instance()101 static DrmHidlEnvironment* Instance() {
102 static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
103 return instance;
104 }
105
HidlSetUp()106 virtual void HidlSetUp() override { ALOGI("SetUp DrmHidlEnvironment"); }
107
HidlTearDown()108 virtual void HidlTearDown() override { ALOGI("TearDown DrmHidlEnvironment"); }
109
registerTestServices()110 void registerTestServices() override {
111 registerTestService<ICryptoFactory>();
112 registerTestService<IDrmFactory>();
113 setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION);
114 }
115
116 private:
DrmHidlEnvironment()117 DrmHidlEnvironment() {}
118
119 GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
120 };
121
122
123 class DrmHalClearkeyTest : public ::testing::VtsHalHidlTargetTestBase {
124 public:
SetUp()125 virtual void SetUp() override {
126 const ::testing::TestInfo* const test_info =
127 ::testing::UnitTest::GetInstance()->current_test_info();
128
129 ALOGD("DrmHalClearkeyTest: Running test %s.%s", test_info->test_case_name(),
130 test_info->name());
131
132 auto manager = android::hardware::defaultServiceManager();
133 ASSERT_NE(nullptr, manager.get());
134 manager->listByInterface(IDrmFactory::descriptor,
135 [&](const hidl_vec<hidl_string> ®istered) {
136 for (const auto &instance : registered) {
137 sp<IDrmFactory> drmFactory =
138 ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(instance);
139 drmPlugin = createDrmPlugin(drmFactory);
140 if (drmPlugin != nullptr) {
141 break;
142 }
143 }
144 }
145 );
146
147 manager->listByInterface(ICryptoFactory::descriptor,
148 [&](const hidl_vec<hidl_string> ®istered) {
149 for (const auto &instance : registered) {
150 sp<ICryptoFactory> cryptoFactory =
151 ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(instance);
152 cryptoPlugin = createCryptoPlugin(cryptoFactory);
153 if (cryptoPlugin != nullptr) {
154 break;
155 }
156 }
157 }
158 );
159
160 ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find clearkey drm@1.1 plugin";
161 ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find clearkey crypto@1.1 plugin";
162 }
163
164
TearDown()165 virtual void TearDown() override {}
166
167 SessionId openSession();
168 SessionId openSession(SecurityLevel level);
169 void closeSession(const SessionId& sessionId);
170 hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
171
172 private:
createDrmPlugin(sp<IDrmFactory> drmFactory)173 sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
174 if (drmFactory == nullptr) {
175 return nullptr;
176 }
177 sp<IDrmPlugin> plugin = nullptr;
178 auto res = drmFactory->createPlugin(
179 kClearKeyUUID, "",
180 [&](Status status, const sp<drm::V1_0::IDrmPlugin>& pluginV1_0) {
181 EXPECT_EQ(Status::OK, status);
182 plugin = IDrmPlugin::castFrom(pluginV1_0);
183 });
184
185 if (!res.isOk()) {
186 ALOGE("createDrmPlugin remote call failed");
187 }
188 return plugin;
189 }
190
createCryptoPlugin(sp<ICryptoFactory> cryptoFactory)191 sp<ICryptoPlugin> createCryptoPlugin(sp<ICryptoFactory> cryptoFactory) {
192 if (cryptoFactory == nullptr) {
193 return nullptr;
194 }
195 sp<ICryptoPlugin> plugin = nullptr;
196 hidl_vec<uint8_t> initVec;
197 auto res = cryptoFactory->createPlugin(
198 kClearKeyUUID, initVec,
199 [&](Status status, const sp<drm::V1_0::ICryptoPlugin>& pluginV1_0) {
200 EXPECT_EQ(Status::OK, status);
201 plugin = pluginV1_0;
202 });
203 if (!res.isOk()) {
204 ALOGE("createCryptoPlugin remote call failed");
205 }
206 return plugin;
207 }
208
209 protected:
210 template <typename CT>
ValueEquals(DrmMetricGroup::ValueType type,const std::string & expected,const CT & actual)211 bool ValueEquals(DrmMetricGroup::ValueType type, const std::string& expected, const CT& actual) {
212 return type == DrmMetricGroup::ValueType::STRING_TYPE && expected == actual.stringValue;
213 }
214
215 template <typename CT>
ValueEquals(DrmMetricGroup::ValueType type,const int64_t expected,const CT & actual)216 bool ValueEquals(DrmMetricGroup::ValueType type, const int64_t expected, const CT& actual) {
217 return type == DrmMetricGroup::ValueType::INT64_TYPE && expected == actual.int64Value;
218 }
219
220 template <typename CT>
ValueEquals(DrmMetricGroup::ValueType type,const double expected,const CT & actual)221 bool ValueEquals(DrmMetricGroup::ValueType type, const double expected, const CT& actual) {
222 return type == DrmMetricGroup::ValueType::DOUBLE_TYPE && expected == actual.doubleValue;
223 }
224
225 template <typename AT, typename VT>
ValidateMetricAttributeAndValue(const DrmMetricGroup::Metric & metric,const std::string & attributeName,const AT & attributeValue,const std::string & componentName,const VT & componentValue)226 bool ValidateMetricAttributeAndValue(const DrmMetricGroup::Metric& metric,
227 const std::string& attributeName, const AT& attributeValue,
228 const std::string& componentName, const VT& componentValue) {
229 bool validAttribute = false;
230 bool validComponent = false;
231 for (const DrmMetricGroup::Attribute& attribute : metric.attributes) {
232 if (attribute.name == attributeName &&
233 ValueEquals(attribute.type, attributeValue, attribute)) {
234 validAttribute = true;
235 }
236 }
237 for (const DrmMetricGroup::Value& value : metric.values) {
238 if (value.componentName == componentName &&
239 ValueEquals(value.type, componentValue, value)) {
240 validComponent = true;
241 }
242 }
243 return validAttribute && validComponent;
244 }
245
246 template <typename AT, typename VT>
ValidateMetricAttributeAndValue(const hidl_vec<DrmMetricGroup> & metricGroups,const std::string & metricName,const std::string & attributeName,const AT & attributeValue,const std::string & componentName,const VT & componentValue)247 bool ValidateMetricAttributeAndValue(const hidl_vec<DrmMetricGroup>& metricGroups,
248 const std::string& metricName,
249 const std::string& attributeName, const AT& attributeValue,
250 const std::string& componentName, const VT& componentValue) {
251 bool foundMetric = false;
252 for (const auto& group : metricGroups) {
253 for (const auto& metric : group.metrics) {
254 if (metric.name == metricName) {
255 foundMetric = foundMetric || ValidateMetricAttributeAndValue(
256 metric, attributeName, attributeValue,
257 componentName, componentValue);
258 }
259 }
260 }
261 return foundMetric;
262 }
263
264 sp<IDrmPlugin> drmPlugin;
265 sp<ICryptoPlugin> cryptoPlugin;
266 };
267
268
269 /**
270 * Helper method to open a session and verify that a non-empty
271 * session ID is returned
272 */
openSession()273 SessionId DrmHalClearkeyTest::openSession() {
274 SessionId sessionId;
275
276 auto res = drmPlugin->openSession(
277 [&sessionId](Status status, const SessionId& id) {
278 EXPECT_EQ(Status::OK, status);
279 EXPECT_NE(0u, id.size());
280 sessionId = id;
281 });
282 EXPECT_OK(res);
283 return sessionId;
284 }
285
286 /**
287 * Helper method to open as session using V1.1 API
288 */
openSession(SecurityLevel level)289 SessionId DrmHalClearkeyTest::openSession(SecurityLevel level) {
290 SessionId sessionId;
291
292 auto res = drmPlugin->openSession_1_1(level,
293 [&sessionId](Status status, const SessionId& id) {
294 EXPECT_EQ(Status::OK, status);
295 EXPECT_NE(0u, id.size());
296 sessionId = id;
297 });
298 EXPECT_OK(res);
299 return sessionId;
300 }
301
302
303 /**
304 * Helper method to close a session
305 */
closeSession(const SessionId & sessionId)306 void DrmHalClearkeyTest::closeSession(const SessionId& sessionId) {
307 EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk());
308 }
309
310 /**
311 * Helper method to load keys for subsequent decrypt tests.
312 * These tests use predetermined key request/response to
313 * avoid requiring a round trip to a license server.
314 */
loadKeys(const SessionId & sessionId,const KeyType & type=KeyType::STREAMING)315 hidl_vec<uint8_t> DrmHalClearkeyTest::loadKeys(
316 const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
317 hidl_vec<uint8_t> initData = {
318 // BMFF box header (4 bytes size + 'pssh')
319 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
320 // full box header (version = 1 flags = 0)
321 0x01, 0x00, 0x00, 0x00,
322 // system id
323 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
324 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
325 // number of key ids
326 0x00, 0x00, 0x00, 0x01,
327 // key id
328 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
329 0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
330 // size of data, must be zero
331 0x00, 0x00, 0x00, 0x00};
332
333 hidl_vec<uint8_t> expectedKeyRequest = {
334 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
335 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
336 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
337 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
338
339 hidl_vec<uint8_t> knownKeyResponse = {
340 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
341 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
342 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
343 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
344 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
345 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
346
347 hidl_string mimeType = "video/mp4";
348 KeyedVector optionalParameters;
349 auto res = drmPlugin->getKeyRequest_1_1(
350 sessionId, initData, mimeType, type, optionalParameters,
351 [&](Status status, const hidl_vec<uint8_t>& request,
352 KeyRequestType requestType, const hidl_string&) {
353 EXPECT_EQ(Status::OK, status);
354 EXPECT_EQ(KeyRequestType::INITIAL, requestType);
355 EXPECT_EQ(request, expectedKeyRequest);
356 });
357 EXPECT_OK(res);
358
359 hidl_vec<uint8_t> keySetId;
360 res = drmPlugin->provideKeyResponse(
361 sessionId, knownKeyResponse,
362 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
363 EXPECT_EQ(Status::OK, status);
364 EXPECT_EQ(0u, myKeySetId.size());
365 keySetId = myKeySetId;
366 });
367 EXPECT_OK(res);
368 return keySetId;
369 }
370
371 /**
372 * Test openSession negative case: security level higher than supported
373 */
TEST_F(DrmHalClearkeyTest,OpenSessionBadLevel)374 TEST_F(DrmHalClearkeyTest, OpenSessionBadLevel) {
375 auto res = drmPlugin->openSession_1_1(SecurityLevel::HW_SECURE_ALL,
376 [&](Status status, const SessionId& /* id */) {
377 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
378 });
379 EXPECT_OK(res);
380 }
381
382 /**
383 * Test getKeyRequest_1_1 via loadKeys
384 */
TEST_F(DrmHalClearkeyTest,GetKeyRequest)385 TEST_F(DrmHalClearkeyTest, GetKeyRequest) {
386 auto sessionId = openSession();
387 loadKeys(sessionId);
388 closeSession(sessionId);
389 }
390
391 /**
392 * A get key request should fail if no sessionId is provided
393 */
TEST_F(DrmHalClearkeyTest,GetKeyRequestNoSession)394 TEST_F(DrmHalClearkeyTest, GetKeyRequestNoSession) {
395 SessionId invalidSessionId;
396 hidl_vec<uint8_t> initData;
397 hidl_string mimeType = "video/mp4";
398 KeyedVector optionalParameters;
399 auto res = drmPlugin->getKeyRequest_1_1(
400 invalidSessionId, initData, mimeType, KeyType::STREAMING,
401 optionalParameters,
402 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
403 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
404 EXPECT_OK(res);
405 }
406
407 /**
408 * The clearkey plugin doesn't support offline key requests.
409 * Test that the plugin returns the expected error code in
410 * this case.
411 */
TEST_F(DrmHalClearkeyTest,GetKeyRequestOfflineKeyTypeNotSupported)412 TEST_F(DrmHalClearkeyTest, GetKeyRequestOfflineKeyTypeNotSupported) {
413 auto sessionId = openSession();
414 hidl_vec<uint8_t> initData;
415 hidl_string mimeType = "video/mp4";
416 KeyedVector optionalParameters;
417
418 auto res = drmPlugin->getKeyRequest_1_1(
419 sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
420 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
421 const hidl_string&) {
422 // Clearkey plugin doesn't support offline key type
423 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
424 });
425 EXPECT_OK(res);
426 closeSession(sessionId);
427 }
428
429 /**
430 * Test that the plugin returns valid connected and max HDCP levels
431 */
TEST_F(DrmHalClearkeyTest,GetHdcpLevels)432 TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
433 auto res = drmPlugin->getHdcpLevels(
434 [&](Status status, const HdcpLevel &connectedLevel,
435 const HdcpLevel &maxLevel) {
436 EXPECT_EQ(Status::OK, status);
437 EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE);
438 EXPECT_LE(maxLevel, HdcpLevel::HDCP_NO_OUTPUT);
439 });
440 EXPECT_OK(res);
441 }
442
443 /**
444 * Since getHdcpLevels only queries information there are no
445 * negative cases.
446 */
447
448 /**
449 * Test that the plugin returns default open and max session counts
450 */
TEST_F(DrmHalClearkeyTest,GetDefaultSessionCounts)451 TEST_F(DrmHalClearkeyTest, GetDefaultSessionCounts) {
452 auto res = drmPlugin->getNumberOfSessions(
453 [&](Status status, uint32_t currentSessions,
454 uint32_t maxSessions) {
455 EXPECT_EQ(Status::OK, status);
456 EXPECT_GE(maxSessions, (uint32_t)8);
457 EXPECT_GE(currentSessions, (uint32_t)0);
458 EXPECT_LE(currentSessions, maxSessions);
459 });
460 EXPECT_OK(res);
461 }
462
463 /**
464 * Test that the plugin returns valid open and max session counts
465 * after a session is opened.
466 */
TEST_F(DrmHalClearkeyTest,GetOpenSessionCounts)467 TEST_F(DrmHalClearkeyTest, GetOpenSessionCounts) {
468 uint32_t initialSessions = 0;
469 auto res = drmPlugin->getNumberOfSessions(
470 [&](Status status, uint32_t currentSessions,
471 uint32_t maxSessions) {
472 EXPECT_EQ(Status::OK, status);
473 EXPECT_GE(maxSessions, (uint32_t)8);
474 EXPECT_GE(currentSessions, (uint32_t)0);
475 EXPECT_LE(currentSessions, maxSessions);
476 initialSessions = currentSessions;
477 });
478 EXPECT_OK(res);
479
480 SessionId session = openSession();
481 res = drmPlugin->getNumberOfSessions(
482 [&](Status status, uint32_t currentSessions,
483 uint32_t /*maxSessions*/) {
484 EXPECT_EQ(Status::OK, status);
485 EXPECT_EQ(currentSessions, initialSessions + 1);
486 });
487 EXPECT_OK(res);
488
489 closeSession(session);
490 res = drmPlugin->getNumberOfSessions(
491 [&](Status status, uint32_t currentSessions,
492 uint32_t /*maxSessions*/) {
493 EXPECT_EQ(Status::OK, status);
494 EXPECT_EQ(currentSessions, initialSessions);
495 });
496 EXPECT_OK(res);
497 }
498
499 /**
500 * Since getNumberOfSessions only queries information there are no
501 * negative cases.
502 */
503
504 /**
505 * Test that the plugin returns the same security level
506 * by default as when it is requested explicitly
507 */
TEST_F(DrmHalClearkeyTest,GetDefaultSecurityLevel)508 TEST_F(DrmHalClearkeyTest, GetDefaultSecurityLevel) {
509 SessionId session = openSession();
510 SecurityLevel defaultLevel;
511 auto res = drmPlugin->getSecurityLevel(session,
512 [&](Status status, SecurityLevel level) {
513 EXPECT_EQ(Status::OK, status);
514 defaultLevel = level;
515 });
516 EXPECT_OK(res);
517 closeSession(session);
518
519 session = openSession(defaultLevel);
520 res = drmPlugin->getSecurityLevel(session,
521 [&](Status status, SecurityLevel level) {
522 EXPECT_EQ(Status::OK, status);
523 EXPECT_EQ(level, defaultLevel);
524 });
525 EXPECT_OK(res);
526 closeSession(session);
527 }
528
529 /**
530 * Test that the plugin returns the lowest security level
531 * when it is requested
532 */
TEST_F(DrmHalClearkeyTest,GetSecurityLevel)533 TEST_F(DrmHalClearkeyTest, GetSecurityLevel) {
534 SessionId session = openSession(SecurityLevel::SW_SECURE_CRYPTO);
535 auto res = drmPlugin->getSecurityLevel(session,
536 [&](Status status, SecurityLevel level) {
537 EXPECT_EQ(Status::OK, status);
538 EXPECT_EQ(level, SecurityLevel::SW_SECURE_CRYPTO);
539 });
540 EXPECT_OK(res);
541 closeSession(session);
542 }
543
544 /**
545 * Test that the plugin returns the documented error
546 * when requesting the security level for an invalid sessionId
547 */
TEST_F(DrmHalClearkeyTest,GetSecurityLevelInvalidSessionId)548 TEST_F(DrmHalClearkeyTest, GetSecurityLevelInvalidSessionId) {
549 SessionId session;
550 auto res = drmPlugin->getSecurityLevel(session,
551 [&](Status status, SecurityLevel /*level*/) {
552 EXPECT_EQ(Status::BAD_VALUE, status);
553 });
554 EXPECT_OK(res);
555 }
556
557 /**
558 * Test metrics are set appropriately for open and close operations.
559 */
TEST_F(DrmHalClearkeyTest,GetMetricsOpenClose)560 TEST_F(DrmHalClearkeyTest, GetMetricsOpenClose) {
561 SessionId sessionId = openSession();
562 // The first close should be successful.
563 closeSession(sessionId);
564 // The second close should fail (not opened).
565 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, drmPlugin->closeSession(sessionId));
566
567 auto res = drmPlugin->getMetrics([this](Status status, hidl_vec<DrmMetricGroup> metricGroups) {
568 EXPECT_EQ(Status::OK, status);
569
570 // Verify the open_session metric.
571 EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "open_session", "status",
572 (int64_t)0, "count", (int64_t)1));
573 // Verify the close_session - success metric.
574 EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
575 (int64_t)0, "count", (int64_t)1));
576 // Verify the close_session - error metric.
577 EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
578 (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
579 "count", (int64_t)1));
580 });
581 EXPECT_OK(res);
582 }
583
584 /**
585 * Since getMetrics only queries information there are no
586 * negative cases.
587 */
588
589 /**
590 * Test that there are no secure stop ids after clearing them
591 */
TEST_F(DrmHalClearkeyTest,GetSecureStopIdsCleared)592 TEST_F(DrmHalClearkeyTest, GetSecureStopIdsCleared) {
593 auto stat = drmPlugin->removeAllSecureStops();
594 EXPECT_OK(stat);
595
596 bool ok = drmPlugin->getSecureStopIds(
597 [&](Status status, const hidl_vec<SecureStopId>& ids) {
598 EXPECT_EQ(Status::OK, status);
599 EXPECT_EQ(0u, ids.size());
600 }).isOk();
601 EXPECT_TRUE(ok);
602 }
603
604 /**
605 * Test that there are secure stop ids after loading keys once
606 */
TEST_F(DrmHalClearkeyTest,GetSecureStopIdsOnce)607 TEST_F(DrmHalClearkeyTest, GetSecureStopIdsOnce) {
608 auto stat = drmPlugin->removeAllSecureStops();
609 EXPECT_OK(stat);
610
611 auto sessionId = openSession();
612 loadKeys(sessionId);
613 closeSession(sessionId);
614
615 auto res = drmPlugin->getSecureStopIds(
616 [&](Status status, const hidl_vec<SecureStopId>& ids) {
617 EXPECT_EQ(Status::OK, status);
618 EXPECT_EQ(1u, ids.size());
619 });
620 EXPECT_OK(res);
621
622 stat = drmPlugin->removeAllSecureStops();
623 EXPECT_OK(stat);
624
625 res = drmPlugin->getSecureStopIds(
626 [&](Status status, const hidl_vec<SecureStopId>& ids) {
627 EXPECT_EQ(Status::OK, status);
628 EXPECT_EQ(0u, ids.size());
629 });
630 EXPECT_OK(res);
631 }
632
633 /**
634 * Since getSecureStopIds only queries information there are no
635 * negative cases.
636 */
637
638 /**
639 * Test that the clearkey plugin reports no secure stops when
640 * there are none.
641 */
TEST_F(DrmHalClearkeyTest,GetNoSecureStops)642 TEST_F(DrmHalClearkeyTest, GetNoSecureStops) {
643 auto stat = drmPlugin->removeAllSecureStops();
644 EXPECT_OK(stat);
645
646 auto res = drmPlugin->getSecureStops(
647 [&](Status status, const hidl_vec<SecureStop>& stops) {
648 EXPECT_EQ(Status::OK, status);
649 EXPECT_EQ(0u, stops.size());
650 });
651 EXPECT_OK(res);
652 }
653
654 /**
655 * Test get/remove of one secure stop
656 */
TEST_F(DrmHalClearkeyTest,GetOneSecureStopAndRemoveIt)657 TEST_F(DrmHalClearkeyTest, GetOneSecureStopAndRemoveIt) {
658 auto stat = drmPlugin->removeAllSecureStops();
659 EXPECT_OK(stat);
660
661 auto sessionId = openSession();
662 loadKeys(sessionId);
663 closeSession(sessionId);
664
665 auto res = drmPlugin->getSecureStops(
666 [&](Status status, const hidl_vec<SecureStop>& stops) {
667 EXPECT_EQ(Status::OK, status);
668 EXPECT_EQ(1u, stops.size());
669 });
670 EXPECT_OK(res);
671
672 stat = drmPlugin->removeAllSecureStops();
673 EXPECT_OK(stat);
674
675 res = drmPlugin->getSecureStops(
676 [&](Status status, const hidl_vec<SecureStop>& stops) {
677 EXPECT_EQ(Status::OK, status);
678 EXPECT_EQ(0u, stops.size());
679 });
680 EXPECT_OK(res);
681 }
682
683 /**
684 * Since getSecureStops only queries information there are no
685 * negative cases.
686 */
687
688 /**
689 * Test that there are no secure stops after clearing them
690 */
TEST_F(DrmHalClearkeyTest,GetSecureStopsCleared)691 TEST_F(DrmHalClearkeyTest, GetSecureStopsCleared) {
692 auto stat = drmPlugin->removeAllSecureStops();
693 EXPECT_OK(stat);
694
695 auto res = drmPlugin->getSecureStops(
696 [&](Status status, const hidl_vec<SecureStop>& stops) {
697 EXPECT_EQ(Status::OK, status);
698 EXPECT_EQ(0u, stops.size());
699 });
700 EXPECT_OK(res);
701 }
702
703 /**
704 * Test that there are secure stops after loading keys once
705 */
TEST_F(DrmHalClearkeyTest,GetSecureStopsOnce)706 TEST_F(DrmHalClearkeyTest, GetSecureStopsOnce) {
707 auto stat = drmPlugin->removeAllSecureStops();
708 EXPECT_OK(stat);
709
710 auto sessionId = openSession();
711 loadKeys(sessionId);
712 closeSession(sessionId);
713
714 auto res = drmPlugin->getSecureStops(
715 [&](Status status, const hidl_vec<SecureStop>& stops) {
716 EXPECT_EQ(Status::OK, status);
717 EXPECT_EQ(1u, stops.size());
718 });
719 EXPECT_OK(res);
720
721 stat = drmPlugin->removeAllSecureStops();
722 EXPECT_OK(stat);
723
724 res = drmPlugin->getSecureStops(
725 [&](Status status, const hidl_vec<SecureStop>& stops) {
726 EXPECT_EQ(Status::OK, status);
727 EXPECT_EQ(0u, stops.size());
728 });
729 EXPECT_OK(res);
730 }
731
732 /**
733 * Since getSecureStops only queries information there are no
734 * negative cases.
735 */
736
737 /**
738 * Test that releasing a secure stop with empty
739 * release message fails with the documented error
740 */
TEST_F(DrmHalClearkeyTest,ReleaseEmptySecureStop)741 TEST_F(DrmHalClearkeyTest, ReleaseEmptySecureStop) {
742 SecureStopRelease emptyRelease = {.opaqueData = hidl_vec<uint8_t>()};
743 Status status = drmPlugin->releaseSecureStops(emptyRelease);
744 EXPECT_EQ(Status::BAD_VALUE, status);
745 }
746
747 /**
748 * Helper function to create a secure release message for
749 * a secure stop. The clearkey secure stop release format
750 * is just a count followed by the secure stop opaque data.
751 */
makeSecureRelease(const SecureStop & stop)752 SecureStopRelease makeSecureRelease(const SecureStop &stop) {
753 std::vector<uint8_t> stopData = stop.opaqueData;
754 std::vector<uint8_t> buffer;
755 std::string count = "0001";
756
757 auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
758 buffer.insert(it + count.size(), stopData.begin(), stopData.end());
759 SecureStopRelease release = { .opaqueData = hidl_vec<uint8_t>(buffer) };
760 return release;
761 }
762
763 /**
764 * Test that releasing one secure stop works
765 */
TEST_F(DrmHalClearkeyTest,ReleaseOneSecureStop)766 TEST_F(DrmHalClearkeyTest, ReleaseOneSecureStop) {
767
768 auto stat = drmPlugin->removeAllSecureStops();
769 EXPECT_OK(stat);
770
771 auto sessionId = openSession();
772 loadKeys(sessionId);
773 closeSession(sessionId);
774
775 SecureStopRelease release;
776 auto res = drmPlugin->getSecureStops(
777 [&](Status status, const hidl_vec<SecureStop>& stops) {
778 EXPECT_EQ(Status::OK, status);
779 EXPECT_EQ(1u, stops.size());
780 release = makeSecureRelease(stops[0]);
781 });
782 EXPECT_OK(res);
783
784 stat = drmPlugin->releaseSecureStops(release);
785 EXPECT_OK(stat);
786
787 res = drmPlugin->getSecureStops(
788 [&](Status status, const hidl_vec<SecureStop>& stops) {
789 EXPECT_EQ(Status::OK, status);
790 EXPECT_EQ(0u, stops.size());
791 });
792 EXPECT_OK(res);
793 }
794
795
796 /**
797 * Test that removing a secure stop with an empty ID returns
798 * documented error
799 */
TEST_F(DrmHalClearkeyTest,RemoveEmptySecureStopId)800 TEST_F(DrmHalClearkeyTest, RemoveEmptySecureStopId) {
801 hidl_vec<uint8_t> emptyId;
802 auto stat = drmPlugin->removeSecureStop(emptyId);
803 EXPECT_OK(stat);
804 EXPECT_EQ(Status::BAD_VALUE, stat);
805 }
806
807 /**
808 * Test that removing a secure stop after it has already
809 * been removed fails with the documented error code.
810 */
TEST_F(DrmHalClearkeyTest,RemoveRemovedSecureStopId)811 TEST_F(DrmHalClearkeyTest, RemoveRemovedSecureStopId) {
812 auto stat = drmPlugin->removeAllSecureStops();
813 EXPECT_OK(stat);
814
815 auto sessionId = openSession();
816 loadKeys(sessionId);
817 closeSession(sessionId);
818 SecureStopId ssid;
819
820 auto res = drmPlugin->getSecureStopIds(
821 [&](Status status, const hidl_vec<SecureStopId>& ids) {
822 EXPECT_EQ(Status::OK, status);
823 EXPECT_EQ(1u, ids.size());
824 ssid = ids[0];
825 });
826 EXPECT_OK(res);
827
828 stat = drmPlugin->removeAllSecureStops();
829 EXPECT_OK(stat);
830
831 Status status = drmPlugin->removeSecureStop(ssid);
832 EXPECT_EQ(Status::BAD_VALUE, status);
833 }
834
835 /**
836 * Test that removing a secure stop by id works
837 */
TEST_F(DrmHalClearkeyTest,RemoveSecureStopById)838 TEST_F(DrmHalClearkeyTest, RemoveSecureStopById) {
839 auto stat = drmPlugin->removeAllSecureStops();
840 EXPECT_OK(stat);
841
842 auto sessionId = openSession();
843 loadKeys(sessionId);
844 closeSession(sessionId);
845 SecureStopId ssid;
846
847 auto res = drmPlugin->getSecureStopIds(
848 [&](Status status, const hidl_vec<SecureStopId>& ids) {
849 EXPECT_EQ(Status::OK, status);
850 EXPECT_EQ(1u, ids.size());
851 ssid = ids[0];
852 });
853 EXPECT_OK(res);
854
855 stat = drmPlugin->removeSecureStop(ssid);
856 EXPECT_OK(stat);
857
858 res = drmPlugin->getSecureStopIds(
859 [&](Status status, const hidl_vec<SecureStopId>& ids) {
860 EXPECT_EQ(Status::OK, status);
861 EXPECT_EQ(0u, ids.size());
862 });
863 EXPECT_OK(res);
864 }
865
866
main(int argc,char ** argv)867 int main(int argc, char** argv) {
868 ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
869 ::testing::InitGoogleTest(&argc, argv);
870 DrmHidlEnvironment::Instance()->init(&argc, argv);
871 int status = RUN_ALL_TESTS();
872 ALOGI("Test result = %d", status);
873 return status;
874 }
875