/*
**
** Copyright 2008, 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.
*/

#include <stdint.h>
#include <sys/limits.h>
#include <sys/types.h>

#define LOG_TAG "KeystoreService"
#include <utils/Log.h>

#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <keystore/IKeystoreService.h>

namespace android {

const ssize_t MAX_GENERATE_ARGS = 3;
static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length);

KeystoreArg::KeystoreArg(const void* data, size_t len)
    : mData(data), mSize(len) {
}

KeystoreArg::~KeystoreArg() {
}

const void *KeystoreArg::data() const {
    return mData;
}

size_t KeystoreArg::size() const {
    return mSize;
}

OperationResult::OperationResult() : resultCode(0), token(), handle(0), inputConsumed(0),
    data(NULL), dataLength(0) {
}

OperationResult::~OperationResult() {
}

status_t OperationResult::readFromParcel(const Parcel* inn) {
    const Parcel& in = *inn;
    resultCode = in.readInt32();
    token = in.readStrongBinder();
    handle = static_cast<keymaster_operation_handle_t>(in.readInt64());
    inputConsumed = in.readInt32();
    ssize_t length = in.readInt32();
    dataLength = 0;
    if (length > 0) {
        const void* buf = in.readInplace(length);
        if (buf) {
            data.reset(reinterpret_cast<uint8_t*>(malloc(length)));
            if (data.get()) {
                memcpy(data.get(), buf, length);
                dataLength = (size_t) length;
            } else {
                ALOGE("Failed to allocate OperationResult buffer");
            }
        } else {
            ALOGE("Failed to readInplace OperationResult data");
        }
    }
    outParams.readFromParcel(in);
    return OK;
}

status_t OperationResult::writeToParcel(Parcel* out) const {
    out->writeInt32(resultCode);
    out->writeStrongBinder(token);
    out->writeInt64(handle);
    out->writeInt32(inputConsumed);
    out->writeInt32(dataLength);
    if (dataLength && data) {
        void* buf = out->writeInplace(dataLength);
        if (buf) {
            memcpy(buf, data.get(), dataLength);
        } else {
            ALOGE("Failed to writeInplace OperationResult data.");
        }
    }
    outParams.writeToParcel(out);
    return OK;
}

ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
}

ExportResult::~ExportResult() {
}

status_t ExportResult::readFromParcel(const Parcel* inn) {
    const Parcel& in = *inn;
    resultCode = in.readInt32();
    ssize_t length = in.readInt32();
    dataLength = 0;
    if (length > 0) {
        const void* buf = in.readInplace(length);
        if (buf) {
            exportData.reset(reinterpret_cast<uint8_t*>(malloc(length)));
            if (exportData.get()) {
                memcpy(exportData.get(), buf, length);
                dataLength = (size_t) length;
            } else {
                ALOGE("Failed to allocate ExportData buffer");
            }
        } else {
            ALOGE("Failed to readInplace ExportData data");
        }
    }
    return OK;
}

status_t ExportResult::writeToParcel(Parcel* out) const {
    out->writeInt32(resultCode);
    out->writeInt32(dataLength);
    if (exportData && dataLength) {
        void* buf = out->writeInplace(dataLength);
        if (buf) {
            memcpy(buf, exportData.get(), dataLength);
        } else {
            ALOGE("Failed to writeInplace ExportResult data.");
        }
    }
    return OK;
}

KeymasterArguments::KeymasterArguments() {
}

KeymasterArguments::~KeymasterArguments() {
    keymaster_free_param_values(params.data(), params.size());
}

void KeymasterArguments::readFromParcel(const Parcel& in) {
    ssize_t length = in.readInt32();
    size_t ulength = (size_t) length;
    if (length < 0) {
        ulength = 0;
    }
    keymaster_free_param_values(params.data(), params.size());
    params.clear();
    for(size_t i = 0; i < ulength; i++) {
        keymaster_key_param_t param;
        if (!readKeymasterArgumentFromParcel(in, &param)) {
            ALOGE("Error reading keymaster argument from parcel");
            break;
        }
        params.push_back(param);
    }
}

void KeymasterArguments::writeToParcel(Parcel* out) const {
    out->writeInt32(params.size());
    for (auto param : params) {
        out->writeInt32(1);
        writeKeymasterArgumentToParcel(param, out);
    }
}

KeyCharacteristics::KeyCharacteristics() {
    memset((void*) &characteristics, 0, sizeof(characteristics));
}

KeyCharacteristics::~KeyCharacteristics() {
    keymaster_free_characteristics(&characteristics);
}

status_t KeyCharacteristics::readFromParcel(const Parcel* inn) {
    const Parcel& in = *inn;
    size_t length = 0;
    keymaster_key_param_t* params = readParamList(in, &length);
    characteristics.sw_enforced.params = params;
    characteristics.sw_enforced.length = length;

    params = readParamList(in, &length);
    characteristics.hw_enforced.params = params;
    characteristics.hw_enforced.length = length;
    return OK;
}

status_t KeyCharacteristics::writeToParcel(Parcel* out) const {
    if (characteristics.sw_enforced.params) {
        out->writeInt32(characteristics.sw_enforced.length);
        for (size_t i = 0; i < characteristics.sw_enforced.length; i++) {
            out->writeInt32(1);
            writeKeymasterArgumentToParcel(characteristics.sw_enforced.params[i], out);
        }
    } else {
        out->writeInt32(0);
    }
    if (characteristics.hw_enforced.params) {
        out->writeInt32(characteristics.hw_enforced.length);
        for (size_t i = 0; i < characteristics.hw_enforced.length; i++) {
            out->writeInt32(1);
            writeKeymasterArgumentToParcel(characteristics.hw_enforced.params[i], out);
        }
    } else {
        out->writeInt32(0);
    }
    return OK;
}

KeymasterCertificateChain::KeymasterCertificateChain() {
    memset(&chain, 0, sizeof(chain));
}

KeymasterCertificateChain::~KeymasterCertificateChain() {
    keymaster_free_cert_chain(&chain);
}

static bool readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
    if (in.readInt32() != 1) {
        return false;
    }

    ssize_t length = in.readInt32();
    if (length <= 0) {
        return false;
    }

    blob->data = static_cast<const uint8_t*>(malloc(length));
    if (!blob->data)
        return false;

    const void* buf = in.readInplace(length);
    if (!buf)
        return false;

    blob->data_length = static_cast<size_t>(length);
    memcpy(const_cast<uint8_t*>(blob->data), buf, length);

    return true;
}

void KeymasterCertificateChain::readFromParcel(const Parcel& in) {
    keymaster_free_cert_chain(&chain);

    ssize_t count = in.readInt32();
    size_t ucount = count;
    if (count <= 0) {
        return;
    }

    chain.entries = reinterpret_cast<keymaster_blob_t*>(malloc(sizeof(keymaster_blob_t) * ucount));
    if (!chain.entries) {
        ALOGE("Error allocating memory for certificate chain");
        return;
    }

    memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount);
    for (size_t i = 0; i < ucount; ++i) {
        if (!readKeymasterBlob(in, &chain.entries[i])) {
            ALOGE("Error reading certificate from parcel");
            keymaster_free_cert_chain(&chain);
            return;
        }
    }
}

void KeymasterCertificateChain::writeToParcel(Parcel* out) const {
    out->writeInt32(chain.entry_count);
    for (size_t i = 0; i < chain.entry_count; ++i) {
        if (chain.entries[i].data) {
            out->writeInt32(chain.entries[i].data_length);
            void* buf = out->writeInplace(chain.entries[i].data_length);
            if (buf) {
                memcpy(buf, chain.entries[i].data, chain.entries[i].data_length);
            } else {
                ALOGE("Failed to writeInplace keymaster cert chain entry");
            }
        } else {
            out->writeInt32(0); // Tell Java side this object is NULL.
            ALOGE("Found NULL certificate chain entry");
        }
    }
}

void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out) {
    switch (keymaster_tag_get_type(param.tag)) {
        case KM_ENUM:
        case KM_ENUM_REP: {
            out->writeInt32(param.tag);
            out->writeInt32(param.enumerated);
            break;
        }
        case KM_UINT:
        case KM_UINT_REP: {
            out->writeInt32(param.tag);
            out->writeInt32(param.integer);
            break;
        }
        case KM_ULONG:
        case KM_ULONG_REP: {
            out->writeInt32(param.tag);
            out->writeInt64(param.long_integer);
            break;
        }
        case KM_DATE: {
            out->writeInt32(param.tag);
            out->writeInt64(param.date_time);
            break;
        }
        case KM_BOOL: {
            out->writeInt32(param.tag);
            break;
        }
        case KM_BIGNUM:
        case KM_BYTES: {
            out->writeInt32(param.tag);
            out->writeInt32(param.blob.data_length);
            void* buf = out->writeInplace(param.blob.data_length);
            if (buf) {
                memcpy(buf, param.blob.data, param.blob.data_length);
            } else {
                ALOGE("Failed to writeInplace keymaster blob param");
            }
            break;
        }
        default: {
            ALOGE("Failed to write argument: Unsupported keymaster_tag_t %d", param.tag);
        }
    }
}


bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out) {
    if (in.readInt32() == 0) {
        return false;
    }
    keymaster_tag_t tag = static_cast<keymaster_tag_t>(in.readInt32());
    switch (keymaster_tag_get_type(tag)) {
        case KM_ENUM:
        case KM_ENUM_REP: {
            uint32_t value = in.readInt32();
            *out = keymaster_param_enum(tag, value);
            break;
        }
        case KM_UINT:
        case KM_UINT_REP: {
            uint32_t value = in.readInt32();
            *out = keymaster_param_int(tag, value);
            break;
        }
        case KM_ULONG:
        case KM_ULONG_REP: {
            uint64_t value = in.readInt64();
            *out = keymaster_param_long(tag, value);
            break;
        }
        case KM_DATE: {
            uint64_t value = in.readInt64();
            *out = keymaster_param_date(tag, value);
            break;
        }
        case KM_BOOL: {
            *out = keymaster_param_bool(tag);
            break;
        }
        case KM_BIGNUM:
        case KM_BYTES: {
            ssize_t length = in.readInt32();
            uint8_t* data = NULL;
            size_t ulength = 0;
            if (length >= 0) {
                ulength = (size_t) length;
                // use malloc here so we can use keymaster_free_param_values
                // consistently.
                data = reinterpret_cast<uint8_t*>(malloc(ulength));
                const void* buf = in.readInplace(ulength);
                if (!buf || !data) {
                    ALOGE("Failed to allocate buffer for keymaster blob param");
                    free(data);
                    return false;
                }
                memcpy(data, buf, ulength);
            }
            *out = keymaster_param_blob(tag, data, ulength);
            break;
        }
        default: {
            ALOGE("Unsupported keymaster_tag_t %d", tag);
            return false;
        }
    }
    return true;
}

/**
 * Read a byte array from in. The data at *data is still owned by the parcel
 */
static void readByteArray(const Parcel& in, const uint8_t** data, size_t* length) {
    ssize_t slength = in.readInt32();
    if (slength > 0) {
        *data = reinterpret_cast<const uint8_t*>(in.readInplace(slength));
        if (*data) {
            *length = static_cast<size_t>(slength);
        } else {
            *length = 0;
        }
    } else {
        *data = NULL;
        *length = 0;
    }
}

// Read a keymaster_key_param_t* from a Parcel for use in a
// keymaster_key_characteristics_t. This will be free'd by calling
// keymaster_free_key_characteristics.
static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length) {
    ssize_t slength = in.readInt32();
    *length = 0;
    if (slength < 0) {
        return NULL;
    }
    *length = (size_t) slength;
    if (*length >= UINT_MAX / sizeof(keymaster_key_param_t)) {
        return NULL;
    }
    keymaster_key_param_t* list =
            reinterpret_cast<keymaster_key_param_t*>(malloc(*length *
                                                            sizeof(keymaster_key_param_t)));
    if (!list) {
        ALOGD("Failed to allocate buffer for generateKey outCharacteristics");
        goto err;
    }
    for (size_t i = 0; i < *length ; i++) {
        if (!readKeymasterArgumentFromParcel(in, &list[i])) {
            ALOGE("Failed to read keymaster argument");
            keymaster_free_param_values(list, i);
            goto err;
        }
    }
    return list;
err:
    free(list);
    return NULL;
}

static std::unique_ptr<keymaster_blob_t> readKeymasterBlob(const Parcel& in) {
    std::unique_ptr<keymaster_blob_t> blob (new keymaster_blob_t);
    if (!readKeymasterBlob(in, blob.get())) {
        blob.reset();
    }
    return blob;
}

class BpKeystoreService: public BpInterface<IKeystoreService>
{
public:
    explicit BpKeystoreService(const sp<IBinder>& impl)
        : BpInterface<IKeystoreService>(impl)
    {
    }

    // test ping
    virtual int32_t getState(int32_t userId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        status_t status = remote()->transact(BnKeystoreService::GET_STATE, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("getState() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("getState() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("get() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        ssize_t len = reply.readInt32();
        if (len >= 0 && (size_t) len <= reply.dataAvail()) {
            size_t ulen = (size_t) len;
            const void* buf = reply.readInplace(ulen);
            *item = (uint8_t*) malloc(ulen);
            if (*item != NULL) {
                memcpy(*item, buf, ulen);
                *itemLength = ulen;
            } else {
                ALOGE("out of memory allocating output array in get");
                *itemLength = 0;
            }
        } else {
            *itemLength = 0;
        }
        if (err < 0) {
            ALOGD("get() caught exception %d\n", err);
            return -1;
        }
        return 0;
    }

    virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
            int32_t flags)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(itemLength);
        void* buf = data.writeInplace(itemLength);
        memcpy(buf, item, itemLength);
        data.writeInt32(uid);
        data.writeInt32(flags);
        status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("import() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("import() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t del(const String16& name, int uid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("del() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("del() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t exist(const String16& name, int uid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("exist() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("exist() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(prefix);
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("list() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t numMatches = reply.readInt32();
        for (int32_t i = 0; i < numMatches; i++) {
            matches->push(reply.readString16());
        }
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("list() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t reset()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("reset() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("reset() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t onUserPasswordChanged(int32_t userId, const String16& password)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        data.writeString16(password);
        status_t status = remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data,
                                             &reply);
        if (status != NO_ERROR) {
            ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("onUserPasswordChanged() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t lock(int32_t userId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("lock() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("lock() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t unlock(int32_t userId, const String16& password)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        data.writeString16(password);
        status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("unlock() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("unlock() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual bool isEmpty(int32_t userId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        status_t status = remote()->transact(BnKeystoreService::IS_EMPTY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("isEmpty() could not contact remote: %d\n", status);
            return false;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("isEmpty() caught exception %d\n", err);
            return false;
        }
        return ret != 0;
    }

    virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
            int32_t flags, Vector<sp<KeystoreArg> >* args)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(uid);
        data.writeInt32(keyType);
        data.writeInt32(keySize);
        data.writeInt32(flags);
        data.writeInt32(1);
        data.writeInt32(args->size());
        for (Vector<sp<KeystoreArg> >::iterator it = args->begin(); it != args->end(); ++it) {
            sp<KeystoreArg> item = *it;
            size_t keyLength = item->size();
            data.writeInt32(keyLength);
            void* buf = data.writeInplace(keyLength);
            memcpy(buf, item->data(), keyLength);
        }
        status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("generate() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("generate() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength, int uid,
            int flags)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(keyLength);
        void* buf = data.writeInplace(keyLength);
        memcpy(buf, key, keyLength);
        data.writeInt32(uid);
        data.writeInt32(flags);
        status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("import() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("import() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out,
            size_t* outLength)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(inLength);
        void* buf = data.writeInplace(inLength);
        memcpy(buf, in, inLength);
        status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("import() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        ssize_t len = reply.readInt32();
        if (len >= 0 && (size_t) len <= reply.dataAvail()) {
            size_t ulen = (size_t) len;
            const void* outBuf = reply.readInplace(ulen);
            *out = (uint8_t*) malloc(ulen);
            if (*out != NULL) {
                memcpy((void*) *out, outBuf, ulen);
                *outLength = ulen;
            } else {
                ALOGE("out of memory allocating output array in sign");
                *outLength = 0;
            }
        } else {
            *outLength = 0;
        }
        if (err < 0) {
            ALOGD("import() caught exception %d\n", err);
            return -1;
        }
        return 0;
    }

    virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength,
            const uint8_t* signature, size_t signatureLength)
    {
        Parcel data, reply;
        void* buf;

        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(inLength);
        buf = data.writeInplace(inLength);
        memcpy(buf, in, inLength);
        data.writeInt32(signatureLength);
        buf = data.writeInplace(signatureLength);
        memcpy(buf, signature, signatureLength);
        status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("verify() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("verify() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("get_pubkey() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        ssize_t len = reply.readInt32();
        if (len >= 0 && (size_t) len <= reply.dataAvail()) {
            size_t ulen = (size_t) len;
            const void* buf = reply.readInplace(ulen);
            *pubkey = (uint8_t*) malloc(ulen);
            if (*pubkey != NULL) {
                memcpy(*pubkey, buf, ulen);
                *pubkeyLength = ulen;
            } else {
                ALOGE("out of memory allocating output array in get_pubkey");
                *pubkeyLength = 0;
            }
        } else {
            *pubkeyLength = 0;
        }
        if (err < 0) {
            ALOGD("get_pubkey() caught exception %d\n", err);
            return -1;
        }
        return 0;
     }

    virtual int32_t grant(const String16& name, int32_t granteeUid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(granteeUid);
        status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("grant() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("grant() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t ungrant(const String16& name, int32_t granteeUid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(granteeUid);
        status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("ungrant() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("ungrant() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    int64_t getmtime(const String16& name, int32_t uid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("getmtime() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int64_t ret = reply.readInt64();
        if (err < 0) {
            ALOGD("getmtime() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
            int32_t destUid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(srcKey);
        data.writeInt32(srcUid);
        data.writeString16(destKey);
        data.writeInt32(destUid);
        status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("duplicate() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("duplicate() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t is_hardware_backed(const String16& keyType)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(keyType);
        status_t status = remote()->transact(BnKeystoreService::IS_HARDWARE_BACKED, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("is_hardware_backed() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("is_hardware_backed() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t clear_uid(int64_t uid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt64(uid);
        status_t status = remote()->transact(BnKeystoreService::CLEAR_UID, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("clear_uid() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("clear_uid() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeByteArray(bufLength, buf);
        status_t status = remote()->transact(BnKeystoreService::ADD_RNG_ENTROPY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("addRngEntropy() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("addRngEntropy() caught exception %d\n", err);
            return -1;
        }
        return ret;
    };

    virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
                                const uint8_t* entropy, size_t entropyLength, int uid, int flags,
                                KeyCharacteristics* outCharacteristics)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(1);
        params.writeToParcel(&data);
        data.writeByteArray(entropyLength, entropy);
        data.writeInt32(uid);
        data.writeInt32(flags);
        status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("generateKey() could not contact remote: %d\n", status);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("generateKey() caught exception %d\n", err);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        if (outCharacteristics) {
            reply.readParcelable(outCharacteristics);
        }
        return ret;
    }
    virtual int32_t getKeyCharacteristics(const String16& name,
                                          const keymaster_blob_t* clientId,
                                          const keymaster_blob_t* appData,
                                          int32_t uid, KeyCharacteristics* outCharacteristics)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        if (clientId) {
            data.writeByteArray(clientId->data_length, clientId->data);
        } else {
            data.writeInt32(-1);
        }
        if (appData) {
            data.writeByteArray(appData->data_length, appData->data);
        } else {
            data.writeInt32(-1);
        }
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
                                             data, &reply);
        if (status != NO_ERROR) {
            ALOGD("getKeyCharacteristics() could not contact remote: %d\n", status);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("getKeyCharacteristics() caught exception %d\n", err);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        if (outCharacteristics) {
            reply.readParcelable(outCharacteristics);
        }
        return ret;
    }
    virtual int32_t importKey(const String16& name, const KeymasterArguments&  params,
                              keymaster_key_format_t format, const uint8_t *keyData,
                              size_t keyLength, int uid, int flags,
                              KeyCharacteristics* outCharacteristics)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(1);
        params.writeToParcel(&data);
        data.writeInt32(format);
        data.writeByteArray(keyLength, keyData);
        data.writeInt32(uid);
        data.writeInt32(flags);
        status_t status = remote()->transact(BnKeystoreService::IMPORT_KEY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("importKey() could not contact remote: %d\n", status);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("importKey() caught exception %d\n", err);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        if (outCharacteristics) {
            reply.readParcelable(outCharacteristics);
        }
        return ret;
    }

    virtual void exportKey(const String16& name, keymaster_key_format_t format,
                           const keymaster_blob_t* clientId,
                           const keymaster_blob_t* appData, int32_t uid, ExportResult* result)
    {
        if (!result) {
            return;
        }

        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(format);
        if (clientId) {
            data.writeByteArray(clientId->data_length, clientId->data);
        } else {
            data.writeInt32(-1);
        }
        if (appData) {
            data.writeByteArray(appData->data_length, appData->data);
        } else {
            data.writeInt32(-1);
        }
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("exportKey() could not contact remote: %d\n", status);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }
        int32_t err = reply.readExceptionCode();
        if (err < 0) {
            ALOGD("exportKey() caught exception %d\n", err);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }

        reply.readParcelable(result);
    }

    virtual void begin(const sp<IBinder>& appToken, const String16& name,
                       keymaster_purpose_t purpose, bool pruneable,
                       const KeymasterArguments& params, const uint8_t* entropy,
                       size_t entropyLength, int32_t uid, OperationResult* result)
    {
        if (!result) {
            return;
        }
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeStrongBinder(appToken);
        data.writeString16(name);
        data.writeInt32(purpose);
        data.writeInt32(pruneable ? 1 : 0);
        data.writeInt32(1);
        params.writeToParcel(&data);
        data.writeByteArray(entropyLength, entropy);
        data.writeInt32(uid);
        status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("begin() could not contact remote: %d\n", status);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }
        int32_t err = reply.readExceptionCode();
        if (err < 0) {
            ALOGD("begin() caught exception %d\n", err);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }

        reply.readParcelable(result);
    }

    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
                        const uint8_t* opData, size_t dataLength, OperationResult* result)
    {
        if (!result) {
            return;
        }
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeStrongBinder(token);
        data.writeInt32(1);
        params.writeToParcel(&data);
        data.writeByteArray(dataLength, opData);
        status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("update() could not contact remote: %d\n", status);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }
        int32_t err = reply.readExceptionCode();
        if (err < 0) {
            ALOGD("update() caught exception %d\n", err);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }

        reply.readParcelable(result);
    }

    virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
                        const uint8_t* signature, size_t signatureLength,
                        const uint8_t* entropy, size_t entropyLength,
                        OperationResult* result)
    {
        if (!result) {
            return;
        }
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeStrongBinder(token);
        data.writeInt32(1);
        params.writeToParcel(&data);
        data.writeByteArray(signatureLength, signature);
        data.writeByteArray(entropyLength, entropy);
        status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("finish() could not contact remote: %d\n", status);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }
        int32_t err = reply.readExceptionCode();
        if (err < 0) {
            ALOGD("finish() caught exception %d\n", err);
            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
            return;
        }

        reply.readParcelable(result);
    }

    virtual int32_t abort(const sp<IBinder>& token)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeStrongBinder(token);
        status_t status = remote()->transact(BnKeystoreService::ABORT, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("abort() could not contact remote: %d\n", status);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("abort() caught exception %d\n", err);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        return ret;
    }

    virtual bool isOperationAuthorized(const sp<IBinder>& token)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeStrongBinder(token);
        status_t status = remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data,
                                             &reply);
        if (status != NO_ERROR) {
            ALOGD("isOperationAuthorized() could not contact remote: %d\n", status);
            return false;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("isOperationAuthorized() caught exception %d\n", err);
            return false;
        }
        return ret == 1;
    }

    virtual int32_t addAuthToken(const uint8_t* token, size_t length)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeByteArray(length, token);
        status_t status = remote()->transact(BnKeystoreService::ADD_AUTH_TOKEN, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("addAuthToken() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("addAuthToken() caught exception %d\n", err);
            return -1;
        }
        return ret;
    };

    virtual int32_t onUserAdded(int32_t userId, int32_t parentId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        data.writeInt32(parentId);
        status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("onUserAdded() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("onUserAdded() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t onUserRemoved(int32_t userId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeInt32(userId);
        status_t status = remote()->transact(BnKeystoreService::ON_USER_REMOVED, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("onUserRemoved() could not contact remote: %d\n", status);
            return -1;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("onUserRemoved() caught exception %d\n", err);
            return -1;
        }
        return ret;
    }

    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
                              KeymasterCertificateChain* outChain) {
        if (!outChain)
            return KM_ERROR_OUTPUT_PARAMETER_NULL;

        Parcel data, reply;
        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeInt32(1);  // params is not NULL.
        params.writeToParcel(&data);

        status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply);
        if (status != NO_ERROR) {
            ALOGD("attestkey() count not contact remote: %d\n", status);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        int32_t err = reply.readExceptionCode();
        int32_t ret = reply.readInt32();
        if (err < 0) {
            ALOGD("attestKey() caught exception %d\n", err);
            return KM_ERROR_UNKNOWN_ERROR;
        }
        if (reply.readInt32() != 0) {
            outChain->readFromParcel(reply);
        }
        return ret;
    }

};

IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");

// ----------------------------------------------------------------------

status_t BnKeystoreService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case GET_STATE: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            int32_t ret = getState(userId);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case GET: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int32_t uid = data.readInt32();
            void* out = NULL;
            size_t outSize = 0;
            int32_t ret = get(name, uid, (uint8_t**) &out, &outSize);
            reply->writeNoException();
            if (ret == 1) {
                reply->writeInt32(outSize);
                void* buf = reply->writeInplace(outSize);
                memcpy(buf, out, outSize);
                free(out);
            } else {
                reply->writeInt32(-1);
            }
            return NO_ERROR;
        } break;
        case INSERT: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            ssize_t inSize = data.readInt32();
            const void* in;
            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
                in = data.readInplace(inSize);
            } else {
                in = NULL;
                inSize = 0;
            }
            int uid = data.readInt32();
            int32_t flags = data.readInt32();
            int32_t ret = insert(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case DEL: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int uid = data.readInt32();
            int32_t ret = del(name, uid);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case EXIST: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int uid = data.readInt32();
            int32_t ret = exist(name, uid);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case LIST: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 prefix = data.readString16();
            int uid = data.readInt32();
            Vector<String16> matches;
            int32_t ret = list(prefix, uid, &matches);
            reply->writeNoException();
            reply->writeInt32(matches.size());
            Vector<String16>::const_iterator it = matches.begin();
            for (; it != matches.end(); ++it) {
                reply->writeString16(*it);
            }
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case RESET: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t ret = reset();
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case ON_USER_PASSWORD_CHANGED: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            String16 pass = data.readString16();
            int32_t ret = onUserPasswordChanged(userId, pass);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case LOCK: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            int32_t ret = lock(userId);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case UNLOCK: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            String16 pass = data.readString16();
            int32_t ret = unlock(userId, pass);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case IS_EMPTY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            bool ret = isEmpty(userId);
            reply->writeNoException();
            reply->writeInt32(ret ? 1 : 0);
            return NO_ERROR;
        } break;
        case GENERATE: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int32_t uid = data.readInt32();
            int32_t keyType = data.readInt32();
            int32_t keySize = data.readInt32();
            int32_t flags = data.readInt32();
            Vector<sp<KeystoreArg> > args;
            int32_t argsPresent = data.readInt32();
            if (argsPresent == 1) {
                ssize_t numArgs = data.readInt32();
                if (numArgs > MAX_GENERATE_ARGS) {
                    return BAD_VALUE;
                }
                if (numArgs > 0) {
                    for (size_t i = 0; i < (size_t) numArgs; i++) {
                        ssize_t inSize = data.readInt32();
                        if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
                            sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize),
                                                                  inSize);
                            args.push_back(arg);
                        } else {
                            args.push_back(NULL);
                        }
                    }
                }
            }
            int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case IMPORT: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            ssize_t inSize = data.readInt32();
            const void* in;
            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
                in = data.readInplace(inSize);
            } else {
                in = NULL;
                inSize = 0;
            }
            int uid = data.readInt32();
            int32_t flags = data.readInt32();
            int32_t ret = import(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case SIGN: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            ssize_t inSize = data.readInt32();
            const void* in;
            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
                in = data.readInplace(inSize);
            } else {
                in = NULL;
                inSize = 0;
            }
            void* out = NULL;
            size_t outSize = 0;
            int32_t ret = sign(name, (const uint8_t*) in, (size_t) inSize, (uint8_t**) &out, &outSize);
            reply->writeNoException();
            if (outSize > 0 && out != NULL) {
                reply->writeInt32(outSize);
                void* buf = reply->writeInplace(outSize);
                memcpy(buf, out, outSize);
                delete[] reinterpret_cast<uint8_t*>(out);
            } else {
                reply->writeInt32(-1);
            }
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case VERIFY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            ssize_t inSize = data.readInt32();
            const void* in;
            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
                in = data.readInplace(inSize);
            } else {
                in = NULL;
                inSize = 0;
            }
            ssize_t sigSize = data.readInt32();
            const void* sig;
            if (sigSize >= 0 && (size_t) sigSize <= data.dataAvail()) {
                sig = data.readInplace(sigSize);
            } else {
                sig = NULL;
                sigSize = 0;
            }
            bool ret = verify(name, (const uint8_t*) in, (size_t) inSize, (const uint8_t*) sig,
                    (size_t) sigSize);
            reply->writeNoException();
            reply->writeInt32(ret ? 1 : 0);
            return NO_ERROR;
        } break;
        case GET_PUBKEY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            void* out = NULL;
            size_t outSize = 0;
            int32_t ret = get_pubkey(name, (unsigned char**) &out, &outSize);
            reply->writeNoException();
            if (outSize > 0 && out != NULL) {
                reply->writeInt32(outSize);
                void* buf = reply->writeInplace(outSize);
                memcpy(buf, out, outSize);
                free(out);
            } else {
                reply->writeInt32(-1);
            }
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case GRANT: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int32_t granteeUid = data.readInt32();
            int32_t ret = grant(name, granteeUid);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case UNGRANT: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int32_t granteeUid = data.readInt32();
            int32_t ret = ungrant(name, granteeUid);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case GETMTIME: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            int32_t uid = data.readInt32();
            int64_t ret = getmtime(name, uid);
            reply->writeNoException();
            reply->writeInt64(ret);
            return NO_ERROR;
        } break;
        case DUPLICATE: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 srcKey = data.readString16();
            int32_t srcUid = data.readInt32();
            String16 destKey = data.readString16();
            int32_t destUid = data.readInt32();
            int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        } break;
        case IS_HARDWARE_BACKED: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 keyType = data.readString16();
            int32_t ret = is_hardware_backed(keyType);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        }
        case CLEAR_UID: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int64_t uid = data.readInt64();
            int32_t ret = clear_uid(uid);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        }
        case ADD_RNG_ENTROPY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            const uint8_t* bytes = NULL;
            size_t size = 0;
            readByteArray(data, &bytes, &size);
            int32_t ret = addRngEntropy(bytes, size);
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        }
        case GENERATE_KEY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            KeymasterArguments args;
            if (data.readInt32() != 0) {
                args.readFromParcel(data);
            }
            const uint8_t* entropy = NULL;
            size_t entropyLength = 0;
            readByteArray(data, &entropy, &entropyLength);
            int32_t uid = data.readInt32();
            int32_t flags = data.readInt32();
            KeyCharacteristics outCharacteristics;
            int32_t ret = generateKey(name, args, entropy, entropyLength, uid, flags,
                                      &outCharacteristics);
            reply->writeNoException();
            reply->writeInt32(ret);
            reply->writeParcelable(outCharacteristics);
            return NO_ERROR;
        }
        case GET_KEY_CHARACTERISTICS: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
            std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
            int32_t uid = data.readInt32();
            KeyCharacteristics outCharacteristics;
            int ret = getKeyCharacteristics(name, clientId.get(), appData.get(), uid,
                                            &outCharacteristics);
            if (clientId.get() && clientId->data) {
                free(const_cast<void*>(static_cast<const void*>(clientId->data)));
            }
            if (appData.get() && appData->data) {
                free(const_cast<void*>(static_cast<const void*>(appData->data)));
            }
            reply->writeNoException();
            reply->writeInt32(ret);
            reply->writeParcelable(outCharacteristics);
            return NO_ERROR;
        }
        case IMPORT_KEY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            KeymasterArguments args;
            if (data.readInt32() != 0) {
                args.readFromParcel(data);
            }
            keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
            const uint8_t* keyData = NULL;
            size_t keyLength = 0;
            readByteArray(data, &keyData, &keyLength);
            int32_t uid = data.readInt32();
            int32_t flags = data.readInt32();
            KeyCharacteristics outCharacteristics;
            int32_t ret = importKey(name, args, format, keyData, keyLength, uid, flags,
                                    &outCharacteristics);
            reply->writeNoException();
            reply->writeInt32(ret);
            reply->writeParcelable(outCharacteristics);
            return NO_ERROR;
        }
        case EXPORT_KEY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
            std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
            std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
            int32_t uid = data.readInt32();
            ExportResult result;
            exportKey(name, format, clientId.get(), appData.get(), uid, &result);
            if (clientId.get() && clientId->data) {
                free(const_cast<void*>(static_cast<const void*>(clientId->data)));
            }
            if (appData.get() && appData->data) {
                free(const_cast<void*>(static_cast<const void*>(appData->data)));
            }
            reply->writeNoException();
            reply->writeParcelable(result);

            return NO_ERROR;
        }
        case BEGIN: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            sp<IBinder> token = data.readStrongBinder();
            String16 name = data.readString16();
            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(data.readInt32());
            bool pruneable = data.readInt32() != 0;
            KeymasterArguments args;
            if (data.readInt32() != 0) {
                args.readFromParcel(data);
            }
            const uint8_t* entropy = NULL;
            size_t entropyLength = 0;
            readByteArray(data, &entropy, &entropyLength);
            int32_t uid = data.readInt32();
            OperationResult result;
            begin(token, name, purpose, pruneable, args, entropy, entropyLength, uid, &result);
            reply->writeNoException();
            reply->writeParcelable(result);

            return NO_ERROR;
        }
        case UPDATE: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            sp<IBinder> token = data.readStrongBinder();
            KeymasterArguments args;
            if (data.readInt32() != 0) {
                args.readFromParcel(data);
            }
            const uint8_t* buf = NULL;
            size_t bufLength = 0;
            readByteArray(data, &buf, &bufLength);
            OperationResult result;
            update(token, args, buf, bufLength, &result);
            reply->writeNoException();
            reply->writeParcelable(result);

            return NO_ERROR;
        }
        case FINISH: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            sp<IBinder> token = data.readStrongBinder();
            KeymasterArguments args;
            if (data.readInt32() != 0) {
                args.readFromParcel(data);
            }
            const uint8_t* signature = NULL;
            size_t signatureLength = 0;
            readByteArray(data, &signature, &signatureLength);
            const uint8_t* entropy = NULL;
            size_t entropyLength = 0;
            readByteArray(data, &entropy, &entropyLength);
            OperationResult result;
            finish(token, args, signature, signatureLength, entropy, entropyLength,  &result);
            reply->writeNoException();
            reply->writeParcelable(result);

            return NO_ERROR;
        }
        case ABORT: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            sp<IBinder> token = data.readStrongBinder();
            int32_t result = abort(token);
            reply->writeNoException();
            reply->writeInt32(result);

            return NO_ERROR;
        }
        case IS_OPERATION_AUTHORIZED: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            sp<IBinder> token = data.readStrongBinder();
            bool result = isOperationAuthorized(token);
            reply->writeNoException();
            reply->writeInt32(result ? 1 : 0);

            return NO_ERROR;
        }
        case ADD_AUTH_TOKEN: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            const uint8_t* token_bytes = NULL;
            size_t size = 0;
            readByteArray(data, &token_bytes, &size);
            int32_t result = addAuthToken(token_bytes, size);
            reply->writeNoException();
            reply->writeInt32(result);

            return NO_ERROR;
        }
        case ON_USER_ADDED: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            int32_t parentId = data.readInt32();
            int32_t result = onUserAdded(userId, parentId);
            reply->writeNoException();
            reply->writeInt32(result);

            return NO_ERROR;
        }
        case ON_USER_REMOVED: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            int32_t userId = data.readInt32();
            int32_t result = onUserRemoved(userId);
            reply->writeNoException();
            reply->writeInt32(result);

            return NO_ERROR;
        }
        case ATTEST_KEY: {
            CHECK_INTERFACE(IKeystoreService, data, reply);
            String16 name = data.readString16();
            KeymasterArguments params;
            if (data.readInt32() != 0) {
                params.readFromParcel(data);
            }
            KeymasterCertificateChain chain;
            int ret = attestKey(name, params, &chain);
            reply->writeNoException();
            reply->writeInt32(ret);
            reply->writeInt32(1);
            chain.writeToParcel(reply);

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

// ----------------------------------------------------------------------------

}; // namespace android
