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