OSDN Git Service

ClearKey Implementation of DRM Plugin APIs
authorJohn "Juce" Bruce <juce@google.com>
Wed, 14 May 2014 05:22:44 +0000 (22:22 -0700)
committerFred Gylys-Colwell <fredgc@google.com>
Tue, 1 Jul 2014 03:27:45 +0000 (03:27 +0000)
Adds shared-object entry points and interface implementations that
implement the Android ClearKey DRM Plugin API.

Change-Id: Ie889747492cf85efe883149833105538faaa4cfe

17 files changed:
drm/mediadrm/plugins/clearkey/Android.mk
drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/ClearKeyUUID.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/CreatePluginFactories.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/CryptoFactory.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/CryptoFactory.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/CryptoPlugin.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/DrmFactory.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/DrmFactory.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/DrmPlugin.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/DrmPlugin.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/Session.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/Session.h [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/SessionLibrary.cpp [new file with mode: 0644]
drm/mediadrm/plugins/clearkey/SessionLibrary.h [new file with mode: 0644]

index 9cc81e8..c0492e7 100644 (file)
@@ -20,6 +20,16 @@ LOCAL_SRC_FILES := \
     AesCtrDecryptor.cpp \
     InitDataParser.cpp \
     JsonWebKey.cpp \
+    ClearKeyUUID.cpp \
+    CreatePluginFactories.cpp \
+    CryptoFactory.cpp \
+    CryptoPlugin.cpp \
+    DrmFactory.cpp \
+    DrmPlugin.cpp \
+    InitDataParser.cpp \
+    JsonWebKey.cpp \
+    Session.cpp \
+    SessionLibrary.cpp \
     Utils.cpp \
 
 LOCAL_C_INCLUDES := \
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
new file mode 100644 (file)
index 0000000..ed050f7
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#include "ClearKeyUUID.h"
+
+namespace clearkeydrm {
+
+bool isClearKeyUUID(const uint8_t uuid[16]) {
+    static const uint8_t kClearKeyUUID[16] = {
+        0x10,0x77,0xEF,0xEC,0xC0,0xB2,0x4D,0x02,
+        0xAC,0xE3,0x3C,0x1E,0x52,0xE2,0xFB,0x4B
+    };
+
+    return !memcmp(uuid, kClearKeyUUID, sizeof(kClearKeyUUID));
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.h b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.h
new file mode 100644 (file)
index 0000000..ac99418
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_UUID_H_
+#define CLEARKEY_UUID_H_
+
+#include <stdint.h>
+
+namespace clearkeydrm {
+
+bool isClearKeyUUID(const uint8_t uuid[16]);
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_UUID_H_
diff --git a/drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp
new file mode 100644 (file)
index 0000000..ec1420e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CreatePluginFactories.h"
+
+#include "CryptoFactory.h"
+#include "DrmFactory.h"
+
+extern "C" {
+
+android::DrmFactory* createDrmFactory() {
+    return new clearkeydrm::DrmFactory();
+}
+
+android::CryptoFactory* createCryptoFactory() {
+    return new clearkeydrm::CryptoFactory();
+}
+
+} // extern "C"
diff --git a/drm/mediadrm/plugins/clearkey/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/CreatePluginFactories.h
new file mode 100644 (file)
index 0000000..d9acec1
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
+#define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
+
+#include <media/drm/DrmAPI.h>
+#include <media/hardware/CryptoAPI.h>
+
+extern "C" {
+    android::DrmFactory* createDrmFactory();
+    android::CryptoFactory* createCryptoFactory();
+}
+
+#endif // CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
diff --git a/drm/mediadrm/plugins/clearkey/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/CryptoFactory.cpp
new file mode 100644 (file)
index 0000000..ee3189b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "CryptoFactory.h"
+
+#include "ClearKeyUUID.h"
+#include "CryptoPlugin.h"
+#include "Session.h"
+#include "SessionLibrary.h"
+
+namespace clearkeydrm {
+
+bool CryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const {
+    return isClearKeyUUID(uuid);
+}
+
+android::status_t CryptoFactory::createPlugin(
+        const uint8_t uuid[16],
+        const void* data, size_t size,
+        android::CryptoPlugin** plugin) {
+    if (!isCryptoSchemeSupported(uuid)) {
+        *plugin = NULL;
+        return android::BAD_VALUE;
+    }
+
+    android::sp<Session> session = SessionLibrary::get()->findSession(
+            data, size);
+    *plugin = new CryptoPlugin(session);
+    return android::OK;
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/CryptoFactory.h
new file mode 100644 (file)
index 0000000..568bc4b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_CRYPTO_FACTORY_H_
+#define CLEARKEY_CRYPTO_FACTORY_H_
+
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+
+namespace clearkeydrm {
+
+class CryptoFactory : public android::CryptoFactory {
+public:
+    CryptoFactory() {}
+    virtual ~CryptoFactory() {}
+
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const;
+
+    virtual android::status_t createPlugin(
+            const uint8_t uuid[16],
+            const void* data, size_t size,
+            android::CryptoPlugin** plugin);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(CryptoFactory);
+};
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_CRYPTO_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp
new file mode 100644 (file)
index 0000000..adad136
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+
+#include "CryptoPlugin.h"
+
+namespace clearkeydrm {
+
+using android::Vector;
+using android::AString;
+using android::status_t;
+
+// Returns negative values for error code and positive values for the size of
+// decrypted data.  In theory, the output size can be larger than the input
+// size, but in practice this will never happen for AES-CTR.
+ssize_t CryptoPlugin::decrypt(bool secure, const KeyId keyId, const Iv iv,
+                              Mode mode, const void* srcPtr,
+                              const SubSample* subSamples, size_t numSubSamples,
+                              void* dstPtr, AString* errorDetailMsg) {
+    if (secure) {
+        errorDetailMsg->setTo("Secure decryption is not supported with "
+                              "ClearKey.");
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    if (mode == kMode_Unencrypted) {
+        size_t offset = 0;
+        for (size_t i = 0; i < numSubSamples; ++i) {
+            const SubSample& subSample = subSamples[i];
+
+            if (subSample.mNumBytesOfEncryptedData != 0) {
+                errorDetailMsg->setTo(
+                        "Encrypted subsamples found in allegedly unencrypted "
+                        "data.");
+                return android::ERROR_DRM_DECRYPT;
+            }
+
+            if (subSample.mNumBytesOfClearData != 0) {
+                memcpy(reinterpret_cast<uint8_t*>(dstPtr) + offset,
+                       reinterpret_cast<const uint8_t*>(srcPtr) + offset,
+                       subSample.mNumBytesOfClearData);
+                offset += subSample.mNumBytesOfClearData;
+            }
+        }
+        return static_cast<ssize_t>(offset);
+    } else if (mode == kMode_AES_CTR) {
+        size_t bytesDecrypted;
+        status_t res = mSession->decrypt(keyId, iv, srcPtr, dstPtr, subSamples,
+                                         numSubSamples, &bytesDecrypted);
+        if (res == android::OK) {
+            return static_cast<ssize_t>(bytesDecrypted);
+        } else {
+            errorDetailMsg->setTo("Decryption Error");
+            return static_cast<ssize_t>(res);
+        }
+    } else {
+        errorDetailMsg->setTo(
+                "Selected encryption mode is not supported by the ClearKey DRM "
+                "Plugin.");
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+}
+
+}  // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/CryptoPlugin.h
new file mode 100644 (file)
index 0000000..002d9e0
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_CRYPTO_PLUGIN_H_
+#define CLEARKEY_CRYPTO_PLUGIN_H_
+
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "ClearKeyTypes.h"
+#include "Session.h"
+#include "Utils.h"
+
+namespace clearkeydrm {
+
+class CryptoPlugin : public android::CryptoPlugin {
+public:
+    CryptoPlugin(const android::sp<Session>& session) : mSession(session) {}
+    virtual ~CryptoPlugin() {}
+
+    virtual bool requiresSecureDecoderComponent(const char* mime) const {
+        UNUSED(mime);
+        return false;
+    }
+
+    virtual ssize_t decrypt(
+            bool secure, const KeyId keyId, const Iv iv,
+            Mode mode, const void* srcPtr,
+            const SubSample* subSamples, size_t numSubSamples,
+            void* dstPtr, android::AString* errorDetailMsg);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(CryptoPlugin);
+
+    android::sp<Session> mSession;
+};
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_CRYPTO_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
new file mode 100644 (file)
index 0000000..40275cf
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+
+#include "DrmFactory.h"
+
+#include "DrmPlugin.h"
+#include "ClearKeyUUID.h"
+#include "SessionLibrary.h"
+
+namespace clearkeydrm {
+
+bool DrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+    return isClearKeyUUID(uuid);
+}
+
+bool DrmFactory::isContentTypeSupported(const android::String8 &initDataType) {
+    // This should match the types handed by InitDataParser.
+    return initDataType == "cenc" ||
+           initDataType == "webm";
+}
+
+android::status_t DrmFactory::createDrmPlugin(
+        const uint8_t uuid[16], android::DrmPlugin** plugin) {
+    if (!isCryptoSchemeSupported(uuid)) {
+        *plugin = NULL;
+        return android::BAD_VALUE;
+    }
+
+    *plugin = new DrmPlugin(SessionLibrary::get());
+    return android::OK;
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.h b/drm/mediadrm/plugins/clearkey/DrmFactory.h
new file mode 100644 (file)
index 0000000..164d3d0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_DRM_FACTORY_H_
+#define CLEARKEY_DRM_FACTORY_H_
+
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+
+#include "Utils.h"
+
+namespace clearkeydrm {
+
+class DrmFactory : public android::DrmFactory {
+public:
+    DrmFactory() {}
+    virtual ~DrmFactory() {}
+
+    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+
+    virtual bool isContentTypeSupported(const android::String8 &initDataType);
+
+    virtual android::status_t createDrmPlugin(
+            const uint8_t uuid[16], android::DrmPlugin** plugin);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(DrmFactory);
+};
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_DRM_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
new file mode 100644 (file)
index 0000000..96fca94
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaErrors.h>
+#include <utils/StrongPointer.h>
+
+#include "DrmPlugin.h"
+
+#include "Session.h"
+
+namespace clearkeydrm {
+
+using android::sp;
+
+status_t DrmPlugin::openSession(Vector<uint8_t>& sessionId) {
+    sp<Session> session = mSessionLibrary->createSession();
+    sessionId = session->sessionId();
+    return android::OK;
+}
+
+status_t DrmPlugin::closeSession(const Vector<uint8_t>& sessionId) {
+    sp<Session> session = mSessionLibrary->findSession(sessionId);
+    mSessionLibrary->destroySession(session);
+    return android::OK;
+}
+
+status_t DrmPlugin::getKeyRequest(
+        const Vector<uint8_t>& scope,
+        const Vector<uint8_t>& initData,
+        const String8& initDataType,
+        KeyType keyType,
+        const KeyedVector<String8, String8>& optionalParameters,
+        Vector<uint8_t>& request,
+        String8& defaultUrl) {
+    UNUSED(optionalParameters);
+    if (keyType != kKeyType_Streaming) {
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    sp<Session> session = mSessionLibrary->findSession(scope);
+    defaultUrl.clear();
+    return session->getKeyRequest(initData, initDataType, &request);
+}
+
+status_t DrmPlugin::provideKeyResponse(
+        const Vector<uint8_t>& scope,
+        const Vector<uint8_t>& response,
+        Vector<uint8_t>& keySetId) {
+    sp<Session> session = mSessionLibrary->findSession(scope);
+    status_t res = session->provideKeyResponse(response);
+    if (res == android::OK) {
+        keySetId.clear();
+    }
+    return res;
+}
+
+status_t DrmPlugin::getPropertyString(
+        const String8& name, String8& value) const {
+    if (name == "vendor") {
+        value = "Google";
+    } else if (name == "version") {
+        value = "1.0";
+    } else if (name == "description") {
+        value = "ClearKey CDM";
+    } else if (name == "algorithms") {
+        value = "";
+    } else {
+        ALOGE("App requested unknown string property %s", name.string());
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+    return android::OK;
+}
+
+}  // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
new file mode 100644 (file)
index 0000000..bfbc6bf
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_DRM_PLUGIN_H_
+#define CLEARKEY_DRM_PLUGIN_H_
+
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "SessionLibrary.h"
+#include "Utils.h"
+
+namespace clearkeydrm {
+
+using android::KeyedVector;
+using android::List;
+using android::status_t;
+using android::String8;
+using android::Vector;
+
+class DrmPlugin : public android::DrmPlugin {
+public:
+    DrmPlugin(SessionLibrary* sessionLibrary)
+            : mSessionLibrary(sessionLibrary) {}
+    virtual ~DrmPlugin() {}
+
+    virtual status_t openSession(Vector<uint8_t>& sessionId);
+
+    virtual status_t closeSession(const Vector<uint8_t>& sessionId);
+
+    virtual status_t getKeyRequest(
+            const Vector<uint8_t>& scope,
+            const Vector<uint8_t>& initData,
+            const String8& initDataType,
+            KeyType keyType,
+            const KeyedVector<String8, String8>& optionalParameters,
+            Vector<uint8_t>& request,
+            String8& defaultUrl);
+
+    virtual status_t provideKeyResponse(
+            const Vector<uint8_t>& scope,
+            const Vector<uint8_t>& response,
+            Vector<uint8_t>& keySetId);
+
+    virtual status_t removeKeys(const Vector<uint8_t>& sessionId) {
+        UNUSED(sessionId);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t restoreKeys(
+            const Vector<uint8_t>& sessionId,
+            const Vector<uint8_t>& keySetId) {
+        UNUSED(sessionId);
+        UNUSED(keySetId);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t queryKeyStatus(
+            const Vector<uint8_t>& sessionId,
+            KeyedVector<String8, String8>& infoMap) const {
+        UNUSED(sessionId);
+        UNUSED(infoMap);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t getProvisionRequest(
+            const String8& cert_type,
+            const String8& cert_authority,
+            Vector<uint8_t>& request,
+            String8& defaultUrl) {
+        UNUSED(cert_type);
+        UNUSED(cert_authority);
+        UNUSED(request);
+        UNUSED(defaultUrl);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t provideProvisionResponse(
+            const Vector<uint8_t>& response,
+            Vector<uint8_t>& certificate,
+            Vector<uint8_t>& wrappedKey) {
+        UNUSED(response);
+        UNUSED(certificate);
+        UNUSED(wrappedKey);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t getSecureStops(List<Vector<uint8_t> >& secureStops) {
+        UNUSED(secureStops);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t releaseSecureStops(const Vector<uint8_t>& ssRelease) {
+        UNUSED(ssRelease);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t getPropertyString(
+            const String8& name, String8& value) const;
+
+    virtual status_t getPropertyByteArray(
+            const String8& name, Vector<uint8_t>& value) const {
+        UNUSED(name);
+        UNUSED(value);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t setPropertyString(
+            const String8& name, const String8& value) {
+        UNUSED(name);
+        UNUSED(value);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t setPropertyByteArray(
+            const String8& name, const Vector<uint8_t>& value) {
+        UNUSED(name);
+        UNUSED(value);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t setCipherAlgorithm(
+            const Vector<uint8_t>& sessionId, const String8& algorithm) {
+        UNUSED(sessionId);
+        UNUSED(algorithm);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t setMacAlgorithm(
+            const Vector<uint8_t>& sessionId, const String8& algorithm) {
+        UNUSED(sessionId);
+        UNUSED(algorithm);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t encrypt(
+            const Vector<uint8_t>& sessionId,
+            const Vector<uint8_t>& keyId,
+            const Vector<uint8_t>& input,
+            const Vector<uint8_t>& iv,
+            Vector<uint8_t>& output) {
+        UNUSED(sessionId);
+        UNUSED(keyId);
+        UNUSED(input);
+        UNUSED(iv);
+        UNUSED(output);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t decrypt(
+            const Vector<uint8_t>& sessionId,
+            const Vector<uint8_t>& keyId,
+            const Vector<uint8_t>& input,
+            const Vector<uint8_t>& iv,
+            Vector<uint8_t>& output) {
+        UNUSED(sessionId);
+        UNUSED(keyId);
+        UNUSED(input);
+        UNUSED(iv);
+        UNUSED(output);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t sign(
+            const Vector<uint8_t>& sessionId,
+            const Vector<uint8_t>& keyId,
+            const Vector<uint8_t>& message,
+            Vector<uint8_t>& signature) {
+        UNUSED(sessionId);
+        UNUSED(keyId);
+        UNUSED(message);
+        UNUSED(signature);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t verify(
+            const Vector<uint8_t>& sessionId,
+            const Vector<uint8_t>& keyId,
+            const Vector<uint8_t>& message,
+            const Vector<uint8_t>& signature, bool& match) {
+        UNUSED(sessionId);
+        UNUSED(keyId);
+        UNUSED(message);
+        UNUSED(signature);
+        UNUSED(match);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    virtual status_t signRSA(
+            const Vector<uint8_t>& sessionId,
+            const String8& algorithm,
+            const Vector<uint8_t>& message,
+            const Vector<uint8_t>& wrappedKey,
+            Vector<uint8_t>& signature) {
+        UNUSED(sessionId);
+        UNUSED(algorithm);
+        UNUSED(message);
+        UNUSED(wrappedKey);
+        UNUSED(signature);
+        return android::ERROR_DRM_CANNOT_HANDLE;
+    }
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
+
+    SessionLibrary* mSessionLibrary;
+};
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_DRM_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/Session.cpp b/drm/mediadrm/plugins/clearkey/Session.cpp
new file mode 100644 (file)
index 0000000..95016f5
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaErrors.h>
+#include <utils/String8.h>
+
+#include "Session.h"
+
+#include "AesCtrDecryptor.h"
+#include "InitDataParser.h"
+#include "JsonWebKey.h"
+
+namespace clearkeydrm {
+
+using android::Mutex;
+using android::String8;
+using android::Vector;
+using android::status_t;
+
+status_t Session::getKeyRequest(
+        const Vector<uint8_t>& initData,
+        const String8& initDataType,
+        Vector<uint8_t>* keyRequest) const {
+    InitDataParser parser;
+    return parser.parse(initData, initDataType, keyRequest);
+}
+
+status_t Session::provideKeyResponse(const Vector<uint8_t>& response) {
+    String8 responseString(
+            reinterpret_cast<const char*>(response.array()), response.size());
+    KeyMap keys;
+
+    Mutex::Autolock lock(mMapLock);
+    JsonWebKey parser;
+    if (parser.extractKeysFromJsonWebKeySet(responseString, &keys)) {
+        for (size_t i = 0; i < keys.size(); ++i) {
+            const KeyMap::key_type& keyId = keys.keyAt(i);
+            const KeyMap::value_type& key = keys.valueAt(i);
+            mKeyMap.add(keyId, key);
+        }
+        return android::OK;
+    } else {
+        return android::ERROR_DRM_UNKNOWN;
+    }
+}
+
+status_t Session::decrypt(
+        const KeyId keyId, const Iv iv, const void* source,
+        void* destination, const SubSample* subSamples,
+        size_t numSubSamples, size_t* bytesDecryptedOut) {
+    Mutex::Autolock lock(mMapLock);
+
+    Vector<uint8_t> keyIdVector;
+    keyIdVector.appendArray(keyId, kBlockSize);
+    if (mKeyMap.indexOfKey(keyIdVector) < 0) {
+        return android::ERROR_DRM_NO_LICENSE;
+    }
+
+    const Vector<uint8_t>& key = mKeyMap.valueFor(keyIdVector);
+    AesCtrDecryptor decryptor;
+    return decryptor.decrypt(
+            key, iv,
+            reinterpret_cast<const uint8_t*>(source),
+            reinterpret_cast<uint8_t*>(destination), subSamples,
+            numSubSamples, bytesDecryptedOut);
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/Session.h b/drm/mediadrm/plugins/clearkey/Session.h
new file mode 100644 (file)
index 0000000..cab0dc3
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_SESSION_H_
+#define CLEARKEY_SESSION_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "ClearKeyTypes.h"
+#include "Utils.h"
+
+namespace clearkeydrm {
+
+class Session : public android::RefBase {
+public:
+    explicit Session(const android::Vector<uint8_t>& sessionId)
+            : mSessionId(sessionId) {}
+    virtual ~Session() {}
+
+    const android::Vector<uint8_t>& sessionId() const { return mSessionId; }
+
+    android::status_t getKeyRequest(
+            const android::Vector<uint8_t>& initData,
+            const android::String8& initDataType,
+            android::Vector<uint8_t>* keyRequest) const;
+
+    android::status_t provideKeyResponse(
+            const android::Vector<uint8_t>& response);
+
+    android::status_t decrypt(
+            const KeyId keyId, const Iv iv, const void* source,
+            void* destination, const SubSample* subSamples,
+            size_t numSubSamples, size_t* bytesDecryptedOut);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(Session);
+
+    const android::Vector<uint8_t> mSessionId;
+
+    android::Mutex mMapLock;
+    KeyMap mKeyMap;
+};
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_SESSION_H_
diff --git a/drm/mediadrm/plugins/clearkey/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/SessionLibrary.cpp
new file mode 100644 (file)
index 0000000..d047c53
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ClearKeyCryptoPlugin"
+#include <utils/Log.h>
+
+#include <utils/String8.h>
+
+#include "SessionLibrary.h"
+
+namespace clearkeydrm {
+
+using android::Mutex;
+using android::sp;
+using android::String8;
+using android::Vector;
+
+Mutex SessionLibrary::sSingletonLock;
+SessionLibrary* SessionLibrary::sSingleton = NULL;
+
+SessionLibrary* SessionLibrary::get() {
+    Mutex::Autolock lock(sSingletonLock);
+
+    if (sSingleton == NULL) {
+        ALOGD("Instantiating Session Library Singleton.");
+        sSingleton = new SessionLibrary();
+    }
+
+    return sSingleton;
+}
+
+const sp<Session>& SessionLibrary::createSession() {
+    Mutex::Autolock lock(mSessionsLock);
+
+    String8 sessionIdString = String8::format("%u", mNextSessionId);
+    mNextSessionId += 1;
+    Vector<uint8_t> sessionId;
+    sessionId.appendArray(
+            reinterpret_cast<const uint8_t*>(sessionIdString.string()),
+            sessionIdString.size());
+
+    mSessions.add(sessionId, new Session(sessionId));
+    return mSessions.valueFor(sessionId);
+}
+
+const sp<Session>& SessionLibrary::findSession(
+        const Vector<uint8_t>& sessionId) {
+    Mutex::Autolock lock(mSessionsLock);
+    return mSessions.valueFor(sessionId);
+}
+
+const sp<Session>& SessionLibrary::findSession(
+        const void* data, size_t size) {
+    Vector<uint8_t> sessionId;
+    sessionId.appendArray(reinterpret_cast<const uint8_t*>(data), size);
+    return findSession(sessionId);
+}
+
+void SessionLibrary::destroySession(const sp<Session>& session) {
+    Mutex::Autolock lock(mSessionsLock);\
+    mSessions.removeItem(session->sessionId());
+}
+
+} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/SessionLibrary.h
new file mode 100644 (file)
index 0000000..56c8828
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CLEARKEY_SESSION_LIBRARY_H_
+#define CLEARKEY_SESSION_LIBRARY_H_
+
+#include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+
+#include "Session.h"
+#include "Utils.h"
+
+namespace clearkeydrm {
+
+class SessionLibrary {
+public:
+    static SessionLibrary* get();
+
+    const android::sp<Session>& createSession();
+
+    const android::sp<Session>& findSession(
+            const android::Vector<uint8_t>& sessionId);
+
+    const android::sp<Session>& findSession(const void* data, size_t size);
+
+    void destroySession(const android::sp<Session>& session);
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(SessionLibrary);
+
+    SessionLibrary() : mNextSessionId(1) {}
+
+    static android::Mutex sSingletonLock;
+    static SessionLibrary* sSingleton;
+
+    android::Mutex mSessionsLock;
+    uint32_t mNextSessionId;
+    android::KeyedVector<android::Vector<uint8_t>, android::sp<Session> >
+            mSessions;
+};
+
+} // namespace clearkeydrm
+
+#endif // CLEARKEY_SESSION_LIBRARY_H_