diff options
| author | John "Juce" Bruce <juce@google.com> | 2014-05-13 22:22:44 -0700 | 
|---|---|---|
| committer | Fred Gylys-Colwell <fredgc@google.com> | 2014-07-01 03:27:45 +0000 | 
| commit | 1fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aa (patch) | |
| tree | 43dab16377cd28fe8bd7a75ae8878f75b37673f7 /drm/mediadrm | |
| parent | 7bdf28d2b83e527f474e96b0984d6a3f5eb457f7 (diff) | |
| download | frameworks_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/mediadrm')
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/Android.mk | 10 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp | 32 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/ClearKeyUUID.h | 28 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/CreatePluginFactories.cpp | 32 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/CreatePluginFactories.h | 28 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/CryptoFactory.cpp | 52 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/CryptoFactory.h | 44 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/CryptoPlugin.cpp | 83 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/CryptoPlugin.h | 56 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/DrmFactory.cpp | 52 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/DrmFactory.h | 46 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/DrmPlugin.cpp | 91 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/DrmPlugin.h | 230 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/Session.cpp | 85 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/Session.h | 64 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/SessionLibrary.cpp | 78 | ||||
| -rw-r--r-- | drm/mediadrm/plugins/clearkey/SessionLibrary.h | 59 | 
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_  | 
