/* * Copyright (C) 2012 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 "wv_crypto_plugin" #include #include "WVCryptoPlugin.h" #include #include #include #include android::CryptoFactory *createCryptoFactory() { return new android::WVCryptoFactory; } namespace android { // static const uint8_t WVCryptoFactory::kUUIDWidevine[16] = { 0xED,0xEF,0x8B,0xA9,0x79,0xD6,0x4A,0xCE, 0xA3,0xC8,0x27,0xDC,0xD5,0x1D,0x21,0xED }; WVCryptoPlugin::WVCryptoPlugin(const void *data, size_t size) : mInitCheck(NO_INIT) { // not using data at this time, require // size to be zero. if (size > 0) { mInitCheck = -EINVAL; } else { OEMCryptoResult res = OEMCrypto_Initialize(); if (res != OEMCrypto_SUCCESS) { ALOGE("OEMCrypto_Initialize failed: %d", res); mInitCheck = -EINVAL; } else { mInitCheck = OK; } } } WVCryptoPlugin::~WVCryptoPlugin() { if (mInitCheck == OK) { OEMCryptoResult res = OEMCrypto_Terminate(); if (res != OEMCrypto_SUCCESS) { ALOGW("OEMCrypto_Terminate failed: %d", res); } } } status_t WVCryptoPlugin::initCheck() const { return mInitCheck; } bool WVCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const { return !strncasecmp(mime, "video/", 6); } status_t WVCryptoPlugin::decrypt( bool secure, const uint8_t key[16], const uint8_t iv[16], Mode mode, const void *srcPtr, const SubSample *subSamples, size_t numSubSamples, void *dstPtr, AString *errorDetailMsg) { Mutex::Autolock autoLock(mLock); //ALOGD("mode=%d, secure=%d, numSubSamples=%d", mode, secure, numSubSamples); CHECK(mode == kMode_Unencrypted || mode == kMode_AES_WV); size_t offset = 0; for (size_t i = 0; i < numSubSamples; ++i) { const SubSample &ss = subSamples[i]; size_t srcSize; if (mode == kMode_Unencrypted) { srcSize = ss.mNumBytesOfClearData; CHECK_EQ(ss.mNumBytesOfEncryptedData, 0u); } else { CHECK_EQ(ss.mNumBytesOfClearData, 0u); srcSize = ss.mNumBytesOfEncryptedData; } //ALOGD("size[%d]=%d", i, srcSize); OEMCrypto_UINT32 dstLength = srcSize; OEMCryptoResult res; OEMCrypto_UINT8 _iv[16]; const OEMCrypto_UINT8 *iv = NULL; if (mode != kMode_Unencrypted) { memset(_iv, 0, sizeof(_iv)); iv = _iv; } if (secure) { //ALOGD("calling DecryptVideo, size=%d", srcSize); res = OEMCrypto_DecryptVideo( iv, (const OEMCrypto_UINT8 *)srcPtr + offset, srcSize, (OEMCrypto_UINT32)dstPtr, offset, &dstLength); } else { //ALOGD("calling DecryptAudio: size=%d", srcSize); res = OEMCrypto_DecryptAudio( iv, (const OEMCrypto_UINT8 *)srcPtr + offset, srcSize, (OEMCrypto_UINT8 *)dstPtr + offset, &dstLength); } if (res != OEMCrypto_SUCCESS) { ALOGE("decrypt result: %d", res); return -EINVAL; } offset += dstLength; } return OK; } } // namespace android