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