1ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber/*
2ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *
4ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * you may not use this file except in compliance with the License.
6ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * You may obtain a copy of the License at
7ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *
8ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *
10ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * Unless required by applicable law or agreed to in writing, software
11ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * See the License for the specific language governing permissions and
14ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * limitations under the License.
15ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber */
16ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
17ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber//#define LOG_NDEBUG 0
18ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#define LOG_TAG "Crypto"
19ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <utils/Log.h>
20ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
21ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include "Crypto.h"
22ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
231bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber#include <media/hardware/CryptoAPI.h>
241bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber#include <media/stagefright/foundation/ADebug.h>
255b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber#include <media/stagefright/foundation/AString.h>
261bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber#include <media/stagefright/foundation/hexdump.h>
27ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <media/stagefright/MediaErrors.h>
28ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
291bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber#include <dlfcn.h>
301bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
31ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Hubernamespace android {
32ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
331bd139a2a68690e80398b70b27ca59550fea0e65Andreas HuberCrypto::Crypto()
341bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    : mInitCheck(NO_INIT),
351bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber      mLibHandle(NULL),
361608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber      mFactory(NULL),
371bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber      mPlugin(NULL) {
381bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    mInitCheck = init();
39ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
40ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
41ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas HuberCrypto::~Crypto() {
421bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    delete mPlugin;
431bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    mPlugin = NULL;
441bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
451bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    delete mFactory;
461bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    mFactory = NULL;
471bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
481bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mLibHandle != NULL) {
491bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        dlclose(mLibHandle);
501bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        mLibHandle = NULL;
511bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
52ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
53ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
541bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberstatus_t Crypto::initCheck() const {
551bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return mInitCheck;
56ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
57ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
581bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberstatus_t Crypto::init() {
591bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    mLibHandle = dlopen("libdrmdecrypt.so", RTLD_NOW);
601bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
611bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mLibHandle == NULL) {
621608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        ALOGE("Unable to locate libdrmdecrypt.so");
631608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber
641bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return ERROR_UNSUPPORTED;
651bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
661bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
671bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    typedef CryptoFactory *(*CreateCryptoFactoryFunc)();
681bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    CreateCryptoFactoryFunc createCryptoFactory =
691bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        (CreateCryptoFactoryFunc)dlsym(mLibHandle, "createCryptoFactory");
701bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
711bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (createCryptoFactory == NULL
721bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            || ((mFactory = createCryptoFactory()) == NULL)) {
731608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        if (createCryptoFactory == NULL) {
741608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber            ALOGE("Unable to find symbol 'createCryptoFactory'.");
751608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        } else {
761608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber            ALOGE("createCryptoFactory() failed.");
771608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        }
781608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber
791bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        dlclose(mLibHandle);
801bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        mLibHandle = NULL;
811bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
821bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return ERROR_UNSUPPORTED;
831bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
841bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
851bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return OK;
86ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
87ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
881bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberbool Crypto::isCryptoSchemeSupported(const uint8_t uuid[16]) const {
891bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    Mutex::Autolock autoLock(mLock);
901bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
911bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mInitCheck != OK) {
921bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return false;
931bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
941bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
951bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return mFactory->isCryptoSchemeSupported(uuid);
96ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
97ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
981bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberstatus_t Crypto::createPlugin(
991bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        const uint8_t uuid[16], const void *data, size_t size) {
1001bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    Mutex::Autolock autoLock(mLock);
1011bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1021bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mInitCheck != OK) {
1031bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return mInitCheck;
1041bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1051bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1061bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mPlugin != NULL) {
1071bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return -EINVAL;
1081bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1091bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1101bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return mFactory->createPlugin(uuid, data, size, &mPlugin);
111ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
112ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
1131bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberstatus_t Crypto::destroyPlugin() {
1141bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    Mutex::Autolock autoLock(mLock);
1151bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1161bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mInitCheck != OK) {
1171bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return mInitCheck;
1181bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1191bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1201bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mPlugin == NULL) {
1211bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return -EINVAL;
1221bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1231bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1241bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    delete mPlugin;
1251bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    mPlugin = NULL;
1261bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1271bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return OK;
1281bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber}
1291bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1301bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huberbool Crypto::requiresSecureDecoderComponent(const char *mime) const {
1311bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    Mutex::Autolock autoLock(mLock);
1321bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1331bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mInitCheck != OK) {
1341bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return mInitCheck;
1351bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1361bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1371bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mPlugin == NULL) {
1381bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return -EINVAL;
1391bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1401bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1411bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return mPlugin->requiresSecureDecoderComponent(mime);
142ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
143ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
144fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wongssize_t Crypto::decrypt(
1451bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        bool secure,
1461bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        const uint8_t key[16],
1471bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        const uint8_t iv[16],
1481bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        CryptoPlugin::Mode mode,
1491bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        const void *srcPtr,
1501bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
1515b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber        void *dstPtr,
1525b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber        AString *errorDetailMsg) {
1531bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    Mutex::Autolock autoLock(mLock);
1541bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1551bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mInitCheck != OK) {
1561bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return mInitCheck;
1571bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1581bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1591bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    if (mPlugin == NULL) {
1601bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return -EINVAL;
1611bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1621bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1631bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    return mPlugin->decrypt(
1645b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            secure, key, iv, mode, srcPtr, subSamples, numSubSamples, dstPtr,
1655b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            errorDetailMsg);
166ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
167ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
168ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}  // namespace android
169