/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "ICrypto"
#include <binder/Parcel.h>
#include <binder/IMemory.h>
#include <cutils/log.h>
#include <media/ICrypto.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <utils/Log.h>

namespace android {

enum {
    INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
    IS_CRYPTO_SUPPORTED,
    CREATE_PLUGIN,
    DESTROY_PLUGIN,
    REQUIRES_SECURE_COMPONENT,
    DECRYPT,
    NOTIFY_RESOLUTION,
    SET_MEDIADRM_SESSION,
    SET_HEAP,
    UNSET_HEAP,
};

struct BpCrypto : public BpInterface<ICrypto> {
    explicit BpCrypto(const sp<IBinder> &impl)
        : BpInterface<ICrypto>(impl) {
    }

    virtual status_t initCheck() const {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        remote()->transact(INIT_CHECK, data, &reply);

        return reply.readInt32();
    }

    virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.write(uuid, 16);
        remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);

        return reply.readInt32() != 0;
    }

    virtual status_t createPlugin(
            const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.write(uuid, 16);
        data.writeInt32(opaqueSize);

        if (opaqueSize > 0) {
            data.write(opaqueData, opaqueSize);
        }

        remote()->transact(CREATE_PLUGIN, data, &reply);

        return reply.readInt32();
    }

    virtual status_t destroyPlugin() {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        remote()->transact(DESTROY_PLUGIN, data, &reply);

        return reply.readInt32();
    }

    virtual bool requiresSecureDecoderComponent(
            const char *mime) const {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeCString(mime);
        remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);

        return reply.readInt32() != 0;
    }

    virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
            CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
            const SourceBuffer &source, size_t offset,
            const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
            const DestinationBuffer &destination, AString *errorDetailMsg) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInt32(mode);
        data.writeInt32(pattern.mEncryptBlocks);
        data.writeInt32(pattern.mSkipBlocks);

        static const uint8_t kDummy[16] = { 0 };

        if (key == NULL) {
            key = kDummy;
        }

        if (iv == NULL) {
            iv = kDummy;
        }

        data.write(key, 16);
        data.write(iv, 16);

        size_t totalSize = 0;
        for (size_t i = 0; i < numSubSamples; ++i) {
            totalSize += subSamples[i].mNumBytesOfEncryptedData;
            totalSize += subSamples[i].mNumBytesOfClearData;
        }

        data.writeInt32(totalSize);
        data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
        data.writeInt32(source.mHeapSeqNum);
        data.writeInt32(offset);

        data.writeInt32(numSubSamples);
        data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);

        data.writeInt32((int32_t)destination.mType);
        if (destination.mType == kDestinationTypeNativeHandle) {
            if (destination.mHandle == NULL) {
                return BAD_VALUE;
            }
            data.writeNativeHandle(destination.mHandle);
        } else {
            if (destination.mSharedMemory == NULL) {
                return BAD_VALUE;
            }
            data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
        }

        remote()->transact(DECRYPT, data, &reply);

        ssize_t result = reply.readInt32();

        if (isCryptoError(result)) {
            AString msg = reply.readCString();
            if (errorDetailMsg) {
                *errorDetailMsg = msg;
            }
        }

        return result;
    }

    virtual void notifyResolution(
        uint32_t width, uint32_t height) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInt32(width);
        data.writeInt32(height);
        remote()->transact(NOTIFY_RESOLUTION, data, &reply);
    }

    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());

        writeVector(data, sessionId);
        remote()->transact(SET_MEDIADRM_SESSION, data, &reply);

        return reply.readInt32();
    }

    virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(heap));
        status_t err = remote()->transact(SET_HEAP, data, &reply);
        if (err != NO_ERROR) {
            return -1;
        }
        int32_t seqNum;
        if (reply.readInt32(&seqNum) != NO_ERROR) {
            return -1;
        }
        return seqNum;
    }

    virtual void unsetHeap(int32_t seqNum) {
        Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInt32(seqNum);
        remote()->transact(UNSET_HEAP, data, &reply);
        return;
    }


private:
    void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
        uint32_t size = reply.readInt32();
        vector.insertAt((size_t)0, size);
        reply.read(vector.editArray(), size);
    }

    void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
        data.writeInt32(vector.size());
        data.write(vector.array(), vector.size());
    }

    DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
};

IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");

////////////////////////////////////////////////////////////////////////////////

void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
    uint32_t size = data.readInt32();
    vector.insertAt((size_t)0, size);
    data.read(vector.editArray(), size);
}

void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
    reply->writeInt32(vector.size());
    reply->write(vector.array(), vector.size());
}

status_t BnCrypto::onTransact(
    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    switch (code) {
        case INIT_CHECK:
        {
            CHECK_INTERFACE(ICrypto, data, reply);
            reply->writeInt32(initCheck());

            return OK;
        }

        case IS_CRYPTO_SUPPORTED:
        {
            CHECK_INTERFACE(ICrypto, data, reply);
            uint8_t uuid[16];
            data.read(uuid, sizeof(uuid));
            reply->writeInt32(isCryptoSchemeSupported(uuid));

            return OK;
        }

        case CREATE_PLUGIN:
        {
            CHECK_INTERFACE(ICrypto, data, reply);

            uint8_t uuid[16];
            data.read(uuid, sizeof(uuid));

            size_t opaqueSize = data.readInt32();
            void *opaqueData = NULL;

            const size_t kMaxOpaqueSize = 100 * 1024;
            if (opaqueSize > kMaxOpaqueSize) {
                return BAD_VALUE;
            }

            opaqueData = malloc(opaqueSize);
            if (NULL == opaqueData) {
                return NO_MEMORY;
            }

            data.read(opaqueData, opaqueSize);
            reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));

            free(opaqueData);
            opaqueData = NULL;

            return OK;
        }

        case DESTROY_PLUGIN:
        {
            CHECK_INTERFACE(ICrypto, data, reply);
            reply->writeInt32(destroyPlugin());

            return OK;
        }

        case REQUIRES_SECURE_COMPONENT:
        {
            CHECK_INTERFACE(ICrypto, data, reply);

            const char *mime = data.readCString();
            if (mime == NULL) {
                reply->writeInt32(BAD_VALUE);
            } else {
                reply->writeInt32(requiresSecureDecoderComponent(mime));
            }

            return OK;
        }

        case DECRYPT:
        {
            CHECK_INTERFACE(ICrypto, data, reply);

            CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
            CryptoPlugin::Pattern pattern;
            pattern.mEncryptBlocks = data.readInt32();
            pattern.mSkipBlocks = data.readInt32();

            uint8_t key[16];
            data.read(key, sizeof(key));

            uint8_t iv[16];
            data.read(iv, sizeof(iv));

            size_t totalSize = data.readInt32();

            SourceBuffer source;

            source.mSharedMemory =
                interface_cast<IMemory>(data.readStrongBinder());
            if (source.mSharedMemory == NULL) {
                reply->writeInt32(BAD_VALUE);
                return OK;
            }
            source.mHeapSeqNum = data.readInt32();

            int32_t offset = data.readInt32();

            int32_t numSubSamples = data.readInt32();
            if (numSubSamples < 0 || numSubSamples > 0xffff) {
                reply->writeInt32(BAD_VALUE);
                return OK;
            }

            CryptoPlugin::SubSample *subSamples =
                    new CryptoPlugin::SubSample[numSubSamples];

            data.read(subSamples,
                    sizeof(CryptoPlugin::SubSample) * numSubSamples);

            DestinationBuffer destination;
            destination.mType = (DestinationType)data.readInt32();
            if (destination.mType == kDestinationTypeNativeHandle) {
                destination.mHandle = data.readNativeHandle();
                if (destination.mHandle == NULL) {
                    reply->writeInt32(BAD_VALUE);
                    return OK;
                }
            } else if (destination.mType == kDestinationTypeSharedMemory) {
                destination.mSharedMemory =
                        interface_cast<IMemory>(data.readStrongBinder());
                if (destination.mSharedMemory == NULL) {
                    reply->writeInt32(BAD_VALUE);
                    return OK;
                }
                sp<IMemory> dest = destination.mSharedMemory;
                if (totalSize > dest->size() ||
                        (size_t)dest->offset() > dest->size() - totalSize) {
                    reply->writeInt32(BAD_VALUE);
                    android_errorWriteLog(0x534e4554, "71389378");
                    return OK;
                }
            }

            AString errorDetailMsg;
            ssize_t result;

            size_t sumSubsampleSizes = 0;
            bool overflow = false;
            for (int32_t i = 0; i < numSubSamples; ++i) {
                CryptoPlugin::SubSample &ss = subSamples[i];
                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
                    sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
                } else {
                    overflow = true;
                }
                if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
                    sumSubsampleSizes += ss.mNumBytesOfClearData;
                } else {
                    overflow = true;
                }
            }

            if (overflow || sumSubsampleSizes != totalSize) {
                result = -EINVAL;
            } else if (totalSize > source.mSharedMemory->size()) {
                result = -EINVAL;
            } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
                result = -EINVAL;
            } else {
                result = decrypt(key, iv, mode, pattern, source, offset,
                        subSamples, numSubSamples, destination, &errorDetailMsg);
            }

            reply->writeInt32(result);

            if (isCryptoError(result)) {
                reply->writeCString(errorDetailMsg.c_str());
            }

            if (destination.mType == kDestinationTypeNativeHandle) {
                int err;
                if ((err = native_handle_close(destination.mHandle)) < 0) {
                    ALOGW("secure buffer native_handle_close failed: %d", err);
                }
                if ((err = native_handle_delete(destination.mHandle)) < 0) {
                    ALOGW("secure buffer native_handle_delete failed: %d", err);
                }
            }

            delete[] subSamples;
            subSamples = NULL;

            return OK;
        }

        case NOTIFY_RESOLUTION:
        {
            CHECK_INTERFACE(ICrypto, data, reply);

            int32_t width = data.readInt32();
            int32_t height = data.readInt32();
            notifyResolution(width, height);

            return OK;
        }

        case SET_MEDIADRM_SESSION:
        {
            CHECK_INTERFACE(IDrm, data, reply);
            Vector<uint8_t> sessionId;
            readVector(data, sessionId);
            reply->writeInt32(setMediaDrmSession(sessionId));
            return OK;
        }

        case SET_HEAP:
        {
            CHECK_INTERFACE(ICrypto, data, reply);
            sp<IMemoryHeap> heap =
                interface_cast<IMemoryHeap>(data.readStrongBinder());
            reply->writeInt32(setHeap(heap));
            return OK;
        }

        case UNSET_HEAP:
        {
            CHECK_INTERFACE(ICrypto, data, reply);
            int32_t seqNum = data.readInt32();
            unsetHeap(seqNum);
            return OK;
        }

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

}  // namespace android
