keymaster: Add keymaster implementation

Initial implementation of keymaster HAL APIs published in keymaster.h

Bug: 7106634
Change-Id: I1b1f611f1988212ce5f6f7f03b9a59ca652d92cf
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..467d7a0
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(filter msm8960,$(TARGET_BOARD_PLATFORM)),)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := keystore.msm8960
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_SRC_FILES := keymaster_qcom.cpp
+
+LOCAL_C_INCLUDES := $(TARGET_OUT_HEADERS)/common/inc \
+                    external/openssl/include
+
+LOCAL_C_FLAGS = -fvisibility=hidden -Wall -Werror
+
+LOCAL_SHARED_LIBRARIES := \
+        libcrypto \
+        liblog \
+        libc \
+        libdl
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # msm8960 == TARGET_BOARD_PLATFORM
diff --git a/QSEEComAPI.h b/QSEEComAPI.h
new file mode 100644
index 0000000..a96cda3
--- /dev/null
+++ b/QSEEComAPI.h
@@ -0,0 +1,299 @@
+/*
+ *  Copyright (c) 2012, The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you
+ *  may not use this file except in compliance with the License.  You may
+ *  obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied.  See the License for the specific language governing
+ *  permissions and limitations under the License.
+ */
+
+#ifndef __QSEECOMAPI_H_
+#define __QSEECOMAPI_H_
+
+
+/*----------------------------------------------------------------------------
+ * Include Files
+* -------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <stdbool.h>
+
+#define QSEECOM_ALIGN_SIZE	0x40
+#define QSEECOM_ALIGN_MASK	(QSEECOM_ALIGN_SIZE - 1)
+#define QSEECOM_ALIGN(x)	\
+	((x + QSEECOM_ALIGN_SIZE) & (~QSEECOM_ALIGN_MASK))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------
+ * Preprocessor Definitions and Constants
+ * -------------------------------------------------------------------------*/
+/** The memory is locked and non-pageable */
+#define MEM_LOCKED         0x00000001
+/** The memory is marked non-cacheable */
+#define MEM_NON_CACHED     0x00000002
+
+#define QSEECOM_APP_QUERY_FAILED       -6
+#define QSEECOM_APP_NOT_LOADED         -5
+#define QSEECOM_APP_ALREADY_LOADED     -4
+#define QSEECOM_LISTENER_UNREGISTERED	-3
+#define QSEECOM_LISTENER_ALREADY_REGISTERED	-2
+#define QSEECOM_LISTENER_REGISTER_FAIL		-1
+
+/*----------------------------------------------------------------------------
+ * Type Declarations
+ * -------------------------------------------------------------------------*/
+struct QSEECom_handle {
+	unsigned char *ion_sbuffer;
+};
+
+struct QSEECom_ion_fd_data {
+	int32_t fd;
+	uint32_t cmd_buf_offset;
+};
+
+struct QSEECom_ion_fd_info {
+	struct QSEECom_ion_fd_data data[4];
+};
+
+/*----------------------------------------------------------------------------
+ * Function Declarations and Documentation
+ * -------------------------------------------------------------------------*/
+/**
+ * @brief Open a handle to the  QSEECom device.
+ *
+ * - Load a secure application. The application will be verified that it is
+ *    secure by digital signature verification.
+ * Allocate memory for sending requests to the QSAPP
+ *
+ * Note/Comments:
+ * There is a one-to-one relation for a HLOS client and a QSAPP;
+ * meaning that only one app can communicate to a QSAPP at a time.
+ *
+ * Please note that there is difference between an application and a listener
+ * service. A QSAPP must be loaded at the request of the HLOS,
+ * and all requests are orginated by the HLOS client.
+ * A listener service on the otherhand is started during start-up by a
+ * daemon, qseecomd.
+ *
+ * A HLOS application may create mutiple handles to the QSAPP
+ *
+ * @param[in/out] handle The device handle
+ * @param[in] fname The directory and filename to load.
+ * @param[in] sb_size Size of the shared buffer memory  for sending requests.
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_start_app(struct QSEECom_handle **clnt_handle, const char *path,
+			const char *fname, uint32_t sb_size);
+
+/**
+ * @brief Close the application associated with the handle.
+ *
+ * - Unload a secure application. The driver will verify if there exists
+ *   any other applications that are communicating with the QSAPP to which
+ *   the "handle" is tied.
+ * - De-allocate memory for sending requests to QSAPP.
+ *
+ * @param[in] handle The device handle
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_shutdown_app(struct QSEECom_handle **handle);
+
+/**
+ * @brief Open a handle to the  QSEECom device.
+ *
+ * - Load an external elf. The elf will be verified that it is
+ *    secure by digital signature verification.
+ *
+ * A HLOS application may create mutiple opens (only one is permitted for the
+ * app, but each listener service can open a unique device in the same HLOS app
+ * /executable.
+ * @param[in/out] handle The device handle
+ * @param[in] fname The directory and filename to load.
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_load_external_elf(struct QSEECom_handle **clnt_handle, const char *path,
+			const char *fname);
+
+/**
+ * @brief Close the external elf
+ *
+ * - Unload an external elf.
+ *
+ * @param[in] handle The device handle
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_unload_external_elf(struct QSEECom_handle **handle);
+
+/**
+ * @brief Register an HLOS listener service. This allows messages from QSAPP
+ * to be received.
+ *
+ * @param[in] handle The device handle
+ * @param[in] lstnr_id The listener service identifier. This ID must be uniquely
+ * assigned to avoid any collisions.
+ * @param[in] sb_length Shared memory buffer between OS and QSE.
+ * @param[in] flags Provide the shared memory flags attributes.
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ *
+ */
+int QSEECom_register_listener(struct QSEECom_handle **handle,
+			uint32_t lstnr_id, uint32_t sb_length, uint32_t flags);
+
+/**
+ * @brief Unregister a listener service.
+ *
+ * @param[in] handle The device handle
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_unregister_listener(struct QSEECom_handle *handle);
+
+
+/**
+ * @brief Send QSAPP a "user" defined buffer (may contain some message/
+ * command request) and receives a response from QSAPP in receive buffer.
+ * The HLOS client writes to the send_buf, where QSAPP writes to the rcv_buf.
+ * This is a blocking call.
+ *
+ * @param[in] handle    The device handle
+ * @param[in] send_buf  The buffer to be sent.
+ *                      If using ion_sbuffer, ensure this
+ *                      QSEECOM_BUFFER_ALIGN'ed.
+ * @param[in] sbuf_len  The send buffer length
+ *                      If using ion_sbuffer, ensure length is
+ *                      multiple of QSEECOM_BUFFER_ALIGN.
+ * @param[in] rcv_buf   The QSEOS returned buffer.
+ *                      If using ion_sbuffer, ensure this is
+ *                      QSEECOM_BUFFER_ALIGN'ed.
+ * @param[in] rbuf_len  The returned buffer length.
+ *                      If using ion_sbuffer, ensure length is
+ *                      multiple of QSEECOM_BUFFER_ALIGN.
+ * @param[in] rbuf_len  The returned buffer length.
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_send_cmd(struct QSEECom_handle *handle, void *send_buf,
+			uint32_t sbuf_len, void *rcv_buf, uint32_t rbuf_len);
+
+
+/**
+ * @brief Send QSAPP a "user" defined buffer (may contain some message/
+ * command request) and receives a response from QSAPP in receive buffer.
+ * This API is same as send_cmd except it takes in addition parameter,
+ * "ifd_data".  This "ifd_data" holds information (ion fd handle and
+ * cmd_buf_offset) used for modifying data in the message in send_buf
+ * at an offset.  Essentailly, it has the ion fd handle information to
+ * retrieve physical address and modify the message in send_buf at the
+ * mentioned offset.
+ *
+ * The HLOS client writes to the send_buf, where QSAPP writes to the rcv_buf.
+ * This is a blocking call.
+ *
+ * @param[in] handle    The device handle
+ * @param[in] send_buf  The buffer to be sent.
+ *                      If using ion_sbuffer, ensure this
+ *                      QSEECOM_BUFFER_ALIGN'ed.
+ * @param[in] sbuf_len  The send buffer length
+ *                      If using ion_sbuffer, ensure length is
+ *                      multiple of QSEECOM_BUFFER_ALIGN.
+ * @param[in] rcv_buf   The QSEOS returned buffer.
+ *                      If using ion_sbuffer, ensure this is
+ *                      QSEECOM_BUFFER_ALIGN'ed.
+ * @param[in] rbuf_len  The returned buffer length.
+ *                      If using ion_sbuffer, ensure length is
+ *                      multiple of QSEECOM_BUFFER_ALIGN.
+ * @param[in] QSEECom_ion_fd_info  data related to memory allocated by ion.
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_send_modified_cmd(struct QSEECom_handle *handle, void *send_buf,
+			uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len,
+			struct QSEECom_ion_fd_info  *ifd_data);
+
+/**
+ * @brief Receive a service defined buffer.
+ *
+ * @param[in] handle    The device handle
+ * @param[out] buf      The buffer that is received
+ * @param[in] len       The receive buffer length
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_receive_req(struct QSEECom_handle *handle,
+			void *buf, uint32_t len);
+
+/**
+ * @brief Send a response based on the previous QSEECom_receive_req.
+ *
+ * This allows a listener service to receive a command (e.g. read file abc).
+ * The service can then handle the request from QSEECom_receive_req, and provide
+ * that information back to QSAPP.
+ *
+ * This allows the HLOS to act as the server and QSAPP to behave as the client.
+ *
+ * @param[in] handle    The device handle
+ * @param[out] send_buf  The buffer to be returned back to QSAPP
+ * @param[in] len       The send buffer length
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_send_resp(struct QSEECom_handle *handle,
+			void *send_buf, uint32_t len);
+
+/**
+ * @brief Set the bandwidth for QSEE.
+ *
+ * This API resulst in improving the performance on the Crypto hardware
+ * in QSEE. It should be called before issuing send_cmd/send_modified_cmd
+ * for commands that requires using the crypto hardware on the QSEE.
+ * Typically this API should be called before issuing the send request to
+ * enable high performance mode and after completion of the send_cmd to
+ * resume to low performance and hence to low power mode.
+ *
+ * This allows the clients of QSEECom to set the QSEE cyptpo HW bus
+ * bandwidth to high/low.
+ *
+ * @param[in] high    Set to 1 to enable bandwidth.
+ *
+ * @return Zero on success, negative on failure. errno will be set on
+ *  error.
+ */
+int QSEECom_set_bandwidth(struct QSEECom_handle *handle, bool high);
+
+/**
+ * @brief Query QSEE to check if app is loaded.
+ *
+ * This API queries QSEE to see if the app is loaded or not.
+ *
+ * @param[in] app_name  Name of the app.
+ *
+ * @return QSEECOM_APP_QUERY_FAILED/QSEECOM_APP_NOT_LOADED/QSEECOM_APP_LOADED.
+ */
+int QSEECom_app_load_query(struct QSEECom_handle *handle, char *app_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/keymaster_qcom.cpp b/keymaster_qcom.cpp
new file mode 100644
index 0000000..4f64c8e
--- /dev/null
+++ b/keymaster_qcom.cpp
@@ -0,0 +1,751 @@
+/*
+ *  Copyright (C) 2012 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you
+ *  may not use this file except in compliance with the License.  You may
+ *  obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied.  See the License for the specific language governing
+ *  permissions and limitations under the License.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster.h>
+
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/rsa.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+#include <utils/UniquePtr.h>
+#include <linux/ioctl.h>
+#include <linux/msm_ion.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+#include "QSEEComAPI.h"
+#include "keymaster_qcom.h"
+
+// For debugging
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "QCOMKeyMaster"
+#include <cutils/log.h>
+struct qcom_km_ion_info_t {
+    int32_t ion_fd;
+    int32_t ifd_data_fd;
+    struct ion_handle_data ion_alloc_handle;
+    unsigned char * ion_sbuffer;
+    uint32_t sbuf_len;
+};
+
+struct qcom_keymaster_handle {
+    struct QSEECom_handle *qseecom;
+    void *libhandle;
+    int (*QSEECom_start_app)(struct QSEECom_handle ** handle, const char* path,
+                          const char* appname, uint32_t size);
+    int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle);
+    int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf,
+                          uint32_t clen, void *rbuf, uint32_t rlen);
+    int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf,
+                          uint32_t clen, void *rbuf, uint32_t rlen,
+                          struct QSEECom_ion_fd_info *ihandle);
+};
+typedef struct qcom_keymaster_handle qcom_keymaster_handle_t;
+
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) const {
+        EVP_PKEY_free(p);
+    }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct RSA_Delete {
+    void operator()(RSA* p) const {
+        RSA_free(p);
+    }
+};
+typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
+
+typedef UniquePtr<keymaster_device_t> Unique_keymaster_device_t;
+
+/**
+ * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
+ * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
+ * without triggering a warning by not using the result of release().
+ */
+#define OWNERSHIP_TRANSFERRED(obj) \
+    typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
+
+static int qcom_km_get_keypair_public(const keymaster_device* dev,
+        const uint8_t* keyBlob, const size_t keyBlobLength,
+        uint8_t** x509_data, size_t* x509_data_length) {
+
+    struct qcom_km_key_blob * keyblob_ptr = (struct qcom_km_key_blob *)keyBlob;
+
+    if (x509_data == NULL || x509_data_length == NULL) {
+        ALOGE("Output public key buffer == NULL");
+        return -1;
+    }
+
+    if (keyBlob == NULL) {
+        ALOGE("Supplied key blob was NULL");
+        return -1;
+    }
+
+    // Should be large enough for keyblob data:
+    if (keyBlobLength < (sizeof(qcom_km_key_blob_t))) {
+        ALOGE("key blob appears to be truncated");
+        return -1;
+    }
+
+    if (keyblob_ptr->magic_num != KM_MAGIC_NUM) {
+        ALOGE("Cannot read key; it was not made by this keymaster");
+        return -1;
+    }
+
+    if (keyblob_ptr->public_exponent_size == 0 ) {
+        ALOGE("Key blob appears to have incorrect exponent length");
+        return -1;
+    }
+    if (keyblob_ptr->modulus_size == 0 ) {
+        ALOGE("Key blob appears to have incorrect modulus length");
+        return -1;
+    }
+
+    Unique_RSA rsa(RSA_new());
+    if (rsa.get() == NULL) {
+        ALOGE("Could not allocate RSA structure");
+        return -1;
+    }
+
+    rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(keyblob_ptr->modulus),
+                               keyblob_ptr->modulus_size, NULL);
+    if (rsa->n == NULL) {
+       ALOGE("Failed to initialize  modulus");
+        return -1;
+    }
+
+    rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(&keyblob_ptr->public_exponent),
+                               keyblob_ptr->public_exponent_size, NULL);
+    if (rsa->e == NULL) {
+        ALOGE("Failed to initialize public exponent");
+        return -1;
+    }
+
+    Unique_EVP_PKEY pkey(EVP_PKEY_new());
+    if (pkey.get() == NULL) {
+        ALOGE("Could not allocate EVP_PKEY structure");
+        return -1;
+    }
+    if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
+        ALOGE("Failed to assign rsa  parameters \n");
+        return -1;
+    }
+    OWNERSHIP_TRANSFERRED(rsa);
+
+    int len = i2d_PUBKEY(pkey.get(), NULL);
+    if (len <= 0) {
+        ALOGE("Len returned is < 0 len = %d", len);
+        return -1;
+    }
+
+    UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len)));
+    if (key.get() == NULL) {
+        ALOGE("Could not allocate memory for public key data");
+        return -1;
+    }
+
+    unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
+    if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
+        ALOGE("Len 2 returned is < 0 len = %d", len);
+        return -1;
+    }
+    *x509_data_length = len;
+    *x509_data = key.release();
+
+    return 0;
+}
+
+static int32_t qcom_km_ION_memalloc(struct qcom_km_ion_info_t *handle,
+                                uint32_t size)
+{
+    int32_t ret = 0;
+    int32_t iret = 0;
+    int32_t fd = 0;
+    unsigned char *v_addr;
+    struct ion_allocation_data ion_alloc_data;
+    int32_t ion_fd;
+    int32_t rc;
+    struct ion_fd_data ifd_data;
+    struct ion_handle_data handle_data;
+
+    /* open ION device for memory management
+     * O_DSYNC -> uncached memory
+    */
+    if(handle == NULL){
+      ALOGE("Error:: null handle received");
+      return -1;
+    }
+    ion_fd  = open("/dev/ion", O_RDONLY | O_DSYNC);
+    if (ion_fd < 0) {
+       ALOGE("Error::Cannot open ION device");
+       return -1;
+    }
+    handle->ion_sbuffer = NULL;
+    handle->ifd_data_fd = 0;
+
+    /* Size of allocation */
+    ion_alloc_data.len = (size + 4095) & (~4095);
+
+    /* 4K aligned */
+    ion_alloc_data.align = 4096;
+
+    /* memory is allocated from EBI heap */
+    ion_alloc_data.heap_mask = ION_HEAP_CARVEOUT_MASK;
+
+    /* Set the memory to be uncached */
+    ion_alloc_data.flags = ION_HEAP(ION_QSECOM_HEAP_ID);
+
+    /* IOCTL call to ION for memory request */
+    rc = ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc_data);
+    if (rc) {
+       ret = -1;
+       goto alloc_fail;
+    }
+
+    if (ion_alloc_data.handle != NULL) {
+       ifd_data.handle = ion_alloc_data.handle;
+    } else {
+       ret = -1;
+       goto alloc_fail;
+    }
+    /* Call MAP ioctl to retrieve the ifd_data.fd file descriptor */
+    rc = ioctl(ion_fd, ION_IOC_MAP, &ifd_data);
+    if (rc) {
+       ret = -1;
+       goto ioctl_fail;
+    }
+
+    /* Make the ion mmap call */
+    v_addr = (unsigned char *)mmap(NULL, ion_alloc_data.len,
+                                    PROT_READ | PROT_WRITE,
+                                    MAP_SHARED, ifd_data.fd, 0);
+    if (v_addr == MAP_FAILED) {
+       ALOGE("Error::ION MMAP failed");
+       ret = -1;
+       goto map_fail;
+    }
+    handle->ion_fd = ion_fd;
+    handle->ifd_data_fd = ifd_data.fd;
+    handle->ion_sbuffer = v_addr;
+    handle->ion_alloc_handle.handle = ion_alloc_data.handle;
+    handle->sbuf_len = size;
+    return ret;
+
+map_fail:
+    if (handle->ion_sbuffer != NULL) {
+        iret = munmap(handle->ion_sbuffer, ion_alloc_data.len);
+        if (iret)
+           ALOGE("Error::Failed to unmap memory for load image. ret = %d", ret);
+    }
+
+ioctl_fail:
+    handle_data.handle = ion_alloc_data.handle;
+    if (handle->ifd_data_fd)
+        close(handle->ifd_data_fd);
+    iret = ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+    if (iret) {
+       ALOGE("Error::ION FREE ioctl returned error = %d",iret);
+    }
+
+alloc_fail:
+    if (ion_fd > 0)
+       close(ion_fd);
+    return ret;
+}
+
+/** @brief: Deallocate ION memory
+ *
+ *
+ */
+static int32_t qcom_km_ion_dealloc(struct qcom_km_ion_info_t *handle)
+{
+    struct ion_handle_data handle_data;
+    int32_t ret = 0;
+
+    /* Deallocate the memory for the listener */
+    ret = munmap(handle->ion_sbuffer, (handle->sbuf_len + 4095) & (~4095));
+    if (ret) {
+        ALOGE("Error::Unmapping ION Buffer failed with ret = %d", ret);
+    }
+
+    handle_data.handle = handle->ion_alloc_handle.handle;
+    close(handle->ifd_data_fd);
+    ret = ioctl(handle->ion_fd, ION_IOC_FREE, &handle_data);
+    if (ret) {
+        ALOGE("Error::ION Memory FREE ioctl failed with ret = %d", ret);
+    }
+    close(handle->ion_fd);
+    return ret;
+}
+
+static int qcom_km_generate_keypair(const keymaster_device_t* dev,
+        const keymaster_keypair_t key_type, const void* key_params,
+        uint8_t** keyBlob, size_t* keyBlobLength) {
+
+    if (dev->context == NULL) {
+        ALOGE("qcom_km_generate_keypair: Context == NULL");
+        return -1;
+    }
+
+    if (key_type != TYPE_RSA) {
+        ALOGE("Unsupported key type %d", key_type);
+        return -1;
+    } else if (key_params == NULL) {
+        ALOGE("key_params == null");
+        return -1;
+    }
+    if (keyBlob == NULL || keyBlobLength == NULL) {
+        ALOGE("output key blob or length == NULL");
+        return -1;
+    }
+    keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;
+
+    keymaster_gen_keypair_cmd_t *send_cmd = NULL;
+    keymaster_gen_keypair_resp_t  *resp = NULL;
+    struct QSEECom_handle *handle = NULL;
+    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
+    int ret = 0;
+
+    handle = (struct QSEECom_handle *)(km_handle->qseecom);
+    send_cmd = (keymaster_gen_keypair_cmd_t *)handle->ion_sbuffer;
+    resp = (keymaster_gen_keypair_resp_t *)(handle->ion_sbuffer +
+                               QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)));
+    send_cmd->cmd_id = KEYMASTER_GENERATE_KEYPAIR;
+    send_cmd->key_type = key_type;
+    send_cmd->rsa_params.modulus_size = rsa_params->modulus_size;
+    send_cmd->rsa_params.public_exponent = rsa_params->public_exponent;
+    resp->status = KEYMASTER_FAILURE;
+    resp->key_blob_len =  sizeof(qcom_km_key_blob_t);
+
+    ret = (*km_handle->QSEECom_send_cmd)(handle, send_cmd,
+                               QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)), resp,
+                               QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_resp_t)));
+
+    if ( (ret < 0)  ||  (resp->status  < 0)) {
+        ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret);
+        return -1;
+    } else {
+        UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
+        if (keydata.get() == NULL) {
+            ALOGE("could not allocate memory for key blob");
+            return -1;
+        }
+        unsigned char* p = keydata.get();
+        memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
+        *keyBlob = keydata.release();
+        *keyBlobLength = resp->key_blob_len;
+    }
+    return 0;
+}
+
+static int qcom_km_import_keypair(const keymaster_device_t* dev,
+        const uint8_t* key, const size_t key_length,
+        uint8_t** keyBlob, size_t* keyBlobLength)
+{
+    if (dev->context == NULL) {
+        ALOGE("qcom_km_import_keypair: Context  == NULL");
+        return -1;
+    }
+
+    if (key == NULL) {
+        ALOGE("Input key == NULL");
+        return -1;
+    } else if (keyBlob == NULL || keyBlobLength == NULL) {
+        ALOGE("Output key blob or length == NULL");
+        return -1;
+    }
+
+    struct QSEECom_ion_fd_info  ion_fd_info;
+    struct qcom_km_ion_info_t ihandle;
+    int ret = 0;
+
+    ihandle.ion_fd = 0;
+    ihandle.ion_alloc_handle.handle = NULL;
+    if (qcom_km_ION_memalloc(&ihandle, QSEECOM_ALIGN(key_length)) < 0) {
+        ALOGE("ION allocation  failed");
+        return -1;
+    }
+    memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
+
+    /* Populate the send data structure */
+    ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
+    ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t);
+
+
+    struct QSEECom_handle *handle = NULL;
+    keymaster_import_keypair_cmd_t *send_cmd = NULL;
+    keymaster_import_keypair_resp_t  *resp = NULL;
+    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
+
+    handle = (struct QSEECom_handle *)(km_handle->qseecom);
+    send_cmd = (keymaster_import_keypair_cmd_t *)handle->ion_sbuffer;
+    resp = (keymaster_import_keypair_resp_t *)(handle->ion_sbuffer +
+                                        QSEECOM_ALIGN(sizeof(keymaster_import_keypair_cmd_t)));
+    send_cmd->cmd_id = KEYMASTER_IMPORT_KEYPAIR;
+    send_cmd->pkcs8_key = (uint32_t)ihandle.ion_sbuffer;
+
+    memcpy((unsigned char *)ihandle.ion_sbuffer, key, key_length);
+
+    send_cmd->pkcs8_key_len = key_length;
+    resp->status = KEYMASTER_FAILURE;
+    resp->key_blob_len =  sizeof(qcom_km_key_blob_t);
+
+    ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
+                               QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
+                               QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
+
+    if ( (ret < 0)  ||  (resp->status  < 0)) {
+        ALOGE("Import key command failed resp->status = %d ret =%d", resp->status, ret);
+        qcom_km_ion_dealloc(&ihandle);
+        return -1;
+    } else {
+        UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
+        if (keydata.get() == NULL) {
+            ALOGE("could not allocate memory for key blob");
+            return -1;
+        }
+        unsigned char* p = keydata.get();
+        memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
+        *keyBlob = keydata.release();
+        *keyBlobLength = resp->key_blob_len;
+
+    }
+    qcom_km_ion_dealloc(&ihandle);
+    return 0;
+}
+
+static int qcom_km_sign_data(const keymaster_device_t* dev,
+        const void* params,
+        const uint8_t* keyBlob, const size_t keyBlobLength,
+        const uint8_t* data, const size_t dataLength,
+        uint8_t** signedData, size_t* signedDataLength)
+{
+    if (dev->context == NULL) {
+        ALOGE("qcom_km_sign_data: Context  == NULL");
+        return -1;
+    }
+    if (dataLength > KM_KEY_SIZE_MAX) {
+        ALOGE("Input data to be signed is too long %d bytes", dataLength);
+        return -1;
+    }
+    if (data == NULL) {
+        ALOGE("input data to sign == NULL");
+        return -1;
+    } else if (signedData == NULL || signedDataLength == NULL) {
+        ALOGE("Output signature buffer == NULL");
+        return -1;
+    }
+    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    } else if (sign_params->padding_type != PADDING_NONE) {
+        ALOGE("Cannot handle padding type %d", sign_params->padding_type);
+        return -1;
+    }
+
+    struct QSEECom_handle *handle = NULL;
+    keymaster_sign_data_cmd_t *send_cmd = NULL;
+    keymaster_sign_data_resp_t  *resp = NULL;
+    struct QSEECom_ion_fd_info  ion_fd_info;
+    struct qcom_km_ion_info_t ihandle;
+    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
+    int ret = 0;
+
+    handle = (struct QSEECom_handle *)(km_handle->qseecom);
+    ihandle.ion_fd = 0;
+    ihandle.ion_alloc_handle.handle = NULL;
+    if (qcom_km_ION_memalloc(&ihandle, dataLength) < 0) {
+        ALOGE("ION allocation  failed");
+        return -1;
+    }
+    memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
+
+    /* Populate the send data structure */
+    ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
+    ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
+         sizeof(qcom_km_key_blob_t) + sizeof(keymaster_rsa_sign_params_t);
+
+    send_cmd = (keymaster_sign_data_cmd_t *)handle->ion_sbuffer;
+    resp = (keymaster_sign_data_resp_t *)(handle->ion_sbuffer +
+                            QSEECOM_ALIGN(sizeof(keymaster_sign_data_cmd_t)));
+    send_cmd->cmd_id = KEYMASTER_SIGN_DATA ;
+    send_cmd->sign_param.digest_type = sign_params->digest_type;
+    send_cmd->sign_param.padding_type = sign_params->padding_type;
+    memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
+    memcpy((unsigned char *)ihandle.ion_sbuffer, data, dataLength);
+
+    send_cmd->data = (uint32_t)ihandle.ion_sbuffer;
+    send_cmd->dlen = dataLength;
+    resp->sig_len = KM_KEY_SIZE_MAX;
+    resp->status = KEYMASTER_FAILURE;
+
+    ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
+                               QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
+                               QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
+    if ( (ret < 0)  ||  (resp->status  < 0)) {
+        ALOGE("Sign data command failed resp->status = %d ret =%d", resp->status, ret);
+        qcom_km_ion_dealloc(&ihandle);
+        return -1;
+    } else {
+        UniquePtr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
+        if (signedDataPtr.get() == NULL) {
+            ALOGE("Sign data memory allocation failed");
+            qcom_km_ion_dealloc(&ihandle);
+            return -1;
+        }
+        unsigned char* p = signedDataPtr.get();
+        memcpy(p, (unsigned char *)(&resp->signed_data), resp->sig_len);
+
+        *signedDataLength = resp->sig_len;
+        *signedData = signedDataPtr.release();
+    }
+    qcom_km_ion_dealloc(&ihandle);
+    return 0;
+}
+
+static int qcom_km_verify_data(const keymaster_device_t* dev,
+        const void* params,
+        const uint8_t* keyBlob, const size_t keyBlobLength,
+        const uint8_t* signedData, const size_t signedDataLength,
+        const uint8_t* signature, const size_t signatureLength)
+{
+    if (dev->context == NULL) {
+        ALOGE("qcom_km_verify_data: Context  == NULL");
+        return -1;
+    }
+
+    if (signedData == NULL || signature == NULL) {
+        ALOGE("data or signature buffers == NULL");
+        return -1;
+    }
+
+    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    } else if (sign_params->padding_type != PADDING_NONE) {
+        ALOGE("Cannot handle padding type %d", sign_params->padding_type);
+        return -1;
+    } else if (signatureLength != signedDataLength) {
+        ALOGE("signed data length must be signature length");
+        return -1;
+    }
+
+    struct QSEECom_handle *handle = NULL;
+    keymaster_verify_data_cmd_t *send_cmd = NULL;
+    keymaster_verify_data_resp_t  *resp = NULL;
+
+    struct QSEECom_ion_fd_info  ion_fd_info;
+    struct qcom_km_ion_info_t ihandle;
+    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
+    int ret = 0;
+
+    handle = (struct QSEECom_handle *)(km_handle->qseecom);
+    ihandle.ion_fd = 0;
+    ihandle.ion_alloc_handle.handle = NULL;
+    if (qcom_km_ION_memalloc(&ihandle, signedDataLength + signatureLength) <0) {
+        ALOGE("ION allocation  failed");
+        return -1;
+    }
+    memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
+
+    /* Populate the send data structure */
+    ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
+    ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
+        sizeof(qcom_km_key_blob_t ) + sizeof(keymaster_rsa_sign_params_t);
+
+    send_cmd = (keymaster_verify_data_cmd_t *)handle->ion_sbuffer;
+    resp = (keymaster_verify_data_resp_t *)((char *)handle->ion_sbuffer +
+                               sizeof(keymaster_verify_data_cmd_t));
+    send_cmd->cmd_id = KEYMASTER_VERIFY_DATA ;
+    send_cmd->sign_param.digest_type = sign_params->digest_type;
+    send_cmd->sign_param.padding_type = sign_params->padding_type;
+    memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
+
+    send_cmd->signed_data = (uint32_t)ihandle.ion_sbuffer;
+    send_cmd->signed_dlen = signedDataLength;
+    memcpy((unsigned char *)ihandle.ion_sbuffer, signedData, signedDataLength);
+
+    send_cmd->signature = signedDataLength;
+    send_cmd->slen = signatureLength;
+    memcpy(((unsigned char *)ihandle.ion_sbuffer + signedDataLength),
+                                  signature, signatureLength);
+    resp->status = KEYMASTER_FAILURE;
+    ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
+                               QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
+                               QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
+
+    if ( (ret < 0)  ||  (resp->status  < 0)) {
+        ALOGE("Verify data command failed resp->status = %d ret =%d", resp->status, ret);
+        qcom_km_ion_dealloc(&ihandle);
+        return -1;
+    }
+    qcom_km_ion_dealloc(&ihandle);
+    return 0;
+}
+
+/* Close an opened OpenSSL instance */
+static int qcom_km_close(hw_device_t *dev)
+{
+    keymaster_device_t* km_dev = (keymaster_device_t *)dev;
+    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)km_dev->context;
+
+    if (km_handle->qseecom == NULL) {
+        ALOGE("Context  == NULL");
+        return -1;
+    }
+    (*km_handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&km_handle->qseecom);
+    free(km_dev->context);
+    free(dev);
+    return 0;
+}
+
+static int qcom_km_get_lib_sym(qcom_keymaster_handle_t* km_handle)
+{
+    km_handle->libhandle = dlopen("/system/lib/libQSEEComAPI.so", RTLD_NOW);
+    if (  km_handle->libhandle  ) {
+        *(void **)(&km_handle->QSEECom_start_app) =
+                               dlsym(km_handle->libhandle,"QSEECom_start_app");
+        if (km_handle->QSEECom_start_app == NULL) {
+               ALOGE("dlsym: Error Loading QSEECom_start_app");
+                   dlclose(km_handle->libhandle );
+                   km_handle->libhandle  = NULL;
+                   return -1;
+            }
+            *(void **)(&km_handle->QSEECom_shutdown_app) =
+                               dlsym(km_handle->libhandle,"QSEECom_shutdown_app");
+            if (km_handle->QSEECom_shutdown_app == NULL) {
+                   ALOGE("dlsym: Error Loading QSEECom_shutdown_app");
+                   dlclose(km_handle->libhandle );
+                   km_handle->libhandle  = NULL;
+                   return -1;
+             }
+            *(void **)(&km_handle->QSEECom_send_cmd) =
+                               dlsym(km_handle->libhandle,"QSEECom_send_cmd");
+            if (km_handle->QSEECom_send_cmd == NULL) {
+                   ALOGE("dlsym: Error Loading QSEECom_send_cmd");
+                   dlclose(km_handle->libhandle );
+                   km_handle->libhandle  = NULL;
+                   return -1;
+             }
+            *(void **)(&km_handle->QSEECom_send_modified_cmd) =
+                               dlsym(km_handle->libhandle,"QSEECom_send_modified_cmd");
+            if (km_handle->QSEECom_send_modified_cmd == NULL) {
+                   ALOGE("dlsym: Error Loading QSEECom_send_modified_cmd");
+                   dlclose(km_handle->libhandle );
+                   km_handle->libhandle  = NULL;
+                   return -1;
+             }
+    } else {
+        ALOGE("failed to load qseecom library");
+        return -1;
+    }
+    return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int qcom_km_open(const hw_module_t* module, const char* name,
+        hw_device_t** device)
+{
+    int ret = 0;
+    qcom_keymaster_handle_t* km_handle;
+    if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
+        return -EINVAL;
+
+    km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
+    if (km_handle == NULL) {
+        ALOGE("Memalloc for keymaster handle failed");
+        return -1;
+    }
+    km_handle->qseecom = NULL;
+    km_handle->libhandle = NULL;
+    ret = qcom_km_get_lib_sym(km_handle);
+    if (ret) {
+        free(km_handle);
+        return -1;
+    }
+    Unique_keymaster_device_t dev(new keymaster_device_t);
+    if (dev.get() == NULL){
+        free(km_handle);
+        return -ENOMEM;
+    }
+    dev->context = (void *)km_handle;
+    ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
+                         "/vendor/firmware/keymaster", "keymaster", 4096);
+    if (ret) {
+        ALOGE("Loading keymaster app failied");
+        free(km_handle);
+        return -1;
+    }
+    dev->common.tag = HARDWARE_DEVICE_TAG;
+    dev->common.version = 1;
+    dev->common.module = (struct hw_module_t*) module;
+    dev->common.close = qcom_km_close;
+    dev->flags = 0;
+
+    dev->generate_keypair = qcom_km_generate_keypair;
+    dev->import_keypair = qcom_km_import_keypair;
+    dev->get_keypair_public = qcom_km_get_keypair_public;
+    dev->delete_keypair = NULL;
+    dev->delete_all = NULL;
+    dev->sign_data = qcom_km_sign_data;
+    dev->verify_data = qcom_km_verify_data;
+
+    *device = reinterpret_cast<hw_device_t*>(dev.release());
+
+    return 0;
+}
+
+static struct hw_module_methods_t keystore_module_methods = {
+    open: qcom_km_open,
+};
+
+struct keystore_module HAL_MODULE_INFO_SYM
+__attribute__ ((visibility ("default"))) = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        version_major: 1,
+        version_minor: 0,
+        id: KEYSTORE_HARDWARE_MODULE_ID,
+        name: "Keymaster QCOM HAL",
+        author: "The Android Open Source Project",
+        methods: &keystore_module_methods,
+        dso: 0,
+        reserved: {},
+    },
+};
diff --git a/keymaster_qcom.h b/keymaster_qcom.h
new file mode 100644
index 0000000..14aa497
--- /dev/null
+++ b/keymaster_qcom.h
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (C) 2012 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you
+ *  may not use this file except in compliance with the License.  You may
+ *  obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied.  See the License for the specific language governing
+ *  permissions and limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_QCOM_KEYMASTER_H
+#define ANDROID_HARDWARE_QCOM_KEYMASTER_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/**
+ * The id of this module
+ */
+#define QCOM_KEYSTORE_KEYMASTER "qcom_keymaster"
+/**
+ * Operation result
+ */
+#define KEYMATER_SUCCESS  0
+#define KEYMASTER_FAILURE  -1
+
+/**
+ * The API level of this version of the header. The allows the implementing
+ * module to recognize which API level of the client it is dealing with in
+ * the case of pre-compiled binary clients.
+ */
+#define QCOM_KEYMASTER_API_VERSION 1
+
+#define KM_MAGIC_NUM     (0x4B4D4B42)    /* "KMKB" Key Master Key Blob in hex */
+#define KM_KEY_SIZE_MAX  (256)           /* 2048 bits */
+#define KM_IV_LENGTH     (16)            /* AES128 CBC IV */
+#define KM_HMAC_LENGTH   (32)            /* SHA2 will be used for HMAC  */
+
+struct  qcom_km_key_blob {
+  uint32_t magic_num;
+  uint32_t version_num;
+  uint8_t  modulus[KM_KEY_SIZE_MAX];
+  uint32_t modulus_size;
+  uint8_t  public_exponent[KM_KEY_SIZE_MAX];
+  uint32_t public_exponent_size;
+  uint8_t  iv[KM_IV_LENGTH];
+  uint8_t  encrypted_private_exponent[KM_KEY_SIZE_MAX];
+  uint32_t encrypted_private_exponent_size;
+  uint8_t  hmac[KM_HMAC_LENGTH];
+};
+typedef struct  qcom_km_key_blob qcom_km_key_blob_t;
+/**
+ * Commands supported
+ */
+enum  keymaster_cmd_t {
+    /*
+     * List the commands supportedin by the hardware.
+     */
+    KEYMASTER_GENERATE_KEYPAIR = 0x00000001,
+    KEYMASTER_IMPORT_KEYPAIR = 0x00000002,
+    KEYMASTER_SIGN_DATA = 0x00000003,
+    KEYMASTER_VERIFY_DATA = 0x00000004,
+};
+
+
+/**
+ * Command to Generate a public and private key. The key data returned
+ * (by secure app) is in shared buffer at offset of "key_blob" and is opaque
+ *
+ * cmd_id       : Command issue to secure app
+ * key_type     : Currently on RSA_TYPE is supported
+ * rsa_params   : Parameters needed to generate an RSA key
+ */
+ struct keymaster_gen_keypair_cmd {
+      keymaster_cmd_t               cmd_id;
+      keymaster_keypair_t           key_type;
+      keymaster_rsa_keygen_params_t rsa_params;
+};
+typedef struct keymaster_gen_keypair_cmd keymaster_gen_keypair_cmd_t;
+
+/**
+ * Response to Generate a public and private key. The key data returned
+ * (by secure app) is in shared buffer at offset of "key_blob" and is opaque
+ *
+ * cmd_id       : Command issue to secure app
+ * key_blob     : key blob data
+ * key_blob_len : Total length of key blob information
+ * status       : Result (success 0, or failure -1)
+ */
+struct keymaster_gen_keypair_resp {
+      keymaster_cmd_t     cmd_id;
+      qcom_km_key_blob_t  key_blob;
+      size_t              key_blob_len;
+      int32_t             status;
+};
+typedef struct keymaster_gen_keypair_resp keymaster_gen_keypair_resp_t;
+
+
+/**
+ * Command to import a public and private key pair. The imported keys
+ * will be in PKCS#8 format with DER encoding (Java standard). The key
+ * data returned (by secure app) is in shared buffer at offset of
+ * "key_blob" and is opaque
+ *
+ * cmd_id       : Command issue to secure app
+ * pkcs8_key    : Pointer to  pkcs8 formatted key information
+ * pkcs8_key_len: PKCS8 formatted key length
+ */
+struct keymaster_import_keypair_cmd {
+      keymaster_cmd_t cmd_id;
+      uint32_t        pkcs8_key;
+      size_t          pkcs8_key_len;
+};
+typedef struct keymaster_import_keypair_cmd keymaster_import_keypair_cmd_t;
+
+/**
+ * Response to import a public and private key. The key data returned
+ * (by secure app) is in shared buffer at offset of "key_blob" and is opaque
+ *
+ * cmd_id       : Command issue to secure app
+ * key_blob     : key blob data
+ * key_blob_len : Total length of key blob information
+ * status       : Result (success 0, or failure -1)
+ */
+struct keymaster_import_keypair_resp {
+      keymaster_cmd_t     cmd_id;
+      qcom_km_key_blob_t  key_blob;
+      size_t              key_blob_len;
+      int32_t             status;
+};
+typedef struct keymaster_import_keypair_resp keymaster_import_keypair_resp_t;
+
+/**
+ * Command to sign data using a key info generated before. This can use either
+ * an asymmetric key or a secret key.
+ * The signed data is returned (by secure app) at offset of data + dlen.
+ *
+ * cmd_id      : Command issue to secure app
+ * sign_param  :
+ * key_blob    : Key data information (in shared buffer)
+ * data        : Pointer to plain data buffer
+ * dlen        : Plain data length
+ */
+struct keymaster_sign_data_cmd {
+      keymaster_cmd_t               cmd_id;
+      keymaster_rsa_sign_params_t   sign_param;
+      qcom_km_key_blob_t            key_blob;
+      uint32_t                      data;
+      size_t                        dlen;
+};
+typedef struct keymaster_sign_data_cmd keymaster_sign_data_cmd_t;
+
+/**
+ * Response to sign data response
+ *
+ * cmd_id      : Command issue to secure app
+ * signed_data : signature
+ * sig_len     : Signed data length
+ * status      : Result (success 0, or failure -1)
+ */
+struct keymaster_sign_data_resp {
+      keymaster_cmd_t     cmd_id;
+      uint8_t             signed_data[KM_KEY_SIZE_MAX];
+      size_t              sig_len;
+      int32_t             status;
+};
+
+typedef struct keymaster_sign_data_resp keymaster_sign_data_resp_t;
+
+/**
+ * Command to verify data using a key info generated before. This can use either
+ * an asymmetric key or a secret key.
+ *
+ * cmd_id      : Command issue to secure app
+ * sign_param  :
+ * key_blob    : Key data information (in shared buffer)
+ * key_blob_len: Total key length
+ * signed_data : Pointer to signed data buffer
+ * signed_dlen : Signed data length
+ * signature   : Offset to the signature data buffer (from signed data buffer)
+ * slen        : Signature data length
+ */
+struct keymaster_verify_data_cmd {
+      keymaster_cmd_t cmd_id;
+      keymaster_rsa_sign_params_t   sign_param;
+      qcom_km_key_blob_t            key_blob;
+      uint32_t                      signed_data;
+      size_t                        signed_dlen;
+      uint32_t                      signature;
+      size_t                        slen;
+};
+typedef struct keymaster_verify_data_cmd keymaster_verify_data_cmd_t;
+/**
+ * Response to verify data
+ *
+ * cmd_id      : Command issue to secure app
+ * status      : Result (success 0, or failure -1)
+ */
+struct  keymaster_verify_data_resp {
+      keymaster_cmd_t     cmd_id;
+      int32_t             status;
+};
+typedef struct keymaster_verify_data_resp keymaster_verify_data_resp_t;
+
+__END_DECLS
+
+#endif  // ANDROID_HARDWARE_QCOM_KEYMASTER_H