1 /*
2 * Copyright (C) 2019 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 #include "vendor_modules.h"
18 #define LOG_TAG "drm_hal_common@1.2"
19
20 #include <android/hidl/allocator/1.0/IAllocator.h>
21 #include <gtest/gtest.h>
22 #include <hidl/HidlSupport.h>
23 #include <hidlmemory/mapping.h>
24 #include <log/log.h>
25 #include <openssl/aes.h>
26 #include <random>
27
28 #include "drm_hal_clearkey_module.h"
29 #include "android/hardware/drm/1.2/vts/drm_hal_common.h"
30
31 using ::android::hardware::drm::V1_0::BufferType;
32 using ::android::hardware::drm::V1_0::DestinationBuffer;
33 using ICryptoPluginV1_0 = ::android::hardware::drm::V1_0::ICryptoPlugin;
34 using IDrmPluginV1_0 = ::android::hardware::drm::V1_0::IDrmPlugin;
35 using ::android::hardware::drm::V1_0::KeyValue;
36 using ::android::hardware::drm::V1_0::SharedBuffer;
37 using StatusV1_0 = ::android::hardware::drm::V1_0::Status;
38
39 using ::android::hardware::drm::V1_1::KeyRequestType;
40
41 using ::android::hardware::drm::V1_2::KeySetId;
42 using ::android::hardware::drm::V1_2::OfflineLicenseState;
43 using StatusV1_2 = ::android::hardware::drm::V1_2::Status;
44
45 using ::android::hardware::hidl_string;
46 using ::android::hardware::hidl_memory;
47
48 using ::android::hidl::allocator::V1_0::IAllocator;
49
50 using std::random_device;
51 using std::mt19937;
52
53 namespace android {
54 namespace hardware {
55 namespace drm {
56 namespace V1_2 {
57 namespace vts {
58
59 const char *kCallbackLostState = "LostState";
60 const char *kCallbackKeysChange = "KeysChange";
61
62 drm_vts::VendorModules *DrmHalTest::gVendorModules = nullptr;
63
64 /**
65 * DrmHalPluginListener
66 */
67
sendSessionLostState(const hidl_vec<uint8_t> & sessionId)68 Return<void> DrmHalPluginListener::sendSessionLostState(const hidl_vec<uint8_t>& sessionId) {
69 ListenerEventArgs args;
70 args.sessionId = sessionId;
71 NotifyFromCallback(kCallbackLostState, args);
72 return Void();
73 }
74
sendKeysChange_1_2(const hidl_vec<uint8_t> & sessionId,const hidl_vec<KeyStatus> & keyStatusList,bool hasNewUsableKey)75 Return<void> DrmHalPluginListener::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
76 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
77 ListenerEventArgs args;
78 args.sessionId = sessionId;
79 args.keyStatusList = keyStatusList;
80 args.hasNewUsableKey = hasNewUsableKey;
81 NotifyFromCallback(kCallbackKeysChange, args);
82 return Void();
83 }
84
getModuleForInstance(const std::string & instance)85 static DrmHalVTSVendorModule_V1* getModuleForInstance(const std::string& instance) {
86 if (instance == "clearkey" || instance == "default") {
87 return new DrmHalVTSClearkeyModule();
88 }
89
90 return static_cast<DrmHalVTSVendorModule_V1*>(DrmHalTest::gVendorModules->getModuleByName(instance));
91 }
92
93 /**
94 * DrmHalTest
95 */
96
DrmHalTest()97 DrmHalTest::DrmHalTest() : vendorModule(getModuleForInstance(GetParamService())) {}
98
SetUp()99 void DrmHalTest::SetUp() {
100 const ::testing::TestInfo* const test_info =
101 ::testing::UnitTest::GetInstance()->current_test_info();
102
103 ALOGD("Running test %s.%s from (vendor) module %s",
104 test_info->test_case_name(), test_info->name(),
105 GetParamService().c_str());
106
107 const string instance = GetParamService();
108
109 drmFactory = IDrmFactory::getService(instance);
110 ASSERT_NE(drmFactory, nullptr);
111 drmPlugin = createDrmPlugin();
112
113 cryptoFactory = ICryptoFactory::getService(instance);
114 ASSERT_NE(cryptoFactory, nullptr);
115 cryptoPlugin = createCryptoPlugin();
116
117 if (!vendorModule) {
118 ASSERT_NE(instance, "widevine") << "Widevine requires vendor module.";
119 ASSERT_NE(instance, "clearkey") << "Clearkey requires vendor module.";
120 GTEST_SKIP() << "No vendor module installed";
121 }
122
123 ASSERT_EQ(instance, vendorModule->getServiceName());
124 contentConfigurations = vendorModule->getContentConfigurations();
125
126 // If drm scheme not installed skip subsequent tests
127 if (!drmFactory->isCryptoSchemeSupported(getUUID())) {
128 if (GetParamUUID() == hidl_array<uint8_t, 16>()) {
129 GTEST_SKIP() << "vendor module drm scheme not supported";
130 } else {
131 FAIL() << "param scheme must be supported: " << android::hardware::toString(GetParamUUID());
132 }
133 }
134
135 ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find " << vendorModule->getServiceName() << " drm@1.2 plugin";
136 ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find " << vendorModule->getServiceName() << " crypto@1.2 plugin";
137
138 }
139
createDrmPlugin()140 sp<IDrmPlugin> DrmHalTest::createDrmPlugin() {
141 if (drmFactory == nullptr) {
142 return nullptr;
143 }
144 sp<IDrmPlugin> plugin = nullptr;
145 hidl_string packageName("android.hardware.drm.test");
146 auto res =
147 drmFactory->createPlugin(getUUID(), packageName,
148 [&](StatusV1_0 status, const sp<IDrmPluginV1_0>& pluginV1_0) {
149 EXPECT_EQ(StatusV1_0::OK == status, pluginV1_0 != nullptr);
150 plugin = IDrmPlugin::castFrom(pluginV1_0);
151 });
152
153 if (!res.isOk()) {
154 ALOGE("createDrmPlugin remote call failed");
155 }
156 return plugin;
157 }
158
createCryptoPlugin()159 sp<ICryptoPlugin> DrmHalTest::createCryptoPlugin() {
160 if (cryptoFactory == nullptr) {
161 return nullptr;
162 }
163 sp<ICryptoPlugin> plugin = nullptr;
164 hidl_vec<uint8_t> initVec;
165 auto res = cryptoFactory->createPlugin(
166 getUUID(), initVec,
167 [&](StatusV1_0 status, const sp<ICryptoPluginV1_0>& pluginV1_0) {
168 EXPECT_EQ(StatusV1_0::OK == status, pluginV1_0 != nullptr);
169 plugin = ICryptoPlugin::castFrom(pluginV1_0);
170 });
171 if (!res.isOk()) {
172 ALOGE("createCryptoPlugin remote call failed");
173 }
174 return plugin;
175 }
176
getUUID()177 hidl_array<uint8_t, 16> DrmHalTest::getUUID() {
178 if (GetParamUUID() == hidl_array<uint8_t, 16>()) {
179 return getVendorUUID();
180 }
181 return GetParamUUID();
182 }
183
getVendorUUID()184 hidl_array<uint8_t, 16> DrmHalTest::getVendorUUID() {
185 if (vendorModule == nullptr) return {};
186 vector<uint8_t> uuid = vendorModule->getUUID();
187 return hidl_array<uint8_t, 16>(&uuid[0]);
188 }
189
provision()190 void DrmHalTest::provision() {
191 hidl_string certificateType;
192 hidl_string certificateAuthority;
193 hidl_vec<uint8_t> provisionRequest;
194 hidl_string defaultUrl;
195 auto res = drmPlugin->getProvisionRequest_1_2(
196 certificateType, certificateAuthority,
197 [&](StatusV1_2 status, const hidl_vec<uint8_t>& request,
198 const hidl_string& url) {
199 if (status == StatusV1_2::OK) {
200 EXPECT_NE(request.size(), 0u);
201 provisionRequest = request;
202 defaultUrl = url;
203 } else if (status == StatusV1_2::ERROR_DRM_CANNOT_HANDLE) {
204 EXPECT_EQ(0u, request.size());
205 }
206 });
207 EXPECT_OK(res);
208
209 if (provisionRequest.size() > 0) {
210 vector<uint8_t> response = vendorModule->handleProvisioningRequest(
211 provisionRequest, defaultUrl);
212 ASSERT_NE(0u, response.size());
213
214 auto res = drmPlugin->provideProvisionResponse(
215 response, [&](StatusV1_0 status, const hidl_vec<uint8_t>&,
216 const hidl_vec<uint8_t>&) {
217 EXPECT_EQ(StatusV1_0::OK, status);
218 });
219 EXPECT_OK(res);
220 }
221 }
222
openSession(SecurityLevel level,StatusV1_0 * err)223 SessionId DrmHalTest::openSession(SecurityLevel level, StatusV1_0 *err) {
224 SessionId sessionId;
225 auto res = drmPlugin->openSession_1_1(level,
226 [&](StatusV1_0 status, const hidl_vec<unsigned char> &id) {
227 *err = status;
228 sessionId = id;
229 });
230 EXPECT_OK(res);
231 return sessionId;
232 }
233
234 /**
235 * Helper method to open a session and verify that a non-empty
236 * session ID is returned
237 */
openSession()238 SessionId DrmHalTest::openSession() {
239 SessionId sessionId;
240
241 auto res = drmPlugin->openSession([&](StatusV1_0 status, const hidl_vec<unsigned char> &id) {
242 EXPECT_EQ(StatusV1_0::OK, status);
243 EXPECT_NE(id.size(), 0u);
244 sessionId = id;
245 });
246 EXPECT_OK(res);
247 return sessionId;
248 }
249
250 /**
251 * Helper method to close a session
252 */
closeSession(const SessionId & sessionId)253 void DrmHalTest::closeSession(const SessionId& sessionId) {
254 StatusV1_0 status = drmPlugin->closeSession(sessionId);
255 EXPECT_EQ(StatusV1_0::OK, status);
256 }
257
getKeyRequest(const SessionId & sessionId,const DrmHalVTSVendorModule_V1::ContentConfiguration & configuration,const KeyType & type=KeyType::STREAMING)258 hidl_vec<uint8_t> DrmHalTest::getKeyRequest(
259 const SessionId& sessionId,
260 const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration,
261 const KeyType& type = KeyType::STREAMING) {
262 hidl_vec<uint8_t> keyRequest;
263 auto res = drmPlugin->getKeyRequest_1_2(
264 sessionId, configuration.initData, configuration.mimeType, type,
265 toHidlKeyedVector(configuration.optionalParameters),
266 [&](Status status, const hidl_vec<uint8_t>& request,
267 KeyRequestType requestType, const hidl_string&) {
268 EXPECT_EQ(Status::OK, status) << "Failed to get "
269 "key request for configuration "
270 << configuration.name;
271 if (type == KeyType::RELEASE) {
272 EXPECT_EQ(KeyRequestType::RELEASE, requestType);
273 } else {
274 EXPECT_EQ(KeyRequestType::INITIAL, requestType);
275 }
276 EXPECT_NE(request.size(), 0u) << "Expected key request size"
277 " to have length > 0 bytes";
278 keyRequest = request;
279 });
280 EXPECT_OK(res);
281 return keyRequest;
282 }
283
getContent(const KeyType & type) const284 DrmHalVTSVendorModule_V1::ContentConfiguration DrmHalTest::getContent(const KeyType& type) const {
285 for (const auto& config : contentConfigurations) {
286 if (type != KeyType::OFFLINE || config.policy.allowOffline) {
287 return config;
288 }
289 }
290 EXPECT_TRUE(false) << "no content configurations found";
291 return {};
292 }
293
provideKeyResponse(const SessionId & sessionId,const hidl_vec<uint8_t> & keyResponse)294 hidl_vec<uint8_t> DrmHalTest::provideKeyResponse(
295 const SessionId& sessionId,
296 const hidl_vec<uint8_t>& keyResponse) {
297 hidl_vec<uint8_t> keySetId;
298 auto res = drmPlugin->provideKeyResponse(
299 sessionId, keyResponse,
300 [&](StatusV1_0 status, const hidl_vec<uint8_t>& myKeySetId) {
301 EXPECT_EQ(StatusV1_0::OK, status) << "Failure providing "
302 "key response for configuration ";
303 keySetId = myKeySetId;
304 });
305 EXPECT_OK(res);
306 return keySetId;
307 }
308
309 /**
310 * Helper method to load keys for subsequent decrypt tests.
311 * These tests use predetermined key request/response to
312 * avoid requiring a round trip to a license server.
313 */
loadKeys(const SessionId & sessionId,const DrmHalVTSVendorModule_V1::ContentConfiguration & configuration,const KeyType & type)314 hidl_vec<uint8_t> DrmHalTest::loadKeys(
315 const SessionId& sessionId,
316 const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration,
317 const KeyType& type) {
318 hidl_vec<uint8_t> keyRequest = getKeyRequest(sessionId, configuration, type);
319
320 /**
321 * Get key response from vendor module
322 */
323 hidl_vec<uint8_t> keyResponse =
324 vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
325 EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
326 "to have length > 0 bytes";
327
328 return provideKeyResponse(sessionId, keyResponse);
329 }
330
loadKeys(const SessionId & sessionId,const KeyType & type)331 hidl_vec<uint8_t> DrmHalTest::loadKeys(
332 const SessionId& sessionId,
333 const KeyType& type) {
334 return loadKeys(sessionId, getContent(type), type);
335 }
336
toHidlKeyedVector(const map<string,string> & params)337 KeyedVector DrmHalTest::toHidlKeyedVector(
338 const map<string, string>& params) {
339 std::vector<KeyValue> stdKeyedVector;
340 for (auto it = params.begin(); it != params.end(); ++it) {
341 KeyValue keyValue;
342 keyValue.key = it->first;
343 keyValue.value = it->second;
344 stdKeyedVector.push_back(keyValue);
345 }
346 return KeyedVector(stdKeyedVector);
347 }
348
toHidlArray(const vector<uint8_t> & vec)349 hidl_array<uint8_t, 16> DrmHalTest::toHidlArray(const vector<uint8_t>& vec) {
350 EXPECT_EQ(16u, vec.size());
351 return hidl_array<uint8_t, 16>(&vec[0]);
352 }
353
354 /**
355 * getDecryptMemory allocates memory for decryption, then sets it
356 * as a shared buffer base in the crypto hal. The allocated and
357 * mapped IMemory is returned.
358 *
359 * @param size the size of the memory segment to allocate
360 * @param the index of the memory segment which will be used
361 * to refer to it for decryption.
362 */
getDecryptMemory(size_t size,size_t index)363 sp<IMemory> DrmHalTest::getDecryptMemory(size_t size, size_t index) {
364 sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
365 EXPECT_NE(nullptr, ashmemAllocator.get());
366
367 hidl_memory hidlMemory;
368 auto res = ashmemAllocator->allocate(
369 size, [&](bool success, const hidl_memory& memory) {
370 EXPECT_EQ(success, true);
371 EXPECT_EQ(memory.size(), size);
372 hidlMemory = memory;
373 });
374
375 EXPECT_OK(res);
376
377 sp<IMemory> mappedMemory = mapMemory(hidlMemory);
378 EXPECT_NE(nullptr, mappedMemory.get());
379 res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
380 EXPECT_OK(res);
381 return mappedMemory;
382 }
383
fillRandom(const sp<IMemory> & memory)384 void DrmHalTest::fillRandom(const sp<IMemory>& memory) {
385 random_device rd;
386 mt19937 rand(rd());
387 for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) {
388 auto p = static_cast<uint32_t*>(
389 static_cast<void*>(memory->getPointer()));
390 p[i] = rand();
391 }
392 }
393
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,StatusV1_2 expectedStatus)394 uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure,
395 const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
396 const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
397 const vector<uint8_t>& key, StatusV1_2 expectedStatus) {
398 const size_t kSegmentIndex = 0;
399
400 uint8_t localIv[AES_BLOCK_SIZE];
401 memcpy(localIv, iv, AES_BLOCK_SIZE);
402
403 size_t totalSize = 0;
404 for (size_t i = 0; i < subSamples.size(); i++) {
405 totalSize += subSamples[i].numBytesOfClearData;
406 totalSize += subSamples[i].numBytesOfEncryptedData;
407 }
408
409 // The first totalSize bytes of shared memory is the encrypted
410 // input, the second totalSize bytes (if exists) is the decrypted output.
411 size_t factor = expectedStatus == StatusV1_2::ERROR_DRM_FRAME_TOO_LARGE ? 1 : 2;
412 sp<IMemory> sharedMemory =
413 getDecryptMemory(totalSize * factor, kSegmentIndex);
414
415 const SharedBuffer sourceBuffer = {
416 .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
417 fillRandom(sharedMemory);
418
419 const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
420 {.bufferId = kSegmentIndex,
421 .offset = totalSize,
422 .size = totalSize},
423 .secureMemory = nullptr};
424 const uint64_t offset = 0;
425 uint32_t bytesWritten = 0;
426 auto res = cryptoPlugin->decrypt_1_2(isSecure, keyId, localIv, mode, pattern,
427 subSamples, sourceBuffer, offset, destBuffer,
428 [&](StatusV1_2 status, uint32_t count, string detailedError) {
429 EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
430 detailedError;
431 bytesWritten = count;
432 });
433 EXPECT_OK(res);
434
435 if (bytesWritten != totalSize) {
436 return bytesWritten;
437 }
438 uint8_t* base = static_cast<uint8_t*>(
439 static_cast<void*>(sharedMemory->getPointer()));
440
441 // generate reference vector
442 vector<uint8_t> reference(totalSize);
443
444 memcpy(localIv, iv, AES_BLOCK_SIZE);
445 switch (mode) {
446 case Mode::UNENCRYPTED:
447 memcpy(&reference[0], base, totalSize);
448 break;
449 case Mode::AES_CTR:
450 aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
451 break;
452 case Mode::AES_CBC:
453 aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
454 break;
455 case Mode::AES_CBC_CTS:
456 EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
457 break;
458 }
459
460 // compare reference to decrypted data which is at base + total size
461 EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]),
462 static_cast<void*>(base + totalSize), totalSize))
463 << "decrypt data mismatch";
464 return totalSize;
465 }
466
467 /**
468 * Decrypt a list of clear+encrypted subsamples using the specified key
469 * in AES-CTR mode
470 */
aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)471 void DrmHalTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
472 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
473 const vector<uint8_t>& key) {
474 AES_KEY decryptionKey;
475 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
476
477 size_t offset = 0;
478 unsigned int blockOffset = 0;
479 uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
480 memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
481
482 for (size_t i = 0; i < subSamples.size(); i++) {
483 const SubSample& subSample = subSamples[i];
484
485 if (subSample.numBytesOfClearData > 0) {
486 memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
487 offset += subSample.numBytesOfClearData;
488 }
489
490 if (subSample.numBytesOfEncryptedData > 0) {
491 AES_ctr128_encrypt(src + offset, dest + offset,
492 subSample.numBytesOfEncryptedData, &decryptionKey,
493 iv, previousEncryptedCounter, &blockOffset);
494 offset += subSample.numBytesOfEncryptedData;
495 }
496 }
497 }
498
499 /**
500 * Decrypt a list of clear+encrypted subsamples using the specified key
501 * in AES-CBC mode
502 */
aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)503 void DrmHalTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
504 uint8_t* iv, const hidl_vec<SubSample>& subSamples,
505 const vector<uint8_t>& key) {
506 AES_KEY decryptionKey;
507 AES_set_encrypt_key(&key[0], 128, &decryptionKey);
508
509 size_t offset = 0;
510 for (size_t i = 0; i < subSamples.size(); i++) {
511 memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
512 offset += subSamples[i].numBytesOfClearData;
513
514 AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData,
515 &decryptionKey, iv, 0 /* decrypt */);
516 offset += subSamples[i].numBytesOfEncryptedData;
517 }
518 }
519
520 /**
521 * Helper method to test decryption with invalid keys is returned
522 */
decryptWithInvalidKeys(hidl_vec<uint8_t> & invalidResponse,vector<uint8_t> & iv,const Pattern & noPattern,const vector<SubSample> & subSamples)523 void DrmHalClearkeyTestV1_2::decryptWithInvalidKeys(
524 hidl_vec<uint8_t>& invalidResponse,
525 vector<uint8_t>& iv,
526 const Pattern& noPattern,
527 const vector<SubSample>& subSamples) {
528 DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent();
529 if (content.keys.empty()) {
530 FAIL() << "no keys";
531 }
532
533 const auto& key = content.keys[0];
534 auto sessionId = openSession();
535 auto res = drmPlugin->provideKeyResponse(
536 sessionId, invalidResponse,
537 [&](StatusV1_0 status, const hidl_vec<uint8_t>& myKeySetId) {
538 EXPECT_EQ(StatusV1_0::OK, status);
539 EXPECT_EQ(0u, myKeySetId.size());
540 });
541 EXPECT_OK(res);
542
543 EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
544
545 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
546 toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
547 key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
548 EXPECT_EQ(0u, byteCount);
549
550 closeSession(sessionId);
551 }
552
553 } // namespace vts
554 } // namespace V1_2
555 } // namespace drm
556 } // namespace hardware
557 } // namespace android
558