1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "ClearKeyCryptoPlugin" 19#include <utils/Log.h> 20 21#include <media/stagefright/MediaErrors.h> 22 23#include "CryptoPlugin.h" 24#include "SessionLibrary.h" 25 26namespace clearkeydrm { 27 28using android::Vector; 29using android::AString; 30using android::status_t; 31 32// Returns negative values for error code and positive values for the size of 33// decrypted data. In theory, the output size can be larger than the input 34// size, but in practice this will never happen for AES-CTR. 35ssize_t CryptoPlugin::decrypt(bool secure, const KeyId keyId, const Iv iv, 36 Mode mode, const Pattern &/* pattern */, const void* srcPtr, 37 const SubSample* subSamples, size_t numSubSamples, 38 void* dstPtr, AString* errorDetailMsg) { 39 if (secure) { 40 errorDetailMsg->setTo("Secure decryption is not supported with " 41 "ClearKey."); 42 return android::ERROR_DRM_CANNOT_HANDLE; 43 } 44 45 if (mode == kMode_Unencrypted) { 46 size_t offset = 0; 47 for (size_t i = 0; i < numSubSamples; ++i) { 48 const SubSample& subSample = subSamples[i]; 49 50 if (subSample.mNumBytesOfEncryptedData != 0) { 51 errorDetailMsg->setTo( 52 "Encrypted subsamples found in allegedly unencrypted " 53 "data."); 54 return android::ERROR_DRM_DECRYPT; 55 } 56 57 if (subSample.mNumBytesOfClearData != 0) { 58 memcpy(reinterpret_cast<uint8_t*>(dstPtr) + offset, 59 reinterpret_cast<const uint8_t*>(srcPtr) + offset, 60 subSample.mNumBytesOfClearData); 61 offset += subSample.mNumBytesOfClearData; 62 } 63 } 64 return static_cast<ssize_t>(offset); 65 } else if (mode == kMode_AES_CTR) { 66 size_t bytesDecrypted; 67 status_t res = mSession->decrypt(keyId, iv, srcPtr, dstPtr, subSamples, 68 numSubSamples, &bytesDecrypted); 69 if (res == android::OK) { 70 return static_cast<ssize_t>(bytesDecrypted); 71 } else { 72 errorDetailMsg->setTo("Decryption Error"); 73 return static_cast<ssize_t>(res); 74 } 75 } else { 76 errorDetailMsg->setTo( 77 "Selected encryption mode is not supported by the ClearKey DRM " 78 "Plugin."); 79 return android::ERROR_DRM_CANNOT_HANDLE; 80 } 81} 82 83android::status_t CryptoPlugin::setMediaDrmSession( 84 const android::Vector<uint8_t>& sessionId) { 85 if (!sessionId.size()) { 86 mSession.clear(); 87 } else { 88 mSession = SessionLibrary::get()->findSession(sessionId); 89 if (!mSession.get()) { 90 return android::ERROR_DRM_SESSION_NOT_OPENED; 91 } 92 } 93 return android::OK; 94} 95 96 97} // namespace clearkeydrm 98