summaryrefslogtreecommitdiffstats
path: root/drm
diff options
context:
space:
mode:
authorJohn "Juce" Bruce <juce@google.com>2014-05-13 22:22:44 -0700
committerFred Gylys-Colwell <fredgc@google.com>2014-07-01 03:27:45 +0000
commit1fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aa (patch)
tree43dab16377cd28fe8bd7a75ae8878f75b37673f7 /drm
parent7bdf28d2b83e527f474e96b0984d6a3f5eb457f7 (diff)
downloadframeworks_av-1fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aa.zip
frameworks_av-1fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aa.tar.gz
frameworks_av-1fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aa.tar.bz2
ClearKey Implementation of DRM Plugin APIs
Adds shared-object entry points and interface implementations that implement the Android ClearKey DRM Plugin API. Change-Id: Ie889747492cf85efe883149833105538faaa4cfe
Diffstat (limited to 'drm')
-rw-r--r--drm/mediadrm/plugins/clearkey/Android.mk10
-rw-r--r--drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp32
-rw-r--r--drm/mediadrm/plugins/clearkey/ClearKeyUUID.h28
-rw-r--r--drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp32
-rw-r--r--drm/mediadrm/plugins/clearkey/CreatePluginFactories.h28
-rw-r--r--drm/mediadrm/plugins/clearkey/CryptoFactory.cpp52
-rw-r--r--drm/mediadrm/plugins/clearkey/CryptoFactory.h44
-rw-r--r--drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp83
-rw-r--r--drm/mediadrm/plugins/clearkey/CryptoPlugin.h56
-rw-r--r--drm/mediadrm/plugins/clearkey/DrmFactory.cpp52
-rw-r--r--drm/mediadrm/plugins/clearkey/DrmFactory.h46
-rw-r--r--drm/mediadrm/plugins/clearkey/DrmPlugin.cpp91
-rw-r--r--drm/mediadrm/plugins/clearkey/DrmPlugin.h230
-rw-r--r--drm/mediadrm/plugins/clearkey/Session.cpp85
-rw-r--r--drm/mediadrm/plugins/clearkey/Session.h64
-rw-r--r--drm/mediadrm/plugins/clearkey/SessionLibrary.cpp78
-rw-r--r--drm/mediadrm/plugins/clearkey/SessionLibrary.h59
17 files changed, 1070 insertions, 0 deletions
diff --git a/drm/mediadrm/plugins/clearkey/Android.mk b/drm/mediadrm/plugins/clearkey/Android.mk
index 9cc81e8..c0492e7 100644
--- a/drm/mediadrm/plugins/clearkey/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/Android.mk
@@ -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
index 0000000..ed050f7
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
@@ -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
index 0000000..ac99418
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.h
@@ -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
index 0000000..ec1420e
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp
@@ -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
index 0000000..d9acec1
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/CreatePluginFactories.h
@@ -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
index 0000000..ee3189b
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/CryptoFactory.cpp
@@ -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
index 0000000..568bc4b
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/CryptoFactory.h
@@ -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
index 0000000..adad136
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp
@@ -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
index 0000000..002d9e0
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/CryptoPlugin.h
@@ -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
index 0000000..40275cf
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
@@ -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
index 0000000..164d3d0
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/DrmFactory.h
@@ -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
index 0000000..96fca94
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
@@ -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
index 0000000..bfbc6bf
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -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
index 0000000..95016f5
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/Session.cpp
@@ -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
index 0000000..cab0dc3
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/Session.h
@@ -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
index 0000000..d047c53
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/SessionLibrary.cpp
@@ -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
index 0000000..56c8828
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/SessionLibrary.h
@@ -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_