blob: e6bea1fcbb99bd8883c00e1deaaa42fd7ccdb630 [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);
64 data.write(opaqueData, opaqueSize);
65 remote()->transact(CREATE_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070066
67 return reply.readInt32();
68 }
69
Andreas Huber1bd139a2012-04-03 14:19:20 -070070 virtual status_t destroyPlugin() {
Andreas Hubered3e3e02012-03-26 11:13:27 -070071 Parcel data, reply;
72 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070073 remote()->transact(DESTROY_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070074
75 return reply.readInt32();
76 }
77
Andreas Huber1bd139a2012-04-03 14:19:20 -070078 virtual bool requiresSecureDecoderComponent(
79 const char *mime) const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070080 Parcel data, reply;
81 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070082 data.writeCString(mime);
83 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070084
Andreas Huber1bd139a2012-04-03 14:19:20 -070085 return reply.readInt32() != 0;
Andreas Hubered3e3e02012-03-26 11:13:27 -070086 }
87
Andreas Huber1bd139a2012-04-03 14:19:20 -070088 virtual status_t decrypt(
89 bool secure,
90 const uint8_t key[16],
91 const uint8_t iv[16],
92 CryptoPlugin::Mode mode,
93 const void *srcPtr,
94 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
95 void *dstPtr) {
Andreas Hubered3e3e02012-03-26 11:13:27 -070096 Parcel data, reply;
97 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070098 data.writeInt32(secure);
99 data.writeInt32(mode);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700100
101 static const uint8_t kDummy[16] = { 0 };
102
103 if (key == NULL) {
104 key = kDummy;
105 }
106
107 if (iv == NULL) {
108 iv = kDummy;
109 }
110
Andreas Huber1bd139a2012-04-03 14:19:20 -0700111 data.write(key, 16);
112 data.write(iv, 16);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700113
Andreas Huber1bd139a2012-04-03 14:19:20 -0700114 size_t totalSize = 0;
115 for (size_t i = 0; i < numSubSamples; ++i) {
116 totalSize += subSamples[i].mNumBytesOfEncryptedData;
117 totalSize += subSamples[i].mNumBytesOfClearData;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700118 }
119
Andreas Huber1bd139a2012-04-03 14:19:20 -0700120 data.writeInt32(totalSize);
121 data.write(srcPtr, totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700122
Andreas Huber1bd139a2012-04-03 14:19:20 -0700123 data.writeInt32(numSubSamples);
124 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700125
Andreas Huber1bd139a2012-04-03 14:19:20 -0700126 if (secure) {
127 data.writeIntPtr((intptr_t)dstPtr);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700128 }
129
Andreas Huber1bd139a2012-04-03 14:19:20 -0700130 remote()->transact(DECRYPT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700131
Andreas Huber1bd139a2012-04-03 14:19:20 -0700132 status_t result = reply.readInt32();
Andreas Hubered3e3e02012-03-26 11:13:27 -0700133
Andreas Huber1bd139a2012-04-03 14:19:20 -0700134 if (result != OK) {
135 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700136 }
137
Andreas Huber1bd139a2012-04-03 14:19:20 -0700138 if (!secure) {
139 reply.read(dstPtr, totalSize);
140 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700141
Andreas Huber1bd139a2012-04-03 14:19:20 -0700142 return OK;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700143 }
144
145private:
146 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
147};
148
149IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
150
151////////////////////////////////////////////////////////////////////////////////
152
153status_t BnCrypto::onTransact(
154 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
155 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700156 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700157 {
158 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700159 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700160
161 return OK;
162 }
163
Andreas Huber1bd139a2012-04-03 14:19:20 -0700164 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700165 {
166 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700167 uint8_t uuid[16];
168 data.read(uuid, sizeof(uuid));
169 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700170
171 return OK;
172 }
173
Andreas Huber1bd139a2012-04-03 14:19:20 -0700174 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700175 {
176 CHECK_INTERFACE(ICrypto, data, reply);
177
Andreas Huber1bd139a2012-04-03 14:19:20 -0700178 uint8_t uuid[16];
179 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700180
Andreas Huber1bd139a2012-04-03 14:19:20 -0700181 size_t opaqueSize = data.readInt32();
182 void *opaqueData = malloc(opaqueSize);
183 data.read(opaqueData, opaqueSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700184
Andreas Huber1bd139a2012-04-03 14:19:20 -0700185 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
186
187 free(opaqueData);
188 opaqueData = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700189
190 return OK;
191 }
192
Andreas Huber1bd139a2012-04-03 14:19:20 -0700193 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700194 {
195 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700196 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700197
198 return OK;
199 }
200
Andreas Huber1bd139a2012-04-03 14:19:20 -0700201 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700202 {
203 CHECK_INTERFACE(ICrypto, data, reply);
204
Andreas Huber1bd139a2012-04-03 14:19:20 -0700205 const char *mime = data.readCString();
206 reply->writeInt32(requiresSecureDecoderComponent(mime));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700207
Andreas Huber1bd139a2012-04-03 14:19:20 -0700208 return OK;
209 }
210
211 case DECRYPT:
212 {
213 CHECK_INTERFACE(ICrypto, data, reply);
214
215 bool secure = data.readInt32() != 0;
216 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
217
218 uint8_t key[16];
219 data.read(key, sizeof(key));
220
221 uint8_t iv[16];
222 data.read(iv, sizeof(iv));
223
224 size_t totalSize = data.readInt32();
225 void *srcData = malloc(totalSize);
226 data.read(srcData, totalSize);
227
228 int32_t numSubSamples = data.readInt32();
229
230 CryptoPlugin::SubSample *subSamples =
231 new CryptoPlugin::SubSample[numSubSamples];
232
233 data.read(
234 subSamples,
235 sizeof(CryptoPlugin::SubSample) * numSubSamples);
236
237 void *dstPtr;
238 if (secure) {
239 dstPtr = (void *)data.readIntPtr();
240 } else {
241 dstPtr = malloc(totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700242 }
243
Andreas Huber1bd139a2012-04-03 14:19:20 -0700244 status_t err = decrypt(
245 secure,
246 key,
247 iv,
248 mode,
249 srcData,
250 subSamples, numSubSamples,
251 dstPtr);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700252
Andreas Huber1bd139a2012-04-03 14:19:20 -0700253 reply->writeInt32(err);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700254
Andreas Huber1bd139a2012-04-03 14:19:20 -0700255 if (!secure) {
256 if (err == OK) {
257 reply->write(dstPtr, totalSize);
258 }
259
260 free(dstPtr);
261 dstPtr = NULL;
262 }
263
264 delete[] subSamples;
265 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700266
267 free(srcData);
268 srcData = NULL;
269
Andreas Hubered3e3e02012-03-26 11:13:27 -0700270 return OK;
271 }
272
273 default:
274 return BBinder::onTransact(code, data, reply, flags);
275 }
276}
277
278} // namespace android
279