blob: d51fe016ab6ace10cb59309c17482f499623e7a8 [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>
23#include <media/stagefright/foundation/ADebug.h>
24
25namespace android {
26
27enum {
Andreas Huber1bd139a2012-04-03 14:19:20 -070028 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
29 IS_CRYPTO_SUPPORTED,
30 CREATE_PLUGIN,
31 DESTROY_PLUGIN,
32 REQUIRES_SECURE_COMPONENT,
33 DECRYPT,
Andreas Hubered3e3e02012-03-26 11:13:27 -070034};
35
36struct BpCrypto : public BpInterface<ICrypto> {
37 BpCrypto(const sp<IBinder> &impl)
38 : BpInterface<ICrypto>(impl) {
39 }
40
Andreas Huber1bd139a2012-04-03 14:19:20 -070041 virtual status_t initCheck() const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070042 Parcel data, reply;
43 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070044 remote()->transact(INIT_CHECK, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070045
46 return reply.readInt32();
47 }
48
Andreas Huber1bd139a2012-04-03 14:19:20 -070049 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070050 Parcel data, reply;
51 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070052 data.write(uuid, 16);
53 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
54
55 return reply.readInt32() != 0;
56 }
57
58 virtual status_t createPlugin(
59 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
60 Parcel data, reply;
61 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
62 data.write(uuid, 16);
63 data.writeInt32(opaqueSize);
Andreas Huber705868c2012-04-11 15:41:45 -070064
65 if (opaqueSize > 0) {
66 data.write(opaqueData, opaqueSize);
67 }
68
Andreas Huber1bd139a2012-04-03 14:19:20 -070069 remote()->transact(CREATE_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070070
71 return reply.readInt32();
72 }
73
Andreas Huber1bd139a2012-04-03 14:19:20 -070074 virtual status_t destroyPlugin() {
Andreas Hubered3e3e02012-03-26 11:13:27 -070075 Parcel data, reply;
76 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070077 remote()->transact(DESTROY_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070078
79 return reply.readInt32();
80 }
81
Andreas Huber1bd139a2012-04-03 14:19:20 -070082 virtual bool requiresSecureDecoderComponent(
83 const char *mime) const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070084 Parcel data, reply;
85 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070086 data.writeCString(mime);
87 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070088
Andreas Huber1bd139a2012-04-03 14:19:20 -070089 return reply.readInt32() != 0;
Andreas Hubered3e3e02012-03-26 11:13:27 -070090 }
91
Andreas Huber1bd139a2012-04-03 14:19:20 -070092 virtual status_t decrypt(
93 bool secure,
94 const uint8_t key[16],
95 const uint8_t iv[16],
96 CryptoPlugin::Mode mode,
97 const void *srcPtr,
98 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
99 void *dstPtr) {
Andreas Hubered3e3e02012-03-26 11:13:27 -0700100 Parcel data, reply;
101 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -0700102 data.writeInt32(secure);
103 data.writeInt32(mode);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700104
105 static const uint8_t kDummy[16] = { 0 };
106
107 if (key == NULL) {
108 key = kDummy;
109 }
110
111 if (iv == NULL) {
112 iv = kDummy;
113 }
114
Andreas Huber1bd139a2012-04-03 14:19:20 -0700115 data.write(key, 16);
116 data.write(iv, 16);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700117
Andreas Huber1bd139a2012-04-03 14:19:20 -0700118 size_t totalSize = 0;
119 for (size_t i = 0; i < numSubSamples; ++i) {
120 totalSize += subSamples[i].mNumBytesOfEncryptedData;
121 totalSize += subSamples[i].mNumBytesOfClearData;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700122 }
123
Andreas Huber1bd139a2012-04-03 14:19:20 -0700124 data.writeInt32(totalSize);
125 data.write(srcPtr, totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700126
Andreas Huber1bd139a2012-04-03 14:19:20 -0700127 data.writeInt32(numSubSamples);
128 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700129
Andreas Huber1bd139a2012-04-03 14:19:20 -0700130 if (secure) {
131 data.writeIntPtr((intptr_t)dstPtr);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700132 }
133
Andreas Huber1bd139a2012-04-03 14:19:20 -0700134 remote()->transact(DECRYPT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700135
Andreas Huber1bd139a2012-04-03 14:19:20 -0700136 status_t result = reply.readInt32();
Andreas Hubered3e3e02012-03-26 11:13:27 -0700137
Andreas Huber1bd139a2012-04-03 14:19:20 -0700138 if (result != OK) {
139 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700140 }
141
Andreas Huber1bd139a2012-04-03 14:19:20 -0700142 if (!secure) {
143 reply.read(dstPtr, totalSize);
144 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700145
Andreas Huber1bd139a2012-04-03 14:19:20 -0700146 return OK;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700147 }
148
149private:
150 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
151};
152
153IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
154
155////////////////////////////////////////////////////////////////////////////////
156
157status_t BnCrypto::onTransact(
158 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
159 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700160 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700161 {
162 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700163 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700164
165 return OK;
166 }
167
Andreas Huber1bd139a2012-04-03 14:19:20 -0700168 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700169 {
170 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700171 uint8_t uuid[16];
172 data.read(uuid, sizeof(uuid));
173 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700174
175 return OK;
176 }
177
Andreas Huber1bd139a2012-04-03 14:19:20 -0700178 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700179 {
180 CHECK_INTERFACE(ICrypto, data, reply);
181
Andreas Huber1bd139a2012-04-03 14:19:20 -0700182 uint8_t uuid[16];
183 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700184
Andreas Huber1bd139a2012-04-03 14:19:20 -0700185 size_t opaqueSize = data.readInt32();
Andreas Huber705868c2012-04-11 15:41:45 -0700186 void *opaqueData = NULL;
187
188 if (opaqueSize > 0) {
189 opaqueData = malloc(opaqueSize);
190 data.read(opaqueData, opaqueSize);
191 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700192
Andreas Huber1bd139a2012-04-03 14:19:20 -0700193 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
194
Andreas Huber705868c2012-04-11 15:41:45 -0700195 if (opaqueData != NULL) {
196 free(opaqueData);
197 opaqueData = NULL;
198 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700199
200 return OK;
201 }
202
Andreas Huber1bd139a2012-04-03 14:19:20 -0700203 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700204 {
205 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700206 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700207
208 return OK;
209 }
210
Andreas Huber1bd139a2012-04-03 14:19:20 -0700211 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700212 {
213 CHECK_INTERFACE(ICrypto, data, reply);
214
Andreas Huber1bd139a2012-04-03 14:19:20 -0700215 const char *mime = data.readCString();
216 reply->writeInt32(requiresSecureDecoderComponent(mime));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700217
Andreas Huber1bd139a2012-04-03 14:19:20 -0700218 return OK;
219 }
220
221 case DECRYPT:
222 {
223 CHECK_INTERFACE(ICrypto, data, reply);
224
225 bool secure = data.readInt32() != 0;
226 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
227
228 uint8_t key[16];
229 data.read(key, sizeof(key));
230
231 uint8_t iv[16];
232 data.read(iv, sizeof(iv));
233
234 size_t totalSize = data.readInt32();
235 void *srcData = malloc(totalSize);
236 data.read(srcData, totalSize);
237
238 int32_t numSubSamples = data.readInt32();
239
240 CryptoPlugin::SubSample *subSamples =
241 new CryptoPlugin::SubSample[numSubSamples];
242
243 data.read(
244 subSamples,
245 sizeof(CryptoPlugin::SubSample) * numSubSamples);
246
247 void *dstPtr;
248 if (secure) {
249 dstPtr = (void *)data.readIntPtr();
250 } else {
251 dstPtr = malloc(totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700252 }
253
Andreas Huber1bd139a2012-04-03 14:19:20 -0700254 status_t err = decrypt(
255 secure,
256 key,
257 iv,
258 mode,
259 srcData,
260 subSamples, numSubSamples,
261 dstPtr);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700262
Andreas Huber1bd139a2012-04-03 14:19:20 -0700263 reply->writeInt32(err);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700264
Andreas Huber1bd139a2012-04-03 14:19:20 -0700265 if (!secure) {
266 if (err == OK) {
267 reply->write(dstPtr, totalSize);
268 }
269
270 free(dstPtr);
271 dstPtr = NULL;
272 }
273
274 delete[] subSamples;
275 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700276
277 free(srcData);
278 srcData = NULL;
279
Andreas Hubered3e3e02012-03-26 11:13:27 -0700280 return OK;
281 }
282
283 default:
284 return BBinder::onTransact(code, data, reply, flags);
285 }
286}
287
288} // namespace android
289