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 <utils/Log.h>
20
21#include <binder/Parcel.h>
22#include <binder/IMemory.h>
23#include <media/ICrypto.h>
24#include <media/stagefright/MediaErrors.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AString.h>
27
28namespace android {
29
30enum {
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
43struct BpCrypto : public BpInterface<ICrypto> {
44    explicit BpCrypto(const sp<IBinder> &impl)
45        : BpInterface<ICrypto>(impl) {
46    }
47
48    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
56    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
65    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
81    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
89    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
99    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
164    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
173    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
183    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
198    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
207private:
208    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
214    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
222IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
223
224////////////////////////////////////////////////////////////////////////////////
225
226void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
227    uint32_t size = data.readInt32();
228    vector.insertAt((size_t)0, size);
229    data.read(vector.editArray(), size);
230}
231
232void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
233    reply->writeInt32(vector.size());
234    reply->write(vector.array(), vector.size());
235}
236
237status_t BnCrypto::onTransact(
238    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
239    switch (code) {
240        case INIT_CHECK:
241        {
242            CHECK_INTERFACE(ICrypto, data, reply);
243            reply->writeInt32(initCheck());
244
245            return OK;
246        }
247
248        case IS_CRYPTO_SUPPORTED:
249        {
250            CHECK_INTERFACE(ICrypto, data, reply);
251            uint8_t uuid[16];
252            data.read(uuid, sizeof(uuid));
253            reply->writeInt32(isCryptoSchemeSupported(uuid));
254
255            return OK;
256        }
257
258        case CREATE_PLUGIN:
259        {
260            CHECK_INTERFACE(ICrypto, data, reply);
261
262            uint8_t uuid[16];
263            data.read(uuid, sizeof(uuid));
264
265            size_t opaqueSize = data.readInt32();
266            void *opaqueData = NULL;
267
268            const size_t kMaxOpaqueSize = 100 * 1024;
269            if (opaqueSize > kMaxOpaqueSize) {
270                return BAD_VALUE;
271            }
272
273            opaqueData = malloc(opaqueSize);
274            if (NULL == opaqueData) {
275                return NO_MEMORY;
276            }
277
278            data.read(opaqueData, opaqueSize);
279            reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
280
281            free(opaqueData);
282            opaqueData = NULL;
283
284            return OK;
285        }
286
287        case DESTROY_PLUGIN:
288        {
289            CHECK_INTERFACE(ICrypto, data, reply);
290            reply->writeInt32(destroyPlugin());
291
292            return OK;
293        }
294
295        case REQUIRES_SECURE_COMPONENT:
296        {
297            CHECK_INTERFACE(ICrypto, data, reply);
298
299            const char *mime = data.readCString();
300            if (mime == NULL) {
301                reply->writeInt32(BAD_VALUE);
302            } else {
303                reply->writeInt32(requiresSecureDecoderComponent(mime));
304            }
305
306            return OK;
307        }
308
309        case DECRYPT:
310        {
311            CHECK_INTERFACE(ICrypto, data, reply);
312
313            CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
314            CryptoPlugin::Pattern pattern;
315            pattern.mEncryptBlocks = data.readInt32();
316            pattern.mSkipBlocks = data.readInt32();
317
318            uint8_t key[16];
319            data.read(key, sizeof(key));
320
321            uint8_t iv[16];
322            data.read(iv, sizeof(iv));
323
324            size_t totalSize = data.readInt32();
325
326            SourceBuffer source;
327
328            source.mSharedMemory =
329                interface_cast<IMemory>(data.readStrongBinder());
330            if (source.mSharedMemory == NULL) {
331                reply->writeInt32(BAD_VALUE);
332                return OK;
333            }
334            source.mHeapSeqNum = data.readInt32();
335
336            int32_t offset = data.readInt32();
337
338            int32_t numSubSamples = data.readInt32();
339            if (numSubSamples < 0 || numSubSamples > 0xffff) {
340                reply->writeInt32(BAD_VALUE);
341                return OK;
342            }
343
344            CryptoPlugin::SubSample *subSamples =
345                    new CryptoPlugin::SubSample[numSubSamples];
346
347            data.read(subSamples,
348                    sizeof(CryptoPlugin::SubSample) * numSubSamples);
349
350            DestinationBuffer destination;
351            destination.mType = (DestinationType)data.readInt32();
352            if (destination.mType == kDestinationTypeNativeHandle) {
353                destination.mHandle = data.readNativeHandle();
354                if (destination.mHandle == NULL) {
355                    reply->writeInt32(BAD_VALUE);
356                    return OK;
357                }
358            } else if (destination.mType == kDestinationTypeSharedMemory) {
359                destination.mSharedMemory =
360                        interface_cast<IMemory>(data.readStrongBinder());
361                if (destination.mSharedMemory == NULL) {
362                    reply->writeInt32(BAD_VALUE);
363                    return OK;
364                }
365            }
366
367            AString errorDetailMsg;
368            ssize_t result;
369
370            size_t sumSubsampleSizes = 0;
371            bool overflow = false;
372            for (int32_t i = 0; i < numSubSamples; ++i) {
373                CryptoPlugin::SubSample &ss = subSamples[i];
374                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
375                    sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
376                } else {
377                    overflow = true;
378                }
379                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
380                    sumSubsampleSizes += ss.mNumBytesOfClearData;
381                } else {
382                    overflow = true;
383                }
384            }
385
386            if (overflow || sumSubsampleSizes != totalSize) {
387                result = -EINVAL;
388            } else if (totalSize > source.mSharedMemory->size()) {
389                result = -EINVAL;
390            } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
391                result = -EINVAL;
392            } else {
393                result = decrypt(key, iv, mode, pattern, source, offset,
394                        subSamples, numSubSamples, destination, &errorDetailMsg);
395            }
396
397            reply->writeInt32(result);
398
399            if (isCryptoError(result)) {
400                reply->writeCString(errorDetailMsg.c_str());
401            }
402
403            if (destination.mType == kDestinationTypeNativeHandle) {
404                int err;
405                if ((err = native_handle_close(destination.mHandle)) < 0) {
406                    ALOGW("secure buffer native_handle_close failed: %d", err);
407                }
408                if ((err = native_handle_delete(destination.mHandle)) < 0) {
409                    ALOGW("secure buffer native_handle_delete failed: %d", err);
410                }
411            }
412
413            delete[] subSamples;
414            subSamples = NULL;
415
416            return OK;
417        }
418
419        case NOTIFY_RESOLUTION:
420        {
421            CHECK_INTERFACE(ICrypto, data, reply);
422
423            int32_t width = data.readInt32();
424            int32_t height = data.readInt32();
425            notifyResolution(width, height);
426
427            return OK;
428        }
429
430        case SET_MEDIADRM_SESSION:
431        {
432            CHECK_INTERFACE(IDrm, data, reply);
433            Vector<uint8_t> sessionId;
434            readVector(data, sessionId);
435            reply->writeInt32(setMediaDrmSession(sessionId));
436            return OK;
437        }
438
439        case SET_HEAP:
440        {
441            CHECK_INTERFACE(ICrypto, data, reply);
442            sp<IMemoryHeap> heap =
443                interface_cast<IMemoryHeap>(data.readStrongBinder());
444            reply->writeInt32(setHeap(heap));
445            return OK;
446        }
447
448        case UNSET_HEAP:
449        {
450            CHECK_INTERFACE(ICrypto, data, reply);
451            int32_t seqNum = data.readInt32();
452            unsetHeap(seqNum);
453            return OK;
454        }
455
456        default:
457            return BBinder::onTransact(code, data, reply, flags);
458    }
459}
460
461}  // namespace android
462