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.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:
SetUp()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
TearDown()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 */
TEST_F(DrmHalClearkeyFactoryTest,ClearKeyPluginSupported)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 */
TEST_F(DrmHalClearkeyFactoryTest,InvalidPluginNotSupported)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 */
TEST_F(DrmHalClearkeyFactoryTest,EmptyPluginUUIDNotSupported)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 */
TEST_F(DrmHalClearkeyFactoryTest,EmptyContentTypeNotSupported)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 */
TEST_F(DrmHalClearkeyFactoryTest,InvalidContentTypeNotSupported)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 */
TEST_F(DrmHalClearkeyFactoryTest,ValidContentTypeSupported)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 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyDrmPluginUsingCommonPsshBoxUuid)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 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyDrmPluginUsingClearKeyUuid)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 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyCryptoPluginUsingCommonPsshBoxUuid)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 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyCryptoPluginUsingClearKeyUuid)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 */
TEST_F(DrmHalClearkeyFactoryTest,CreateInvalidDrmPlugin)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 */
TEST_F(DrmHalClearkeyFactoryTest,CreateInvalidCryptoPlugin)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:
SetUp()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
TearDown()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 */
TEST_F(DrmHalClearkeyPluginTest,GetProvisionRequest)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 */
TEST_F(DrmHalClearkeyPluginTest,ProvideEmptyProvisionResponse)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 */
openSession()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 */
closeSession(const SessionId & sessionId)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 */
loadKeys(const SessionId & sessionId,const KeyType & type=KeyType::STREAMING)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 */
TEST_F(DrmHalClearkeyPluginTest,OpenCloseSession)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 */
TEST_F(DrmHalClearkeyPluginTest,CloseInvalidSession)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 */
TEST_F(DrmHalClearkeyPluginTest,CloseClosedSession)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 */
TEST_F(DrmHalClearkeyPluginTest,GetKeyRequestNoSession)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 */
TEST_F(DrmHalClearkeyPluginTest,GetKeyRequestOfflineKeyTypeNotSupported)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 */
TEST_F(DrmHalClearkeyPluginTest,GetKeyRequestBadMime)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 */
TEST_F(DrmHalClearkeyPluginTest,ProvideKeyResponseClosedSession)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 */
TEST_F(DrmHalClearkeyPluginTest,ProvideKeyResponseInvalidSessionId)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 */
TEST_F(DrmHalClearkeyPluginTest,ProvideKeyResponseEmptyResponse)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 */
TEST_F(DrmHalClearkeyPluginTest,RemoveKeysEmptySessionId)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 */
TEST_F(DrmHalClearkeyPluginTest,RemoveKeysNewSession)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 */
TEST_F(DrmHalClearkeyPluginTest,RestoreKeysCannotHandle)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 */
TEST_F(DrmHalClearkeyPluginTest,RestoreKeysNull)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 */
TEST_F(DrmHalClearkeyPluginTest,GetSecureStops)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 */
TEST_F(DrmHalClearkeyPluginTest,GetSecureStopEmptySSID)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 */
TEST_F(DrmHalClearkeyPluginTest,ReleaseAllSecureStops)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 */
TEST_F(DrmHalClearkeyPluginTest,ReleaseSecureStopEmptySSID)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 */
TEST_F(DrmHalClearkeyPluginTest,GetVendorProperty)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
TEST_F(DrmHalClearkeyPluginTest,GetVersionProperty)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
TEST_F(DrmHalClearkeyPluginTest,GetDescriptionProperty)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
TEST_F(DrmHalClearkeyPluginTest,GetAlgorithmsProperty)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 */
TEST_F(DrmHalClearkeyPluginTest,GetInvalidStringProperty)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
TEST_F(DrmHalClearkeyPluginTest,GetByteArrayPropertyNotSupported)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 */
TEST_F(DrmHalClearkeyPluginTest,SetStringPropertyNotSupported)704 TEST_F(DrmHalClearkeyPluginTest, SetStringPropertyNotSupported) {
705 Status status = drmPlugin->setPropertyString("property", "value");
706 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
707 }
708
TEST_F(DrmHalClearkeyPluginTest,SetByteArrayPropertyNotSupported)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 */
TEST_F(DrmHalClearkeyPluginTest,SetCipherAlgorithmNotSupported)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 */
TEST_F(DrmHalClearkeyPluginTest,SetCipherEmptyAlgorithm)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 */
TEST_F(DrmHalClearkeyPluginTest,SetCipherAlgorithmNoSession)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 */
TEST_F(DrmHalClearkeyPluginTest,SetMacAlgorithmNotSupported)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 */
TEST_F(DrmHalClearkeyPluginTest,SetMacEmptyAlgorithm)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 */
TEST_F(DrmHalClearkeyPluginTest,SetMacAlgorithmNoSession)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 */
TEST_F(DrmHalClearkeyPluginTest,GenericEncryptNotSupported)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
TEST_F(DrmHalClearkeyPluginTest,GenericDecryptNotSupported)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
TEST_F(DrmHalClearkeyPluginTest,GenericSignNotSupported)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
TEST_F(DrmHalClearkeyPluginTest,GenericVerifyNotSupported)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
TEST_F(DrmHalClearkeyPluginTest,GenericSignRSANotSupported)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 */
TEST_F(DrmHalClearkeyPluginTest,RequiresSecureDecoder)870 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoder) {
871 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("cenc"));
872 }
873
874 /**
875 * Verify that requiresSecureDecoderComponent handles empty mimetype
876 */
TEST_F(DrmHalClearkeyPluginTest,RequiresSecureDecoderEmptyMimeType)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 */
TEST_F(DrmHalClearkeyPluginTest,NotifyResolution)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 */
getDecryptMemory(size_t size,size_t index)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 */
TEST_F(DrmHalClearkeyPluginTest,SetMediaDrmSession)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 */
TEST_F(DrmHalClearkeyPluginTest,SetMediaDrmSessionClosedSession)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 */
TEST_F(DrmHalClearkeyPluginTest,SetMediaDrmSessionEmptySession)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);
toHidlArray(const vector<uint8_t> & vec)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
fillRandom(const sp<IMemory> & memory)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
decrypt(Mode mode,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const Pattern & pattern,Status expectedStatus)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 */
aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)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 */
aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)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 */
TEST_F(DrmHalClearkeyDecryptTest,TestQueryKeyStatus)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 */
TEST_F(DrmHalClearkeyDecryptTest,ClearSegmentTest)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 */
TEST_F(DrmHalClearkeyDecryptTest,EncryptedAesCtrSegmentTest)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 */
TEST_F(DrmHalClearkeyDecryptTest,EncryptedAesCtrSegmentTestNoKeys)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 */
decryptWithInvalidKeys(hidl_vec<uint8_t> & invalidResponse,vector<uint8_t> & iv,const Pattern & noPattern,const vector<SubSample> & subSamples)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 */
TEST_F(DrmHalClearkeyDecryptTest,DecryptWithEmptyKey)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 */
TEST_F(DrmHalClearkeyDecryptTest,DecryptWithKeyTooLong)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