• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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