am ad4661a0: Merge "Add Keymaster 1.0 binder methods"

* commit 'ad4661a0be6b627735116d26a32033c959852c40':
  Add Keymaster 1.0 binder methods
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 53788bd..e3f7602 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -16,6 +16,7 @@
 */
 
 #include <stdint.h>
+#include <sys/limits.h>
 #include <sys/types.h>
 
 #define LOG_TAG "KeystoreService"
@@ -29,6 +30,8 @@
 
 namespace android {
 
+static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length);
+
 KeystoreArg::KeystoreArg(const void* data, size_t len)
     : mData(data), mSize(len) {
 }
@@ -44,6 +47,317 @@
     return mSize;
 }
 
+OperationResult::OperationResult() : resultCode(0), token(), inputConsumed(0),
+    data(NULL), dataLength(0) {
+}
+
+OperationResult::~OperationResult() {
+}
+
+void OperationResult::readFromParcel(const Parcel& in) {
+    resultCode = in.readInt32();
+    token = in.readStrongBinder();
+    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");
+        }
+    }
+}
+
+void OperationResult::writeToParcel(Parcel* out) const {
+    out->writeInt32(resultCode);
+    out->writeStrongBinder(token);
+    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.");
+        }
+    }
+}
+
+ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
+}
+
+ExportResult::~ExportResult() {
+}
+
+void ExportResult::readFromParcel(const Parcel& in) {
+    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");
+        }
+    }
+}
+
+void 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.");
+        }
+    }
+}
+
+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);
+}
+
+void KeyCharacteristics::readFromParcel(const Parcel& in) {
+    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;
+}
+
+void 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);
+    }
+}
+
+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_INT:
+        case KM_INT_REP: {
+            out->writeInt32(param.tag);
+            out->writeInt32(param.integer);
+            break;
+        }
+        case KM_LONG: {
+            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_INT:
+        case KM_INT_REP: {
+            uint32_t value = in.readInt32();
+            *out = keymaster_param_int(tag, value);
+            break;
+        }
+        case KM_LONG: {
+            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");
+                    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 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 void readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
+    ssize_t length = in.readInt32();
+    if (length > 0) {
+        blob->data = (uint8_t*) in.readInplace(length);
+        if (blob->data) {
+            blob->data_length = (size_t) length;
+        } else {
+            blob->data_length = 0;
+        }
+    } else {
+        blob->data = NULL;
+        blob->data_length = 0;
+    }
+}
+
 class BpKeystoreService: public BpInterface<IKeystoreService>
 {
 public:
@@ -639,6 +953,253 @@
         }
         return ret;
     }
+    virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(bufLength);
+        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,
+                                int uid, int flags, KeyCharacteristics* outCharacteristics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(1);
+        params.writeToParcel(&data);
+        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 (reply.readInt32() != 0 && outCharacteristics) {
+            outCharacteristics->readFromParcel(reply);
+        }
+        return ret;
+    }
+    virtual int32_t getKeyCharacteristics(const String16& name,
+                                          const keymaster_blob_t& clientId,
+                                          const keymaster_blob_t& appData,
+                                          KeyCharacteristics* outCharacteristics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeByteArray(clientId.data_length, clientId.data);
+        data.writeByteArray(appData.data_length, appData.data);
+        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 (reply.readInt32() != 0 && outCharacteristics) {
+            outCharacteristics->readFromParcel(reply);
+        }
+        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 (reply.readInt32() != 0 && outCharacteristics) {
+            outCharacteristics->readFromParcel(reply);
+        }
+        return ret;
+    }
+
+    virtual void exportKey(const String16& name, keymaster_key_format_t format,
+                           const keymaster_blob_t& clientId,
+                           const keymaster_blob_t& appData, ExportResult* result)
+    {
+        if (!result) {
+            return;
+        }
+
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(format);
+        data.writeByteArray(clientId.data_length, clientId.data);
+        data.writeByteArray(appData.data_length, appData.data);
+        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;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual void begin(const sp<IBinder>& appToken, const String16& name,
+                       keymaster_purpose_t purpose, bool pruneable,
+                       const KeymasterArguments& params, KeymasterArguments* outParams,
+                       OperationResult* result)
+    {
+        if (!result || !outParams) {
+            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);
+        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;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+        if (reply.readInt32() != 0) {
+            outParams->readFromParcel(reply);
+        }
+    }
+
+    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
+                        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;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                        uint8_t* signature, size_t signatureLength, 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);
+        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;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual int32_t abort(const sp<IBinder>& token)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        status_t status = remote()->transact(BnKeystoreService::FINISH, 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;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
@@ -965,6 +1526,170 @@
             reply->writeInt32(ret);
             return NO_ERROR;
         }
+        case ADD_RNG_ENTROPY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            size_t size = data.readInt32();
+            uint8_t* bytes;
+            if (size > 0) {
+                bytes = (uint8_t*) data.readInplace(size);
+            } else {
+                bytes = NULL;
+            }
+            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);
+            }
+            int32_t uid = data.readInt32();
+            int32_t flags = data.readInt32();
+            KeyCharacteristics outCharacteristics;
+            int32_t ret = generateKey(name, args, uid, flags, &outCharacteristics);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            reply->writeInt32(1);
+            outCharacteristics.writeToParcel(reply);
+            return NO_ERROR;
+        }
+        case GET_KEY_CHARACTERISTICS: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            keymaster_blob_t clientId, appData;
+            readKeymasterBlob(data, &clientId);
+            readKeymasterBlob(data, &appData);
+            KeyCharacteristics outCharacteristics;
+            int ret = getKeyCharacteristics(name, clientId, appData, &outCharacteristics);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            reply->writeInt32(1);
+            outCharacteristics.writeToParcel(reply);
+            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());
+            uint8_t* keyData = NULL;
+            ssize_t keyLength = data.readInt32();
+            size_t ukeyLength = (size_t) keyLength;
+            if (keyLength >= 0) {
+                keyData = (uint8_t*) data.readInplace(keyLength);
+            } else {
+                ukeyLength = 0;
+            }
+            int32_t uid = data.readInt32();
+            int32_t flags = data.readInt32();
+            KeyCharacteristics outCharacteristics;
+            int32_t ret = importKey(name, args, format, keyData, ukeyLength, uid, flags,
+                                    &outCharacteristics);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            reply->writeInt32(1);
+            outCharacteristics.writeToParcel(reply);
+
+            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());
+            keymaster_blob_t clientId, appData;
+            readKeymasterBlob(data, &clientId);
+            readKeymasterBlob(data, &appData);
+            ExportResult result;
+            exportKey(name, format, clientId, appData, &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            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);
+            }
+            KeymasterArguments outArgs;
+            OperationResult result;
+            begin(token, name, purpose, pruneable, args, &outArgs, &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+            reply->writeInt32(1);
+            outArgs.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case UPDATE: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            uint8_t* buf = NULL;
+            ssize_t bufLength = data.readInt32();
+            size_t ubufLength = (size_t) bufLength;
+            if (bufLength > 0) {
+                buf = (uint8_t*) data.readInplace(ubufLength);
+            } else {
+                ubufLength = 0;
+            }
+            OperationResult result;
+            update(token, args, buf, ubufLength, &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case FINISH: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            uint8_t* buf = NULL;
+            ssize_t bufLength = data.readInt32();
+            size_t ubufLength = (size_t) bufLength;
+            if (bufLength > 0) {
+                buf = (uint8_t*) data.readInplace(ubufLength);
+            } else {
+                ubufLength = 0;
+            }
+            OperationResult result;
+            finish(token, args, buf, ubufLength, &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            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;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index afdff8d..f69b76e 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -17,9 +17,11 @@
 #ifndef KEYSTORE_IKEYSTORESERVICE_H
 #define KEYSTORE_IKEYSTORESERVICE_H
 
+#include <hardware/keymaster_defs.h>
 #include <utils/RefBase.h>
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
+#include <vector>
 
 namespace android {
 
@@ -36,6 +38,59 @@
     size_t mSize;
 };
 
+struct MallocDeleter {
+    void operator()(uint8_t* p) { free(p); }
+};
+
+// struct for serializing the results of begin/update/finish
+struct OperationResult {
+    OperationResult();
+    ~OperationResult();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    int resultCode;
+    sp<IBinder> token;
+    int inputConsumed;
+    std::unique_ptr<uint8_t[], MallocDeleter> data;
+    size_t dataLength;
+};
+
+// struct for serializing the results of export
+struct ExportResult {
+    ExportResult();
+    ~ExportResult();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    int resultCode;
+    std::unique_ptr<uint8_t[], MallocDeleter> exportData;
+    size_t dataLength;
+};
+
+// struct for serializing/deserializing a list of keymaster_key_param_t's
+struct KeymasterArguments {
+    KeymasterArguments();
+    ~KeymasterArguments();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    std::vector<keymaster_key_param_t> params;
+};
+
+// struct for serializing keymaster_key_characteristics_t's
+struct KeyCharacteristics {
+    KeyCharacteristics();
+    ~KeyCharacteristics();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    keymaster_key_characteristics_t characteristics;
+};
+
+bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out);
+void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out);
+
 /*
  * This must be kept manually in sync with frameworks/base's IKeystoreService.java
  */
@@ -68,6 +123,15 @@
         RESET_UID = IBinder::FIRST_CALL_TRANSACTION + 23,
         SYNC_UID = IBinder::FIRST_CALL_TRANSACTION + 24,
         PASSWORD_UID = IBinder::FIRST_CALL_TRANSACTION + 25,
+        ADD_RNG_ENTROPY = IBinder::FIRST_CALL_TRANSACTION + 26,
+        GENERATE_KEY = IBinder::FIRST_CALL_TRANSACTION + 27,
+        GET_KEY_CHARACTERISTICS = IBinder::FIRST_CALL_TRANSACTION + 28,
+        IMPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 29,
+        EXPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 30,
+        BEGIN = IBinder::FIRST_CALL_TRANSACTION + 31,
+        UPDATE = IBinder::FIRST_CALL_TRANSACTION + 32,
+        FINISH = IBinder::FIRST_CALL_TRANSACTION + 33,
+        ABORT = IBinder::FIRST_CALL_TRANSACTION + 34,
     };
 
     DECLARE_META_INTERFACE(KeystoreService);
@@ -129,6 +193,37 @@
     virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) = 0;
 
     virtual int32_t password_uid(const String16& password, int32_t uid) = 0;
+
+    virtual int32_t addRngEntropy(const uint8_t* data, size_t dataLength) = 0;
+
+    virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
+                                int uid, int flags, KeyCharacteristics* outCharacteristics) = 0;
+    virtual int32_t getKeyCharacteristics(const String16& name,
+                                          const keymaster_blob_t& clientId,
+                                          const keymaster_blob_t& appData,
+                                          KeyCharacteristics* outCharacteristics) = 0;
+    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) = 0;
+
+    virtual void exportKey(const String16& name, keymaster_key_format_t format,
+                           const keymaster_blob_t& clientId,
+                           const keymaster_blob_t& appData, ExportResult* result) = 0;
+
+    virtual void begin(const sp<IBinder>& apptoken, const String16& name,
+                       keymaster_purpose_t purpose, bool pruneable,
+                       const KeymasterArguments& params, KeymasterArguments* outParams,
+                       OperationResult* result) = 0;
+
+    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
+                        uint8_t* data, size_t dataLength, OperationResult* result) = 0;
+
+    virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                        uint8_t* signature, size_t signatureLength, OperationResult* result) = 0;
+
+    virtual int32_t abort(const sp<IBinder>& handle) = 0;
+
 };
 
 // ----------------------------------------------------------------------------
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 194b87c..cf799f1 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -2433,6 +2433,56 @@
         return ::SYSTEM_ERROR;
     }
 
+    int32_t addRngEntropy(const uint8_t* /*data*/, size_t /*dataLength*/) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+
+    int32_t generateKey(const String16& /*name*/, const KeymasterArguments& /*params*/,
+                        int /*uid*/, int /*flags*/, KeyCharacteristics* /*outCharacteristics*/) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+
+    int32_t getKeyCharacteristics(const String16& /*name*/,
+                                  const keymaster_blob_t& /*clientId*/,
+                                  const keymaster_blob_t& /*appData*/,
+                                  KeyCharacteristics* /*outCharacteristics*/) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+
+    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*/) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+
+    void exportKey(const String16& /*name*/, keymaster_key_format_t /*format*/,
+                           const keymaster_blob_t& /*clientId*/,
+                           const keymaster_blob_t& /*appData*/, ExportResult* result) {
+        result->resultCode = KM_ERROR_UNIMPLEMENTED;
+    }
+
+    void begin(const sp<IBinder>& /*appToken*/, const String16& /*name*/,
+               keymaster_purpose_t /*purpose*/, bool /*pruneable*/,
+               const KeymasterArguments& /*params*/, KeymasterArguments* /*outParams*/,
+               OperationResult* result) {
+        result->resultCode = KM_ERROR_UNIMPLEMENTED;
+    }
+
+    void update(const sp<IBinder>& /*token*/, const KeymasterArguments& /*params*/,
+                uint8_t* /*data*/, size_t /*dataLength*/, OperationResult* result) {
+        result->resultCode = KM_ERROR_UNIMPLEMENTED;
+    }
+
+    void finish(const sp<IBinder>& /*token*/, const KeymasterArguments& /*args*/,
+                uint8_t* /*signature*/, size_t /*signatureLength*/, OperationResult* result) {
+        result->resultCode = KM_ERROR_UNIMPLEMENTED;
+    }
+
+    int32_t abort(const sp<IBinder>& /*token*/) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+
 private:
     inline bool isKeystoreUnlocked(State state) {
         switch (state) {