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_test@1.2"
18
19 #include <gtest/gtest.h>
20 #include <hidl/HidlSupport.h>
21 #include <log/log.h>
22 #include <openssl/aes.h>
23
24 #include "drm_hal_common.h"
25
26 using ::android::hardware::drm::V1_0::Status;
27 using ::android::hardware::drm::V1_1::KeyRequestType;
28 using ::android::hardware::drm::V1_1::SecurityLevel;
29 using ::android::hardware::drm::V1_2::HdcpLevel;
30 using ::android::hardware::drm::V1_2::KeySetId;
31 using ::android::hardware::drm::V1_2::KeyStatus;
32 using ::android::hardware::drm::V1_2::KeyStatusType;
33 using ::android::hardware::drm::V1_2::OfflineLicenseState;
34
35 using ::android::hardware::drm::V1_2::vts::DrmHalClearkeyTest;
36 using ::android::hardware::drm::V1_2::vts::DrmHalPluginListener;
37 using ::android::hardware::drm::V1_2::vts::DrmHalTest;
38 using ::android::hardware::drm::V1_2::vts::DrmHidlEnvironment;
39 using ::android::hardware::drm::V1_2::vts::kCallbackLostState;
40 using ::android::hardware::drm::V1_2::vts::kCallbackKeysChange;
41
42 using ::android::hardware::hidl_string;
43
44 static const char* const kVideoMp4 = "video/mp4";
45 static const char* const kBadMime = "video/unknown";
46 static const char* const kDrmErrorTestKey = "drmErrorTest";
47 static const char* const kDrmErrorInvalidState = "invalidState";
48 static const char* const kDrmErrorResourceContention = "resourceContention";
49 static const SecurityLevel kSwSecureCrypto = SecurityLevel::SW_SECURE_CRYPTO;
50
51 /**
52 * Ensure drm factory supports module UUID Scheme
53 */
TEST_P(DrmHalTest,VendorUuidSupported)54 TEST_P(DrmHalTest, VendorUuidSupported) {
55 auto res = drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kVideoMp4, kSwSecureCrypto);
56 ALOGI("kVideoMp4 = %s res %d", kVideoMp4, (bool)res);
57 EXPECT_TRUE(res);
58 }
59
60 /**
61 * Ensure drm factory doesn't support an invalid scheme UUID
62 */
TEST_P(DrmHalTest,InvalidPluginNotSupported)63 TEST_P(DrmHalTest, InvalidPluginNotSupported) {
64 const uint8_t kInvalidUUID[16] = {
65 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
66 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
67 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(kInvalidUUID, kVideoMp4, kSwSecureCrypto));
68 }
69
70 /**
71 * Ensure drm factory doesn't support an empty UUID
72 */
TEST_P(DrmHalTest,EmptyPluginUUIDNotSupported)73 TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) {
74 hidl_array<uint8_t, 16> emptyUUID;
75 memset(emptyUUID.data(), 0, 16);
76 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(emptyUUID, kVideoMp4, kSwSecureCrypto));
77 }
78
79 /**
80 * Ensure drm factory doesn't support an invalid mime type
81 */
TEST_P(DrmHalTest,BadMimeNotSupported)82 TEST_P(DrmHalTest, BadMimeNotSupported) {
83 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kBadMime, kSwSecureCrypto));
84 }
85
86 /**
87 * DrmPlugin tests
88 */
89
90 /**
91 * Test that a DRM plugin can handle provisioning. While
92 * it is not required that a DRM scheme require provisioning,
93 * it should at least return appropriate status values. If
94 * a provisioning request is returned, it is passed to the
95 * vendor module which should provide a provisioning response
96 * that is delivered back to the HAL.
97 */
TEST_P(DrmHalTest,DoProvisioning)98 TEST_P(DrmHalTest, DoProvisioning) {
99 RETURN_IF_SKIPPED;
100 hidl_string certificateType;
101 hidl_string certificateAuthority;
102 hidl_vec<uint8_t> provisionRequest;
103 hidl_string defaultUrl;
104 auto res = drmPlugin->getProvisionRequest_1_2(
105 certificateType, certificateAuthority,
106 [&](StatusV1_2 status, const hidl_vec<uint8_t>& request,
107 const hidl_string& url) {
108 if (status == StatusV1_2::OK) {
109 EXPECT_NE(request.size(), 0u);
110 provisionRequest = request;
111 defaultUrl = url;
112 } else if (status == StatusV1_2::ERROR_DRM_CANNOT_HANDLE) {
113 EXPECT_EQ(0u, request.size());
114 }
115 });
116 EXPECT_OK(res);
117
118 if (provisionRequest.size() > 0) {
119 vector<uint8_t> response = vendorModule->handleProvisioningRequest(
120 provisionRequest, defaultUrl);
121 ASSERT_NE(0u, response.size());
122
123 auto res = drmPlugin->provideProvisionResponse(
124 response, [&](Status status, const hidl_vec<uint8_t>&,
125 const hidl_vec<uint8_t>&) {
126 EXPECT_EQ(Status::OK, status);
127 });
128 EXPECT_OK(res);
129 }
130 }
131
132 /**
133 * A get key request should fail if no sessionId is provided
134 */
TEST_P(DrmHalTest,GetKeyRequestNoSession)135 TEST_P(DrmHalTest, GetKeyRequestNoSession) {
136 SessionId invalidSessionId;
137 hidl_vec<uint8_t> initData;
138 KeyedVector optionalParameters;
139 auto res = drmPlugin->getKeyRequest_1_2(
140 invalidSessionId, initData, kVideoMp4, KeyType::STREAMING,
141 optionalParameters,
142 [&](StatusV1_2 status, const hidl_vec<uint8_t>&, KeyRequestType,
143 const hidl_string&) { EXPECT_EQ(StatusV1_2::BAD_VALUE, status); });
144 EXPECT_OK(res);
145 }
146
147 /**
148 * Test that the plugin returns the documented error for the
149 * case of attempting to generate a key request using an
150 * invalid mime type
151 */
TEST_P(DrmHalTest,GetKeyRequestBadMime)152 TEST_P(DrmHalTest, GetKeyRequestBadMime) {
153 auto sessionId = openSession();
154 hidl_vec<uint8_t> initData;
155 KeyedVector optionalParameters;
156 auto res = drmPlugin->getKeyRequest_1_2(
157 sessionId, initData, kBadMime, KeyType::STREAMING,
158 optionalParameters, [&](StatusV1_2 status, const hidl_vec<uint8_t>&,
159 KeyRequestType, const hidl_string&) {
160 EXPECT_NE(StatusV1_2::OK, status);
161 });
162 EXPECT_OK(res);
163 closeSession(sessionId);
164 }
165
166 template <Status S, size_t N>
checkKeySetIds(Status status,const hidl_vec<KeySetId> & keySetIds)167 void checkKeySetIds(Status status, const hidl_vec<KeySetId>& keySetIds) {
168 EXPECT_EQ(S, status);
169 if (S == Status::OK) {
170 EXPECT_EQ(N, keySetIds.size());
171 }
172 }
173
174 template <Status S, OfflineLicenseState T>
checkKeySetIdState(Status status,OfflineLicenseState state)175 void checkKeySetIdState(Status status, OfflineLicenseState state) {
176 if (S == Status::OK) {
177 EXPECT_TRUE(T == OfflineLicenseState::USABLE || T == OfflineLicenseState::INACTIVE);
178 } else {
179 EXPECT_TRUE(T == OfflineLicenseState::UNKNOWN);
180 }
181 EXPECT_EQ(S, status);
182 EXPECT_EQ(T, state);
183 }
184
185 /**
186 * Test drm plugin offline key support
187 */
TEST_P(DrmHalTest,OfflineLicenseTest)188 TEST_P(DrmHalTest, OfflineLicenseTest) {
189 auto sessionId = openSession();
190 hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
191
192 auto res = drmPlugin->getOfflineLicenseKeySetIds(
193 [&](Status status, const hidl_vec<KeySetId>& keySetIds) {
194 bool found = false;
195 EXPECT_EQ(Status::OK, status);
196 for (KeySetId keySetId2: keySetIds) {
197 if (keySetId == keySetId2) {
198 found = true;
199 break;
200 }
201 }
202 EXPECT_TRUE(found) << "keySetId not found";
203 });
204 EXPECT_OK(res);
205
206 Status err = drmPlugin->removeOfflineLicense(keySetId);
207 EXPECT_EQ(Status::OK, err);
208
209 res = drmPlugin->getOfflineLicenseKeySetIds(
210 [&](Status status, const hidl_vec<KeySetId>& keySetIds) {
211 EXPECT_EQ(Status::OK, status);
212 for (KeySetId keySetId2: keySetIds) {
213 EXPECT_NE(keySetId, keySetId2);
214 }
215 });
216 EXPECT_OK(res);
217
218 err = drmPlugin->removeOfflineLicense(keySetId);
219 EXPECT_EQ(Status::BAD_VALUE, err);
220
221 closeSession(sessionId);
222 }
223
224 /**
225 * Test drm plugin offline key state
226 */
TEST_P(DrmHalTest,OfflineLicenseStateTest)227 TEST_P(DrmHalTest, OfflineLicenseStateTest) {
228 auto sessionId = openSession();
229 DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(KeyType::OFFLINE);
230 hidl_vec<uint8_t> keySetId = loadKeys(sessionId, content, KeyType::OFFLINE);
231 drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::OK, OfflineLicenseState::USABLE>);
232
233 hidl_vec<uint8_t> keyRequest = getKeyRequest(keySetId, content, KeyType::RELEASE);
234 drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::OK, OfflineLicenseState::INACTIVE>);
235
236 /**
237 * Get key response from vendor module
238 */
239 hidl_vec<uint8_t> keyResponse =
240 vendorModule->handleKeyRequest(keyRequest, content.serverUrl);
241 EXPECT_GT(keyResponse.size(), 0u);
242
243 provideKeyResponse(keySetId, keyResponse);
244 drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::BAD_VALUE, OfflineLicenseState::UNKNOWN>);
245 closeSession(sessionId);
246 }
247
248 /**
249 * Negative offline license test. Remove empty keySetId
250 */
TEST_P(DrmHalTest,RemoveEmptyKeySetId)251 TEST_P(DrmHalTest, RemoveEmptyKeySetId) {
252 KeySetId emptyKeySetId;
253 Status err = drmPlugin->removeOfflineLicense(emptyKeySetId);
254 EXPECT_EQ(Status::BAD_VALUE, err);
255 }
256
257 /**
258 * Negative offline license test. Get empty keySetId state
259 */
TEST_P(DrmHalTest,GetEmptyKeySetIdState)260 TEST_P(DrmHalTest, GetEmptyKeySetIdState) {
261 KeySetId emptyKeySetId;
262 auto res = drmPlugin->getOfflineLicenseState(emptyKeySetId, checkKeySetIdState<Status::BAD_VALUE, OfflineLicenseState::UNKNOWN>);
263 EXPECT_OK(res);
264 }
265
266 /**
267 * Test that the plugin returns valid connected and max HDCP levels
268 */
TEST_P(DrmHalTest,GetHdcpLevels)269 TEST_P(DrmHalTest, GetHdcpLevels) {
270 auto res = drmPlugin->getHdcpLevels_1_2(
271 [&](StatusV1_2 status, const HdcpLevel &connectedLevel,
272 const HdcpLevel &maxLevel) {
273 EXPECT_EQ(StatusV1_2::OK, status);
274 EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE);
275 EXPECT_LE(maxLevel, HdcpLevel::HDCP_V2_3);
276 });
277 EXPECT_OK(res);
278 }
279
280 /**
281 * Simulate the plugin sending keys change and make sure
282 * the listener gets them.
283 */
TEST_P(DrmHalTest,ListenerKeysChange)284 TEST_P(DrmHalTest, ListenerKeysChange) {
285 RETURN_IF_SKIPPED;
286 sp<DrmHalPluginListener> listener = new DrmHalPluginListener();
287 auto res = drmPlugin->setListener(listener);
288 EXPECT_OK(res);
289
290 auto sessionId = openSession();
291 const hidl_vec<KeyStatus> keyStatusList = {
292 {{1}, KeyStatusType::USABLE},
293 {{2}, KeyStatusType::EXPIRED},
294 {{3}, KeyStatusType::OUTPUTNOTALLOWED},
295 {{4}, KeyStatusType::STATUSPENDING},
296 {{5}, KeyStatusType::INTERNALERROR},
297 {{6}, KeyStatusType::USABLEINFUTURE},
298 };
299
300 drmPlugin->sendKeysChange_1_2(sessionId, keyStatusList, true);
301 auto result = listener->WaitForCallback(kCallbackKeysChange);
302 EXPECT_TRUE(result.no_timeout);
303 EXPECT_TRUE(result.args);
304 EXPECT_EQ(sessionId, result.args->sessionId);
305 EXPECT_EQ(keyStatusList, result.args->keyStatusList);
306 closeSession(sessionId);
307 }
308
309 /**
310 * CryptoPlugin Decrypt tests
311 */
312
313 /**
314 * Positive decrypt test. "Decrypt" a single clear segment
315 */
TEST_P(DrmHalTest,ClearSegmentTest)316 TEST_P(DrmHalTest, ClearSegmentTest) {
317 RETURN_IF_SKIPPED;
318 for (const auto& config : contentConfigurations) {
319 for (const auto& key : config.keys) {
320 const size_t kSegmentSize = 1024;
321 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
322 const Pattern noPattern = {0, 0};
323 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
324 .numBytesOfEncryptedData = 0}};
325 auto sessionId = openSession();
326 loadKeys(sessionId, config);
327
328 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
329 EXPECT_EQ(Status::OK, status);
330
331 uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
332 &iv[0], subSamples, noPattern, key.clearContentKey, StatusV1_2::OK);
333 EXPECT_EQ(kSegmentSize, byteCount);
334
335 closeSession(sessionId);
336 }
337 }
338 }
339
340 /**
341 * Positive decrypt test. Decrypt a single segment using aes_ctr.
342 * Verify data matches.
343 */
TEST_P(DrmHalTest,EncryptedAesCtrSegmentTest)344 TEST_P(DrmHalTest, EncryptedAesCtrSegmentTest) {
345 RETURN_IF_SKIPPED;
346 for (const auto& config : contentConfigurations) {
347 for (const auto& key : config.keys) {
348 const size_t kSegmentSize = 1024;
349 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
350 const Pattern noPattern = {0, 0};
351 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
352 .numBytesOfEncryptedData = 0}};
353 auto sessionId = openSession();
354 loadKeys(sessionId, config);
355
356 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
357 EXPECT_EQ(Status::OK, status);
358
359 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
360 &iv[0], subSamples, noPattern, key.clearContentKey, StatusV1_2::OK);
361 EXPECT_EQ(kSegmentSize, byteCount);
362
363 closeSession(sessionId);
364 }
365 }
366 }
367
368 /**
369 * Negative decrypt test. Decrypted frame too large to fit in output buffer
370 */
TEST_P(DrmHalTest,ErrorFrameTooLarge)371 TEST_P(DrmHalTest, ErrorFrameTooLarge) {
372 RETURN_IF_SKIPPED;
373 for (const auto& config : contentConfigurations) {
374 for (const auto& key : config.keys) {
375 const size_t kSegmentSize = 1024;
376 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
377 const Pattern noPattern = {0, 0};
378 const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
379 .numBytesOfEncryptedData = 0}};
380 auto sessionId = openSession();
381 loadKeys(sessionId, config);
382
383 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
384 EXPECT_EQ(Status::OK, status);
385
386 decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
387 &iv[0], subSamples, noPattern, key.clearContentKey, StatusV1_2::ERROR_DRM_FRAME_TOO_LARGE);
388
389 closeSession(sessionId);
390 }
391 }
392 }
393
394 /**
395 * Negative decrypt test. Decrypt without loading keys.
396 */
TEST_P(DrmHalTest,EncryptedAesCtrSegmentTestNoKeys)397 TEST_P(DrmHalTest, EncryptedAesCtrSegmentTestNoKeys) {
398 RETURN_IF_SKIPPED;
399 for (const auto& config : contentConfigurations) {
400 for (const auto& key : config.keys) {
401 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
402 const Pattern noPattern = {0, 0};
403 const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
404 .numBytesOfEncryptedData = 256}};
405 auto sessionId = openSession();
406
407 Status status = cryptoPlugin->setMediaDrmSession(sessionId);
408 EXPECT_EQ(Status::OK, status);
409
410 uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
411 toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
412 key.clearContentKey, StatusV1_2::ERROR_DRM_NO_LICENSE);
413 EXPECT_EQ(0u, byteCount);
414
415 closeSession(sessionId);
416 }
417 }
418 }
419
420 /**
421 * Ensure clearkey drm factory doesn't support security level higher than supported
422 */
TEST_P(DrmHalClearkeyTest,BadLevelNotSupported)423 TEST_P(DrmHalClearkeyTest, BadLevelNotSupported) {
424 const SecurityLevel kHwSecureAll = SecurityLevel::HW_SECURE_ALL;
425 EXPECT_FALSE(drmFactory->isCryptoSchemeSupported_1_2(getVendorUUID(), kVideoMp4, kHwSecureAll));
426 }
427
428 /**
429 * Test resource contention during attempt to generate key request
430 */
TEST_P(DrmHalClearkeyTest,GetKeyRequestResourceContention)431 TEST_P(DrmHalClearkeyTest, GetKeyRequestResourceContention) {
432 Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorResourceContention);
433 EXPECT_EQ(Status::OK, status);
434 auto sessionId = openSession();
435 hidl_vec<uint8_t> initData;
436 KeyedVector optionalParameters;
437 auto res = drmPlugin->getKeyRequest_1_2(
438 sessionId, initData, kVideoMp4, KeyType::STREAMING,
439 optionalParameters, [&](StatusV1_2 status, const hidl_vec<uint8_t>&,
440 KeyRequestType, const hidl_string&) {
441 EXPECT_EQ(StatusV1_2::ERROR_DRM_RESOURCE_CONTENTION, status);
442 });
443 EXPECT_OK(res);
444
445 status = drmPlugin->closeSession(sessionId);
446 EXPECT_NE(Status::OK, status);
447 }
448
449 /**
450 * Test clearkey plugin offline key with mock error
451 */
TEST_P(DrmHalClearkeyTest,OfflineLicenseInvalidState)452 TEST_P(DrmHalClearkeyTest, OfflineLicenseInvalidState) {
453 auto sessionId = openSession();
454 hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
455 Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState);
456 EXPECT_EQ(Status::OK, status);
457
458 // everything should start failing
459 const Status kInvalidState = Status::ERROR_DRM_INVALID_STATE;
460 const OfflineLicenseState kUnknownState = OfflineLicenseState::UNKNOWN;
461 auto res = drmPlugin->getOfflineLicenseKeySetIds(checkKeySetIds<kInvalidState, 0u>);
462 EXPECT_OK(res);
463 res = drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<kInvalidState, kUnknownState>);
464 EXPECT_OK(res);
465 Status err = drmPlugin->removeOfflineLicense(keySetId);
466 EXPECT_EQ(kInvalidState, err);
467 closeSession(sessionId);
468 }
469
470 /**
471 * Test SessionLostState is triggered on error
472 */
TEST_P(DrmHalClearkeyTest,SessionLostState)473 TEST_P(DrmHalClearkeyTest, SessionLostState) {
474 sp<DrmHalPluginListener> listener = new DrmHalPluginListener();
475 auto res = drmPlugin->setListener(listener);
476 EXPECT_OK(res);
477
478 Status status = drmPlugin->setPropertyString(kDrmErrorTestKey, kDrmErrorInvalidState);
479 EXPECT_EQ(Status::OK, status);
480
481 auto sessionId = openSession();
482 drmPlugin->closeSession(sessionId);
483
484 auto result = listener->WaitForCallback(kCallbackLostState);
485 EXPECT_TRUE(result.no_timeout);
486 EXPECT_TRUE(result.args);
487 EXPECT_EQ(sessionId, result.args->sessionId);
488 }
489
490 /**
491 * Negative decrypt test. Decrypt with invalid key.
492 */
TEST_P(DrmHalClearkeyTest,DecryptWithEmptyKey)493 TEST_P(DrmHalClearkeyTest, DecryptWithEmptyKey) {
494 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
495 const Pattern noPattern = {0, 0};
496 const uint32_t kClearBytes = 512;
497 const uint32_t kEncryptedBytes = 512;
498 const vector<SubSample> subSamples = {
499 {.numBytesOfClearData = kClearBytes,
500 .numBytesOfEncryptedData = kEncryptedBytes}};
501
502 // base 64 encoded JSON response string, must not contain padding character '='
503 const hidl_string emptyKeyResponse =
504 "{\"keys\":[" \
505 "{" \
506 "\"kty\":\"oct\"" \
507 "\"alg\":\"A128KW2\"" \
508 "\"k\":\"SGVsbG8gRnJpZW5kIQ\"" \
509 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAyAy\"" \
510 "}" \
511 "{" \
512 "\"kty\":\"oct\"," \
513 "\"alg\":\"A128KW2\"" \
514 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \
515 // empty key follows
516 "\"k\":\"R\"" \
517 "}]" \
518 "}";
519 const size_t kEmptyKeyResponseSize = emptyKeyResponse.size();
520
521 hidl_vec<uint8_t> invalidResponse;
522 invalidResponse.resize(kEmptyKeyResponseSize);
523 memcpy(invalidResponse.data(), emptyKeyResponse.c_str(), kEmptyKeyResponseSize);
524 decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples);
525 }
526
527 /**
528 * Negative decrypt test. Decrypt with a key exceeds AES_BLOCK_SIZE.
529 */
TEST_P(DrmHalClearkeyTest,DecryptWithKeyTooLong)530 TEST_P(DrmHalClearkeyTest, DecryptWithKeyTooLong) {
531 vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
532 const Pattern noPattern = {0, 0};
533 const uint32_t kClearBytes = 512;
534 const uint32_t kEncryptedBytes = 512;
535 const vector<SubSample> subSamples = {
536 {.numBytesOfClearData = kClearBytes,
537 .numBytesOfEncryptedData = kEncryptedBytes}};
538
539 // base 64 encoded JSON response string, must not contain padding character '='
540 const hidl_string keyTooLongResponse =
541 "{\"keys\":[" \
542 "{" \
543 "\"kty\":\"oct\"," \
544 "\"alg\":\"A128KW2\"" \
545 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAzAy\"," \
546 // key too long
547 "\"k\":\"V2lubmllIHRoZSBwb29oIVdpbm5pZSB0aGUgcG9vaCE=\"" \
548 "}]" \
549 "}";
550 const size_t kKeyTooLongResponseSize = keyTooLongResponse.size();
551
552 hidl_vec<uint8_t> invalidResponse;
553 invalidResponse.resize(kKeyTooLongResponseSize);
554 memcpy(invalidResponse.data(), keyTooLongResponse.c_str(), kKeyTooLongResponseSize);
555 decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples);
556 }
557
558 /**
559 * Instantiate the set of test cases for each vendor module
560 */
561
562 INSTANTIATE_TEST_CASE_P(
563 DrmHalTestClearkey, DrmHalTest,
564 testing::Values("clearkey"));
565
566 INSTANTIATE_TEST_CASE_P(
567 DrmHalTestClearkeyExtended, DrmHalClearkeyTest,
568 testing::Values("clearkey"));
569
570 INSTANTIATE_TEST_CASE_P(
571 DrmHalTestVendor, DrmHalTest,
572 testing::ValuesIn(DrmHalTest::gVendorModules->getPathList()));
573
main(int argc,char ** argv)574 int main(int argc, char** argv) {
575 #if defined(__LP64__)
576 const char* kModulePath = "/data/local/tmp/64/lib";
577 #else
578 const char* kModulePath = "/data/local/tmp/32/lib";
579 #endif
580 DrmHalTest::gVendorModules = new drm_vts::VendorModules(kModulePath);
581 if (DrmHalTest::gVendorModules->getPathList().size() == 0) {
582 std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
583 ", all vendor tests will be skipped" << std::endl;
584 }
585 ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
586 ::testing::InitGoogleTest(&argc, argv);
587 DrmHidlEnvironment::Instance()->init(&argc, argv);
588 int status = RUN_ALL_TESTS();
589 ALOGI("Test result = %d", status);
590 return status;
591 }
592