blob: a398ff72447bac3b02f40a76c7188358eca19e77 [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>
Jeff Tinkerc481b502015-04-06 18:21:05 -070022#include <binder/IMemory.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070023#include <media/ICrypto.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070024#include <media/stagefright/MediaErrors.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070025#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070026#include <media/stagefright/foundation/AString.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070027
28namespace android {
29
30enum {
Andreas Huber1bd139a2012-04-03 14:19:20 -070031 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
32 IS_CRYPTO_SUPPORTED,
33 CREATE_PLUGIN,
34 DESTROY_PLUGIN,
35 REQUIRES_SECURE_COMPONENT,
36 DECRYPT,
Jeff Tinker2514d082014-11-03 13:29:35 -080037 NOTIFY_RESOLUTION,
Jeff Tinker18495702015-04-10 04:10:59 -070038 SET_MEDIADRM_SESSION,
Andreas Hubered3e3e02012-03-26 11:13:27 -070039};
40
41struct BpCrypto : public BpInterface<ICrypto> {
42 BpCrypto(const sp<IBinder> &impl)
43 : BpInterface<ICrypto>(impl) {
44 }
45
Andreas Huber1bd139a2012-04-03 14:19:20 -070046 virtual status_t initCheck() const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070047 Parcel data, reply;
48 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070049 remote()->transact(INIT_CHECK, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070050
51 return reply.readInt32();
52 }
53
Jeff Tinkerbafb6822013-03-22 15:26:39 -070054 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
Andreas Hubered3e3e02012-03-26 11:13:27 -070055 Parcel data, reply;
56 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070057 data.write(uuid, 16);
58 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
59
60 return reply.readInt32() != 0;
61 }
62
63 virtual status_t createPlugin(
64 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
65 Parcel data, reply;
66 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
67 data.write(uuid, 16);
68 data.writeInt32(opaqueSize);
Andreas Huber705868c2012-04-11 15:41:45 -070069
70 if (opaqueSize > 0) {
71 data.write(opaqueData, opaqueSize);
72 }
73
Andreas Huber1bd139a2012-04-03 14:19:20 -070074 remote()->transact(CREATE_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070075
76 return reply.readInt32();
77 }
78
Andreas Huber1bd139a2012-04-03 14:19:20 -070079 virtual status_t destroyPlugin() {
Andreas Hubered3e3e02012-03-26 11:13:27 -070080 Parcel data, reply;
81 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070082 remote()->transact(DESTROY_PLUGIN, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070083
84 return reply.readInt32();
85 }
86
Andreas Huber1bd139a2012-04-03 14:19:20 -070087 virtual bool requiresSecureDecoderComponent(
88 const char *mime) const {
Andreas Hubered3e3e02012-03-26 11:13:27 -070089 Parcel data, reply;
90 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -070091 data.writeCString(mime);
92 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -070093
Andreas Huber1bd139a2012-04-03 14:19:20 -070094 return reply.readInt32() != 0;
Andreas Hubered3e3e02012-03-26 11:13:27 -070095 }
96
Edwin Wongfa2b8f22012-07-10 20:01:13 -070097 virtual ssize_t decrypt(
Andreas Huber1bd139a2012-04-03 14:19:20 -070098 bool secure,
99 const uint8_t key[16],
100 const uint8_t iv[16],
101 CryptoPlugin::Mode mode,
Jeff Tinkerc481b502015-04-06 18:21:05 -0700102 const sp<IMemory> &sharedBuffer, size_t offset,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700103 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700104 void *dstPtr,
105 AString *errorDetailMsg) {
Andreas Hubered3e3e02012-03-26 11:13:27 -0700106 Parcel data, reply;
107 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -0700108 data.writeInt32(secure);
109 data.writeInt32(mode);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700110
111 static const uint8_t kDummy[16] = { 0 };
112
113 if (key == NULL) {
114 key = kDummy;
115 }
116
117 if (iv == NULL) {
118 iv = kDummy;
119 }
120
Andreas Huber1bd139a2012-04-03 14:19:20 -0700121 data.write(key, 16);
122 data.write(iv, 16);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700123
Andreas Huber1bd139a2012-04-03 14:19:20 -0700124 size_t totalSize = 0;
125 for (size_t i = 0; i < numSubSamples; ++i) {
126 totalSize += subSamples[i].mNumBytesOfEncryptedData;
127 totalSize += subSamples[i].mNumBytesOfClearData;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700128 }
129
Andreas Huber1bd139a2012-04-03 14:19:20 -0700130 data.writeInt32(totalSize);
Jeff Tinkerc481b502015-04-06 18:21:05 -0700131 data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
132 data.writeInt32(offset);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700133
Andreas Huber1bd139a2012-04-03 14:19:20 -0700134 data.writeInt32(numSubSamples);
135 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700136
Andreas Huber1bd139a2012-04-03 14:19:20 -0700137 if (secure) {
Jeff Tinkerbcca9e02014-06-09 15:51:38 -0700138 data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700139 }
140
Andreas Huber1bd139a2012-04-03 14:19:20 -0700141 remote()->transact(DECRYPT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700142
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700143 ssize_t result = reply.readInt32();
Andreas Hubered3e3e02012-03-26 11:13:27 -0700144
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700145 if (isCryptoError(result)) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700146 errorDetailMsg->setTo(reply.readCString());
147 }
148
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700149 if (!secure && result >= 0) {
150 reply.read(dstPtr, result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700151 }
152
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700153 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700154 }
155
Jeff Tinker2514d082014-11-03 13:29:35 -0800156 virtual void notifyResolution(
157 uint32_t width, uint32_t height) {
158 Parcel data, reply;
159 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
160 data.writeInt32(width);
161 data.writeInt32(height);
162 remote()->transact(NOTIFY_RESOLUTION, data, &reply);
163 }
164
Jeff Tinker18495702015-04-10 04:10:59 -0700165 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
166 Parcel data, reply;
167 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
168
169 writeVector(data, sessionId);
170 remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
171
172 return reply.readInt32();
173 }
174
Andreas Hubered3e3e02012-03-26 11:13:27 -0700175private:
Jeff Tinker18495702015-04-10 04:10:59 -0700176 void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
177 uint32_t size = reply.readInt32();
178 vector.insertAt((size_t)0, size);
179 reply.read(vector.editArray(), size);
180 }
181
182 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
183 data.writeInt32(vector.size());
184 data.write(vector.array(), vector.size());
185 }
186
Andreas Hubered3e3e02012-03-26 11:13:27 -0700187 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
188};
189
190IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
191
192////////////////////////////////////////////////////////////////////////////////
193
Jeff Tinker18495702015-04-10 04:10:59 -0700194void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
195 uint32_t size = data.readInt32();
196 vector.insertAt((size_t)0, size);
197 data.read(vector.editArray(), size);
198}
199
200void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
201 reply->writeInt32(vector.size());
202 reply->write(vector.array(), vector.size());
203}
204
Andreas Hubered3e3e02012-03-26 11:13:27 -0700205status_t BnCrypto::onTransact(
206 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
207 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700208 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700209 {
210 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700211 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700212
213 return OK;
214 }
215
Andreas Huber1bd139a2012-04-03 14:19:20 -0700216 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700217 {
218 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700219 uint8_t uuid[16];
220 data.read(uuid, sizeof(uuid));
221 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700222
223 return OK;
224 }
225
Andreas Huber1bd139a2012-04-03 14:19:20 -0700226 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700227 {
228 CHECK_INTERFACE(ICrypto, data, reply);
229
Andreas Huber1bd139a2012-04-03 14:19:20 -0700230 uint8_t uuid[16];
231 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700232
Andreas Huber1bd139a2012-04-03 14:19:20 -0700233 size_t opaqueSize = data.readInt32();
Andreas Huber705868c2012-04-11 15:41:45 -0700234 void *opaqueData = NULL;
235
236 if (opaqueSize > 0) {
237 opaqueData = malloc(opaqueSize);
238 data.read(opaqueData, opaqueSize);
239 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700240
Andreas Huber1bd139a2012-04-03 14:19:20 -0700241 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
242
Andreas Huber705868c2012-04-11 15:41:45 -0700243 if (opaqueData != NULL) {
244 free(opaqueData);
245 opaqueData = NULL;
246 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700247
248 return OK;
249 }
250
Andreas Huber1bd139a2012-04-03 14:19:20 -0700251 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700252 {
253 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700254 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700255
256 return OK;
257 }
258
Andreas Huber1bd139a2012-04-03 14:19:20 -0700259 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700260 {
261 CHECK_INTERFACE(ICrypto, data, reply);
262
Andreas Huber1bd139a2012-04-03 14:19:20 -0700263 const char *mime = data.readCString();
264 reply->writeInt32(requiresSecureDecoderComponent(mime));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700265
Andreas Huber1bd139a2012-04-03 14:19:20 -0700266 return OK;
267 }
268
269 case DECRYPT:
270 {
271 CHECK_INTERFACE(ICrypto, data, reply);
272
273 bool secure = data.readInt32() != 0;
274 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
275
276 uint8_t key[16];
277 data.read(key, sizeof(key));
278
279 uint8_t iv[16];
280 data.read(iv, sizeof(iv));
281
282 size_t totalSize = data.readInt32();
Jeff Tinkerc481b502015-04-06 18:21:05 -0700283 sp<IMemory> sharedBuffer =
284 interface_cast<IMemory>(data.readStrongBinder());
285 int32_t offset = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700286
287 int32_t numSubSamples = data.readInt32();
288
289 CryptoPlugin::SubSample *subSamples =
290 new CryptoPlugin::SubSample[numSubSamples];
291
292 data.read(
293 subSamples,
294 sizeof(CryptoPlugin::SubSample) * numSubSamples);
295
Jeff Tinkered555d72015-08-17 17:57:47 -0700296 void *secureBufferId, *dstPtr;
Andreas Huber1bd139a2012-04-03 14:19:20 -0700297 if (secure) {
Jeff Tinkered555d72015-08-17 17:57:47 -0700298 secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
Andreas Huber1bd139a2012-04-03 14:19:20 -0700299 } else {
Jeff Tinker3fd87602015-09-16 13:21:51 -0700300 dstPtr = calloc(1, totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700301 }
302
Andreas Huber5b8987e2012-04-19 12:52:20 -0700303 AString errorDetailMsg;
Jeff Tinkerc481b502015-04-06 18:21:05 -0700304 ssize_t result;
305
Jeff Tinkerc6fc6a32015-08-26 20:22:39 -0700306 size_t sumSubsampleSizes = 0;
307 bool overflow = false;
308 for (int32_t i = 0; i < numSubSamples; ++i) {
309 CryptoPlugin::SubSample &ss = subSamples[i];
310 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
311 sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
312 } else {
313 overflow = true;
314 }
315 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
316 sumSubsampleSizes += ss.mNumBytesOfClearData;
317 } else {
318 overflow = true;
319 }
320 }
321
322 if (overflow || sumSubsampleSizes != totalSize) {
323 result = -EINVAL;
324 } else if (offset + totalSize > sharedBuffer->size()) {
Jeff Tinkerc481b502015-04-06 18:21:05 -0700325 result = -EINVAL;
326 } else {
327 result = decrypt(
Andreas Huber1bd139a2012-04-03 14:19:20 -0700328 secure,
329 key,
330 iv,
331 mode,
Jeff Tinkerc481b502015-04-06 18:21:05 -0700332 sharedBuffer, offset,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700333 subSamples, numSubSamples,
Jeff Tinkered555d72015-08-17 17:57:47 -0700334 secure ? secureBufferId : dstPtr,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700335 &errorDetailMsg);
Jeff Tinkerc481b502015-04-06 18:21:05 -0700336 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700337
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700338 reply->writeInt32(result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700339
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700340 if (isCryptoError(result)) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700341 reply->writeCString(errorDetailMsg.c_str());
342 }
343
Andreas Huber1bd139a2012-04-03 14:19:20 -0700344 if (!secure) {
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700345 if (result >= 0) {
346 CHECK_LE(result, static_cast<ssize_t>(totalSize));
347 reply->write(dstPtr, result);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700348 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700349 free(dstPtr);
350 dstPtr = NULL;
351 }
352
353 delete[] subSamples;
354 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700355
Andreas Hubered3e3e02012-03-26 11:13:27 -0700356 return OK;
357 }
358
Jeff Tinker2514d082014-11-03 13:29:35 -0800359 case NOTIFY_RESOLUTION:
360 {
361 CHECK_INTERFACE(ICrypto, data, reply);
362
363 int32_t width = data.readInt32();
364 int32_t height = data.readInt32();
365 notifyResolution(width, height);
366
367 return OK;
368 }
369
Jeff Tinker18495702015-04-10 04:10:59 -0700370 case SET_MEDIADRM_SESSION:
371 {
372 CHECK_INTERFACE(IDrm, data, reply);
373 Vector<uint8_t> sessionId;
374 readVector(data, sessionId);
375 reply->writeInt32(setMediaDrmSession(sessionId));
376 return OK;
377 }
378
Andreas Hubered3e3e02012-03-26 11:13:27 -0700379 default:
380 return BBinder::onTransact(code, data, reply, flags);
381 }
382}
383
384} // namespace android