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
26 namespace clearkeydrm {
27
28 using android::Vector;
29 using android::AString;
30 using 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.
decrypt(bool secure,const KeyId keyId,const Iv iv,Mode mode,const Pattern &,const void * srcPtr,const SubSample * subSamples,size_t numSubSamples,void * dstPtr,AString * errorDetailMsg)35 ssize_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
setMediaDrmSession(const android::Vector<uint8_t> & sessionId)83 android::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