blob: f352f736f7c0de6cee4529dc82635865317a267c [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> {
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070042 explicit BpCrypto(const sp<IBinder> &impl)
Andreas Hubered3e3e02012-03-26 11:13:27 -070043 : 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(
Jeff Tinker9ac86b32016-01-23 17:27:58 -080098 DestinationType dstType,
Andreas Huber1bd139a2012-04-03 14:19:20 -070099 const uint8_t key[16],
100 const uint8_t iv[16],
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800101 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
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());
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800108 data.writeInt32((int32_t)dstType);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700109 data.writeInt32(mode);
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800110 data.writeInt32(pattern.mEncryptBlocks);
111 data.writeInt32(pattern.mSkipBlocks);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700112
113 static const uint8_t kDummy[16] = { 0 };
114
115 if (key == NULL) {
116 key = kDummy;
117 }
118
119 if (iv == NULL) {
120 iv = kDummy;
121 }
122
Andreas Huber1bd139a2012-04-03 14:19:20 -0700123 data.write(key, 16);
124 data.write(iv, 16);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700125
Andreas Huber1bd139a2012-04-03 14:19:20 -0700126 size_t totalSize = 0;
127 for (size_t i = 0; i < numSubSamples; ++i) {
128 totalSize += subSamples[i].mNumBytesOfEncryptedData;
129 totalSize += subSamples[i].mNumBytesOfClearData;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700130 }
131
Andreas Huber1bd139a2012-04-03 14:19:20 -0700132 data.writeInt32(totalSize);
Jeff Tinkerc481b502015-04-06 18:21:05 -0700133 data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
134 data.writeInt32(offset);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700135
Andreas Huber1bd139a2012-04-03 14:19:20 -0700136 data.writeInt32(numSubSamples);
137 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700138
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800139 if (dstType == kDestinationTypeNativeHandle) {
140 data.writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
141 } else if (dstType == kDestinationTypeOpaqueHandle) {
Jeff Tinkerbcca9e02014-06-09 15:51:38 -0700142 data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800143 } else {
144 dstType = kDestinationTypeVmPointer;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700145 }
146
Andreas Huber1bd139a2012-04-03 14:19:20 -0700147 remote()->transact(DECRYPT, data, &reply);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700148
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700149 ssize_t result = reply.readInt32();
Andreas Hubered3e3e02012-03-26 11:13:27 -0700150
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700151 if (isCryptoError(result)) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700152 errorDetailMsg->setTo(reply.readCString());
153 }
154
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800155 if (dstType == kDestinationTypeVmPointer && result >= 0) {
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700156 reply.read(dstPtr, result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700157 }
158
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700159 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700160 }
161
Jeff Tinker2514d082014-11-03 13:29:35 -0800162 virtual void notifyResolution(
163 uint32_t width, uint32_t height) {
164 Parcel data, reply;
165 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
166 data.writeInt32(width);
167 data.writeInt32(height);
168 remote()->transact(NOTIFY_RESOLUTION, data, &reply);
169 }
170
Jeff Tinker18495702015-04-10 04:10:59 -0700171 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
172 Parcel data, reply;
173 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
174
175 writeVector(data, sessionId);
176 remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
177
178 return reply.readInt32();
179 }
180
Andreas Hubered3e3e02012-03-26 11:13:27 -0700181private:
Jeff Tinker18495702015-04-10 04:10:59 -0700182 void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
183 uint32_t size = reply.readInt32();
184 vector.insertAt((size_t)0, size);
185 reply.read(vector.editArray(), size);
186 }
187
188 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
189 data.writeInt32(vector.size());
190 data.write(vector.array(), vector.size());
191 }
192
Andreas Hubered3e3e02012-03-26 11:13:27 -0700193 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
194};
195
196IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
197
198////////////////////////////////////////////////////////////////////////////////
199
Jeff Tinker18495702015-04-10 04:10:59 -0700200void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
201 uint32_t size = data.readInt32();
202 vector.insertAt((size_t)0, size);
203 data.read(vector.editArray(), size);
204}
205
206void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
207 reply->writeInt32(vector.size());
208 reply->write(vector.array(), vector.size());
209}
210
Andreas Hubered3e3e02012-03-26 11:13:27 -0700211status_t BnCrypto::onTransact(
212 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
213 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700214 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700215 {
216 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700217 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700218
219 return OK;
220 }
221
Andreas Huber1bd139a2012-04-03 14:19:20 -0700222 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700223 {
224 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700225 uint8_t uuid[16];
226 data.read(uuid, sizeof(uuid));
227 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700228
229 return OK;
230 }
231
Andreas Huber1bd139a2012-04-03 14:19:20 -0700232 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700233 {
234 CHECK_INTERFACE(ICrypto, data, reply);
235
Andreas Huber1bd139a2012-04-03 14:19:20 -0700236 uint8_t uuid[16];
237 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700238
Andreas Huber1bd139a2012-04-03 14:19:20 -0700239 size_t opaqueSize = data.readInt32();
Andreas Huber705868c2012-04-11 15:41:45 -0700240 void *opaqueData = NULL;
241
242 if (opaqueSize > 0) {
243 opaqueData = malloc(opaqueSize);
244 data.read(opaqueData, opaqueSize);
245 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700246
Andreas Huber1bd139a2012-04-03 14:19:20 -0700247 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
248
Andreas Huber705868c2012-04-11 15:41:45 -0700249 if (opaqueData != NULL) {
250 free(opaqueData);
251 opaqueData = NULL;
252 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700253
254 return OK;
255 }
256
Andreas Huber1bd139a2012-04-03 14:19:20 -0700257 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700258 {
259 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700260 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700261
262 return OK;
263 }
264
Andreas Huber1bd139a2012-04-03 14:19:20 -0700265 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700266 {
267 CHECK_INTERFACE(ICrypto, data, reply);
268
Andreas Huber1bd139a2012-04-03 14:19:20 -0700269 const char *mime = data.readCString();
Wei Jia2afac0c2016-01-07 12:13:07 -0800270 if (mime == NULL) {
271 reply->writeInt32(BAD_VALUE);
272 } else {
273 reply->writeInt32(requiresSecureDecoderComponent(mime));
274 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700275
Andreas Huber1bd139a2012-04-03 14:19:20 -0700276 return OK;
277 }
278
279 case DECRYPT:
280 {
281 CHECK_INTERFACE(ICrypto, data, reply);
282
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800283 DestinationType dstType = (DestinationType)data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700284 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800285 CryptoPlugin::Pattern pattern;
286 pattern.mEncryptBlocks = data.readInt32();
287 pattern.mSkipBlocks = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700288
289 uint8_t key[16];
290 data.read(key, sizeof(key));
291
292 uint8_t iv[16];
293 data.read(iv, sizeof(iv));
294
295 size_t totalSize = data.readInt32();
Jeff Tinkerc481b502015-04-06 18:21:05 -0700296 sp<IMemory> sharedBuffer =
297 interface_cast<IMemory>(data.readStrongBinder());
Wei Jia2afac0c2016-01-07 12:13:07 -0800298 if (sharedBuffer == NULL) {
299 reply->writeInt32(BAD_VALUE);
300 return OK;
301 }
Jeff Tinkerc481b502015-04-06 18:21:05 -0700302 int32_t offset = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700303
304 int32_t numSubSamples = data.readInt32();
Jeff Tinker4183d532016-05-20 17:19:31 -0700305 if (numSubSamples < 0 || numSubSamples > 0xffff) {
306 reply->writeInt32(BAD_VALUE);
307 return OK;
308 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700309
310 CryptoPlugin::SubSample *subSamples =
311 new CryptoPlugin::SubSample[numSubSamples];
312
313 data.read(
314 subSamples,
315 sizeof(CryptoPlugin::SubSample) * numSubSamples);
316
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800317 native_handle_t *nativeHandle = NULL;
318 void *secureBufferId = NULL, *dstPtr;
319 if (dstType == kDestinationTypeNativeHandle) {
320 nativeHandle = data.readNativeHandle();
321 dstPtr = static_cast<void *>(nativeHandle);
322 } else if (dstType == kDestinationTypeOpaqueHandle) {
Jeff Tinkered555d72015-08-17 17:57:47 -0700323 secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800324 dstPtr = secureBufferId;
Andreas Huber1bd139a2012-04-03 14:19:20 -0700325 } else {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800326 dstType = kDestinationTypeVmPointer;
Andreas Huber1bd139a2012-04-03 14:19:20 -0700327 dstPtr = malloc(totalSize);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700328 }
329
Andreas Huber5b8987e2012-04-19 12:52:20 -0700330 AString errorDetailMsg;
Jeff Tinkerc481b502015-04-06 18:21:05 -0700331 ssize_t result;
332
Jeff Tinkerc6fc6a32015-08-26 20:22:39 -0700333 size_t sumSubsampleSizes = 0;
334 bool overflow = false;
335 for (int32_t i = 0; i < numSubSamples; ++i) {
336 CryptoPlugin::SubSample &ss = subSamples[i];
337 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
338 sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
339 } else {
340 overflow = true;
341 }
342 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
343 sumSubsampleSizes += ss.mNumBytesOfClearData;
344 } else {
345 overflow = true;
346 }
347 }
348
349 if (overflow || sumSubsampleSizes != totalSize) {
350 result = -EINVAL;
Jeff Tinkerbb4877d2015-12-04 16:29:16 -0800351 } else if (totalSize > sharedBuffer->size()) {
352 result = -EINVAL;
353 } else if ((size_t)offset > sharedBuffer->size() - totalSize) {
Jeff Tinkerc481b502015-04-06 18:21:05 -0700354 result = -EINVAL;
355 } else {
356 result = decrypt(
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800357 dstType,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700358 key,
359 iv,
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800360 mode, pattern,
Jeff Tinkerc481b502015-04-06 18:21:05 -0700361 sharedBuffer, offset,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700362 subSamples, numSubSamples,
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800363 dstPtr,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700364 &errorDetailMsg);
Jeff Tinkerc481b502015-04-06 18:21:05 -0700365 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700366
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700367 reply->writeInt32(result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700368
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700369 if (isCryptoError(result)) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700370 reply->writeCString(errorDetailMsg.c_str());
371 }
372
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800373 if (dstType == kDestinationTypeVmPointer) {
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700374 if (result >= 0) {
375 CHECK_LE(result, static_cast<ssize_t>(totalSize));
376 reply->write(dstPtr, result);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700377 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700378 free(dstPtr);
379 dstPtr = NULL;
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800380 } else if (dstType == kDestinationTypeNativeHandle) {
381 int err;
382 if ((err = native_handle_close(nativeHandle)) < 0) {
383 ALOGW("secure buffer native_handle_close failed: %d", err);
384 }
385 if ((err = native_handle_delete(nativeHandle)) < 0) {
386 ALOGW("secure buffer native_handle_delete failed: %d", err);
387 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700388 }
389
390 delete[] subSamples;
391 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700392
Andreas Hubered3e3e02012-03-26 11:13:27 -0700393 return OK;
394 }
395
Jeff Tinker2514d082014-11-03 13:29:35 -0800396 case NOTIFY_RESOLUTION:
397 {
398 CHECK_INTERFACE(ICrypto, data, reply);
399
400 int32_t width = data.readInt32();
401 int32_t height = data.readInt32();
402 notifyResolution(width, height);
403
404 return OK;
405 }
406
Jeff Tinker18495702015-04-10 04:10:59 -0700407 case SET_MEDIADRM_SESSION:
408 {
409 CHECK_INTERFACE(IDrm, data, reply);
410 Vector<uint8_t> sessionId;
411 readVector(data, sessionId);
412 reply->writeInt32(setMediaDrmSession(sessionId));
413 return OK;
414 }
415
Andreas Hubered3e3e02012-03-26 11:13:27 -0700416 default:
417 return BBinder::onTransact(code, data, reply, flags);
418 }
419}
420
421} // namespace android