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_vendor_test@1.0"
18
19 #include <openssl/aes.h>
20 #include <random>
21
22 #include "drm_hal_vendor_module_api.h"
23 #include "vendor_modules.h"
24 #include <VtsHalHidlTargetCallbackBase.h>
25
26 #include "android/hardware/drm/1.0/vts/drm_hal_vendor_test.h"
27
28 using std::random_device;
29 using std::mt19937;
30
31 static const uint8_t kInvalidUUID[16] = {
32 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
33 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
34 };
35
__anonc14513810102null36 static drm_vts::VendorModules* gVendorModules = [] {
37 #if defined(__LP64__)
38 const char* kModulePath = "/data/local/tmp/64/lib";
39 #else
40 const char* kModulePath = "/data/local/tmp/32/lib";
41 #endif
42 auto modules = new drm_vts::VendorModules(kModulePath);
43 if (modules->getPathList().size() == 0) {
44 std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
45 ", all vendor tests will be skipped" << std::endl;
46 }
47 return modules;
48 }();
49
50 namespace android {
51 namespace hardware {
52 namespace drm {
53 namespace V1_0 {
54 namespace vts {
55
DrmHalVendorFactoryTest()56 DrmHalVendorFactoryTest::DrmHalVendorFactoryTest()
57 : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
58 gVendorModules->getModuleByName(GetParam().instance_))) {} // getModuleByName
59
TEST_P(DrmHalVendorFactoryTest,ValidateConfigurations)60 TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
61 const char* kVendorStr = "Vendor module ";
62 size_t count = 0;
63 for (const auto& config : contentConfigurations) {
64 ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
65 ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
66 << "has no serverUrl";
67 ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
68 << "has no init data";
69 ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
70 << "has no mime type";
71 ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
72 for (const auto& key : config.keys) {
73 ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
74 << " has zero length keyId";
75 ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
76 << " has zero length key value";
77 }
78 count++;
79 }
80 EXPECT_NE(0u, count);
81 }
82
83 /**
84 * Ensure the factory doesn't support an invalid scheme UUID
85 */
TEST_P(DrmHalVendorFactoryTest,InvalidPluginNotSupported)86 TEST_P(DrmHalVendorFactoryTest, InvalidPluginNotSupported) {
87 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID));
88 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID));
89 }
90
91 /**
92 * Ensure the factory doesn't support an empty UUID
93 */
TEST_P(DrmHalVendorFactoryTest,EmptyPluginUUIDNotSupported)94 TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
95 hidl_array<uint8_t, 16> emptyUUID;
96 memset(emptyUUID.data(), 0, 16);
97 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
98 EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
99 }
100
101 /**
102 * Check if the factory supports the scheme uuid in the config.
103 */
TEST_P(DrmHalVendorFactoryTest,PluginConfigUUIDSupported)104 TEST_P(DrmHalVendorFactoryTest, PluginConfigUUIDSupported) {
105 RETURN_IF_SKIPPED;
106 EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getUUID()));
107 EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getUUID()));
108 }
109
110 /**
111 * Ensure empty content type is not supported
112 */
TEST_P(DrmHalVendorFactoryTest,EmptyContentTypeNotSupported)113 TEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) {
114 hidl_string empty;
115 EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
116 }
117
118 /**
119 * Ensure invalid content type is not supported
120 */
TEST_P(DrmHalVendorFactoryTest,InvalidContentTypeNotSupported)121 TEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) {
122 hidl_string invalid("abcdabcd");
123 EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
124 }
125
126 /**
127 * Ensure valid content types in the configs are supported
128 */
TEST_P(DrmHalVendorFactoryTest,ValidContentTypeSupported)129 TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
130 RETURN_IF_SKIPPED;
131 for (const auto& config : contentConfigurations) {
132 EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
133 }
134 }
135
136 /**
137 * Ensure vendor drm plugin can be created
138 */
TEST_P(DrmHalVendorFactoryTest,CreateVendorDrmPlugin)139 TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
140 RETURN_IF_SKIPPED;
141 hidl_string packageName("android.hardware.drm.test");
142 auto res = drmFactory->createPlugin(
143 getUUID(), packageName,
144 [&](Status status, const sp<IDrmPlugin>& plugin) {
145 EXPECT_EQ(Status::OK, status);
146 EXPECT_NE(nullptr, plugin.get());
147 });
148 EXPECT_OK(res);
149 }
150
151 /**
152 * Ensure vendor crypto plugin can be created
153 */
TEST_P(DrmHalVendorFactoryTest,CreateVendorCryptoPlugin)154 TEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) {
155 RETURN_IF_SKIPPED;
156 hidl_vec<uint8_t> initVec;
157 auto res = cryptoFactory->createPlugin(
158 getUUID(), initVec,
159 [&](Status status, const sp<ICryptoPlugin>& plugin) {
160 EXPECT_EQ(Status::OK, status);
161 EXPECT_NE(nullptr, plugin.get());
162 });
163 EXPECT_OK(res);
164 }
165
166 /**
167 * Ensure invalid drm plugin can't be created
168 */
TEST_P(DrmHalVendorFactoryTest,CreateInvalidDrmPlugin)169 TEST_P(DrmHalVendorFactoryTest, CreateInvalidDrmPlugin) {
170 RETURN_IF_SKIPPED;
171 hidl_string packageName("android.hardware.drm.test");
172 auto res = drmFactory->createPlugin(
173 kInvalidUUID, packageName,
174 [&](Status status, const sp<IDrmPlugin>& plugin) {
175 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
176 EXPECT_EQ(nullptr, plugin.get());
177 });
178 EXPECT_OK(res);
179 }
180
181 /**
182 * Ensure invalid crypto plugin can't be created
183 */
TEST_P(DrmHalVendorFactoryTest,CreateInvalidCryptoPlugin)184 TEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) {
185 RETURN_IF_SKIPPED;
186 hidl_vec<uint8_t> initVec;
187 auto res = cryptoFactory->createPlugin(
188 kInvalidUUID, initVec,
189 [&](Status status, const sp<ICryptoPlugin>& plugin) {
190 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
191 EXPECT_EQ(nullptr, plugin.get());
192 });
193 EXPECT_OK(res);
194 }
195
196 /**
197 * DrmPlugin tests
198 */
199
200 /**
201 * Test that a DRM plugin can handle provisioning. While
202 * it is not required that a DRM scheme require provisioning,
203 * it should at least return appropriate status values. If
204 * a provisioning request is returned, it is passed to the
205 * vendor module which should provide a provisioning response
206 * that is delivered back to the HAL.
207 */
208
TEST_P(DrmHalVendorPluginTest,DoProvisioning)209 TEST_P(DrmHalVendorPluginTest, DoProvisioning) {
210 RETURN_IF_SKIPPED;
211 hidl_string certificateType;
212 hidl_string certificateAuthority;
213 hidl_vec<uint8_t> provisionRequest;
214 hidl_string defaultUrl;
215 auto res = drmPlugin->getProvisionRequest(
216 certificateType, certificateAuthority,
217 [&](Status status, const hidl_vec<uint8_t>& request,
218 const hidl_string& url) {
219 if (status == Status::OK) {
220 EXPECT_NE(request.size(), 0u);
221 provisionRequest = request;
222 defaultUrl = url;
223 } else if (status == Status::ERROR_DRM_CANNOT_HANDLE) {
224 EXPECT_EQ(0u, request.size());
225 }
226 });
227 EXPECT_OK(res);
228
229 if (provisionRequest.size() > 0) {
230 vector<uint8_t> response = vendorModule->handleProvisioningRequest(
231 provisionRequest, defaultUrl);
232 ASSERT_NE(0u, response.size());
233
234 auto res = drmPlugin->provideProvisionResponse(
235 response, [&](Status status, const hidl_vec<uint8_t>&,
236 const hidl_vec<uint8_t>&) {
237 EXPECT_EQ(Status::OK, status);
238 });
239 EXPECT_OK(res);
240 }
241 }
242
243 /**
244 * The DRM HAL should return BAD_VALUE if an empty provisioning
245 * response is provided.
246 */
TEST_P(DrmHalVendorPluginTest,ProvideEmptyProvisionResponse)247 TEST_P(DrmHalVendorPluginTest, ProvideEmptyProvisionResponse) {
248 RETURN_IF_SKIPPED;
249 hidl_vec<uint8_t> response;
250 auto res = drmPlugin->provideProvisionResponse(
251 response, [&](Status status, const hidl_vec<uint8_t>&,
252 const hidl_vec<uint8_t>&) {
253 EXPECT_EQ(Status::BAD_VALUE, status);
254 });
255 EXPECT_OK(res);
256 }
257
258 /**
259 * Helper method to open a session and verify that a non-empty
260 * session ID is returned
261 */
openSession()262 SessionId DrmHalVendorPluginTest::openSession() {
263 SessionId sessionId;
264
265 auto res = drmPlugin->openSession([&](Status status, const SessionId& id) {
266 EXPECT_EQ(Status::OK, status);
267 EXPECT_NE(id.size(), 0u);
268 sessionId = id;
269 });
270 EXPECT_OK(res);
271 return sessionId;
272 }
273
274 /**
275 * Helper method to close a session
276 */
closeSession(const SessionId & sessionId)277 void DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) {
278 Status status = drmPlugin->closeSession(sessionId);
279 EXPECT_EQ(Status::OK, status);
280 }
281
toHidlKeyedVector(const map<string,string> & params)282 KeyedVector DrmHalVendorPluginTest::toHidlKeyedVector(
283 const map<string, string>& params) {
284 std::vector<KeyValue> stdKeyedVector;
285 for (auto it = params.begin(); it != params.end(); ++it) {
286 KeyValue keyValue;
287 keyValue.key = it->first;
288 keyValue.value = it->second;
289 stdKeyedVector.push_back(keyValue);
290 }
291 return KeyedVector(stdKeyedVector);
292 }
293
294 /**
295 * Helper method to load keys for subsequent decrypt tests.
296 * These tests use predetermined key request/response to
297 * avoid requiring a round trip to a license server.
298 */
loadKeys(const SessionId & sessionId,const ContentConfiguration & configuration,const KeyType & type=KeyType::STREAMING)299 hidl_vec<uint8_t> DrmHalVendorPluginTest::loadKeys(
300 const SessionId& sessionId, const ContentConfiguration& configuration,
301 const KeyType& type = KeyType::STREAMING) {
302 hidl_vec<uint8_t> keyRequest;
303 auto res = drmPlugin->getKeyRequest(
304 sessionId, configuration.initData, configuration.mimeType, type,
305 toHidlKeyedVector(configuration.optionalParameters),
306 [&](Status status, const hidl_vec<uint8_t>& request,
307 KeyRequestType type, const hidl_string&) {
308 EXPECT_EQ(Status::OK, status) << "Failed to get "
309 "key request for configuration "
310 << configuration.name;
311 EXPECT_EQ(type, KeyRequestType::INITIAL);
312 EXPECT_NE(request.size(), 0u) << "Expected key request size"
313 " to have length > 0 bytes";
314 keyRequest = request;
315 });
316 EXPECT_OK(res);
317
318 /**
319 * Get key response from vendor module
320 */
321 hidl_vec<uint8_t> keyResponse =
322 vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
323
324 EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
325 "to have length > 0 bytes";
326
327 hidl_vec<uint8_t> keySetId;
328 res = drmPlugin->provideKeyResponse(
329 sessionId, keyResponse,
330 [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
331 EXPECT_EQ(Status::OK, status) << "Failure providing "
332 "key response for configuration "
333 << configuration.name;
334 keySetId = myKeySetId;
335 });
336 EXPECT_OK(res);
337 return keySetId;
338 }
339
340 /**
341 * Test that a session can be opened and closed
342 */
TEST_P(DrmHalVendorPluginTest,OpenCloseSession)343 TEST_P(DrmHalVendorPluginTest, OpenCloseSession) {
344 RETURN_IF_SKIPPED;
345 auto sessionId = openSession();
346 closeSession(sessionId);
347 }
348
349 /**
350 * Test that attempting to close an invalid (empty) sessionId
351 * is prohibited with the documented error code.
352 */
TEST_P(DrmHalVendorPluginTest,CloseInvalidSession)353 TEST_P(DrmHalVendorPluginTest, CloseInvalidSession) {
354 RETURN_IF_SKIPPED;
355 SessionId invalidSessionId;
356 Status status = drmPlugin->closeSession(invalidSessionId);
357 EXPECT_EQ(Status::BAD_VALUE, status);
358 }
359
360 /**
361 * Test that attempting to close a valid session twice
362 * is prohibited with the documented error code.
363 */
TEST_P(DrmHalVendorPluginTest,CloseClosedSession)364 TEST_P(DrmHalVendorPluginTest, CloseClosedSession) {
365 RETURN_IF_SKIPPED;
366 auto sessionId = openSession();
367 closeSession(sessionId);
368 Status status = drmPlugin->closeSession(sessionId);
369 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
370 }
371
372 /**
373 * A get key request should fail if no sessionId is provided
374 */
TEST_P(DrmHalVendorPluginTest,GetKeyRequestNoSession)375 TEST_P(DrmHalVendorPluginTest, GetKeyRequestNoSession) {
376 RETURN_IF_SKIPPED;
377 SessionId invalidSessionId;
378 hidl_vec<uint8_t> initData;
379 hidl_string mimeType = "video/mp4";
380 KeyedVector optionalParameters;
381 auto res = drmPlugin->getKeyRequest(
382 invalidSessionId, initData, mimeType, KeyType::STREAMING,
383 optionalParameters,
384 [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
385 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
386 EXPECT_OK(res);
387 }
388
389 /**
390 * Test that an empty sessionID returns BAD_VALUE
391 */
TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptySessionId)392 TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptySessionId) {
393 RETURN_IF_SKIPPED;
394 SessionId session;
395
396 hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65,
397 0x79, 0x73, 0x22, 0x3a};
398 auto res = drmPlugin->provideKeyResponse(
399 session, keyResponse,
400 [&](Status status, const hidl_vec<uint8_t>& keySetId) {
401 EXPECT_EQ(Status::BAD_VALUE, status);
402 EXPECT_EQ(keySetId.size(), 0u);
403 });
404 EXPECT_OK(res);
405 }
406
407 /**
408 * Test that an empty key response returns BAD_VALUE
409 */
TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptyResponse)410 TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptyResponse) {
411 RETURN_IF_SKIPPED;
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(keySetId.size(), 0u);
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(DrmHalVendorPluginTest,RemoveKeysEmptySessionId)427 TEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) {
428 RETURN_IF_SKIPPED;
429 SessionId sessionId;
430 Status status = drmPlugin->removeKeys(sessionId);
431 EXPECT_TRUE(status == Status::BAD_VALUE);
432 }
433
434 /**
435 * Test that remove keys returns okay on an initialized session
436 * that has no keys.
437 */
TEST_P(DrmHalVendorPluginTest,RemoveKeysNewSession)438 TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
439 RETURN_IF_SKIPPED;
440 SessionId sessionId = openSession();
441 Status status = drmPlugin->removeKeys(sessionId);
442 EXPECT_TRUE(status == Status::OK);
443 closeSession(sessionId);
444 }
445
446 /**
447 * Test that keys are successfully restored to a new session
448 * for all content having a policy that allows offline use.
449 */
TEST_P(DrmHalVendorPluginTest,RestoreKeys)450 TEST_P(DrmHalVendorPluginTest, RestoreKeys) {
451 RETURN_IF_SKIPPED;
452 for (const auto& config : contentConfigurations) {
453 if (config.policy.allowOffline) {
454 auto sessionId = openSession();
455 hidl_vec<uint8_t> keySetId =
456 loadKeys(sessionId, config, KeyType::OFFLINE);
457 closeSession(sessionId);
458 sessionId = openSession();
459 EXPECT_NE(0u, keySetId.size());
460 Status status = drmPlugin->restoreKeys(sessionId, keySetId);
461 EXPECT_EQ(Status::OK, status);
462 closeSession(sessionId);
463 }
464 }
465 }
466
467 /**
468 * Test that restoreKeys fails with a null key set ID.
469 * Error message is expected to be Status::BAD_VALUE.
470 */
TEST_P(DrmHalVendorPluginTest,RestoreKeysNull)471 TEST_P(DrmHalVendorPluginTest, RestoreKeysNull) {
472 RETURN_IF_SKIPPED;
473 SessionId sessionId = openSession();
474 hidl_vec<uint8_t> nullKeySetId;
475 Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId);
476 EXPECT_EQ(Status::BAD_VALUE, status);
477 closeSession(sessionId);
478 }
479
480 /**
481 * Test that restoreKeys fails to restore keys to a closed
482 * session. Error message is expected to be
483 * Status::ERROR_DRM_SESSION_NOT_OPENED.
484 */
TEST_P(DrmHalVendorPluginTest,RestoreKeysClosedSession)485 TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) {
486 RETURN_IF_SKIPPED;
487 for (const auto& config : contentConfigurations) {
488 if (config.policy.allowOffline) {
489 auto sessionId = openSession();
490 hidl_vec<uint8_t> keySetId =
491 loadKeys(sessionId, config, KeyType::OFFLINE);
492 EXPECT_NE(0u, keySetId.size());
493 closeSession(sessionId);
494 sessionId = openSession();
495 closeSession(sessionId);
496 Status status = drmPlugin->restoreKeys(sessionId, keySetId);
497 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
498 }
499 }
500 }
501
502 /**
503 * Test that the plugin either doesn't support getting
504 * secure stops, or has no secure stops available after
505 * clearing them.
506 */
TEST_P(DrmHalVendorPluginTest,GetSecureStops)507 TEST_P(DrmHalVendorPluginTest, GetSecureStops) {
508 RETURN_IF_SKIPPED;
509 // There may be secure stops, depending on if there were keys
510 // loaded and unloaded previously. Clear them to get to a known
511 // state, then make sure there are none.
512 auto res = drmPlugin->getSecureStops(
513 [&](Status status, const hidl_vec<SecureStop>&) {
514 if (status != Status::OK) {
515 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
516 }
517 });
518 EXPECT_OK(res);
519
520 res = drmPlugin->getSecureStops(
521 [&](Status status, const hidl_vec<SecureStop>& secureStops) {
522 if (status == Status::OK) {
523 EXPECT_EQ(secureStops.size(), 0u);
524 } else {
525 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
526 }
527 });
528 EXPECT_OK(res);
529 }
530
531 /**
532 * Test that the clearkey plugin returns BAD_VALUE if
533 * an empty ssid is provided.
534 */
TEST_P(DrmHalVendorPluginTest,GetSecureStopEmptySSID)535 TEST_P(DrmHalVendorPluginTest, GetSecureStopEmptySSID) {
536 RETURN_IF_SKIPPED;
537 SecureStopId ssid;
538 auto res = drmPlugin->getSecureStop(
539 ssid, [&](Status status, const SecureStop&) {
540 EXPECT_EQ(Status::BAD_VALUE, status);
541 });
542 EXPECT_OK(res);
543 }
544
545 /**
546 * Test that releasing all secure stops either isn't supported
547 * or is completed successfully
548 */
TEST_P(DrmHalVendorPluginTest,ReleaseAllSecureStops)549 TEST_P(DrmHalVendorPluginTest, ReleaseAllSecureStops) {
550 RETURN_IF_SKIPPED;
551 Status status = drmPlugin->releaseAllSecureStops();
552 EXPECT_TRUE(status == Status::OK ||
553 status == Status::ERROR_DRM_CANNOT_HANDLE);
554 }
555
556 /**
557 * Releasing a secure stop without first getting one and sending it to the
558 * server to get a valid SSID should return ERROR_DRM_INVALID_STATE.
559 * This is an optional API so it can also return CANNOT_HANDLE.
560 */
TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopSequenceError)561 TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopSequenceError) {
562 RETURN_IF_SKIPPED;
563 SecureStopId ssid = {1, 2, 3, 4};
564 Status status = drmPlugin->releaseSecureStop(ssid);
565 EXPECT_TRUE(status == Status::ERROR_DRM_INVALID_STATE ||
566 status == Status::ERROR_DRM_CANNOT_HANDLE);
567 }
568
569 /**
570 * Test that releasing a specific secure stop with an empty ssid
571 * return BAD_VALUE. This is an optional API so it can also return
572 * CANNOT_HANDLE.
573 */
TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopEmptySSID)574 TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopEmptySSID) {
575 RETURN_IF_SKIPPED;
576 SecureStopId ssid;
577 Status status = drmPlugin->releaseSecureStop(ssid);
578 EXPECT_TRUE(status == Status::BAD_VALUE ||
579 status == Status::ERROR_DRM_CANNOT_HANDLE);
580 }
581
582 /**
583 * The following five tests verify that the properties
584 * defined in the MediaDrm API are supported by
585 * the plugin.
586 */
TEST_P(DrmHalVendorPluginTest,GetVendorProperty)587 TEST_P(DrmHalVendorPluginTest, GetVendorProperty) {
588 RETURN_IF_SKIPPED;
589 auto res = drmPlugin->getPropertyString(
590 "vendor", [&](Status status, const hidl_string& value) {
591 EXPECT_EQ(Status::OK, status);
592 EXPECT_NE(value.size(), 0u);
593 });
594 EXPECT_OK(res);
595 }
596
TEST_P(DrmHalVendorPluginTest,GetVersionProperty)597 TEST_P(DrmHalVendorPluginTest, GetVersionProperty) {
598 RETURN_IF_SKIPPED;
599 auto res = drmPlugin->getPropertyString(
600 "version", [&](Status status, const hidl_string& value) {
601 EXPECT_EQ(Status::OK, status);
602 EXPECT_NE(value.size(), 0u);
603 });
604 EXPECT_OK(res);
605 }
606
TEST_P(DrmHalVendorPluginTest,GetDescriptionProperty)607 TEST_P(DrmHalVendorPluginTest, GetDescriptionProperty) {
608 RETURN_IF_SKIPPED;
609 auto res = drmPlugin->getPropertyString(
610 "description", [&](Status status, const hidl_string& value) {
611 EXPECT_EQ(Status::OK, status);
612 EXPECT_NE(value.size(), 0u);
613 });
614 EXPECT_OK(res);
615 }
616
TEST_P(DrmHalVendorPluginTest,GetAlgorithmsProperty)617 TEST_P(DrmHalVendorPluginTest, GetAlgorithmsProperty) {
618 RETURN_IF_SKIPPED;
619 auto res = drmPlugin->getPropertyString(
620 "algorithms", [&](Status status, const hidl_string& value) {
621 if (status == Status::OK) {
622 EXPECT_NE(value.size(), 0u);
623 } else {
624 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
625 }
626 });
627 EXPECT_OK(res);
628 }
629
TEST_P(DrmHalVendorPluginTest,GetPropertyUniqueDeviceID)630 TEST_P(DrmHalVendorPluginTest, GetPropertyUniqueDeviceID) {
631 RETURN_IF_SKIPPED;
632 auto res = drmPlugin->getPropertyByteArray(
633 "deviceUniqueId",
634 [&](Status status, const hidl_vec<uint8_t>& value) {
635 if (status == Status::OK) {
636 EXPECT_NE(value.size(), 0u);
637 } else {
638 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
639 }
640 });
641 EXPECT_OK(res);
642 }
643
644 /**
645 * Test that attempting to read invalid string and byte array
646 * properties returns the documented error code.
647 */
TEST_P(DrmHalVendorPluginTest,GetInvalidStringProperty)648 TEST_P(DrmHalVendorPluginTest, GetInvalidStringProperty) {
649 RETURN_IF_SKIPPED;
650 auto res = drmPlugin->getPropertyString(
651 "invalid", [&](Status status, const hidl_string&) {
652 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
653 });
654 EXPECT_OK(res);
655 }
656
TEST_P(DrmHalVendorPluginTest,GetInvalidByteArrayProperty)657 TEST_P(DrmHalVendorPluginTest, GetInvalidByteArrayProperty) {
658 RETURN_IF_SKIPPED;
659 auto res = drmPlugin->getPropertyByteArray(
660 "invalid", [&](Status status, const hidl_vec<uint8_t>&) {
661 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
662 });
663 EXPECT_OK(res);
664 }
665
666 /**
667 * Test that setting invalid string and byte array properties returns
668 * the expected status value.
669 */
TEST_P(DrmHalVendorPluginTest,SetStringPropertyNotSupported)670 TEST_P(DrmHalVendorPluginTest, SetStringPropertyNotSupported) {
671 RETURN_IF_SKIPPED;
672 EXPECT_EQ(drmPlugin->setPropertyString("awefijaeflijwef", "value"),
673 Status::ERROR_DRM_CANNOT_HANDLE);
674 }
675
TEST_P(DrmHalVendorPluginTest,SetByteArrayPropertyNotSupported)676 TEST_P(DrmHalVendorPluginTest, SetByteArrayPropertyNotSupported) {
677 RETURN_IF_SKIPPED;
678 hidl_vec<uint8_t> value;
679 EXPECT_EQ(drmPlugin->setPropertyByteArray("awefijaeflijwef", value),
680 Status::ERROR_DRM_CANNOT_HANDLE);
681 }
682
683 /**
684 * Test that setting an invalid cipher algorithm returns
685 * the expected status value.
686 */
TEST_P(DrmHalVendorPluginTest,SetCipherInvalidAlgorithm)687 TEST_P(DrmHalVendorPluginTest, SetCipherInvalidAlgorithm) {
688 RETURN_IF_SKIPPED;
689 SessionId session = openSession();
690 hidl_string algorithm;
691 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
692 EXPECT_EQ(Status::BAD_VALUE, status);
693 closeSession(session);
694 }
695
696 /**
697 * Test that setting a cipher algorithm with no session returns
698 * the expected status value.
699 */
TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithmNoSession)700 TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithmNoSession) {
701 RETURN_IF_SKIPPED;
702 SessionId session;
703 hidl_string algorithm = "AES/CBC/NoPadding";
704 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
705 EXPECT_EQ(Status::BAD_VALUE, status);
706 }
707
708 /**
709 * Test that setting a valid cipher algorithm returns
710 * the expected status value. It is not required that all
711 * vendor modules support this algorithm, but they must
712 * either accept it or return ERROR_DRM_CANNOT_HANDLE
713 */
TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithm)714 TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithm) {
715 RETURN_IF_SKIPPED;
716 SessionId session = openSession();
717 ;
718 hidl_string algorithm = "AES/CBC/NoPadding";
719 Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
720 EXPECT_TRUE(status == Status::OK ||
721 status == Status::ERROR_DRM_CANNOT_HANDLE);
722 closeSession(session);
723 }
724
725 /**
726 * Test that setting an invalid mac algorithm returns
727 * the expected status value.
728 */
TEST_P(DrmHalVendorPluginTest,SetMacInvalidAlgorithm)729 TEST_P(DrmHalVendorPluginTest, SetMacInvalidAlgorithm) {
730 RETURN_IF_SKIPPED;
731 SessionId session = openSession();
732 hidl_string algorithm;
733 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
734 EXPECT_EQ(Status::BAD_VALUE, status);
735 closeSession(session);
736 }
737
738 /**
739 * Test that setting a mac algorithm with no session returns
740 * the expected status value.
741 */
TEST_P(DrmHalVendorPluginTest,SetMacNullAlgorithmNoSession)742 TEST_P(DrmHalVendorPluginTest, SetMacNullAlgorithmNoSession) {
743 RETURN_IF_SKIPPED;
744 SessionId session;
745 hidl_string algorithm = "HmacSHA256";
746 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
747 EXPECT_EQ(Status::BAD_VALUE, status);
748 }
749
750 /**
751 * Test that setting a valid mac algorithm returns
752 * the expected status value. It is not required that all
753 * vendor modules support this algorithm, but they must
754 * either accept it or return ERROR_DRM_CANNOT_HANDLE
755 */
TEST_P(DrmHalVendorPluginTest,SetMacAlgorithm)756 TEST_P(DrmHalVendorPluginTest, SetMacAlgorithm) {
757 RETURN_IF_SKIPPED;
758 SessionId session = openSession();
759 hidl_string algorithm = "HmacSHA256";
760 Status status = drmPlugin->setMacAlgorithm(session, algorithm);
761 EXPECT_TRUE(status == Status::OK ||
762 status == Status::ERROR_DRM_CANNOT_HANDLE);
763 closeSession(session);
764 }
765
766 /**
767 * The Generic* methods provide general purpose crypto operations
768 * that may be used for applications other than DRM. They leverage
769 * the hardware root of trust and secure key distribution mechanisms
770 * of a DRM system to enable app-specific crypto functionality where
771 * the crypto keys are not exposed outside of the trusted execution
772 * environment.
773 *
774 * Generic encrypt/decrypt/sign/verify should fail on invalid
775 * inputs, e.g. empty sessionId
776 */
TEST_P(DrmHalVendorPluginTest,GenericEncryptNoSession)777 TEST_P(DrmHalVendorPluginTest, GenericEncryptNoSession) {
778 RETURN_IF_SKIPPED;
779 SessionId session;
780 hidl_vec<uint8_t> keyId, input, iv;
781 auto res = drmPlugin->encrypt(
782 session, keyId, input, iv,
783 [&](Status status, const hidl_vec<uint8_t>&) {
784 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
785 });
786 EXPECT_OK(res);
787 }
788
TEST_P(DrmHalVendorPluginTest,GenericDecryptNoSession)789 TEST_P(DrmHalVendorPluginTest, GenericDecryptNoSession) {
790 RETURN_IF_SKIPPED;
791 SessionId session;
792 hidl_vec<uint8_t> keyId, input, iv;
793 auto res = drmPlugin->decrypt(
794 session, keyId, input, iv,
795 [&](Status status, const hidl_vec<uint8_t>&) {
796 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
797 });
798 EXPECT_OK(res);
799 }
800
TEST_P(DrmHalVendorPluginTest,GenericSignNoSession)801 TEST_P(DrmHalVendorPluginTest, GenericSignNoSession) {
802 RETURN_IF_SKIPPED;
803 SessionId session;
804 hidl_vec<uint8_t> keyId, message;
805 auto res = drmPlugin->sign(
806 session, keyId, message,
807 [&](Status status, const hidl_vec<uint8_t>&) {
808 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
809 });
810 EXPECT_OK(res);
811 }
812
TEST_P(DrmHalVendorPluginTest,GenericVerifyNoSession)813 TEST_P(DrmHalVendorPluginTest, GenericVerifyNoSession) {
814 RETURN_IF_SKIPPED;
815 SessionId session;
816 hidl_vec<uint8_t> keyId, message, signature;
817 auto res = drmPlugin->verify(
818 session, keyId, message, signature, [&](Status status, bool) {
819 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
820 });
821 EXPECT_OK(res);
822 }
823
TEST_P(DrmHalVendorPluginTest,GenericSignRSANoSession)824 TEST_P(DrmHalVendorPluginTest, GenericSignRSANoSession) {
825 RETURN_IF_SKIPPED;
826 SessionId session;
827 hidl_string algorithm;
828 hidl_vec<uint8_t> message, wrappedKey;
829 auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey,
830 [&](Status status, const hidl_vec<uint8_t>&) {
831 EXPECT_EQ(Status::BAD_VALUE, status);
832 });
833 EXPECT_OK(res);
834 }
835
836 /**
837 * Exercise the requiresSecureDecoderComponent method. Additional tests
838 * will verify positive cases with specific vendor content configurations.
839 * Below we just test the negative cases.
840 */
841
842 /**
843 * Verify that requiresSecureDecoderComponent handles empty mimetype.
844 */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderEmptyMimeType)845 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderEmptyMimeType) {
846 RETURN_IF_SKIPPED;
847 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent(""));
848 }
849
850 /**
851 * Verify that requiresSecureDecoderComponent handles invalid mimetype.
852 */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderInvalidMimeType)853 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) {
854 RETURN_IF_SKIPPED;
855 EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("bad"));
856 }
857
858 /**
859 * Verify that requiresSecureDecoderComponent returns true for secure
860 * configurations
861 */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderConfig)862 TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
863 RETURN_IF_SKIPPED;
864 for (const auto& config : contentConfigurations) {
865 for (const auto& key : config.keys) {
866 if (key.isSecure) {
867 EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
868 break;
869 }
870 }
871 }
872 }
873
874 /**
875 * Event Handling tests
876 */
877 struct ListenerEventArgs {
878 EventType eventType;
879 SessionId sessionId;
880 hidl_vec<uint8_t> data;
881 int64_t expiryTimeInMS;
882 hidl_vec<KeyStatus> keyStatusList;
883 bool hasNewUsableKey;
884 };
885
886 const char *kCallbackEvent = "SendEvent";
887 const char *kCallbackExpirationUpdate = "SendExpirationUpdate";
888 const char *kCallbackKeysChange = "SendKeysChange";
889
890 class TestDrmPluginListener
891 : public ::testing::VtsHalHidlTargetCallbackBase<ListenerEventArgs>,
892 public IDrmPluginListener {
893 public:
TestDrmPluginListener()894 TestDrmPluginListener() {
895 SetWaitTimeoutDefault(std::chrono::milliseconds(500));
896 }
~TestDrmPluginListener()897 virtual ~TestDrmPluginListener() {}
898
sendEvent(EventType eventType,const hidl_vec<uint8_t> & sessionId,const hidl_vec<uint8_t> & data)899 virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
900 const hidl_vec<uint8_t>& data) override {
901 ListenerEventArgs args;
902 args.eventType = eventType;
903 args.sessionId = sessionId;
904 args.data = data;
905 NotifyFromCallback(kCallbackEvent, args);
906 return Void();
907 }
908
sendExpirationUpdate(const hidl_vec<uint8_t> & sessionId,int64_t expiryTimeInMS)909 virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
910 int64_t expiryTimeInMS) override {
911 ListenerEventArgs args;
912 args.sessionId = sessionId;
913 args.expiryTimeInMS = expiryTimeInMS;
914 NotifyFromCallback(kCallbackExpirationUpdate, args);
915 return Void();
916 }
917
sendKeysChange(const hidl_vec<uint8_t> & sessionId,const hidl_vec<KeyStatus> & keyStatusList,bool hasNewUsableKey)918 virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
919 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override {
920 ListenerEventArgs args;
921 args.sessionId = sessionId;
922 args.keyStatusList = keyStatusList;
923 args.hasNewUsableKey = hasNewUsableKey;
924 NotifyFromCallback(kCallbackKeysChange, args);
925 return Void();
926 }
927 };
928
929
930 /**
931 * Simulate the plugin sending events. Make sure the listener
932 * gets them.
933 */
TEST_P(DrmHalVendorPluginTest,ListenerEvents)934 TEST_P(DrmHalVendorPluginTest, ListenerEvents) {
935 RETURN_IF_SKIPPED;
936 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
937 drmPlugin->setListener(listener);
938 auto sessionId = openSession();
939 hidl_vec<uint8_t> data = {0, 1, 2};
940 EventType eventTypes[] = {EventType::PROVISION_REQUIRED,
941 EventType::KEY_NEEDED,
942 EventType::KEY_EXPIRED,
943 EventType::VENDOR_DEFINED,
944 EventType::SESSION_RECLAIMED};
945 for (auto eventType : eventTypes) {
946 drmPlugin->sendEvent(eventType, sessionId, data);
947 auto result = listener->WaitForCallback(kCallbackEvent);
948 EXPECT_TRUE(result.no_timeout);
949 EXPECT_TRUE(result.args);
950 EXPECT_EQ(eventType, result.args->eventType);
951 EXPECT_EQ(sessionId, result.args->sessionId);
952 EXPECT_EQ(data, result.args->data);
953 }
954 closeSession(sessionId);
955 }
956
957 /**
958 * Simulate the plugin sending expiration updates and make sure
959 * the listener gets them.
960 */
TEST_P(DrmHalVendorPluginTest,ListenerExpirationUpdate)961 TEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) {
962 RETURN_IF_SKIPPED;
963 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
964 drmPlugin->setListener(listener);
965 auto sessionId = openSession();
966 drmPlugin->sendExpirationUpdate(sessionId, 100);
967 auto result = listener->WaitForCallback(kCallbackExpirationUpdate);
968 EXPECT_TRUE(result.no_timeout);
969 EXPECT_TRUE(result.args);
970 EXPECT_EQ(sessionId, result.args->sessionId);
971 EXPECT_EQ(100, result.args->expiryTimeInMS);
972 closeSession(sessionId);
973 }
974
975 /**
976 * Simulate the plugin sending keys change and make sure
977 * the listener gets them.
978 */
TEST_P(DrmHalVendorPluginTest,ListenerKeysChange)979 TEST_P(DrmHalVendorPluginTest, ListenerKeysChange) {
980 RETURN_IF_SKIPPED;
981 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
982 drmPlugin->setListener(listener);
983 auto sessionId = openSession();
984 const hidl_vec<KeyStatus> keyStatusList = {
985 {{1}, KeyStatusType::USABLE},
986 {{2}, KeyStatusType::EXPIRED},
987 {{3}, KeyStatusType::OUTPUTNOTALLOWED},
988 {{4}, KeyStatusType::STATUSPENDING},
989 {{5}, KeyStatusType::INTERNALERROR},
990 };
991
992 drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
993 auto result = listener->WaitForCallback(kCallbackKeysChange);
994 EXPECT_TRUE(result.no_timeout);
995 EXPECT_TRUE(result.args);
996 EXPECT_EQ(sessionId, result.args->sessionId);
997 EXPECT_EQ(keyStatusList, result.args->keyStatusList);
998 closeSession(sessionId);
999 }
1000
1001 /**
1002 * Negative listener tests. Call send methods with no
1003 * listener set.
1004 */
TEST_P(DrmHalVendorPluginTest,NotListening)1005 TEST_P(DrmHalVendorPluginTest, NotListening) {
1006 RETURN_IF_SKIPPED;
1007 sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
1008 drmPlugin->setListener(listener);
1009 drmPlugin->setListener(nullptr);
1010
1011 SessionId sessionId;
1012 hidl_vec<uint8_t> data;
1013 hidl_vec<KeyStatus> keyStatusList;
1014 drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data);
1015 drmPlugin->sendExpirationUpdate(sessionId, 100);
1016 drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
1017 auto result = listener->WaitForCallbackAny(
1018 {kCallbackEvent, kCallbackExpirationUpdate, kCallbackKeysChange});
1019 EXPECT_FALSE(result.no_timeout);
1020 }
1021
1022
1023 /**
1024 * CryptoPlugin tests
1025 */
1026
1027 /**
1028 * Exercise the NotifyResolution API. There is no observable result,
1029 * just call the method for coverage.
1030 */
TEST_P(DrmHalVendorPluginTest,NotifyResolution)1031 TEST_P(DrmHalVendorPluginTest, NotifyResolution) {
1032 RETURN_IF_SKIPPED;
1033 cryptoPlugin->notifyResolution(1920, 1080);
1034 }
1035
1036 /**
1037 * getDecryptMemory allocates memory for decryption, then sets it
1038 * as a shared buffer base in the crypto hal. The allocated and
1039 * mapped IMemory is returned.
1040 *
1041 * @param size the size of the memory segment to allocate
1042 * @param the index of the memory segment which will be used
1043 * to refer to it for decryption.
1044 */
getDecryptMemory(size_t size,size_t index)1045 sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
1046 size_t index) {
1047 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
1048 EXPECT_NE(nullptr, ashmemAllocator.get());
1049
1050 hidl_memory hidlMemory;
1051 auto res = ashmemAllocator->allocate(
1052 size, [&](bool success, const hidl_memory& memory) {
1053 EXPECT_EQ(success, true);
1054 EXPECT_EQ(memory.size(), size);
1055 hidlMemory = memory;
1056 });
1057
1058 EXPECT_OK(res);
1059
1060 sp<IMemory> mappedMemory = android::hardware::mapMemory(hidlMemory);
1061 EXPECT_NE(nullptr, mappedMemory.get());
1062 res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
1063 EXPECT_OK(res);
1064 return mappedMemory;
1065 }
1066
1067 /**
1068 * Exercise the setMediaDrmSession method. setMediaDrmSession
1069 * is used to associate a drm session with a crypto session.
1070 */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSession)1071 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSession) {
1072 RETURN_IF_SKIPPED;
1073 auto sessionId = openSession();
1074 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1075 EXPECT_EQ(Status::OK, status);
1076 closeSession(sessionId);
1077 }
1078
1079 /**
1080 * setMediaDrmSession with a closed session id
1081 */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionClosedSession)1082 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionClosedSession) {
1083 RETURN_IF_SKIPPED;
1084 auto sessionId = openSession();
1085 closeSession(sessionId);
1086 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1087 EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
1088 }
1089
1090 /**
1091 * setMediaDrmSession with a empty session id: BAD_VALUE
1092 */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionEmptySession)1093 TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
1094 RETURN_IF_SKIPPED;
1095 SessionId sessionId;
1096 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1097 EXPECT_EQ(Status::BAD_VALUE, status);
1098 }
1099
1100 /**
1101 * Decrypt tests
1102 */
1103
fillRandom(const sp<IMemory> & memory)1104 void DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) {
1105 random_device rd;
1106 mt19937 rand(rd());
1107 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) {
1108 auto p = static_cast<uint32_t*>(
1109 static_cast<void*>(memory->getPointer()));
1110 p[i] = rand();
1111 }
1112 }
1113
queryKeyStatus(SessionId sessionId)1114 hidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) {
1115 hidl_vec<KeyValue> keyStatus;
1116 auto res = drmPlugin->queryKeyStatus(sessionId,
1117 [&](Status status, KeyedVector info) {
1118 EXPECT_EQ(Status::OK, status);
1119 keyStatus = info;
1120 });
1121 EXPECT_OK(res);
1122 return keyStatus;
1123 }
1124
removeKeys(SessionId sessionId)1125 void DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) {
1126 auto res = drmPlugin->removeKeys(sessionId);
1127 EXPECT_OK(res);
1128 }
1129
decrypt(Mode mode,bool isSecure,const hidl_array<uint8_t,16> & keyId,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const Pattern & pattern,const vector<uint8_t> & key,Status expectedStatus)1130 uint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure,
1131 const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
1132 const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
1133 const vector<uint8_t>& key, Status expectedStatus) {
1134 const size_t kSegmentIndex = 0;
1135
1136 uint8_t localIv[AES_BLOCK_SIZE];
1137 memcpy(localIv, iv, AES_BLOCK_SIZE);
1138
1139 size_t totalSize = 0;
1140 for (size_t i = 0; i < subSamples.size(); i++) {
1141 totalSize += subSamples[i].numBytesOfClearData;
1142 totalSize += subSamples[i].numBytesOfEncryptedData;
1143 }
1144
1145 // The first totalSize bytes of shared memory is the encrypted
1146 // input, the second totalSize bytes is the decrypted output.
1147 sp<IMemory> sharedMemory =
1148 getDecryptMemory(totalSize * 2, kSegmentIndex);
1149
1150 SharedBuffer sourceBuffer = {
1151 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
1152 fillRandom(sharedMemory);
1153
1154 DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
1155 {.bufferId = kSegmentIndex,
1156 .offset = totalSize,
1157 .size = totalSize},
1158 .secureMemory = nullptr};
1159 uint64_t offset = 0;
1160 uint32_t bytesWritten = 0;
1161 auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern,
1162 subSamples, sourceBuffer, offset, destBuffer,
1163 [&](Status status, uint32_t count, string detailedError) {
1164 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
1165 detailedError;
1166 bytesWritten = count;
1167 });
1168 EXPECT_OK(res);
1169
1170 if (bytesWritten != totalSize) {
1171 return bytesWritten;
1172 }
1173 uint8_t* base = static_cast<uint8_t*>(
1174 static_cast<void*>(sharedMemory->getPointer()));
1175
1176 // generate reference vector
1177 vector<uint8_t> reference(totalSize);
1178
1179 memcpy(localIv, iv, AES_BLOCK_SIZE);
1180 switch (mode) {
1181 case Mode::UNENCRYPTED:
1182 memcpy(&reference[0], base, totalSize);
1183 break;
1184 case Mode::AES_CTR:
1185 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
1186 break;
1187 case Mode::AES_CBC:
1188 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
1189 break;
1190 case Mode::AES_CBC_CTS:
1191 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
1192 break;
1193 }
1194
1195 // compare reference to decrypted data which is at base + total size
1196 EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]),
1197 static_cast<void*>(base + totalSize), totalSize))
1198 << "decrypt data mismatch";
1199 return totalSize;
1200 }
1201
1202 /**
1203 * Decrypt a list of clear+encrypted subsamples using the specified key
1204 * in AES-CTR mode
1205 */
aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1206 void DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
1207 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1208 const vector<uint8_t>& key) {
1209
1210 AES_KEY decryptionKey;
1211 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1212
1213 size_t offset = 0;
1214 unsigned blockOffset = 0;
1215 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
1216 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
1217
1218 for (size_t i = 0; i < subSamples.size(); i++) {
1219 const SubSample& subSample = subSamples[i];
1220
1221 if (subSample.numBytesOfClearData > 0) {
1222 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1223 offset += subSample.numBytesOfClearData;
1224 }
1225
1226 if (subSample.numBytesOfEncryptedData > 0) {
1227 AES_ctr128_encrypt(src + offset, dest + offset,
1228 subSample.numBytesOfEncryptedData, &decryptionKey,
1229 iv, previousEncryptedCounter, &blockOffset);
1230 offset += subSample.numBytesOfEncryptedData;
1231 }
1232 }
1233 }
1234
1235 /**
1236 * Decrypt a list of clear+encrypted subsamples using the specified key
1237 * in AES-CBC mode
1238 */
aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1239 void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
1240 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1241 const vector<uint8_t>& key) {
1242 AES_KEY decryptionKey;
1243 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1244
1245 size_t offset = 0;
1246 for (size_t i = 0; i < subSamples.size(); i++) {
1247 const SubSample& subSample = subSamples[i];
1248
1249 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1250 offset += subSample.numBytesOfClearData;
1251
1252 AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData,
1253 &decryptionKey, iv, 0 /* decrypt */);
1254 offset += subSample.numBytesOfEncryptedData;
1255 }
1256 }
1257
1258
1259 /**
1260 * Test key status with empty session id, should return BAD_VALUE
1261 */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusInvalidSession)1262 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) {
1263 RETURN_IF_SKIPPED;
1264 SessionId sessionId;
1265 auto res = drmPlugin->queryKeyStatus(sessionId,
1266 [&](Status status, KeyedVector /* info */) {
1267 EXPECT_EQ(Status::BAD_VALUE, status);
1268 });
1269 EXPECT_OK(res);
1270 }
1271
1272
1273 /**
1274 * Test key status. There should be no key status prior to loading keys
1275 */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusWithNoKeys)1276 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) {
1277 RETURN_IF_SKIPPED;
1278 auto sessionId = openSession();
1279 auto keyStatus = queryKeyStatus(sessionId);
1280 EXPECT_EQ(0u, keyStatus.size());
1281 closeSession(sessionId);
1282 }
1283
1284
1285 /**
1286 * Test key status. There should be key status after loading keys.
1287 */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatus)1288 TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
1289 RETURN_IF_SKIPPED;
1290 for (const auto& config : contentConfigurations) {
1291 auto sessionId = openSession();
1292 loadKeys(sessionId, config);
1293 auto keyStatus = queryKeyStatus(sessionId);
1294 EXPECT_NE(0u, keyStatus.size());
1295 closeSession(sessionId);
1296 }
1297 }
1298
1299 /**
1300 * Positive decrypt test. "Decrypt" a single clear segment and verify.
1301 */
TEST_P(DrmHalVendorDecryptTest,ClearSegmentTest)1302 TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
1303 RETURN_IF_SKIPPED;
1304 for (const auto& config : contentConfigurations) {
1305 for (const auto& key : config.keys) {
1306 const size_t kSegmentSize = 1024;
1307 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1308 const Pattern noPattern = {0, 0};
1309 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1310 .numBytesOfEncryptedData = 0}};
1311 auto sessionId = openSession();
1312 loadKeys(sessionId, config);
1313
1314 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1315 EXPECT_EQ(Status::OK, status);
1316
1317 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
1318 &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1319 EXPECT_EQ(kSegmentSize, byteCount);
1320
1321 closeSession(sessionId);
1322 }
1323 }
1324 }
1325
1326 /**
1327 * Positive decrypt test. Decrypt a single segment using aes_ctr.
1328 * Verify data matches.
1329 */
TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTest)1330 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
1331 RETURN_IF_SKIPPED;
1332 for (const auto& config : contentConfigurations) {
1333 for (const auto& key : config.keys) {
1334 const size_t kSegmentSize = 1024;
1335 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1336 const Pattern noPattern = {0, 0};
1337 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1338 .numBytesOfEncryptedData = 0}};
1339 auto sessionId = openSession();
1340 loadKeys(sessionId, config);
1341
1342 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1343 EXPECT_EQ(Status::OK, status);
1344
1345 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
1346 &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1347 EXPECT_EQ(kSegmentSize, byteCount);
1348
1349 closeSession(sessionId);
1350 }
1351 }
1352 }
1353
1354 /**
1355 * Negative decrypt test. Decrypt without loading keys.
1356 */
TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTestNoKeys)1357 TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
1358 RETURN_IF_SKIPPED;
1359 for (const auto& config : contentConfigurations) {
1360 for (const auto& key : config.keys) {
1361 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1362 const Pattern noPattern = {0, 0};
1363 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1364 .numBytesOfEncryptedData = 256}};
1365 auto sessionId = openSession();
1366
1367 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1368 EXPECT_EQ(Status::OK, status);
1369
1370 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1371 toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1372 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1373 EXPECT_EQ(0u, byteCount);
1374
1375 closeSession(sessionId);
1376 }
1377 }
1378 }
1379
1380 /**
1381 * Test key removal. Load keys then remove them and verify that
1382 * decryption can't be performed.
1383 */
TEST_P(DrmHalVendorDecryptTest,AttemptDecryptWithKeysRemoved)1384 TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
1385 RETURN_IF_SKIPPED;
1386 for (const auto& config : contentConfigurations) {
1387 for (const auto& key : config.keys) {
1388 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1389 const Pattern noPattern = {0, 0};
1390 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1391 .numBytesOfEncryptedData = 256}};
1392 auto sessionId = openSession();
1393
1394 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1395 EXPECT_EQ(Status::OK, status);
1396
1397 loadKeys(sessionId, config);
1398 removeKeys(sessionId);
1399
1400 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1401 toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1402 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1403 EXPECT_EQ(0u, byteCount);
1404
1405 closeSession(sessionId);
1406 }
1407 }
1408 }
1409
1410 } // namespace vts
1411 } // namespace V1_0
1412 } // namespace drm
1413 } // namespace hardware
1414 } // namespace android
1415