ICrypto.cpp revision 9ac86b3cae9a1e14b12bf97223ddde96142aae43
1ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber/*
2ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *
4ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * you may not use this file except in compliance with the License.
6ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * You may obtain a copy of the License at
7ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *
8ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *
10ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * Unless required by applicable law or agreed to in writing, software
11ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * See the License for the specific language governing permissions and
14ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber * limitations under the License.
15ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber */
16ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
17ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber//#define LOG_NDEBUG 0
18ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#define LOG_TAG "ICrypto"
19ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <utils/Log.h>
20ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
21ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <binder/Parcel.h>
22c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker#include <binder/IMemory.h>
23ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <media/ICrypto.h>
245b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber#include <media/stagefright/MediaErrors.h>
25ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber#include <media/stagefright/foundation/ADebug.h>
265b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber#include <media/stagefright/foundation/AString.h>
27ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
28ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Hubernamespace android {
29ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
30ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberenum {
311bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
321bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    IS_CRYPTO_SUPPORTED,
331bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    CREATE_PLUGIN,
341bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    DESTROY_PLUGIN,
351bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    REQUIRES_SECURE_COMPONENT,
361bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    DECRYPT,
372514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker    NOTIFY_RESOLUTION,
381849570240443d1f75775c205fa658f7070849c6Jeff Tinker    SET_MEDIADRM_SESSION,
39ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber};
40ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
41ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberstruct BpCrypto : public BpInterface<ICrypto> {
42ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    BpCrypto(const sp<IBinder> &impl)
43ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        : BpInterface<ICrypto>(impl) {
44ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
45ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
461bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    virtual status_t initCheck() const {
47ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        Parcel data, reply;
48ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
491bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        remote()->transact(INIT_CHECK, data, &reply);
50ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
51ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        return reply.readInt32();
52ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
53ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
54bafb682ec7f51486e751fea954169deb91846063Jeff Tinker    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
55ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        Parcel data, reply;
56ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
571bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.write(uuid, 16);
581bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
59ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
601bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return reply.readInt32() != 0;
61ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
62ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
631bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    virtual status_t createPlugin(
641bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
65ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        Parcel data, reply;
66ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
671bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.write(uuid, 16);
681bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.writeInt32(opaqueSize);
69705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber
70705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber        if (opaqueSize > 0) {
71705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber            data.write(opaqueData, opaqueSize);
72705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber        }
73705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber
741bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        remote()->transact(CREATE_PLUGIN, data, &reply);
75ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
76ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        return reply.readInt32();
77ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
78ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
791bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    virtual status_t destroyPlugin() {
80ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        Parcel data, reply;
81ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
821bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        remote()->transact(DESTROY_PLUGIN, data, &reply);
83ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
84ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        return reply.readInt32();
85ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
86ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
871bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    virtual bool requiresSecureDecoderComponent(
881bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            const char *mime) const {
89ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        Parcel data, reply;
90ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
911bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.writeCString(mime);
921bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
93ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
941bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        return reply.readInt32() != 0;
95ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
96ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
97fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong    virtual ssize_t decrypt(
989ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            DestinationType dstType,
991bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            const uint8_t key[16],
1001bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            const uint8_t iv[16],
10118cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
102c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker            const sp<IMemory> &sharedBuffer, size_t offset,
1031bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
1045b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            void *dstPtr,
1055b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            AString *errorDetailMsg) {
106ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        Parcel data, reply;
107ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
1089ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker        data.writeInt32((int32_t)dstType);
1091bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.writeInt32(mode);
11018cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker        data.writeInt32(pattern.mEncryptBlocks);
11118cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker        data.writeInt32(pattern.mSkipBlocks);
1124b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber
1134b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        static const uint8_t kDummy[16] = { 0 };
1144b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber
1154b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        if (key == NULL) {
1164b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            key = kDummy;
1174b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        }
1184b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber
1194b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        if (iv == NULL) {
1204b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            iv = kDummy;
1214b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        }
1224b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber
1231bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.write(key, 16);
1241bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.write(iv, 16);
1251bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1261bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        size_t totalSize = 0;
1271bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        for (size_t i = 0; i < numSubSamples; ++i) {
1281bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            totalSize += subSamples[i].mNumBytesOfEncryptedData;
1291bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            totalSize += subSamples[i].mNumBytesOfClearData;
130ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
131ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
1321bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.writeInt32(totalSize);
133c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker        data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
134c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker        data.writeInt32(offset);
1351bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1361bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.writeInt32(numSubSamples);
1371bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
1381bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1399ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker        if (dstType == kDestinationTypeNativeHandle) {
1409ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            data.writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
1419ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker        } else if (dstType == kDestinationTypeOpaqueHandle) {
142bcca9e072c1f288a53ce6862936f57dc36488f96Jeff Tinker            data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
1439ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker        } else {
1449ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            dstType = kDestinationTypeVmPointer;
1451bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        }
146ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
1471bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        remote()->transact(DECRYPT, data, &reply);
148ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
149fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong        ssize_t result = reply.readInt32();
150ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
151ceffd8cc911bd2e685b525f838cd3d8198ab35cfJeff Tinker        if (isCryptoError(result)) {
1525b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            errorDetailMsg->setTo(reply.readCString());
1535b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber        }
1545b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber
1559ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker        if (dstType == kDestinationTypeVmPointer && result >= 0) {
156fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong            reply.read(dstPtr, result);
157ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
158ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
159fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong        return result;
160ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
161ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
1622514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker    virtual void notifyResolution(
1632514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        uint32_t width, uint32_t height) {
1642514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        Parcel data, reply;
1652514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
1662514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        data.writeInt32(width);
1672514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        data.writeInt32(height);
1682514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        remote()->transact(NOTIFY_RESOLUTION, data, &reply);
1692514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker    }
1702514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker
1711849570240443d1f75775c205fa658f7070849c6Jeff Tinker    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
1721849570240443d1f75775c205fa658f7070849c6Jeff Tinker        Parcel data, reply;
1731849570240443d1f75775c205fa658f7070849c6Jeff Tinker        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
1741849570240443d1f75775c205fa658f7070849c6Jeff Tinker
1751849570240443d1f75775c205fa658f7070849c6Jeff Tinker        writeVector(data, sessionId);
1761849570240443d1f75775c205fa658f7070849c6Jeff Tinker        remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
1771849570240443d1f75775c205fa658f7070849c6Jeff Tinker
1781849570240443d1f75775c205fa658f7070849c6Jeff Tinker        return reply.readInt32();
1791849570240443d1f75775c205fa658f7070849c6Jeff Tinker    }
1801849570240443d1f75775c205fa658f7070849c6Jeff Tinker
181ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberprivate:
1821849570240443d1f75775c205fa658f7070849c6Jeff Tinker    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
1831849570240443d1f75775c205fa658f7070849c6Jeff Tinker        uint32_t size = reply.readInt32();
1841849570240443d1f75775c205fa658f7070849c6Jeff Tinker        vector.insertAt((size_t)0, size);
1851849570240443d1f75775c205fa658f7070849c6Jeff Tinker        reply.read(vector.editArray(), size);
1861849570240443d1f75775c205fa658f7070849c6Jeff Tinker    }
1871849570240443d1f75775c205fa658f7070849c6Jeff Tinker
1881849570240443d1f75775c205fa658f7070849c6Jeff Tinker    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
1891849570240443d1f75775c205fa658f7070849c6Jeff Tinker        data.writeInt32(vector.size());
1901849570240443d1f75775c205fa658f7070849c6Jeff Tinker        data.write(vector.array(), vector.size());
1911849570240443d1f75775c205fa658f7070849c6Jeff Tinker    }
1921849570240443d1f75775c205fa658f7070849c6Jeff Tinker
193ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
194ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber};
195ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
196ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas HuberIMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
197ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
198ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber////////////////////////////////////////////////////////////////////////////////
199ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2001849570240443d1f75775c205fa658f7070849c6Jeff Tinkervoid BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
2011849570240443d1f75775c205fa658f7070849c6Jeff Tinker    uint32_t size = data.readInt32();
2021849570240443d1f75775c205fa658f7070849c6Jeff Tinker    vector.insertAt((size_t)0, size);
2031849570240443d1f75775c205fa658f7070849c6Jeff Tinker    data.read(vector.editArray(), size);
2041849570240443d1f75775c205fa658f7070849c6Jeff Tinker}
2051849570240443d1f75775c205fa658f7070849c6Jeff Tinker
2061849570240443d1f75775c205fa658f7070849c6Jeff Tinkervoid BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
2071849570240443d1f75775c205fa658f7070849c6Jeff Tinker    reply->writeInt32(vector.size());
2081849570240443d1f75775c205fa658f7070849c6Jeff Tinker    reply->write(vector.array(), vector.size());
2091849570240443d1f75775c205fa658f7070849c6Jeff Tinker}
2101849570240443d1f75775c205fa658f7070849c6Jeff Tinker
211ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberstatus_t BnCrypto::onTransact(
212ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
213ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    switch (code) {
2141bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        case INIT_CHECK:
215ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        {
216ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            CHECK_INTERFACE(ICrypto, data, reply);
2171bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            reply->writeInt32(initCheck());
218ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
219ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            return OK;
220ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
221ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2221bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        case IS_CRYPTO_SUPPORTED:
223ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        {
224ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            CHECK_INTERFACE(ICrypto, data, reply);
2251bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            uint8_t uuid[16];
2261bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            data.read(uuid, sizeof(uuid));
2271bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            reply->writeInt32(isCryptoSchemeSupported(uuid));
228ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
229ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            return OK;
230ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
231ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2321bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        case CREATE_PLUGIN:
233ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        {
234ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            CHECK_INTERFACE(ICrypto, data, reply);
235ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2361bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            uint8_t uuid[16];
2371bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            data.read(uuid, sizeof(uuid));
2381bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
2391bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            size_t opaqueSize = data.readInt32();
240705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber            void *opaqueData = NULL;
241705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber
242705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber            if (opaqueSize > 0) {
243705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber                opaqueData = malloc(opaqueSize);
244705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber                data.read(opaqueData, opaqueSize);
245705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber            }
246ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2471bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
248ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
249705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber            if (opaqueData != NULL) {
250705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber                free(opaqueData);
251705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber                opaqueData = NULL;
252705868c0f2a6e85a39addefe4db9f2130627c219Andreas Huber            }
253ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
254ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            return OK;
255ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
256ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2571bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        case DESTROY_PLUGIN:
258ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        {
259ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            CHECK_INTERFACE(ICrypto, data, reply);
2601bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            reply->writeInt32(destroyPlugin());
261ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
262ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            return OK;
263ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
264ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2651bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        case REQUIRES_SECURE_COMPONENT:
266ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        {
267ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            CHECK_INTERFACE(ICrypto, data, reply);
268ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2691bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            const char *mime = data.readCString();
2702afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia            if (mime == NULL) {
2712afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia                reply->writeInt32(BAD_VALUE);
2722afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia            } else {
2732afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia                reply->writeInt32(requiresSecureDecoderComponent(mime));
2742afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia            }
275ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2761bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            return OK;
2771bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        }
278ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2791bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        case DECRYPT:
2801bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        {
2811bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            CHECK_INTERFACE(ICrypto, data, reply);
282ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2839ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            DestinationType dstType = (DestinationType)data.readInt32();
2841bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
28518cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker            CryptoPlugin::Pattern pattern;
28618cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker            pattern.mEncryptBlocks = data.readInt32();
28718cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker            pattern.mSkipBlocks = data.readInt32();
288ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2891bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            uint8_t key[16];
2901bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            data.read(key, sizeof(key));
291ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2921bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            uint8_t iv[16];
2931bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            data.read(iv, sizeof(iv));
294ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
2951bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            size_t totalSize = data.readInt32();
296c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker            sp<IMemory> sharedBuffer =
297c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker                interface_cast<IMemory>(data.readStrongBinder());
2982afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia            if (sharedBuffer == NULL) {
2992afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia                reply->writeInt32(BAD_VALUE);
3002afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia                return OK;
3012afac0c7c42560ff5b8f133c6074b7e023279d6dWei Jia            }
302c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker            int32_t offset = data.readInt32();
303ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3041bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            int32_t numSubSamples = data.readInt32();
305ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3061bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            CryptoPlugin::SubSample *subSamples =
3071bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                new CryptoPlugin::SubSample[numSubSamples];
308ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3091bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            data.read(
3101bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                    subSamples,
3111bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                    sizeof(CryptoPlugin::SubSample) * numSubSamples);
312ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3139ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            native_handle_t *nativeHandle = NULL;
3149ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            void *secureBufferId = NULL, *dstPtr;
3159ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            if (dstType == kDestinationTypeNativeHandle) {
3169ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                nativeHandle = data.readNativeHandle();
3179ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                dstPtr = static_cast<void *>(nativeHandle);
3189ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            } else if (dstType == kDestinationTypeOpaqueHandle) {
319ed555d70d80964f40563d89a4e6d6a80f83f4b89Jeff Tinker                secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
3209ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                dstPtr = secureBufferId;
3211bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            } else {
3229ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                dstType = kDestinationTypeVmPointer;
3231bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                dstPtr = malloc(totalSize);
324ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            }
325ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3265b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            AString errorDetailMsg;
327c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker            ssize_t result;
328c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker
329c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker            size_t sumSubsampleSizes = 0;
330c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker            bool overflow = false;
331c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker            for (int32_t i = 0; i < numSubSamples; ++i) {
332c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                CryptoPlugin::SubSample &ss = subSamples[i];
333c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
334c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                    sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
335c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                } else {
336c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                    overflow = true;
337c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                }
338c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
339c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                    sumSubsampleSizes += ss.mNumBytesOfClearData;
340c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                } else {
341c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                    overflow = true;
342c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                }
343c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker            }
344c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker
345c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker            if (overflow || sumSubsampleSizes != totalSize) {
346c6fc6a3ca618b0e72ee565ded2e4960797f53fa6Jeff Tinker                result = -EINVAL;
347bb4877d143c6c7ec9b42e3c490fed58af4f39deaJeff Tinker            } else if (totalSize > sharedBuffer->size()) {
348bb4877d143c6c7ec9b42e3c490fed58af4f39deaJeff Tinker                result = -EINVAL;
349bb4877d143c6c7ec9b42e3c490fed58af4f39deaJeff Tinker            } else if ((size_t)offset > sharedBuffer->size() - totalSize) {
350c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker                result = -EINVAL;
351c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker            } else {
352c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker                result = decrypt(
3539ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                    dstType,
3541bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                    key,
3551bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                    iv,
35618cb1eca504817b5b144a023ae2792d90e74c9a5Jeff Tinker                    mode, pattern,
357c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker                    sharedBuffer, offset,
3581bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                    subSamples, numSubSamples,
3599ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                    dstPtr,
3605b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                    &errorDetailMsg);
361c481b5012a5f6cf72e5e93b36f1ed4c9169916f2Jeff Tinker            }
362ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
363fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong            reply->writeInt32(result);
364ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
365ceffd8cc911bd2e685b525f838cd3d8198ab35cfJeff Tinker            if (isCryptoError(result)) {
3665b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                reply->writeCString(errorDetailMsg.c_str());
3675b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            }
3685b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber
3699ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            if (dstType == kDestinationTypeVmPointer) {
370fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong                if (result >= 0) {
371fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong                    CHECK_LE(result, static_cast<ssize_t>(totalSize));
372fa2b8f243eb048fb2b8e5a14356190f69eb31a36Edwin Wong                    reply->write(dstPtr, result);
3731bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                }
3741bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                free(dstPtr);
3751bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber                dstPtr = NULL;
3769ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker            } else if (dstType == kDestinationTypeNativeHandle) {
3779ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                int err;
3789ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                if ((err = native_handle_close(nativeHandle)) < 0) {
3799ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                    ALOGW("secure buffer native_handle_close failed: %d", err);
3809ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                }
3819ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                if ((err = native_handle_delete(nativeHandle)) < 0) {
3829ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                    ALOGW("secure buffer native_handle_delete failed: %d", err);
3839ac86b3cae9a1e14b12bf97223ddde96142aae43Jeff Tinker                }
384ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            }
385ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3861bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            delete[] subSamples;
3871bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            subSamples = NULL;
388ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
389ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            return OK;
390ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        }
391ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
3922514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        case NOTIFY_RESOLUTION:
3932514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        {
3942514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker            CHECK_INTERFACE(ICrypto, data, reply);
3952514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker
3962514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker            int32_t width = data.readInt32();
3972514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker            int32_t height = data.readInt32();
3982514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker            notifyResolution(width, height);
3992514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker
4002514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker            return OK;
4012514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker        }
4022514d080c8a54ff603a45d7e336de668fe7329dbJeff Tinker
4031849570240443d1f75775c205fa658f7070849c6Jeff Tinker        case SET_MEDIADRM_SESSION:
4041849570240443d1f75775c205fa658f7070849c6Jeff Tinker        {
4051849570240443d1f75775c205fa658f7070849c6Jeff Tinker            CHECK_INTERFACE(IDrm, data, reply);
4061849570240443d1f75775c205fa658f7070849c6Jeff Tinker            Vector<uint8_t> sessionId;
4071849570240443d1f75775c205fa658f7070849c6Jeff Tinker            readVector(data, sessionId);
4081849570240443d1f75775c205fa658f7070849c6Jeff Tinker            reply->writeInt32(setMediaDrmSession(sessionId));
4091849570240443d1f75775c205fa658f7070849c6Jeff Tinker            return OK;
4101849570240443d1f75775c205fa658f7070849c6Jeff Tinker        }
4111849570240443d1f75775c205fa658f7070849c6Jeff Tinker
412ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        default:
413ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            return BBinder::onTransact(code, data, reply, flags);
414ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
415ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
416ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
417ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}  // namespace android
418