• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2017 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_vendor_test@1.0"
18  
19  #include <openssl/aes.h>
20  #include <random>
21  
22  #include "drm_hal_vendor_module_api.h"
23  #include "vendor_modules.h"
24  #include <VtsHalHidlTargetCallbackBase.h>
25  
26  #include "android/hardware/drm/1.0/vts/drm_hal_vendor_test.h"
27  
28  using std::random_device;
29  using std::mt19937;
30  
31  static const uint8_t kInvalidUUID[16] = {
32          0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
33          0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
34  };
35  
__anonc14513810102null36  static drm_vts::VendorModules* gVendorModules = [] {
37  #if defined(__LP64__)
38      const char* kModulePath = "/data/local/tmp/64/lib";
39  #else
40      const char* kModulePath = "/data/local/tmp/32/lib";
41  #endif
42      auto modules = new drm_vts::VendorModules(kModulePath);
43      if (modules->getPathList().size() == 0) {
44          std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
45                  ", all vendor tests will be skipped" << std::endl;
46      }
47      return modules;
48  }();
49  
50  namespace android {
51  namespace hardware {
52  namespace drm {
53  namespace V1_0 {
54  namespace vts {
55  
DrmHalVendorFactoryTest()56  DrmHalVendorFactoryTest::DrmHalVendorFactoryTest()
57       : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
58               gVendorModules->getModuleByName(GetParam().instance_))) {} // getModuleByName
59  
TEST_P(DrmHalVendorFactoryTest,ValidateConfigurations)60  TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
61      const char* kVendorStr = "Vendor module ";
62      size_t count = 0;
63      for (const auto& config : contentConfigurations) {
64          ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
65          ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
66                                                   << "has no serverUrl";
67          ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
68                                                  << "has no init data";
69          ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
70                                                  << "has no mime type";
71          ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
72          for (const auto& key : config.keys) {
73              ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
74                                                << " has zero length keyId";
75              ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
76                                                << " has zero length key value";
77          }
78          count++;
79      }
80      EXPECT_NE(0u, count);
81  }
82  
83  /**
84   * Ensure the factory doesn't support an invalid scheme UUID
85   */
TEST_P(DrmHalVendorFactoryTest,InvalidPluginNotSupported)86  TEST_P(DrmHalVendorFactoryTest, InvalidPluginNotSupported) {
87      EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID));
88      EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID));
89  }
90  
91  /**
92   * Ensure the factory doesn't support an empty UUID
93   */
TEST_P(DrmHalVendorFactoryTest,EmptyPluginUUIDNotSupported)94  TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
95      hidl_array<uint8_t, 16> emptyUUID;
96      memset(emptyUUID.data(), 0, 16);
97      EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
98      EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
99  }
100  
101  /**
102   * Check if the factory supports the scheme uuid in the config.
103   */
TEST_P(DrmHalVendorFactoryTest,PluginConfigUUIDSupported)104  TEST_P(DrmHalVendorFactoryTest, PluginConfigUUIDSupported) {
105      RETURN_IF_SKIPPED;
106      EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getUUID()));
107      EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getUUID()));
108  }
109  
110  /**
111   * Ensure empty content type is not supported
112   */
TEST_P(DrmHalVendorFactoryTest,EmptyContentTypeNotSupported)113  TEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) {
114      hidl_string empty;
115      EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
116  }
117  
118  /**
119   * Ensure invalid content type is not supported
120   */
TEST_P(DrmHalVendorFactoryTest,InvalidContentTypeNotSupported)121  TEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) {
122      hidl_string invalid("abcdabcd");
123      EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
124  }
125  
126  /**
127   * Ensure valid content types in the configs are supported
128   */
TEST_P(DrmHalVendorFactoryTest,ValidContentTypeSupported)129  TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
130      RETURN_IF_SKIPPED;
131      for (const auto& config : contentConfigurations) {
132          EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
133      }
134  }
135  
136  /**
137   * Ensure vendor drm plugin can be created
138   */
TEST_P(DrmHalVendorFactoryTest,CreateVendorDrmPlugin)139  TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
140      RETURN_IF_SKIPPED;
141      hidl_string packageName("android.hardware.drm.test");
142      auto res = drmFactory->createPlugin(
143              getUUID(), packageName,
144              [&](Status status, const sp<IDrmPlugin>& plugin) {
145                  EXPECT_EQ(Status::OK, status);
146                  EXPECT_NE(nullptr, plugin.get());
147              });
148      EXPECT_OK(res);
149  }
150  
151  /**
152   * Ensure vendor crypto plugin can be created
153   */
TEST_P(DrmHalVendorFactoryTest,CreateVendorCryptoPlugin)154  TEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) {
155      RETURN_IF_SKIPPED;
156      hidl_vec<uint8_t> initVec;
157      auto res = cryptoFactory->createPlugin(
158              getUUID(), initVec,
159              [&](Status status, const sp<ICryptoPlugin>& plugin) {
160                  EXPECT_EQ(Status::OK, status);
161                  EXPECT_NE(nullptr, plugin.get());
162              });
163      EXPECT_OK(res);
164  }
165  
166  /**
167   * Ensure invalid drm plugin can't be created
168   */
TEST_P(DrmHalVendorFactoryTest,CreateInvalidDrmPlugin)169  TEST_P(DrmHalVendorFactoryTest, CreateInvalidDrmPlugin) {
170      RETURN_IF_SKIPPED;
171      hidl_string packageName("android.hardware.drm.test");
172      auto res = drmFactory->createPlugin(
173              kInvalidUUID, packageName,
174              [&](Status status, const sp<IDrmPlugin>& plugin) {
175                  EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
176                  EXPECT_EQ(nullptr, plugin.get());
177              });
178      EXPECT_OK(res);
179  }
180  
181  /**
182   * Ensure invalid crypto plugin can't be created
183   */
TEST_P(DrmHalVendorFactoryTest,CreateInvalidCryptoPlugin)184  TEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) {
185      RETURN_IF_SKIPPED;
186      hidl_vec<uint8_t> initVec;
187      auto res = cryptoFactory->createPlugin(
188              kInvalidUUID, initVec,
189              [&](Status status, const sp<ICryptoPlugin>& plugin) {
190                  EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
191                  EXPECT_EQ(nullptr, plugin.get());
192              });
193      EXPECT_OK(res);
194  }
195  
196  /**
197   *  DrmPlugin tests
198   */
199  
200  /**
201   * Test that a DRM plugin can handle provisioning.  While
202   * it is not required that a DRM scheme require provisioning,
203   * it should at least return appropriate status values. If
204   * a provisioning request is returned, it is passed to the
205   * vendor module which should provide a provisioning response
206   * that is delivered back to the HAL.
207   */
208  
TEST_P(DrmHalVendorPluginTest,DoProvisioning)209  TEST_P(DrmHalVendorPluginTest, DoProvisioning) {
210      RETURN_IF_SKIPPED;
211      hidl_string certificateType;
212      hidl_string certificateAuthority;
213      hidl_vec<uint8_t> provisionRequest;
214      hidl_string defaultUrl;
215      auto res = drmPlugin->getProvisionRequest(
216              certificateType, certificateAuthority,
217              [&](Status status, const hidl_vec<uint8_t>& request,
218                  const hidl_string& url) {
219                  if (status == Status::OK) {
220                      EXPECT_NE(request.size(), 0u);
221                      provisionRequest = request;
222                      defaultUrl = url;
223                  } else if (status == Status::ERROR_DRM_CANNOT_HANDLE) {
224                      EXPECT_EQ(0u, request.size());
225                  }
226              });
227      EXPECT_OK(res);
228  
229      if (provisionRequest.size() > 0) {
230          vector<uint8_t> response = vendorModule->handleProvisioningRequest(
231                  provisionRequest, defaultUrl);
232          ASSERT_NE(0u, response.size());
233  
234          auto res = drmPlugin->provideProvisionResponse(
235                  response, [&](Status status, const hidl_vec<uint8_t>&,
236                                const hidl_vec<uint8_t>&) {
237                      EXPECT_EQ(Status::OK, status);
238                  });
239          EXPECT_OK(res);
240      }
241  }
242  
243  /**
244   * The DRM HAL should return BAD_VALUE if an empty provisioning
245   * response is provided.
246   */
TEST_P(DrmHalVendorPluginTest,ProvideEmptyProvisionResponse)247  TEST_P(DrmHalVendorPluginTest, ProvideEmptyProvisionResponse) {
248      RETURN_IF_SKIPPED;
249      hidl_vec<uint8_t> response;
250      auto res = drmPlugin->provideProvisionResponse(
251              response, [&](Status status, const hidl_vec<uint8_t>&,
252                            const hidl_vec<uint8_t>&) {
253                  EXPECT_EQ(Status::BAD_VALUE, status);
254              });
255      EXPECT_OK(res);
256  }
257  
258  /**
259   * Helper method to open a session and verify that a non-empty
260   * session ID is returned
261   */
openSession()262  SessionId DrmHalVendorPluginTest::openSession() {
263      SessionId sessionId;
264  
265      auto res = drmPlugin->openSession([&](Status status, const SessionId& id) {
266          EXPECT_EQ(Status::OK, status);
267          EXPECT_NE(id.size(), 0u);
268          sessionId = id;
269      });
270      EXPECT_OK(res);
271      return sessionId;
272  }
273  
274  /**
275   * Helper method to close a session
276   */
closeSession(const SessionId & sessionId)277  void DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) {
278      Status status = drmPlugin->closeSession(sessionId);
279      EXPECT_EQ(Status::OK, status);
280  }
281  
toHidlKeyedVector(const map<string,string> & params)282  KeyedVector DrmHalVendorPluginTest::toHidlKeyedVector(
283      const map<string, string>& params) {
284      std::vector<KeyValue> stdKeyedVector;
285      for (auto it = params.begin(); it != params.end(); ++it) {
286          KeyValue keyValue;
287          keyValue.key = it->first;
288          keyValue.value = it->second;
289          stdKeyedVector.push_back(keyValue);
290      }
291      return KeyedVector(stdKeyedVector);
292  }
293  
294  /**
295   * Helper method to load keys for subsequent decrypt tests.
296   * These tests use predetermined key request/response to
297   * avoid requiring a round trip to a license server.
298   */
loadKeys(const SessionId & sessionId,const ContentConfiguration & configuration,const KeyType & type=KeyType::STREAMING)299  hidl_vec<uint8_t> DrmHalVendorPluginTest::loadKeys(
300      const SessionId& sessionId, const ContentConfiguration& configuration,
301      const KeyType& type = KeyType::STREAMING) {
302      hidl_vec<uint8_t> keyRequest;
303      auto res = drmPlugin->getKeyRequest(
304          sessionId, configuration.initData, configuration.mimeType, type,
305          toHidlKeyedVector(configuration.optionalParameters),
306          [&](Status status, const hidl_vec<uint8_t>& request,
307              KeyRequestType type, const hidl_string&) {
308              EXPECT_EQ(Status::OK, status) << "Failed to get "
309                                               "key request for configuration "
310                                            << configuration.name;
311              EXPECT_EQ(type, KeyRequestType::INITIAL);
312              EXPECT_NE(request.size(), 0u) << "Expected key request size"
313                                               " to have length > 0 bytes";
314              keyRequest = request;
315          });
316      EXPECT_OK(res);
317  
318      /**
319       * Get key response from vendor module
320       */
321      hidl_vec<uint8_t> keyResponse =
322          vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
323  
324      EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
325                                           "to have length > 0 bytes";
326  
327      hidl_vec<uint8_t> keySetId;
328      res = drmPlugin->provideKeyResponse(
329          sessionId, keyResponse,
330          [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
331              EXPECT_EQ(Status::OK, status) << "Failure providing "
332                                               "key response for configuration "
333                                            << configuration.name;
334              keySetId = myKeySetId;
335          });
336      EXPECT_OK(res);
337      return keySetId;
338  }
339  
340  /**
341   * Test that a session can be opened and closed
342   */
TEST_P(DrmHalVendorPluginTest,OpenCloseSession)343  TEST_P(DrmHalVendorPluginTest, OpenCloseSession) {
344      RETURN_IF_SKIPPED;
345      auto sessionId = openSession();
346      closeSession(sessionId);
347  }
348  
349  /**
350   * Test that attempting to close an invalid (empty) sessionId
351   * is prohibited with the documented error code.
352   */
TEST_P(DrmHalVendorPluginTest,CloseInvalidSession)353  TEST_P(DrmHalVendorPluginTest, CloseInvalidSession) {
354      RETURN_IF_SKIPPED;
355      SessionId invalidSessionId;
356      Status status = drmPlugin->closeSession(invalidSessionId);
357      EXPECT_EQ(Status::BAD_VALUE, status);
358  }
359  
360  /**
361   * Test that attempting to close a valid session twice
362   * is prohibited with the documented error code.
363   */
TEST_P(DrmHalVendorPluginTest,CloseClosedSession)364  TEST_P(DrmHalVendorPluginTest, CloseClosedSession) {
365      RETURN_IF_SKIPPED;
366      auto sessionId = openSession();
367      closeSession(sessionId);
368      Status status = drmPlugin->closeSession(sessionId);
369      EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
370  }
371  
372  /**
373   * A get key request should fail if no sessionId is provided
374   */
TEST_P(DrmHalVendorPluginTest,GetKeyRequestNoSession)375  TEST_P(DrmHalVendorPluginTest, GetKeyRequestNoSession) {
376      RETURN_IF_SKIPPED;
377      SessionId invalidSessionId;
378      hidl_vec<uint8_t> initData;
379      hidl_string mimeType = "video/mp4";
380      KeyedVector optionalParameters;
381      auto res = drmPlugin->getKeyRequest(
382              invalidSessionId, initData, mimeType, KeyType::STREAMING,
383              optionalParameters,
384              [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
385                  const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
386      EXPECT_OK(res);
387  }
388  
389  /**
390   * Test that an empty sessionID returns BAD_VALUE
391   */
TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptySessionId)392  TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptySessionId) {
393      RETURN_IF_SKIPPED;
394      SessionId session;
395  
396      hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65,
397                                       0x79, 0x73, 0x22, 0x3a};
398      auto res = drmPlugin->provideKeyResponse(
399              session, keyResponse,
400              [&](Status status, const hidl_vec<uint8_t>& keySetId) {
401                  EXPECT_EQ(Status::BAD_VALUE, status);
402                  EXPECT_EQ(keySetId.size(), 0u);
403              });
404      EXPECT_OK(res);
405  }
406  
407  /**
408   * Test that an empty key response returns BAD_VALUE
409   */
TEST_P(DrmHalVendorPluginTest,ProvideKeyResponseEmptyResponse)410  TEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptyResponse) {
411      RETURN_IF_SKIPPED;
412      SessionId session = openSession();
413      hidl_vec<uint8_t> emptyResponse;
414      auto res = drmPlugin->provideKeyResponse(
415              session, emptyResponse,
416              [&](Status status, const hidl_vec<uint8_t>& keySetId) {
417                  EXPECT_EQ(Status::BAD_VALUE, status);
418                  EXPECT_EQ(keySetId.size(), 0u);
419              });
420      EXPECT_OK(res);
421      closeSession(session);
422  }
423  
424  /**
425   * Test that a removeKeys on an empty sessionID returns BAD_VALUE
426   */
TEST_P(DrmHalVendorPluginTest,RemoveKeysEmptySessionId)427  TEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) {
428      RETURN_IF_SKIPPED;
429      SessionId sessionId;
430      Status status = drmPlugin->removeKeys(sessionId);
431      EXPECT_TRUE(status == Status::BAD_VALUE);
432  }
433  
434  /**
435   * Test that remove keys returns okay on an initialized session
436   * that has no keys.
437   */
TEST_P(DrmHalVendorPluginTest,RemoveKeysNewSession)438  TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
439      RETURN_IF_SKIPPED;
440      SessionId sessionId = openSession();
441      Status status = drmPlugin->removeKeys(sessionId);
442      EXPECT_TRUE(status == Status::OK);
443      closeSession(sessionId);
444  }
445  
446  /**
447   * Test that keys are successfully restored to a new session
448   * for all content having a policy that allows offline use.
449   */
TEST_P(DrmHalVendorPluginTest,RestoreKeys)450  TEST_P(DrmHalVendorPluginTest, RestoreKeys) {
451      RETURN_IF_SKIPPED;
452      for (const auto& config : contentConfigurations) {
453          if (config.policy.allowOffline) {
454              auto sessionId = openSession();
455              hidl_vec<uint8_t> keySetId =
456                      loadKeys(sessionId, config, KeyType::OFFLINE);
457              closeSession(sessionId);
458              sessionId = openSession();
459              EXPECT_NE(0u, keySetId.size());
460              Status status = drmPlugin->restoreKeys(sessionId, keySetId);
461              EXPECT_EQ(Status::OK, status);
462              closeSession(sessionId);
463          }
464      }
465  }
466  
467  /**
468   * Test that restoreKeys fails with a null key set ID.
469   * Error message is expected to be Status::BAD_VALUE.
470   */
TEST_P(DrmHalVendorPluginTest,RestoreKeysNull)471  TEST_P(DrmHalVendorPluginTest, RestoreKeysNull) {
472      RETURN_IF_SKIPPED;
473      SessionId sessionId = openSession();
474      hidl_vec<uint8_t> nullKeySetId;
475      Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId);
476      EXPECT_EQ(Status::BAD_VALUE, status);
477      closeSession(sessionId);
478  }
479  
480  /**
481   * Test that restoreKeys fails to restore keys to a closed
482   * session. Error message is expected to be
483   * Status::ERROR_DRM_SESSION_NOT_OPENED.
484   */
TEST_P(DrmHalVendorPluginTest,RestoreKeysClosedSession)485  TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) {
486      RETURN_IF_SKIPPED;
487      for (const auto& config : contentConfigurations) {
488          if (config.policy.allowOffline) {
489              auto sessionId = openSession();
490              hidl_vec<uint8_t> keySetId =
491                      loadKeys(sessionId, config, KeyType::OFFLINE);
492              EXPECT_NE(0u, keySetId.size());
493              closeSession(sessionId);
494              sessionId = openSession();
495              closeSession(sessionId);
496              Status status = drmPlugin->restoreKeys(sessionId, keySetId);
497              EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
498          }
499      }
500  }
501  
502  /**
503   * Test that the plugin either doesn't support getting
504   * secure stops, or has no secure stops available after
505   * clearing them.
506   */
TEST_P(DrmHalVendorPluginTest,GetSecureStops)507  TEST_P(DrmHalVendorPluginTest, GetSecureStops) {
508      RETURN_IF_SKIPPED;
509      // There may be secure stops, depending on if there were keys
510      // loaded and unloaded previously. Clear them to get to a known
511      // state, then make sure there are none.
512      auto res = drmPlugin->getSecureStops(
513              [&](Status status, const hidl_vec<SecureStop>&) {
514                  if (status != Status::OK) {
515                      EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
516                  }
517              });
518      EXPECT_OK(res);
519  
520      res = drmPlugin->getSecureStops(
521              [&](Status status, const hidl_vec<SecureStop>& secureStops) {
522                  if (status == Status::OK) {
523                      EXPECT_EQ(secureStops.size(), 0u);
524                  } else {
525                      EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
526                  }
527              });
528      EXPECT_OK(res);
529  }
530  
531  /**
532   * Test that the clearkey plugin returns BAD_VALUE if
533   * an empty ssid is provided.
534   */
TEST_P(DrmHalVendorPluginTest,GetSecureStopEmptySSID)535  TEST_P(DrmHalVendorPluginTest, GetSecureStopEmptySSID) {
536      RETURN_IF_SKIPPED;
537      SecureStopId ssid;
538      auto res = drmPlugin->getSecureStop(
539              ssid, [&](Status status, const SecureStop&) {
540                  EXPECT_EQ(Status::BAD_VALUE, status);
541              });
542      EXPECT_OK(res);
543  }
544  
545  /**
546   * Test that releasing all secure stops either isn't supported
547   * or is completed successfully
548   */
TEST_P(DrmHalVendorPluginTest,ReleaseAllSecureStops)549  TEST_P(DrmHalVendorPluginTest, ReleaseAllSecureStops) {
550      RETURN_IF_SKIPPED;
551      Status status = drmPlugin->releaseAllSecureStops();
552      EXPECT_TRUE(status == Status::OK ||
553                  status == Status::ERROR_DRM_CANNOT_HANDLE);
554  }
555  
556  /**
557   * Releasing a secure stop without first getting one and sending it to the
558   * server to get a valid SSID should return ERROR_DRM_INVALID_STATE.
559   * This is an optional API so it can also return CANNOT_HANDLE.
560   */
TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopSequenceError)561  TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopSequenceError) {
562      RETURN_IF_SKIPPED;
563      SecureStopId ssid = {1, 2, 3, 4};
564      Status status = drmPlugin->releaseSecureStop(ssid);
565      EXPECT_TRUE(status == Status::ERROR_DRM_INVALID_STATE ||
566                  status == Status::ERROR_DRM_CANNOT_HANDLE);
567  }
568  
569  /**
570   * Test that releasing a specific secure stop with an empty ssid
571   * return BAD_VALUE. This is an optional API so it can also return
572   * CANNOT_HANDLE.
573   */
TEST_P(DrmHalVendorPluginTest,ReleaseSecureStopEmptySSID)574  TEST_P(DrmHalVendorPluginTest, ReleaseSecureStopEmptySSID) {
575      RETURN_IF_SKIPPED;
576      SecureStopId ssid;
577      Status status = drmPlugin->releaseSecureStop(ssid);
578      EXPECT_TRUE(status == Status::BAD_VALUE ||
579                  status == Status::ERROR_DRM_CANNOT_HANDLE);
580  }
581  
582  /**
583   * The following five tests verify that the properties
584   * defined in the MediaDrm API are supported by
585   * the plugin.
586   */
TEST_P(DrmHalVendorPluginTest,GetVendorProperty)587  TEST_P(DrmHalVendorPluginTest, GetVendorProperty) {
588      RETURN_IF_SKIPPED;
589      auto res = drmPlugin->getPropertyString(
590              "vendor", [&](Status status, const hidl_string& value) {
591                  EXPECT_EQ(Status::OK, status);
592                  EXPECT_NE(value.size(), 0u);
593              });
594      EXPECT_OK(res);
595  }
596  
TEST_P(DrmHalVendorPluginTest,GetVersionProperty)597  TEST_P(DrmHalVendorPluginTest, GetVersionProperty) {
598      RETURN_IF_SKIPPED;
599      auto res = drmPlugin->getPropertyString(
600              "version", [&](Status status, const hidl_string& value) {
601                  EXPECT_EQ(Status::OK, status);
602                  EXPECT_NE(value.size(), 0u);
603              });
604      EXPECT_OK(res);
605  }
606  
TEST_P(DrmHalVendorPluginTest,GetDescriptionProperty)607  TEST_P(DrmHalVendorPluginTest, GetDescriptionProperty) {
608      RETURN_IF_SKIPPED;
609      auto res = drmPlugin->getPropertyString(
610              "description", [&](Status status, const hidl_string& value) {
611                  EXPECT_EQ(Status::OK, status);
612                  EXPECT_NE(value.size(), 0u);
613              });
614      EXPECT_OK(res);
615  }
616  
TEST_P(DrmHalVendorPluginTest,GetAlgorithmsProperty)617  TEST_P(DrmHalVendorPluginTest, GetAlgorithmsProperty) {
618      RETURN_IF_SKIPPED;
619      auto res = drmPlugin->getPropertyString(
620              "algorithms", [&](Status status, const hidl_string& value) {
621                  if (status == Status::OK) {
622                      EXPECT_NE(value.size(), 0u);
623                  } else {
624                      EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
625                  }
626              });
627      EXPECT_OK(res);
628  }
629  
TEST_P(DrmHalVendorPluginTest,GetPropertyUniqueDeviceID)630  TEST_P(DrmHalVendorPluginTest, GetPropertyUniqueDeviceID) {
631      RETURN_IF_SKIPPED;
632      auto res = drmPlugin->getPropertyByteArray(
633              "deviceUniqueId",
634              [&](Status status, const hidl_vec<uint8_t>& value) {
635                  if (status == Status::OK) {
636                      EXPECT_NE(value.size(), 0u);
637                  } else {
638                      EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
639                  }
640              });
641      EXPECT_OK(res);
642  }
643  
644  /**
645   * Test that attempting to read invalid string and byte array
646   * properties returns the documented error code.
647   */
TEST_P(DrmHalVendorPluginTest,GetInvalidStringProperty)648  TEST_P(DrmHalVendorPluginTest, GetInvalidStringProperty) {
649      RETURN_IF_SKIPPED;
650      auto res = drmPlugin->getPropertyString(
651              "invalid", [&](Status status, const hidl_string&) {
652                  EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
653              });
654      EXPECT_OK(res);
655  }
656  
TEST_P(DrmHalVendorPluginTest,GetInvalidByteArrayProperty)657  TEST_P(DrmHalVendorPluginTest, GetInvalidByteArrayProperty) {
658      RETURN_IF_SKIPPED;
659      auto res = drmPlugin->getPropertyByteArray(
660              "invalid", [&](Status status, const hidl_vec<uint8_t>&) {
661                  EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
662              });
663      EXPECT_OK(res);
664  }
665  
666  /**
667   * Test that setting invalid string and byte array properties returns
668   * the expected status value.
669   */
TEST_P(DrmHalVendorPluginTest,SetStringPropertyNotSupported)670  TEST_P(DrmHalVendorPluginTest, SetStringPropertyNotSupported) {
671      RETURN_IF_SKIPPED;
672      EXPECT_EQ(drmPlugin->setPropertyString("awefijaeflijwef", "value"),
673                Status::ERROR_DRM_CANNOT_HANDLE);
674  }
675  
TEST_P(DrmHalVendorPluginTest,SetByteArrayPropertyNotSupported)676  TEST_P(DrmHalVendorPluginTest, SetByteArrayPropertyNotSupported) {
677      RETURN_IF_SKIPPED;
678      hidl_vec<uint8_t> value;
679      EXPECT_EQ(drmPlugin->setPropertyByteArray("awefijaeflijwef", value),
680                Status::ERROR_DRM_CANNOT_HANDLE);
681  }
682  
683  /**
684   * Test that setting an invalid cipher algorithm returns
685   * the expected status value.
686   */
TEST_P(DrmHalVendorPluginTest,SetCipherInvalidAlgorithm)687  TEST_P(DrmHalVendorPluginTest, SetCipherInvalidAlgorithm) {
688      RETURN_IF_SKIPPED;
689      SessionId session = openSession();
690      hidl_string algorithm;
691      Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
692      EXPECT_EQ(Status::BAD_VALUE, status);
693      closeSession(session);
694  }
695  
696  /**
697   * Test that setting a cipher algorithm with no session returns
698   * the expected status value.
699   */
TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithmNoSession)700  TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithmNoSession) {
701      RETURN_IF_SKIPPED;
702      SessionId session;
703      hidl_string algorithm = "AES/CBC/NoPadding";
704      Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
705      EXPECT_EQ(Status::BAD_VALUE, status);
706  }
707  
708  /**
709   * Test that setting a valid cipher algorithm returns
710   * the expected status value. It is not required that all
711   * vendor modules support this algorithm, but they must
712   * either accept it or return ERROR_DRM_CANNOT_HANDLE
713   */
TEST_P(DrmHalVendorPluginTest,SetCipherAlgorithm)714  TEST_P(DrmHalVendorPluginTest, SetCipherAlgorithm) {
715      RETURN_IF_SKIPPED;
716      SessionId session = openSession();
717      ;
718      hidl_string algorithm = "AES/CBC/NoPadding";
719      Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
720      EXPECT_TRUE(status == Status::OK ||
721                  status == Status::ERROR_DRM_CANNOT_HANDLE);
722      closeSession(session);
723  }
724  
725  /**
726   * Test that setting an invalid mac algorithm returns
727   * the expected status value.
728   */
TEST_P(DrmHalVendorPluginTest,SetMacInvalidAlgorithm)729  TEST_P(DrmHalVendorPluginTest, SetMacInvalidAlgorithm) {
730      RETURN_IF_SKIPPED;
731      SessionId session = openSession();
732      hidl_string algorithm;
733      Status status = drmPlugin->setMacAlgorithm(session, algorithm);
734      EXPECT_EQ(Status::BAD_VALUE, status);
735      closeSession(session);
736  }
737  
738  /**
739   * Test that setting a mac algorithm with no session returns
740   * the expected status value.
741   */
TEST_P(DrmHalVendorPluginTest,SetMacNullAlgorithmNoSession)742  TEST_P(DrmHalVendorPluginTest, SetMacNullAlgorithmNoSession) {
743      RETURN_IF_SKIPPED;
744      SessionId session;
745      hidl_string algorithm = "HmacSHA256";
746      Status status = drmPlugin->setMacAlgorithm(session, algorithm);
747      EXPECT_EQ(Status::BAD_VALUE, status);
748  }
749  
750  /**
751   * Test that setting a valid mac algorithm returns
752   * the expected status value. It is not required that all
753   * vendor modules support this algorithm, but they must
754   * either accept it or return ERROR_DRM_CANNOT_HANDLE
755   */
TEST_P(DrmHalVendorPluginTest,SetMacAlgorithm)756  TEST_P(DrmHalVendorPluginTest, SetMacAlgorithm) {
757      RETURN_IF_SKIPPED;
758      SessionId session = openSession();
759      hidl_string algorithm = "HmacSHA256";
760      Status status = drmPlugin->setMacAlgorithm(session, algorithm);
761      EXPECT_TRUE(status == Status::OK ||
762                  status == Status::ERROR_DRM_CANNOT_HANDLE);
763      closeSession(session);
764  }
765  
766  /**
767   * The Generic* methods provide general purpose crypto operations
768   * that may be used for applications other than DRM. They leverage
769   * the hardware root of trust and secure key distribution mechanisms
770   * of a DRM system to enable app-specific crypto functionality where
771   * the crypto keys are not exposed outside of the trusted execution
772   * environment.
773   *
774   * Generic encrypt/decrypt/sign/verify should fail on invalid
775   * inputs, e.g. empty sessionId
776   */
TEST_P(DrmHalVendorPluginTest,GenericEncryptNoSession)777  TEST_P(DrmHalVendorPluginTest, GenericEncryptNoSession) {
778      RETURN_IF_SKIPPED;
779      SessionId session;
780      hidl_vec<uint8_t> keyId, input, iv;
781      auto res = drmPlugin->encrypt(
782              session, keyId, input, iv,
783              [&](Status status, const hidl_vec<uint8_t>&) {
784                  EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
785              });
786      EXPECT_OK(res);
787  }
788  
TEST_P(DrmHalVendorPluginTest,GenericDecryptNoSession)789  TEST_P(DrmHalVendorPluginTest, GenericDecryptNoSession) {
790      RETURN_IF_SKIPPED;
791      SessionId session;
792      hidl_vec<uint8_t> keyId, input, iv;
793      auto res = drmPlugin->decrypt(
794              session, keyId, input, iv,
795              [&](Status status, const hidl_vec<uint8_t>&) {
796                  EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
797              });
798      EXPECT_OK(res);
799  }
800  
TEST_P(DrmHalVendorPluginTest,GenericSignNoSession)801  TEST_P(DrmHalVendorPluginTest, GenericSignNoSession) {
802      RETURN_IF_SKIPPED;
803      SessionId session;
804      hidl_vec<uint8_t> keyId, message;
805      auto res = drmPlugin->sign(
806              session, keyId, message,
807              [&](Status status, const hidl_vec<uint8_t>&) {
808                  EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
809              });
810      EXPECT_OK(res);
811  }
812  
TEST_P(DrmHalVendorPluginTest,GenericVerifyNoSession)813  TEST_P(DrmHalVendorPluginTest, GenericVerifyNoSession) {
814      RETURN_IF_SKIPPED;
815      SessionId session;
816      hidl_vec<uint8_t> keyId, message, signature;
817      auto res = drmPlugin->verify(
818              session, keyId, message, signature, [&](Status status, bool) {
819                  EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
820              });
821      EXPECT_OK(res);
822  }
823  
TEST_P(DrmHalVendorPluginTest,GenericSignRSANoSession)824  TEST_P(DrmHalVendorPluginTest, GenericSignRSANoSession) {
825      RETURN_IF_SKIPPED;
826      SessionId session;
827      hidl_string algorithm;
828      hidl_vec<uint8_t> message, wrappedKey;
829      auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey,
830                                    [&](Status status, const hidl_vec<uint8_t>&) {
831                                        EXPECT_EQ(Status::BAD_VALUE, status);
832                                    });
833      EXPECT_OK(res);
834  }
835  
836  /**
837   * Exercise the requiresSecureDecoderComponent method. Additional tests
838   * will verify positive cases with specific vendor content configurations.
839   * Below we just test the negative cases.
840   */
841  
842  /**
843   * Verify that requiresSecureDecoderComponent handles empty mimetype.
844   */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderEmptyMimeType)845  TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderEmptyMimeType) {
846      RETURN_IF_SKIPPED;
847      EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent(""));
848  }
849  
850  /**
851   * Verify that requiresSecureDecoderComponent handles invalid mimetype.
852   */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderInvalidMimeType)853  TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) {
854      RETURN_IF_SKIPPED;
855      EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("bad"));
856  }
857  
858  /**
859   * Verify that requiresSecureDecoderComponent returns true for secure
860   * configurations
861   */
TEST_P(DrmHalVendorPluginTest,RequiresSecureDecoderConfig)862  TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
863      RETURN_IF_SKIPPED;
864      for (const auto& config : contentConfigurations) {
865          for (const auto& key : config.keys) {
866              if (key.isSecure) {
867                  EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
868                  break;
869              }
870          }
871      }
872  }
873  
874  /**
875   *  Event Handling tests
876   */
877  struct ListenerEventArgs {
878      EventType eventType;
879      SessionId sessionId;
880      hidl_vec<uint8_t> data;
881      int64_t expiryTimeInMS;
882      hidl_vec<KeyStatus> keyStatusList;
883      bool hasNewUsableKey;
884  };
885  
886  const char *kCallbackEvent = "SendEvent";
887  const char *kCallbackExpirationUpdate = "SendExpirationUpdate";
888  const char *kCallbackKeysChange = "SendKeysChange";
889  
890  class TestDrmPluginListener
891      : public ::testing::VtsHalHidlTargetCallbackBase<ListenerEventArgs>,
892        public IDrmPluginListener {
893  public:
TestDrmPluginListener()894      TestDrmPluginListener() {
895          SetWaitTimeoutDefault(std::chrono::milliseconds(500));
896      }
~TestDrmPluginListener()897      virtual ~TestDrmPluginListener() {}
898  
sendEvent(EventType eventType,const hidl_vec<uint8_t> & sessionId,const hidl_vec<uint8_t> & data)899      virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
900              const hidl_vec<uint8_t>& data) override {
901          ListenerEventArgs args;
902          args.eventType = eventType;
903          args.sessionId = sessionId;
904          args.data = data;
905          NotifyFromCallback(kCallbackEvent, args);
906          return Void();
907      }
908  
sendExpirationUpdate(const hidl_vec<uint8_t> & sessionId,int64_t expiryTimeInMS)909      virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
910              int64_t expiryTimeInMS) override {
911          ListenerEventArgs args;
912          args.sessionId = sessionId;
913          args.expiryTimeInMS = expiryTimeInMS;
914          NotifyFromCallback(kCallbackExpirationUpdate, args);
915          return Void();
916      }
917  
sendKeysChange(const hidl_vec<uint8_t> & sessionId,const hidl_vec<KeyStatus> & keyStatusList,bool hasNewUsableKey)918      virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
919              const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override {
920          ListenerEventArgs args;
921          args.sessionId = sessionId;
922          args.keyStatusList = keyStatusList;
923          args.hasNewUsableKey = hasNewUsableKey;
924          NotifyFromCallback(kCallbackKeysChange, args);
925          return Void();
926      }
927  };
928  
929  
930  /**
931   * Simulate the plugin sending events. Make sure the listener
932   * gets them.
933   */
TEST_P(DrmHalVendorPluginTest,ListenerEvents)934  TEST_P(DrmHalVendorPluginTest, ListenerEvents) {
935      RETURN_IF_SKIPPED;
936      sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
937      drmPlugin->setListener(listener);
938      auto sessionId = openSession();
939      hidl_vec<uint8_t> data = {0, 1, 2};
940      EventType eventTypes[] = {EventType::PROVISION_REQUIRED,
941                                EventType::KEY_NEEDED,
942                                EventType::KEY_EXPIRED,
943                                EventType::VENDOR_DEFINED,
944                                EventType::SESSION_RECLAIMED};
945      for (auto eventType : eventTypes) {
946          drmPlugin->sendEvent(eventType, sessionId, data);
947          auto result = listener->WaitForCallback(kCallbackEvent);
948          EXPECT_TRUE(result.no_timeout);
949          EXPECT_TRUE(result.args);
950          EXPECT_EQ(eventType, result.args->eventType);
951          EXPECT_EQ(sessionId, result.args->sessionId);
952          EXPECT_EQ(data, result.args->data);
953      }
954      closeSession(sessionId);
955  }
956  
957  /**
958   * Simulate the plugin sending expiration updates and make sure
959   * the listener gets them.
960   */
TEST_P(DrmHalVendorPluginTest,ListenerExpirationUpdate)961  TEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) {
962      RETURN_IF_SKIPPED;
963      sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
964      drmPlugin->setListener(listener);
965      auto sessionId = openSession();
966      drmPlugin->sendExpirationUpdate(sessionId, 100);
967      auto result = listener->WaitForCallback(kCallbackExpirationUpdate);
968      EXPECT_TRUE(result.no_timeout);
969      EXPECT_TRUE(result.args);
970      EXPECT_EQ(sessionId, result.args->sessionId);
971      EXPECT_EQ(100, result.args->expiryTimeInMS);
972      closeSession(sessionId);
973  }
974  
975  /**
976   * Simulate the plugin sending keys change and make sure
977   * the listener gets them.
978   */
TEST_P(DrmHalVendorPluginTest,ListenerKeysChange)979  TEST_P(DrmHalVendorPluginTest, ListenerKeysChange) {
980      RETURN_IF_SKIPPED;
981      sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
982      drmPlugin->setListener(listener);
983      auto sessionId = openSession();
984      const hidl_vec<KeyStatus> keyStatusList = {
985          {{1}, KeyStatusType::USABLE},
986          {{2}, KeyStatusType::EXPIRED},
987          {{3}, KeyStatusType::OUTPUTNOTALLOWED},
988          {{4}, KeyStatusType::STATUSPENDING},
989          {{5}, KeyStatusType::INTERNALERROR},
990      };
991  
992      drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
993      auto result = listener->WaitForCallback(kCallbackKeysChange);
994      EXPECT_TRUE(result.no_timeout);
995      EXPECT_TRUE(result.args);
996      EXPECT_EQ(sessionId, result.args->sessionId);
997      EXPECT_EQ(keyStatusList, result.args->keyStatusList);
998      closeSession(sessionId);
999  }
1000  
1001  /**
1002   * Negative listener tests. Call send methods with no
1003   * listener set.
1004   */
TEST_P(DrmHalVendorPluginTest,NotListening)1005  TEST_P(DrmHalVendorPluginTest, NotListening) {
1006      RETURN_IF_SKIPPED;
1007      sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
1008      drmPlugin->setListener(listener);
1009      drmPlugin->setListener(nullptr);
1010  
1011      SessionId sessionId;
1012      hidl_vec<uint8_t> data;
1013      hidl_vec<KeyStatus> keyStatusList;
1014      drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data);
1015      drmPlugin->sendExpirationUpdate(sessionId, 100);
1016      drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
1017      auto result = listener->WaitForCallbackAny(
1018              {kCallbackEvent, kCallbackExpirationUpdate, kCallbackKeysChange});
1019      EXPECT_FALSE(result.no_timeout);
1020  }
1021  
1022  
1023  /**
1024   *  CryptoPlugin tests
1025   */
1026  
1027  /**
1028   * Exercise the NotifyResolution API. There is no observable result,
1029   * just call the method for coverage.
1030   */
TEST_P(DrmHalVendorPluginTest,NotifyResolution)1031  TEST_P(DrmHalVendorPluginTest, NotifyResolution) {
1032      RETURN_IF_SKIPPED;
1033      cryptoPlugin->notifyResolution(1920, 1080);
1034  }
1035  
1036  /**
1037   * getDecryptMemory allocates memory for decryption, then sets it
1038   * as a shared buffer base in the crypto hal.  The allocated and
1039   * mapped IMemory is returned.
1040   *
1041   * @param size the size of the memory segment to allocate
1042   * @param the index of the memory segment which will be used
1043   * to refer to it for decryption.
1044   */
getDecryptMemory(size_t size,size_t index)1045  sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
1046                                                       size_t index) {
1047      sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
1048      EXPECT_NE(nullptr, ashmemAllocator.get());
1049  
1050      hidl_memory hidlMemory;
1051      auto res = ashmemAllocator->allocate(
1052              size, [&](bool success, const hidl_memory& memory) {
1053                  EXPECT_EQ(success, true);
1054                  EXPECT_EQ(memory.size(), size);
1055                  hidlMemory = memory;
1056              });
1057  
1058      EXPECT_OK(res);
1059  
1060      sp<IMemory> mappedMemory = android::hardware::mapMemory(hidlMemory);
1061      EXPECT_NE(nullptr, mappedMemory.get());
1062      res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
1063      EXPECT_OK(res);
1064      return mappedMemory;
1065  }
1066  
1067  /**
1068   * Exercise the setMediaDrmSession method. setMediaDrmSession
1069   * is used to associate a drm session with a crypto session.
1070   */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSession)1071  TEST_P(DrmHalVendorPluginTest, SetMediaDrmSession) {
1072      RETURN_IF_SKIPPED;
1073      auto sessionId = openSession();
1074      Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1075      EXPECT_EQ(Status::OK, status);
1076      closeSession(sessionId);
1077  }
1078  
1079  /**
1080   * setMediaDrmSession with a closed session id
1081   */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionClosedSession)1082  TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionClosedSession) {
1083      RETURN_IF_SKIPPED;
1084      auto sessionId = openSession();
1085      closeSession(sessionId);
1086      Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1087      EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
1088  }
1089  
1090  /**
1091   * setMediaDrmSession with a empty session id: BAD_VALUE
1092   */
TEST_P(DrmHalVendorPluginTest,SetMediaDrmSessionEmptySession)1093  TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
1094      RETURN_IF_SKIPPED;
1095      SessionId sessionId;
1096      Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1097      EXPECT_EQ(Status::BAD_VALUE, status);
1098  }
1099  
1100  /**
1101   * Decrypt tests
1102   */
1103  
fillRandom(const sp<IMemory> & memory)1104  void DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) {
1105      random_device rd;
1106      mt19937 rand(rd());
1107      for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) {
1108          auto p = static_cast<uint32_t*>(
1109                  static_cast<void*>(memory->getPointer()));
1110          p[i] = rand();
1111      }
1112  }
1113  
queryKeyStatus(SessionId sessionId)1114  hidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) {
1115      hidl_vec<KeyValue> keyStatus;
1116      auto res = drmPlugin->queryKeyStatus(sessionId,
1117              [&](Status status, KeyedVector info) {
1118                  EXPECT_EQ(Status::OK, status);
1119                  keyStatus = info;
1120              });
1121      EXPECT_OK(res);
1122      return keyStatus;
1123  }
1124  
removeKeys(SessionId sessionId)1125  void DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) {
1126      auto res = drmPlugin->removeKeys(sessionId);
1127      EXPECT_OK(res);
1128  }
1129  
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,Status expectedStatus)1130  uint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure,
1131          const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
1132          const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
1133          const vector<uint8_t>& key, Status expectedStatus) {
1134      const size_t kSegmentIndex = 0;
1135  
1136      uint8_t localIv[AES_BLOCK_SIZE];
1137      memcpy(localIv, iv, AES_BLOCK_SIZE);
1138  
1139      size_t totalSize = 0;
1140      for (size_t i = 0; i < subSamples.size(); i++) {
1141          totalSize += subSamples[i].numBytesOfClearData;
1142          totalSize += subSamples[i].numBytesOfEncryptedData;
1143      }
1144  
1145      // The first totalSize bytes of shared memory is the encrypted
1146      // input, the second totalSize bytes is the decrypted output.
1147      sp<IMemory> sharedMemory =
1148              getDecryptMemory(totalSize * 2, kSegmentIndex);
1149  
1150      SharedBuffer sourceBuffer = {
1151              .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
1152      fillRandom(sharedMemory);
1153  
1154      DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
1155                                      {.bufferId = kSegmentIndex,
1156                                       .offset = totalSize,
1157                                       .size = totalSize},
1158                                      .secureMemory = nullptr};
1159      uint64_t offset = 0;
1160      uint32_t bytesWritten = 0;
1161      auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern,
1162              subSamples, sourceBuffer, offset, destBuffer,
1163              [&](Status status, uint32_t count, string detailedError) {
1164                  EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
1165                  detailedError;
1166                  bytesWritten = count;
1167              });
1168      EXPECT_OK(res);
1169  
1170      if (bytesWritten != totalSize) {
1171          return bytesWritten;
1172      }
1173      uint8_t* base = static_cast<uint8_t*>(
1174              static_cast<void*>(sharedMemory->getPointer()));
1175  
1176      // generate reference vector
1177      vector<uint8_t> reference(totalSize);
1178  
1179      memcpy(localIv, iv, AES_BLOCK_SIZE);
1180      switch (mode) {
1181      case Mode::UNENCRYPTED:
1182          memcpy(&reference[0], base, totalSize);
1183          break;
1184      case Mode::AES_CTR:
1185          aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
1186          break;
1187      case Mode::AES_CBC:
1188          aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
1189          break;
1190      case Mode::AES_CBC_CTS:
1191          EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
1192          break;
1193      }
1194  
1195      // compare reference to decrypted data which is at base + total size
1196      EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]),
1197                          static_cast<void*>(base + totalSize), totalSize))
1198              << "decrypt data mismatch";
1199      return totalSize;
1200  }
1201  
1202  /**
1203   * Decrypt a list of clear+encrypted subsamples using the specified key
1204   * in AES-CTR mode
1205   */
aes_ctr_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1206  void DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
1207          uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1208          const vector<uint8_t>& key) {
1209  
1210      AES_KEY decryptionKey;
1211      AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1212  
1213      size_t offset = 0;
1214      unsigned blockOffset = 0;
1215      uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
1216      memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
1217  
1218      for (size_t i = 0; i < subSamples.size(); i++) {
1219          const SubSample& subSample = subSamples[i];
1220  
1221          if (subSample.numBytesOfClearData > 0) {
1222              memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1223              offset += subSample.numBytesOfClearData;
1224          }
1225  
1226          if (subSample.numBytesOfEncryptedData > 0) {
1227              AES_ctr128_encrypt(src + offset, dest + offset,
1228                      subSample.numBytesOfEncryptedData, &decryptionKey,
1229                      iv, previousEncryptedCounter, &blockOffset);
1230              offset += subSample.numBytesOfEncryptedData;
1231          }
1232      }
1233  }
1234  
1235  /**
1236   * Decrypt a list of clear+encrypted subsamples using the specified key
1237   * in AES-CBC mode
1238   */
aes_cbc_decrypt(uint8_t * dest,uint8_t * src,uint8_t * iv,const hidl_vec<SubSample> & subSamples,const vector<uint8_t> & key)1239  void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
1240          uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1241          const vector<uint8_t>& key) {
1242      AES_KEY decryptionKey;
1243      AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1244  
1245      size_t offset = 0;
1246      for (size_t i = 0; i < subSamples.size(); i++) {
1247          const SubSample& subSample = subSamples[i];
1248  
1249          memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1250          offset += subSample.numBytesOfClearData;
1251  
1252          AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData,
1253                  &decryptionKey, iv, 0 /* decrypt */);
1254          offset += subSample.numBytesOfEncryptedData;
1255      }
1256  }
1257  
1258  
1259  /**
1260   * Test key status with empty session id, should return BAD_VALUE
1261   */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusInvalidSession)1262  TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) {
1263      RETURN_IF_SKIPPED;
1264      SessionId sessionId;
1265      auto res = drmPlugin->queryKeyStatus(sessionId,
1266              [&](Status status, KeyedVector /* info */) {
1267                  EXPECT_EQ(Status::BAD_VALUE, status);
1268              });
1269      EXPECT_OK(res);
1270  }
1271  
1272  
1273  /**
1274   * Test key status.  There should be no key status prior to loading keys
1275   */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatusWithNoKeys)1276  TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) {
1277      RETURN_IF_SKIPPED;
1278      auto sessionId = openSession();
1279      auto keyStatus = queryKeyStatus(sessionId);
1280      EXPECT_EQ(0u, keyStatus.size());
1281      closeSession(sessionId);
1282  }
1283  
1284  
1285  /**
1286   * Test key status.  There should be key status after loading keys.
1287   */
TEST_P(DrmHalVendorDecryptTest,QueryKeyStatus)1288  TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
1289      RETURN_IF_SKIPPED;
1290      for (const auto& config : contentConfigurations) {
1291          auto sessionId = openSession();
1292          loadKeys(sessionId, config);
1293          auto keyStatus = queryKeyStatus(sessionId);
1294          EXPECT_NE(0u, keyStatus.size());
1295          closeSession(sessionId);
1296      }
1297  }
1298  
1299  /**
1300   * Positive decrypt test. "Decrypt" a single clear segment and verify.
1301   */
TEST_P(DrmHalVendorDecryptTest,ClearSegmentTest)1302  TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
1303      RETURN_IF_SKIPPED;
1304      for (const auto& config : contentConfigurations) {
1305          for (const auto& key : config.keys) {
1306              const size_t kSegmentSize = 1024;
1307              vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1308              const Pattern noPattern = {0, 0};
1309              const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1310                                                     .numBytesOfEncryptedData = 0}};
1311              auto sessionId = openSession();
1312              loadKeys(sessionId, config);
1313  
1314              Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1315              EXPECT_EQ(Status::OK, status);
1316  
1317              uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
1318                      &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1319              EXPECT_EQ(kSegmentSize, byteCount);
1320  
1321              closeSession(sessionId);
1322          }
1323      }
1324  }
1325  
1326  /**
1327   * Positive decrypt test.  Decrypt a single segment using aes_ctr.
1328   * Verify data matches.
1329   */
TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTest)1330  TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
1331      RETURN_IF_SKIPPED;
1332      for (const auto& config : contentConfigurations) {
1333          for (const auto& key : config.keys) {
1334              const size_t kSegmentSize = 1024;
1335              vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1336              const Pattern noPattern = {0, 0};
1337              const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1338                                                     .numBytesOfEncryptedData = 0}};
1339              auto sessionId = openSession();
1340              loadKeys(sessionId, config);
1341  
1342              Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1343              EXPECT_EQ(Status::OK, status);
1344  
1345              uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
1346                      &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1347              EXPECT_EQ(kSegmentSize, byteCount);
1348  
1349              closeSession(sessionId);
1350          }
1351      }
1352  }
1353  
1354  /**
1355   * Negative decrypt test. Decrypt without loading keys.
1356   */
TEST_P(DrmHalVendorDecryptTest,EncryptedAesCtrSegmentTestNoKeys)1357  TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
1358      RETURN_IF_SKIPPED;
1359      for (const auto& config : contentConfigurations) {
1360          for (const auto& key : config.keys) {
1361              vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1362              const Pattern noPattern = {0, 0};
1363              const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1364                                                     .numBytesOfEncryptedData = 256}};
1365              auto sessionId = openSession();
1366  
1367              Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1368              EXPECT_EQ(Status::OK, status);
1369  
1370              uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1371                      toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1372                      key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1373              EXPECT_EQ(0u, byteCount);
1374  
1375              closeSession(sessionId);
1376          }
1377      }
1378  }
1379  
1380  /**
1381   * Test key removal.  Load keys then remove them and verify that
1382   * decryption can't be performed.
1383   */
TEST_P(DrmHalVendorDecryptTest,AttemptDecryptWithKeysRemoved)1384  TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
1385      RETURN_IF_SKIPPED;
1386      for (const auto& config : contentConfigurations) {
1387          for (const auto& key : config.keys) {
1388              vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1389              const Pattern noPattern = {0, 0};
1390              const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1391                                                     .numBytesOfEncryptedData = 256}};
1392              auto sessionId = openSession();
1393  
1394              Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1395              EXPECT_EQ(Status::OK, status);
1396  
1397              loadKeys(sessionId, config);
1398              removeKeys(sessionId);
1399  
1400              uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1401                      toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1402                      key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1403              EXPECT_EQ(0u, byteCount);
1404  
1405              closeSession(sessionId);
1406          }
1407      }
1408  }
1409  
1410  }  // namespace vts
1411  }  // namespace V1_0
1412  }  // namespace drm
1413  }  // namespace hardware
1414  }  // namespace android
1415