Enable keymaster3

As required by vts.

It mimics trusty keymaster hal on the guest side.
i.e., to pass everything to host through pipe;
host will do all the real work.

If the host side does not support keymaster3,
it will fallback to software keymaster in the guest.
(bootable, but won't pass all the vts)

Test: Boot emulator image to home screen with KeymasterService3
working property in the guest. In addition, pass all
the keymaster VTS test

vts-tradefed run vts -m VtsHalKeymasterV3_0Target

BUG: 62137383
(cherry picked from commit 264d7b77eb246b7db443fc994866afd3ef367ab5)

Change-Id: Iff3e61326be1f0bbfc5410f541e2b165410cd553
Merged-In: Ia7faf54e6eeb7abb5bc264049dbc36a15f85fe18
diff --git a/keymaster/Android.mk b/keymaster/Android.mk
index 600e32d..7203c47 100644
--- a/keymaster/Android.mk
+++ b/keymaster/Android.mk
@@ -1,47 +1,19 @@
-# Copyright (C) 2017 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_VENDOR_MODULE := true
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_MODULE := libgoldfishkeymaster
-LOCAL_SRC_FILES := keymaster_openssl.c
-LOCAL_C_INCLUDES := system/security/keystore \
-                    $(LOCAL_PATH)/../include
-LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder
-LOCAL_MODULE_TAGS := optional
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_SHARED_LIBRARY)
-
 # Emulated keymaster - ranchu build##########################################
-
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
-LOCAL_VENDOR_MODULE := true
 ifeq ($(USE_32_BIT_KEYSTORE), true)
 LOCAL_MULTILIB := 32
 endif
 LOCAL_MODULE := keystore.ranchu
+LOCAL_VENDOR_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := module.cpp
-LOCAL_C_INCLUDES := system/security/keystore
+LOCAL_SRC_FILES := keymaster_module.cpp \
+                   trusty_keymaster_ipc.cpp \
+                   trusty_keymaster_device.cpp
+
+LOCAL_C_INCLUDES := system/security/keystore \
+                    $(LOCAL_PATH)/../include
 LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder libgoldfishkeymaster
+LOCAL_SHARED_LIBRARIES := libcrypto liblog libsoftkeymasterdevice libkeymaster_messages libcutils
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_SHARED_LIBRARY)
diff --git a/keymaster/keymaster_ipc.h b/keymaster/keymaster_ipc.h
new file mode 100644
index 0000000..b38eb05
--- /dev/null
+++ b/keymaster/keymaster_ipc.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+// clang-format off
+
+#define KEYMASTER_PORT "com.android.trusty.keymaster"
+#define KEYMASTER_MAX_BUFFER_LENGTH 4096
+
+// Commands
+enum keymaster_command : uint32_t {
+    KEYMASTER_RESP_BIT              = 1,
+    KEYMASTER_REQ_SHIFT             = 1,
+
+    KM_GENERATE_KEY                 = (0 << KEYMASTER_REQ_SHIFT),
+    KM_BEGIN_OPERATION              = (1 << KEYMASTER_REQ_SHIFT),
+    KM_UPDATE_OPERATION             = (2 << KEYMASTER_REQ_SHIFT),
+    KM_FINISH_OPERATION             = (3 << KEYMASTER_REQ_SHIFT),
+    KM_ABORT_OPERATION              = (4 << KEYMASTER_REQ_SHIFT),
+    KM_IMPORT_KEY                   = (5 << KEYMASTER_REQ_SHIFT),
+    KM_EXPORT_KEY                   = (6 << KEYMASTER_REQ_SHIFT),
+    KM_GET_VERSION                  = (7 << KEYMASTER_REQ_SHIFT),
+    KM_ADD_RNG_ENTROPY              = (8 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_ALGORITHMS     = (9 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_BLOCK_MODES    = (10 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_PADDING_MODES  = (11 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_DIGESTS        = (12 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_IMPORT_FORMATS = (13 << KEYMASTER_REQ_SHIFT),
+    KM_GET_SUPPORTED_EXPORT_FORMATS = (14 << KEYMASTER_REQ_SHIFT),
+    KM_GET_KEY_CHARACTERISTICS      = (15 << KEYMASTER_REQ_SHIFT),
+    KM_ATTEST_KEY                   = (16 << KEYMASTER_REQ_SHIFT),
+    KM_UPGRADE_KEY                  = (17 << KEYMASTER_REQ_SHIFT),
+    KM_CONFIGURE                    = (18 << KEYMASTER_REQ_SHIFT),
+};
+
+#ifdef __ANDROID__
+
+/**
+ * keymaster_message - Serial header for communicating with KM server
+ * @cmd: the command, one of keymaster_command.
+ * @payload: start of the serialized command specific payload
+ */
+struct keymaster_message {
+    uint32_t cmd;
+    uint8_t payload[0];
+};
+
+#endif
diff --git a/keymaster/keymaster_module.cpp b/keymaster/keymaster_module.cpp
new file mode 100644
index 0000000..66c468e
--- /dev/null
+++ b/keymaster/keymaster_module.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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 <hardware/hardware.h>
+#include <hardware/keymaster0.h>
+#include <keymaster/soft_keymaster_device.h>
+
+#include "trusty_keymaster_device.h"
+#include "trusty_keymaster_ipc.h"
+
+using keymaster::TrustyKeymasterDevice;
+
+/*
+ * Generic device handling
+ */
+static int trusty_keymaster_open(const hw_module_t* module, const char* name, hw_device_t** device) {
+    if (strcmp(name, KEYSTORE_KEYMASTER) != 0) {
+        return -EINVAL;
+    }
+
+    int rc = trusty_keymaster_connect();
+    if (rc < 0) {
+        *device = reinterpret_cast<hw_device_t*>((new keymaster::SoftKeymasterDevice())->keymaster2_device());
+        return 0;
+    }
+
+    TrustyKeymasterDevice* dev = new TrustyKeymasterDevice(module);
+    if (dev == NULL) {
+        return -ENOMEM;
+    }
+    *device = dev->hw_device();
+    // Do not delete dev; it will get cleaned up when the caller calls device->close(), and must
+    // exist until then.
+    return 0;
+}
+
+static struct hw_module_methods_t keystore_module_methods = {
+    .open = trusty_keymaster_open,
+};
+
+struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
+    .common =
+        {
+            .tag = HARDWARE_MODULE_TAG,
+            .module_api_version = KEYMASTER_MODULE_API_VERSION_2_0,
+            .hal_api_version = HARDWARE_HAL_API_VERSION,
+            .id = KEYSTORE_HARDWARE_MODULE_ID,
+            .name = "Trusty Keymaster HAL",
+            .author = "The Android Open Source Project",
+            .methods = &keystore_module_methods,
+            .dso = 0,
+            .reserved = {},
+        },
+};
diff --git a/keymaster/keymaster_openssl.c b/keymaster/keymaster_openssl.c
deleted file mode 100644
index 69c9572..0000000
--- a/keymaster/keymaster_openssl.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2017 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 <assert.h>
-#include <errno.h>
-#include <hardware/keymaster_common.h>
-#include <malloc.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <string.h>
-
-#define LOG_TAG "OpenSSLKeyMaster"
-#include <cutils/log.h>
-
-#ifdef DEBUG
-#   define D(...)   ALOGD(__VA_ARGS__)
-#else
-#   define D(...)   ((void)0)
-#endif
-
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-#include "qemud.h"
-
-#define KEYMASTER_SERVICE_NAME "KeymasterService"
-
-typedef struct qemu_keymaster0_device_t {
-    keymaster0_device_t device; // "inheritance", must be the first member
-    int qchanfd;
-    pthread_mutex_t lock;
-} qemu_keymaster0_device_t;
-
-enum {
-        GenerateKeypair = 0,
-        ImportKeypair,
-        GetKeypairPublic,
-        SignData,
-        VerifyData,
-};
-
-static int32_t unwrap_key_type(const uint8_t* key_blob) {
-    int32_t key_type = 0;
-    const uint8_t* p = key_blob;
-    size_t i;
-    for (i = 0; i < sizeof(key_type); i++) {
-        key_type = (key_type << 8) | *p++;
-    }
-    return key_type;
-}
-
-static int keymaster_fd_write(int fd, const void* buff, int len) {
-    int ret = WriteFully(fd, buff, len);
-    assert(ret);
-    return ret;
-}
-
-static int keymaster_fd_read(int fd, void* buff, int len) {
-    int ret = ReadFully(fd, buff, len);
-    assert(ret);
-    return ret;
-}
-
-static int EVP2EncoderType(int evpType) {
-    switch (evpType) {
-        case 6: // RSA
-            return TYPE_RSA;
-        case 408: // EC:
-            return TYPE_EC;
-        case 116: // DSA:
-            return TYPE_DSA;
-        default:
-            D("Unsupported evp key type %d", evpType);
-            return -1;
-    }
-}
-
-static int gen_param_length(int type, const void* params) {
-    switch (type) {
-        case TYPE_DSA: {
-            keymaster_dsa_keygen_params_t* dsa_params =
-                    (keymaster_dsa_keygen_params_t*)params;
-            return 4 + 4 + 4 + 4 + dsa_params->generator_len
-                    + dsa_params->prime_p_len
-                    + dsa_params->prime_q_len;
-        }
-        case TYPE_EC:
-            return 4;
-        case TYPE_RSA:
-            return 8 + 4;
-        default:
-            D("Unsupported key type %d", type);
-            return -1;
-    }
-}
-
-static int sign_param_length(int type) {
-    switch (type) {
-        case TYPE_DSA:
-            return sizeof(keymaster_digest_algorithm_t);
-            break;
-        case TYPE_EC:
-            return sizeof(keymaster_digest_algorithm_t);
-            break;
-        case TYPE_RSA:
-            return sizeof(keymaster_digest_algorithm_t)
-                    + sizeof(keymaster_rsa_padding_t);
-            break;
-        default:
-            D("Unsupported key type %d", type);
-            return -1;
-    }
-}
-
-static void write_gen_param(int fd,
-    const keymaster_keypair_t type,
-    const void* key_params) {
-    switch (type) {
-        case TYPE_DSA: {
-            keymaster_dsa_keygen_params_t* dsa_params =
-                (keymaster_dsa_keygen_params_t*)key_params;
-
-            keymaster_fd_write(fd, (void*)&dsa_params->key_size,
-                sizeof(dsa_params->key_size));
-
-            keymaster_fd_write(fd, (void*)&dsa_params->generator_len,
-                sizeof(dsa_params->generator_len));
-            keymaster_fd_write(fd, (void*)&dsa_params->prime_p_len,
-                sizeof(dsa_params->prime_p_len));
-            keymaster_fd_write(fd, (void*)&dsa_params->prime_q_len,
-                sizeof(dsa_params->prime_q_len));
-
-            keymaster_fd_write(fd, (void*)dsa_params->generator,
-                dsa_params->generator_len);
-            keymaster_fd_write(fd, (void*)dsa_params->prime_p,
-                dsa_params->prime_p_len);
-            keymaster_fd_write(fd, (void*)dsa_params->prime_q,
-                dsa_params->prime_q_len);
-            break;
-        }
-        case TYPE_EC: {
-            keymaster_ec_keygen_params_t* ec_params =
-                (keymaster_ec_keygen_params_t*)key_params;
-            keymaster_fd_write(fd, (void*)&ec_params->field_size,
-                sizeof(ec_params->field_size));
-            break;
-        }
-        case TYPE_RSA: {
-            keymaster_rsa_keygen_params_t* rsa_params =
-                (keymaster_rsa_keygen_params_t*)key_params;
-            keymaster_fd_write(fd, (void*)&rsa_params->modulus_size,
-                sizeof(rsa_params->modulus_size));
-            keymaster_fd_write(fd, (void*)&rsa_params->public_exponent,
-                sizeof(rsa_params->public_exponent));
-            break;
-        }
-        default:
-            D("Unsupported key type %d", type);
-            return;
-    }
-}
-
-static void write_sign_param(int fd,
-    const keymaster_keypair_t type,
-    const void* key_params) {
-    switch (type) {
-        case TYPE_DSA: {
-            keymaster_dsa_sign_params_t* dsa_params =
-                (keymaster_dsa_sign_params_t*)key_params;
-            keymaster_fd_write(fd, (void*)&dsa_params->digest_type,
-                sizeof(dsa_params->digest_type));
-            break;
-        }
-        case TYPE_EC: {
-            keymaster_ec_sign_params_t* ec_params =
-                (keymaster_ec_sign_params_t*)key_params;
-            keymaster_fd_write(fd, (void*)&ec_params->digest_type,
-                sizeof(ec_params->digest_type));
-            break;
-        }
-        case TYPE_RSA: {
-            keymaster_rsa_sign_params_t* rsa_params =
-                (keymaster_rsa_sign_params_t*)key_params;
-            keymaster_fd_write(fd, (void*)&rsa_params->digest_type,
-                sizeof(rsa_params->digest_type));
-            keymaster_fd_write(fd, (void*)&rsa_params->padding_type,
-                sizeof(rsa_params->padding_type));
-            break;
-        }
-        default:
-            D("Unsupported key type %d", type);
-            return;
-    }
-}
-
-static int openssl_generate_keypair(const keymaster0_device_t* device,
-        const keymaster_keypair_t key_type, const void* key_params,
-        uint8_t** key_blob, size_t* key_blob_length) {
-    D("generate keypair");
-    if (key_params == NULL) {
-        ALOGE("key_params == null");
-        return -1;
-    }
-    const uint32_t cmd = GenerateKeypair;
-    int32_t _key_type = (int)key_type;
-    int32_t key_params_len = gen_param_length(key_type, key_params);
-    if (key_params_len < 0) {
-        return -1;
-    }
-    qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
-    pthread_mutex_lock(&qemu_dev->lock);
-    // send
-    const uint64_t cmdLen = sizeof(cmd) + sizeof(_key_type) + sizeof(key_params_len)
-            + key_params_len;
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_type, sizeof(_key_type));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&key_params_len, sizeof(key_params_len));
-    write_gen_param(qemu_dev->qchanfd, key_type, key_params);
-
-    // receive
-    uint32_t _key_blob_len = 0;
-    int32_t ret;
-    keymaster_fd_read(qemu_dev->qchanfd, &_key_blob_len, sizeof(_key_blob_len));
-    *key_blob_length = _key_blob_len;
-    if (_key_blob_len) {
-        *key_blob = malloc(_key_blob_len);
-        keymaster_fd_read(qemu_dev->qchanfd, *key_blob, _key_blob_len);
-    }
-    keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
-
-    pthread_mutex_unlock(&qemu_dev->lock);
-    return ret;
-}
-
-static int openssl_import_keypair(const keymaster0_device_t* device,
-                                                                  const uint8_t* key,
-                                                                  const size_t key_length,
-                                                                  uint8_t** key_blob,
-                                                                  size_t* key_blob_length) {
-    D("import keypair");
-    if (key == NULL) {
-        ALOGW("input key == NULL");
-        return -1;
-    } else if (key_blob == NULL || key_blob_length == NULL) {
-        ALOGW("output key blob or length == NULL");
-        return -1;
-    }
-
-    const uint32_t cmd = ImportKeypair;
-    qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
-    pthread_mutex_lock(&qemu_dev->lock);
-    // send
-    const uint32_t _key_length = (uint32_t)key_length;
-    const uint64_t cmdLen = sizeof(cmd) + sizeof(_key_length) + _key_length;
-
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_length, sizeof(_key_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)key, key_length);
-
-    // receive
-    uint32_t _key_blob_len = 0;
-    int32_t ret;
-    keymaster_fd_read(qemu_dev->qchanfd, &_key_blob_len, sizeof(_key_blob_len));
-    *key_blob_length = _key_blob_len;
-    *key_blob = malloc(_key_blob_len);
-    keymaster_fd_read(qemu_dev->qchanfd, *key_blob, _key_blob_len);
-    keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
-
-    pthread_mutex_unlock(&qemu_dev->lock);
-    return ret;
-}
-
-static int openssl_get_keypair_public(const keymaster0_device_t* device,
-        const uint8_t* key_blob, const size_t key_blob_length,
-        uint8_t** x509_data, size_t* x509_data_length) {
-    D("get keypair public");
-    if (x509_data == NULL || x509_data_length == NULL) {
-        ALOGW("output public key buffer == NULL");
-        return -1;
-    }
-
-    const uint32_t cmd = GetKeypairPublic;
-    qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
-    pthread_mutex_lock(&qemu_dev->lock);
-    // send
-    const uint32_t _key_blob_length = (uint32_t)key_blob_length;
-    const uint64_t cmdLen = sizeof(cmd) + sizeof(_key_blob_length) +
-                            _key_blob_length;
-
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_blob_length, sizeof(_key_blob_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)key_blob, _key_blob_length);
-
-    // receive
-    uint32_t _x509_data_length = 0;
-    int32_t ret;
-    keymaster_fd_read(qemu_dev->qchanfd, &_x509_data_length,
-            sizeof(_x509_data_length));
-    *x509_data_length = _x509_data_length;
-    if (_x509_data_length) {
-        *x509_data = malloc(_x509_data_length);
-        keymaster_fd_read(qemu_dev->qchanfd, *x509_data, _x509_data_length);
-    } else {
-        *x509_data = NULL;
-    }
-    keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
-
-    pthread_mutex_unlock(&qemu_dev->lock);
-    return ret;
-}
-
-static int openssl_sign_data(const keymaster0_device_t* device, const void* params,
-        const uint8_t* key_blob,  const size_t key_blob_length,
-        const uint8_t* data, const size_t data_length,
-        uint8_t** signed_data, size_t* signed_data_length) {
-    D("sign data");
-    if (signed_data == NULL || signed_data_length == NULL) {
-        ALOGW("output signature buffer == NULL");
-        return -1;
-    }
-
-    int32_t key_type = EVP2EncoderType(unwrap_key_type(key_blob));
-    int32_t params_len = sign_param_length(key_type);
-    if (params_len < 0) {
-        return -1;
-    }
-
-    const uint32_t cmd = SignData;
-    qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
-    pthread_mutex_lock(&qemu_dev->lock);
-    // send
-    const uint32_t _key_blob_length = (uint32_t)key_blob_length;
-    const uint32_t _data_length = (uint32_t)data_length;
-    const uint64_t cmdLen = sizeof(cmd) + sizeof(key_type) + sizeof(params_len) + params_len +
-                            sizeof(_key_blob_length) + _key_blob_length +
-                            sizeof(_data_length) + _data_length;
-
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&key_type, sizeof(key_type));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&params_len, sizeof(params_len));
-    write_sign_param(qemu_dev->qchanfd, key_type, params);
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_blob_length, sizeof(_key_blob_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)key_blob, _key_blob_length);
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_data_length, sizeof(_data_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)data, _data_length);
-
-    // receive
-    uint32_t _signed_data_length = 0;
-    int32_t ret;
-    keymaster_fd_read(qemu_dev->qchanfd, &_signed_data_length,
-            sizeof(_signed_data_length));
-    *signed_data_length = _signed_data_length;
-    if (_signed_data_length) {
-        *signed_data = malloc(_signed_data_length);
-        keymaster_fd_read(qemu_dev->qchanfd, *signed_data, _signed_data_length);
-    }
-    keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
-
-    pthread_mutex_unlock(&qemu_dev->lock);
-    return ret;
-}
-
-static int openssl_verify_data(const keymaster0_device_t* device, const void* params,
-        const uint8_t* key_blob, const size_t key_blob_length,
-        const uint8_t* signed_data, const size_t signed_data_length,
-        const uint8_t* signature, const size_t signature_length) {
-    D("verify data");
-    if (signed_data == NULL || signature == NULL) {
-        ALOGW("data or signature buffers == NULL");
-        return -1;
-    }
-
-    int32_t key_type = EVP2EncoderType(unwrap_key_type(key_blob));
-    int32_t params_len = sign_param_length(key_type);
-    if (params_len < 0) {
-        return -1;
-    }
-
-    const uint32_t cmd = VerifyData;
-    qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
-    pthread_mutex_lock(&qemu_dev->lock);
-    // send
-    const uint32_t _key_blob_length = (uint32_t)key_blob_length;
-    const uint32_t _signed_data_length = (uint32_t)signed_data_length;
-    const uint32_t _signature_length = (uint32_t)signature_length;
-    const uint64_t cmdLen = sizeof(cmd) + sizeof(key_type) + sizeof(params_len) + params_len +
-                            sizeof(_key_blob_length) + _key_blob_length +
-                            sizeof(_signed_data_length) + _signed_data_length +
-                            sizeof(_signature_length) + _signature_length;
-
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&key_type, sizeof(key_type));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&params_len, sizeof(params_len));
-    write_sign_param(qemu_dev->qchanfd, key_type, params);
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_blob_length, sizeof(_key_blob_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)key_blob, _key_blob_length);
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_signed_data_length, sizeof(_signed_data_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)signed_data, _signed_data_length);
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)&_signature_length, sizeof(_signature_length));
-    keymaster_fd_write(qemu_dev->qchanfd, (void*)signature, _signature_length);
-
-    // receive
-    int32_t ret;
-    keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
-
-    pthread_mutex_unlock(&qemu_dev->lock);
-    return ret;
-}
-
-/* Close an opened OpenSSL instance */
-static int openssl_close(hw_device_t* dev) {
-    D("close device");
-    qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)dev;
-    pthread_mutex_destroy(&qemu_dev->lock);
-    close(qemu_dev->qchanfd);
-    free(qemu_dev);
-    return 0;
-}
-
-/*
- * Generic device handling
- */
-static int openssl_open(const hw_module_t* module, const char* name,
-                        hw_device_t** device) {
-    D("open device");
-    if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
-        return -EINVAL;
-
-    qemu_keymaster0_device_t* qemu_dev = calloc(1, sizeof(qemu_keymaster0_device_t));
-    if (qemu_dev == NULL)
-        return -ENOMEM;
-    keymaster0_device_t* dev = (keymaster0_device_t*)qemu_dev;
-
-    dev->common.tag = HARDWARE_DEVICE_TAG;
-    dev->common.version = 1;
-    dev->common.module = (struct hw_module_t*)module;
-    dev->common.close = openssl_close;
-
-    dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_DSA |
-                 KEYMASTER_SUPPORTS_EC;
-
-    dev->generate_keypair = openssl_generate_keypair;
-    dev->import_keypair = openssl_import_keypair;
-    dev->get_keypair_public = openssl_get_keypair_public;
-    dev->delete_keypair = NULL;
-    dev->delete_all = NULL;
-    dev->sign_data = openssl_sign_data;
-    dev->verify_data = openssl_verify_data;
-
-    // set up the pipe
-    qemu_dev->qchanfd = qemu_pipe_open(KEYMASTER_SERVICE_NAME);
-    if (qemu_dev->qchanfd < 0) {
-        ALOGE("keymaster: failed to get host connection while opening %s\n", name);
-        free(qemu_dev);
-        return -EIO;
-    }
-    pthread_mutex_init(&qemu_dev->lock, NULL);
-
-    *device = &dev->common;
-
-    return 0;
-}
-
-static struct hw_module_methods_t keystore_module_methods = {
-    .open = openssl_open,
-};
-
-struct keystore_module goldfishkeymaster_module __attribute__((visibility("default"))) = {
-    .common =
-        {
-         .tag = HARDWARE_MODULE_TAG,
-         .module_api_version = KEYMASTER_MODULE_API_VERSION_0_2,
-         .hal_api_version = HARDWARE_HAL_API_VERSION,
-         .id = KEYSTORE_HARDWARE_MODULE_ID,
-         .name = "Keymaster OpenSSL HAL",
-         .author = "The Android Open Source Project",
-         .methods = &keystore_module_methods,
-         .dso = 0,
-         .reserved = {},
-        },
-};
diff --git a/keymaster/module.cpp b/keymaster/module.cpp
deleted file mode 100644
index 97a15cc..0000000
--- a/keymaster/module.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2017 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 <keystore/keystore.h>
-
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-extern struct keystore_module goldfishkeymaster_module;
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = goldfishkeymaster_module;
diff --git a/keymaster/trusty_keymaster_device.cpp b/keymaster/trusty_keymaster_device.cpp
new file mode 100644
index 0000000..2afb1a9
--- /dev/null
+++ b/keymaster/trusty_keymaster_device.cpp
@@ -0,0 +1,792 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TrustyKeymaster"
+
+#include <assert.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <algorithm>
+#include <type_traits>
+
+#include <hardware/keymaster2.h>
+#include <keymaster/authorization_set.h>
+#include <log/log.h>
+
+#include "keymaster_ipc.h"
+#include "trusty_keymaster_device.h"
+#include "trusty_keymaster_ipc.h"
+
+#define MY_PAGE_SIZE (PAGE_SIZE * 128)
+const uint32_t RECV_BUF_SIZE = MY_PAGE_SIZE;
+const uint32_t SEND_BUF_SIZE = (MY_PAGE_SIZE - sizeof(struct keymaster_message) - 16 /* tipc header */);
+
+const size_t kMaximumAttestationChallengeLength = 128;
+const size_t kMaximumFinishInputLength = 2048 * 1024;
+
+namespace keymaster {
+
+static keymaster_error_t translate_error(int err) {
+    switch (err) {
+        case 0:
+            return KM_ERROR_OK;
+        case -EPERM:
+        case -EACCES:
+            return KM_ERROR_SECURE_HW_ACCESS_DENIED;
+
+        case -ECANCELED:
+            return KM_ERROR_OPERATION_CANCELLED;
+
+        case -ENODEV:
+            return KM_ERROR_UNIMPLEMENTED;
+
+        case -ENOMEM:
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+        case -EBUSY:
+            return KM_ERROR_SECURE_HW_BUSY;
+
+        case -EIO:
+            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+
+        case -EOVERFLOW:
+            return KM_ERROR_INVALID_INPUT_LENGTH;
+
+        default:
+            return KM_ERROR_UNKNOWN_ERROR;
+    }
+}
+
+TrustyKeymasterDevice::TrustyKeymasterDevice(const hw_module_t* module) {
+    static_assert(std::is_standard_layout<TrustyKeymasterDevice>::value,
+                  "TrustyKeymasterDevice must be standard layout");
+    static_assert(offsetof(TrustyKeymasterDevice, device_) == 0,
+                  "device_ must be the first member of TrustyKeymasterDevice");
+    static_assert(offsetof(TrustyKeymasterDevice, device_.common) == 0,
+                  "common must be the first member of keymaster2_device");
+
+    ALOGI("Creating device");
+    ALOGD("Device address: %p", this);
+
+    device_ = {};
+
+    device_.common.tag = HARDWARE_DEVICE_TAG;
+    device_.common.version = 1;
+    device_.common.module = const_cast<hw_module_t*>(module);
+    device_.common.close = close_device;
+
+    device_.flags = KEYMASTER_SUPPORTS_EC | KEYMASTER_BLOBS_ARE_STANDALONE ;
+
+    device_.configure = configure;
+    device_.add_rng_entropy = add_rng_entropy;
+    device_.generate_key = generate_key;
+    device_.get_key_characteristics = get_key_characteristics;
+    device_.import_key = import_key;
+    device_.export_key = export_key;
+    device_.attest_key = attest_key;
+    device_.upgrade_key = upgrade_key;
+    device_.delete_key = nullptr;
+    device_.delete_all_keys = nullptr;
+    device_.begin = begin;
+    device_.update = update;
+    device_.finish = finish;
+    device_.abort = abort;
+
+    GetVersionRequest version_request;
+    GetVersionResponse version_response;
+    error_ = Send(KM_GET_VERSION, version_request, &version_response);
+    if (error_ == KM_ERROR_INVALID_ARGUMENT || error_ == KM_ERROR_UNIMPLEMENTED) {
+        ALOGE("\"Bad parameters\" error on GetVersion call.  Version 0 is not supported.");
+        error_ = KM_ERROR_VERSION_MISMATCH;
+        return;
+    }
+    message_version_ = MessageVersion(version_response.major_ver, version_response.minor_ver,
+                                      version_response.subminor_ver);
+    if (message_version_ < 0) {
+        // Can't translate version?  Keymaster implementation must be newer.
+        ALOGE("Keymaster version %d.%d.%d not supported.", version_response.major_ver,
+              version_response.minor_ver, version_response.subminor_ver);
+        error_ = KM_ERROR_VERSION_MISMATCH;
+    }
+}
+
+TrustyKeymasterDevice::~TrustyKeymasterDevice() {
+    trusty_keymaster_disconnect();
+}
+
+namespace {
+
+// Allocates a new buffer with malloc and copies the contents of |buffer| to it. Caller takes
+// ownership of the returned buffer.
+uint8_t* DuplicateBuffer(const uint8_t* buffer, size_t size) {
+    uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(size));
+    if (tmp) {
+        memcpy(tmp, buffer, size);
+    }
+    return tmp;
+}
+
+template <typename RequestType>
+void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
+                         RequestType* request) {
+    request->additional_params.Clear();
+    if (client_id) {
+        request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
+    }
+    if (app_data) {
+        request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
+    }
+}
+
+}  //  unnamed namespace
+
+keymaster_error_t TrustyKeymasterDevice::configure(const keymaster_key_param_set_t* params) {
+    ALOGD("Device received configure\n");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!params) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    AuthorizationSet params_copy(*params);
+    ConfigureRequest request;
+    if (!params_copy.GetTagValue(TAG_OS_VERSION, &request.os_version) ||
+        !params_copy.GetTagValue(TAG_OS_PATCHLEVEL, &request.os_patchlevel)) {
+        ALOGD("Configuration parameters must contain OS version and patch level");
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+
+    ConfigureResponse response;
+    keymaster_error_t err = Send(KM_CONFIGURE, request, &response);
+    return err;
+}
+
+keymaster_error_t TrustyKeymasterDevice::add_rng_entropy(const uint8_t* data, size_t data_length) {
+    ALOGD("Device received add_rng_entropy");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+
+    AddEntropyRequest request;
+    request.random_data.Reinitialize(data, data_length);
+    AddEntropyResponse response;
+    return Send(KM_ADD_RNG_ENTROPY, request, &response);
+}
+
+keymaster_error_t TrustyKeymasterDevice::generate_key(
+    const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob,
+    keymaster_key_characteristics_t* characteristics) {
+    ALOGD("Device received generate_key");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!params) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!key_blob) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    GenerateKeyRequest request(message_version_);
+    request.key_description.Reinitialize(*params);
+    //request.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
+
+    GenerateKeyResponse response(message_version_);
+    keymaster_error_t err = Send(KM_GENERATE_KEY, request, &response);
+    if (err != KM_ERROR_OK) {
+        ALOGD("Device generate_key return error code %d", err);
+        return err;
+    }
+
+    key_blob->key_material_size = response.key_blob.key_material_size;
+    key_blob->key_material =
+        DuplicateBuffer(response.key_blob.key_material, response.key_blob.key_material_size);
+    if (!key_blob->key_material) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+
+    if (characteristics) {
+        response.enforced.CopyToParamSet(&characteristics->hw_enforced);
+        response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::get_key_characteristics(
+    const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id,
+    const keymaster_blob_t* app_data, keymaster_key_characteristics_t* characteristics) {
+    ALOGD("Device received get_key_characteristics");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!key_blob || !key_blob->key_material) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!characteristics) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    GetKeyCharacteristicsRequest request;
+    request.SetKeyMaterial(*key_blob);
+    AddClientAndAppData(client_id, app_data, &request);
+
+    GetKeyCharacteristicsResponse response;
+    keymaster_error_t err = Send(KM_GET_KEY_CHARACTERISTICS, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    response.enforced.CopyToParamSet(&characteristics->hw_enforced);
+    response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::import_key(
+    const keymaster_key_param_set_t* params, keymaster_key_format_t key_format,
+    const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob,
+    keymaster_key_characteristics_t* characteristics) {
+    ALOGD("Device received import_key");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!params || !key_data) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!key_blob) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    ImportKeyRequest request(message_version_);
+    request.key_description.Reinitialize(*params);
+    //request.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
+
+    request.key_format = key_format;
+    request.SetKeyMaterial(key_data->data, key_data->data_length);
+
+    ImportKeyResponse response(message_version_);
+    keymaster_error_t err = Send(KM_IMPORT_KEY, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    key_blob->key_material_size = response.key_blob.key_material_size;
+    key_blob->key_material =
+        DuplicateBuffer(response.key_blob.key_material, response.key_blob.key_material_size);
+    if (!key_blob->key_material) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+
+    if (characteristics) {
+        response.enforced.CopyToParamSet(&characteristics->hw_enforced);
+        response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::export_key(keymaster_key_format_t export_format,
+                                                    const keymaster_key_blob_t* key_to_export,
+                                                    const keymaster_blob_t* client_id,
+                                                    const keymaster_blob_t* app_data,
+                                                    keymaster_blob_t* export_data) {
+    ALOGD("Device received export_key");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!key_to_export || !key_to_export->key_material) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!export_data) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    export_data->data = nullptr;
+    export_data->data_length = 0;
+
+    ExportKeyRequest request(message_version_);
+    request.key_format = export_format;
+    request.SetKeyMaterial(*key_to_export);
+    AddClientAndAppData(client_id, app_data, &request);
+
+    ExportKeyResponse response(message_version_);
+    keymaster_error_t err = Send(KM_EXPORT_KEY, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    export_data->data_length = response.key_data_length;
+    export_data->data = DuplicateBuffer(response.key_data, response.key_data_length);
+    if (!export_data->data) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::attest_key(const keymaster_key_blob_t* key_to_attest,
+                                                    const keymaster_key_param_set_t* attest_params,
+                                                    keymaster_cert_chain_t* cert_chain) {
+    ALOGD("Device received attest_key");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!key_to_attest || !attest_params) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!cert_chain) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    cert_chain->entry_count = 0;
+    cert_chain->entries = nullptr;
+
+    AttestKeyRequest request;
+    request.SetKeyMaterial(*key_to_attest);
+    request.attest_params.Reinitialize(*attest_params);
+
+    keymaster_blob_t attestation_challenge = {};
+    request.attest_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge);
+    if (attestation_challenge.data_length > kMaximumAttestationChallengeLength) {
+        ALOGE("%zu-byte attestation challenge; only %zu bytes allowed",
+              attestation_challenge.data_length, kMaximumAttestationChallengeLength);
+        return KM_ERROR_INVALID_INPUT_LENGTH;
+    }
+
+    AttestKeyResponse response;
+    keymaster_error_t err = Send(KM_ATTEST_KEY, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    // Allocate and clear storage for cert_chain.
+    keymaster_cert_chain_t& rsp_chain = response.certificate_chain;
+    cert_chain->entries = reinterpret_cast<keymaster_blob_t*>(
+        malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries)));
+    if (!cert_chain->entries) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+    cert_chain->entry_count = rsp_chain.entry_count;
+    for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count)) {
+        entry = {};
+    }
+
+    // Copy cert_chain contents
+    size_t i = 0;
+    for (keymaster_blob_t& entry : array_range(rsp_chain.entries, rsp_chain.entry_count)) {
+        cert_chain->entries[i].data = DuplicateBuffer(entry.data, entry.data_length);
+        if (!cert_chain->entries[i].data) {
+            keymaster_free_cert_chain(cert_chain);
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+        cert_chain->entries[i].data_length = entry.data_length;
+        ++i;
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::upgrade_key(const keymaster_key_blob_t* key_to_upgrade,
+                                                     const keymaster_key_param_set_t* upgrade_params,
+                                                     keymaster_key_blob_t* upgraded_key) {
+    ALOGD("Device received upgrade_key");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!key_to_upgrade || !upgrade_params) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!upgraded_key) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    UpgradeKeyRequest request;
+    request.SetKeyMaterial(*key_to_upgrade);
+    request.upgrade_params.Reinitialize(*upgrade_params);
+
+    UpgradeKeyResponse response;
+    keymaster_error_t err = Send(KM_UPGRADE_KEY, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    upgraded_key->key_material_size = response.upgraded_key.key_material_size;
+    upgraded_key->key_material = DuplicateBuffer(response.upgraded_key.key_material,
+                                                 response.upgraded_key.key_material_size);
+    if (!upgraded_key->key_material) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::begin(keymaster_purpose_t purpose,
+                                               const keymaster_key_blob_t* key,
+                                               const keymaster_key_param_set_t* in_params,
+                                               keymaster_key_param_set_t* out_params,
+                                               keymaster_operation_handle_t* operation_handle) {
+    ALOGD("Device received begin");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!key || !key->key_material) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!operation_handle) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    if (out_params) {
+        *out_params = {};
+    }
+
+    BeginOperationRequest request;
+    request.purpose = purpose;
+    request.SetKeyMaterial(*key);
+    request.additional_params.Reinitialize(*in_params);
+
+    BeginOperationResponse response;
+    keymaster_error_t err = Send(KM_BEGIN_OPERATION, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    if (response.output_params.size() > 0) {
+        if (out_params) {
+            response.output_params.CopyToParamSet(out_params);
+        } else {
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+        }
+    }
+    *operation_handle = response.op_handle;
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::update(keymaster_operation_handle_t operation_handle,
+                                                const keymaster_key_param_set_t* in_params,
+                                                const keymaster_blob_t* input,
+                                                size_t* input_consumed,
+                                                keymaster_key_param_set_t* out_params,
+                                                keymaster_blob_t* output) {
+    ALOGD("Device received update");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (!input) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    if (!input_consumed) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    if (out_params) {
+        *out_params = {};
+    }
+    if (output) {
+        *output = {};
+    }
+
+    UpdateOperationRequest request;
+    request.op_handle = operation_handle;
+    if (in_params) {
+        request.additional_params.Reinitialize(*in_params);
+    }
+    if (input && input->data_length > 0) {
+        size_t max_input_size = SEND_BUF_SIZE - request.SerializedSize();
+        request.input.Reinitialize(input->data, std::min(input->data_length, max_input_size));
+    }
+
+    UpdateOperationResponse response;
+    keymaster_error_t err = Send(KM_UPDATE_OPERATION, request, &response);
+    if (err != KM_ERROR_OK) {
+        return err;
+    }
+
+    if (response.output_params.size() > 0) {
+        if (out_params) {
+            response.output_params.CopyToParamSet(out_params);
+        } else {
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+        }
+    }
+    *input_consumed = response.input_consumed;
+    if (output) {
+        output->data_length = response.output.available_read();
+        output->data = DuplicateBuffer(response.output.peek_read(), output->data_length);
+        if (!output->data) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+    } else if (response.output.available_read() > 0) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::finish(keymaster_operation_handle_t operation_handle,
+                                                const keymaster_key_param_set_t* in_params,
+                                                const keymaster_blob_t* input,
+                                                const keymaster_blob_t* signature,
+                                                keymaster_key_param_set_t* out_params,
+                                                keymaster_blob_t* output) {
+    ALOGE("Device received finish");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+    if (input && input->data_length > kMaximumFinishInputLength) {
+    ALOGE("here %s at %d", __func__, __LINE__);
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (out_params) {
+        *out_params = {};
+    }
+    if (output) {
+        *output = {};
+    }
+
+    FinishOperationRequest request;
+    request.op_handle = operation_handle;
+    if (signature && signature->data && signature->data_length > 0) {
+        request.signature.Reinitialize(signature->data, signature->data_length);
+        ALOGE("here %s at %d signature length %d", __func__, __LINE__,
+                (int)(signature->data_length));
+    }
+    if (input && input->data && input->data_length) {
+        request.input.Reinitialize(input->data, input->data_length);
+        ALOGE("here %s at %d input data length %d", __func__, __LINE__,
+                (int)(input->data_length));
+    }
+    if (in_params) {
+        request.additional_params.Reinitialize(*in_params);
+    }
+
+    FinishOperationResponse response;
+    keymaster_error_t err = Send(KM_FINISH_OPERATION, request, &response);
+    if (err != KM_ERROR_OK) {
+    ALOGE("here %s at %d", __func__, __LINE__);
+        return err;
+    }
+
+    if (response.output_params.size() > 0) {
+        if (out_params) {
+            response.output_params.CopyToParamSet(out_params);
+        } else {
+    ALOGE("here %s at %d", __func__, __LINE__);
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+        }
+    }
+    if (output) {
+        output->data_length = response.output.available_read();
+        output->data = DuplicateBuffer(response.output.peek_read(), output->data_length);
+        if (!output->data) {
+            ALOGE("here %s at %d", __func__, __LINE__);
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        } else {
+            ALOGE("here %s at %d output data length %d", __func__, __LINE__,
+                    (int)(output->data_length));
+        }
+    } else if (response.output.available_read() > 0) {
+        ALOGE("here %s at %d", __func__, __LINE__);
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    ALOGE("OK here %s at %d", __func__, __LINE__);
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustyKeymasterDevice::abort(keymaster_operation_handle_t operation_handle) {
+    ALOGD("Device received abort");
+
+    if (error_ != KM_ERROR_OK) {
+        return error_;
+    }
+
+    AbortOperationRequest request;
+    request.op_handle = operation_handle;
+    AbortOperationResponse response;
+    return Send(KM_ABORT_OPERATION, request, &response);
+}
+
+hw_device_t* TrustyKeymasterDevice::hw_device() {
+    return &device_.common;
+}
+
+static inline TrustyKeymasterDevice* convert_device(const keymaster2_device_t* dev) {
+    return reinterpret_cast<TrustyKeymasterDevice*>(const_cast<keymaster2_device_t*>(dev));
+}
+
+/* static */
+int TrustyKeymasterDevice::close_device(hw_device_t* dev) {
+    delete reinterpret_cast<TrustyKeymasterDevice*>(dev);
+    return 0;
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::configure(const keymaster2_device_t* dev,
+                                                   const keymaster_key_param_set_t* params) {
+    return convert_device(dev)->configure(params);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::add_rng_entropy(const keymaster2_device_t* dev,
+                                                         const uint8_t* data, size_t data_length) {
+    return convert_device(dev)->add_rng_entropy(data, data_length);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::generate_key(
+    const keymaster2_device_t* dev, const keymaster_key_param_set_t* params,
+    keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) {
+    return convert_device(dev)->generate_key(params, key_blob, characteristics);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::get_key_characteristics(
+    const keymaster2_device_t* dev, const keymaster_key_blob_t* key_blob,
+    const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
+    keymaster_key_characteristics_t* characteristics) {
+    return convert_device(dev)->get_key_characteristics(key_blob, client_id, app_data,
+                                                        characteristics);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::import_key(
+    const keymaster2_device_t* dev, const keymaster_key_param_set_t* params,
+    keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
+    keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) {
+    return convert_device(dev)->import_key(params, key_format, key_data, key_blob, characteristics);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::export_key(const keymaster2_device_t* dev,
+                                                    keymaster_key_format_t export_format,
+                                                    const keymaster_key_blob_t* key_to_export,
+                                                    const keymaster_blob_t* client_id,
+                                                    const keymaster_blob_t* app_data,
+                                                    keymaster_blob_t* export_data) {
+    return convert_device(dev)->export_key(export_format, key_to_export, client_id, app_data,
+                                           export_data);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::attest_key(const keymaster2_device_t* dev,
+                                                    const keymaster_key_blob_t* key_to_attest,
+                                                    const keymaster_key_param_set_t* attest_params,
+                                                    keymaster_cert_chain_t* cert_chain) {
+    return convert_device(dev)->attest_key(key_to_attest, attest_params, cert_chain);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::upgrade_key(const keymaster2_device_t* dev,
+                                                     const keymaster_key_blob_t* key_to_upgrade,
+                                                     const keymaster_key_param_set_t* upgrade_params,
+                                                     keymaster_key_blob_t* upgraded_key) {
+    return convert_device(dev)->upgrade_key(key_to_upgrade, upgrade_params, upgraded_key);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::begin(const keymaster2_device_t* dev,
+                                               keymaster_purpose_t purpose,
+                                               const keymaster_key_blob_t* key,
+                                               const keymaster_key_param_set_t* in_params,
+                                               keymaster_key_param_set_t* out_params,
+                                               keymaster_operation_handle_t* operation_handle) {
+    return convert_device(dev)->begin(purpose, key, in_params, out_params, operation_handle);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::update(
+    const keymaster2_device_t* dev, keymaster_operation_handle_t operation_handle,
+    const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input,
+    size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) {
+    return convert_device(dev)->update(operation_handle, in_params, input, input_consumed,
+                                       out_params, output);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::finish(const keymaster2_device_t* dev,
+                                                keymaster_operation_handle_t operation_handle,
+                                                const keymaster_key_param_set_t* in_params,
+                                                const keymaster_blob_t* input,
+                                                const keymaster_blob_t* signature,
+                                                keymaster_key_param_set_t* out_params,
+                                                keymaster_blob_t* output) {
+    return convert_device(dev)->finish(operation_handle, in_params, input, signature, out_params,
+                                       output);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::abort(const keymaster2_device_t* dev,
+                                               keymaster_operation_handle_t operation_handle) {
+    return convert_device(dev)->abort(operation_handle);
+}
+
+keymaster_error_t TrustyKeymasterDevice::Send(uint32_t command, const Serializable& req,
+                                              KeymasterResponse* rsp) {
+    uint32_t req_size = req.SerializedSize();
+    if (req_size > SEND_BUF_SIZE) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+    uint8_t send_buf[SEND_BUF_SIZE];
+    Eraser send_buf_eraser(send_buf, SEND_BUF_SIZE);
+    req.Serialize(send_buf, send_buf + req_size);
+
+    // Send it
+    uint8_t recv_buf[RECV_BUF_SIZE];
+    Eraser recv_buf_eraser(recv_buf, RECV_BUF_SIZE);
+    uint32_t rsp_size = RECV_BUF_SIZE;
+    // ALOGE("Sending %d byte request\n", (int)req.SerializedSize());
+    int rc = trusty_keymaster_call(command, send_buf, req_size, recv_buf, &rsp_size);
+    if (rc < 0) {
+        ALOGE("tipc error: %d\n", rc);
+        return translate_error(rc);
+    } else {
+        ALOGE("Received %d byte response\n", (int)rsp_size);
+    }
+
+    const uint8_t* p = recv_buf;
+    if (!rsp->Deserialize(&p, p + rsp_size)) {
+        ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
+        return KM_ERROR_UNKNOWN_ERROR;
+    } else if (rsp->error != KM_ERROR_OK) {
+        ALOGE("Error: Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
+        return rsp->error;
+    }
+    return rsp->error;
+}
+
+}  // namespace keymaster
diff --git a/keymaster/trusty_keymaster_device.h b/keymaster/trusty_keymaster_device.h
new file mode 100644
index 0000000..cfada1b
--- /dev/null
+++ b/keymaster/trusty_keymaster_device.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2014 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 TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
+#define TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
+
+#include <hardware/keymaster2.h>
+#include <keymaster/android_keymaster_messages.h>
+
+namespace keymaster {
+
+/**
+ * Trusty Keymaster device.
+ *
+ * IMPORTANT MAINTAINER NOTE: Pointers to instances of this class must be castable to hw_device_t
+ * and keymaster_device. This means it must remain a standard layout class (no virtual functions and
+ * no data members which aren't standard layout), and device_ must be the first data member.
+ * Assertions in the constructor validate compliance with those constraints.
+ */
+class TrustyKeymasterDevice {
+  public:
+    /*
+     * These are the only symbols that will be exported by libtrustykeymaster.  All functionality
+     * can be reached via the function pointers in device_.
+     */
+    __attribute__((visibility("default"))) explicit TrustyKeymasterDevice(const hw_module_t* module);
+    __attribute__((visibility("default"))) hw_device_t* hw_device();
+
+    ~TrustyKeymasterDevice();
+
+    keymaster_error_t session_error() { return error_; }
+
+    keymaster_error_t configure(const keymaster_key_param_set_t* params);
+    keymaster_error_t add_rng_entropy(const uint8_t* data, size_t data_length);
+    keymaster_error_t generate_key(const keymaster_key_param_set_t* params,
+                                   keymaster_key_blob_t* key_blob,
+                                   keymaster_key_characteristics_t* characteristics);
+    keymaster_error_t get_key_characteristics(const keymaster_key_blob_t* key_blob,
+                                              const keymaster_blob_t* client_id,
+                                              const keymaster_blob_t* app_data,
+                                              keymaster_key_characteristics_t* character);
+    keymaster_error_t import_key(const keymaster_key_param_set_t* params,
+                                 keymaster_key_format_t key_format,
+                                 const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob,
+                                 keymaster_key_characteristics_t* characteristics);
+    keymaster_error_t export_key(keymaster_key_format_t export_format,
+                                 const keymaster_key_blob_t* key_to_export,
+                                 const keymaster_blob_t* client_id,
+                                 const keymaster_blob_t* app_data, keymaster_blob_t* export_data);
+    keymaster_error_t attest_key(const keymaster_key_blob_t* key_to_attest,
+                                 const keymaster_key_param_set_t* attest_params,
+                                 keymaster_cert_chain_t* cert_chain);
+    keymaster_error_t upgrade_key(const keymaster_key_blob_t* key_to_upgrade,
+                                  const keymaster_key_param_set_t* upgrade_params,
+                                  keymaster_key_blob_t* upgraded_key);
+    keymaster_error_t begin(keymaster_purpose_t purpose, const keymaster_key_blob_t* key,
+                            const keymaster_key_param_set_t* in_params,
+                            keymaster_key_param_set_t* out_params,
+                            keymaster_operation_handle_t* operation_handle);
+    keymaster_error_t update(keymaster_operation_handle_t operation_handle,
+                             const keymaster_key_param_set_t* in_params,
+                             const keymaster_blob_t* input, size_t* input_consumed,
+                             keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
+    keymaster_error_t finish(keymaster_operation_handle_t operation_handle,
+                             const keymaster_key_param_set_t* in_params,
+                             const keymaster_blob_t* input, const keymaster_blob_t* signature,
+                             keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
+    keymaster_error_t abort(keymaster_operation_handle_t operation_handle);
+
+  private:
+    keymaster_error_t Send(uint32_t command, const Serializable& request,
+                           KeymasterResponse* response);
+
+    /*
+     * These static methods are the functions referenced through the function pointers in
+     * keymaster_device.  They're all trivial wrappers.
+     */
+    static int close_device(hw_device_t* dev);
+    static keymaster_error_t configure(const keymaster2_device_t* dev,
+                                       const keymaster_key_param_set_t* params);
+    static keymaster_error_t add_rng_entropy(const keymaster2_device_t* dev, const uint8_t* data,
+                                             size_t data_length);
+    static keymaster_error_t generate_key(const keymaster2_device_t* dev,
+                                          const keymaster_key_param_set_t* params,
+                                          keymaster_key_blob_t* key_blob,
+                                          keymaster_key_characteristics_t* characteristics);
+    static keymaster_error_t get_key_characteristics(const keymaster2_device_t* dev,
+                                                     const keymaster_key_blob_t* key_blob,
+                                                     const keymaster_blob_t* client_id,
+                                                     const keymaster_blob_t* app_data,
+                                                     keymaster_key_characteristics_t* character);
+    static keymaster_error_t import_key(const keymaster2_device_t* dev,
+                                        const keymaster_key_param_set_t* params,
+                                        keymaster_key_format_t key_format,
+                                        const keymaster_blob_t* key_data,
+                                        keymaster_key_blob_t* key_blob,
+                                        keymaster_key_characteristics_t* characteristics);
+    static keymaster_error_t export_key(const keymaster2_device_t* dev,
+                                        keymaster_key_format_t export_format,
+                                        const keymaster_key_blob_t* key_to_export,
+                                        const keymaster_blob_t* client_id,
+                                        const keymaster_blob_t* app_data,
+                                        keymaster_blob_t* export_data);
+    static keymaster_error_t attest_key(const keymaster2_device_t* dev,
+                                        const keymaster_key_blob_t* key_to_attest,
+                                        const keymaster_key_param_set_t* attest_params,
+                                        keymaster_cert_chain_t* cert_chain);
+    static keymaster_error_t upgrade_key(const keymaster2_device_t* dev,
+                                         const keymaster_key_blob_t* key_to_upgrade,
+                                         const keymaster_key_param_set_t* upgrade_params,
+                                         keymaster_key_blob_t* upgraded_key);
+    static keymaster_error_t delete_key(const keymaster2_device_t* dev,
+                                        const keymaster_key_blob_t* key);
+    static keymaster_error_t delete_all_keys(const keymaster2_device_t* dev);
+    static keymaster_error_t begin(const keymaster2_device_t* dev, keymaster_purpose_t purpose,
+                                   const keymaster_key_blob_t* key,
+                                   const keymaster_key_param_set_t* in_params,
+                                   keymaster_key_param_set_t* out_params,
+                                   keymaster_operation_handle_t* operation_handle);
+    static keymaster_error_t update(const keymaster2_device_t* dev,
+                                    keymaster_operation_handle_t operation_handle,
+                                    const keymaster_key_param_set_t* in_params,
+                                    const keymaster_blob_t* input, size_t* input_consumed,
+                                    keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
+    static keymaster_error_t finish(const keymaster2_device_t* dev,
+                                    keymaster_operation_handle_t operation_handle,
+                                    const keymaster_key_param_set_t* in_params,
+                                    const keymaster_blob_t* input, const keymaster_blob_t* signature,
+                                    keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
+    static keymaster_error_t abort(const keymaster2_device_t* dev,
+                                   keymaster_operation_handle_t operation_handle);
+
+    keymaster2_device_t device_;
+    keymaster_error_t error_;
+    int32_t message_version_;
+};
+
+}  // namespace keymaster
+
+#endif  // TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
diff --git a/keymaster/trusty_keymaster_ipc.cpp b/keymaster/trusty_keymaster_ipc.cpp
new file mode 100644
index 0000000..381ba4a
--- /dev/null
+++ b/keymaster/trusty_keymaster_ipc.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TrustyKeymaster"
+
+// TODO: make this generic in libtrusty
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <log/log.h>
+
+#include "keymaster_ipc.h"
+#include "trusty_keymaster_ipc.h"
+#include "qemud.h"
+
+#define KEYMASTER_SERVICE_NAME "KeymasterService3"
+
+static int handle_ = 0;
+
+int trusty_keymaster_connect() {
+    ALOGE("calling %s\n", __func__);
+    handle_ = qemu_pipe_open(KEYMASTER_SERVICE_NAME);
+    if (handle_ < 0) {
+        handle_ = 0;
+        ALOGE("failed to open %s pipe service", KEYMASTER_SERVICE_NAME);
+        ALOGE("calling %s failed\n", __func__);
+        return -1;
+    }
+    ALOGE("calling %s succeeded\n", __func__);
+    return 0;
+}
+
+int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+                          uint32_t* out_size) {
+
+    size_t msg_size = in_size + sizeof(struct keymaster_message);
+    ALOGE("calling %s insize %d msg size %d\n", __func__, (int)in_size, (int) msg_size);
+    struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size));
+    msg->cmd = cmd;
+    memcpy(msg->payload, in, in_size);
+
+    int pipe_command_length = msg_size;
+    assert(pipe_command_length > 0);
+    ssize_t rc = WriteFully(handle_, &pipe_command_length, sizeof(pipe_command_length));
+    if (rc < 1) {
+        ALOGE("failed to send msg_size (%d) for cmd (%d) to %s: %s\n", (int)(sizeof(pipe_command_length)),
+                (int)cmd, KEYMASTER_PORT, strerror(errno));
+        return -errno;
+    }
+
+    rc = WriteFully(handle_, msg, pipe_command_length);
+    if (in_size == 157 && cmd == KM_FINISH_OPERATION) {
+        for (int i=0; i < (int)in_size; ++i) {
+            ALOGE("pay[%d]: %d", i, (int)(msg->payload[i]));
+        }
+    }
+    free(msg);
+
+
+    if (rc < 1) {
+        ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT, strerror(errno));
+        return -errno;
+    }
+
+    rc = ReadFully(handle_, &pipe_command_length, sizeof(pipe_command_length));
+    if (rc < 1) {
+        ALOGE("failed to retrieve response length for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
+              strerror(errno));
+        return -errno;
+    }
+
+    rc = ReadFully(handle_, out, pipe_command_length);
+    if (rc < 1) {
+        ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
+              strerror(errno));
+        return -errno;
+    }
+    *out_size = pipe_command_length;
+    return pipe_command_length;
+}
+
+void trusty_keymaster_disconnect() {
+    ALOGE("calling %s\n", __func__);
+    if (handle_ != 0) {
+        close(handle_);
+        handle_ = 0;
+    }
+}
diff --git a/keymaster/trusty_keymaster_ipc.h b/keymaster/trusty_keymaster_ipc.h
new file mode 100644
index 0000000..c15f7c1
--- /dev/null
+++ b/keymaster/trusty_keymaster_ipc.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 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 TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_IPC_H_
+#define TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_IPC_H_
+
+__BEGIN_DECLS
+
+int trusty_keymaster_connect(void);
+int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+                          uint32_t* out_size);
+void trusty_keymaster_disconnect(void);
+
+__END_DECLS
+
+#endif  // TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_IPC_H_