blob: 0d5f99008520679e8251ffae5eddd140eb855d62 [file] [log] [blame]
Andreas Hubered3e3e02012-03-26 11:13:27 -07001/*
2 * Copyright (C) 2012 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 "ICrypto"
19#include <utils/Log.h>
20
21#include <binder/Parcel.h>
22#include <media/ICrypto.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070023#include <media/stagefright/MediaErrors.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070024#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070025#include <media/stagefright/foundation/AString.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070026
27namespace android {
28
29enum {
Andreas Huber1bd139a2012-04-03 14:19:20 -070030 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
31 IS_CRYPTO_SUPPORTED,
32 CREATE_PLUGIN,
33 DESTROY_PLUGIN,
34 REQUIRES_SECURE_COMPONENT,
35 DECRYPT,
Andreas Hubered3e3e02012-03-26 11:13:27 -070036};
37
38struct BpCrypto : public BpInterface<ICrypto> {
39 BpCrypto(const sp<IBinder> &impl)
40 : BpInterface<ICrypto>(impl) {
41 }
42
Andreas Huber1bd139a2012-04-03 14:19:20 -070043 virtual status_t initCheck() const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070044 Parcel data, reply;
45 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070046 remote()->transact(INIT_CHECK, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070047
48 return reply.readInt32();
49 }
50
Jeff Tinkerbafb6822013-03-22 15:26:39 -070051 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
Andreas Hubered3e3e02012-03-26 11:13:27 -070052 Parcel data, reply;
53 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070054 data.write(uuid, 16);
55 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
56
57 return reply.readInt32() != 0;
58 }
59
60 virtual status_t createPlugin(
61 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
62 Parcel data, reply;
63 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
64 data.write(uuid, 16);
65 data.writeInt32(opaqueSize);
Andreas Huber705868c2012-04-11 15:41:45 -070066
67 if (opaqueSize > 0) {
68 data.write(opaqueData, opaqueSize);
69 }
70
Andreas Huber1bd139a2012-04-03 14:19:20 -070071 remote()->transact(CREATE_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070072
73 return reply.readInt32();
74 }
75
Andreas Huber1bd139a2012-04-03 14:19:20 -070076 virtual status_t destroyPlugin() {
Andreas Hubered3e3e02012-03-26 11:13:27 -070077 Parcel data, reply;
78 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070079 remote()->transact(DESTROY_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070080
81 return reply.readInt32();
82 }
83
Andreas Huber1bd139a2012-04-03 14:19:20 -070084 virtual bool requiresSecureDecoderComponent(
85 const char *mime) const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070086 Parcel data, reply;
87 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070088 data.writeCString(mime);
89 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070090
Andreas Huber1bd139a2012-04-03 14:19:20 -070091 return reply.readInt32() != 0;
Andreas Hubered3e3e02012-03-26 11:13:27 -070092 }
93
Edwin Wongfa2b8f22012-07-10 20:01:13 -070094 virtual ssize_t decrypt(
Andreas Huber1bd139a2012-04-03 14:19:20 -070095 bool secure,
96 const uint8_t key[16],
97 const uint8_t iv[16],
98 CryptoPlugin::Mode mode,
99 const void *srcPtr,
100 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700101 void *dstPtr,
102 AString *errorDetailMsg) {
Andreas Hubered3e3e02012-03-26 11:13:27 -0700103 Parcel data, reply;
104 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -0700105 data.writeInt32(secure);
106 data.writeInt32(mode);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700107
108 static const uint8_t kDummy[16] = { 0 };
109
110 if (key == NULL) {
111 key = kDummy;
112 }
113
114 if (iv == NULL) {
115 iv = kDummy;
116 }
117
Andreas Huber1bd139a2012-04-03 14:19:20 -0700118 data.write(key, 16);
119 data.write(iv, 16);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700120
Andreas Huber1bd139a2012-04-03 14:19:20 -0700121 size_t totalSize = 0;
122 for (size_t i = 0; i < numSubSamples; ++i) {
123 totalSize += subSamples[i].mNumBytesOfEncryptedData;
124 totalSize += subSamples[i].mNumBytesOfClearData;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700125 }
126
Andreas Huber1bd139a2012-04-03 14:19:20 -0700127 data.writeInt32(totalSize);
128 data.write(srcPtr, totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700129
Andreas Huber1bd139a2012-04-03 14:19:20 -0700130 data.writeInt32(numSubSamples);
131 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700132
Andreas Huber1bd139a2012-04-03 14:19:20 -0700133 if (secure) {
Jeff Tinkerbcca9e02014-06-09 15:51:38 -0700134 data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700135 }
136
Andreas Huber1bd139a2012-04-03 14:19:20 -0700137 remote()->transact(DECRYPT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700138
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700139 ssize_t result = reply.readInt32();
Andreas Hubered3e3e02012-03-26 11:13:27 -0700140
Andreas Huber5b8987e2012-04-19 12:52:20 -0700141 if (result >= ERROR_DRM_VENDOR_MIN && result <= ERROR_DRM_VENDOR_MAX) {
142 errorDetailMsg->setTo(reply.readCString());
143 }
144
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700145 if (!secure && result >= 0) {
146 reply.read(dstPtr, result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700147 }
148
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700149 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700150 }
151
152private:
153 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
154};
155
156IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
157
158////////////////////////////////////////////////////////////////////////////////
159
160status_t BnCrypto::onTransact(
161 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
162 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700163 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700164 {
165 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700166 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700167
168 return OK;
169 }
170
Andreas Huber1bd139a2012-04-03 14:19:20 -0700171 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700172 {
173 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700174 uint8_t uuid[16];
175 data.read(uuid, sizeof(uuid));
176 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700177
178 return OK;
179 }
180
Andreas Huber1bd139a2012-04-03 14:19:20 -0700181 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700182 {
183 CHECK_INTERFACE(ICrypto, data, reply);
184
Andreas Huber1bd139a2012-04-03 14:19:20 -0700185 uint8_t uuid[16];
186 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700187
Andreas Huber1bd139a2012-04-03 14:19:20 -0700188 size_t opaqueSize = data.readInt32();
Andreas Huber705868c2012-04-11 15:41:45 -0700189 void *opaqueData = NULL;
190
191 if (opaqueSize > 0) {
192 opaqueData = malloc(opaqueSize);
193 data.read(opaqueData, opaqueSize);
194 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700195
Andreas Huber1bd139a2012-04-03 14:19:20 -0700196 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
197
Andreas Huber705868c2012-04-11 15:41:45 -0700198 if (opaqueData != NULL) {
199 free(opaqueData);
200 opaqueData = NULL;
201 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700202
203 return OK;
204 }
205
Andreas Huber1bd139a2012-04-03 14:19:20 -0700206 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700207 {
208 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700209 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700210
211 return OK;
212 }
213
Andreas Huber1bd139a2012-04-03 14:19:20 -0700214 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700215 {
216 CHECK_INTERFACE(ICrypto, data, reply);
217
Andreas Huber1bd139a2012-04-03 14:19:20 -0700218 const char *mime = data.readCString();
219 reply->writeInt32(requiresSecureDecoderComponent(mime));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700220
Andreas Huber1bd139a2012-04-03 14:19:20 -0700221 return OK;
222 }
223
224 case DECRYPT:
225 {
226 CHECK_INTERFACE(ICrypto, data, reply);
227
228 bool secure = data.readInt32() != 0;
229 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
230
231 uint8_t key[16];
232 data.read(key, sizeof(key));
233
234 uint8_t iv[16];
235 data.read(iv, sizeof(iv));
236
237 size_t totalSize = data.readInt32();
238 void *srcData = malloc(totalSize);
239 data.read(srcData, totalSize);
240
241 int32_t numSubSamples = data.readInt32();
242
243 CryptoPlugin::SubSample *subSamples =
244 new CryptoPlugin::SubSample[numSubSamples];
245
246 data.read(
247 subSamples,
248 sizeof(CryptoPlugin::SubSample) * numSubSamples);
249
250 void *dstPtr;
251 if (secure) {
Jeff Tinkerbcca9e02014-06-09 15:51:38 -0700252 dstPtr = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
Andreas Huber1bd139a2012-04-03 14:19:20 -0700253 } else {
254 dstPtr = malloc(totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700255 }
256
Andreas Huber5b8987e2012-04-19 12:52:20 -0700257 AString errorDetailMsg;
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700258 ssize_t result = decrypt(
Andreas Huber1bd139a2012-04-03 14:19:20 -0700259 secure,
260 key,
261 iv,
262 mode,
263 srcData,
264 subSamples, numSubSamples,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700265 dstPtr,
266 &errorDetailMsg);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700267
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700268 reply->writeInt32(result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700269
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700270 if (result >= ERROR_DRM_VENDOR_MIN
271 && result <= ERROR_DRM_VENDOR_MAX) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700272 reply->writeCString(errorDetailMsg.c_str());
273 }
274
Andreas Huber1bd139a2012-04-03 14:19:20 -0700275 if (!secure) {
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700276 if (result >= 0) {
277 CHECK_LE(result, static_cast<ssize_t>(totalSize));
278 reply->write(dstPtr, result);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700279 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700280 free(dstPtr);
281 dstPtr = NULL;
282 }
283
284 delete[] subSamples;
285 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700286
287 free(srcData);
288 srcData = NULL;
289
Andreas Hubered3e3e02012-03-26 11:13:27 -0700290 return OK;
291 }
292
293 default:
294 return BBinder::onTransact(code, data, reply, flags);
295 }
296}
297
298} // namespace android
299