• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ICrypto.h>
23 #include <media/stagefright/MediaErrors.h>
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/foundation/AString.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] = {0};
268             if (data.read(uuid, sizeof(uuid)) != NO_ERROR) {
269                 android_errorWriteLog(0x534e4554, "144767096");
270                 reply->writeInt32(BAD_VALUE);
271                 return OK;
272             }
273 
274             size_t opaqueSize = data.readInt32();
275             void *opaqueData = NULL;
276 
277             const size_t kMaxOpaqueSize = 100 * 1024;
278             if (opaqueSize > kMaxOpaqueSize) {
279                 return BAD_VALUE;
280             }
281 
282             opaqueData = malloc(opaqueSize);
283             if (NULL == opaqueData) {
284                 return NO_MEMORY;
285             }
286 
287             if (data.read(opaqueData, opaqueSize) != NO_ERROR) {
288                 android_errorWriteLog(0x534e4554, "144767096");
289                 reply->writeInt32(BAD_VALUE);
290                 return OK;
291             }
292             reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
293 
294             free(opaqueData);
295             opaqueData = NULL;
296 
297             return OK;
298         }
299 
300         case DESTROY_PLUGIN:
301         {
302             CHECK_INTERFACE(ICrypto, data, reply);
303             reply->writeInt32(destroyPlugin());
304 
305             return OK;
306         }
307 
308         case REQUIRES_SECURE_COMPONENT:
309         {
310             CHECK_INTERFACE(ICrypto, data, reply);
311 
312             const char *mime = data.readCString();
313             if (mime == NULL) {
314                 reply->writeInt32(BAD_VALUE);
315             } else {
316                 reply->writeInt32(requiresSecureDecoderComponent(mime));
317             }
318 
319             return OK;
320         }
321 
322         case DECRYPT:
323         {
324             CHECK_INTERFACE(ICrypto, data, reply);
325 
326             CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
327             CryptoPlugin::Pattern pattern;
328             pattern.mEncryptBlocks = data.readInt32();
329             pattern.mSkipBlocks = data.readInt32();
330 
331             uint8_t key[16];
332             data.read(key, sizeof(key));
333 
334             uint8_t iv[16];
335             data.read(iv, sizeof(iv));
336 
337             size_t totalSize = data.readInt32();
338 
339             SourceBuffer source;
340 
341             source.mSharedMemory =
342                 interface_cast<IMemory>(data.readStrongBinder());
343             if (source.mSharedMemory == NULL) {
344                 reply->writeInt32(BAD_VALUE);
345                 return OK;
346             }
347             source.mHeapSeqNum = data.readInt32();
348 
349             int32_t offset = data.readInt32();
350 
351             int32_t numSubSamples = data.readInt32();
352             if (numSubSamples < 0 || numSubSamples > 0xffff) {
353                 reply->writeInt32(BAD_VALUE);
354                 return OK;
355             }
356 
357             CryptoPlugin::SubSample *subSamples =
358                     new CryptoPlugin::SubSample[numSubSamples];
359 
360             data.read(subSamples,
361                     sizeof(CryptoPlugin::SubSample) * numSubSamples);
362 
363             DestinationBuffer destination;
364             destination.mType = (DestinationType)data.readInt32();
365             if (destination.mType == kDestinationTypeNativeHandle) {
366                 destination.mHandle = data.readNativeHandle();
367                 if (destination.mHandle == NULL) {
368                     reply->writeInt32(BAD_VALUE);
369                     return OK;
370                 }
371             } else if (destination.mType == kDestinationTypeSharedMemory) {
372                 destination.mSharedMemory =
373                         interface_cast<IMemory>(data.readStrongBinder());
374                 if (destination.mSharedMemory == NULL) {
375                     reply->writeInt32(BAD_VALUE);
376                     return OK;
377                 }
378                 sp<IMemory> dest = destination.mSharedMemory;
379                 if (totalSize > dest->size() ||
380                         (size_t)dest->offset() > dest->size() - totalSize) {
381                     reply->writeInt32(BAD_VALUE);
382                     android_errorWriteLog(0x534e4554, "71389378");
383                     return OK;
384                 }
385             } else {
386                 reply->writeInt32(BAD_VALUE);
387                 android_errorWriteLog(0x534e4554, "70526702");
388                 return OK;
389             }
390 
391             AString errorDetailMsg;
392             ssize_t result;
393 
394             size_t sumSubsampleSizes = 0;
395             bool overflow = false;
396             for (int32_t i = 0; i < numSubSamples; ++i) {
397                 CryptoPlugin::SubSample &ss = subSamples[i];
398                 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
399                     sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
400                 } else {
401                     overflow = true;
402                 }
403                 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
404                     sumSubsampleSizes += ss.mNumBytesOfClearData;
405                 } else {
406                     overflow = true;
407                 }
408             }
409 
410             if (overflow || sumSubsampleSizes != totalSize) {
411                 result = -EINVAL;
412             } else if (totalSize > source.mSharedMemory->size()) {
413                 result = -EINVAL;
414             } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
415                 result = -EINVAL;
416             } else {
417                 result = decrypt(key, iv, mode, pattern, source, offset,
418                         subSamples, numSubSamples, destination, &errorDetailMsg);
419             }
420 
421             reply->writeInt32(result);
422 
423             if (isCryptoError(result)) {
424                 reply->writeCString(errorDetailMsg.c_str());
425             }
426 
427             if (destination.mType == kDestinationTypeNativeHandle) {
428                 int err;
429                 if ((err = native_handle_close(destination.mHandle)) < 0) {
430                     ALOGW("secure buffer native_handle_close failed: %d", err);
431                 }
432                 if ((err = native_handle_delete(destination.mHandle)) < 0) {
433                     ALOGW("secure buffer native_handle_delete failed: %d", err);
434                 }
435             }
436 
437             delete[] subSamples;
438             subSamples = NULL;
439 
440             return OK;
441         }
442 
443         case NOTIFY_RESOLUTION:
444         {
445             CHECK_INTERFACE(ICrypto, data, reply);
446 
447             int32_t width = data.readInt32();
448             int32_t height = data.readInt32();
449             notifyResolution(width, height);
450 
451             return OK;
452         }
453 
454         case SET_MEDIADRM_SESSION:
455         {
456             CHECK_INTERFACE(IDrm, data, reply);
457             Vector<uint8_t> sessionId;
458             readVector(data, sessionId);
459             reply->writeInt32(setMediaDrmSession(sessionId));
460             return OK;
461         }
462 
463         case SET_HEAP:
464         {
465             CHECK_INTERFACE(ICrypto, data, reply);
466             sp<IMemoryHeap> heap =
467                 interface_cast<IMemoryHeap>(data.readStrongBinder());
468             reply->writeInt32(setHeap(heap));
469             return OK;
470         }
471 
472         case UNSET_HEAP:
473         {
474             CHECK_INTERFACE(ICrypto, data, reply);
475             int32_t seqNum = data.readInt32();
476             unsetHeap(seqNum);
477             return OK;
478         }
479 
480         default:
481             return BBinder::onTransact(code, data, reply, flags);
482     }
483 }
484 
485 }  // namespace android
486