Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 007d23e7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add testcases for restoreKeys API." into oc-dev

parents e1df4992 6799c3a5
Loading
Loading
Loading
Loading
+89 −62
Original line number Diff line number Diff line
@@ -245,6 +245,7 @@ class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {

    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:
@@ -312,6 +313,70 @@ void DrmHalClearkeyPluginTest::closeSession(const SessionId& sessionId) {
    EXPECT_EQ(Status::OK, result);
}

/**
 * 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
 */
@@ -470,6 +535,30 @@ TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) {
    closeSession(sessionId);
}

/**
 * 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.
@@ -831,7 +920,6 @@ TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) {

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());
@@ -845,67 +933,6 @@ class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest {
            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());
+19 −6
Original line number Diff line number Diff line
@@ -157,18 +157,31 @@ class DrmHalVTSVendorModule_V1 : public DrmHalVTSVendorModule {
         */
        const std::map<std::string, std::string> optionalParameters;

        /**
         *  Define license policy attributes for the content configuration.
         *  These attributes can affect which tests are able to be applied.
         */
        struct Policy {
            /**
             * Indicate if the license policy allows offline playback.
             * Content configurated with this policy supports KeyType::OFFLINE
             * key requests/responses. A vendor module should provide at least
             * one content configuration where allowOffline is true if the drm
             * scheme supports offline content.
             */
            bool allowOffline;
        } policy;

        /**
         * The keys that will be available once the keys are loaded
         */
        struct Key {
            /**
             * Indicate if the key content is configured to require secure
             * buffers,
             * where the output buffers are protected and cannot be accessed.
             * A vendor module should provide some content configurations where
             * isSecure is false, to allow decrypt result verification tests to
             * be
             * run.
             * buffers, where the output buffers are protected and cannot be
             * accessed by the non-secure cpu. A vendor module should provide
             * at least one content configurations where isSecure is false, to
             * allow decrypt result verification tests to be run.
             */
            bool isSecure;

+115 −61
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {

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
@@ -157,7 +158,9 @@ TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
                                              << " has zero length key value";
        }
        count++;
    }
    EXPECT_NE(0u, count);
}

/**
@@ -299,6 +302,10 @@ class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
    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;
@@ -389,6 +396,64 @@ void DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) {
    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
 */
@@ -487,6 +552,56 @@ TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
    closeSession(sessionId);
}

/**
 * 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
@@ -821,7 +936,6 @@ TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) {
 * configurations
 */
TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
    const char* kVendorStr = "Vendor module ";
    for (auto config : contentConfigurations) {
        for (auto key : config.keys) {
            if (key.isSecure) {
@@ -1060,10 +1174,7 @@ class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest {
    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]);
@@ -1080,63 +1191,6 @@ class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest {
            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());