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