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 static const uint32_t k256SubSampleByteCount = 256;
93 static const uint32_t k512SubSampleClearBytes = 512;
94 static const uint32_t k512SubSampleEncryptedBytes = 512;
95
96 class DrmHalClearkeyFactoryTest : public ::testing::VtsHalHidlTargetTestBase {
97 public:
SetUp()98 virtual void SetUp() override {
99 const ::testing::TestInfo* const test_info =
100 ::testing::UnitTest::GetInstance()->current_test_info();
101 ALOGD("Running test %s.%s", test_info->test_case_name(),
102 test_info->name());
103
104 drmFactory =
105 ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>();
106 ASSERT_NE(nullptr, drmFactory.get());
107 cryptoFactory =
108 ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>();
109 ASSERT_NE(nullptr, cryptoFactory.get());
110 }
111
TearDown()112 virtual void TearDown() override {}
113
114 protected:
115 sp<IDrmFactory> drmFactory;
116 sp<ICryptoFactory> cryptoFactory;
117 };
118
119 /**
120 * Ensure the factory supports both Common Pssh Box UUID and Clearkey Scheme UUID
121 */
TEST_F(DrmHalClearkeyFactoryTest,ClearKeyPluginSupported)122 TEST_F(DrmHalClearkeyFactoryTest, ClearKeyPluginSupported) {
123 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID));
124 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID));
125
126 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kClearKeyUUID));
127 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID));
128 }
129
130 /**
131 * Ensure the factory doesn't support an invalid scheme UUID
132 */
TEST_F(DrmHalClearkeyFactoryTest,InvalidPluginNotSupported)133 TEST_F(DrmHalClearkeyFactoryTest, InvalidPluginNotSupported) {
134 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID));
135 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID));
136 }
137
138 /**
139 * Ensure the factory doesn't support an empty UUID
140 */
TEST_F(DrmHalClearkeyFactoryTest,EmptyPluginUUIDNotSupported)141 TEST_F(DrmHalClearkeyFactoryTest, EmptyPluginUUIDNotSupported) {
142 hidl_array<uint8_t, 16> emptyUUID;
143 memset(emptyUUID.data(), 0, 16);
144 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
145 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
146 }
147
148 /**
149 * Ensure empty content type is not supported
150 */
TEST_F(DrmHalClearkeyFactoryTest,EmptyContentTypeNotSupported)151 TEST_F(DrmHalClearkeyFactoryTest, EmptyContentTypeNotSupported) {
152 hidl_string empty;
153 EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
154 }
155
156 /**
157 * Ensure invalid content type is not supported
158 */
TEST_F(DrmHalClearkeyFactoryTest,InvalidContentTypeNotSupported)159 TEST_F(DrmHalClearkeyFactoryTest, InvalidContentTypeNotSupported) {
160 hidl_string invalid("abcdabcd");
161 EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
162 }
163
164 /**
165 * Ensure valid content type is supported
166 */
TEST_F(DrmHalClearkeyFactoryTest,ValidContentTypeSupported)167 TEST_F(DrmHalClearkeyFactoryTest, ValidContentTypeSupported) {
168 hidl_string cencType("cenc");
169 EXPECT_TRUE(drmFactory->isContentTypeSupported(cencType));
170 }
171
172 /**
173 * Ensure clearkey drm plugin can be created using Common Pssh Box UUID
174 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyDrmPluginUsingCommonPsshBoxUuid)175 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPluginUsingCommonPsshBoxUuid) {
176 hidl_string packageName("android.hardware.drm.test");
177 auto res = drmFactory->createPlugin(
178 kCommonPsshBoxUUID, packageName,
179 [&](Status status, const sp<IDrmPlugin>& plugin) {
180 EXPECT_EQ(Status::OK, status);
181 EXPECT_NE(nullptr, plugin.get());
182 });
183 EXPECT_OK(res);
184 }
185
186 /**
187 * Ensure clearkey drm plugin can be created using ClearKey UUID
188 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyDrmPluginUsingClearKeyUuid)189 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPluginUsingClearKeyUuid) {
190 hidl_string packageName("android.hardware.drm.test");
191 auto res = drmFactory->createPlugin(
192 kClearKeyUUID, packageName,
193 [&](Status status, const sp<IDrmPlugin>& plugin) {
194 EXPECT_EQ(Status::OK, status);
195 EXPECT_NE(nullptr, plugin.get());
196 });
197 EXPECT_OK(res);
198 }
199
200 /**
201 * Ensure clearkey crypto plugin can be created using Common Pssh Box UUID
202 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyCryptoPluginUsingCommonPsshBoxUuid)203 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPluginUsingCommonPsshBoxUuid) {
204 hidl_vec<uint8_t> initVec;
205 auto res = cryptoFactory->createPlugin(
206 kCommonPsshBoxUUID, initVec,
207 [&](Status status, const sp<ICryptoPlugin>& plugin) {
208 EXPECT_EQ(Status::OK, status);
209 EXPECT_NE(nullptr, plugin.get());
210 });
211 EXPECT_OK(res);
212 }
213
214 /**
215 * Ensure clearkey crypto plugin can be created using ClearKey UUID
216 */
TEST_F(DrmHalClearkeyFactoryTest,CreateClearKeyCryptoPluginUsingClearKeyUuid)217 TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyCryptoPluginUsingClearKeyUuid) {
218 hidl_vec<uint8_t> initVec;
219 auto res = cryptoFactory->createPlugin(
220 kClearKeyUUID, initVec,
221 [&](Status status, const sp<ICryptoPlugin>& plugin) {
222 EXPECT_EQ(Status::OK, status);
223 EXPECT_NE(nullptr, plugin.get());
224 });
225 EXPECT_OK(res);
226 }
227
228 /**
229 * Ensure invalid drm plugin can't be created
230 */
TEST_F(DrmHalClearkeyFactoryTest,CreateInvalidDrmPlugin)231 TEST_F(DrmHalClearkeyFactoryTest, CreateInvalidDrmPlugin) {
232 hidl_string packageName("android.hardware.drm.test");
233 auto res = drmFactory->createPlugin(
234 kInvalidUUID, packageName,
235 [&](Status status, const sp<IDrmPlugin>& plugin) {
236 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
237 EXPECT_EQ(nullptr, plugin.get());
238 });
239 EXPECT_OK(res);
240 }
241
242 /**
243 * Ensure invalid crypto plugin can't be created
244 */
TEST_F(DrmHalClearkeyFactoryTest,CreateInvalidCryptoPlugin)245 TEST_F(DrmHalClearkeyFactoryTest, CreateInvalidCryptoPlugin) {
246 hidl_vec<uint8_t> initVec;
247 auto res = cryptoFactory->createPlugin(
248 kInvalidUUID, initVec,
249 [&](Status status, const sp<ICryptoPlugin>& plugin) {
250 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
251 EXPECT_EQ(nullptr, plugin.get());
252 });
253 EXPECT_OK(res);
254 }
255
256 class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {
257 public:
SetUp()258 virtual void SetUp() override {
259 // Create factories
260 DrmHalClearkeyFactoryTest::SetUp();
261
262 ASSERT_NE(nullptr, drmFactory.get());
263 hidl_string packageName("android.hardware.drm.test");
264 auto res = drmFactory->createPlugin(
265 kClearKeyUUID, packageName,
266 [this](Status status, const sp<IDrmPlugin>& plugin) {
267 EXPECT_EQ(Status::OK, status);
268 ASSERT_NE(nullptr, plugin.get());
269 drmPlugin = plugin;
270 });
271 ASSERT_OK(res);
272
273 hidl_vec<uint8_t> initVec;
274 res = cryptoFactory->createPlugin(
275 kClearKeyUUID, initVec,
276 [this](Status status, const sp<ICryptoPlugin>& plugin) {
277 EXPECT_EQ(Status::OK, status);
278 ASSERT_NE(nullptr, plugin.get());
279 cryptoPlugin = plugin;
280 });
281 ASSERT_OK(res);
282 }
283
TearDown()284 virtual void TearDown() override {}
285
286 SessionId openSession();
287 void closeSession(const SessionId& sessionId);
288 hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
289 sp<IMemory> getDecryptMemory(size_t size, size_t index);
290
291 protected:
292 sp<IDrmPlugin> drmPlugin;
293 sp<ICryptoPlugin> cryptoPlugin;
294 };
295
296 /**
297 * DrmPlugin tests
298 */
299
300 /**
301 * Test that the plugin can return a provision request. Since
302 * the clearkey plugin doesn't support provisioning, it is
303 * expected to return Status::ERROR_DRM_CANNOT_HANDLE.
304 */
TEST_F(DrmHalClearkeyPluginTest,GetProvisionRequest)305 TEST_F(DrmHalClearkeyPluginTest, GetProvisionRequest) {
306 hidl_string certificateType;
307 hidl_string certificateAuthority;
308 auto res = drmPlugin->getProvisionRequest(
309 certificateType, certificateAuthority,
310 [&](Status status, const hidl_vec<uint8_t>&, const hidl_string&) {
311 // clearkey doesn't require provisioning
312 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
313 });
314 EXPECT_OK(res);
315 }
316
317 /**
318 * The DRM HAL should return BAD_VALUE if an empty provisioning
319 * response is provided.
320 */
TEST_F(DrmHalClearkeyPluginTest,ProvideEmptyProvisionResponse)321 TEST_F(DrmHalClearkeyPluginTest, ProvideEmptyProvisionResponse) {
322 hidl_vec<uint8_t> response;
323 auto res = drmPlugin->provideProvisionResponse(
324 response, [&](Status status, const hidl_vec<uint8_t>&,
325 const hidl_vec<uint8_t>&) {
326 EXPECT_EQ(Status::BAD_VALUE, status);
327 });
328 EXPECT_OK(res);
329 }
330
331 /**
332 * Helper method to open a session and verify that a non-empty
333 * session ID is returned
334 */
openSession()335 SessionId DrmHalClearkeyPluginTest::openSession() {
336 SessionId sessionId;
337
338 auto res = drmPlugin->openSession(
339 [&sessionId](Status status, const SessionId& id) {
340 EXPECT_EQ(Status::OK, status);
341 EXPECT_NE(0u, id.size());
342 sessionId = id;
343 });
344 EXPECT_OK(res);
345 return sessionId;
346 }
347
348 /**
349 * Helper method to close a session
350 */
closeSession(const SessionId & sessionId)351 void DrmHalClearkeyPluginTest::closeSession(const SessionId& sessionId) {
352 auto result = drmPlugin->closeSession(sessionId);
353 EXPECT_EQ(Status::OK, result);
354 }
355
356 /**
357 * Helper method to load keys for subsequent decrypt tests.
358 * These tests use predetermined key request/response to
359 * avoid requiring a round trip to a license server.
360 */
loadKeys(const SessionId & sessionId,const KeyType & type=KeyType::STREAMING)361 hidl_vec<uint8_t> DrmHalClearkeyPluginTest::loadKeys(
362 const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
363 hidl_vec<uint8_t> initData = {
364 // BMFF box header (4 bytes size + 'pssh')
365 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
366 // full box header (version = 1 flags = 0)
367 0x01, 0x00, 0x00, 0x00,
368 // system id
369 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
370 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
371 // number of key ids
372 0x00, 0x00, 0x00, 0x01,
373 // key id
374 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
375 0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
376 // size of data, must be zero
377 0x00, 0x00, 0x00, 0x00};
378
379 hidl_vec<uint8_t> expectedKeyRequest = {
380 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
381 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
382 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
383 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
384
385 hidl_vec<uint8_t> knownKeyResponse = {
386 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
387 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
388 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
389 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
390 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
391 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
392
393 hidl_string mimeType = "video/mp4";
394 KeyedVector optionalParameters;
395 auto res = drmPlugin->getKeyRequest(
396 sessionId, initData, mimeType, type, optionalParameters,
397 [&](Status status, const hidl_vec<uint8_t>& request,
398 KeyRequestType requestType, const hidl_string&) {
399 EXPECT_EQ(Status::OK, status);
400 EXPECT_EQ(KeyRequestType::INITIAL, requestType);
401 EXPECT_EQ(request, expectedKeyRequest);
402 });
403 EXPECT_OK(res);
404
405 hidl_vec<uint8_t> keySetId;
406 res = drmPlugin->provideKeyResponse(
407 sessionId, knownKeyResponse,
408 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
409 EXPECT_EQ(Status::OK, status);
410 EXPECT_EQ(0u, myKeySetId.size());
411 keySetId = myKeySetId;
412 });
413 EXPECT_OK(res);
414 return keySetId;
415 }
416
417 /**
418 * Test that a session can be opened and closed
419 */
TEST_F(DrmHalClearkeyPluginTest,OpenCloseSession)420 TEST_F(DrmHalClearkeyPluginTest, OpenCloseSession) {
421 auto sessionId = openSession();
422 closeSession(sessionId);
423 }
424
425 /**
426 * Test that attempting to close an invalid (empty) sessionId
427 * is prohibited with the documented error code.
428 */
TEST_F(DrmHalClearkeyPluginTest,CloseInvalidSession)429 TEST_F(DrmHalClearkeyPluginTest, CloseInvalidSession) {
430 SessionId invalidSessionId;
431 Status result = drmPlugin->closeSession(invalidSessionId);
432 EXPECT_EQ(Status::BAD_VALUE, result);
433 }
434
435 /**
436 * Test that attempting to close a session that is already closed
437 * is prohibited with the documented error code.
438 */
TEST_F(DrmHalClearkeyPluginTest,CloseClosedSession)439 TEST_F(DrmHalClearkeyPluginTest, CloseClosedSession) {
440 SessionId sessionId = openSession();
441 closeSession(sessionId);
442 Status result = drmPlugin->closeSession(sessionId);
443 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, result);
444 }
445
446 /**
447 * A get key request should fail if no sessionId is provided
448 */
TEST_F(DrmHalClearkeyPluginTest,GetKeyRequestNoSession)449 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestNoSession) {
450 SessionId invalidSessionId;
451 hidl_vec<uint8_t> initData;
452 hidl_string mimeType = "video/mp4";
453 KeyedVector optionalParameters;
454 auto res = drmPlugin->getKeyRequest(
455 invalidSessionId, initData, mimeType, KeyType::STREAMING,
456 optionalParameters,
457 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
458 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
459 EXPECT_OK(res);
460 }
461
462 /**
463 * The clearkey plugin doesn't support offline key requests.
464 * Test that the plugin returns the expected error code in
465 * this case.
466 */
TEST_F(DrmHalClearkeyPluginTest,GetKeyRequestOfflineKeyTypeNotSupported)467 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestOfflineKeyTypeNotSupported) {
468 auto sessionId = openSession();
469 hidl_vec<uint8_t> initData;
470 hidl_string mimeType = "video/mp4";
471 KeyedVector optionalParameters;
472
473 auto res = drmPlugin->getKeyRequest(
474 sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
475 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
476 const hidl_string&) {
477 // Clearkey plugin doesn't support offline key type
478 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
479 });
480 EXPECT_OK(res);
481 closeSession(sessionId);
482 }
483
484 /**
485 * Test that the plugin returns the documented error for the
486 * case of attempting to generate a key request using an
487 * invalid mime type
488 */
TEST_F(DrmHalClearkeyPluginTest,GetKeyRequestBadMime)489 TEST_F(DrmHalClearkeyPluginTest, GetKeyRequestBadMime) {
490 auto sessionId = openSession();
491 hidl_vec<uint8_t> initData;
492 hidl_string mimeType = "video/unknown";
493 KeyedVector optionalParameters;
494 auto res = drmPlugin->getKeyRequest(
495 sessionId, initData, mimeType, KeyType::STREAMING,
496 optionalParameters, [&](Status status, const hidl_vec<uint8_t>&,
497 KeyRequestType, const hidl_string&) {
498 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
499 });
500 EXPECT_OK(res);
501 closeSession(sessionId);
502 }
503
504 /**
505 * Test that a closed sessionID returns SESSION_NOT_OPENED
506 */
TEST_F(DrmHalClearkeyPluginTest,ProvideKeyResponseClosedSession)507 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseClosedSession) {
508 SessionId session = openSession();
509 closeSession(session);
510
511 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65,
512 0x79, 0x73, 0x22, 0x3a};
513 auto res = drmPlugin->provideKeyResponse(
514 session, keyResponse,
515 [&](Status status, const hidl_vec<uint8_t>& keySetId) {
516 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
517 EXPECT_EQ(0u, keySetId.size());
518 });
519 EXPECT_OK(res);
520 }
521
522 /**
523 * Test that an empty sessionID returns BAD_VALUE
524 */
TEST_F(DrmHalClearkeyPluginTest,ProvideKeyResponseInvalidSessionId)525 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseInvalidSessionId) {
526 SessionId session;
527
528 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65,
529 0x79, 0x73, 0x22, 0x3a};
530 auto res = drmPlugin->provideKeyResponse(
531 session, keyResponse,
532 [&](Status status, const hidl_vec<uint8_t>& keySetId) {
533 EXPECT_EQ(Status::BAD_VALUE, status);
534 EXPECT_EQ(0u, keySetId.size());
535 });
536 EXPECT_OK(res);
537 }
538
539 /**
540 * Test that an empty key response returns BAD_VALUE
541 */
TEST_F(DrmHalClearkeyPluginTest,ProvideKeyResponseEmptyResponse)542 TEST_F(DrmHalClearkeyPluginTest, ProvideKeyResponseEmptyResponse) {
543 SessionId session = openSession();
544 hidl_vec<uint8_t> emptyResponse;
545 auto res = drmPlugin->provideKeyResponse(
546 session, emptyResponse,
547 [&](Status status, const hidl_vec<uint8_t>& keySetId) {
548 EXPECT_EQ(Status::BAD_VALUE, status);
549 EXPECT_EQ(0u, keySetId.size());
550 });
551 EXPECT_OK(res);
552 closeSession(session);
553 }
554
555 /**
556 * Test that a removeKeys on an empty sessionID returns BAD_VALUE
557 */
TEST_F(DrmHalClearkeyPluginTest,RemoveKeysEmptySessionId)558 TEST_F(DrmHalClearkeyPluginTest, RemoveKeysEmptySessionId) {
559 SessionId sessionId;
560 Status status = drmPlugin->removeKeys(sessionId);
561 EXPECT_TRUE(status == Status::BAD_VALUE);
562 }
563
564 /**
565 * Remove keys is not supported for clearkey.
566 */
TEST_F(DrmHalClearkeyPluginTest,RemoveKeysNewSession)567 TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) {
568 SessionId sessionId = openSession();
569 Status status = drmPlugin->removeKeys(sessionId);
570 // Clearkey plugin doesn't support remove keys
571 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
572 closeSession(sessionId);
573 }
574
575 /**
576 * Test that ClearKey cannot handle key restoring.
577 * Expected message is Status::ERROR_DRM_CANNOT_HANDLE.
578 */
TEST_F(DrmHalClearkeyPluginTest,RestoreKeysCannotHandle)579 TEST_F(DrmHalClearkeyPluginTest, RestoreKeysCannotHandle) {
580 hidl_vec<uint8_t> keySetId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
581 SessionId sessionId = openSession();
582 Status status = drmPlugin->restoreKeys(sessionId, keySetId);
583 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
584 closeSession(sessionId);
585 }
586
587 /**
588 * Test that restoreKeys fails with a null key set ID.
589 * Error message is expected to be Status::BAD_VALUE.
590 */
TEST_F(DrmHalClearkeyPluginTest,RestoreKeysNull)591 TEST_F(DrmHalClearkeyPluginTest, RestoreKeysNull) {
592 SessionId sessionId = openSession();
593 hidl_vec<uint8_t> nullKeySetId;
594 Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId);
595 EXPECT_EQ(Status::BAD_VALUE, status);
596 closeSession(sessionId);
597 }
598
599 /**
600 * Test that the clearkey plugin doesn't support getting
601 * secure stops.
602 */
TEST_F(DrmHalClearkeyPluginTest,GetSecureStops)603 TEST_F(DrmHalClearkeyPluginTest, GetSecureStops) {
604 auto res = drmPlugin->getSecureStops(
605 [&](Status status, const hidl_vec<SecureStop>&) {
606 // Clearkey plugin doesn't support secure stops
607 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
608 });
609 EXPECT_OK(res);
610 }
611
612 /**
613 * Test that the clearkey plugin returns BAD_VALUE if
614 * an empty ssid is provided.
615 */
TEST_F(DrmHalClearkeyPluginTest,GetSecureStopEmptySSID)616 TEST_F(DrmHalClearkeyPluginTest, GetSecureStopEmptySSID) {
617 SecureStopId ssid;
618 auto res = drmPlugin->getSecureStop(
619 ssid, [&](Status status, const SecureStop&) {
620 EXPECT_EQ(Status::BAD_VALUE, status);
621 });
622 EXPECT_OK(res);
623 }
624
625 /**
626 * Test that releasing all secure stops isn't handled by
627 * clearkey.
628 */
TEST_F(DrmHalClearkeyPluginTest,ReleaseAllSecureStops)629 TEST_F(DrmHalClearkeyPluginTest, ReleaseAllSecureStops) {
630 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
631 drmPlugin->releaseAllSecureStops());
632 }
633
634 /**
635 * Test that releasing a specific secure stop with an empty
636 * SSID returns BAD_VALUE.
637 */
TEST_F(DrmHalClearkeyPluginTest,ReleaseSecureStopEmptySSID)638 TEST_F(DrmHalClearkeyPluginTest, ReleaseSecureStopEmptySSID) {
639 SecureStopId ssid;
640 Status status = drmPlugin->releaseSecureStop(ssid);
641 EXPECT_EQ(Status::BAD_VALUE, status);
642 }
643
644 /**
645 * The following four tests verify that the properties
646 * defined in the MediaDrm API are supported by
647 * the plugin.
648 */
TEST_F(DrmHalClearkeyPluginTest,GetVendorProperty)649 TEST_F(DrmHalClearkeyPluginTest, GetVendorProperty) {
650 auto res = drmPlugin->getPropertyString(
651 "vendor", [&](Status status, const hidl_string& value) {
652 EXPECT_EQ(Status::OK, status);
653 EXPECT_EQ("Google", value);
654 });
655 EXPECT_OK(res);
656 }
657
TEST_F(DrmHalClearkeyPluginTest,GetVersionProperty)658 TEST_F(DrmHalClearkeyPluginTest, GetVersionProperty) {
659 auto res = drmPlugin->getPropertyString(
660 "version", [&](Status status, const hidl_string& value) {
661 EXPECT_EQ(Status::OK, status);
662 EXPECT_EQ("1.0", value);
663 });
664 EXPECT_OK(res);
665 }
666
TEST_F(DrmHalClearkeyPluginTest,GetDescriptionProperty)667 TEST_F(DrmHalClearkeyPluginTest, GetDescriptionProperty) {
668 auto res = drmPlugin->getPropertyString(
669 "description", [&](Status status, const hidl_string& value) {
670 EXPECT_EQ(Status::OK, status);
671 EXPECT_EQ("ClearKey CDM", value);
672 });
673 EXPECT_OK(res);
674 }
675
TEST_F(DrmHalClearkeyPluginTest,GetAlgorithmsProperty)676 TEST_F(DrmHalClearkeyPluginTest, GetAlgorithmsProperty) {
677 auto res = drmPlugin->getPropertyString(
678 "algorithms", [&](Status status, const hidl_string& value) {
679 EXPECT_EQ(Status::OK, status);
680 EXPECT_EQ("", value);
681 });
682 EXPECT_OK(res);
683 }
684
685 /**
686 * Test that attempting to read invalid string and byte array
687 * properties returns the documented error code.
688 */
TEST_F(DrmHalClearkeyPluginTest,GetInvalidStringProperty)689 TEST_F(DrmHalClearkeyPluginTest, GetInvalidStringProperty) {
690 auto res = drmPlugin->getPropertyString(
691 "invalid", [&](Status status, const hidl_string&) {
692 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
693 });
694 EXPECT_OK(res);
695 }
696
TEST_F(DrmHalClearkeyPluginTest,GetByteArrayPropertyNotSupported)697 TEST_F(DrmHalClearkeyPluginTest, GetByteArrayPropertyNotSupported) {
698 auto res = drmPlugin->getPropertyByteArray(
699 "deviceUniqueId", [&](Status status, const hidl_vec<uint8_t>&) {
700 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
701 });
702 EXPECT_OK(res);
703 }
704
705 /**
706 * Clearkey doesn't support setting string or byte array properties,
707 * particularly an undefined one.
708 */
TEST_F(DrmHalClearkeyPluginTest,SetStringPropertyNotSupported)709 TEST_F(DrmHalClearkeyPluginTest, SetStringPropertyNotSupported) {
710 Status status = drmPlugin->setPropertyString("property", "value");
711 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
712 }
713
TEST_F(DrmHalClearkeyPluginTest,SetByteArrayPropertyNotSupported)714 TEST_F(DrmHalClearkeyPluginTest, SetByteArrayPropertyNotSupported) {
715 hidl_vec<uint8_t> value;
716 Status status = drmPlugin->setPropertyByteArray("property", value);
717 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
718 }
719
720 /**
721 * Clearkey doesn't support setting cipher algorithms, verify it
722 */
TEST_F(DrmHalClearkeyPluginTest,SetCipherAlgorithmNotSupported)723 TEST_F(DrmHalClearkeyPluginTest, SetCipherAlgorithmNotSupported) {
724 SessionId session = openSession();
725 hidl_string algorithm = "AES/CBC/NoPadding";
726 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
727 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
728 closeSession(session);
729 }
730
731 /**
732 * Setting an empty algorithm should return BAD_VALUE
733 */
TEST_F(DrmHalClearkeyPluginTest,SetCipherEmptyAlgorithm)734 TEST_F(DrmHalClearkeyPluginTest, SetCipherEmptyAlgorithm) {
735 SessionId session = openSession();
736 hidl_string algorithm;
737 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
738 EXPECT_EQ(Status::BAD_VALUE, status);
739 closeSession(session);
740 }
741
742 /**
743 * Setting a cipher algorithm with no session returns BAD_VALUE
744 */
TEST_F(DrmHalClearkeyPluginTest,SetCipherAlgorithmNoSession)745 TEST_F(DrmHalClearkeyPluginTest, SetCipherAlgorithmNoSession) {
746 SessionId session;
747 hidl_string algorithm = "AES/CBC/NoPadding";
748 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
749 EXPECT_EQ(Status::BAD_VALUE, status);
750 }
751
752 /**
753 * Clearkey doesn't support setting mac algorithms, verify it
754 */
TEST_F(DrmHalClearkeyPluginTest,SetMacAlgorithmNotSupported)755 TEST_F(DrmHalClearkeyPluginTest, SetMacAlgorithmNotSupported) {
756 SessionId session = openSession();
757 hidl_string algorithm = "HmacSHA256";
758 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
759 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
760 closeSession(session);
761 }
762
763 /**
764 * Setting an empty algorithm should return BAD_VALUE
765 */
TEST_F(DrmHalClearkeyPluginTest,SetMacEmptyAlgorithm)766 TEST_F(DrmHalClearkeyPluginTest, SetMacEmptyAlgorithm) {
767 SessionId session = openSession();
768 hidl_string algorithm;
769 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
770 EXPECT_EQ(Status::BAD_VALUE, status);
771 closeSession(session);
772 }
773
774 /**
775 * Setting a mac algorithm with no session should return BAD_VALUE
776 */
TEST_F(DrmHalClearkeyPluginTest,SetMacAlgorithmNoSession)777 TEST_F(DrmHalClearkeyPluginTest, SetMacAlgorithmNoSession) {
778 SessionId session;
779 hidl_string algorithm = "HmacSHA256";
780 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
781 EXPECT_EQ(Status::BAD_VALUE, status);
782 }
783
784 /**
785 * The Generic* methods provide general purpose crypto operations
786 * that may be used for applications other than DRM. They leverage
787 * the hardware root of trust and secure key distribution mechanisms
788 * of a DRM system to enable app-specific crypto functionality where
789 * the crypto keys are not exposed outside of the trusted execution
790 * environment.
791 *
792 * Clearkey doesn't support generic encrypt/decrypt/sign/verify.
793 */
TEST_F(DrmHalClearkeyPluginTest,GenericEncryptNotSupported)794 TEST_F(DrmHalClearkeyPluginTest, GenericEncryptNotSupported) {
795 SessionId session = openSession();
796 ;
797 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
798 hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
799 hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
800 auto res = drmPlugin->encrypt(session, keyId, input, iv,
801 [&](Status status, const hidl_vec<uint8_t>&) {
802 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
803 status);
804 });
805 EXPECT_OK(res);
806 closeSession(session);
807 }
808
TEST_F(DrmHalClearkeyPluginTest,GenericDecryptNotSupported)809 TEST_F(DrmHalClearkeyPluginTest, GenericDecryptNotSupported) {
810 SessionId session = openSession();
811 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
812 hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
813 hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
814 auto res = drmPlugin->decrypt(session, keyId, input, iv,
815 [&](Status status, const hidl_vec<uint8_t>&) {
816 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
817 status);
818 });
819 EXPECT_OK(res);
820 closeSession(session);
821 }
822
TEST_F(DrmHalClearkeyPluginTest,GenericSignNotSupported)823 TEST_F(DrmHalClearkeyPluginTest, GenericSignNotSupported) {
824 SessionId session = openSession();
825 ;
826 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
827 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5};
828 auto res = drmPlugin->sign(session, keyId, message,
829 [&](Status status, const hidl_vec<uint8_t>&) {
830 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
831 status);
832 });
833 EXPECT_OK(res);
834 closeSession(session);
835 }
836
TEST_F(DrmHalClearkeyPluginTest,GenericVerifyNotSupported)837 TEST_F(DrmHalClearkeyPluginTest, GenericVerifyNotSupported) {
838 SessionId session = openSession();
839 ;
840 hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
841 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5};
842 hidl_vec<uint8_t> signature = {0, 0, 0, 0, 0, 0, 0, 0,
843 0, 0, 0, 0, 0, 0, 0, 0};
844 auto res = drmPlugin->verify(
845 session, keyId, message, signature, [&](Status status, bool) {
846 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
847 });
848 EXPECT_OK(res);
849 closeSession(session);
850 }
851
TEST_F(DrmHalClearkeyPluginTest,GenericSignRSANotSupported)852 TEST_F(DrmHalClearkeyPluginTest, GenericSignRSANotSupported) {
853 SessionId session = openSession();
854 hidl_string algorithm = "RSASSA-PSS-SHA1";
855 hidl_vec<uint8_t> message = {1, 2, 3, 4, 5};
856 hidl_vec<uint8_t> wrappedKey = {0, 0, 0, 0, 0, 0, 0, 0,
857 0, 0, 0, 0, 0, 0, 0, 0};
858 auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey,
859 [&](Status status, const hidl_vec<uint8_t>&) {
860 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
861 status);
862 });
863 EXPECT_OK(res);
864 closeSession(session);
865 }
866
867 /**
868 * CryptoPlugin tests
869 */
870
871 /**
872 * Clearkey doesn't support secure decoder and is expected to
873 * return false.
874 */
TEST_F(DrmHalClearkeyPluginTest,RequiresSecureDecoder)875 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoder) {
876 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("cenc"));
877 }
878
879 /**
880 * Verify that requiresSecureDecoderComponent handles empty mimetype
881 */
TEST_F(DrmHalClearkeyPluginTest,RequiresSecureDecoderEmptyMimeType)882 TEST_F(DrmHalClearkeyPluginTest, RequiresSecureDecoderEmptyMimeType) {
883 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent(""));
884 }
885
886 /**
887 * Exercise the NotifyResolution API. There is no observable result,
888 * just call the method for coverage.
889 */
TEST_F(DrmHalClearkeyPluginTest,NotifyResolution)890 TEST_F(DrmHalClearkeyPluginTest, NotifyResolution) {
891 cryptoPlugin->notifyResolution(1920, 1080);
892 }
893
894 /**
895 * getDecryptMemory allocates memory for decryption, then sets it
896 * as a shared buffer base in the crypto hal. The allocated and
897 * mapped IMemory is returned.
898 *
899 * @param size the size of the memory segment to allocate
900 * @param the index of the memory segment which will be used
901 * to refer to it for decryption.
902 */
getDecryptMemory(size_t size,size_t index)903 sp<IMemory> DrmHalClearkeyPluginTest::getDecryptMemory(size_t size,
904 size_t index) {
905 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
906 EXPECT_NE(nullptr, ashmemAllocator.get());
907
908 hidl_memory hidlMemory;
909 auto res = ashmemAllocator->allocate(
910 size, [&](bool success, const hidl_memory& memory) {
911 EXPECT_EQ(true, success);
912 EXPECT_OK(cryptoPlugin->setSharedBufferBase(memory, index));
913 hidlMemory = memory;
914 });
915 EXPECT_OK(res);
916
917 sp<IMemory> mappedMemory = mapMemory(hidlMemory);
918 EXPECT_NE(nullptr, mappedMemory.get());
919 EXPECT_OK(cryptoPlugin->setSharedBufferBase(hidlMemory, index));
920 return mappedMemory;
921 }
922
923 /**
924 * Exercise the setMediaDrmSession method. setMediaDrmSession
925 * is used to associate a drm session with a crypto session.
926 */
TEST_F(DrmHalClearkeyPluginTest,SetMediaDrmSession)927 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSession) {
928 auto sessionId = openSession();
929 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
930 EXPECT_EQ(Status::OK, status);
931 closeSession(sessionId);
932 }
933
934 /**
935 * setMediaDrmSession with a closed session id
936 */
TEST_F(DrmHalClearkeyPluginTest,SetMediaDrmSessionClosedSession)937 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionClosedSession) {
938 auto sessionId = openSession();
939 closeSession(sessionId);
940 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
941 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
942 }
943
944 /**
945 * setMediaDrmSession with an empty session id: BAD_VALUE. An
946 * empty session clears the previously set session and should
947 * return OK.
948 */
TEST_F(DrmHalClearkeyPluginTest,SetMediaDrmSessionEmptySession)949 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) {
950 SessionId sessionId;
951 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
952 EXPECT_EQ(Status::OK, status);
953 }
954
955 /**
956 * Decrypt tests
957 */
958
959 class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest {
960 public:
961 void fillRandom(const sp<IMemory>& memory);
toHidlArray(const vector<uint8_t> & vec)962 hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
963 EXPECT_EQ(16u, vec.size());
964 return hidl_array<uint8_t, 16>(&vec[0]);
965 }
966 uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples,
967 const Pattern& pattern, Status status);
968 void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
969 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
970 void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
971 const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
972 };
973
fillRandom(const sp<IMemory> & memory)974 void DrmHalClearkeyDecryptTest::fillRandom(const sp<IMemory>& memory) {
975 random_device rd;
976 mt19937 rand(rd());
977 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) {
978 auto p = static_cast<uint32_t*>(
979 static_cast<void*>(memory->getPointer()));
980 p[i] = rand();
981 }
982 }
983
decrypt(Mode mode,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const Pattern & pattern,Status expectedStatus)984 uint32_t DrmHalClearkeyDecryptTest::decrypt(Mode mode,
985 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
986 const Pattern& pattern, Status expectedStatus) {
987 const size_t kSegmentIndex = 0;
988 const vector<uint8_t> keyId = {0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47,
989 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
990 0x1e, 0xd0, 0x0d, 0x1e};
991 const vector<uint8_t> contentKey = {0x1a, 0x8a, 0x20, 0x95, 0xe4,
992 0xde, 0xb2, 0xd2, 0x9e, 0xc8,
993 0x16, 0xac, 0x7b, 0xae, 0x20, 0x82};
994 uint8_t localIv[AES_BLOCK_SIZE];
995 memcpy(localIv, iv, AES_BLOCK_SIZE);
996
997 size_t totalSize = 0;
998 for (size_t i = 0; i < subSamples.size(); i++) {
999 totalSize += subSamples[i].numBytesOfClearData;
1000 totalSize += subSamples[i].numBytesOfEncryptedData;
1001 }
1002
1003 // The first totalSize bytes of shared memory is the encrypted
1004 // input, the second totalSize bytes is the decrypted output.
1005 sp<IMemory> sharedMemory =
1006 getDecryptMemory(totalSize * 2, kSegmentIndex);
1007
1008 const SharedBuffer sourceBuffer = {
1009 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
1010 fillRandom(sharedMemory);
1011
1012 const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
1013 {.bufferId = kSegmentIndex,
1014 .offset = totalSize,
1015 .size = totalSize},
1016 .secureMemory = nullptr};
1017 const uint64_t offset = 0;
1018 const bool kNotSecure = false;
1019 uint32_t bytesWritten = 0;
1020 auto res = cryptoPlugin->decrypt(kNotSecure, toHidlArray(keyId), localIv, mode,
1021 pattern, subSamples, sourceBuffer, offset, destBuffer,
1022 [&](Status status, uint32_t count, string detailedError) {
1023 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
1024 detailedError;
1025 bytesWritten = count;
1026 });
1027 EXPECT_OK(res);
1028
1029 if (bytesWritten != totalSize) {
1030 return bytesWritten;
1031 }
1032 uint8_t* base = static_cast<uint8_t*>(
1033 static_cast<void*>(sharedMemory->getPointer()));
1034
1035 // generate reference vector
1036 vector<uint8_t> reference(totalSize);
1037
1038 memcpy(localIv, iv, AES_BLOCK_SIZE);
1039 switch (mode) {
1040 case Mode::UNENCRYPTED:
1041 memcpy(&reference[0], base, totalSize);
1042 break;
1043 case Mode::AES_CTR:
1044 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, contentKey);
1045 break;
1046 case Mode::AES_CBC:
1047 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, contentKey);
1048 break;
1049 case Mode::AES_CBC_CTS:
1050 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
1051 break;
1052 }
1053
1054 // compare reference to decrypted data which is at base + total size
1055 EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]),
1056 static_cast<void*>(base + totalSize), totalSize))
1057 << "decrypt data mismatch";
1058 return totalSize;
1059 }
1060
1061 /**
1062 * Decrypt a list of clear+encrypted subsamples using the specified key
1063 * in AES-CTR mode
1064 */
aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1065 void DrmHalClearkeyDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
1066 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1067 const vector<uint8_t>& key) {
1068 AES_KEY decryptionKey;
1069 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1070
1071 size_t offset = 0;
1072 unsigned int blockOffset = 0;
1073 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
1074 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
1075
1076 for (size_t i = 0; i < subSamples.size(); i++) {
1077 const SubSample& subSample = subSamples[i];
1078
1079 if (subSample.numBytesOfClearData > 0) {
1080 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1081 offset += subSample.numBytesOfClearData;
1082 }
1083
1084 if (subSample.numBytesOfEncryptedData > 0) {
1085 AES_ctr128_encrypt(src + offset, dest + offset,
1086 subSample.numBytesOfEncryptedData, &decryptionKey,
1087 iv, previousEncryptedCounter, &blockOffset);
1088 offset += subSample.numBytesOfEncryptedData;
1089 }
1090 }
1091 }
1092
1093 /**
1094 * Decrypt a list of clear+encrypted subsamples using the specified key
1095 * in AES-CBC mode
1096 */
aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1097 void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
1098 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1099 const vector<uint8_t>& key) {
1100 AES_KEY decryptionKey;
1101 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1102
1103 size_t offset = 0;
1104 for (size_t i = 0; i < subSamples.size(); i++) {
1105 memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
1106 offset += subSamples[i].numBytesOfClearData;
1107
1108 AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData,
1109 &decryptionKey, iv, 0 /* decrypt */);
1110 offset += subSamples[i].numBytesOfEncryptedData;
1111 }
1112 }
1113
1114 /**
1115 * Test query key status
1116 */
TEST_F(DrmHalClearkeyDecryptTest,TestQueryKeyStatus)1117 TEST_F(DrmHalClearkeyDecryptTest, TestQueryKeyStatus) {
1118 auto sessionId = openSession();
1119 auto res = drmPlugin->queryKeyStatus(
1120 sessionId, [&](Status status, KeyedVector /* info */) { EXPECT_EQ(Status::OK, status); });
1121 EXPECT_OK(res);
1122
1123 closeSession(sessionId);
1124 }
1125
1126 /**
1127 * Positive decrypt test. "Decrypt" a single clear segment
1128 */
TEST_F(DrmHalClearkeyDecryptTest,ClearSegmentTest)1129 TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
1130 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1131 const Pattern noPattern = {0, 0};
1132 const vector<SubSample> subSamples = {
1133 {.numBytesOfClearData = k256SubSampleByteCount,
1134 .numBytesOfEncryptedData = 0}};
1135 auto sessionId = openSession();
1136 loadKeys(sessionId);
1137
1138 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1139 EXPECT_EQ(Status::OK, status);
1140
1141 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
1142 noPattern, Status::OK);
1143 EXPECT_EQ(k256SubSampleByteCount, byteCount);
1144
1145 closeSession(sessionId);
1146 }
1147
1148 /**
1149 * Positive decrypt test. Decrypt a single segment using AES_CTR.
1150 * Verify data matches.
1151 */
TEST_F(DrmHalClearkeyDecryptTest,EncryptedAesCtrSegmentTest)1152 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) {
1153 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1154 const Pattern noPattern = {0, 0};
1155 const vector<SubSample> subSamples = {
1156 {.numBytesOfClearData = k512SubSampleClearBytes,
1157 .numBytesOfEncryptedData = k512SubSampleEncryptedBytes}};
1158 auto sessionId = openSession();
1159 loadKeys(sessionId);
1160
1161 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1162 EXPECT_EQ(Status::OK, status);
1163
1164 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
1165 noPattern, Status::OK);
1166 EXPECT_EQ(k512SubSampleClearBytes + k512SubSampleEncryptedBytes, byteCount);
1167
1168 closeSession(sessionId);
1169 }
1170
1171 /**
1172 * Negative decrypt test. Decrypt without loading keys.
1173 */
TEST_F(DrmHalClearkeyDecryptTest,EncryptedAesCtrSegmentTestNoKeys)1174 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
1175 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1176 const Pattern noPattern = {0, 0};
1177 const vector<SubSample> subSamples = {
1178 {.numBytesOfClearData = k256SubSampleByteCount,
1179 .numBytesOfEncryptedData = k256SubSampleByteCount}};
1180 auto sessionId = openSession();
1181
1182 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1183 EXPECT_EQ(Status::OK, status);
1184
1185 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
1186 noPattern, Status::ERROR_DRM_NO_LICENSE);
1187 EXPECT_EQ(0u, byteCount);
1188
1189 closeSession(sessionId);
1190 }
1191
1192 /**
1193 * Negative decrypt test. Decrypt with invalid key.
1194 */
TEST_F(DrmHalClearkeyDecryptTest,DecryptWithEmptyKey)1195 TEST_F(DrmHalClearkeyDecryptTest, DecryptWithEmptyKey) {
1196 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1197 const Pattern noPattern = {0, 0};
1198 const vector<SubSample> subSamples = {
1199 {.numBytesOfClearData = k512SubSampleClearBytes,
1200 .numBytesOfEncryptedData = k512SubSampleEncryptedBytes}};
1201
1202 // base 64 encoded JSON response string, must not contain padding character '='
1203 const hidl_string emptyKeyResponse =
1204 "{\"keys\":[" \
1205 "{" \
1206 "\"kty\":\"oct\"" \
1207 "\"alg\":\"A128KW2\"" \
1208 "\"k\":\"SGVsbG8gRnJpZW5kIQ\"" \
1209 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAyAy\"" \
1210 "}" \
1211 "{" \
1212 "\"kty\":\"oct\"," \
1213 "\"alg\":\"A128KW2\"" \
1214 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \
1215 // empty key follows
1216 "\"k\":\"R\"" \
1217 "}]" \
1218 "}";
1219 const size_t kEmptyKeyResponseSize = emptyKeyResponse.size();
1220
1221 hidl_vec<uint8_t> invalidResponse;
1222 invalidResponse.resize(kEmptyKeyResponseSize);
1223 memcpy(invalidResponse.data(), emptyKeyResponse.c_str(), kEmptyKeyResponseSize);
1224
1225 auto sessionId = openSession();
1226
1227 auto res = drmPlugin->provideKeyResponse(
1228 sessionId, invalidResponse,
1229 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
1230 EXPECT_EQ(Status::OK, status);
1231 EXPECT_EQ(0u, myKeySetId.size());
1232 });
1233 EXPECT_OK(res);
1234
1235 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1236 EXPECT_EQ(Status::OK, status);
1237
1238 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
1239 noPattern, Status::ERROR_DRM_NO_LICENSE);
1240 EXPECT_EQ(0u, byteCount);
1241
1242 closeSession(sessionId);
1243 }
1244
1245 /**
1246 * Negative decrypt test. Decrypt with a key exceeds AES_BLOCK_SIZE.
1247 */
TEST_F(DrmHalClearkeyDecryptTest,DecryptWithKeyTooLong)1248 TEST_F(DrmHalClearkeyDecryptTest, DecryptWithKeyTooLong) {
1249 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1250 const Pattern noPattern = {0, 0};
1251 const vector<SubSample> subSamples = {
1252 {.numBytesOfClearData = k512SubSampleClearBytes,
1253 .numBytesOfEncryptedData = k512SubSampleEncryptedBytes}};
1254
1255 // base 64 encoded JSON response string, must not contain padding character '='
1256 const hidl_string keyTooLongResponse =
1257 "{\"keys\":[" \
1258 "{" \
1259 "\"kty\":\"oct\"," \
1260 "\"alg\":\"A128KW2\"" \
1261 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \
1262 // key too long
1263 "\"k\":\"V2lubmllIHRoZSBwb29oIVdpbm5pZSB0aGUgcG9vaCE=\"" \
1264 "}]" \
1265 "}";
1266 const size_t kKeyTooLongResponseSize = keyTooLongResponse.size();
1267
1268 hidl_vec<uint8_t> invalidResponse;
1269 invalidResponse.resize(kKeyTooLongResponseSize);
1270 memcpy(invalidResponse.data(), keyTooLongResponse.c_str(), kKeyTooLongResponseSize);
1271
1272 auto sessionId = openSession();
1273
1274 auto res = drmPlugin->provideKeyResponse(
1275 sessionId, invalidResponse,
1276 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
1277 EXPECT_EQ(Status::OK, status);
1278 EXPECT_EQ(0u, myKeySetId.size());
1279 });
1280 EXPECT_OK(res);
1281
1282 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1283 EXPECT_EQ(Status::OK, status);
1284
1285 uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
1286 noPattern, Status::ERROR_DRM_NO_LICENSE);
1287 EXPECT_EQ(0u, byteCount);
1288
1289 closeSession(sessionId);
1290 }
1291