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