From 1fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aa Mon Sep 17 00:00:00 2001 From: "John \"Juce\" Bruce" Date: Tue, 13 May 2014 22:22:44 -0700 Subject: 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 --- drm/mediadrm/plugins/clearkey/Android.mk | 10 + drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp | 32 +++ drm/mediadrm/plugins/clearkey/ClearKeyUUID.h | 28 +++ .../plugins/clearkey/CreatePluginFactories.cpp | 32 +++ .../plugins/clearkey/CreatePluginFactories.h | 28 +++ drm/mediadrm/plugins/clearkey/CryptoFactory.cpp | 52 +++++ drm/mediadrm/plugins/clearkey/CryptoFactory.h | 44 ++++ drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp | 83 ++++++++ drm/mediadrm/plugins/clearkey/CryptoPlugin.h | 56 +++++ drm/mediadrm/plugins/clearkey/DrmFactory.cpp | 52 +++++ drm/mediadrm/plugins/clearkey/DrmFactory.h | 46 +++++ drm/mediadrm/plugins/clearkey/DrmPlugin.cpp | 91 ++++++++ drm/mediadrm/plugins/clearkey/DrmPlugin.h | 230 +++++++++++++++++++++ drm/mediadrm/plugins/clearkey/Session.cpp | 85 ++++++++ drm/mediadrm/plugins/clearkey/Session.h | 64 ++++++ drm/mediadrm/plugins/clearkey/SessionLibrary.cpp | 78 +++++++ drm/mediadrm/plugins/clearkey/SessionLibrary.h | 59 ++++++ 17 files changed, 1070 insertions(+) create mode 100644 drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp create mode 100644 drm/mediadrm/plugins/clearkey/ClearKeyUUID.h create mode 100644 drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp create mode 100644 drm/mediadrm/plugins/clearkey/CreatePluginFactories.h create mode 100644 drm/mediadrm/plugins/clearkey/CryptoFactory.cpp create mode 100644 drm/mediadrm/plugins/clearkey/CryptoFactory.h create mode 100644 drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp create mode 100644 drm/mediadrm/plugins/clearkey/CryptoPlugin.h create mode 100644 drm/mediadrm/plugins/clearkey/DrmFactory.cpp create mode 100644 drm/mediadrm/plugins/clearkey/DrmFactory.h create mode 100644 drm/mediadrm/plugins/clearkey/DrmPlugin.cpp create mode 100644 drm/mediadrm/plugins/clearkey/DrmPlugin.h create mode 100644 drm/mediadrm/plugins/clearkey/Session.cpp create mode 100644 drm/mediadrm/plugins/clearkey/Session.h create mode 100644 drm/mediadrm/plugins/clearkey/SessionLibrary.cpp create mode 100644 drm/mediadrm/plugins/clearkey/SessionLibrary.h (limited to 'drm') 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 + +#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 + +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 +#include + +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 + +#include +#include + +#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 = 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 +#include +#include + +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 + +#include +#include + +#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(dstPtr) + offset, + reinterpret_cast(srcPtr) + offset, + subSample.mNumBytesOfClearData); + offset += subSample.mNumBytesOfClearData; + } + } + return static_cast(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(bytesDecrypted); + } else { + errorDetailMsg->setTo("Decryption Error"); + return static_cast(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 +#include +#include +#include +#include + +#include "ClearKeyTypes.h" +#include "Session.h" +#include "Utils.h" + +namespace clearkeydrm { + +class CryptoPlugin : public android::CryptoPlugin { +public: + CryptoPlugin(const android::sp& 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 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 + +#include + +#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 +#include +#include + +#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 + +#include +#include + +#include "DrmPlugin.h" + +#include "Session.h" + +namespace clearkeydrm { + +using android::sp; + +status_t DrmPlugin::openSession(Vector& sessionId) { + sp session = mSessionLibrary->createSession(); + sessionId = session->sessionId(); + return android::OK; +} + +status_t DrmPlugin::closeSession(const Vector& sessionId) { + sp session = mSessionLibrary->findSession(sessionId); + mSessionLibrary->destroySession(session); + return android::OK; +} + +status_t DrmPlugin::getKeyRequest( + const Vector& scope, + const Vector& initData, + const String8& initDataType, + KeyType keyType, + const KeyedVector& optionalParameters, + Vector& request, + String8& defaultUrl) { + UNUSED(optionalParameters); + if (keyType != kKeyType_Streaming) { + return android::ERROR_DRM_CANNOT_HANDLE; + } + + sp session = mSessionLibrary->findSession(scope); + defaultUrl.clear(); + return session->getKeyRequest(initData, initDataType, &request); +} + +status_t DrmPlugin::provideKeyResponse( + const Vector& scope, + const Vector& response, + Vector& keySetId) { + sp 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 +#include +#include +#include +#include +#include +#include +#include + +#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& sessionId); + + virtual status_t closeSession(const Vector& sessionId); + + virtual status_t getKeyRequest( + const Vector& scope, + const Vector& initData, + const String8& initDataType, + KeyType keyType, + const KeyedVector& optionalParameters, + Vector& request, + String8& defaultUrl); + + virtual status_t provideKeyResponse( + const Vector& scope, + const Vector& response, + Vector& keySetId); + + virtual status_t removeKeys(const Vector& sessionId) { + UNUSED(sessionId); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t restoreKeys( + const Vector& sessionId, + const Vector& keySetId) { + UNUSED(sessionId); + UNUSED(keySetId); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t queryKeyStatus( + const Vector& sessionId, + KeyedVector& 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& 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& response, + Vector& certificate, + Vector& wrappedKey) { + UNUSED(response); + UNUSED(certificate); + UNUSED(wrappedKey); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t getSecureStops(List >& secureStops) { + UNUSED(secureStops); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t releaseSecureStops(const Vector& 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& 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& value) { + UNUSED(name); + UNUSED(value); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t setCipherAlgorithm( + const Vector& sessionId, const String8& algorithm) { + UNUSED(sessionId); + UNUSED(algorithm); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t setMacAlgorithm( + const Vector& sessionId, const String8& algorithm) { + UNUSED(sessionId); + UNUSED(algorithm); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t encrypt( + const Vector& sessionId, + const Vector& keyId, + const Vector& input, + const Vector& iv, + Vector& output) { + UNUSED(sessionId); + UNUSED(keyId); + UNUSED(input); + UNUSED(iv); + UNUSED(output); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t decrypt( + const Vector& sessionId, + const Vector& keyId, + const Vector& input, + const Vector& iv, + Vector& output) { + UNUSED(sessionId); + UNUSED(keyId); + UNUSED(input); + UNUSED(iv); + UNUSED(output); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t sign( + const Vector& sessionId, + const Vector& keyId, + const Vector& message, + Vector& signature) { + UNUSED(sessionId); + UNUSED(keyId); + UNUSED(message); + UNUSED(signature); + return android::ERROR_DRM_CANNOT_HANDLE; + } + + virtual status_t verify( + const Vector& sessionId, + const Vector& keyId, + const Vector& message, + const Vector& 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& sessionId, + const String8& algorithm, + const Vector& message, + const Vector& wrappedKey, + Vector& 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 + +#include +#include + +#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& initData, + const String8& initDataType, + Vector* keyRequest) const { + InitDataParser parser; + return parser.parse(initData, initDataType, keyRequest); +} + +status_t Session::provideKeyResponse(const Vector& response) { + String8 responseString( + reinterpret_cast(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 keyIdVector; + keyIdVector.appendArray(keyId, kBlockSize); + if (mKeyMap.indexOfKey(keyIdVector) < 0) { + return android::ERROR_DRM_NO_LICENSE; + } + + const Vector& key = mKeyMap.valueFor(keyIdVector); + AesCtrDecryptor decryptor; + return decryptor.decrypt( + key, iv, + reinterpret_cast(source), + reinterpret_cast(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 +#include +#include +#include +#include +#include + +#include "ClearKeyTypes.h" +#include "Utils.h" + +namespace clearkeydrm { + +class Session : public android::RefBase { +public: + explicit Session(const android::Vector& sessionId) + : mSessionId(sessionId) {} + virtual ~Session() {} + + const android::Vector& sessionId() const { return mSessionId; } + + android::status_t getKeyRequest( + const android::Vector& initData, + const android::String8& initDataType, + android::Vector* keyRequest) const; + + android::status_t provideKeyResponse( + const android::Vector& 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 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 + +#include + +#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& SessionLibrary::createSession() { + Mutex::Autolock lock(mSessionsLock); + + String8 sessionIdString = String8::format("%u", mNextSessionId); + mNextSessionId += 1; + Vector sessionId; + sessionId.appendArray( + reinterpret_cast(sessionIdString.string()), + sessionIdString.size()); + + mSessions.add(sessionId, new Session(sessionId)); + return mSessions.valueFor(sessionId); +} + +const sp& SessionLibrary::findSession( + const Vector& sessionId) { + Mutex::Autolock lock(mSessionsLock); + return mSessions.valueFor(sessionId); +} + +const sp& SessionLibrary::findSession( + const void* data, size_t size) { + Vector sessionId; + sessionId.appendArray(reinterpret_cast(data), size); + return findSession(sessionId); +} + +void SessionLibrary::destroySession(const sp& 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 +#include +#include +#include + +#include "Session.h" +#include "Utils.h" + +namespace clearkeydrm { + +class SessionLibrary { +public: + static SessionLibrary* get(); + + const android::sp& createSession(); + + const android::sp& findSession( + const android::Vector& sessionId); + + const android::sp& findSession(const void* data, size_t size); + + void destroySession(const android::sp& 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::sp > + mSessions; +}; + +} // namespace clearkeydrm + +#endif // CLEARKEY_SESSION_LIBRARY_H_ -- cgit v1.1