blob: 92c954802752d1e6a4cebb251f6b55cb81edf9d9 [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
Jeff Tinkera53d6552017-01-20 00:31:46 -080097 virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
Jeff Tinker18cb1ec2015-12-18 11:55:22 -080098 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
Jeff Tinkera53d6552017-01-20 00:31:46 -080099 const sp<IMemory> &source, size_t offset,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700100 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
Jeff Tinkera53d6552017-01-20 00:31:46 -0800101 const DestinationBuffer &destination, AString *errorDetailMsg) {
Andreas Hubered3e3e02012-03-26 11:13:27 -0700102 Parcel data, reply;
103 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
Andreas Huber1bd139a2012-04-03 14:19:20 -0700104 data.writeInt32(mode);
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800105 data.writeInt32(pattern.mEncryptBlocks);
106 data.writeInt32(pattern.mSkipBlocks);
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);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800128 data.writeStrongBinder(IInterface::asBinder(source));
Jeff Tinkerc481b502015-04-06 18:21:05 -0700129 data.writeInt32(offset);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700130
Andreas Huber1bd139a2012-04-03 14:19:20 -0700131 data.writeInt32(numSubSamples);
132 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700133
Jeff Tinkera53d6552017-01-20 00:31:46 -0800134 data.writeInt32((int32_t)destination.mType);
135 if (destination.mType == kDestinationTypeNativeHandle) {
136 if (destination.mHandle == NULL) {
137 return BAD_VALUE;
138 }
139 data.writeNativeHandle(destination.mHandle);
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800140 } else {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800141 if (destination.mSharedMemory == NULL) {
142 return BAD_VALUE;
143 }
144 data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
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)) {
Jeff Tinker0be134a2017-03-09 17:01:10 -0800152 AString msg = reply.readCString();
153 if (errorDetailMsg) {
154 *errorDetailMsg = msg;
155 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700156 }
157
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700158 return result;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700159 }
160
Jeff Tinker2514d082014-11-03 13:29:35 -0800161 virtual void notifyResolution(
162 uint32_t width, uint32_t height) {
163 Parcel data, reply;
164 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
165 data.writeInt32(width);
166 data.writeInt32(height);
167 remote()->transact(NOTIFY_RESOLUTION, data, &reply);
168 }
169
Jeff Tinker18495702015-04-10 04:10:59 -0700170 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
171 Parcel data, reply;
172 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
173
174 writeVector(data, sessionId);
175 remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
176
177 return reply.readInt32();
178 }
179
Andreas Hubered3e3e02012-03-26 11:13:27 -0700180private:
Jeff Tinker18495702015-04-10 04:10:59 -0700181 void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
182 uint32_t size = reply.readInt32();
183 vector.insertAt((size_t)0, size);
184 reply.read(vector.editArray(), size);
185 }
186
187 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
188 data.writeInt32(vector.size());
189 data.write(vector.array(), vector.size());
190 }
191
Andreas Hubered3e3e02012-03-26 11:13:27 -0700192 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
193};
194
195IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
196
197////////////////////////////////////////////////////////////////////////////////
198
Jeff Tinker18495702015-04-10 04:10:59 -0700199void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
200 uint32_t size = data.readInt32();
201 vector.insertAt((size_t)0, size);
202 data.read(vector.editArray(), size);
203}
204
205void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
206 reply->writeInt32(vector.size());
207 reply->write(vector.array(), vector.size());
208}
209
Andreas Hubered3e3e02012-03-26 11:13:27 -0700210status_t BnCrypto::onTransact(
211 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
212 switch (code) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700213 case INIT_CHECK:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700214 {
215 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700216 reply->writeInt32(initCheck());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700217
218 return OK;
219 }
220
Andreas Huber1bd139a2012-04-03 14:19:20 -0700221 case IS_CRYPTO_SUPPORTED:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700222 {
223 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700224 uint8_t uuid[16];
225 data.read(uuid, sizeof(uuid));
226 reply->writeInt32(isCryptoSchemeSupported(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700227
228 return OK;
229 }
230
Andreas Huber1bd139a2012-04-03 14:19:20 -0700231 case CREATE_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700232 {
233 CHECK_INTERFACE(ICrypto, data, reply);
234
Andreas Huber1bd139a2012-04-03 14:19:20 -0700235 uint8_t uuid[16];
236 data.read(uuid, sizeof(uuid));
Andreas Hubered3e3e02012-03-26 11:13:27 -0700237
Andreas Huber1bd139a2012-04-03 14:19:20 -0700238 size_t opaqueSize = data.readInt32();
Andreas Huber705868c2012-04-11 15:41:45 -0700239 void *opaqueData = NULL;
240
Edwin Wong9247e102017-03-13 16:38:20 -0700241 const size_t kMaxOpaqueSize = 100 * 1024;
242 if (opaqueSize > kMaxOpaqueSize) {
243 return BAD_VALUE;
Andreas Huber705868c2012-04-11 15:41:45 -0700244 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700245
Edwin Wong9247e102017-03-13 16:38:20 -0700246 opaqueData = malloc(opaqueSize);
247 if (NULL == opaqueData) {
248 return NO_MEMORY;
249 }
250
251 data.read(opaqueData, opaqueSize);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700252 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
253
Edwin Wong9247e102017-03-13 16:38:20 -0700254 free(opaqueData);
255 opaqueData = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700256
257 return OK;
258 }
259
Andreas Huber1bd139a2012-04-03 14:19:20 -0700260 case DESTROY_PLUGIN:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700261 {
262 CHECK_INTERFACE(ICrypto, data, reply);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700263 reply->writeInt32(destroyPlugin());
Andreas Hubered3e3e02012-03-26 11:13:27 -0700264
265 return OK;
266 }
267
Andreas Huber1bd139a2012-04-03 14:19:20 -0700268 case REQUIRES_SECURE_COMPONENT:
Andreas Hubered3e3e02012-03-26 11:13:27 -0700269 {
270 CHECK_INTERFACE(ICrypto, data, reply);
271
Andreas Huber1bd139a2012-04-03 14:19:20 -0700272 const char *mime = data.readCString();
Wei Jia2afac0c2016-01-07 12:13:07 -0800273 if (mime == NULL) {
274 reply->writeInt32(BAD_VALUE);
275 } else {
276 reply->writeInt32(requiresSecureDecoderComponent(mime));
277 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700278
Andreas Huber1bd139a2012-04-03 14:19:20 -0700279 return OK;
280 }
281
282 case DECRYPT:
283 {
284 CHECK_INTERFACE(ICrypto, data, reply);
285
Andreas Huber1bd139a2012-04-03 14:19:20 -0700286 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800287 CryptoPlugin::Pattern pattern;
288 pattern.mEncryptBlocks = data.readInt32();
289 pattern.mSkipBlocks = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700290
291 uint8_t key[16];
292 data.read(key, sizeof(key));
293
294 uint8_t iv[16];
295 data.read(iv, sizeof(iv));
296
297 size_t totalSize = data.readInt32();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800298 sp<IMemory> source =
Jeff Tinkerc481b502015-04-06 18:21:05 -0700299 interface_cast<IMemory>(data.readStrongBinder());
Jeff Tinkera53d6552017-01-20 00:31:46 -0800300 if (source == NULL) {
Wei Jia2afac0c2016-01-07 12:13:07 -0800301 reply->writeInt32(BAD_VALUE);
302 return OK;
303 }
Jeff Tinkerc481b502015-04-06 18:21:05 -0700304 int32_t offset = data.readInt32();
Andreas Huber1bd139a2012-04-03 14:19:20 -0700305
306 int32_t numSubSamples = data.readInt32();
Jeff Tinker4183d532016-05-20 17:19:31 -0700307 if (numSubSamples < 0 || numSubSamples > 0xffff) {
308 reply->writeInt32(BAD_VALUE);
309 return OK;
310 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700311
312 CryptoPlugin::SubSample *subSamples =
Jeff Tinkera53d6552017-01-20 00:31:46 -0800313 new CryptoPlugin::SubSample[numSubSamples];
Andreas Huber1bd139a2012-04-03 14:19:20 -0700314
Jeff Tinkera53d6552017-01-20 00:31:46 -0800315 data.read(subSamples,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700316 sizeof(CryptoPlugin::SubSample) * numSubSamples);
317
Jeff Tinkera53d6552017-01-20 00:31:46 -0800318 DestinationBuffer destination;
319 destination.mType = (DestinationType)data.readInt32();
320 if (destination.mType == kDestinationTypeNativeHandle) {
321 destination.mHandle = data.readNativeHandle();
322 if (destination.mHandle == NULL) {
323 reply->writeInt32(BAD_VALUE);
324 return OK;
325 }
326 } else if (destination.mType == kDestinationTypeSharedMemory) {
327 destination.mSharedMemory =
328 interface_cast<IMemory>(data.readStrongBinder());
329 if (destination.mSharedMemory == NULL) {
330 reply->writeInt32(BAD_VALUE);
331 return OK;
332 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700333 }
334
Andreas Huber5b8987e2012-04-19 12:52:20 -0700335 AString errorDetailMsg;
Jeff Tinkerc481b502015-04-06 18:21:05 -0700336 ssize_t result;
337
Jeff Tinkerc6fc6a32015-08-26 20:22:39 -0700338 size_t sumSubsampleSizes = 0;
339 bool overflow = false;
340 for (int32_t i = 0; i < numSubSamples; ++i) {
341 CryptoPlugin::SubSample &ss = subSamples[i];
342 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
343 sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
344 } else {
345 overflow = true;
346 }
347 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
348 sumSubsampleSizes += ss.mNumBytesOfClearData;
349 } else {
350 overflow = true;
351 }
352 }
353
354 if (overflow || sumSubsampleSizes != totalSize) {
355 result = -EINVAL;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800356 } else if (totalSize > source->size()) {
Jeff Tinkerbb4877d2015-12-04 16:29:16 -0800357 result = -EINVAL;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800358 } else if ((size_t)offset > source->size() - totalSize) {
Jeff Tinkerc481b502015-04-06 18:21:05 -0700359 result = -EINVAL;
360 } else {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800361 result = decrypt(key, iv, mode, pattern, source, offset,
362 subSamples, numSubSamples, destination, &errorDetailMsg);
Jeff Tinkerc481b502015-04-06 18:21:05 -0700363 }
Andreas Hubered3e3e02012-03-26 11:13:27 -0700364
Edwin Wongfa2b8f22012-07-10 20:01:13 -0700365 reply->writeInt32(result);
Andreas Hubered3e3e02012-03-26 11:13:27 -0700366
Jeff Tinkerceffd8c2015-05-05 15:09:14 -0700367 if (isCryptoError(result)) {
Andreas Huber5b8987e2012-04-19 12:52:20 -0700368 reply->writeCString(errorDetailMsg.c_str());
369 }
370
Jeff Tinkera53d6552017-01-20 00:31:46 -0800371 if (destination.mType == kDestinationTypeNativeHandle) {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800372 int err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800373 if ((err = native_handle_close(destination.mHandle)) < 0) {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800374 ALOGW("secure buffer native_handle_close failed: %d", err);
375 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800376 if ((err = native_handle_delete(destination.mHandle)) < 0) {
Jeff Tinker9ac86b32016-01-23 17:27:58 -0800377 ALOGW("secure buffer native_handle_delete failed: %d", err);
378 }
Andreas Huber1bd139a2012-04-03 14:19:20 -0700379 }
380
381 delete[] subSamples;
382 subSamples = NULL;
Andreas Hubered3e3e02012-03-26 11:13:27 -0700383
Andreas Hubered3e3e02012-03-26 11:13:27 -0700384 return OK;
385 }
386
Jeff Tinker2514d082014-11-03 13:29:35 -0800387 case NOTIFY_RESOLUTION:
388 {
389 CHECK_INTERFACE(ICrypto, data, reply);
390
391 int32_t width = data.readInt32();
392 int32_t height = data.readInt32();
393 notifyResolution(width, height);
394
395 return OK;
396 }
397
Jeff Tinker18495702015-04-10 04:10:59 -0700398 case SET_MEDIADRM_SESSION:
399 {
400 CHECK_INTERFACE(IDrm, data, reply);
401 Vector<uint8_t> sessionId;
402 readVector(data, sessionId);
403 reply->writeInt32(setMediaDrmSession(sessionId));
404 return OK;
405 }
406
Andreas Hubered3e3e02012-03-26 11:13:27 -0700407 default:
408 return BBinder::onTransact(code, data, reply, flags);
409 }
410}
411
412} // namespace android