SessionId openSession();
void closeSession(const SessionId& sessionId);
+ hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
sp<IMemory> getDecryptMemory(size_t size, size_t index);
protected:
}
/**
+ * Helper method to load keys for subsequent decrypt tests.
+ * These tests use predetermined key request/response to
+ * avoid requiring a round trip to a license server.
+ */
+hidl_vec<uint8_t> DrmHalClearkeyPluginTest::loadKeys(
+ const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
+ hidl_vec<uint8_t> initData = {
+ // BMFF box header (4 bytes size + 'pssh')
+ 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
+ // full box header (version = 1 flags = 0)
+ 0x01, 0x00, 0x00, 0x00,
+ // system id
+ 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e,
+ 0x52, 0xe2, 0xfb, 0x4b,
+ // number of key ids
+ 0x00, 0x00, 0x00, 0x01,
+ // key id
+ 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
+ 0x1e, 0xd0, 0x0d, 0x1e,
+ // size of data, must be zero
+ 0x00, 0x00, 0x00, 0x00};
+
+ hidl_vec<uint8_t> expectedKeyRequest = {
+ 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59,
+ 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b,
+ 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22,
+ 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x74,
+ 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
+
+ hidl_vec<uint8_t> knownKeyResponse = {
+ 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22,
+ 0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c,
+ 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65,
+ 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b, 0x56, 0x39, 0x41,
+ 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b,
+ 0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65,
+ 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34,
+ 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
+
+ hidl_string mimeType = "video/mp4";
+ KeyedVector optionalParameters;
+ auto res = drmPlugin->getKeyRequest(
+ sessionId, initData, mimeType, type, optionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& request,
+ KeyRequestType requestType, const hidl_string&) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(KeyRequestType::INITIAL, requestType);
+ EXPECT_EQ(request, expectedKeyRequest);
+ });
+ EXPECT_OK(res);
+
+ hidl_vec<uint8_t> keySetId;
+ res = drmPlugin->provideKeyResponse(
+ sessionId, knownKeyResponse,
+ [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, myKeySetId.size());
+ keySetId = myKeySetId;
+ });
+ EXPECT_OK(res);
+ return keySetId;
+}
+
+/**
* Test that a session can be opened and closed
*/
TEST_F(DrmHalClearkeyPluginTest, OpenCloseSession) {
}
/**
+ * Test that ClearKey cannot handle key restoring.
+ * Expected message is Status::ERROR_DRM_CANNOT_HANDLE.
+ */
+TEST_F(DrmHalClearkeyPluginTest, RestoreKeysCannotHandle) {
+ hidl_vec<uint8_t> keySetId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ SessionId sessionId = openSession();
+ Status status = drmPlugin->restoreKeys(sessionId, keySetId);
+ EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+ closeSession(sessionId);
+}
+
+/**
+ * Test that restoreKeys fails with a null key set ID.
+ * Error message is expected to be Status::BAD_VALUE.
+ */
+TEST_F(DrmHalClearkeyPluginTest, RestoreKeysNull) {
+ SessionId sessionId = openSession();
+ hidl_vec<uint8_t> nullKeySetId;
+ Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId);
+ EXPECT_EQ(Status::BAD_VALUE, status);
+ closeSession(sessionId);
+}
+
+/**
* Test that the clearkey plugin doesn't support getting
* secure stops.
*/
class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest {
public:
- void loadKeys(const SessionId& sessionId);
void fillRandom(const sp<IMemory>& memory);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(16u, vec.size());
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
};
-/**
- * Helper method to load keys for subsequent decrypt tests.
- * These tests use predetermined key request/response to
- * avoid requiring a round trip to a license server.
- */
-void DrmHalClearkeyDecryptTest::loadKeys(const SessionId& sessionId) {
- hidl_vec<uint8_t> initData = {
- // BMFF box header (4 bytes size + 'pssh')
- 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
- // full box header (version = 1 flags = 0)
- 0x01, 0x00, 0x00, 0x00,
- // system id
- 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
- 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
- // number of key ids
- 0x00, 0x00, 0x00, 0x01,
- // key id
- 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
- 0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
- // size of data, must be zero
- 0x00, 0x00, 0x00, 0x00};
-
- hidl_vec<uint8_t> expectedKeyRequest = {
- 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59,
- 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b,
- 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22,
- 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x74,
- 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
-
- hidl_vec<uint8_t> knownKeyResponse = {
- 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22,
- 0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c,
- 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65,
- 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2b, 0x56, 0x39, 0x41,
- 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b,
- 0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65,
- 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34,
- 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
-
- hidl_string mimeType = "video/mp4";
- KeyedVector optionalParameters;
- auto res = drmPlugin->getKeyRequest(
- sessionId, initData, mimeType, KeyType::STREAMING,
- optionalParameters,
- [&](Status status, const hidl_vec<uint8_t>& request,
- KeyRequestType requestType, const hidl_string&) {
- EXPECT_EQ(Status::OK, status);
- EXPECT_EQ(KeyRequestType::INITIAL, requestType);
- EXPECT_EQ(request, expectedKeyRequest);
- });
- EXPECT_OK(res);
-
- res = drmPlugin->provideKeyResponse(
- sessionId, knownKeyResponse,
- [&](Status status, const hidl_vec<uint8_t>& keySetId) {
- EXPECT_EQ(Status::OK, status);
- EXPECT_EQ(0u, keySetId.size());
- });
- EXPECT_OK(res);
-}
-
void DrmHalClearkeyDecryptTest::fillRandom(const sp<IMemory>& memory) {
random_device rd;
mt19937 rand(rd());
TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
const char* kVendorStr = "Vendor module ";
+ size_t count = 0;
for (auto config : contentConfigurations) {
ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
<< " has zero length key value";
}
+ count++;
}
+ EXPECT_NE(0u, count);
}
/**
SessionId openSession();
void closeSession(const SessionId& sessionId);
sp<IMemory> getDecryptMemory(size_t size, size_t index);
+ KeyedVector toHidlKeyedVector(const map<string, string>& params);
+ hidl_vec<uint8_t> loadKeys(const SessionId& sessionId,
+ const ContentConfiguration& configuration,
+ const KeyType& type);
protected:
sp<IDrmPlugin> drmPlugin;
EXPECT_EQ(Status::OK, status);
}
+KeyedVector DrmHalVendorPluginTest::toHidlKeyedVector(
+ const map<string, string>& params) {
+ std::vector<KeyValue> stdKeyedVector;
+ for (auto it = params.begin(); it != params.end(); ++it) {
+ KeyValue keyValue;
+ keyValue.key = it->first;
+ keyValue.value = it->second;
+ stdKeyedVector.push_back(keyValue);
+ }
+ return KeyedVector(stdKeyedVector);
+}
+
+/**
+ * Helper method to load keys for subsequent decrypt tests.
+ * These tests use predetermined key request/response to
+ * avoid requiring a round trip to a license server.
+ */
+hidl_vec<uint8_t> DrmHalVendorPluginTest::loadKeys(
+ const SessionId& sessionId, const ContentConfiguration& configuration,
+ const KeyType& type = KeyType::STREAMING) {
+ hidl_vec<uint8_t> keyRequest;
+ auto res = drmPlugin->getKeyRequest(
+ sessionId, configuration.initData, configuration.mimeType, type,
+ toHidlKeyedVector(configuration.optionalParameters),
+ [&](Status status, const hidl_vec<uint8_t>& request,
+ KeyRequestType type, const hidl_string&) {
+ EXPECT_EQ(Status::OK, status) << "Failed to get "
+ "key request for configuration "
+ << configuration.name;
+ EXPECT_EQ(type, KeyRequestType::INITIAL);
+ EXPECT_NE(request.size(), 0u) << "Expected key request size"
+ " to have length > 0 bytes";
+ keyRequest = request;
+ });
+ EXPECT_OK(res);
+
+ /**
+ * Get key response from vendor module
+ */
+ hidl_vec<uint8_t> keyResponse =
+ vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
+
+ EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
+ "to have length > 0 bytes";
+
+ hidl_vec<uint8_t> keySetId;
+ res = drmPlugin->provideKeyResponse(
+ sessionId, keyResponse,
+ [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
+ EXPECT_EQ(Status::OK, status) << "Failure providing "
+ "key response for configuration "
+ << configuration.name;
+ keySetId = myKeySetId;
+ });
+ EXPECT_OK(res);
+ return keySetId;
+}
+
/**
* Test that a session can be opened and closed
*/
}
/**
+ * Test that keys are successfully restored to a new session
+ * for all content having a policy that allows offline use.
+ */
+TEST_P(DrmHalVendorPluginTest, RestoreKeys) {
+ for (auto config : contentConfigurations) {
+ if (config.policy.allowOffline) {
+ auto sessionId = openSession();
+ hidl_vec<uint8_t> keySetId =
+ loadKeys(sessionId, config, KeyType::OFFLINE);
+ closeSession(sessionId);
+ sessionId = openSession();
+ EXPECT_NE(0u, keySetId.size());
+ Status status = drmPlugin->restoreKeys(sessionId, keySetId);
+ EXPECT_EQ(Status::OK, status);
+ closeSession(sessionId);
+ }
+ }
+}
+
+/**
+ * Test that restoreKeys fails with a null key set ID.
+ * Error message is expected to be Status::BAD_VALUE.
+ */
+TEST_P(DrmHalVendorPluginTest, RestoreKeysNull) {
+ SessionId sessionId = openSession();
+ hidl_vec<uint8_t> nullKeySetId;
+ Status status = drmPlugin->restoreKeys(sessionId, nullKeySetId);
+ EXPECT_EQ(Status::BAD_VALUE, status);
+ closeSession(sessionId);
+}
+
+/**
+ * Test that restoreKeys fails to restore keys to a closed
+ * session. Error message is expected to be
+ * Status::ERROR_DRM_SESSION_NOT_OPENED.
+ */
+TEST_P(DrmHalVendorPluginTest, RestoreKeysClosedSession) {
+ for (auto config : contentConfigurations) {
+ auto sessionId = openSession();
+ hidl_vec<uint8_t> keySetId = loadKeys(sessionId, config);
+ EXPECT_NE(0u, keySetId.size());
+ closeSession(sessionId);
+ sessionId = openSession();
+ closeSession(sessionId);
+ Status status = drmPlugin->restoreKeys(sessionId, keySetId);
+ EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
+ }
+}
+
+/**
* Test that the plugin either doesn't support getting
* secure stops, or has no secure stops available after
* clearing them.
* configurations
*/
TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
- const char* kVendorStr = "Vendor module ";
for (auto config : contentConfigurations) {
for (auto key : config.keys) {
if (key.isSecure) {
virtual ~DrmHalVendorDecryptTest() {}
protected:
- void loadKeys(const SessionId& sessionId,
- const ContentConfiguration& configuration);
void fillRandom(const sp<IMemory>& memory);
- KeyedVector toHidlKeyedVector(const map<string, string>& params);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(vec.size(), 16u);
return hidl_array<uint8_t, 16>(&vec[0]);
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
};
-KeyedVector DrmHalVendorDecryptTest::toHidlKeyedVector(
- const map<string, string>& params) {
- std::vector<KeyValue> stdKeyedVector;
- for (auto it = params.begin(); it != params.end(); ++it) {
- KeyValue keyValue;
- keyValue.key = it->first;
- keyValue.value = it->second;
- stdKeyedVector.push_back(keyValue);
- }
- return KeyedVector(stdKeyedVector);
-}
-
-/**
- * Helper method to load keys for subsequent decrypt tests.
- * These tests use predetermined key request/response to
- * avoid requiring a round trip to a license server.
- */
-void DrmHalVendorDecryptTest::loadKeys(const SessionId& sessionId,
- const ContentConfiguration& configuration) {
- hidl_vec<uint8_t> keyRequest;
- auto res = drmPlugin->getKeyRequest(
- sessionId, configuration.initData, configuration.mimeType,
- KeyType::STREAMING,
- toHidlKeyedVector(configuration.optionalParameters),
- [&](Status status, const hidl_vec<uint8_t>& request,
- KeyRequestType type, const hidl_string&) {
- EXPECT_EQ(Status::OK, status)
- << "Failed to get "
- "key request for configuration "
- << configuration.name;
- EXPECT_EQ(type, KeyRequestType::INITIAL);
- EXPECT_NE(request.size(), 0u) << "Expected key request size"
- " to have length > 0 bytes";
- keyRequest = request;
- });
- EXPECT_OK(res);
-
- /**
- * Get key response from vendor module
- */
- hidl_vec<uint8_t> keyResponse =
- vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
-
- EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
- "to have length > 0 bytes";
-
- res = drmPlugin->provideKeyResponse(
- sessionId, keyResponse,
- [&](Status status, const hidl_vec<uint8_t>&) {
- EXPECT_EQ(Status::OK, status)
- << "Failure providing "
- "key response for configuration "
- << configuration.name;
- });
- EXPECT_OK(res);
-}
-
void DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) {
random_device rd;
mt19937 rand(rd());