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