1 /*
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 <binder/Parcel.h>
20 #include <binder/IMemory.h>
21 #include <cutils/log.h>
22 #include <media/stagefright/MediaErrors.h>
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/AString.h>
25 #include <mediadrm/ICrypto.h>
26 #include <utils/Log.h>
27
28 namespace android {
29
30 enum {
31 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
32 IS_CRYPTO_SUPPORTED,
33 CREATE_PLUGIN,
34 DESTROY_PLUGIN,
35 REQUIRES_SECURE_COMPONENT,
36 DECRYPT,
37 NOTIFY_RESOLUTION,
38 SET_MEDIADRM_SESSION,
39 SET_HEAP,
40 UNSET_HEAP,
41 };
42
43 struct BpCrypto : public BpInterface<ICrypto> {
BpCryptoandroid::BpCrypto44 explicit BpCrypto(const sp<IBinder> &impl)
45 : BpInterface<ICrypto>(impl) {
46 }
47
initCheckandroid::BpCrypto48 virtual status_t initCheck() const {
49 Parcel data, reply;
50 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
51 remote()->transact(INIT_CHECK, data, &reply);
52
53 return reply.readInt32();
54 }
55
isCryptoSchemeSupportedandroid::BpCrypto56 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
57 Parcel data, reply;
58 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
59 data.write(uuid, 16);
60 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
61
62 return reply.readInt32() != 0;
63 }
64
createPluginandroid::BpCrypto65 virtual status_t createPlugin(
66 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
67 Parcel data, reply;
68 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
69 data.write(uuid, 16);
70 data.writeInt32(opaqueSize);
71
72 if (opaqueSize > 0) {
73 data.write(opaqueData, opaqueSize);
74 }
75
76 remote()->transact(CREATE_PLUGIN, data, &reply);
77
78 return reply.readInt32();
79 }
80
destroyPluginandroid::BpCrypto81 virtual status_t destroyPlugin() {
82 Parcel data, reply;
83 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
84 remote()->transact(DESTROY_PLUGIN, data, &reply);
85
86 return reply.readInt32();
87 }
88
requiresSecureDecoderComponentandroid::BpCrypto89 virtual bool requiresSecureDecoderComponent(
90 const char *mime) const {
91 Parcel data, reply;
92 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
93 data.writeCString(mime);
94 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
95
96 return reply.readInt32() != 0;
97 }
98
decryptandroid::BpCrypto99 virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
100 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
101 const SourceBuffer &source, size_t offset,
102 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
103 const DestinationBuffer &destination, AString *errorDetailMsg) {
104 Parcel data, reply;
105 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
106 data.writeInt32(mode);
107 data.writeInt32(pattern.mEncryptBlocks);
108 data.writeInt32(pattern.mSkipBlocks);
109
110 static const uint8_t kDummy[16] = { 0 };
111
112 if (key == NULL) {
113 key = kDummy;
114 }
115
116 if (iv == NULL) {
117 iv = kDummy;
118 }
119
120 data.write(key, 16);
121 data.write(iv, 16);
122
123 size_t totalSize = 0;
124 for (size_t i = 0; i < numSubSamples; ++i) {
125 totalSize += subSamples[i].mNumBytesOfEncryptedData;
126 totalSize += subSamples[i].mNumBytesOfClearData;
127 }
128
129 data.writeInt32(totalSize);
130 data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
131 data.writeInt32(source.mHeapSeqNum);
132 data.writeInt32(offset);
133
134 data.writeInt32(numSubSamples);
135 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
136
137 data.writeInt32((int32_t)destination.mType);
138 if (destination.mType == kDestinationTypeNativeHandle) {
139 if (destination.mHandle == NULL) {
140 return BAD_VALUE;
141 }
142 data.writeNativeHandle(destination.mHandle);
143 } else {
144 if (destination.mSharedMemory == NULL) {
145 return BAD_VALUE;
146 }
147 data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
148 }
149
150 remote()->transact(DECRYPT, data, &reply);
151
152 ssize_t result = reply.readInt32();
153
154 if (isCryptoError(result)) {
155 AString msg = reply.readCString();
156 if (errorDetailMsg) {
157 *errorDetailMsg = msg;
158 }
159 }
160
161 return result;
162 }
163
notifyResolutionandroid::BpCrypto164 virtual void notifyResolution(
165 uint32_t width, uint32_t height) {
166 Parcel data, reply;
167 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
168 data.writeInt32(width);
169 data.writeInt32(height);
170 remote()->transact(NOTIFY_RESOLUTION, data, &reply);
171 }
172
setMediaDrmSessionandroid::BpCrypto173 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
174 Parcel data, reply;
175 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
176
177 writeVector(data, sessionId);
178 remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
179
180 return reply.readInt32();
181 }
182
setHeapandroid::BpCrypto183 virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
184 Parcel data, reply;
185 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
186 data.writeStrongBinder(IInterface::asBinder(heap));
187 status_t err = remote()->transact(SET_HEAP, data, &reply);
188 if (err != NO_ERROR) {
189 return -1;
190 }
191 int32_t seqNum;
192 if (reply.readInt32(&seqNum) != NO_ERROR) {
193 return -1;
194 }
195 return seqNum;
196 }
197
unsetHeapandroid::BpCrypto198 virtual void unsetHeap(int32_t seqNum) {
199 Parcel data, reply;
200 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
201 data.writeInt32(seqNum);
202 remote()->transact(UNSET_HEAP, data, &reply);
203 return;
204 }
205
206
207 private:
readVectorandroid::BpCrypto208 void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
209 uint32_t size = reply.readInt32();
210 vector.insertAt((size_t)0, size);
211 reply.read(vector.editArray(), size);
212 }
213
writeVectorandroid::BpCrypto214 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
215 data.writeInt32(vector.size());
216 data.write(vector.array(), vector.size());
217 }
218
219 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
220 };
221
222 IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
223
224 ////////////////////////////////////////////////////////////////////////////////
225
readVector(const Parcel & data,Vector<uint8_t> & vector) const226 void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
227 uint32_t size = data.readInt32();
228 if (vector.insertAt((size_t)0, size) < 0) {
229 vector.clear();
230 }
231 if (data.read(vector.editArray(), size) != NO_ERROR) {
232 vector.clear();
233 android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
234 }
235 }
236
writeVector(Parcel * reply,Vector<uint8_t> const & vector) const237 void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
238 reply->writeInt32(vector.size());
239 reply->write(vector.array(), vector.size());
240 }
241
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)242 status_t BnCrypto::onTransact(
243 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
244 switch (code) {
245 case INIT_CHECK:
246 {
247 CHECK_INTERFACE(ICrypto, data, reply);
248 reply->writeInt32(initCheck());
249
250 return OK;
251 }
252
253 case IS_CRYPTO_SUPPORTED:
254 {
255 CHECK_INTERFACE(ICrypto, data, reply);
256 uint8_t uuid[16];
257 data.read(uuid, sizeof(uuid));
258 reply->writeInt32(isCryptoSchemeSupported(uuid));
259
260 return OK;
261 }
262
263 case CREATE_PLUGIN:
264 {
265 CHECK_INTERFACE(ICrypto, data, reply);
266
267 uint8_t uuid[16];
268 data.read(uuid, sizeof(uuid));
269
270 size_t opaqueSize = data.readInt32();
271 void *opaqueData = NULL;
272
273 const size_t kMaxOpaqueSize = 100 * 1024;
274 if (opaqueSize > kMaxOpaqueSize) {
275 return BAD_VALUE;
276 }
277
278 opaqueData = malloc(opaqueSize);
279 if (NULL == opaqueData) {
280 return NO_MEMORY;
281 }
282
283 data.read(opaqueData, opaqueSize);
284 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
285
286 free(opaqueData);
287 opaqueData = NULL;
288
289 return OK;
290 }
291
292 case DESTROY_PLUGIN:
293 {
294 CHECK_INTERFACE(ICrypto, data, reply);
295 reply->writeInt32(destroyPlugin());
296
297 return OK;
298 }
299
300 case REQUIRES_SECURE_COMPONENT:
301 {
302 CHECK_INTERFACE(ICrypto, data, reply);
303
304 const char *mime = data.readCString();
305 if (mime == NULL) {
306 reply->writeInt32(BAD_VALUE);
307 } else {
308 reply->writeInt32(requiresSecureDecoderComponent(mime));
309 }
310
311 return OK;
312 }
313
314 case DECRYPT:
315 {
316 CHECK_INTERFACE(ICrypto, data, reply);
317
318 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
319 CryptoPlugin::Pattern pattern;
320 pattern.mEncryptBlocks = data.readInt32();
321 pattern.mSkipBlocks = data.readInt32();
322
323 uint8_t key[16];
324 data.read(key, sizeof(key));
325
326 uint8_t iv[16];
327 data.read(iv, sizeof(iv));
328
329 size_t totalSize = data.readInt32();
330
331 SourceBuffer source;
332
333 source.mSharedMemory =
334 interface_cast<IMemory>(data.readStrongBinder());
335 if (source.mSharedMemory == NULL) {
336 reply->writeInt32(BAD_VALUE);
337 return OK;
338 }
339 source.mHeapSeqNum = data.readInt32();
340
341 int32_t offset = data.readInt32();
342
343 int32_t numSubSamples = data.readInt32();
344 if (numSubSamples < 0 || numSubSamples > 0xffff) {
345 reply->writeInt32(BAD_VALUE);
346 return OK;
347 }
348
349 std::unique_ptr<CryptoPlugin::SubSample[]> subSamples =
350 std::make_unique<CryptoPlugin::SubSample[]>(numSubSamples);
351
352 data.read(subSamples.get(),
353 sizeof(CryptoPlugin::SubSample) * numSubSamples);
354
355 DestinationBuffer destination;
356 destination.mType = (DestinationType)data.readInt32();
357 if (destination.mType == kDestinationTypeNativeHandle) {
358 destination.mHandle = data.readNativeHandle();
359 if (destination.mHandle == NULL) {
360 reply->writeInt32(BAD_VALUE);
361 return OK;
362 }
363 } else if (destination.mType == kDestinationTypeSharedMemory) {
364 destination.mSharedMemory =
365 interface_cast<IMemory>(data.readStrongBinder());
366 if (destination.mSharedMemory == NULL) {
367 reply->writeInt32(BAD_VALUE);
368 return OK;
369 }
370 sp<IMemory> dest = destination.mSharedMemory;
371 if (totalSize > dest->size() ||
372 (size_t)dest->offset() > dest->size() - totalSize) {
373 reply->writeInt32(BAD_VALUE);
374 android_errorWriteLog(0x534e4554, "71389378");
375 return OK;
376 }
377 } else {
378 reply->writeInt32(BAD_VALUE);
379 android_errorWriteLog(0x534e4554, "70526702");
380 return OK;
381 }
382
383 AString errorDetailMsg;
384 ssize_t result;
385
386 size_t sumSubsampleSizes = 0;
387 bool overflow = false;
388 for (int32_t i = 0; i < numSubSamples; ++i) {
389 CryptoPlugin::SubSample &ss = subSamples[i];
390 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
391 sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
392 } else {
393 overflow = true;
394 }
395 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
396 sumSubsampleSizes += ss.mNumBytesOfClearData;
397 } else {
398 overflow = true;
399 }
400 }
401
402 if (overflow || sumSubsampleSizes != totalSize) {
403 result = -EINVAL;
404 } else if (totalSize > source.mSharedMemory->size()) {
405 result = -EINVAL;
406 } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
407 result = -EINVAL;
408 } else {
409 result = decrypt(key, iv, mode, pattern, source, offset,
410 subSamples.get(), numSubSamples, destination, &errorDetailMsg);
411 }
412
413 reply->writeInt32(result);
414
415 if (isCryptoError(result)) {
416 reply->writeCString(errorDetailMsg.c_str());
417 }
418
419 if (destination.mType == kDestinationTypeNativeHandle) {
420 int err;
421 if ((err = native_handle_close(destination.mHandle)) < 0) {
422 ALOGW("secure buffer native_handle_close failed: %d", err);
423 }
424 if ((err = native_handle_delete(destination.mHandle)) < 0) {
425 ALOGW("secure buffer native_handle_delete failed: %d", err);
426 }
427 }
428
429 subSamples.reset();
430 return OK;
431 }
432
433 case NOTIFY_RESOLUTION:
434 {
435 CHECK_INTERFACE(ICrypto, data, reply);
436
437 int32_t width = data.readInt32();
438 int32_t height = data.readInt32();
439 notifyResolution(width, height);
440
441 return OK;
442 }
443
444 case SET_MEDIADRM_SESSION:
445 {
446 CHECK_INTERFACE(IDrm, data, reply);
447 Vector<uint8_t> sessionId;
448 readVector(data, sessionId);
449 reply->writeInt32(setMediaDrmSession(sessionId));
450 return OK;
451 }
452
453 case SET_HEAP:
454 {
455 CHECK_INTERFACE(ICrypto, data, reply);
456 sp<IMemoryHeap> heap =
457 interface_cast<IMemoryHeap>(data.readStrongBinder());
458 reply->writeInt32(setHeap(heap));
459 return OK;
460 }
461
462 case UNSET_HEAP:
463 {
464 CHECK_INTERFACE(ICrypto, data, reply);
465 int32_t seqNum = data.readInt32();
466 unsetHeap(seqNum);
467 return OK;
468 }
469
470 default:
471 return BBinder::onTransact(code, data, reply, flags);
472 }
473 }
474
475 } // namespace android
476