Project import
diff --git a/security/MODULE_LICENSE_APACHE2 b/security/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/security/MODULE_LICENSE_APACHE2
diff --git a/security/NOTICE b/security/NOTICE
new file mode 100644
index 0000000..89ae7c4
--- /dev/null
+++ b/security/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2008-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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/security/keystore-engine/Android.mk b/security/keystore-engine/Android.mk
new file mode 100644
index 0000000..1f5d903
--- /dev/null
+++ b/security/keystore-engine/Android.mk
@@ -0,0 +1,60 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+
+ifneq (,$(wildcard $(TOP)/external/boringssl/flavor.mk))
+	include $(TOP)/external/boringssl/flavor.mk
+else
+	include $(TOP)/external/openssl/flavor.mk
+endif
+ifeq ($(OPENSSL_FLAVOR),BoringSSL)
+  LOCAL_MODULE := libkeystore-engine
+
+  LOCAL_SRC_FILES := \
+	android_engine.cpp
+else
+  LOCAL_MODULE := libkeystore
+
+  LOCAL_MODULE_RELATIVE_PATH := ssl/engines
+
+  LOCAL_SRC_FILES := \
+	eng_keystore.cpp \
+	keyhandle.cpp \
+	ecdsa_meth.cpp \
+	dsa_meth.cpp \
+	rsa_meth.cpp
+
+  LOCAL_C_INCLUDES += \
+	external/openssl/include \
+	external/openssl
+endif
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror
+
+LOCAL_SHARED_LIBRARIES += \
+	libcrypto \
+	liblog \
+	libcutils \
+	libutils \
+	libbinder \
+	libkeystore_binder
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/security/keystore-engine/android_engine.cpp b/security/keystore-engine/android_engine.cpp
new file mode 100644
index 0000000..de67df2
--- /dev/null
+++ b/security/keystore-engine/android_engine.cpp
@@ -0,0 +1,454 @@
+/* Copyright 2014 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#include <UniquePtr.h>
+
+#include <sys/socket.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+#include <binder/IServiceManager.h>
+#include <keystore/keystore.h>
+#include <keystore/IKeystoreService.h>
+
+using namespace android;
+
+namespace {
+
+extern const RSA_METHOD keystore_rsa_method;
+extern const ECDSA_METHOD keystore_ecdsa_method;
+
+/* key_id_dup is called when one of the RSA or EC_KEY objects is duplicated. */
+int key_id_dup(CRYPTO_EX_DATA* /* to */,
+               const CRYPTO_EX_DATA* /* from */,
+               void** from_d,
+               int /* index */,
+               long /* argl */,
+               void* /* argp */) {
+    char *key_id = reinterpret_cast<char *>(*from_d);
+    if (key_id != NULL) {
+        *from_d = strdup(key_id);
+    }
+    return 1;
+}
+
+/* key_id_free is called when one of the RSA, DSA or EC_KEY object is freed. */
+void key_id_free(void* /* parent */,
+                 void* ptr,
+                 CRYPTO_EX_DATA* /* ad */,
+                 int /* index */,
+                 long /* argl */,
+                 void* /* argp */) {
+    char *key_id = reinterpret_cast<char *>(ptr);
+    free(key_id);
+}
+
+/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
+ * forwarding the requested operations to Keystore. */
+class KeystoreEngine {
+ public:
+  KeystoreEngine()
+      : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
+                                        NULL /* argp */,
+                                        NULL /* new_func */,
+                                        key_id_dup,
+                                        key_id_free)),
+        ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
+                                              NULL /* argp */,
+                                              NULL /* new_func */,
+                                              key_id_dup,
+                                              key_id_free)),
+        engine_(ENGINE_new()) {
+    ENGINE_set_RSA_method(
+        engine_, &keystore_rsa_method, sizeof(keystore_rsa_method));
+    ENGINE_set_ECDSA_method(
+        engine_, &keystore_ecdsa_method, sizeof(keystore_ecdsa_method));
+  }
+
+  int rsa_ex_index() const { return rsa_index_; }
+  int ec_key_ex_index() const { return ec_key_index_; }
+
+  const ENGINE* engine() const { return engine_; }
+
+ private:
+  const int rsa_index_;
+  const int ec_key_index_;
+  ENGINE* const engine_;
+};
+
+pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
+KeystoreEngine *g_keystore_engine;
+
+/* init_keystore_engine is called to initialize |g_keystore_engine|. This
+ * should only be called by |pthread_once|. */
+void init_keystore_engine() {
+    g_keystore_engine = new KeystoreEngine;
+}
+
+/* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
+ * valid |KeystoreEngine| object and creates one if not. */
+void ensure_keystore_engine() {
+    pthread_once(&g_keystore_engine_once, init_keystore_engine);
+}
+
+/* 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()
+
+const char* rsa_get_key_id(const RSA* rsa) {
+  return reinterpret_cast<char*>(
+      RSA_get_ex_data(rsa, g_keystore_engine->rsa_ex_index()));
+}
+
+/* rsa_private_transform takes a big-endian integer from |in|, calculates the
+ * d'th power of it, modulo the RSA modulus, and writes the result as a
+ * big-endian integer to |out|. Both |in| and |out| are |len| bytes long. It
+ * returns one on success and zero otherwise. */
+int rsa_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in, size_t len) {
+    ALOGV("rsa_private_transform(%p, %p, %p, %u)", rsa, out, in, (unsigned) len);
+
+    const char *key_id = rsa_get_key_id(rsa);
+    if (key_id == NULL) {
+        ALOGE("key had no key_id!");
+        return 0;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    uint8_t* reply = NULL;
+    size_t reply_len;
+    int32_t ret = service->sign(String16(key_id), in, len, &reply, &reply_len);
+    if (ret < 0) {
+        ALOGW("There was an error during rsa_decrypt: could not connect");
+        return 0;
+    } else if (ret != 0) {
+        ALOGW("Error during sign from keystore: %d", ret);
+        return 0;
+    } else if (reply_len == 0) {
+        ALOGW("No valid signature returned");
+        free(reply);
+        return 0;
+    }
+
+    if (reply_len > len) {
+        /* The result of the RSA operation can never be larger than the size of
+         * the modulus so we assume that the result has extra zeros on the
+         * left. This provides attackers with an oracle, but there's nothing
+         * that we can do about it here. */
+        memcpy(out, reply + reply_len - len, len);
+    } else if (reply_len < len) {
+        /* If the Keystore implementation returns a short value we assume that
+         * it's because it removed leading zeros from the left side. This is
+         * bad because it provides attackers with an oracle but we cannot do
+         * anything about a broken Keystore implementation here. */
+        memset(out, 0, len);
+        memcpy(out + len - reply_len, reply, reply_len);
+    } else {
+        memcpy(out, reply, len);
+    }
+
+    free(reply);
+
+    ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
+    return 1;
+}
+
+const struct rsa_meth_st keystore_rsa_method = {
+  {
+    0 /* references */,
+    1 /* is_static */,
+  },
+  NULL /* app_data */,
+
+  NULL /* init */,
+  NULL /* finish */,
+
+  NULL /* size */,
+
+  NULL /* sign */,
+  NULL /* verify */,
+
+  NULL /* encrypt */,
+  NULL /* sign_raw */,
+  NULL /* decrypt */,
+  NULL /* verify_raw */,
+
+  rsa_private_transform,
+
+  NULL /* mod_exp */,
+  NULL /* bn_mod_exp */,
+
+  RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE,
+
+  NULL /* keygen */,
+  NULL /* multi_prime_keygen */,
+  NULL /* supports_digest */,
+};
+
+const char* ecdsa_get_key_id(const EC_KEY* ec_key) {
+    return reinterpret_cast<char*>(
+        EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
+}
+
+/* ecdsa_sign signs |digest_len| bytes from |digest| with |ec_key| and writes
+ * the resulting signature (an ASN.1 encoded blob) to |sig|. It returns one on
+ * success and zero otherwise. */
+static int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                      unsigned int* sig_len, EC_KEY* ec_key) {
+    ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned) digest_len, ec_key);
+
+    const char *key_id = ecdsa_get_key_id(ec_key);
+    if (key_id == NULL) {
+        ALOGE("key had no key_id!");
+        return 0;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    size_t ecdsa_size = ECDSA_size(ec_key);
+
+    uint8_t* reply = NULL;
+    size_t reply_len;
+    int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)),
+                                digest, digest_len, &reply, &reply_len);
+    if (ret < 0) {
+        ALOGW("There was an error during ecdsa_sign: could not connect");
+        return 0;
+    } else if (ret != 0) {
+        ALOGW("Error during sign from keystore: %d", ret);
+        return 0;
+    } else if (reply_len == 0) {
+        ALOGW("No valid signature returned");
+        free(reply);
+        return 0;
+    } else if (reply_len > ecdsa_size) {
+        ALOGW("Signature is too large");
+        free(reply);
+        return 0;
+    }
+
+    memcpy(sig, reply, reply_len);
+    *sig_len = reply_len;
+
+    ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len,
+          ec_key);
+    return 1;
+}
+
+const ECDSA_METHOD keystore_ecdsa_method = {
+    {
+     0 /* references */,
+     1 /* is_static */
+    } /* common */,
+    NULL /* app_data */,
+
+    NULL /* init */,
+    NULL /* finish */,
+    NULL /* group_order_size */,
+    ecdsa_sign,
+    NULL /* verify */,
+    ECDSA_FLAG_OPAQUE,
+};
+
+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;
+
+struct EC_KEY_Delete {
+    void operator()(EC_KEY* ec) const {
+        EC_KEY_free(ec);
+    }
+};
+typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
+
+/* wrap_rsa returns an |EVP_PKEY| that contains an RSA key where the public
+ * part is taken from |public_rsa| and the private operations are forwarded to
+ * KeyStore and operate on the key named |key_id|. */
+static EVP_PKEY *wrap_rsa(const char *key_id, const RSA *public_rsa) {
+    Unique_RSA rsa(RSA_new_method(g_keystore_engine->engine()));
+    if (rsa.get() == NULL) {
+        return NULL;
+    }
+
+    char *key_id_copy = strdup(key_id);
+    if (key_id_copy == NULL) {
+        return NULL;
+    }
+
+    if (!RSA_set_ex_data(rsa.get(), g_keystore_engine->rsa_ex_index(),
+                         key_id_copy)) {
+        free(key_id_copy);
+        return NULL;
+    }
+
+    rsa->n = BN_dup(public_rsa->n);
+    rsa->e = BN_dup(public_rsa->e);
+    if (rsa->n == NULL || rsa->e == NULL) {
+        return NULL;
+    }
+
+    Unique_EVP_PKEY result(EVP_PKEY_new());
+    if (result.get() == NULL ||
+        !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
+        return NULL;
+    }
+    OWNERSHIP_TRANSFERRED(rsa);
+
+    return result.release();
+}
+
+/* wrap_ecdsa returns an |EVP_PKEY| that contains an ECDSA key where the public
+ * part is taken from |public_rsa| and the private operations are forwarded to
+ * KeyStore and operate on the key named |key_id|. */
+static EVP_PKEY *wrap_ecdsa(const char *key_id, const EC_KEY *public_ecdsa) {
+    Unique_EC_KEY ec(EC_KEY_new_method(g_keystore_engine->engine()));
+    if (ec.get() == NULL) {
+        return NULL;
+    }
+
+    if (!EC_KEY_set_group(ec.get(), EC_KEY_get0_group(public_ecdsa)) ||
+        !EC_KEY_set_public_key(ec.get(), EC_KEY_get0_public_key(public_ecdsa))) {
+        return NULL;
+    }
+
+    char *key_id_copy = strdup(key_id);
+    if (key_id_copy == NULL) {
+        return NULL;
+    }
+
+    if (!EC_KEY_set_ex_data(ec.get(), g_keystore_engine->ec_key_ex_index(),
+                            key_id_copy)) {
+        free(key_id_copy);
+        return NULL;
+    }
+
+    Unique_EVP_PKEY result(EVP_PKEY_new());
+    if (result.get() == NULL ||
+        !EVP_PKEY_assign_EC_KEY(result.get(), ec.get())) {
+        return NULL;
+    }
+    OWNERSHIP_TRANSFERRED(ec);
+
+    return result.release();
+}
+
+}  /* anonymous namespace */
+
+extern "C" {
+
+EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) __attribute__((visibility("default")));
+
+/* EVP_PKEY_from_keystore returns an |EVP_PKEY| that contains either an RSA or
+ * ECDSA key where the public part of the key reflects the value of the key
+ * named |key_id| in Keystore and the private operations are forwarded onto
+ * KeyStore. */
+EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) {
+    ALOGV("EVP_PKEY_from_keystore(\"%s\")", key_id);
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    uint8_t *pubkey = NULL;
+    size_t pubkey_len;
+    int32_t ret = service->get_pubkey(String16(key_id), &pubkey, &pubkey_len);
+    if (ret < 0) {
+        ALOGW("could not contact keystore");
+        return NULL;
+    } else if (ret != 0) {
+        ALOGW("keystore reports error: %d", ret);
+        return NULL;
+    }
+
+    const uint8_t *inp = pubkey;
+    Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &inp, pubkey_len));
+    free(pubkey);
+    if (pkey.get() == NULL) {
+        ALOGW("Cannot convert pubkey");
+        return NULL;
+    }
+
+    ensure_keystore_engine();
+
+    EVP_PKEY *result;
+    switch (EVP_PKEY_type(pkey->type)) {
+    case EVP_PKEY_RSA: {
+        Unique_RSA public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
+        result = wrap_rsa(key_id, public_rsa.get());
+        break;
+    }
+    case EVP_PKEY_EC: {
+        Unique_EC_KEY public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
+        result = wrap_ecdsa(key_id, public_ecdsa.get());
+        break;
+    }
+    default:
+        ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type));
+        result = NULL;
+    }
+
+    return result;
+}
+
+}  // extern "C"
diff --git a/security/keystore-engine/dsa_meth.cpp b/security/keystore-engine/dsa_meth.cpp
new file mode 100644
index 0000000..3788364
--- /dev/null
+++ b/security/keystore-engine/dsa_meth.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <UniquePtr.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OpenSSL-keystore-dsa"
+#include <cutils/log.h>
+
+#include <binder/IServiceManager.h>
+#include <keystore/IKeystoreService.h>
+
+#include <openssl/dsa.h>
+#include <openssl/engine.h>
+
+#include "methods.h"
+
+
+using namespace android;
+
+struct DSA_SIG_Delete {
+    void operator()(DSA_SIG* p) const {
+        DSA_SIG_free(p);
+    }
+};
+typedef UniquePtr<DSA_SIG, struct DSA_SIG_Delete> Unique_DSA_SIG;
+
+static DSA_SIG* keystore_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) {
+    ALOGV("keystore_dsa_do_sign(%p, %d, %p)", dgst, dlen, dsa);
+
+    uint8_t* key_id = reinterpret_cast<uint8_t*>(DSA_get_ex_data(dsa, dsa_key_handle));
+    if (key_id == NULL) {
+        ALOGE("key had no key_id!");
+        return 0;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    int num = DSA_size(dsa);
+
+    uint8_t* reply = NULL;
+    size_t replyLen;
+    int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), dgst,
+            dlen, &reply, &replyLen);
+    if (ret < 0) {
+        ALOGW("There was an error during dsa_do_sign: could not connect");
+        return 0;
+    } else if (ret != 0) {
+        ALOGW("Error during sign from keystore: %d", ret);
+        return 0;
+    } else if (replyLen <= 0) {
+        ALOGW("No valid signature returned");
+        return 0;
+    } else if (replyLen > (size_t) num) {
+        ALOGW("Signature is too large");
+        return 0;
+    }
+
+    Unique_DSA_SIG dsa_sig(d2i_DSA_SIG(NULL,
+            const_cast<const unsigned char**>(reinterpret_cast<unsigned char**>(&reply)),
+            replyLen));
+    if (dsa_sig.get() == NULL) {
+        ALOGW("conversion from DER to DSA_SIG failed");
+        return 0;
+    }
+
+    ALOGV("keystore_dsa_do_sign(%p, %d, %p) => returning %p len %zu", dgst, dlen, dsa,
+            dsa_sig.get(), replyLen);
+    return dsa_sig.release();
+}
+
+static DSA_METHOD keystore_dsa_meth = {
+        kKeystoreEngineId, /* name */
+        keystore_dsa_do_sign, /* dsa_do_sign */
+        NULL, /* dsa_sign_setup */
+        NULL, /* dsa_do_verify */
+        NULL, /* dsa_mod_exp */
+        NULL, /* bn_mod_exp */
+        NULL, /* init */
+        NULL, /* finish */
+        0, /* flags */
+        NULL, /* app_data */
+        NULL, /* dsa_paramgen */
+        NULL, /* dsa_keygen */
+};
+
+static int register_dsa_methods() {
+    const DSA_METHOD* dsa_meth = DSA_OpenSSL();
+
+    keystore_dsa_meth.dsa_do_verify = dsa_meth->dsa_do_verify;
+
+    return 1;
+}
+
+int dsa_pkey_setup(ENGINE *e, EVP_PKEY *pkey, const char *key_id) {
+    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
+    if (!DSA_set_ex_data(dsa.get(), dsa_key_handle, reinterpret_cast<void*>(strdup(key_id)))) {
+        ALOGW("Could not set ex_data for loaded DSA key");
+        return 0;
+    }
+
+    DSA_set_method(dsa.get(), &keystore_dsa_meth);
+
+    /*
+     * "DSA_set_ENGINE()" should probably be an OpenSSL API. Since it isn't,
+     * and EVP_PKEY_free() calls ENGINE_finish(), we need to call ENGINE_init()
+     * here.
+     */
+    ENGINE_init(e);
+    dsa->engine = e;
+
+    return 1;
+}
+
+int dsa_register(ENGINE* e) {
+    if (!ENGINE_set_DSA(e, &keystore_dsa_meth)
+            || !register_dsa_methods()) {
+        ALOGE("Could not set up keystore DSA methods");
+        return 0;
+    }
+
+    return 1;
+}
diff --git a/security/keystore-engine/ecdsa_meth.cpp b/security/keystore-engine/ecdsa_meth.cpp
new file mode 100644
index 0000000..48f178d
--- /dev/null
+++ b/security/keystore-engine/ecdsa_meth.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <UniquePtr.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OpenSSL-keystore-ecdsa"
+#include <cutils/log.h>
+
+#include <binder/IServiceManager.h>
+#include <keystore/IKeystoreService.h>
+
+#include <openssl/ecdsa.h>
+#include <openssl/engine.h>
+
+// TODO replace this with real OpenSSL API when it exists
+#include "crypto/ec/ec_lcl.h"
+#include "crypto/ecdsa/ecs_locl.h"
+
+#include "methods.h"
+
+
+using namespace android;
+
+struct ECDSA_SIG_Delete {
+    void operator()(ECDSA_SIG* p) const {
+        ECDSA_SIG_free(p);
+    }
+};
+typedef UniquePtr<ECDSA_SIG, struct ECDSA_SIG_Delete> Unique_ECDSA_SIG;
+
+static ECDSA_SIG* keystore_ecdsa_do_sign(const unsigned char *dgst, int dlen,
+        const BIGNUM*, const BIGNUM*, EC_KEY *eckey) {
+    ALOGV("keystore_ecdsa_do_sign(%p, %d, %p)", dgst, dlen, eckey);
+
+    uint8_t* key_id = reinterpret_cast<uint8_t*>(EC_KEY_get_key_method_data(eckey,
+                ex_data_dup, ex_data_free, ex_data_clear_free));
+    if (key_id == NULL) {
+        ALOGE("key had no key_id!");
+        return 0;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    int num = ECDSA_size(eckey);
+
+    uint8_t* reply = NULL;
+    size_t replyLen;
+    int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), dgst,
+            dlen, &reply, &replyLen);
+    if (ret < 0) {
+        ALOGW("There was an error during dsa_do_sign: could not connect");
+        return 0;
+    } else if (ret != 0) {
+        ALOGW("Error during sign from keystore: %d", ret);
+        return 0;
+    } else if (replyLen <= 0) {
+        ALOGW("No valid signature returned");
+        return 0;
+    } else if (replyLen > (size_t) num) {
+        ALOGW("Signature is too large");
+        return 0;
+    }
+
+    Unique_ECDSA_SIG ecdsa_sig(d2i_ECDSA_SIG(NULL,
+            const_cast<const unsigned char**>(reinterpret_cast<unsigned char**>(&reply)),
+            replyLen));
+    if (ecdsa_sig.get() == NULL) {
+        ALOGW("conversion from DER to ECDSA_SIG failed");
+        return 0;
+    }
+
+    ALOGV("keystore_ecdsa_do_sign(%p, %d, %p) => returning %p len %zu", dgst, dlen, eckey,
+            ecdsa_sig.get(), replyLen);
+    return ecdsa_sig.release();
+}
+
+static ECDSA_METHOD keystore_ecdsa_meth = {
+        kKeystoreEngineId, /* name */
+        keystore_ecdsa_do_sign, /* ecdsa_do_sign */
+        NULL, /* ecdsa_sign_setup */
+        NULL, /* ecdsa_do_verify */
+        0, /* flags */
+        NULL, /* app_data */
+};
+
+static int register_ecdsa_methods() {
+    const ECDSA_METHOD* ecdsa_meth = ECDSA_OpenSSL();
+
+    keystore_ecdsa_meth.ecdsa_do_verify = ecdsa_meth->ecdsa_do_verify;
+
+    return 1;
+}
+
+int ecdsa_pkey_setup(ENGINE *e, EVP_PKEY *pkey, const char *key_id) {
+    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
+    void* oldData = EC_KEY_insert_key_method_data(eckey.get(),
+            reinterpret_cast<void*>(strdup(key_id)), ex_data_dup, ex_data_free,
+            ex_data_clear_free);
+    if (oldData != NULL) {
+        free(oldData);
+    }
+
+    ECDSA_set_method(eckey.get(), &keystore_ecdsa_meth);
+
+    /*
+     * "ECDSA_set_ENGINE()" should probably be an OpenSSL API. Since it isn't,
+     * and EC_KEY_free() calls ENGINE_finish(), we need to call ENGINE_init()
+     * here.
+     */
+    ECDSA_DATA *ecdsa = ecdsa_check(eckey.get());
+    ENGINE_init(e);
+    ecdsa->engine = e;
+
+    return 1;
+}
+
+int ecdsa_register(ENGINE* e) {
+    if (!ENGINE_set_ECDSA(e, &keystore_ecdsa_meth)
+            || !register_ecdsa_methods()) {
+        ALOGE("Could not set up keystore ECDSA methods");
+        return 0;
+    }
+
+    return 1;
+}
diff --git a/security/keystore-engine/eng_keystore.cpp b/security/keystore-engine/eng_keystore.cpp
new file mode 100644
index 0000000..6feb0f9
--- /dev/null
+++ b/security/keystore-engine/eng_keystore.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <UniquePtr.h>
+
+#include <sys/socket.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/dsa.h>
+#include <openssl/engine.h>
+#include <openssl/ec.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OpenSSL-keystore"
+#include <cutils/log.h>
+
+#include <binder/IServiceManager.h>
+#include <keystore/keystore.h>
+#include <keystore/IKeystoreService.h>
+
+#include "methods.h"
+
+using namespace android;
+
+#define DYNAMIC_ENGINE
+const char* kKeystoreEngineId = "keystore";
+static const char* kKeystoreEngineDesc = "Android keystore engine";
+
+
+/*
+ * ex_data index for keystore's key alias.
+ */
+int rsa_key_handle;
+int dsa_key_handle;
+
+
+/*
+ * Only initialize the *_key_handle once.
+ */
+static pthread_once_t key_handle_control = PTHREAD_ONCE_INIT;
+
+/**
+ * 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()
+
+
+struct ENGINE_Delete {
+    void operator()(ENGINE* p) const {
+        ENGINE_free(p);
+    }
+};
+typedef UniquePtr<ENGINE, ENGINE_Delete> Unique_ENGINE;
+
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) const {
+        EVP_PKEY_free(p);
+    }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+/**
+ * Called to initialize RSA's ex_data for the key_id handle. This should
+ * only be called when protected by a lock.
+ */
+static void init_key_handle() {
+    rsa_key_handle = RSA_get_ex_new_index(0, NULL, keyhandle_new, keyhandle_dup, keyhandle_free);
+    dsa_key_handle = DSA_get_ex_new_index(0, NULL, keyhandle_new, keyhandle_dup, keyhandle_free);
+}
+
+static EVP_PKEY* keystore_loadkey(ENGINE* e, const char* key_id, UI_METHOD* ui_method,
+        void* callback_data) {
+#if LOG_NDEBUG
+    (void)ui_method;
+    (void)callback_data;
+#else
+    ALOGV("keystore_loadkey(%p, \"%s\", %p, %p)", e, key_id, ui_method, callback_data);
+#endif
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    uint8_t *pubkey = NULL;
+    size_t pubkeyLen;
+    int32_t ret = service->get_pubkey(String16(key_id), &pubkey, &pubkeyLen);
+    if (ret < 0) {
+        ALOGW("could not contact keystore");
+        free(pubkey);
+        return NULL;
+    } else if (ret != 0) {
+        ALOGW("keystore reports error: %d", ret);
+        free(pubkey);
+        return NULL;
+    }
+
+    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(pubkey);
+    Unique_EVP_PKEY pkey(d2i_PUBKEY(NULL, &tmp, pubkeyLen));
+    free(pubkey);
+    if (pkey.get() == NULL) {
+        ALOGW("Cannot convert pubkey");
+        return NULL;
+    }
+
+    switch (EVP_PKEY_type(pkey->type)) {
+    case EVP_PKEY_DSA: {
+        dsa_pkey_setup(e, pkey.get(), key_id);
+        break;
+    }
+    case EVP_PKEY_RSA: {
+        rsa_pkey_setup(e, pkey.get(), key_id);
+        break;
+    }
+    case EVP_PKEY_EC: {
+        ecdsa_pkey_setup(e, pkey.get(), key_id);
+        break;
+    }
+    default:
+        ALOGE("Unsupported key type %d", EVP_PKEY_type(pkey->type));
+        return NULL;
+    }
+
+    return pkey.release();
+}
+
+static const ENGINE_CMD_DEFN keystore_cmd_defns[] = {
+    {0, NULL, NULL, 0}
+};
+
+static int keystore_engine_setup(ENGINE* e) {
+    ALOGV("keystore_engine_setup");
+
+    if (!ENGINE_set_id(e, kKeystoreEngineId)
+            || !ENGINE_set_name(e, kKeystoreEngineDesc)
+            || !ENGINE_set_load_privkey_function(e, keystore_loadkey)
+            || !ENGINE_set_load_pubkey_function(e, keystore_loadkey)
+            || !ENGINE_set_flags(e, 0)
+            || !ENGINE_set_cmd_defns(e, keystore_cmd_defns)) {
+        ALOGE("Could not set up keystore engine");
+        return 0;
+    }
+
+    /* We need a handle in the keys types as well for keygen if it's not already initialized. */
+    pthread_once(&key_handle_control, init_key_handle);
+    if ((rsa_key_handle < 0) || (dsa_key_handle < 0)) {
+        ALOGE("Could not set up ex_data index");
+        return 0;
+    }
+
+    if (!dsa_register(e)) {
+        ALOGE("DSA registration failed");
+        return 0;
+    } else if (!ecdsa_register(e)) {
+        ALOGE("ECDSA registration failed");
+        return 0;
+    } else if (!rsa_register(e)) {
+        ALOGE("RSA registration failed");
+        return 0;
+    }
+
+    return 1;
+}
+
+ENGINE* ENGINE_keystore() {
+    ALOGV("ENGINE_keystore");
+
+    Unique_ENGINE engine(ENGINE_new());
+    if (engine.get() == NULL) {
+        return NULL;
+    }
+
+    if (!keystore_engine_setup(engine.get())) {
+        return NULL;
+    }
+
+    return engine.release();
+}
+
+static int keystore_bind_fn(ENGINE *e, const char *id) {
+    ALOGV("keystore_bind_fn");
+
+    if (!id) {
+        return 0;
+    }
+
+    if (strcmp(id, kKeystoreEngineId)) {
+        return 0;
+    }
+
+    if (!keystore_engine_setup(e)) {
+        return 0;
+    }
+
+    return 1;
+}
+
+extern "C" {
+#undef OPENSSL_EXPORT
+#define OPENSSL_EXPORT extern __attribute__ ((visibility ("default")))
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(keystore_bind_fn)
+};
diff --git a/security/keystore-engine/keyhandle.cpp b/security/keystore-engine/keyhandle.cpp
new file mode 100644
index 0000000..aeba896
--- /dev/null
+++ b/security/keystore-engine/keyhandle.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <openssl/engine.h>
+
+#include <string.h>
+
+/**
+ * Makes sure the ex_data for the keyhandle is initially set to NULL.
+ */
+int keyhandle_new(void*, void*, CRYPTO_EX_DATA* ad, int idx, long, void*) {
+    return CRYPTO_set_ex_data(ad, idx, NULL);
+}
+
+/**
+ * Frees a previously allocated keyhandle stored in ex_data.
+ */
+void keyhandle_free(void *, void *ptr, CRYPTO_EX_DATA*, int, long, void*) {
+    char* keyhandle = reinterpret_cast<char*>(ptr);
+    if (keyhandle != NULL) {
+        free(keyhandle);
+    }
+}
+
+/**
+ * Duplicates a keyhandle stored in ex_data in case we copy a key.
+ */
+int keyhandle_dup(CRYPTO_EX_DATA* to, CRYPTO_EX_DATA*, void *ptrRef, int idx, long, void *) {
+    // This appears to be a bug in OpenSSL.
+    void** ptr = reinterpret_cast<void**>(ptrRef);
+    char* keyhandle = reinterpret_cast<char*>(*ptr);
+    if (keyhandle != NULL) {
+        char* keyhandle_copy = strdup(keyhandle);
+        *ptr = keyhandle_copy;
+
+        // Call this in case OpenSSL is fixed in the future.
+        (void) CRYPTO_set_ex_data(to, idx, keyhandle_copy);
+    }
+    return 1;
+}
+
+void *ex_data_dup(void *data) {
+    char* keyhandle = reinterpret_cast<char*>(data);
+    return strdup(keyhandle);
+}
+
+void ex_data_free(void *data) {
+    char* keyhandle = reinterpret_cast<char*>(data);
+    free(keyhandle);
+}
+
+void ex_data_clear_free(void *data) {
+    char* keyhandle = reinterpret_cast<char*>(data);
+    memset(data, '\0', strlen(keyhandle));
+    free(keyhandle);
+}
diff --git a/security/keystore-engine/methods.h b/security/keystore-engine/methods.h
new file mode 100644
index 0000000..fb85942
--- /dev/null
+++ b/security/keystore-engine/methods.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* For ENGINE method registration purposes. */
+extern const char* kKeystoreEngineId;
+
+extern int dsa_key_handle;
+extern int rsa_key_handle;
+
+struct DSA_Delete {
+    void operator()(DSA* p) const {
+        DSA_free(p);
+    }
+};
+typedef UniquePtr<DSA, struct DSA_Delete> Unique_DSA;
+
+struct EC_KEY_Delete {
+    void operator()(EC_KEY* p) const {
+        EC_KEY_free(p);
+    }
+};
+typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
+
+struct RSA_Delete {
+    void operator()(RSA* p) const {
+        RSA_free(p);
+    }
+};
+typedef UniquePtr<RSA, struct RSA_Delete> Unique_RSA;
+
+
+/* Keyhandles for ENGINE metadata */
+int keyhandle_new(void*, void*, CRYPTO_EX_DATA* ad, int idx, long, void*);
+void keyhandle_free(void *, void *ptr, CRYPTO_EX_DATA*, int, long, void*);
+int keyhandle_dup(CRYPTO_EX_DATA* to, CRYPTO_EX_DATA*, void *ptrRef, int idx, long, void *);
+
+/* For EC_EX_DATA stuff */
+void *ex_data_dup(void *);
+void ex_data_free(void *);
+void ex_data_clear_free(void *);
+
+/* ECDSA */
+int ecdsa_register(ENGINE *);
+int ecdsa_pkey_setup(ENGINE *, EVP_PKEY*, const char*);
+
+/* DSA */
+int dsa_register(ENGINE *);
+int dsa_pkey_setup(ENGINE *, EVP_PKEY*, const char*);
+
+/* RSA */
+int rsa_register(ENGINE *);
+int rsa_pkey_setup(ENGINE *, EVP_PKEY*, const char*);
diff --git a/security/keystore-engine/rsa_meth.cpp b/security/keystore-engine/rsa_meth.cpp
new file mode 100644
index 0000000..74dfa5c
--- /dev/null
+++ b/security/keystore-engine/rsa_meth.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <UniquePtr.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OpenSSL-keystore-rsa"
+#include <cutils/log.h>
+
+#include <binder/IServiceManager.h>
+#include <keystore/IKeystoreService.h>
+
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+
+#include "methods.h"
+
+
+using namespace android;
+
+
+int keystore_rsa_priv_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
+        int padding) {
+    ALOGV("keystore_rsa_priv_enc(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
+
+    int num = RSA_size(rsa);
+    UniquePtr<uint8_t> padded(new uint8_t[num]);
+    if (padded.get() == NULL) {
+        ALOGE("could not allocate padded signature");
+        return 0;
+    }
+
+    switch (padding) {
+    case RSA_PKCS1_PADDING:
+        if (!RSA_padding_add_PKCS1_type_1(padded.get(), num, from, flen)) {
+            return 0;
+        }
+        break;
+    case RSA_X931_PADDING:
+        if (!RSA_padding_add_X931(padded.get(), num, from, flen)) {
+            return 0;
+        }
+        break;
+    case RSA_NO_PADDING:
+        if (!RSA_padding_add_none(padded.get(), num, from, flen)) {
+            return 0;
+        }
+        break;
+    default:
+        ALOGE("Unknown padding type: %d", padding);
+        return 0;
+    }
+
+    uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle));
+    if (key_id == NULL) {
+        ALOGE("key had no key_id!");
+        return 0;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    uint8_t* reply = NULL;
+    size_t replyLen;
+    int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), padded.get(),
+            num, &reply, &replyLen);
+    if (ret < 0) {
+        ALOGW("There was an error during signing: could not connect");
+        free(reply);
+        return 0;
+    } else if (ret != 0) {
+        ALOGW("Error during signing from keystore: %d", ret);
+        free(reply);
+        return 0;
+    } else if (replyLen <= 0) {
+        ALOGW("No valid signature returned");
+        return 0;
+    }
+
+    memcpy(to, reply, replyLen);
+    free(reply);
+
+    ALOGV("rsa=%p keystore_rsa_priv_enc => returning %p len %llu", rsa, to,
+            (unsigned long long) replyLen);
+    return static_cast<int>(replyLen);
+}
+
+int keystore_rsa_priv_dec(int flen, const unsigned char* from, unsigned char* to, RSA* rsa,
+        int padding) {
+    ALOGV("keystore_rsa_priv_dec(%d, %p, %p, %p, %d)", flen, from, to, rsa, padding);
+
+    uint8_t* key_id = reinterpret_cast<uint8_t*>(RSA_get_ex_data(rsa, rsa_key_handle));
+    if (key_id == NULL) {
+        ALOGE("key had no key_id!");
+        return 0;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return 0;
+    }
+
+    int num = RSA_size(rsa);
+
+    uint8_t* reply = NULL;
+    size_t replyLen;
+    int32_t ret = service->sign(String16(reinterpret_cast<const char*>(key_id)), from,
+            flen, &reply, &replyLen);
+    if (ret < 0) {
+        ALOGW("There was an error during rsa_mod_exp: could not connect");
+        return 0;
+    } else if (ret != 0) {
+        ALOGW("Error during sign from keystore: %d", ret);
+        return 0;
+    } else if (replyLen <= 0) {
+        ALOGW("No valid signature returned");
+        return 0;
+    }
+
+    /* Trim off the top zero if it's there */
+    uint8_t* alignedReply;
+    if (*reply == 0x00) {
+        alignedReply = reply + 1;
+        replyLen--;
+    } else {
+        alignedReply = reply;
+    }
+
+    int outSize;
+    switch (padding) {
+    case RSA_PKCS1_PADDING:
+        outSize = RSA_padding_check_PKCS1_type_2(to, num, alignedReply, replyLen, num);
+        break;
+    case RSA_X931_PADDING:
+        outSize = RSA_padding_check_X931(to, num, alignedReply, replyLen, num);
+        break;
+    case RSA_NO_PADDING:
+        outSize = RSA_padding_check_none(to, num, alignedReply, replyLen, num);
+        break;
+    default:
+        ALOGE("Unknown padding type: %d", padding);
+        outSize = -1;
+        break;
+    }
+
+    free(reply);
+
+    ALOGV("rsa=%p keystore_rsa_priv_dec => returning %p len %d", rsa, to, outSize);
+    return outSize;
+}
+
+static RSA_METHOD keystore_rsa_meth = {
+        kKeystoreEngineId,
+        NULL, /* rsa_pub_enc (wrap) */
+        NULL, /* rsa_pub_dec (verification) */
+        keystore_rsa_priv_enc, /* rsa_priv_enc (signing) */
+        keystore_rsa_priv_dec, /* rsa_priv_dec (unwrap) */
+        NULL, /* rsa_mod_exp */
+        NULL, /* bn_mod_exp */
+        NULL, /* init */
+        NULL, /* finish */
+        RSA_FLAG_EXT_PKEY | RSA_FLAG_NO_BLINDING, /* flags */
+        NULL, /* app_data */
+        NULL, /* rsa_sign */
+        NULL, /* rsa_verify */
+        NULL, /* rsa_keygen */
+};
+
+static int register_rsa_methods() {
+    const RSA_METHOD* rsa_meth = RSA_PKCS1_SSLeay();
+
+    keystore_rsa_meth.rsa_pub_enc = rsa_meth->rsa_pub_enc;
+    keystore_rsa_meth.rsa_pub_dec = rsa_meth->rsa_pub_dec;
+    keystore_rsa_meth.rsa_mod_exp = rsa_meth->rsa_mod_exp;
+    keystore_rsa_meth.bn_mod_exp = rsa_meth->bn_mod_exp;
+
+    return 1;
+}
+
+int rsa_pkey_setup(ENGINE *e, EVP_PKEY *pkey, const char *key_id) {
+    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
+    if (!RSA_set_ex_data(rsa.get(), rsa_key_handle, reinterpret_cast<void*>(strdup(key_id)))) {
+        ALOGW("Could not set ex_data for loaded RSA key");
+        return 0;
+    }
+
+    RSA_set_method(rsa.get(), &keystore_rsa_meth);
+    RSA_blinding_off(rsa.get());
+
+    /*
+     * "RSA_set_ENGINE()" should probably be an OpenSSL API. Since it isn't,
+     * and EVP_PKEY_free() calls ENGINE_finish(), we need to call ENGINE_init()
+     * here.
+     */
+    ENGINE_init(e);
+    rsa->engine = e;
+    rsa->flags |= RSA_FLAG_EXT_PKEY;
+
+    return 1;
+}
+
+int rsa_register(ENGINE* e) {
+    if (!ENGINE_set_RSA(e, &keystore_rsa_meth)
+            || !register_rsa_methods()) {
+        ALOGE("Could not set up keystore RSA methods");
+        return 0;
+    }
+
+    return 1;
+}
diff --git a/security/keystore/.clang-format b/security/keystore/.clang-format
new file mode 100644
index 0000000..5747e19
--- /dev/null
+++ b/security/keystore/.clang-format
@@ -0,0 +1,10 @@
+BasedOnStyle: LLVM
+IndentWidth: 4
+UseTab: Never
+BreakBeforeBraces: Attach
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+IndentCaseLabels: false
+ColumnLimit: 100
+PointerBindsToType: true
+SpacesBeforeTrailingComments: 2
diff --git a/security/keystore/Android.mk b/security/keystore/Android.mk
new file mode 100644
index 0000000..059bfd4
--- /dev/null
+++ b/security/keystore/Android.mk
@@ -0,0 +1,130 @@
+#
+# Copyright (C) 2009 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)
+
+# This has to be lazy-resolved because it depends on the LOCAL_MODULE_CLASS
+# which varies depending on what is being built.
+define keystore_proto_include
+$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
+endef
+
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
+LOCAL_SRC_FILES := \
+	auth_token_table.cpp \
+	blob.cpp \
+	entropy.cpp \
+	key_store_service.cpp \
+	keyblob_utils.cpp \
+	keystore.cpp \
+	keystore_main.cpp \
+	keystore_utils.cpp \
+	operation.cpp \
+	permissions.cpp \
+	user_state.cpp
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libcutils \
+	libcrypto \
+	libhardware \
+	libkeystore_binder \
+	liblog \
+	libsoftkeymaster \
+	libutils \
+	libselinux \
+	libsoftkeymasterdevice \
+	libkeymaster_messages \
+	libkeymaster1
+LOCAL_MODULE := keystore
+LOCAL_MODULE_TAGS := optional
+LOCAL_INIT_RC := keystore.rc
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror
+LOCAL_SRC_FILES := keystore_cli.cpp
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto libkeystore_binder libutils liblog libbinder
+LOCAL_MODULE := keystore_cli
+LOCAL_MODULE_TAGS := debug
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter -DKEYMASTER_NAME_TAGS
+LOCAL_SRC_FILES := keystore_cli_v2.cpp
+LOCAL_SHARED_LIBRARIES := \
+	libchrome \
+	libkeymaster_messages \
+	libkeystore_binder
+LOCAL_MODULE := keystore_cli_v2
+LOCAL_MODULE_TAGS := debug
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/gtest/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
+# Library for keystore clients
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror
+LOCAL_SRC_FILES := \
+	IKeystoreService.cpp \
+	keyblob_utils.cpp \
+	keystore_client.proto \
+	keystore_client_impl.cpp \
+	keystore_get.cpp
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libkeymaster_messages \
+	liblog \
+	libprotobuf-cpp-lite \
+	libsoftkeymasterdevice \
+	libutils
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE := libkeystore_binder
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(call keystore_proto_include)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_SHARED_LIBRARY)
+
+# Library for unit tests
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror
+LOCAL_SRC_FILES := auth_token_table.cpp
+LOCAL_MODULE := libkeystore_test
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libgtest_main
+LOCAL_SHARED_LIBRARIES := libkeymaster_messages
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_STATIC_LIBRARY)
diff --git a/security/keystore/IKeystoreService.cpp b/security/keystore/IKeystoreService.cpp
new file mode 100644
index 0000000..635d3a7
--- /dev/null
+++ b/security/keystore/IKeystoreService.cpp
@@ -0,0 +1,1847 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdint.h>
+#include <sys/limits.h>
+#include <sys/types.h>
+
+#define LOG_TAG "KeystoreService"
+#include <utils/Log.h>
+
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <keystore/IKeystoreService.h>
+
+namespace android {
+
+const ssize_t MAX_GENERATE_ARGS = 3;
+static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length);
+
+KeystoreArg::KeystoreArg(const void* data, size_t len)
+    : mData(data), mSize(len) {
+}
+
+KeystoreArg::~KeystoreArg() {
+}
+
+const void *KeystoreArg::data() const {
+    return mData;
+}
+
+size_t KeystoreArg::size() const {
+    return mSize;
+}
+
+OperationResult::OperationResult() : resultCode(0), token(), handle(0), inputConsumed(0),
+    data(NULL), dataLength(0) {
+}
+
+OperationResult::~OperationResult() {
+}
+
+void OperationResult::readFromParcel(const Parcel& in) {
+    resultCode = in.readInt32();
+    token = in.readStrongBinder();
+    handle = static_cast<keymaster_operation_handle_t>(in.readInt64());
+    inputConsumed = in.readInt32();
+    ssize_t length = in.readInt32();
+    dataLength = 0;
+    if (length > 0) {
+        const void* buf = in.readInplace(length);
+        if (buf) {
+            data.reset(reinterpret_cast<uint8_t*>(malloc(length)));
+            if (data.get()) {
+                memcpy(data.get(), buf, length);
+                dataLength = (size_t) length;
+            } else {
+                ALOGE("Failed to allocate OperationResult buffer");
+            }
+        } else {
+            ALOGE("Failed to readInplace OperationResult data");
+        }
+    }
+    outParams.readFromParcel(in);
+}
+
+void OperationResult::writeToParcel(Parcel* out) const {
+    out->writeInt32(resultCode);
+    out->writeStrongBinder(token);
+    out->writeInt64(handle);
+    out->writeInt32(inputConsumed);
+    out->writeInt32(dataLength);
+    if (dataLength && data) {
+        void* buf = out->writeInplace(dataLength);
+        if (buf) {
+            memcpy(buf, data.get(), dataLength);
+        } else {
+            ALOGE("Failed to writeInplace OperationResult data.");
+        }
+    }
+    outParams.writeToParcel(out);
+}
+
+ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
+}
+
+ExportResult::~ExportResult() {
+}
+
+void ExportResult::readFromParcel(const Parcel& in) {
+    resultCode = in.readInt32();
+    ssize_t length = in.readInt32();
+    dataLength = 0;
+    if (length > 0) {
+        const void* buf = in.readInplace(length);
+        if (buf) {
+            exportData.reset(reinterpret_cast<uint8_t*>(malloc(length)));
+            if (exportData.get()) {
+                memcpy(exportData.get(), buf, length);
+                dataLength = (size_t) length;
+            } else {
+                ALOGE("Failed to allocate ExportData buffer");
+            }
+        } else {
+            ALOGE("Failed to readInplace ExportData data");
+        }
+    }
+}
+
+void ExportResult::writeToParcel(Parcel* out) const {
+    out->writeInt32(resultCode);
+    out->writeInt32(dataLength);
+    if (exportData && dataLength) {
+        void* buf = out->writeInplace(dataLength);
+        if (buf) {
+            memcpy(buf, exportData.get(), dataLength);
+        } else {
+            ALOGE("Failed to writeInplace ExportResult data.");
+        }
+    }
+}
+
+KeymasterArguments::KeymasterArguments() {
+}
+
+KeymasterArguments::~KeymasterArguments() {
+    keymaster_free_param_values(params.data(), params.size());
+}
+
+void KeymasterArguments::readFromParcel(const Parcel& in) {
+    ssize_t length = in.readInt32();
+    size_t ulength = (size_t) length;
+    if (length < 0) {
+        ulength = 0;
+    }
+    keymaster_free_param_values(params.data(), params.size());
+    params.clear();
+    for(size_t i = 0; i < ulength; i++) {
+        keymaster_key_param_t param;
+        if (!readKeymasterArgumentFromParcel(in, &param)) {
+            ALOGE("Error reading keymaster argument from parcel");
+            break;
+        }
+        params.push_back(param);
+    }
+}
+
+void KeymasterArguments::writeToParcel(Parcel* out) const {
+    out->writeInt32(params.size());
+    for (auto param : params) {
+        out->writeInt32(1);
+        writeKeymasterArgumentToParcel(param, out);
+    }
+}
+
+KeyCharacteristics::KeyCharacteristics() {
+    memset((void*) &characteristics, 0, sizeof(characteristics));
+}
+
+KeyCharacteristics::~KeyCharacteristics() {
+    keymaster_free_characteristics(&characteristics);
+}
+
+void KeyCharacteristics::readFromParcel(const Parcel& in) {
+    size_t length = 0;
+    keymaster_key_param_t* params = readParamList(in, &length);
+    characteristics.sw_enforced.params = params;
+    characteristics.sw_enforced.length = length;
+
+    params = readParamList(in, &length);
+    characteristics.hw_enforced.params = params;
+    characteristics.hw_enforced.length = length;
+}
+
+void KeyCharacteristics::writeToParcel(Parcel* out) const {
+    if (characteristics.sw_enforced.params) {
+        out->writeInt32(characteristics.sw_enforced.length);
+        for (size_t i = 0; i < characteristics.sw_enforced.length; i++) {
+            out->writeInt32(1);
+            writeKeymasterArgumentToParcel(characteristics.sw_enforced.params[i], out);
+        }
+    } else {
+        out->writeInt32(0);
+    }
+    if (characteristics.hw_enforced.params) {
+        out->writeInt32(characteristics.hw_enforced.length);
+        for (size_t i = 0; i < characteristics.hw_enforced.length; i++) {
+            out->writeInt32(1);
+            writeKeymasterArgumentToParcel(characteristics.hw_enforced.params[i], out);
+        }
+    } else {
+        out->writeInt32(0);
+    }
+}
+
+KeymasterCertificateChain::KeymasterCertificateChain() {
+    memset(&chain, 0, sizeof(chain));
+}
+
+KeymasterCertificateChain::~KeymasterCertificateChain() {
+    keymaster_free_cert_chain(&chain);
+}
+
+static bool readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
+    if (in.readInt32() != 1) {
+        return false;
+    }
+
+    ssize_t length = in.readInt32();
+    if (length <= 0) {
+        return false;
+    }
+
+    blob->data = reinterpret_cast<const uint8_t*>(malloc(length));
+    if (!blob->data)
+        return false;
+
+    const void* buf = in.readInplace(length);
+    if (!buf)
+        return false;
+
+    blob->data_length = static_cast<size_t>(length);
+    memcpy(const_cast<uint8_t*>(blob->data), buf, length);
+
+    return true;
+}
+
+void KeymasterCertificateChain::readFromParcel(const Parcel& in) {
+    keymaster_free_cert_chain(&chain);
+
+    ssize_t count = in.readInt32();
+    size_t ucount = count;
+    if (count <= 0) {
+        return;
+    }
+
+    chain.entries = reinterpret_cast<keymaster_blob_t*>(malloc(sizeof(keymaster_blob_t) * ucount));
+    if (!chain.entries) {
+        ALOGE("Error allocating memory for certificate chain");
+        return;
+    }
+
+    memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount);
+    for (size_t i = 0; i < ucount; ++i) {
+        if (!readKeymasterBlob(in, &chain.entries[i])) {
+            ALOGE("Error reading certificate from parcel");
+            keymaster_free_cert_chain(&chain);
+            return;
+        }
+    }
+}
+
+void KeymasterCertificateChain::writeToParcel(Parcel* out) const {
+    out->writeInt32(chain.entry_count);
+    for (size_t i = 0; i < chain.entry_count; ++i) {
+        if (chain.entries[i].data) {
+            out->writeInt32(1); // Tell Java side that object is not NULL
+            out->writeInt32(chain.entries[i].data_length);
+            void* buf = out->writeInplace(chain.entries[i].data_length);
+            if (buf) {
+                memcpy(buf, chain.entries[i].data, chain.entries[i].data_length);
+            } else {
+                ALOGE("Failed to writeInplace keymaster cert chain entry");
+            }
+        } else {
+            out->writeInt32(0); // Tell Java side this object is NULL.
+            ALOGE("Found NULL certificate chain entry");
+        }
+    }
+}
+
+void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out) {
+    switch (keymaster_tag_get_type(param.tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP: {
+            out->writeInt32(param.tag);
+            out->writeInt32(param.enumerated);
+            break;
+        }
+        case KM_UINT:
+        case KM_UINT_REP: {
+            out->writeInt32(param.tag);
+            out->writeInt32(param.integer);
+            break;
+        }
+        case KM_ULONG:
+        case KM_ULONG_REP: {
+            out->writeInt32(param.tag);
+            out->writeInt64(param.long_integer);
+            break;
+        }
+        case KM_DATE: {
+            out->writeInt32(param.tag);
+            out->writeInt64(param.date_time);
+            break;
+        }
+        case KM_BOOL: {
+            out->writeInt32(param.tag);
+            break;
+        }
+        case KM_BIGNUM:
+        case KM_BYTES: {
+            out->writeInt32(param.tag);
+            out->writeInt32(param.blob.data_length);
+            void* buf = out->writeInplace(param.blob.data_length);
+            if (buf) {
+                memcpy(buf, param.blob.data, param.blob.data_length);
+            } else {
+                ALOGE("Failed to writeInplace keymaster blob param");
+            }
+            break;
+        }
+        default: {
+            ALOGE("Failed to write argument: Unsupported keymaster_tag_t %d", param.tag);
+        }
+    }
+}
+
+
+bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out) {
+    if (in.readInt32() == 0) {
+        return false;
+    }
+    keymaster_tag_t tag = static_cast<keymaster_tag_t>(in.readInt32());
+    switch (keymaster_tag_get_type(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP: {
+            uint32_t value = in.readInt32();
+            *out = keymaster_param_enum(tag, value);
+            break;
+        }
+        case KM_UINT:
+        case KM_UINT_REP: {
+            uint32_t value = in.readInt32();
+            *out = keymaster_param_int(tag, value);
+            break;
+        }
+        case KM_ULONG:
+        case KM_ULONG_REP: {
+            uint64_t value = in.readInt64();
+            *out = keymaster_param_long(tag, value);
+            break;
+        }
+        case KM_DATE: {
+            uint64_t value = in.readInt64();
+            *out = keymaster_param_date(tag, value);
+            break;
+        }
+        case KM_BOOL: {
+            *out = keymaster_param_bool(tag);
+            break;
+        }
+        case KM_BIGNUM:
+        case KM_BYTES: {
+            ssize_t length = in.readInt32();
+            uint8_t* data = NULL;
+            size_t ulength = 0;
+            if (length >= 0) {
+                ulength = (size_t) length;
+                // use malloc here so we can use keymaster_free_param_values
+                // consistently.
+                data = reinterpret_cast<uint8_t*>(malloc(ulength));
+                const void* buf = in.readInplace(ulength);
+                if (!buf || !data) {
+                    ALOGE("Failed to allocate buffer for keymaster blob param");
+                    free(data);
+                    return false;
+                }
+                memcpy(data, buf, ulength);
+            }
+            *out = keymaster_param_blob(tag, data, ulength);
+            break;
+        }
+        default: {
+            ALOGE("Unsupported keymaster_tag_t %d", tag);
+            return false;
+        }
+    }
+    return true;
+}
+
+/**
+ * Read a byte array from in. The data at *data is still owned by the parcel
+ */
+static void readByteArray(const Parcel& in, const uint8_t** data, size_t* length) {
+    ssize_t slength = in.readInt32();
+    if (slength > 0) {
+        *data = reinterpret_cast<const uint8_t*>(in.readInplace(slength));
+        if (*data) {
+            *length = static_cast<size_t>(slength);
+        } else {
+            *length = 0;
+        }
+    } else {
+        *data = NULL;
+        *length = 0;
+    }
+}
+
+// Read a keymaster_key_param_t* from a Parcel for use in a
+// keymaster_key_characteristics_t. This will be free'd by calling
+// keymaster_free_key_characteristics.
+static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length) {
+    ssize_t slength = in.readInt32();
+    *length = 0;
+    if (slength < 0) {
+        return NULL;
+    }
+    *length = (size_t) slength;
+    if (*length >= UINT_MAX / sizeof(keymaster_key_param_t)) {
+        return NULL;
+    }
+    keymaster_key_param_t* list =
+            reinterpret_cast<keymaster_key_param_t*>(malloc(*length *
+                                                            sizeof(keymaster_key_param_t)));
+    if (!list) {
+        ALOGD("Failed to allocate buffer for generateKey outCharacteristics");
+        goto err;
+    }
+    for (size_t i = 0; i < *length ; i++) {
+        if (!readKeymasterArgumentFromParcel(in, &list[i])) {
+            ALOGE("Failed to read keymaster argument");
+            keymaster_free_param_values(list, i);
+            goto err;
+        }
+    }
+    return list;
+err:
+    free(list);
+    return NULL;
+}
+
+static std::unique_ptr<keymaster_blob_t> readKeymasterBlob(const Parcel& in) {
+    std::unique_ptr<keymaster_blob_t> blob (new keymaster_blob_t);
+    if (!readKeymasterBlob(in, blob.get())) {
+        blob.reset();
+    }
+    return blob;
+}
+
+class BpKeystoreService: public BpInterface<IKeystoreService>
+{
+public:
+    explicit BpKeystoreService(const sp<IBinder>& impl)
+        : BpInterface<IKeystoreService>(impl)
+    {
+    }
+
+    // test ping
+    virtual int32_t getState(int32_t userId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        status_t status = remote()->transact(BnKeystoreService::GET_STATE, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("getState() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("getState() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t get(const String16& name, uint8_t** item, size_t* itemLength)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("get() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        ssize_t len = reply.readInt32();
+        if (len >= 0 && (size_t) len <= reply.dataAvail()) {
+            size_t ulen = (size_t) len;
+            const void* buf = reply.readInplace(ulen);
+            *item = (uint8_t*) malloc(ulen);
+            if (*item != NULL) {
+                memcpy(*item, buf, ulen);
+                *itemLength = ulen;
+            } else {
+                ALOGE("out of memory allocating output array in get");
+                *itemLength = 0;
+            }
+        } else {
+            *itemLength = 0;
+        }
+        if (err < 0) {
+            ALOGD("get() caught exception %d\n", err);
+            return -1;
+        }
+        return 0;
+    }
+
+    virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
+            int32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(itemLength);
+        void* buf = data.writeInplace(itemLength);
+        memcpy(buf, item, itemLength);
+        data.writeInt32(uid);
+        data.writeInt32(flags);
+        status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("import() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("import() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t del(const String16& name, int uid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(uid);
+        status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("del() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("del() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t exist(const String16& name, int uid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(uid);
+        status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("exist() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("exist() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(prefix);
+        data.writeInt32(uid);
+        status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("list() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t numMatches = reply.readInt32();
+        for (int32_t i = 0; i < numMatches; i++) {
+            matches->push(reply.readString16());
+        }
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("list() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t reset()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("reset() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("reset() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t onUserPasswordChanged(int32_t userId, const String16& password)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        data.writeString16(password);
+        status_t status = remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data,
+                                             &reply);
+        if (status != NO_ERROR) {
+            ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("onUserPasswordChanged() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t lock(int32_t userId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("lock() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("lock() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t unlock(int32_t userId, const String16& password)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        data.writeString16(password);
+        status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("unlock() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("unlock() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual bool isEmpty(int32_t userId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        status_t status = remote()->transact(BnKeystoreService::IS_EMPTY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("isEmpty() could not contact remote: %d\n", status);
+            return false;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("isEmpty() caught exception %d\n", err);
+            return false;
+        }
+        return ret != 0;
+    }
+
+    virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
+            int32_t flags, Vector<sp<KeystoreArg> >* args)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(uid);
+        data.writeInt32(keyType);
+        data.writeInt32(keySize);
+        data.writeInt32(flags);
+        data.writeInt32(1);
+        data.writeInt32(args->size());
+        for (Vector<sp<KeystoreArg> >::iterator it = args->begin(); it != args->end(); ++it) {
+            sp<KeystoreArg> item = *it;
+            size_t keyLength = item->size();
+            data.writeInt32(keyLength);
+            void* buf = data.writeInplace(keyLength);
+            memcpy(buf, item->data(), keyLength);
+        }
+        status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("generate() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("generate() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength, int uid,
+            int flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(keyLength);
+        void* buf = data.writeInplace(keyLength);
+        memcpy(buf, key, keyLength);
+        data.writeInt32(uid);
+        data.writeInt32(flags);
+        status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("import() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("import() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out,
+            size_t* outLength)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(inLength);
+        void* buf = data.writeInplace(inLength);
+        memcpy(buf, in, inLength);
+        status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("import() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        ssize_t len = reply.readInt32();
+        if (len >= 0 && (size_t) len <= reply.dataAvail()) {
+            size_t ulen = (size_t) len;
+            const void* outBuf = reply.readInplace(ulen);
+            *out = (uint8_t*) malloc(ulen);
+            if (*out != NULL) {
+                memcpy((void*) *out, outBuf, ulen);
+                *outLength = ulen;
+            } else {
+                ALOGE("out of memory allocating output array in sign");
+                *outLength = 0;
+            }
+        } else {
+            *outLength = 0;
+        }
+        if (err < 0) {
+            ALOGD("import() caught exception %d\n", err);
+            return -1;
+        }
+        return 0;
+    }
+
+    virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength,
+            const uint8_t* signature, size_t signatureLength)
+    {
+        Parcel data, reply;
+        void* buf;
+
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(inLength);
+        buf = data.writeInplace(inLength);
+        memcpy(buf, in, inLength);
+        data.writeInt32(signatureLength);
+        buf = data.writeInplace(signatureLength);
+        memcpy(buf, signature, signatureLength);
+        status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("verify() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("verify() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("get_pubkey() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        ssize_t len = reply.readInt32();
+        if (len >= 0 && (size_t) len <= reply.dataAvail()) {
+            size_t ulen = (size_t) len;
+            const void* buf = reply.readInplace(ulen);
+            *pubkey = (uint8_t*) malloc(ulen);
+            if (*pubkey != NULL) {
+                memcpy(*pubkey, buf, ulen);
+                *pubkeyLength = ulen;
+            } else {
+                ALOGE("out of memory allocating output array in get_pubkey");
+                *pubkeyLength = 0;
+            }
+        } else {
+            *pubkeyLength = 0;
+        }
+        if (err < 0) {
+            ALOGD("get_pubkey() caught exception %d\n", err);
+            return -1;
+        }
+        return 0;
+     }
+
+    virtual int32_t grant(const String16& name, int32_t granteeUid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(granteeUid);
+        status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("grant() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("grant() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t ungrant(const String16& name, int32_t granteeUid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(granteeUid);
+        status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("ungrant() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("ungrant() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    int64_t getmtime(const String16& name)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("getmtime() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int64_t ret = reply.readInt64();
+        if (err < 0) {
+            ALOGD("getmtime() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
+            int32_t destUid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(srcKey);
+        data.writeInt32(srcUid);
+        data.writeString16(destKey);
+        data.writeInt32(destUid);
+        status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("duplicate() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("duplicate() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t is_hardware_backed(const String16& keyType)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(keyType);
+        status_t status = remote()->transact(BnKeystoreService::IS_HARDWARE_BACKED, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("is_hardware_backed() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("is_hardware_backed() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t clear_uid(int64_t uid)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt64(uid);
+        status_t status = remote()->transact(BnKeystoreService::CLEAR_UID, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("clear_uid() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("clear_uid() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeByteArray(bufLength, buf);
+        status_t status = remote()->transact(BnKeystoreService::ADD_RNG_ENTROPY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("addRngEntropy() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("addRngEntropy() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    };
+
+    virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
+                                const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+                                KeyCharacteristics* outCharacteristics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(1);
+        params.writeToParcel(&data);
+        data.writeByteArray(entropyLength, entropy);
+        data.writeInt32(uid);
+        data.writeInt32(flags);
+        status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("generateKey() could not contact remote: %d\n", status);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("generateKey() caught exception %d\n", err);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        if (reply.readInt32() != 0 && outCharacteristics) {
+            outCharacteristics->readFromParcel(reply);
+        }
+        return ret;
+    }
+    virtual int32_t getKeyCharacteristics(const String16& name,
+                                          const keymaster_blob_t* clientId,
+                                          const keymaster_blob_t* appData,
+                                          KeyCharacteristics* outCharacteristics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        if (clientId) {
+            data.writeByteArray(clientId->data_length, clientId->data);
+        } else {
+            data.writeInt32(-1);
+        }
+        if (appData) {
+            data.writeByteArray(appData->data_length, appData->data);
+        } else {
+            data.writeInt32(-1);
+        }
+        status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
+                                             data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("getKeyCharacteristics() could not contact remote: %d\n", status);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("getKeyCharacteristics() caught exception %d\n", err);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        if (reply.readInt32() != 0 && outCharacteristics) {
+            outCharacteristics->readFromParcel(reply);
+        }
+        return ret;
+    }
+    virtual int32_t importKey(const String16& name, const KeymasterArguments&  params,
+                              keymaster_key_format_t format, const uint8_t *keyData,
+                              size_t keyLength, int uid, int flags,
+                              KeyCharacteristics* outCharacteristics)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(1);
+        params.writeToParcel(&data);
+        data.writeInt32(format);
+        data.writeByteArray(keyLength, keyData);
+        data.writeInt32(uid);
+        data.writeInt32(flags);
+        status_t status = remote()->transact(BnKeystoreService::IMPORT_KEY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("importKey() could not contact remote: %d\n", status);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("importKey() caught exception %d\n", err);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        if (reply.readInt32() != 0 && outCharacteristics) {
+            outCharacteristics->readFromParcel(reply);
+        }
+        return ret;
+    }
+
+    virtual void exportKey(const String16& name, keymaster_key_format_t format,
+                           const keymaster_blob_t* clientId,
+                           const keymaster_blob_t* appData, ExportResult* result)
+    {
+        if (!result) {
+            return;
+        }
+
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(format);
+        if (clientId) {
+            data.writeByteArray(clientId->data_length, clientId->data);
+        } else {
+            data.writeInt32(-1);
+        }
+        if (appData) {
+            data.writeByteArray(appData->data_length, appData->data);
+        } else {
+            data.writeInt32(-1);
+        }
+        status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("exportKey() could not contact remote: %d\n", status);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        int32_t err = reply.readExceptionCode();
+        if (err < 0) {
+            ALOGD("exportKey() caught exception %d\n", err);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual void begin(const sp<IBinder>& appToken, const String16& name,
+                       keymaster_purpose_t purpose, bool pruneable,
+                       const KeymasterArguments& params, const uint8_t* entropy,
+                       size_t entropyLength, OperationResult* result)
+    {
+        if (!result) {
+            return;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeStrongBinder(appToken);
+        data.writeString16(name);
+        data.writeInt32(purpose);
+        data.writeInt32(pruneable ? 1 : 0);
+        data.writeInt32(1);
+        params.writeToParcel(&data);
+        data.writeByteArray(entropyLength, entropy);
+        status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("begin() could not contact remote: %d\n", status);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        int32_t err = reply.readExceptionCode();
+        if (err < 0) {
+            ALOGD("begin() caught exception %d\n", err);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
+                        const uint8_t* opData, size_t dataLength, OperationResult* result)
+    {
+        if (!result) {
+            return;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        data.writeInt32(1);
+        params.writeToParcel(&data);
+        data.writeByteArray(dataLength, opData);
+        status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("update() could not contact remote: %d\n", status);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        int32_t err = reply.readExceptionCode();
+        if (err < 0) {
+            ALOGD("update() caught exception %d\n", err);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                        const uint8_t* signature, size_t signatureLength,
+                        const uint8_t* entropy, size_t entropyLength,
+                        OperationResult* result)
+    {
+        if (!result) {
+            return;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        data.writeInt32(1);
+        params.writeToParcel(&data);
+        data.writeByteArray(signatureLength, signature);
+        data.writeByteArray(entropyLength, entropy);
+        status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("finish() could not contact remote: %d\n", status);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        int32_t err = reply.readExceptionCode();
+        if (err < 0) {
+            ALOGD("finish() caught exception %d\n", err);
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+        if (reply.readInt32() != 0) {
+            result->readFromParcel(reply);
+        }
+    }
+
+    virtual int32_t abort(const sp<IBinder>& token)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        status_t status = remote()->transact(BnKeystoreService::ABORT, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("abort() could not contact remote: %d\n", status);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("abort() caught exception %d\n", err);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        return ret;
+    }
+
+    virtual bool isOperationAuthorized(const sp<IBinder>& token)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        status_t status = remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data,
+                                             &reply);
+        if (status != NO_ERROR) {
+            ALOGD("isOperationAuthorized() could not contact remote: %d\n", status);
+            return false;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("isOperationAuthorized() caught exception %d\n", err);
+            return false;
+        }
+        return ret == 1;
+    }
+
+    virtual int32_t addAuthToken(const uint8_t* token, size_t length)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeByteArray(length, token);
+        status_t status = remote()->transact(BnKeystoreService::ADD_AUTH_TOKEN, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("addAuthToken() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("addAuthToken() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    };
+
+    virtual int32_t onUserAdded(int32_t userId, int32_t parentId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        data.writeInt32(parentId);
+        status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("onUserAdded() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("onUserAdded() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t onUserRemoved(int32_t userId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeInt32(userId);
+        status_t status = remote()->transact(BnKeystoreService::ON_USER_REMOVED, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("onUserRemoved() could not contact remote: %d\n", status);
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("onUserRemoved() caught exception %d\n", err);
+            return -1;
+        }
+        return ret;
+    }
+
+    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
+                              KeymasterCertificateChain* outChain) {
+        if (!outChain)
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(1);  // params is not NULL.
+        params.writeToParcel(&data);
+
+        status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("attestkey() count not contact remote: %d\n", status);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("attestKey() caught exception %d\n", err);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        if (reply.readInt32() != 0) {
+            outChain->readFromParcel(reply);
+        }
+        return ret;
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
+
+// ----------------------------------------------------------------------
+
+status_t BnKeystoreService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case GET_STATE: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            int32_t ret = getState(userId);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case GET: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            void* out = NULL;
+            size_t outSize = 0;
+            int32_t ret = get(name, (uint8_t**) &out, &outSize);
+            reply->writeNoException();
+            if (ret == 1) {
+                reply->writeInt32(outSize);
+                void* buf = reply->writeInplace(outSize);
+                memcpy(buf, out, outSize);
+                free(out);
+            } else {
+                reply->writeInt32(-1);
+            }
+            return NO_ERROR;
+        } break;
+        case INSERT: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            ssize_t inSize = data.readInt32();
+            const void* in;
+            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
+                in = data.readInplace(inSize);
+            } else {
+                in = NULL;
+                inSize = 0;
+            }
+            int uid = data.readInt32();
+            int32_t flags = data.readInt32();
+            int32_t ret = insert(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case DEL: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            int uid = data.readInt32();
+            int32_t ret = del(name, uid);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case EXIST: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            int uid = data.readInt32();
+            int32_t ret = exist(name, uid);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case LIST: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 prefix = data.readString16();
+            int uid = data.readInt32();
+            Vector<String16> matches;
+            int32_t ret = list(prefix, uid, &matches);
+            reply->writeNoException();
+            reply->writeInt32(matches.size());
+            Vector<String16>::const_iterator it = matches.begin();
+            for (; it != matches.end(); ++it) {
+                reply->writeString16(*it);
+            }
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case RESET: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t ret = reset();
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case ON_USER_PASSWORD_CHANGED: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            String16 pass = data.readString16();
+            int32_t ret = onUserPasswordChanged(userId, pass);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case LOCK: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            int32_t ret = lock(userId);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case UNLOCK: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            String16 pass = data.readString16();
+            int32_t ret = unlock(userId, pass);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case IS_EMPTY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            bool ret = isEmpty(userId);
+            reply->writeNoException();
+            reply->writeInt32(ret ? 1 : 0);
+            return NO_ERROR;
+        } break;
+        case GENERATE: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            int32_t uid = data.readInt32();
+            int32_t keyType = data.readInt32();
+            int32_t keySize = data.readInt32();
+            int32_t flags = data.readInt32();
+            Vector<sp<KeystoreArg> > args;
+            int32_t argsPresent = data.readInt32();
+            if (argsPresent == 1) {
+                ssize_t numArgs = data.readInt32();
+                if (numArgs > MAX_GENERATE_ARGS) {
+                    return BAD_VALUE;
+                }
+                if (numArgs > 0) {
+                    for (size_t i = 0; i < (size_t) numArgs; i++) {
+                        ssize_t inSize = data.readInt32();
+                        if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
+                            sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize),
+                                                                  inSize);
+                            args.push_back(arg);
+                        } else {
+                            args.push_back(NULL);
+                        }
+                    }
+                }
+            }
+            int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case IMPORT: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            ssize_t inSize = data.readInt32();
+            const void* in;
+            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
+                in = data.readInplace(inSize);
+            } else {
+                in = NULL;
+                inSize = 0;
+            }
+            int uid = data.readInt32();
+            int32_t flags = data.readInt32();
+            int32_t ret = import(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case SIGN: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            ssize_t inSize = data.readInt32();
+            const void* in;
+            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
+                in = data.readInplace(inSize);
+            } else {
+                in = NULL;
+                inSize = 0;
+            }
+            void* out = NULL;
+            size_t outSize = 0;
+            int32_t ret = sign(name, (const uint8_t*) in, (size_t) inSize, (uint8_t**) &out, &outSize);
+            reply->writeNoException();
+            if (outSize > 0 && out != NULL) {
+                reply->writeInt32(outSize);
+                void* buf = reply->writeInplace(outSize);
+                memcpy(buf, out, outSize);
+                delete[] reinterpret_cast<uint8_t*>(out);
+            } else {
+                reply->writeInt32(-1);
+            }
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case VERIFY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            ssize_t inSize = data.readInt32();
+            const void* in;
+            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
+                in = data.readInplace(inSize);
+            } else {
+                in = NULL;
+                inSize = 0;
+            }
+            ssize_t sigSize = data.readInt32();
+            const void* sig;
+            if (sigSize >= 0 && (size_t) sigSize <= data.dataAvail()) {
+                sig = data.readInplace(sigSize);
+            } else {
+                sig = NULL;
+                sigSize = 0;
+            }
+            bool ret = verify(name, (const uint8_t*) in, (size_t) inSize, (const uint8_t*) sig,
+                    (size_t) sigSize);
+            reply->writeNoException();
+            reply->writeInt32(ret ? 1 : 0);
+            return NO_ERROR;
+        } break;
+        case GET_PUBKEY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            void* out = NULL;
+            size_t outSize = 0;
+            int32_t ret = get_pubkey(name, (unsigned char**) &out, &outSize);
+            reply->writeNoException();
+            if (outSize > 0 && out != NULL) {
+                reply->writeInt32(outSize);
+                void* buf = reply->writeInplace(outSize);
+                memcpy(buf, out, outSize);
+                free(out);
+            } else {
+                reply->writeInt32(-1);
+            }
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case GRANT: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            int32_t granteeUid = data.readInt32();
+            int32_t ret = grant(name, granteeUid);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case UNGRANT: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            int32_t granteeUid = data.readInt32();
+            int32_t ret = ungrant(name, granteeUid);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case GETMTIME: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            int64_t ret = getmtime(name);
+            reply->writeNoException();
+            reply->writeInt64(ret);
+            return NO_ERROR;
+        } break;
+        case DUPLICATE: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 srcKey = data.readString16();
+            int32_t srcUid = data.readInt32();
+            String16 destKey = data.readString16();
+            int32_t destUid = data.readInt32();
+            int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        } break;
+        case IS_HARDWARE_BACKED: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 keyType = data.readString16();
+            int32_t ret = is_hardware_backed(keyType);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        }
+        case CLEAR_UID: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int64_t uid = data.readInt64();
+            int32_t ret = clear_uid(uid);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        }
+        case ADD_RNG_ENTROPY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            const uint8_t* bytes = NULL;
+            size_t size = 0;
+            readByteArray(data, &bytes, &size);
+            int32_t ret = addRngEntropy(bytes, size);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            return NO_ERROR;
+        }
+        case GENERATE_KEY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            const uint8_t* entropy = NULL;
+            size_t entropyLength = 0;
+            readByteArray(data, &entropy, &entropyLength);
+            int32_t uid = data.readInt32();
+            int32_t flags = data.readInt32();
+            KeyCharacteristics outCharacteristics;
+            int32_t ret = generateKey(name, args, entropy, entropyLength, uid, flags,
+                                      &outCharacteristics);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            reply->writeInt32(1);
+            outCharacteristics.writeToParcel(reply);
+            return NO_ERROR;
+        }
+        case GET_KEY_CHARACTERISTICS: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
+            std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
+            KeyCharacteristics outCharacteristics;
+            int ret = getKeyCharacteristics(name, clientId.get(), appData.get(),
+                                            &outCharacteristics);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            reply->writeInt32(1);
+            outCharacteristics.writeToParcel(reply);
+            return NO_ERROR;
+        }
+        case IMPORT_KEY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
+            const uint8_t* keyData = NULL;
+            size_t keyLength = 0;
+            readByteArray(data, &keyData, &keyLength);
+            int32_t uid = data.readInt32();
+            int32_t flags = data.readInt32();
+            KeyCharacteristics outCharacteristics;
+            int32_t ret = importKey(name, args, format, keyData, keyLength, uid, flags,
+                                    &outCharacteristics);
+            reply->writeNoException();
+            reply->writeInt32(ret);
+            reply->writeInt32(1);
+            outCharacteristics.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case EXPORT_KEY: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            String16 name = data.readString16();
+            keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
+            std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
+            std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
+            ExportResult result;
+            exportKey(name, format, clientId.get(), appData.get(), &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case BEGIN: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            String16 name = data.readString16();
+            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(data.readInt32());
+            bool pruneable = data.readInt32() != 0;
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            const uint8_t* entropy = NULL;
+            size_t entropyLength = 0;
+            readByteArray(data, &entropy, &entropyLength);
+            OperationResult result;
+            begin(token, name, purpose, pruneable, args, entropy, entropyLength, &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case UPDATE: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            const uint8_t* buf = NULL;
+            size_t bufLength = 0;
+            readByteArray(data, &buf, &bufLength);
+            OperationResult result;
+            update(token, args, buf, bufLength, &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case FINISH: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            KeymasterArguments args;
+            if (data.readInt32() != 0) {
+                args.readFromParcel(data);
+            }
+            const uint8_t* signature = NULL;
+            size_t signatureLength = 0;
+            readByteArray(data, &signature, &signatureLength);
+            const uint8_t* entropy = NULL;
+            size_t entropyLength = 0;
+            readByteArray(data, &entropy, &entropyLength);
+            OperationResult result;
+            finish(token, args, signature, signatureLength, entropy, entropyLength,  &result);
+            reply->writeNoException();
+            reply->writeInt32(1);
+            result.writeToParcel(reply);
+
+            return NO_ERROR;
+        }
+        case ABORT: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            int32_t result = abort(token);
+            reply->writeNoException();
+            reply->writeInt32(result);
+
+            return NO_ERROR;
+        }
+        case IS_OPERATION_AUTHORIZED: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            bool result = isOperationAuthorized(token);
+            reply->writeNoException();
+            reply->writeInt32(result ? 1 : 0);
+
+            return NO_ERROR;
+        }
+        case ADD_AUTH_TOKEN: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            const uint8_t* token_bytes = NULL;
+            size_t size = 0;
+            readByteArray(data, &token_bytes, &size);
+            int32_t result = addAuthToken(token_bytes, size);
+            reply->writeNoException();
+            reply->writeInt32(result);
+
+            return NO_ERROR;
+        }
+        case ON_USER_ADDED: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            int32_t parentId = data.readInt32();
+            int32_t result = onUserAdded(userId, parentId);
+            reply->writeNoException();
+            reply->writeInt32(result);
+
+            return NO_ERROR;
+        }
+        case ON_USER_REMOVED: {
+            CHECK_INTERFACE(IKeystoreService, data, reply);
+            int32_t userId = data.readInt32();
+            int32_t result = onUserRemoved(userId);
+            reply->writeNoException();
+            reply->writeInt32(result);
+
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/security/keystore/auth_token_table.cpp b/security/keystore/auth_token_table.cpp
new file mode 100644
index 0000000..c6e5843
--- /dev/null
+++ b/security/keystore/auth_token_table.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+#include "auth_token_table.h"
+
+#include <assert.h>
+#include <time.h>
+
+#include <algorithm>
+
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/logger.h>
+
+namespace keymaster {
+
+//
+// Some trivial template wrappers around std algorithms, so they take containers not ranges.
+//
+template <typename Container, typename Predicate>
+typename Container::iterator find_if(Container& container, Predicate pred) {
+    return std::find_if(container.begin(), container.end(), pred);
+}
+
+template <typename Container, typename Predicate>
+typename Container::iterator remove_if(Container& container, Predicate pred) {
+    return std::remove_if(container.begin(), container.end(), pred);
+}
+
+template <typename Container> typename Container::iterator min_element(Container& container) {
+    return std::min_element(container.begin(), container.end());
+}
+
+time_t clock_gettime_raw() {
+    struct timespec time;
+    clock_gettime(CLOCK_MONOTONIC_RAW, &time);
+    return time.tv_sec;
+}
+
+void AuthTokenTable::AddAuthenticationToken(const hw_auth_token_t* auth_token) {
+    Entry new_entry(auth_token, clock_function_());
+    RemoveEntriesSupersededBy(new_entry);
+    if (entries_.size() >= max_entries_) {
+        LOG_W("Auth token table filled up; replacing oldest entry", 0);
+        *min_element(entries_) = std::move(new_entry);
+    } else {
+        entries_.push_back(std::move(new_entry));
+    }
+}
+
+inline bool is_secret_key_operation(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose) {
+    if ((algorithm != KM_ALGORITHM_RSA || algorithm != KM_ALGORITHM_EC))
+        return true;
+    if (purpose == KM_PURPOSE_SIGN || purpose == KM_PURPOSE_DECRYPT)
+        return true;
+    return false;
+}
+
+inline bool KeyRequiresAuthentication(const AuthorizationSet& key_info,
+                                      keymaster_purpose_t purpose) {
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+    key_info.GetTagValue(TAG_ALGORITHM, &algorithm);
+    return is_secret_key_operation(algorithm, purpose) && key_info.find(TAG_NO_AUTH_REQUIRED) == -1;
+}
+
+inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info,
+                                        keymaster_purpose_t purpose) {
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+    key_info.GetTagValue(TAG_ALGORITHM, &algorithm);
+    return is_secret_key_operation(algorithm, purpose) && key_info.find(TAG_AUTH_TIMEOUT) == -1;
+}
+
+AuthTokenTable::Error AuthTokenTable::FindAuthorization(const AuthorizationSet& key_info,
+                                                        keymaster_purpose_t purpose,
+                                                        keymaster_operation_handle_t op_handle,
+                                                        const hw_auth_token_t** found) {
+    if (!KeyRequiresAuthentication(key_info, purpose))
+        return AUTH_NOT_REQUIRED;
+
+    hw_authenticator_type_t auth_type = HW_AUTH_NONE;
+    key_info.GetTagValue(TAG_USER_AUTH_TYPE, &auth_type);
+
+    std::vector<uint64_t> key_sids;
+    ExtractSids(key_info, &key_sids);
+
+    if (KeyRequiresAuthPerOperation(key_info, purpose))
+        return FindAuthPerOpAuthorization(key_sids, auth_type, op_handle, found);
+    else
+        return FindTimedAuthorization(key_sids, auth_type, key_info, found);
+}
+
+AuthTokenTable::Error AuthTokenTable::FindAuthPerOpAuthorization(
+    const std::vector<uint64_t>& sids, hw_authenticator_type_t auth_type,
+    keymaster_operation_handle_t op_handle, const hw_auth_token_t** found) {
+    if (op_handle == 0)
+        return OP_HANDLE_REQUIRED;
+
+    auto matching_op = find_if(
+        entries_, [&](Entry& e) { return e.token()->challenge == op_handle && !e.completed(); });
+
+    if (matching_op == entries_.end())
+        return AUTH_TOKEN_NOT_FOUND;
+
+    if (!matching_op->SatisfiesAuth(sids, auth_type))
+        return AUTH_TOKEN_WRONG_SID;
+
+    *found = matching_op->token();
+    return OK;
+}
+
+AuthTokenTable::Error AuthTokenTable::FindTimedAuthorization(const std::vector<uint64_t>& sids,
+                                                             hw_authenticator_type_t auth_type,
+                                                             const AuthorizationSet& key_info,
+                                                             const hw_auth_token_t** found) {
+    Entry* newest_match = NULL;
+    for (auto& entry : entries_)
+        if (entry.SatisfiesAuth(sids, auth_type) && entry.is_newer_than(newest_match))
+            newest_match = &entry;
+
+    if (!newest_match)
+        return AUTH_TOKEN_NOT_FOUND;
+
+    uint32_t timeout;
+    key_info.GetTagValue(TAG_AUTH_TIMEOUT, &timeout);
+    time_t now = clock_function_();
+    if (static_cast<int64_t>(newest_match->time_received()) + timeout < static_cast<int64_t>(now))
+        return AUTH_TOKEN_EXPIRED;
+
+    newest_match->UpdateLastUse(now);
+    *found = newest_match->token();
+    return OK;
+}
+
+void AuthTokenTable::ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids) {
+    assert(sids);
+    for (auto& param : key_info)
+        if (param.tag == TAG_USER_SECURE_ID)
+            sids->push_back(param.long_integer);
+}
+
+void AuthTokenTable::RemoveEntriesSupersededBy(const Entry& entry) {
+    entries_.erase(remove_if(entries_, [&](Entry& e) { return entry.Supersedes(e); }),
+                   entries_.end());
+}
+
+void AuthTokenTable::Clear() {
+    entries_.clear();
+}
+
+bool AuthTokenTable::IsSupersededBySomeEntry(const Entry& entry) {
+    return std::any_of(entries_.begin(), entries_.end(),
+                       [&](Entry& e) { return e.Supersedes(entry); });
+}
+
+void AuthTokenTable::MarkCompleted(const keymaster_operation_handle_t op_handle) {
+    auto found = find_if(entries_, [&](Entry& e) { return e.token()->challenge == op_handle; });
+    if (found == entries_.end())
+        return;
+
+    assert(!IsSupersededBySomeEntry(*found));
+    found->mark_completed();
+
+    if (IsSupersededBySomeEntry(*found))
+        entries_.erase(found);
+}
+
+AuthTokenTable::Entry::Entry(const hw_auth_token_t* token, time_t current_time)
+    : token_(token), time_received_(current_time), last_use_(current_time),
+      operation_completed_(token_->challenge == 0) {
+}
+
+uint32_t AuthTokenTable::Entry::timestamp_host_order() const {
+    return ntoh(token_->timestamp);
+}
+
+hw_authenticator_type_t AuthTokenTable::Entry::authenticator_type() const {
+    hw_authenticator_type_t result = static_cast<hw_authenticator_type_t>(
+        ntoh(static_cast<uint32_t>(token_->authenticator_type)));
+    return result;
+}
+
+bool AuthTokenTable::Entry::SatisfiesAuth(const std::vector<uint64_t>& sids,
+                                          hw_authenticator_type_t auth_type) {
+    for (auto sid : sids)
+        if ((sid == token_->authenticator_id) ||
+            (sid == token_->user_id && (auth_type & authenticator_type()) != 0))
+            return true;
+    return false;
+}
+
+void AuthTokenTable::Entry::UpdateLastUse(time_t time) {
+    this->last_use_ = time;
+}
+
+bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const {
+    if (!entry.completed())
+        return false;
+
+    return (token_->user_id == entry.token_->user_id &&
+            token_->authenticator_type == entry.token_->authenticator_type &&
+            token_->authenticator_type == entry.token_->authenticator_type &&
+            timestamp_host_order() > entry.timestamp_host_order());
+}
+
+}  // namespace keymaster
diff --git a/security/keystore/auth_token_table.h b/security/keystore/auth_token_table.h
new file mode 100644
index 0000000..bcf88fd
--- /dev/null
+++ b/security/keystore/auth_token_table.h
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+#include <memory>
+#include <vector>
+
+#include <hardware/hw_auth_token.h>
+#include <keymaster/authorization_set.h>
+
+#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
+#define KEYSTORE_AUTH_TOKEN_TABLE_H_
+
+namespace keymaster {
+
+namespace test {
+class AuthTokenTableTest;
+}  // namespace test
+
+time_t clock_gettime_raw();
+
+/**
+ * AuthTokenTable manages a set of received authorization tokens and can provide the appropriate
+ * token for authorizing a key operation.
+ *
+ * To keep the table from growing without bound, superseded entries are removed when possible, and
+ * least recently used entries are automatically pruned when when the table exceeds a size limit,
+ * which is expected to be relatively small, since the implementation uses a linear search.
+ */
+class AuthTokenTable {
+  public:
+    explicit AuthTokenTable(size_t max_entries = 32, time_t (*clock_function)() = clock_gettime_raw)
+        : max_entries_(max_entries), clock_function_(clock_function) {}
+
+    enum Error {
+        OK,
+        AUTH_NOT_REQUIRED = -1,
+        AUTH_TOKEN_EXPIRED = -2,    // Found a matching token, but it's too old.
+        AUTH_TOKEN_WRONG_SID = -3,  // Found a token with the right challenge, but wrong SID.  This
+                                    // most likely indicates that the authenticator was updated
+                                    // (e.g. new fingerprint enrolled).
+        OP_HANDLE_REQUIRED = -4,    // The key requires auth per use but op_handle was zero.
+        AUTH_TOKEN_NOT_FOUND = -5,
+    };
+
+    /**
+     * Add an authorization token to the table.  The table takes ownership of the argument.
+     */
+    void AddAuthenticationToken(const hw_auth_token_t* token);
+
+    /**
+     * Find an authorization token that authorizes the operation specified by \p operation_handle on
+     * a key with the characteristics specified in \p key_info.
+     *
+     * This method is O(n * m), where n is the number of KM_TAG_USER_SECURE_ID entries in key_info
+     * and m is the number of entries in the table.  It could be made better, but n and m should
+     * always be small.
+     *
+     * The table retains ownership of the returned object.
+     */
+    Error FindAuthorization(const AuthorizationSet& key_info, keymaster_purpose_t purpose,
+                            keymaster_operation_handle_t op_handle, const hw_auth_token_t** found);
+
+    /**
+     * Find an authorization token that authorizes the operation specified by \p operation_handle on
+     * a key with the characteristics specified in \p key_info.
+     *
+     * This method is O(n * m), where n is the number of KM_TAG_USER_SECURE_ID entries in key_info
+     * and m is the number of entries in the table.  It could be made better, but n and m should
+     * always be small.
+     *
+     * The table retains ownership of the returned object.
+     */
+    Error FindAuthorization(const keymaster_key_param_t* params, size_t params_count,
+                            keymaster_purpose_t purpose, keymaster_operation_handle_t op_handle,
+                            const hw_auth_token_t** found) {
+        return FindAuthorization(AuthorizationSet(params, params_count), purpose, op_handle, found);
+    }
+
+    /**
+     * Mark operation completed.  This allows tokens associated with the specified operation to be
+     * superseded by new tokens.
+     */
+    void MarkCompleted(const keymaster_operation_handle_t op_handle);
+
+    void Clear();
+
+    size_t size() { return entries_.size(); }
+
+  private:
+    friend class AuthTokenTableTest;
+
+    class Entry {
+      public:
+        Entry(const hw_auth_token_t* token, time_t current_time);
+        Entry(Entry&& entry) { *this = std::move(entry); }
+
+        void operator=(Entry&& rhs) {
+            token_ = std::move(rhs.token_);
+            time_received_ = rhs.time_received_;
+            last_use_ = rhs.last_use_;
+            operation_completed_ = rhs.operation_completed_;
+        }
+
+        bool operator<(const Entry& rhs) const { return last_use_ < rhs.last_use_; }
+
+        void UpdateLastUse(time_t time);
+
+        bool Supersedes(const Entry& entry) const;
+        bool SatisfiesAuth(const std::vector<uint64_t>& sids, hw_authenticator_type_t auth_type);
+
+        bool is_newer_than(const Entry* entry) {
+            if (!entry)
+                return true;
+            return timestamp_host_order() > entry->timestamp_host_order();
+        }
+
+        void mark_completed() { operation_completed_ = true; }
+
+        const hw_auth_token_t* token() { return token_.get(); }
+        time_t time_received() const { return time_received_; }
+        bool completed() const { return operation_completed_; }
+        uint32_t timestamp_host_order() const;
+        hw_authenticator_type_t authenticator_type() const;
+
+      private:
+        std::unique_ptr<const hw_auth_token_t> token_;
+        time_t time_received_;
+        time_t last_use_;
+        bool operation_completed_;
+    };
+
+    Error FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
+                                     hw_authenticator_type_t auth_type,
+                                     keymaster_operation_handle_t op_handle,
+                                     const hw_auth_token_t** found);
+    Error FindTimedAuthorization(const std::vector<uint64_t>& sids,
+                                 hw_authenticator_type_t auth_type,
+                                 const AuthorizationSet& key_info, const hw_auth_token_t** found);
+    void ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids);
+    void RemoveEntriesSupersededBy(const Entry& entry);
+    bool IsSupersededBySomeEntry(const Entry& entry);
+
+    std::vector<Entry> entries_;
+    size_t max_entries_;
+    time_t (*clock_function_)();
+};
+
+}  // namespace keymaster
+
+#endif  // KEYSTORE_AUTH_TOKEN_TABLE_H_
diff --git a/security/keystore/blob.cpp b/security/keystore/blob.cpp
new file mode 100644
index 0000000..8b08f07
--- /dev/null
+++ b/security/keystore/blob.cpp
@@ -0,0 +1,213 @@
+/*
+ * 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 "keystore"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <cutils/log.h>
+
+#include "blob.h"
+#include "entropy.h"
+
+#include "keystore_utils.h"
+
+Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
+           BlobType type) {
+    memset(&mBlob, 0, sizeof(mBlob));
+    if (valueLength > VALUE_SIZE) {
+        valueLength = VALUE_SIZE;
+        ALOGW("Provided blob length too large");
+    }
+    if (infoLength + valueLength > VALUE_SIZE) {
+        infoLength = VALUE_SIZE - valueLength;
+        ALOGW("Provided info length too large");
+    }
+    mBlob.length = valueLength;
+    memcpy(mBlob.value, value, valueLength);
+
+    mBlob.info = infoLength;
+    memcpy(mBlob.value + valueLength, info, infoLength);
+
+    mBlob.version = CURRENT_BLOB_VERSION;
+    mBlob.type = uint8_t(type);
+
+    if (type == TYPE_MASTER_KEY) {
+        mBlob.flags = KEYSTORE_FLAG_ENCRYPTED;
+    } else {
+        mBlob.flags = KEYSTORE_FLAG_NONE;
+    }
+}
+
+Blob::Blob(blob b) {
+    mBlob = b;
+}
+
+Blob::Blob() {
+    memset(&mBlob, 0, sizeof(mBlob));
+}
+
+bool Blob::isEncrypted() const {
+    if (mBlob.version < 2) {
+        return true;
+    }
+
+    return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
+}
+
+void Blob::setEncrypted(bool encrypted) {
+    if (encrypted) {
+        mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
+    } else {
+        mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
+    }
+}
+
+void Blob::setFallback(bool fallback) {
+    if (fallback) {
+        mBlob.flags |= KEYSTORE_FLAG_FALLBACK;
+    } else {
+        mBlob.flags &= ~KEYSTORE_FLAG_FALLBACK;
+    }
+}
+
+ResponseCode Blob::writeBlob(const char* filename, AES_KEY* aes_key, State state,
+                             Entropy* entropy) {
+    ALOGV("writing blob %s", filename);
+    if (isEncrypted()) {
+        if (state != STATE_NO_ERROR) {
+            ALOGD("couldn't insert encrypted blob while not unlocked");
+            return LOCKED;
+        }
+
+        if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
+            ALOGW("Could not read random data for: %s", filename);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    // data includes the value and the value's length
+    size_t dataLength = mBlob.length + sizeof(mBlob.length);
+    // pad data to the AES_BLOCK_SIZE
+    size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
+    // encrypted data includes the digest value
+    size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
+    // move info after space for padding
+    memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
+    // zero padding area
+    memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);
+
+    mBlob.length = htonl(mBlob.length);
+
+    if (isEncrypted()) {
+        MD5(mBlob.digested, digestedLength, mBlob.digest);
+
+        uint8_t vector[AES_BLOCK_SIZE];
+        memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
+        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, vector,
+                        AES_ENCRYPT);
+    }
+
+    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
+    size_t fileLength = encryptedLength + headerLength + mBlob.info;
+
+    const char* tmpFileName = ".tmp";
+    int out =
+        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+    if (out < 0) {
+        ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
+    if (close(out) != 0) {
+        return SYSTEM_ERROR;
+    }
+    if (writtenBytes != fileLength) {
+        ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
+        unlink(tmpFileName);
+        return SYSTEM_ERROR;
+    }
+    if (rename(tmpFileName, filename) == -1) {
+        ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    return NO_ERROR;
+}
+
+ResponseCode Blob::readBlob(const char* filename, AES_KEY* aes_key, State state) {
+    ALOGV("reading blob %s", filename);
+    int in = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
+    if (in < 0) {
+        return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+    }
+    // fileLength may be less than sizeof(mBlob) since the in
+    // memory version has extra padding to tolerate rounding up to
+    // the AES_BLOCK_SIZE
+    size_t fileLength = readFully(in, (uint8_t*)&mBlob, sizeof(mBlob));
+    if (close(in) != 0) {
+        return SYSTEM_ERROR;
+    }
+
+    if (fileLength == 0) {
+        return VALUE_CORRUPTED;
+    }
+
+    if (isEncrypted() && (state != STATE_NO_ERROR)) {
+        return LOCKED;
+    }
+
+    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
+    if (fileLength < headerLength) {
+        return VALUE_CORRUPTED;
+    }
+
+    ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
+    if (encryptedLength < 0) {
+        return VALUE_CORRUPTED;
+    }
+
+    ssize_t digestedLength;
+    if (isEncrypted()) {
+        if (encryptedLength % AES_BLOCK_SIZE != 0) {
+            return VALUE_CORRUPTED;
+        }
+
+        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, mBlob.vector,
+                        AES_DECRYPT);
+        digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
+        uint8_t computedDigest[MD5_DIGEST_LENGTH];
+        MD5(mBlob.digested, digestedLength, computedDigest);
+        if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
+            return VALUE_CORRUPTED;
+        }
+    } else {
+        digestedLength = encryptedLength;
+    }
+
+    ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
+    mBlob.length = ntohl(mBlob.length);
+    if (mBlob.length < 0 || mBlob.length > maxValueLength) {
+        return VALUE_CORRUPTED;
+    }
+    if (mBlob.info != 0) {
+        // move info from after padding to after data
+        memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
+    }
+    return ::NO_ERROR;
+}
diff --git a/security/keystore/blob.h b/security/keystore/blob.h
new file mode 100644
index 0000000..95610ad
--- /dev/null
+++ b/security/keystore/blob.h
@@ -0,0 +1,111 @@
+/*
+ * 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 KEYSTORE_BLOB_H_
+#define KEYSTORE_BLOB_H_
+
+#include <stdint.h>
+
+#include <openssl/aes.h>
+#include <openssl/md5.h>
+
+#include <keystore/keystore.h>
+
+#define VALUE_SIZE      32768
+
+/* Here is the file format. There are two parts in blob.value, the secret and
+ * the description. The secret is stored in ciphertext, and its original size
+ * can be found in blob.length. The description is stored after the secret in
+ * plaintext, and its size is specified in blob.info. The total size of the two
+ * parts must be no more than VALUE_SIZE bytes. The first field is the version,
+ * the second is the blob's type, and the third byte is flags. Fields other
+ * than blob.info, blob.length, and blob.value are modified by encryptBlob()
+ * and decryptBlob(). Thus they should not be accessed from outside. */
+
+/* ** Note to future implementors of encryption: **
+ * Currently this is the construction:
+ *   metadata || Enc(MD5(data) || data)
+ *
+ * This should be the construction used for encrypting if re-implementing:
+ *
+ *   Derive independent keys for encryption and MAC:
+ *     Kenc = AES_encrypt(masterKey, "Encrypt")
+ *     Kmac = AES_encrypt(masterKey, "MAC")
+ *
+ *   Store this:
+ *     metadata || AES_CTR_encrypt(Kenc, rand_IV, data) ||
+ *             HMAC(Kmac, metadata || Enc(data))
+ */
+struct __attribute__((packed)) blob {
+    uint8_t version;
+    uint8_t type;
+    uint8_t flags;
+    uint8_t info;
+    uint8_t vector[AES_BLOCK_SIZE];
+    uint8_t encrypted[0]; // Marks offset to encrypted data.
+    uint8_t digest[MD5_DIGEST_LENGTH];
+    uint8_t digested[0]; // Marks offset to digested data.
+    int32_t length; // in network byte order when encrypted
+    uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+};
+
+static const uint8_t CURRENT_BLOB_VERSION = 2;
+
+typedef enum {
+    TYPE_ANY = 0, // meta type that matches anything
+    TYPE_GENERIC = 1,
+    TYPE_MASTER_KEY = 2,
+    TYPE_KEY_PAIR = 3,
+    TYPE_KEYMASTER_10 = 4,
+} BlobType;
+
+class Entropy;
+
+class Blob {
+  public:
+    Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
+         BlobType type);
+    explicit Blob(blob b);
+
+    Blob();
+
+    const uint8_t* getValue() const { return mBlob.value; }
+
+    int32_t getLength() const { return mBlob.length; }
+
+    const uint8_t* getInfo() const { return mBlob.value + mBlob.length; }
+    uint8_t getInfoLength() const { return mBlob.info; }
+
+    uint8_t getVersion() const { return mBlob.version; }
+
+    bool isEncrypted() const;
+    void setEncrypted(bool encrypted);
+
+    bool isFallback() const { return mBlob.flags & KEYSTORE_FLAG_FALLBACK; }
+    void setFallback(bool fallback);
+
+    void setVersion(uint8_t version) { mBlob.version = version; }
+    BlobType getType() const { return BlobType(mBlob.type); }
+    void setType(BlobType type) { mBlob.type = uint8_t(type); }
+
+    ResponseCode writeBlob(const char* filename, AES_KEY* aes_key, State state, Entropy* entropy);
+    ResponseCode readBlob(const char* filename, AES_KEY* aes_key, State state);
+
+  private:
+    struct blob mBlob;
+};
+
+#endif  // KEYSTORE_BLOB_H_
diff --git a/security/keystore/defaults.h b/security/keystore/defaults.h
new file mode 100644
index 0000000..9232dd0
--- /dev/null
+++ b/security/keystore/defaults.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 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 KEYSTORE_DEFAULTS_H_
+#define KEYSTORE_DEFAULTS_H_
+
+/*
+ * These must be kept in sync with
+ * frameworks/base/keystore/java/android/security/KeyPairGeneratorSpec.java
+ */
+
+/* DSA */
+#define DSA_DEFAULT_KEY_SIZE 1024
+#define DSA_MIN_KEY_SIZE 512
+#define DSA_MAX_KEY_SIZE 8192
+
+/* EC */
+#define EC_DEFAULT_KEY_SIZE 256
+#define EC_MIN_KEY_SIZE 192
+#define EC_MAX_KEY_SIZE 521
+
+/* RSA */
+#define RSA_DEFAULT_KEY_SIZE 2048
+#define RSA_DEFAULT_EXPONENT 0x10001
+#define RSA_MIN_KEY_SIZE 512
+#define RSA_MAX_KEY_SIZE 8192
+
+#endif /* KEYSTORE_DEFAULTS_H_ */
diff --git a/security/keystore/entropy.cpp b/security/keystore/entropy.cpp
new file mode 100644
index 0000000..1bfe9a1
--- /dev/null
+++ b/security/keystore/entropy.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 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 "keystore"
+
+#include "entropy.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+
+#include "keystore_utils.h"
+
+Entropy::~Entropy() {
+    if (mRandom >= 0) {
+        close(mRandom);
+    }
+}
+
+bool Entropy::open() {
+    const char* randomDevice = "/dev/urandom";
+    mRandom = TEMP_FAILURE_RETRY(::open(randomDevice, O_RDONLY));
+    if (mRandom < 0) {
+        ALOGE("open: %s: %s", randomDevice, strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+bool Entropy::generate_random_data(uint8_t* data, size_t size) const {
+    return (readFully(mRandom, data, size) == size);
+}
diff --git a/security/keystore/entropy.h b/security/keystore/entropy.h
new file mode 100644
index 0000000..0e4d1b2
--- /dev/null
+++ b/security/keystore/entropy.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 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 KEYSTORE_ENTROPY_H_
+#define KEYSTORE_ENTROPY_H_
+
+#include <stdint.h>
+
+class Entropy {
+  public:
+    Entropy() : mRandom(-1) {}
+    ~Entropy();
+
+    bool open();
+    bool generate_random_data(uint8_t* data, size_t size) const;
+
+  private:
+    int mRandom;
+};
+
+#endif  // KEYSTORE_ENTROPY_H_
diff --git a/security/keystore/include/keystore/IKeystoreService.h b/security/keystore/include/keystore/IKeystoreService.h
new file mode 100644
index 0000000..0f9ee27
--- /dev/null
+++ b/security/keystore/include/keystore/IKeystoreService.h
@@ -0,0 +1,262 @@
+/*
+ * 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 KEYSTORE_IKEYSTORESERVICE_H
+#define KEYSTORE_IKEYSTORESERVICE_H
+
+#include <hardware/keymaster_defs.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <vector>
+
+namespace android {
+
+class KeystoreArg : public RefBase {
+public:
+    KeystoreArg(const void *data, size_t len);
+    ~KeystoreArg();
+
+    const void* data() const;
+    size_t size() const;
+
+private:
+    const void* mData;
+    size_t mSize;
+};
+
+struct MallocDeleter {
+    void operator()(uint8_t* p) { free(p); }
+};
+
+// struct for serializing/deserializing a list of keymaster_key_param_t's
+struct KeymasterArguments {
+    KeymasterArguments();
+    ~KeymasterArguments();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    std::vector<keymaster_key_param_t> params;
+};
+
+// struct for serializing the results of begin/update/finish
+struct OperationResult {
+    OperationResult();
+    ~OperationResult();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    int resultCode;
+    sp<IBinder> token;
+    keymaster_operation_handle_t handle;
+    int inputConsumed;
+    std::unique_ptr<uint8_t[], MallocDeleter> data;
+    size_t dataLength;
+    KeymasterArguments outParams;
+};
+
+// struct for serializing the results of export
+struct ExportResult {
+    ExportResult();
+    ~ExportResult();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    int resultCode;
+    std::unique_ptr<uint8_t[], MallocDeleter> exportData;
+    size_t dataLength;
+};
+
+// struct for serializing keymaster_key_characteristics_t's
+struct KeyCharacteristics {
+    KeyCharacteristics();
+    ~KeyCharacteristics();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    keymaster_key_characteristics_t characteristics;
+};
+
+// struct for serializing keymaster_cert_chain_t's
+struct KeymasterCertificateChain {
+    KeymasterCertificateChain();
+    ~KeymasterCertificateChain();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    void FreeChain();
+
+    keymaster_cert_chain_t chain;
+};
+
+bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out);
+void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out);
+
+/*
+ * This must be kept manually in sync with frameworks/base's IKeystoreService.java
+ */
+class IKeystoreService: public IInterface {
+public:
+    enum {
+        GET_STATE = IBinder::FIRST_CALL_TRANSACTION + 0,
+        GET = IBinder::FIRST_CALL_TRANSACTION + 1,
+        INSERT = IBinder::FIRST_CALL_TRANSACTION + 2,
+        DEL = IBinder::FIRST_CALL_TRANSACTION + 3,
+        EXIST = IBinder::FIRST_CALL_TRANSACTION + 4,
+        LIST = IBinder::FIRST_CALL_TRANSACTION + 5,
+        RESET = IBinder::FIRST_CALL_TRANSACTION + 6,
+        ON_USER_PASSWORD_CHANGED = IBinder::FIRST_CALL_TRANSACTION + 7,
+        LOCK = IBinder::FIRST_CALL_TRANSACTION + 8,
+        UNLOCK = IBinder::FIRST_CALL_TRANSACTION + 9,
+        IS_EMPTY = IBinder::FIRST_CALL_TRANSACTION + 10,
+        GENERATE = IBinder::FIRST_CALL_TRANSACTION + 11,
+        IMPORT = IBinder::FIRST_CALL_TRANSACTION + 12,
+        SIGN = IBinder::FIRST_CALL_TRANSACTION + 13,
+        VERIFY = IBinder::FIRST_CALL_TRANSACTION + 14,
+        GET_PUBKEY = IBinder::FIRST_CALL_TRANSACTION + 15,
+        GRANT = IBinder::FIRST_CALL_TRANSACTION + 16,
+        UNGRANT = IBinder::FIRST_CALL_TRANSACTION + 17,
+        GETMTIME = IBinder::FIRST_CALL_TRANSACTION + 18,
+        DUPLICATE = IBinder::FIRST_CALL_TRANSACTION + 19,
+        IS_HARDWARE_BACKED = IBinder::FIRST_CALL_TRANSACTION + 20,
+        CLEAR_UID = IBinder::FIRST_CALL_TRANSACTION + 21,
+        ADD_RNG_ENTROPY = IBinder::FIRST_CALL_TRANSACTION + 22,
+        GENERATE_KEY = IBinder::FIRST_CALL_TRANSACTION + 23,
+        GET_KEY_CHARACTERISTICS = IBinder::FIRST_CALL_TRANSACTION + 24,
+        IMPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 25,
+        EXPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 26,
+        BEGIN = IBinder::FIRST_CALL_TRANSACTION + 27,
+        UPDATE = IBinder::FIRST_CALL_TRANSACTION + 28,
+        FINISH = IBinder::FIRST_CALL_TRANSACTION + 29,
+        ABORT = IBinder::FIRST_CALL_TRANSACTION + 30,
+        IS_OPERATION_AUTHORIZED = IBinder::FIRST_CALL_TRANSACTION + 31,
+        ADD_AUTH_TOKEN = IBinder::FIRST_CALL_TRANSACTION + 32,
+        ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33,
+        ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34,
+        ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35,
+    };
+
+    DECLARE_META_INTERFACE(KeystoreService);
+
+    virtual int32_t getState(int32_t userId) = 0;
+
+    virtual int32_t get(const String16& name, uint8_t** item, size_t* itemLength) = 0;
+
+    virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
+            int32_t flags) = 0;
+
+    virtual int32_t del(const String16& name, int uid) = 0;
+
+    virtual int32_t exist(const String16& name, int uid) = 0;
+
+    virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches) = 0;
+
+    virtual int32_t reset() = 0;
+
+    virtual int32_t onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
+
+    virtual int32_t lock(int32_t userId) = 0;
+
+    virtual int32_t unlock(int32_t userId, const String16& password) = 0;
+
+    virtual bool isEmpty(int32_t userId) = 0;
+
+    virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
+            int32_t flags, Vector<sp<KeystoreArg> >* args) = 0;
+
+    virtual int32_t import(const String16& name, const uint8_t* data, size_t length, int uid,
+            int32_t flags) = 0;
+
+    virtual int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
+            size_t* outLength) = 0;
+
+    virtual int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
+            const uint8_t* signature, size_t signatureLength) = 0;
+
+    virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) = 0;
+
+    virtual int32_t grant(const String16& name, int32_t granteeUid) = 0;
+
+    virtual int32_t ungrant(const String16& name, int32_t granteeUid) = 0;
+
+    virtual int64_t getmtime(const String16& name) = 0;
+
+    virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
+            int32_t destUid) = 0;
+
+    virtual int32_t is_hardware_backed(const String16& keyType) = 0;
+
+    virtual int32_t clear_uid(int64_t uid) = 0;
+
+    virtual int32_t addRngEntropy(const uint8_t* data, size_t dataLength) = 0;
+
+    virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
+                                const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+                                KeyCharacteristics* outCharacteristics) = 0;
+
+    virtual int32_t getKeyCharacteristics(const String16& name,
+                                          const keymaster_blob_t* clientId,
+                                          const keymaster_blob_t* appData,
+                                          KeyCharacteristics* outCharacteristics) = 0;
+
+    virtual int32_t importKey(const String16& name, const KeymasterArguments&  params,
+                              keymaster_key_format_t format, const uint8_t *keyData,
+                              size_t keyLength, int uid, int flags,
+                              KeyCharacteristics* outCharacteristics) = 0;
+
+    virtual void exportKey(const String16& name, keymaster_key_format_t format,
+                           const keymaster_blob_t* clientId,
+                           const keymaster_blob_t* appData, ExportResult* result) = 0;
+
+    virtual void begin(const sp<IBinder>& apptoken, const String16& name,
+                       keymaster_purpose_t purpose, bool pruneable,
+                       const KeymasterArguments& params, const uint8_t* entropy,
+                       size_t entropyLength, OperationResult* result) = 0;
+
+    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
+                        const uint8_t* data, size_t dataLength, OperationResult* result) = 0;
+
+    virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                        const uint8_t* signature, size_t signatureLength,
+                        const uint8_t* entropy, size_t entropyLength,
+                        OperationResult* result) = 0;
+
+    virtual int32_t abort(const sp<IBinder>& handle) = 0;
+
+    virtual bool isOperationAuthorized(const sp<IBinder>& handle) = 0;
+
+    virtual int32_t addAuthToken(const uint8_t* token, size_t length) = 0;
+
+    virtual int32_t onUserAdded(int32_t userId, int32_t parentId) = 0;
+
+    virtual int32_t onUserRemoved(int32_t userId) = 0;
+
+    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
+                              KeymasterCertificateChain* outChain) = 0;
+
+};
+
+// ----------------------------------------------------------------------------
+
+class BnKeystoreService: public BnInterface<IKeystoreService> {
+public:
+    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+            uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif
diff --git a/security/keystore/include/keystore/keystore.h b/security/keystore/include/keystore/keystore.h
new file mode 100644
index 0000000..dcb6032
--- /dev/null
+++ b/security/keystore/include/keystore/keystore.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 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 __KEYSTORE_H__
+#define __KEYSTORE_H__
+
+#include <stdint.h>
+
+// note state values overlap with ResponseCode for the purposes of the state() API
+enum State {
+    STATE_NO_ERROR      = 1,
+    STATE_LOCKED        = 2,
+    STATE_UNINITIALIZED = 3,
+};
+
+enum ResponseCode {
+    NO_ERROR          =  STATE_NO_ERROR, // 1
+    LOCKED            =  STATE_LOCKED, // 2
+    UNINITIALIZED     =  STATE_UNINITIALIZED, // 3
+    SYSTEM_ERROR      =  4,
+    PROTOCOL_ERROR    =  5,
+    PERMISSION_DENIED =  6,
+    KEY_NOT_FOUND     =  7,
+    VALUE_CORRUPTED   =  8,
+    UNDEFINED_ACTION  =  9,
+    WRONG_PASSWORD_0  = 10,
+    WRONG_PASSWORD_1  = 11,
+    WRONG_PASSWORD_2  = 12,
+    WRONG_PASSWORD_3  = 13, // MAX_RETRY = 4
+    SIGNATURE_INVALID = 14,
+    OP_AUTH_NEEDED    = 15, // Auth is needed for this operation before it can be used.
+};
+
+/*
+ * All the flags for import and insert calls.
+ */
+enum {
+    KEYSTORE_FLAG_NONE = 0,
+    KEYSTORE_FLAG_ENCRYPTED = 1 << 0,
+    KEYSTORE_FLAG_FALLBACK = 1 << 1,
+};
+
+/**
+ * Returns the size of the softkey magic header value for measuring
+ * and allocating purposes.
+ */
+size_t get_softkey_header_size();
+
+/**
+ * Adds the magic softkey header to a key blob.
+ *
+ * Returns NULL if the destination array is too small. Otherwise it
+ * returns the offset directly after the magic value.
+ */
+uint8_t* add_softkey_header(uint8_t* key_blob, size_t key_blob_length);
+
+/**
+ * Returns true if the key blob has a magic softkey header at the beginning.
+ */
+bool is_softkey(const uint8_t* key_blob, const size_t key_blob_length);
+
+#endif
diff --git a/security/keystore/include/keystore/keystore_client.h b/security/keystore/include/keystore/keystore_client.h
new file mode 100644
index 0000000..cec29f7
--- /dev/null
+++ b/security/keystore/include/keystore/keystore_client.h
@@ -0,0 +1,180 @@
+// Copyright 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 KEYSTORE_KEYSTORE_CLIENT_H_
+#define KEYSTORE_KEYSTORE_CLIENT_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "hardware/keymaster_defs.h"
+#include "keymaster/authorization_set.h"
+
+namespace keystore {
+
+// An abstract class providing a convenient interface to keystore services. This
+// interface is designed to:
+//   - hide details of the IPC mechanism (e.g. binder)
+//   - use std data types
+//   - encourage the use of keymaster::AuthorizationSet[Builder]
+//   - be convenient for native services integrating with keystore
+//   - be safely mocked for unit testing (e.g. pure virtual methods)
+//
+// Example usage:
+//   KeystoreClient* keystore = new KeyStoreClientImpl();
+//   keystore->AddRandomNumberGeneratorEntropy("unpredictable");
+//
+// Notes on error codes:
+//   Keystore binder methods return a variety of values including ResponseCode
+//   values defined in keystore.h, keymaster_error_t values defined in
+//   keymaster_defs.h, or just 0 or -1 (both of which conflict with
+//   keymaster_error_t). The methods in this class converge on a single success
+//   indicator for convenience. KM_ERROR_OK was chosen over ::NO_ERROR for two
+//   reasons:
+//   1) KM_ERROR_OK is 0, which is a common convention for success, is the gmock
+//      default, and allows error checks like 'if (error) {...'.
+//   2) Although both pollute the global namespace, KM_ERROR_OK has a prefix per
+//      C convention and hopefully clients can use this interface without
+//      needing to include 'keystore.h' directly.
+class KeystoreClient {
+  public:
+    KeystoreClient() = default;
+    virtual ~KeystoreClient() = default;
+
+    // Encrypts and authenticates |data| with minimal configuration for local
+    // decryption. If a key identified by |key_name| does not already exist it
+    // will be generated. On success returns true and populates |encrypted_data|.
+    // Note: implementations may generate more than one key but they will always
+    // have |key_name| as a prefix.
+    virtual bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
+                                           std::string* encrypted_data) = 0;
+
+    // Decrypts and authenticates |encrypted_data| as output by
+    // EncryptWithAuthentication using the key(s) identified by |key_name|. On
+    // success returns true and populates |data|.
+    virtual bool decryptWithAuthentication(const std::string& key_name,
+                                           const std::string& encrypted_data,
+                                           std::string* data) = 0;
+
+    // Performs a Begin/Update/Finish sequence for an operation. The |purpose|,
+    // |key_name|, |input_parameters|, and |output_parameters| are as in
+    // BeginOperation. The |input_data| is as in UpdateOperation. The
+    // |signature_to_verify| and |output_data| are as in FinishOperation. On
+    // success returns true.
+    virtual bool oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
+                                  const keymaster::AuthorizationSet& input_parameters,
+                                  const std::string& input_data,
+                                  const std::string& signature_to_verify,
+                                  keymaster::AuthorizationSet* output_parameters,
+                                  std::string* output_data) = 0;
+
+    // Adds |entropy| to the random number generator. Returns KM_ERROR_OK on
+    // success and a Keystore ResponseCode or keymaster_error_t on failure.
+    virtual int32_t addRandomNumberGeneratorEntropy(const std::string& entropy) = 0;
+
+    // Generates a key according to the given |key_parameters| and stores it with
+    // the given |key_name|. The [hardware|software]_enforced_characteristics of
+    // the key are provided on success. Returns KM_ERROR_OK on success. Returns
+    // KM_ERROR_OK on success and a Keystore ResponseCode or keymaster_error_t on
+    // failure.
+    virtual int32_t generateKey(const std::string& key_name,
+                                const keymaster::AuthorizationSet& key_parameters,
+                                keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                                keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+    // Provides the [hardware|software]_enforced_characteristics of a key
+    // identified by |key_name|. Returns KM_ERROR_OK on success and a Keystore
+    // ResponseCode or keymaster_error_t on failure.
+    virtual int32_t
+    getKeyCharacteristics(const std::string& key_name,
+                          keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                          keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+    // Imports |key_data| in the given |key_format|, applies the given
+    // |key_parameters|, and stores it with the given |key_name|. The
+    // [hardware|software]_enforced_characteristics of the key are provided on
+    // success. Returns KM_ERROR_OK on success and a Keystore ResponseCode or
+    // keymaster_error_t on failure.
+    virtual int32_t importKey(const std::string& key_name,
+                              const keymaster::AuthorizationSet& key_parameters,
+                              keymaster_key_format_t key_format, const std::string& key_data,
+                              keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                              keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+    // Exports the public key identified by |key_name| to |export_data| using
+    // |export_format|. Returns KM_ERROR_OK on success and a Keystore ResponseCode
+    // or keymaster_error_t on failure.
+    virtual int32_t exportKey(keymaster_key_format_t export_format, const std::string& key_name,
+                              std::string* export_data) = 0;
+
+    // Deletes the key identified by |key_name|. Returns KM_ERROR_OK on success
+    // and a Keystore ResponseCode or keymaster_error_t on failure.
+    virtual int32_t deleteKey(const std::string& key_name) = 0;
+
+    // Deletes all keys owned by the caller. Returns KM_ERROR_OK on success and a
+    // Keystore ResponseCode or keymaster_error_t on failure.
+    virtual int32_t deleteAllKeys() = 0;
+
+    // Begins a cryptographic operation (e.g. encrypt, sign) identified by
+    // |purpose| using the key identified by |key_name| and the given
+    // |input_parameters|. On success, any |output_parameters| and an operation
+    // |handle| are populated. Returns KM_ERROR_OK on success and a Keystore
+    // ResponseCode or keymaster_error_t on failure.
+    virtual int32_t beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+                                   const keymaster::AuthorizationSet& input_parameters,
+                                   keymaster::AuthorizationSet* output_parameters,
+                                   keymaster_operation_handle_t* handle) = 0;
+
+    // Continues the operation associated with |handle| using the given
+    // |input_parameters| and |input_data|. On success, the
+    // |num_input_bytes_consumed| and any |output_parameters| are populated. Any
+    // |output_data| will be appended. Returns KM_ERROR_OK on success and a
+    // Keystore ResponseCode or keymaster_error_t on failure.
+    virtual int32_t updateOperation(keymaster_operation_handle_t handle,
+                                    const keymaster::AuthorizationSet& input_parameters,
+                                    const std::string& input_data, size_t* num_input_bytes_consumed,
+                                    keymaster::AuthorizationSet* output_parameters,
+                                    std::string* output_data) = 0;
+
+    // Finishes the operation associated with |handle| using the given
+    // |input_parameters| and, if necessary, a |signature_to_verify|. On success,
+    // any |output_parameters| are populated and |output_data| is appended.
+    // Returns KM_ERROR_OK on success and a Keystore ResponseCode or
+    // keymaster_error_t on failure.
+    virtual int32_t finishOperation(keymaster_operation_handle_t handle,
+                                    const keymaster::AuthorizationSet& input_parameters,
+                                    const std::string& signature_to_verify,
+                                    keymaster::AuthorizationSet* output_parameters,
+                                    std::string* output_data) = 0;
+
+    // Aborts the operation associated with |handle|. Returns KM_ERROR_OK on
+    // success and a Keystore ResponseCode or keymaster_error_t on failure.
+    virtual int32_t abortOperation(keymaster_operation_handle_t handle) = 0;
+
+    // Returns true if a key identified by |key_name| exists in the caller's
+    // key store. Returns false if an error occurs.
+    virtual bool doesKeyExist(const std::string& key_name) = 0;
+
+    // Provides a |key_name_list| containing all existing key names in the
+    // caller's key store starting with |prefix|. Returns true on success.
+    virtual bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) = 0;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(KeystoreClient);
+};
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_KEYSTORE_CLIENT_H_
diff --git a/security/keystore/include/keystore/keystore_client_impl.h b/security/keystore/include/keystore/keystore_client_impl.h
new file mode 100644
index 0000000..21f68f9
--- /dev/null
+++ b/security/keystore/include/keystore/keystore_client_impl.h
@@ -0,0 +1,119 @@
+// Copyright 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 KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
+#define KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
+
+#include "keystore/keystore_client.h"
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include "binder/IBinder.h"
+#include "binder/IServiceManager.h"
+#include "keystore/IKeystoreService.h"
+#include "utils/StrongPointer.h"
+
+namespace keystore {
+
+class KeystoreClientImpl : public KeystoreClient {
+  public:
+    KeystoreClientImpl();
+    ~KeystoreClientImpl() override = default;
+
+    // KeystoreClient methods.
+    bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
+                                   std::string* encrypted_data) override;
+    bool decryptWithAuthentication(const std::string& key_name, const std::string& encrypted_data,
+                                   std::string* data) override;
+    bool oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
+                          const keymaster::AuthorizationSet& input_parameters,
+                          const std::string& input_data, const std::string& signature_to_verify,
+                          keymaster::AuthorizationSet* output_parameters,
+                          std::string* output_data) override;
+    int32_t addRandomNumberGeneratorEntropy(const std::string& entropy) override;
+    int32_t generateKey(const std::string& key_name,
+                        const keymaster::AuthorizationSet& key_parameters,
+                        keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                        keymaster::AuthorizationSet* software_enforced_characteristics) override;
+    int32_t
+    getKeyCharacteristics(const std::string& key_name,
+                          keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                          keymaster::AuthorizationSet* software_enforced_characteristics) override;
+    int32_t importKey(const std::string& key_name,
+                      const keymaster::AuthorizationSet& key_parameters,
+                      keymaster_key_format_t key_format, const std::string& key_data,
+                      keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                      keymaster::AuthorizationSet* software_enforced_characteristics) override;
+    int32_t exportKey(keymaster_key_format_t export_format, const std::string& key_name,
+                      std::string* export_data) override;
+    int32_t deleteKey(const std::string& key_name) override;
+    int32_t deleteAllKeys() override;
+    int32_t beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+                           const keymaster::AuthorizationSet& input_parameters,
+                           keymaster::AuthorizationSet* output_parameters,
+                           keymaster_operation_handle_t* handle) override;
+    int32_t updateOperation(keymaster_operation_handle_t handle,
+                            const keymaster::AuthorizationSet& input_parameters,
+                            const std::string& input_data, size_t* num_input_bytes_consumed,
+                            keymaster::AuthorizationSet* output_parameters,
+                            std::string* output_data) override;
+    int32_t finishOperation(keymaster_operation_handle_t handle,
+                            const keymaster::AuthorizationSet& input_parameters,
+                            const std::string& signature_to_verify,
+                            keymaster::AuthorizationSet* output_parameters,
+                            std::string* output_data) override;
+    int32_t abortOperation(keymaster_operation_handle_t handle) override;
+    bool doesKeyExist(const std::string& key_name) override;
+    bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) override;
+
+  private:
+    // Returns an available virtual operation handle.
+    keymaster_operation_handle_t getNextVirtualHandle();
+
+    // Maps a keystore error code to a code where all success cases use
+    // KM_ERROR_OK (not keystore's NO_ERROR).
+    int32_t mapKeystoreError(int32_t keystore_error);
+
+    // Creates an encryption key suitable for EncryptWithAuthentication or
+    // verifies attributes if the key already exists. Returns true on success.
+    bool createOrVerifyEncryptionKey(const std::string& key_name);
+
+    // Creates an authentication key suitable for EncryptWithAuthentication or
+    // verifies attributes if the key already exists. Returns true on success.
+    bool createOrVerifyAuthenticationKey(const std::string& key_name);
+
+    // Verifies attributes of an encryption key suitable for
+    // EncryptWithAuthentication. Returns true on success and populates |verified|
+    // with the result of the verification.
+    bool verifyEncryptionKeyAttributes(const std::string& key_name, bool* verified);
+
+    // Verifies attributes of an authentication key suitable for
+    // EncryptWithAuthentication. Returns true on success and populates |verified|
+    // with the result of the verification.
+    bool verifyAuthenticationKeyAttributes(const std::string& key_name, bool* verified);
+
+    android::sp<android::IServiceManager> service_manager_;
+    android::sp<android::IBinder> keystore_binder_;
+    android::sp<android::IKeystoreService> keystore_;
+    keymaster_operation_handle_t next_virtual_handle_ = 1;
+    std::map<keymaster_operation_handle_t, android::sp<android::IBinder>> active_operations_;
+
+    DISALLOW_COPY_AND_ASSIGN(KeystoreClientImpl);
+};
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
diff --git a/security/keystore/include/keystore/keystore_client_mock.h b/security/keystore/include/keystore/keystore_client_mock.h
new file mode 100644
index 0000000..2d1f499
--- /dev/null
+++ b/security/keystore/include/keystore/keystore_client_mock.h
@@ -0,0 +1,88 @@
+// Copyright 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 KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
+#define KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
+
+#include "gmock/gmock.h"
+#include "keystore/keystore_client.h"
+
+using testing::_;
+
+namespace keystore {
+
+// A mock implementation of KeystoreClient. By default all methods do nothing
+// and return KM_ERROR_OK (or false).
+class KeystoreClientMock : public KeystoreClient {
+  public:
+    KeystoreClientMock() = default;
+    ~KeystoreClientMock() = default;
+
+    MOCK_METHOD3(encryptWithAuthentication,
+                 bool(const std::string& key_name, const std::string& data,
+                      std::string* encrypted_data));
+    MOCK_METHOD3(decryptWithAuthentication,
+                 bool(const std::string& key_name, const std::string& encrypted_data,
+                      std::string* data));
+    MOCK_METHOD7(oneShotOperation,
+                 bool(keymaster_purpose_t purpose, const std::string& key_name,
+                      const keymaster::AuthorizationSet& input_parameters,
+                      const std::string& input_data, const std::string& signature_to_verify,
+                      keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+    MOCK_METHOD1(addRandomNumberGeneratorEntropy, int32_t(const std::string& entropy));
+    MOCK_METHOD4(generateKey,
+                 int32_t(const std::string& key_name,
+                         const keymaster::AuthorizationSet& key_parameters,
+                         keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                         keymaster::AuthorizationSet* software_enforced_characteristics));
+    MOCK_METHOD3(getKeyCharacteristics,
+                 int32_t(const std::string& key_name,
+                         keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                         keymaster::AuthorizationSet* software_enforced_characteristics));
+    MOCK_METHOD6(importKey,
+                 int32_t(const std::string& key_name,
+                         const keymaster::AuthorizationSet& key_parameters,
+                         keymaster_key_format_t key_format, const std::string& key_data,
+                         keymaster::AuthorizationSet* hardware_enforced_characteristics,
+                         keymaster::AuthorizationSet* software_enforced_characteristics));
+    MOCK_METHOD3(exportKey, int32_t(keymaster_key_format_t export_format,
+                                    const std::string& key_name, std::string* export_data));
+    MOCK_METHOD1(deleteKey, int32_t(const std::string& key_name));
+    MOCK_METHOD0(deleteAllKeys, int32_t());
+    MOCK_METHOD5(beginOperation, int32_t(keymaster_purpose_t purpose, const std::string& key_name,
+                                         const keymaster::AuthorizationSet& input_parameters,
+                                         keymaster::AuthorizationSet* output_parameters,
+                                         keymaster_operation_handle_t* handle));
+    MOCK_METHOD6(updateOperation,
+                 int32_t(keymaster_operation_handle_t handle,
+                         const keymaster::AuthorizationSet& input_parameters,
+                         const std::string& input_data, size_t* num_input_bytes_consumed,
+                         keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+    MOCK_METHOD5(finishOperation,
+                 int32_t(keymaster_operation_handle_t handle,
+                         const keymaster::AuthorizationSet& input_parameters,
+                         const std::string& signature_to_verify,
+                         keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+    MOCK_METHOD1(abortOperation, int32_t(keymaster_operation_handle_t handle));
+    MOCK_METHOD1(doesKeyExist, bool(const std::string& key_name));
+    MOCK_METHOD2(listKeys,
+                 bool(const std::string& prefix, std::vector<std::string>* key_name_list));
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(KeystoreClientMock);
+};
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
diff --git a/security/keystore/include/keystore/keystore_get.h b/security/keystore/include/keystore/keystore_get.h
new file mode 100644
index 0000000..4bddd70
--- /dev/null
+++ b/security/keystore/include/keystore/keystore_get.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 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 __KEYSTORE_GET_H__
+#define __KEYSTORE_GET_H__
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This function is provided for native components to get values from keystore.
+ * Users are required to link against libkeystore_binder.
+ *
+ * Keys and values are 8-bit safe. The first two arguments are the key and its
+ * length. The third argument is a pointer to an array that will be malloc()
+ * and the caller is responsible for calling free() on the buffer.
+ */
+ssize_t keystore_get(const char *key, size_t length, uint8_t** value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/security/keystore/key_store_service.cpp b/security/keystore/key_store_service.cpp
new file mode 100644
index 0000000..e3df13a
--- /dev/null
+++ b/security/keystore/key_store_service.cpp
@@ -0,0 +1,1488 @@
+/*
+ * Copyright (C) 2016 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 "key_store_service.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sstream>
+
+#include <binder/IPCThreadState.h>
+
+#include <private/android_filesystem_config.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include "defaults.h"
+#include "keystore_utils.h"
+
+namespace android {
+
+const size_t MAX_OPERATIONS = 15;
+
+struct BIGNUM_Delete {
+    void operator()(BIGNUM* p) const { BN_free(p); }
+};
+typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
+
+void KeyStoreService::binderDied(const wp<IBinder>& who) {
+    auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
+    for (const auto& token : operations) {
+        abort(token);
+    }
+}
+
+int32_t KeyStoreService::getState(int32_t userId) {
+    if (!checkBinderPermission(P_GET_STATE)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    return mKeyStore->getState(userId);
+}
+
+int32_t KeyStoreService::get(const String16& name, uint8_t** item, size_t* itemLength) {
+    if (!checkBinderPermission(P_GET)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    String8 name8(name);
+    Blob keyBlob;
+
+    ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_GENERIC);
+    if (responseCode != ::NO_ERROR) {
+        *item = NULL;
+        *itemLength = 0;
+        return responseCode;
+    }
+
+    *item = (uint8_t*)malloc(keyBlob.getLength());
+    memcpy(*item, keyBlob.getValue(), keyBlob.getLength());
+    *itemLength = keyBlob.getLength();
+
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::insert(const String16& name, const uint8_t* item, size_t itemLength,
+                                int targetUid, int32_t flags) {
+    targetUid = getEffectiveUid(targetUid);
+    int32_t result =
+        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (result != ::NO_ERROR) {
+        return result;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+
+    Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
+}
+
+int32_t KeyStoreService::del(const String16& name, int targetUid) {
+    targetUid = getEffectiveUid(targetUid);
+    if (!checkBinderPermission(P_DELETE, targetUid)) {
+        return ::PERMISSION_DENIED;
+    }
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+    return mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
+}
+
+int32_t KeyStoreService::exist(const String16& name, int targetUid) {
+    targetUid = getEffectiveUid(targetUid);
+    if (!checkBinderPermission(P_EXIST, targetUid)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+
+    if (access(filename.string(), R_OK) == -1) {
+        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+    }
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::list(const String16& prefix, int targetUid, Vector<String16>* matches) {
+    targetUid = getEffectiveUid(targetUid);
+    if (!checkBinderPermission(P_LIST, targetUid)) {
+        return ::PERMISSION_DENIED;
+    }
+    const String8 prefix8(prefix);
+    String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid));
+
+    if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ::NO_ERROR) {
+        return ::SYSTEM_ERROR;
+    }
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::reset() {
+    if (!checkBinderPermission(P_RESET)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    mKeyStore->resetUser(get_user_id(callingUid), false);
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password) {
+    if (!checkBinderPermission(P_PASSWORD)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    const String8 password8(password);
+    // Flush the auth token table to prevent stale tokens from sticking
+    // around.
+    mAuthTokenTable.Clear();
+
+    if (password.size() == 0) {
+        ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
+        mKeyStore->resetUser(userId, true);
+        return ::NO_ERROR;
+    } else {
+        switch (mKeyStore->getState(userId)) {
+        case ::STATE_UNINITIALIZED: {
+            // generate master key, encrypt with password, write to file,
+            // initialize mMasterKey*.
+            return mKeyStore->initializeUser(password8, userId);
+        }
+        case ::STATE_NO_ERROR: {
+            // rewrite master key with new password.
+            return mKeyStore->writeMasterKey(password8, userId);
+        }
+        case ::STATE_LOCKED: {
+            ALOGE("Changing user %d's password while locked, clearing old encryption", userId);
+            mKeyStore->resetUser(userId, true);
+            return mKeyStore->initializeUser(password8, userId);
+        }
+        }
+        return ::SYSTEM_ERROR;
+    }
+}
+
+int32_t KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
+    if (!checkBinderPermission(P_USER_CHANGED)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    // Sanity check that the new user has an empty keystore.
+    if (!mKeyStore->isEmpty(userId)) {
+        ALOGW("New user %d's keystore not empty. Clearing old entries.", userId);
+    }
+    // Unconditionally clear the keystore, just to be safe.
+    mKeyStore->resetUser(userId, false);
+    if (parentId != -1) {
+        // This profile must share the same master key password as the parent profile. Because the
+        // password of the parent profile is not known here, the best we can do is copy the parent's
+        // master key and master key file. This makes this profile use the same master key as the
+        // parent profile, forever.
+        return mKeyStore->copyMasterKey(parentId, userId);
+    } else {
+        return ::NO_ERROR;
+    }
+}
+
+int32_t KeyStoreService::onUserRemoved(int32_t userId) {
+    if (!checkBinderPermission(P_USER_CHANGED)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    mKeyStore->resetUser(userId, false);
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::lock(int32_t userId) {
+    if (!checkBinderPermission(P_LOCK)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    State state = mKeyStore->getState(userId);
+    if (state != ::STATE_NO_ERROR) {
+        ALOGD("calling lock in state: %d", state);
+        return state;
+    }
+
+    mKeyStore->lock(userId);
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::unlock(int32_t userId, const String16& pw) {
+    if (!checkBinderPermission(P_UNLOCK)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    State state = mKeyStore->getState(userId);
+    if (state != ::STATE_LOCKED) {
+        switch (state) {
+        case ::STATE_NO_ERROR:
+            ALOGI("calling unlock when already unlocked, ignoring.");
+            break;
+        case ::STATE_UNINITIALIZED:
+            ALOGE("unlock called on uninitialized keystore.");
+            break;
+        default:
+            ALOGE("unlock called on keystore in unknown state: %d", state);
+            break;
+        }
+        return state;
+    }
+
+    const String8 password8(pw);
+    // read master key, decrypt with password, initialize mMasterKey*.
+    return mKeyStore->readMasterKey(password8, userId);
+}
+
+bool KeyStoreService::isEmpty(int32_t userId) {
+    if (!checkBinderPermission(P_IS_EMPTY)) {
+        return false;
+    }
+
+    return mKeyStore->isEmpty(userId);
+}
+
+int32_t KeyStoreService::generate(const String16& name, int32_t targetUid, int32_t keyType,
+                                  int32_t keySize, int32_t flags, Vector<sp<KeystoreArg>>* args) {
+    targetUid = getEffectiveUid(targetUid);
+    int32_t result =
+        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (result != ::NO_ERROR) {
+        return result;
+    }
+
+    KeymasterArguments params;
+    add_legacy_key_authorizations(keyType, &params.params);
+
+    switch (keyType) {
+    case EVP_PKEY_EC: {
+        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+        if (keySize == -1) {
+            keySize = EC_DEFAULT_KEY_SIZE;
+        } else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
+            ALOGI("invalid key size %d", keySize);
+            return ::SYSTEM_ERROR;
+        }
+        params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+        break;
+    }
+    case EVP_PKEY_RSA: {
+        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+        if (keySize == -1) {
+            keySize = RSA_DEFAULT_KEY_SIZE;
+        } else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
+            ALOGI("invalid key size %d", keySize);
+            return ::SYSTEM_ERROR;
+        }
+        params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+        unsigned long exponent = RSA_DEFAULT_EXPONENT;
+        if (args->size() > 1) {
+            ALOGI("invalid number of arguments: %zu", args->size());
+            return ::SYSTEM_ERROR;
+        } else if (args->size() == 1) {
+            const sp<KeystoreArg>& expArg = args->itemAt(0);
+            if (expArg != NULL) {
+                Unique_BIGNUM pubExpBn(BN_bin2bn(
+                    reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
+                if (pubExpBn.get() == NULL) {
+                    ALOGI("Could not convert public exponent to BN");
+                    return ::SYSTEM_ERROR;
+                }
+                exponent = BN_get_word(pubExpBn.get());
+                if (exponent == 0xFFFFFFFFL) {
+                    ALOGW("cannot represent public exponent as a long value");
+                    return ::SYSTEM_ERROR;
+                }
+            } else {
+                ALOGW("public exponent not read");
+                return ::SYSTEM_ERROR;
+            }
+        }
+        params.params.push_back(keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, exponent));
+        break;
+    }
+    default: {
+        ALOGW("Unsupported key type %d", keyType);
+        return ::SYSTEM_ERROR;
+    }
+    }
+
+    int32_t rc = generateKey(name, params, NULL, 0, targetUid, flags,
+                             /*outCharacteristics*/ NULL);
+    if (rc != ::NO_ERROR) {
+        ALOGW("generate failed: %d", rc);
+    }
+    return translateResultToLegacyResult(rc);
+}
+
+int32_t KeyStoreService::import(const String16& name, const uint8_t* data, size_t length,
+                                int targetUid, int32_t flags) {
+    const uint8_t* ptr = data;
+
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, length));
+    if (!pkcs8.get()) {
+        return ::SYSTEM_ERROR;
+    }
+    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+    if (!pkey.get()) {
+        return ::SYSTEM_ERROR;
+    }
+    int type = EVP_PKEY_type(pkey->type);
+    KeymasterArguments params;
+    add_legacy_key_authorizations(type, &params.params);
+    switch (type) {
+    case EVP_PKEY_RSA:
+        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+        break;
+    case EVP_PKEY_EC:
+        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+        break;
+    default:
+        ALOGW("Unsupported key type %d", type);
+        return ::SYSTEM_ERROR;
+    }
+    int32_t rc = importKey(name, params, KM_KEY_FORMAT_PKCS8, data, length, targetUid, flags,
+                           /*outCharacteristics*/ NULL);
+    if (rc != ::NO_ERROR) {
+        ALOGW("importKey failed: %d", rc);
+    }
+    return translateResultToLegacyResult(rc);
+}
+
+int32_t KeyStoreService::sign(const String16& name, const uint8_t* data, size_t length,
+                              uint8_t** out, size_t* outLength) {
+    if (!checkBinderPermission(P_SIGN)) {
+        return ::PERMISSION_DENIED;
+    }
+    return doLegacySignVerify(name, data, length, out, outLength, NULL, 0, KM_PURPOSE_SIGN);
+}
+
+int32_t KeyStoreService::verify(const String16& name, const uint8_t* data, size_t dataLength,
+                                const uint8_t* signature, size_t signatureLength) {
+    if (!checkBinderPermission(P_VERIFY)) {
+        return ::PERMISSION_DENIED;
+    }
+    return doLegacySignVerify(name, data, dataLength, NULL, NULL, signature, signatureLength,
+                              KM_PURPOSE_VERIFY);
+}
+
+/*
+ * TODO: The abstraction between things stored in hardware and regular blobs
+ * of data stored on the filesystem should be moved down to keystore itself.
+ * Unfortunately the Java code that calls this has naming conventions that it
+ * knows about. Ideally keystore shouldn't be used to store random blobs of
+ * data.
+ *
+ * Until that happens, it's necessary to have a separate "get_pubkey" and
+ * "del_key" since the Java code doesn't really communicate what it's
+ * intentions are.
+ */
+int32_t KeyStoreService::get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {
+    ExportResult result;
+    exportKey(name, KM_KEY_FORMAT_X509, NULL, NULL, &result);
+    if (result.resultCode != ::NO_ERROR) {
+        ALOGW("export failed: %d", result.resultCode);
+        return translateResultToLegacyResult(result.resultCode);
+    }
+
+    *pubkey = result.exportData.release();
+    *pubkeyLength = result.dataLength;
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::grant(const String16& name, int32_t granteeUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
+    if (result != ::NO_ERROR) {
+        return result;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
+
+    if (access(filename.string(), R_OK) == -1) {
+        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+    }
+
+    mKeyStore->addGrant(filename.string(), granteeUid);
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
+    if (result != ::NO_ERROR) {
+        return result;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
+
+    if (access(filename.string(), R_OK) == -1) {
+        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+    }
+
+    return mKeyStore->removeGrant(filename.string(), granteeUid) ? ::NO_ERROR : ::KEY_NOT_FOUND;
+}
+
+int64_t KeyStoreService::getmtime(const String16& name) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    if (!checkBinderPermission(P_GET)) {
+        ALOGW("permission denied for %d: getmtime", callingUid);
+        return -1L;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
+
+    if (access(filename.string(), R_OK) == -1) {
+        ALOGW("could not access %s for getmtime", filename.string());
+        return -1L;
+    }
+
+    int fd = TEMP_FAILURE_RETRY(open(filename.string(), O_NOFOLLOW, O_RDONLY));
+    if (fd < 0) {
+        ALOGW("could not open %s for getmtime", filename.string());
+        return -1L;
+    }
+
+    struct stat s;
+    int ret = fstat(fd, &s);
+    close(fd);
+    if (ret == -1) {
+        ALOGW("could not stat %s for getmtime", filename.string());
+        return -1L;
+    }
+
+    return static_cast<int64_t>(s.st_mtime);
+}
+
+int32_t KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
+                                   int32_t destUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    pid_t spid = IPCThreadState::self()->getCallingPid();
+    if (!has_permission(callingUid, P_DUPLICATE, spid)) {
+        ALOGW("permission denied for %d: duplicate", callingUid);
+        return -1L;
+    }
+
+    State state = mKeyStore->getState(get_user_id(callingUid));
+    if (!isKeystoreUnlocked(state)) {
+        ALOGD("calling duplicate in state: %d", state);
+        return state;
+    }
+
+    if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
+        srcUid = callingUid;
+    } else if (!is_granted_to(callingUid, srcUid)) {
+        ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
+        return ::PERMISSION_DENIED;
+    }
+
+    if (destUid == -1) {
+        destUid = callingUid;
+    }
+
+    if (srcUid != destUid) {
+        if (static_cast<uid_t>(srcUid) != callingUid) {
+            ALOGD("can only duplicate from caller to other or to same uid: "
+                  "calling=%d, srcUid=%d, destUid=%d",
+                  callingUid, srcUid, destUid);
+            return ::PERMISSION_DENIED;
+        }
+
+        if (!is_granted_to(callingUid, destUid)) {
+            ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
+            return ::PERMISSION_DENIED;
+        }
+    }
+
+    String8 source8(srcKey);
+    String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid));
+
+    String8 target8(destKey);
+    String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid));
+
+    if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
+        ALOGD("destination already exists: %s", targetFile.string());
+        return ::SYSTEM_ERROR;
+    }
+
+    Blob keyBlob;
+    ResponseCode responseCode =
+        mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
+    if (responseCode != ::NO_ERROR) {
+        return responseCode;
+    }
+
+    return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
+}
+
+int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
+    return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
+}
+
+int32_t KeyStoreService::clear_uid(int64_t targetUid64) {
+    uid_t targetUid = getEffectiveUid(targetUid64);
+    if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
+        return ::PERMISSION_DENIED;
+    }
+
+    String8 prefix = String8::format("%u_", targetUid);
+    Vector<String16> aliases;
+    if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ::NO_ERROR) {
+        return ::SYSTEM_ERROR;
+    }
+
+    for (uint32_t i = 0; i < aliases.size(); i++) {
+        String8 name8(aliases[i]);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+        mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
+    }
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::addRngEntropy(const uint8_t* data, size_t dataLength) {
+    const auto* device = mKeyStore->getDevice();
+    const auto* fallback = mKeyStore->getFallbackDevice();
+    int32_t devResult = KM_ERROR_UNIMPLEMENTED;
+    int32_t fallbackResult = KM_ERROR_UNIMPLEMENTED;
+    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+        device->add_rng_entropy != NULL) {
+        devResult = device->add_rng_entropy(device, data, dataLength);
+    }
+    if (fallback->add_rng_entropy) {
+        fallbackResult = fallback->add_rng_entropy(fallback, data, dataLength);
+    }
+    if (devResult) {
+        return devResult;
+    }
+    if (fallbackResult) {
+        return fallbackResult;
+    }
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
+                                     const uint8_t* entropy, size_t entropyLength, int uid,
+                                     int flags, KeyCharacteristics* outCharacteristics) {
+    uid = getEffectiveUid(uid);
+    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    rc = KM_ERROR_UNIMPLEMENTED;
+    bool isFallback = false;
+    keymaster_key_blob_t blob;
+    keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+
+    const auto* device = mKeyStore->getDevice();
+    const auto* fallback = mKeyStore->getFallbackDevice();
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    if (device == NULL) {
+        return ::SYSTEM_ERROR;
+    }
+    // TODO: Seed from Linux RNG before this.
+    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+        device->generate_key != NULL) {
+        if (!entropy) {
+            rc = KM_ERROR_OK;
+        } else if (device->add_rng_entropy) {
+            rc = device->add_rng_entropy(device, entropy, entropyLength);
+        } else {
+            rc = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (rc == KM_ERROR_OK) {
+            rc =
+                device->generate_key(device, &inParams, &blob, outCharacteristics ? &out : nullptr);
+        }
+    }
+    // If the HW device didn't support generate_key or generate_key failed
+    // fall back to the software implementation.
+    if (rc && fallback->generate_key != NULL) {
+        ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
+        isFallback = true;
+        if (!entropy) {
+            rc = KM_ERROR_OK;
+        } else if (fallback->add_rng_entropy) {
+            rc = fallback->add_rng_entropy(fallback, entropy, entropyLength);
+        } else {
+            rc = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (rc == KM_ERROR_OK) {
+            rc = fallback->generate_key(fallback, &inParams, &blob,
+                                        outCharacteristics ? &out : nullptr);
+        }
+    }
+
+    if (outCharacteristics) {
+        outCharacteristics->characteristics = out;
+    }
+
+    if (rc) {
+        return rc;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+    keyBlob.setFallback(isFallback);
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+    free(const_cast<uint8_t*>(blob.key_material));
+
+    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+}
+
+int32_t KeyStoreService::getKeyCharacteristics(const String16& name,
+                                               const keymaster_blob_t* clientId,
+                                               const keymaster_blob_t* appData,
+                                               KeyCharacteristics* outCharacteristics) {
+    if (!outCharacteristics) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    Blob keyBlob;
+    String8 name8(name);
+    int rc;
+
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        return responseCode;
+    }
+    keymaster_key_blob_t key;
+    key.key_material_size = keyBlob.getLength();
+    key.key_material = keyBlob.getValue();
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+    if (!dev->get_key_characteristics) {
+        ALOGE("device does not implement get_key_characteristics");
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+    rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
+    if (rc != KM_ERROR_OK) {
+        return rc;
+    }
+
+    outCharacteristics->characteristics = out;
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::importKey(const String16& name, const KeymasterArguments& params,
+                                   keymaster_key_format_t format, const uint8_t* keyData,
+                                   size_t keyLength, int uid, int flags,
+                                   KeyCharacteristics* outCharacteristics) {
+    uid = getEffectiveUid(uid);
+    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    rc = KM_ERROR_UNIMPLEMENTED;
+    bool isFallback = false;
+    keymaster_key_blob_t blob;
+    keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+
+    const auto* device = mKeyStore->getDevice();
+    const auto* fallback = mKeyStore->getFallbackDevice();
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    const keymaster_blob_t input = {keyData, keyLength};
+    if (device == NULL) {
+        return ::SYSTEM_ERROR;
+    }
+    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+        device->import_key != NULL) {
+        rc = device->import_key(device, &inParams, format, &input, &blob,
+                                outCharacteristics ? &out : nullptr);
+    }
+    if (rc && fallback->import_key != NULL) {
+        ALOGW("Primary keymaster device failed to import key, falling back to SW.");
+        isFallback = true;
+        rc = fallback->import_key(fallback, &inParams, format, &input, &blob,
+                                  outCharacteristics ? &out : nullptr);
+    }
+    if (outCharacteristics) {
+        outCharacteristics->characteristics = out;
+    }
+
+    if (rc) {
+        return rc;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+    keyBlob.setFallback(isFallback);
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+    free(const_cast<uint8_t*>(blob.key_material));
+
+    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+}
+
+void KeyStoreService::exportKey(const String16& name, keymaster_key_format_t format,
+                                const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
+                                ExportResult* result) {
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    Blob keyBlob;
+    String8 name8(name);
+    int rc;
+
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        result->resultCode = responseCode;
+        return;
+    }
+    keymaster_key_blob_t key;
+    key.key_material_size = keyBlob.getLength();
+    key.key_material = keyBlob.getValue();
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    if (!dev->export_key) {
+        result->resultCode = KM_ERROR_UNIMPLEMENTED;
+        return;
+    }
+    keymaster_blob_t output = {NULL, 0};
+    rc = dev->export_key(dev, format, &key, clientId, appData, &output);
+    result->exportData.reset(const_cast<uint8_t*>(output.data));
+    result->dataLength = output.data_length;
+    result->resultCode = rc ? rc : ::NO_ERROR;
+}
+
+void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name,
+                            keymaster_purpose_t purpose, bool pruneable,
+                            const KeymasterArguments& params, const uint8_t* entropy,
+                            size_t entropyLength, OperationResult* result) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
+        ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
+        result->resultCode = ::PERMISSION_DENIED;
+        return;
+    }
+    if (!checkAllowedOperationParams(params.params)) {
+        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+        return;
+    }
+    Blob keyBlob;
+    String8 name8(name);
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        result->resultCode = responseCode;
+        return;
+    }
+    keymaster_key_blob_t key;
+    key.key_material_size = keyBlob.getLength();
+    key.key_material = keyBlob.getValue();
+    keymaster_operation_handle_t handle;
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    Unique_keymaster_key_characteristics characteristics;
+    characteristics.reset(new keymaster_key_characteristics_t);
+    err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+    const hw_auth_token_t* authToken = NULL;
+    int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
+                                      /*failOnTokenMissing*/ false);
+    // If per-operation auth is needed we need to begin the operation and
+    // the client will need to authorize that operation before calling
+    // update. Any other auth issues stop here.
+    if (authResult != ::NO_ERROR && authResult != ::OP_AUTH_NEEDED) {
+        result->resultCode = authResult;
+        return;
+    }
+    addAuthToParams(&opParams, authToken);
+    // Add entropy to the device first.
+    if (entropy) {
+        if (dev->add_rng_entropy) {
+            err = dev->add_rng_entropy(dev, entropy, entropyLength);
+        } else {
+            err = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+    }
+    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+
+    // Create a keyid for this key.
+    keymaster::km_id_t keyid;
+    if (!enforcement_policy.CreateKeyId(key, &keyid)) {
+        ALOGE("Failed to create a key ID for authorization checking.");
+        result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+        return;
+    }
+
+    // Check that all key authorization policy requirements are met.
+    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+    key_auths.push_back(characteristics->sw_enforced);
+    keymaster::AuthorizationSet operation_params(inParams);
+    err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+                                                0 /* op_handle */, true /* is_begin_operation */);
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+
+    keymaster_key_param_set_t outParams = {NULL, 0};
+
+    // If there are more than MAX_OPERATIONS, abort the oldest operation that was started as
+    // pruneable.
+    while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) {
+        ALOGD("Reached or exceeded concurrent operations limit");
+        if (!pruneOperation()) {
+            break;
+        }
+    }
+
+    err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+    if (err != KM_ERROR_OK) {
+        ALOGE("Got error %d from begin()", err);
+    }
+
+    // If there are too many operations abort the oldest operation that was
+    // started as pruneable and try again.
+    while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
+        ALOGE("Ran out of operation handles");
+        if (!pruneOperation()) {
+            break;
+        }
+        err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+    }
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+
+    sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev, appToken,
+                                                            characteristics.release(), pruneable);
+    if (authToken) {
+        mOperationMap.setOperationAuthToken(operationToken, authToken);
+    }
+    // Return the authentication lookup result. If this is a per operation
+    // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
+    // application should get an auth token using the handle before the
+    // first call to update, which will fail if keystore hasn't received the
+    // auth token.
+    result->resultCode = authResult;
+    result->token = operationToken;
+    result->handle = handle;
+    if (outParams.params) {
+        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+        free(outParams.params);
+    }
+}
+
+void KeyStoreService::update(const sp<IBinder>& token, const KeymasterArguments& params,
+                             const uint8_t* data, size_t dataLength, OperationResult* result) {
+    if (!checkAllowedOperationParams(params.params)) {
+        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+        return;
+    }
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    const keymaster_key_characteristics_t* characteristics;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+        return;
+    }
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
+    if (authResult != ::NO_ERROR) {
+        result->resultCode = authResult;
+        return;
+    }
+    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    keymaster_blob_t input = {data, dataLength};
+    size_t consumed = 0;
+    keymaster_blob_t output = {NULL, 0};
+    keymaster_key_param_set_t outParams = {NULL, 0};
+
+    // Check that all key authorization policy requirements are met.
+    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+    key_auths.push_back(characteristics->sw_enforced);
+    keymaster::AuthorizationSet operation_params(inParams);
+    result->resultCode = enforcement_policy.AuthorizeOperation(
+        purpose, keyid, key_auths, operation_params, handle, false /* is_begin_operation */);
+    if (result->resultCode) {
+        return;
+    }
+
+    keymaster_error_t err =
+        dev->update(dev, handle, &inParams, &input, &consumed, &outParams, &output);
+    result->data.reset(const_cast<uint8_t*>(output.data));
+    result->dataLength = output.data_length;
+    result->inputConsumed = consumed;
+    result->resultCode = err ? (int32_t)err : ::NO_ERROR;
+    if (outParams.params) {
+        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+        free(outParams.params);
+    }
+}
+
+void KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                             const uint8_t* signature, size_t signatureLength,
+                             const uint8_t* entropy, size_t entropyLength,
+                             OperationResult* result) {
+    if (!checkAllowedOperationParams(params.params)) {
+        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+        return;
+    }
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    const keymaster_key_characteristics_t* characteristics;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+        return;
+    }
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
+    if (authResult != ::NO_ERROR) {
+        result->resultCode = authResult;
+        return;
+    }
+    keymaster_error_t err;
+    if (entropy) {
+        if (dev->add_rng_entropy) {
+            err = dev->add_rng_entropy(dev, entropy, entropyLength);
+        } else {
+            err = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+    }
+
+    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    keymaster_blob_t input = {nullptr, 0};
+    keymaster_blob_t sig = {signature, signatureLength};
+    keymaster_blob_t output = {nullptr, 0};
+    keymaster_key_param_set_t outParams = {nullptr, 0};
+
+    // Check that all key authorization policy requirements are met.
+    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+    key_auths.push_back(characteristics->sw_enforced);
+    keymaster::AuthorizationSet operation_params(inParams);
+    err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params, handle,
+                                                false /* is_begin_operation */);
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+
+    err =
+        dev->finish(dev, handle, &inParams, &input /* TODO(swillden): wire up input to finish() */,
+                    &sig, &outParams, &output);
+    // Remove the operation regardless of the result
+    mOperationMap.removeOperation(token);
+    mAuthTokenTable.MarkCompleted(handle);
+
+    result->data.reset(const_cast<uint8_t*>(output.data));
+    result->dataLength = output.data_length;
+    result->resultCode = err ? (int32_t)err : ::NO_ERROR;
+    if (outParams.params) {
+        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+        free(outParams.params);
+    }
+}
+
+int32_t KeyStoreService::abort(const sp<IBinder>& token) {
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
+        return KM_ERROR_INVALID_OPERATION_HANDLE;
+    }
+    mOperationMap.removeOperation(token);
+    int32_t rc;
+    if (!dev->abort) {
+        rc = KM_ERROR_UNIMPLEMENTED;
+    } else {
+        rc = dev->abort(dev, handle);
+    }
+    mAuthTokenTable.MarkCompleted(handle);
+    if (rc) {
+        return rc;
+    }
+    return ::NO_ERROR;
+}
+
+bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    const keymaster_key_characteristics_t* characteristics;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+        return false;
+    }
+    const hw_auth_token_t* authToken = NULL;
+    mOperationMap.getOperationAuthToken(token, &authToken);
+    std::vector<keymaster_key_param_t> ignored;
+    int32_t authResult = addOperationAuthTokenIfNeeded(token, &ignored);
+    return authResult == ::NO_ERROR;
+}
+
+int32_t KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+    if (!checkBinderPermission(P_ADD_AUTH)) {
+        ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
+        return ::PERMISSION_DENIED;
+    }
+    if (length != sizeof(hw_auth_token_t)) {
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+    hw_auth_token_t* authToken = new hw_auth_token_t;
+    memcpy(reinterpret_cast<void*>(authToken), token, sizeof(hw_auth_token_t));
+    // The table takes ownership of authToken.
+    mAuthTokenTable.AddAuthenticationToken(authToken);
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
+                                   KeymasterCertificateChain* outChain) {
+    if (!outChain)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    if (!checkAllowedOperationParams(params.params)) {
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    Blob keyBlob;
+    String8 name8(name);
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        return responseCode;
+    }
+
+    keymaster_key_blob_t key = {keyBlob.getValue(),
+                                static_cast<size_t>(std::max(0, keyBlob.getLength()))};
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    if (!dev->attest_key)
+        return KM_ERROR_UNIMPLEMENTED;
+
+    const keymaster_key_param_set_t in_params = {
+        const_cast<keymaster_key_param_t*>(params.params.data()), params.params.size()};
+    outChain->chain = {nullptr, 0};
+    int32_t rc = dev->attest_key(dev, &key, &in_params, &outChain->chain);
+    if (rc)
+        return rc;
+    return ::NO_ERROR;
+}
+
+/**
+ * Prune the oldest pruneable operation.
+ */
+bool KeyStoreService::pruneOperation() {
+    sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation();
+    ALOGD("Trying to prune operation %p", oldest.get());
+    size_t op_count_before_abort = mOperationMap.getOperationCount();
+    // We mostly ignore errors from abort() because all we care about is whether at least
+    // one operation has been removed.
+    int abort_error = abort(oldest);
+    if (mOperationMap.getOperationCount() >= op_count_before_abort) {
+        ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Get the effective target uid for a binder operation that takes an
+ * optional uid as the target.
+ */
+uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
+    if (targetUid == UID_SELF) {
+        return IPCThreadState::self()->getCallingUid();
+    }
+    return static_cast<uid_t>(targetUid);
+}
+
+/**
+ * Check if the caller of the current binder method has the required
+ * permission and if acting on other uids the grants to do so.
+ */
+bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    pid_t spid = IPCThreadState::self()->getCallingPid();
+    if (!has_permission(callingUid, permission, spid)) {
+        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
+        return false;
+    }
+    if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
+        ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Check if the caller of the current binder method has the required
+ * permission and the target uid is the caller or the caller is system.
+ */
+bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    pid_t spid = IPCThreadState::self()->getCallingPid();
+    if (!has_permission(callingUid, permission, spid)) {
+        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
+        return false;
+    }
+    return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
+}
+
+/**
+ * Check if the caller of the current binder method has the required
+ * permission or the target of the operation is the caller's uid. This is
+ * for operation where the permission is only for cross-uid activity and all
+ * uids are allowed to act on their own (ie: clearing all entries for a
+ * given uid).
+ */
+bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    if (getEffectiveUid(targetUid) == callingUid) {
+        return true;
+    } else {
+        return checkBinderPermission(permission, targetUid);
+    }
+}
+
+/**
+ * Helper method to check that the caller has the required permission as
+ * well as the keystore is in the unlocked state if checkUnlocked is true.
+ *
+ * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
+ * otherwise the state of keystore when not unlocked and checkUnlocked is
+ * true.
+ */
+int32_t KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
+                                                               bool checkUnlocked) {
+    if (!checkBinderPermission(permission, targetUid)) {
+        return ::PERMISSION_DENIED;
+    }
+    State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
+    if (checkUnlocked && !isKeystoreUnlocked(state)) {
+        return state;
+    }
+
+    return ::NO_ERROR;
+}
+
+inline bool KeyStoreService::isKeystoreUnlocked(State state) {
+    switch (state) {
+    case ::STATE_NO_ERROR:
+        return true;
+    case ::STATE_UNINITIALIZED:
+    case ::STATE_LOCKED:
+        return false;
+    }
+    return false;
+}
+
+bool KeyStoreService::isKeyTypeSupported(const keymaster2_device_t* device,
+                                         keymaster_keypair_t keyType) {
+    const int32_t device_api = device->common.module->module_api_version;
+    if (device_api == KEYMASTER_MODULE_API_VERSION_0_2) {
+        switch (keyType) {
+        case TYPE_RSA:
+        case TYPE_DSA:
+        case TYPE_EC:
+            return true;
+        default:
+            return false;
+        }
+    } else if (device_api >= KEYMASTER_MODULE_API_VERSION_0_3) {
+        switch (keyType) {
+        case TYPE_RSA:
+            return true;
+        case TYPE_DSA:
+            return device->flags & KEYMASTER_SUPPORTS_DSA;
+        case TYPE_EC:
+            return device->flags & KEYMASTER_SUPPORTS_EC;
+        default:
+            return false;
+        }
+    } else {
+        return keyType == TYPE_RSA;
+    }
+}
+
+/**
+ * Check that all keymaster_key_param_t's provided by the application are
+ * allowed. Any parameter that keystore adds itself should be disallowed here.
+ */
+bool KeyStoreService::checkAllowedOperationParams(
+    const std::vector<keymaster_key_param_t>& params) {
+    for (auto param : params) {
+        switch (param.tag) {
+        case KM_TAG_AUTH_TOKEN:
+            return false;
+        default:
+            break;
+        }
+    }
+    return true;
+}
+
+keymaster_error_t KeyStoreService::getOperationCharacteristics(
+    const keymaster_key_blob_t& key, const keymaster2_device_t* dev,
+    const std::vector<keymaster_key_param_t>& params, keymaster_key_characteristics_t* out) {
+    UniquePtr<keymaster_blob_t> appId;
+    UniquePtr<keymaster_blob_t> appData;
+    for (auto param : params) {
+        if (param.tag == KM_TAG_APPLICATION_ID) {
+            appId.reset(new keymaster_blob_t);
+            appId->data = param.blob.data;
+            appId->data_length = param.blob.data_length;
+        } else if (param.tag == KM_TAG_APPLICATION_DATA) {
+            appData.reset(new keymaster_blob_t);
+            appData->data = param.blob.data;
+            appData->data_length = param.blob.data_length;
+        }
+    }
+    keymaster_key_characteristics_t result = {{nullptr, 0}, {nullptr, 0}};
+    if (!dev->get_key_characteristics) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+    keymaster_error_t error =
+        dev->get_key_characteristics(dev, &key, appId.get(), appData.get(), &result);
+    if (error == KM_ERROR_OK) {
+        *out = result;
+    }
+    return error;
+}
+
+/**
+ * Get the auth token for this operation from the auth token table.
+ *
+ * Returns ::NO_ERROR if the auth token was set or none was required.
+ *         ::OP_AUTH_NEEDED if it is a per op authorization, no
+ *         authorization token exists for that operation and
+ *         failOnTokenMissing is false.
+ *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
+ *         token for the operation
+ */
+int32_t KeyStoreService::getAuthToken(const keymaster_key_characteristics_t* characteristics,
+                                      keymaster_operation_handle_t handle,
+                                      keymaster_purpose_t purpose,
+                                      const hw_auth_token_t** authToken, bool failOnTokenMissing) {
+
+    std::vector<keymaster_key_param_t> allCharacteristics;
+    for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
+        allCharacteristics.push_back(characteristics->sw_enforced.params[i]);
+    }
+    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
+        allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
+    }
+    keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
+        allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
+    switch (err) {
+    case keymaster::AuthTokenTable::OK:
+    case keymaster::AuthTokenTable::AUTH_NOT_REQUIRED:
+        return ::NO_ERROR;
+    case keymaster::AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
+    case keymaster::AuthTokenTable::AUTH_TOKEN_EXPIRED:
+    case keymaster::AuthTokenTable::AUTH_TOKEN_WRONG_SID:
+        return KM_ERROR_KEY_USER_NOT_AUTHENTICATED;
+    case keymaster::AuthTokenTable::OP_HANDLE_REQUIRED:
+        return failOnTokenMissing ? (int32_t)KM_ERROR_KEY_USER_NOT_AUTHENTICATED
+                                  : (int32_t)::OP_AUTH_NEEDED;
+    default:
+        ALOGE("Unexpected FindAuthorization return value %d", err);
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+}
+
+inline void KeyStoreService::addAuthToParams(std::vector<keymaster_key_param_t>* params,
+                                             const hw_auth_token_t* token) {
+    if (token) {
+        params->push_back(keymaster_param_blob(
+            KM_TAG_AUTH_TOKEN, reinterpret_cast<const uint8_t*>(token), sizeof(hw_auth_token_t)));
+    }
+}
+
+/**
+ * Add the auth token for the operation to the param list if the operation
+ * requires authorization. Uses the cached result in the OperationMap if available
+ * otherwise gets the token from the AuthTokenTable and caches the result.
+ *
+ * Returns ::NO_ERROR if the auth token was added or not needed.
+ *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
+ *         authenticated.
+ *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
+ *         operation token.
+ */
+int32_t KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
+                                                       std::vector<keymaster_key_param_t>* params) {
+    const hw_auth_token_t* authToken = NULL;
+    mOperationMap.getOperationAuthToken(token, &authToken);
+    if (!authToken) {
+        const keymaster2_device_t* dev;
+        keymaster_operation_handle_t handle;
+        const keymaster_key_characteristics_t* characteristics = NULL;
+        keymaster_purpose_t purpose;
+        keymaster::km_id_t keyid;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+            return KM_ERROR_INVALID_OPERATION_HANDLE;
+        }
+        int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
+        if (result != ::NO_ERROR) {
+            return result;
+        }
+        if (authToken) {
+            mOperationMap.setOperationAuthToken(token, authToken);
+        }
+    }
+    addAuthToParams(params, authToken);
+    return ::NO_ERROR;
+}
+
+/**
+ * Translate a result value to a legacy return value. All keystore errors are
+ * preserved and keymaster errors become SYSTEM_ERRORs
+ */
+inline int32_t KeyStoreService::translateResultToLegacyResult(int32_t result) {
+    if (result > 0) {
+        return result;
+    }
+    return ::SYSTEM_ERROR;
+}
+
+keymaster_key_param_t*
+KeyStoreService::getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
+    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
+        if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
+            return &characteristics->hw_enforced.params[i];
+        }
+    }
+    for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
+        if (characteristics->sw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
+            return &characteristics->sw_enforced.params[i];
+        }
+    }
+    return NULL;
+}
+
+void KeyStoreService::addLegacyBeginParams(const String16& name,
+                                           std::vector<keymaster_key_param_t>& params) {
+    // All legacy keys are DIGEST_NONE/PAD_NONE.
+    params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+    params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+
+    // Look up the algorithm of the key.
+    KeyCharacteristics characteristics;
+    int32_t rc = getKeyCharacteristics(name, NULL, NULL, &characteristics);
+    if (rc != ::NO_ERROR) {
+        ALOGE("Failed to get key characteristics");
+        return;
+    }
+    keymaster_key_param_t* algorithm = getKeyAlgorithm(&characteristics.characteristics);
+    if (!algorithm) {
+        ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
+        return;
+    }
+    params.push_back(*algorithm);
+}
+
+int32_t KeyStoreService::doLegacySignVerify(const String16& name, const uint8_t* data,
+                                            size_t length, uint8_t** out, size_t* outLength,
+                                            const uint8_t* signature, size_t signatureLength,
+                                            keymaster_purpose_t purpose) {
+
+    std::basic_stringstream<uint8_t> outBuffer;
+    OperationResult result;
+    KeymasterArguments inArgs;
+    addLegacyBeginParams(name, inArgs.params);
+    sp<IBinder> appToken(new BBinder);
+    sp<IBinder> token;
+
+    begin(appToken, name, purpose, true, inArgs, NULL, 0, &result);
+    if (result.resultCode != ResponseCode::NO_ERROR) {
+        if (result.resultCode == ::KEY_NOT_FOUND) {
+            ALOGW("Key not found");
+        } else {
+            ALOGW("Error in begin: %d", result.resultCode);
+        }
+        return translateResultToLegacyResult(result.resultCode);
+    }
+    inArgs.params.clear();
+    token = result.token;
+    size_t consumed = 0;
+    size_t lastConsumed = 0;
+    do {
+        update(token, inArgs, data + consumed, length - consumed, &result);
+        if (result.resultCode != ResponseCode::NO_ERROR) {
+            ALOGW("Error in update: %d", result.resultCode);
+            return translateResultToLegacyResult(result.resultCode);
+        }
+        if (out) {
+            outBuffer.write(result.data.get(), result.dataLength);
+        }
+        lastConsumed = result.inputConsumed;
+        consumed += lastConsumed;
+    } while (consumed < length && lastConsumed > 0);
+
+    if (consumed != length) {
+        ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
+        return ::SYSTEM_ERROR;
+    }
+
+    finish(token, inArgs, signature, signatureLength, NULL, 0, &result);
+    if (result.resultCode != ResponseCode::NO_ERROR) {
+        ALOGW("Error in finish: %d", result.resultCode);
+        return translateResultToLegacyResult(result.resultCode);
+    }
+    if (out) {
+        outBuffer.write(result.data.get(), result.dataLength);
+    }
+
+    if (out) {
+        auto buf = outBuffer.str();
+        *out = new uint8_t[buf.size()];
+        memcpy(*out, buf.c_str(), buf.size());
+        *outLength = buf.size();
+    }
+
+    return ::NO_ERROR;
+}
+
+}  // namespace android
diff --git a/security/keystore/key_store_service.h b/security/keystore/key_store_service.h
new file mode 100644
index 0000000..3efae47
--- /dev/null
+++ b/security/keystore/key_store_service.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 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 KEYSTORE_KEYSTORE_SERVICE_H_
+#define KEYSTORE_KEYSTORE_SERVICE_H_
+
+#include <keystore/IKeystoreService.h>
+
+#include "auth_token_table.h"
+#include "keystore.h"
+#include "keystore_keymaster_enforcement.h"
+#include "operation.h"
+#include "permissions.h"
+
+namespace android {
+
+class KeyStoreService : public BnKeystoreService, public IBinder::DeathRecipient {
+  public:
+    explicit KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
+
+    void binderDied(const wp<IBinder>& who);
+
+    int32_t getState(int32_t userId);
+
+    int32_t get(const String16& name, uint8_t** item, size_t* itemLength);
+    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int targetUid,
+                   int32_t flags);
+    int32_t del(const String16& name, int targetUid);
+    int32_t exist(const String16& name, int targetUid);
+    int32_t list(const String16& prefix, int targetUid, Vector<String16>* matches);
+
+    int32_t reset();
+
+    int32_t onUserPasswordChanged(int32_t userId, const String16& password);
+    int32_t onUserAdded(int32_t userId, int32_t parentId);
+    int32_t onUserRemoved(int32_t userId);
+
+    int32_t lock(int32_t userId);
+    int32_t unlock(int32_t userId, const String16& pw);
+
+    bool isEmpty(int32_t userId);
+
+    int32_t generate(const String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
+                     int32_t flags, Vector<sp<KeystoreArg>>* args);
+    int32_t import(const String16& name, const uint8_t* data, size_t length, int targetUid,
+                   int32_t flags);
+    int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
+                 size_t* outLength);
+    int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
+                   const uint8_t* signature, size_t signatureLength);
+
+    /*
+     * TODO: The abstraction between things stored in hardware and regular blobs
+     * of data stored on the filesystem should be moved down to keystore itself.
+     * Unfortunately the Java code that calls this has naming conventions that it
+     * knows about. Ideally keystore shouldn't be used to store random blobs of
+     * data.
+     *
+     * Until that happens, it's necessary to have a separate "get_pubkey" and
+     * "del_key" since the Java code doesn't really communicate what it's
+     * intentions are.
+     */
+    int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength);
+
+    int32_t grant(const String16& name, int32_t granteeUid);
+    int32_t ungrant(const String16& name, int32_t granteeUid);
+
+    int64_t getmtime(const String16& name);
+
+    int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
+                      int32_t destUid);
+
+    int32_t is_hardware_backed(const String16& keyType);
+
+    int32_t clear_uid(int64_t targetUid64);
+
+    int32_t addRngEntropy(const uint8_t* data, size_t dataLength);
+    int32_t generateKey(const String16& name, const KeymasterArguments& params,
+                        const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+                        KeyCharacteristics* outCharacteristics);
+    int32_t getKeyCharacteristics(const String16& name, const keymaster_blob_t* clientId,
+                                  const keymaster_blob_t* appData,
+                                  KeyCharacteristics* outCharacteristics);
+    int32_t importKey(const String16& name, const KeymasterArguments& params,
+                      keymaster_key_format_t format, const uint8_t* keyData, size_t keyLength,
+                      int uid, int flags, KeyCharacteristics* outCharacteristics);
+    void exportKey(const String16& name, keymaster_key_format_t format,
+                   const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
+                   ExportResult* result);
+    void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
+               bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
+               size_t entropyLength, OperationResult* result);
+    void update(const sp<IBinder>& token, const KeymasterArguments& params, const uint8_t* data,
+                size_t dataLength, OperationResult* result);
+    void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                const uint8_t* signature, size_t signatureLength, const uint8_t* entropy,
+                size_t entropyLength, OperationResult* result);
+    int32_t abort(const sp<IBinder>& token);
+
+    bool isOperationAuthorized(const sp<IBinder>& token);
+
+    int32_t addAuthToken(const uint8_t* token, size_t length);
+
+    int32_t attestKey(const String16& name, const KeymasterArguments& params,
+                      KeymasterCertificateChain* outChain) override;
+
+  private:
+    static const int32_t UID_SELF = -1;
+
+    /**
+     * Prune the oldest pruneable operation.
+     */
+    bool pruneOperation();
+
+    /**
+     * Get the effective target uid for a binder operation that takes an
+     * optional uid as the target.
+     */
+    uid_t getEffectiveUid(int32_t targetUid);
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission and if acting on other uids the grants to do so.
+     */
+    bool checkBinderPermission(perm_t permission, int32_t targetUid = UID_SELF);
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission and the target uid is the caller or the caller is system.
+     */
+    bool checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid);
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission or the target of the operation is the caller's uid. This is
+     * for operation where the permission is only for cross-uid activity and all
+     * uids are allowed to act on their own (ie: clearing all entries for a
+     * given uid).
+     */
+    bool checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid);
+
+    /**
+     * Helper method to check that the caller has the required permission as
+     * well as the keystore is in the unlocked state if checkUnlocked is true.
+     *
+     * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
+     * otherwise the state of keystore when not unlocked and checkUnlocked is
+     * true.
+     */
+    int32_t checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid = -1,
+                                                  bool checkUnlocked = true);
+
+    bool isKeystoreUnlocked(State state);
+
+    bool isKeyTypeSupported(const keymaster2_device_t* device, keymaster_keypair_t keyType);
+
+    /**
+     * Check that all keymaster_key_param_t's provided by the application are
+     * allowed. Any parameter that keystore adds itself should be disallowed here.
+     */
+    bool checkAllowedOperationParams(const std::vector<keymaster_key_param_t>& params);
+
+    keymaster_error_t getOperationCharacteristics(const keymaster_key_blob_t& key,
+                                                  const keymaster2_device_t* dev,
+                                                  const std::vector<keymaster_key_param_t>& params,
+                                                  keymaster_key_characteristics_t* out);
+
+    /**
+     * Get the auth token for this operation from the auth token table.
+     *
+     * Returns ::NO_ERROR if the auth token was set or none was required.
+     *         ::OP_AUTH_NEEDED if it is a per op authorization, no
+     *         authorization token exists for that operation and
+     *         failOnTokenMissing is false.
+     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
+     *         token for the operation
+     */
+    int32_t getAuthToken(const keymaster_key_characteristics_t* characteristics,
+                         keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
+                         const hw_auth_token_t** authToken, bool failOnTokenMissing = true);
+
+    void addAuthToParams(std::vector<keymaster_key_param_t>* params, const hw_auth_token_t* token);
+
+    /**
+     * Add the auth token for the operation to the param list if the operation
+     * requires authorization. Uses the cached result in the OperationMap if available
+     * otherwise gets the token from the AuthTokenTable and caches the result.
+     *
+     * Returns ::NO_ERROR if the auth token was added or not needed.
+     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
+     *         authenticated.
+     *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
+     *         operation token.
+     */
+    int32_t addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
+                                          std::vector<keymaster_key_param_t>* params);
+
+    /**
+     * Translate a result value to a legacy return value. All keystore errors are
+     * preserved and keymaster errors become SYSTEM_ERRORs
+     */
+    int32_t translateResultToLegacyResult(int32_t result);
+
+    keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics);
+
+    void addLegacyBeginParams(const String16& name, std::vector<keymaster_key_param_t>& params);
+
+    int32_t doLegacySignVerify(const String16& name, const uint8_t* data, size_t length,
+                               uint8_t** out, size_t* outLength, const uint8_t* signature,
+                               size_t signatureLength, keymaster_purpose_t purpose);
+
+    ::KeyStore* mKeyStore;
+    OperationMap mOperationMap;
+    keymaster::AuthTokenTable mAuthTokenTable;
+    KeystoreKeymasterEnforcement enforcement_policy;
+};
+
+};  // namespace android
+
+#endif  // KEYSTORE_KEYSTORE_SERVICE_H_
diff --git a/security/keystore/keyblob_utils.cpp b/security/keystore/keyblob_utils.cpp
new file mode 100644
index 0000000..3616822
--- /dev/null
+++ b/security/keystore/keyblob_utils.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <keystore/keystore.h>
+
+/**
+ * When a key is being migrated from a software keymaster implementation
+ * to a hardware keymaster implementation, the first 4 bytes of the key_blob
+ * given to the hardware implementation will be equal to SOFT_KEY_MAGIC.
+ * The hardware implementation should import these PKCS#8 format keys which
+ * are encoded like this:
+ *
+ * 4-byte SOFT_KEY_MAGIC
+ *
+ * 4-byte 32-bit integer big endian for public_key_length. This may be zero
+ *     length which indicates the public key should be derived from the
+ *     private key.
+ *
+ * public_key_length bytes of public key (may be empty)
+ *
+ * 4-byte 32-bit integer big endian for private_key_length
+ *
+ * private_key_length bytes of private key
+ */
+static const uint8_t SOFT_KEY_MAGIC[] = { 'P', 'K', '#', '8' };
+
+size_t get_softkey_header_size() {
+    return sizeof(SOFT_KEY_MAGIC);
+}
+
+uint8_t* add_softkey_header(uint8_t* key_blob, size_t key_blob_length) {
+    if (key_blob_length < sizeof(SOFT_KEY_MAGIC)) {
+        return NULL;
+    }
+
+    memcpy(key_blob, SOFT_KEY_MAGIC, sizeof(SOFT_KEY_MAGIC));
+
+    return key_blob + sizeof(SOFT_KEY_MAGIC);
+}
+
+bool is_softkey(const uint8_t* key_blob, const size_t key_blob_length) {
+    if (key_blob_length < sizeof(SOFT_KEY_MAGIC)) {
+        return false;
+    }
+
+    return !memcmp(key_blob, SOFT_KEY_MAGIC, sizeof(SOFT_KEY_MAGIC));
+}
diff --git a/security/keystore/keystore.cpp b/security/keystore/keystore.cpp
new file mode 100644
index 0000000..3c87fd5
--- /dev/null
+++ b/security/keystore/keystore.cpp
@@ -0,0 +1,756 @@
+/*
+ * Copyright (C) 2016 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.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+
+#include <openssl/bio.h>
+
+#include <utils/String16.h>
+
+#include <keystore/IKeystoreService.h>
+
+#include "keystore_utils.h"
+#include "permissions.h"
+
+const char* KeyStore::sOldMasterKey = ".masterkey";
+const char* KeyStore::sMetaDataFile = ".metadata";
+
+const android::String16 KeyStore::sRSAKeyType("RSA");
+const android::String16 KeyStore::sECKeyType("EC");
+
+KeyStore::KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback)
+    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback) {
+    memset(&mMetaData, '\0', sizeof(mMetaData));
+}
+
+KeyStore::~KeyStore() {
+    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
+        delete *it;
+    }
+    mGrants.clear();
+
+    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
+         it++) {
+        delete *it;
+    }
+    mMasterKeys.clear();
+}
+
+ResponseCode KeyStore::initialize() {
+    readMetaData();
+    if (upgradeKeystore()) {
+        writeMetaData();
+    }
+
+    return ::NO_ERROR;
+}
+
+ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return userState->initialize(pw, mEntropy);
+}
+
+ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
+    UserState* userState = getUserState(dstUser);
+    UserState* initState = getUserState(srcUser);
+    return userState->copyMasterKey(initState);
+}
+
+ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return userState->writeMasterKey(pw, mEntropy);
+}
+
+ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return userState->readMasterKey(pw, mEntropy);
+}
+
+/* Here is the encoding of keys. This is necessary in order to allow arbitrary
+ * characters in keys. Characters in [0-~] are not encoded. Others are encoded
+ * into two bytes. The first byte is one of [+-.] which represents the first
+ * two bits of the character. The second byte encodes the rest of the bits into
+ * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
+ * that Base64 cannot be used here due to the need of prefix match on keys. */
+
+static size_t encode_key_length(const android::String8& keyName) {
+    const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
+    size_t length = keyName.length();
+    for (int i = length; i > 0; --i, ++in) {
+        if (*in < '0' || *in > '~') {
+            ++length;
+        }
+    }
+    return length;
+}
+
+static int encode_key(char* out, const android::String8& keyName) {
+    const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
+    size_t length = keyName.length();
+    for (int i = length; i > 0; --i, ++in, ++out) {
+        if (*in < '0' || *in > '~') {
+            *out = '+' + (*in >> 6);
+            *++out = '0' + (*in & 0x3F);
+            ++length;
+        } else {
+            *out = *in;
+        }
+    }
+    *out = '\0';
+    return length;
+}
+
+android::String8 KeyStore::getKeyName(const android::String8& keyName) {
+    std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
+    encode_key(encoded.data(), keyName);
+    return android::String8(encoded.data());
+}
+
+android::String8 KeyStore::getKeyNameForUid(const android::String8& keyName, uid_t uid) {
+    std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
+    encode_key(encoded.data(), keyName);
+    return android::String8::format("%u_%s", uid, encoded.data());
+}
+
+android::String8 KeyStore::getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid) {
+    std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
+    encode_key(encoded.data(), keyName);
+    return android::String8::format("%s/%u_%s", getUserStateByUid(uid)->getUserDirName(), uid,
+                                    encoded.data());
+}
+
+void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
+    android::String8 prefix("");
+    android::Vector<android::String16> aliases;
+    UserState* userState = getUserState(userId);
+    if (list(prefix, &aliases, userId) != ::NO_ERROR) {
+        return;
+    }
+    for (uint32_t i = 0; i < aliases.size(); i++) {
+        android::String8 filename(aliases[i]);
+        filename = android::String8::format("%s/%s", userState->getUserDirName(),
+                                            getKeyName(filename).string());
+        bool shouldDelete = true;
+        if (keepUnenryptedEntries) {
+            Blob blob;
+            ResponseCode rc = get(filename, &blob, ::TYPE_ANY, userId);
+
+            /* get can fail if the blob is encrypted and the state is
+             * not unlocked, only skip deleting blobs that were loaded and
+             * who are not encrypted. If there are blobs we fail to read for
+             * other reasons err on the safe side and delete them since we
+             * can't tell if they're encrypted.
+             */
+            shouldDelete = !(rc == ::NO_ERROR && !blob.isEncrypted());
+        }
+        if (shouldDelete) {
+            del(filename, ::TYPE_ANY, userId);
+        }
+    }
+    if (!userState->deleteMasterKey()) {
+        ALOGE("Failed to delete user %d's master key", userId);
+    }
+    if (!keepUnenryptedEntries) {
+        if (!userState->reset()) {
+            ALOGE("Failed to remove user %d's directory", userId);
+        }
+    }
+}
+
+bool KeyStore::isEmpty(uid_t userId) const {
+    const UserState* userState = getUserState(userId);
+    if (userState == NULL) {
+        return true;
+    }
+
+    DIR* dir = opendir(userState->getUserDirName());
+    if (!dir) {
+        return true;
+    }
+
+    bool result = true;
+    struct dirent* file;
+    while ((file = readdir(dir)) != NULL) {
+        // We only care about files.
+        if (file->d_type != DT_REG) {
+            continue;
+        }
+
+        // Skip anything that starts with a "."
+        if (file->d_name[0] == '.') {
+            continue;
+        }
+
+        result = false;
+        break;
+    }
+    closedir(dir);
+    return result;
+}
+
+void KeyStore::lock(uid_t userId) {
+    UserState* userState = getUserState(userId);
+    userState->zeroizeMasterKeysInMemory();
+    userState->setState(STATE_LOCKED);
+}
+
+ResponseCode KeyStore::get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    ResponseCode rc =
+        keyBlob->readBlob(filename, userState->getDecryptionKey(), userState->getState());
+    if (rc != NO_ERROR) {
+        return rc;
+    }
+
+    const uint8_t version = keyBlob->getVersion();
+    if (version < CURRENT_BLOB_VERSION) {
+        /* If we upgrade the key, we need to write it to disk again. Then
+         * it must be read it again since the blob is encrypted each time
+         * it's written.
+         */
+        if (upgradeBlob(filename, keyBlob, version, type, userId)) {
+            if ((rc = this->put(filename, keyBlob, userId)) != NO_ERROR ||
+                (rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
+                                        userState->getState())) != NO_ERROR) {
+                return rc;
+            }
+        }
+    }
+
+    /*
+     * This will upgrade software-backed keys to hardware-backed keys when
+     * the HAL for the device supports the newer key types.
+     */
+    if (rc == NO_ERROR && type == TYPE_KEY_PAIR &&
+        mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2 &&
+        keyBlob->isFallback()) {
+        ResponseCode imported =
+            importKey(keyBlob->getValue(), keyBlob->getLength(), filename, userId,
+                      keyBlob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
+
+        // The HAL allowed the import, reget the key to have the "fresh"
+        // version.
+        if (imported == NO_ERROR) {
+            rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
+        }
+    }
+
+    // Keymaster 0.3 keys are valid keymaster 1.0 keys, so silently upgrade.
+    if (keyBlob->getType() == TYPE_KEY_PAIR) {
+        keyBlob->setType(TYPE_KEYMASTER_10);
+        rc = this->put(filename, keyBlob, userId);
+    }
+
+    if (type != TYPE_ANY && keyBlob->getType() != type) {
+        ALOGW("key found but type doesn't match: %d vs %d", keyBlob->getType(), type);
+        return KEY_NOT_FOUND;
+    }
+
+    return rc;
+}
+
+ResponseCode KeyStore::put(const char* filename, Blob* keyBlob, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState(),
+                              mEntropy);
+}
+
+ResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t userId) {
+    Blob keyBlob;
+    ResponseCode rc = get(filename, &keyBlob, type, userId);
+    if (rc == ::VALUE_CORRUPTED) {
+        // The file is corrupt, the best we can do is rm it.
+        return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+    }
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
+        // A device doesn't have to implement delete_key.
+        if (mDevice->delete_key != NULL && !keyBlob.isFallback()) {
+            keymaster_key_blob_t blob = {keyBlob.getValue(),
+                                         static_cast<size_t>(keyBlob.getLength())};
+            if (mDevice->delete_key(mDevice, &blob)) {
+                rc = ::SYSTEM_ERROR;
+            }
+        }
+    }
+    if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
+        auto* dev = getDeviceForBlob(keyBlob);
+        if (dev->delete_key) {
+            keymaster_key_blob_t blob;
+            blob.key_material = keyBlob.getValue();
+            blob.key_material_size = keyBlob.getLength();
+            dev->delete_key(dev, &blob);
+        }
+    }
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+}
+
+/*
+ * Converts from the "escaped" format on disk to actual name.
+ * This will be smaller than the input string.
+ *
+ * Characters that should combine with the next at the end will be truncated.
+ */
+static size_t decode_key_length(const char* in, size_t length) {
+    size_t outLength = 0;
+
+    for (const char* end = in + length; in < end; in++) {
+        /* This combines with the next character. */
+        if (*in < '0' || *in > '~') {
+            continue;
+        }
+
+        outLength++;
+    }
+    return outLength;
+}
+
+static void decode_key(char* out, const char* in, size_t length) {
+    for (const char* end = in + length; in < end; in++) {
+        if (*in < '0' || *in > '~') {
+            /* Truncate combining characters at the end. */
+            if (in + 1 >= end) {
+                break;
+            }
+
+            *out = (*in++ - '+') << 6;
+            *out++ |= (*in - '0') & 0x3F;
+        } else {
+            *out++ = *in;
+        }
+    }
+    *out = '\0';
+}
+
+ResponseCode KeyStore::list(const android::String8& prefix,
+                            android::Vector<android::String16>* matches, uid_t userId) {
+
+    UserState* userState = getUserState(userId);
+    size_t n = prefix.length();
+
+    DIR* dir = opendir(userState->getUserDirName());
+    if (!dir) {
+        ALOGW("can't open directory for user: %s", strerror(errno));
+        return ::SYSTEM_ERROR;
+    }
+
+    struct dirent* file;
+    while ((file = readdir(dir)) != NULL) {
+        // We only care about files.
+        if (file->d_type != DT_REG) {
+            continue;
+        }
+
+        // Skip anything that starts with a "."
+        if (file->d_name[0] == '.') {
+            continue;
+        }
+
+        if (!strncmp(prefix.string(), file->d_name, n)) {
+            const char* p = &file->d_name[n];
+            size_t plen = strlen(p);
+
+            size_t extra = decode_key_length(p, plen);
+            char* match = (char*)malloc(extra + 1);
+            if (match != NULL) {
+                decode_key(match, p, plen);
+                matches->push(android::String16(match, extra));
+                free(match);
+            } else {
+                ALOGW("could not allocate match of size %zd", extra);
+            }
+        }
+    }
+    closedir(dir);
+    return ::NO_ERROR;
+}
+
+void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
+    const grant_t* existing = getGrant(filename, granteeUid);
+    if (existing == NULL) {
+        grant_t* grant = new grant_t;
+        grant->uid = granteeUid;
+        grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
+        mGrants.add(grant);
+    }
+}
+
+bool KeyStore::removeGrant(const char* filename, uid_t granteeUid) {
+    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
+        grant_t* grant = *it;
+        if (grant->uid == granteeUid &&
+            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
+            mGrants.erase(it);
+            return true;
+        }
+    }
+    return false;
+}
+
+ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* filename,
+                                 uid_t userId, int32_t flags) {
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
+    if (!pkcs8.get()) {
+        return ::SYSTEM_ERROR;
+    }
+    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+    if (!pkey.get()) {
+        return ::SYSTEM_ERROR;
+    }
+    int type = EVP_PKEY_type(pkey->type);
+    android::KeymasterArguments params;
+    add_legacy_key_authorizations(type, &params.params);
+    switch (type) {
+    case EVP_PKEY_RSA:
+        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+        break;
+    case EVP_PKEY_EC:
+        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+        break;
+    default:
+        ALOGW("Unsupported key type %d", type);
+        return ::SYSTEM_ERROR;
+    }
+
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    keymaster_blob_t input = {key, keyLen};
+    keymaster_key_blob_t blob = {nullptr, 0};
+    bool isFallback = false;
+    keymaster_error_t error = mDevice->import_key(mDevice, &inParams, KM_KEY_FORMAT_PKCS8, &input,
+                                                  &blob, NULL /* characteristics */);
+    if (error != KM_ERROR_OK) {
+        ALOGE("Keymaster error %d importing key pair, falling back", error);
+
+        /*
+         * There should be no way to get here.  Fallback shouldn't ever really happen
+         * because the main device may be many (SW, KM0/SW hybrid, KM1/SW hybrid), but it must
+         * provide full support of the API.  In any case, we'll do the fallback just for
+         * consistency... and I suppose to cover for broken HW implementations.
+         */
+        error = mFallbackDevice->import_key(mFallbackDevice, &inParams, KM_KEY_FORMAT_PKCS8, &input,
+                                            &blob, NULL /* characteristics */);
+        isFallback = true;
+
+        if (error) {
+            ALOGE("Keymaster error while importing key pair with fallback: %d", error);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
+    free(const_cast<uint8_t*>(blob.key_material));
+
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+    keyBlob.setFallback(isFallback);
+
+    return put(filename, &keyBlob, userId);
+}
+
+bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
+    if (mDevice == NULL) {
+        ALOGW("can't get keymaster device");
+        return false;
+    }
+
+    if (sRSAKeyType == keyType) {
+        return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0;
+    } else {
+        return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0 &&
+               (mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2);
+    }
+}
+
+ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
+                                     const uid_t uid, const BlobType type) {
+    android::String8 filepath8(getKeyNameForUidWithDir(keyName, uid));
+    uid_t userId = get_user_id(uid);
+
+    ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
+    if (responseCode == NO_ERROR) {
+        return responseCode;
+    }
+
+    // If this is one of the legacy UID->UID mappings, use it.
+    uid_t euid = get_keystore_euid(uid);
+    if (euid != uid) {
+        filepath8 = getKeyNameForUidWithDir(keyName, euid);
+        responseCode = get(filepath8.string(), keyBlob, type, userId);
+        if (responseCode == NO_ERROR) {
+            return responseCode;
+        }
+    }
+
+    // They might be using a granted key.
+    android::String8 filename8 = getKeyName(keyName);
+    char* end;
+    strtoul(filename8.string(), &end, 10);
+    if (end[0] != '_' || end[1] == 0) {
+        return KEY_NOT_FOUND;
+    }
+    filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
+                                         filename8.string());
+    if (!hasGrant(filepath8.string(), uid)) {
+        return responseCode;
+    }
+
+    // It is a granted key. Try to load it.
+    return get(filepath8.string(), keyBlob, type, userId);
+}
+
+UserState* KeyStore::getUserState(uid_t userId) {
+    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
+         it++) {
+        UserState* state = *it;
+        if (state->getUserId() == userId) {
+            return state;
+        }
+    }
+
+    UserState* userState = new UserState(userId);
+    if (!userState->initialize()) {
+        /* There's not much we can do if initialization fails. Trying to
+         * unlock the keystore for that user will fail as well, so any
+         * subsequent request for this user will just return SYSTEM_ERROR.
+         */
+        ALOGE("User initialization failed for %u; subsuquent operations will fail", userId);
+    }
+    mMasterKeys.add(userState);
+    return userState;
+}
+
+UserState* KeyStore::getUserStateByUid(uid_t uid) {
+    uid_t userId = get_user_id(uid);
+    return getUserState(userId);
+}
+
+const UserState* KeyStore::getUserState(uid_t userId) const {
+    for (android::Vector<UserState*>::const_iterator it(mMasterKeys.begin());
+         it != mMasterKeys.end(); it++) {
+        UserState* state = *it;
+        if (state->getUserId() == userId) {
+            return state;
+        }
+    }
+
+    return NULL;
+}
+
+const UserState* KeyStore::getUserStateByUid(uid_t uid) const {
+    uid_t userId = get_user_id(uid);
+    return getUserState(userId);
+}
+
+const grant_t* KeyStore::getGrant(const char* filename, uid_t uid) const {
+    for (android::Vector<grant_t*>::const_iterator it(mGrants.begin()); it != mGrants.end(); it++) {
+        grant_t* grant = *it;
+        if (grant->uid == uid &&
+            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
+            return grant;
+        }
+    }
+    return NULL;
+}
+
+bool KeyStore::upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
+                           const BlobType type, uid_t uid) {
+    bool updated = false;
+    uint8_t version = oldVersion;
+
+    /* From V0 -> V1: All old types were unknown */
+    if (version == 0) {
+        ALOGV("upgrading to version 1 and setting type %d", type);
+
+        blob->setType(type);
+        if (type == TYPE_KEY_PAIR) {
+            importBlobAsKey(blob, filename, uid);
+        }
+        version = 1;
+        updated = true;
+    }
+
+    /* From V1 -> V2: All old keys were encrypted */
+    if (version == 1) {
+        ALOGV("upgrading to version 2");
+
+        blob->setEncrypted(true);
+        version = 2;
+        updated = true;
+    }
+
+    /*
+     * If we've updated, set the key blob to the right version
+     * and write it.
+     */
+    if (updated) {
+        ALOGV("updated and writing file %s", filename);
+        blob->setVersion(version);
+    }
+
+    return updated;
+}
+
+struct BIO_Delete {
+    void operator()(BIO* p) const { BIO_free(p); }
+};
+typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
+
+ResponseCode KeyStore::importBlobAsKey(Blob* blob, const char* filename, uid_t uid) {
+    // We won't even write to the blob directly with this BIO, so const_cast is okay.
+    Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
+    if (b.get() == NULL) {
+        ALOGE("Problem instantiating BIO");
+        return SYSTEM_ERROR;
+    }
+
+    Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
+    if (pkey.get() == NULL) {
+        ALOGE("Couldn't read old PEM file");
+        return SYSTEM_ERROR;
+    }
+
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
+    int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
+    if (len < 0) {
+        ALOGE("Couldn't measure PKCS#8 length");
+        return SYSTEM_ERROR;
+    }
+
+    UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
+    uint8_t* tmp = pkcs8key.get();
+    if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
+        ALOGE("Couldn't convert to PKCS#8");
+        return SYSTEM_ERROR;
+    }
+
+    ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
+                                blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
+    if (rc != NO_ERROR) {
+        return rc;
+    }
+
+    return get(filename, blob, TYPE_KEY_PAIR, uid);
+}
+
+void KeyStore::readMetaData() {
+    int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
+    if (in < 0) {
+        return;
+    }
+    size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData));
+    if (fileLength != sizeof(mMetaData)) {
+        ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData));
+    }
+    close(in);
+}
+
+void KeyStore::writeMetaData() {
+    const char* tmpFileName = ".metadata.tmp";
+    int out =
+        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+    if (out < 0) {
+        ALOGE("couldn't write metadata file: %s", strerror(errno));
+        return;
+    }
+    size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData));
+    if (fileLength != sizeof(mMetaData)) {
+        ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
+              sizeof(mMetaData));
+    }
+    close(out);
+    rename(tmpFileName, sMetaDataFile);
+}
+
+bool KeyStore::upgradeKeystore() {
+    bool upgraded = false;
+
+    if (mMetaData.version == 0) {
+        UserState* userState = getUserStateByUid(0);
+
+        // Initialize first so the directory is made.
+        userState->initialize();
+
+        // Migrate the old .masterkey file to user 0.
+        if (access(sOldMasterKey, R_OK) == 0) {
+            if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
+                ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
+                return false;
+            }
+        }
+
+        // Initialize again in case we had a key.
+        userState->initialize();
+
+        // Try to migrate existing keys.
+        DIR* dir = opendir(".");
+        if (!dir) {
+            // Give up now; maybe we can upgrade later.
+            ALOGE("couldn't open keystore's directory; something is wrong");
+            return false;
+        }
+
+        struct dirent* file;
+        while ((file = readdir(dir)) != NULL) {
+            // We only care about files.
+            if (file->d_type != DT_REG) {
+                continue;
+            }
+
+            // Skip anything that starts with a "."
+            if (file->d_name[0] == '.') {
+                continue;
+            }
+
+            // Find the current file's user.
+            char* end;
+            unsigned long thisUid = strtoul(file->d_name, &end, 10);
+            if (end[0] != '_' || end[1] == 0) {
+                continue;
+            }
+            UserState* otherUser = getUserStateByUid(thisUid);
+            if (otherUser->getUserId() != 0) {
+                unlinkat(dirfd(dir), file->d_name, 0);
+            }
+
+            // Rename the file into user directory.
+            DIR* otherdir = opendir(otherUser->getUserDirName());
+            if (otherdir == NULL) {
+                ALOGW("couldn't open user directory for rename");
+                continue;
+            }
+            if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
+                ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
+            }
+            closedir(otherdir);
+        }
+        closedir(dir);
+
+        mMetaData.version = 1;
+        upgraded = true;
+    }
+
+    return upgraded;
+}
diff --git a/security/keystore/keystore.h b/security/keystore/keystore.h
new file mode 100644
index 0000000..62d7294
--- /dev/null
+++ b/security/keystore/keystore.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 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 KEYSTORE_KEYSTORE_H_
+#define KEYSTORE_KEYSTORE_H_
+
+#include "user_state.h"
+
+#include <hardware/keymaster2.h>
+
+#include <utils/Vector.h>
+
+#include "blob.h"
+
+typedef struct {
+    uint32_t uid;
+    const uint8_t* filename;
+} grant_t;
+
+class KeyStore {
+  public:
+    KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback);
+    ~KeyStore();
+
+    keymaster2_device_t* getDevice() const { return mDevice; }
+
+    keymaster2_device_t* getFallbackDevice() const { return mFallbackDevice; }
+
+    keymaster2_device_t* getDeviceForBlob(const Blob& blob) const {
+        return blob.isFallback() ? mFallbackDevice : mDevice;
+    }
+
+    ResponseCode initialize();
+
+    State getState(uid_t userId) { return getUserState(userId)->getState(); }
+
+    ResponseCode initializeUser(const android::String8& pw, uid_t userId);
+
+    ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser);
+    ResponseCode writeMasterKey(const android::String8& pw, uid_t userId);
+    ResponseCode readMasterKey(const android::String8& pw, uid_t userId);
+
+    android::String8 getKeyName(const android::String8& keyName);
+    android::String8 getKeyNameForUid(const android::String8& keyName, uid_t uid);
+    android::String8 getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid);
+
+    /*
+     * Delete entries owned by userId. If keepUnencryptedEntries is true
+     * then only encrypted entries will be removed, otherwise all entries will
+     * be removed.
+     */
+    void resetUser(uid_t userId, bool keepUnenryptedEntries);
+    bool isEmpty(uid_t userId) const;
+
+    void lock(uid_t userId);
+
+    ResponseCode get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId);
+    ResponseCode put(const char* filename, Blob* keyBlob, uid_t userId);
+    ResponseCode del(const char* filename, const BlobType type, uid_t userId);
+    ResponseCode list(const android::String8& prefix, android::Vector<android::String16>* matches,
+                      uid_t userId);
+
+    void addGrant(const char* filename, uid_t granteeUid);
+    bool removeGrant(const char* filename, uid_t granteeUid);
+    bool hasGrant(const char* filename, const uid_t uid) const {
+        return getGrant(filename, uid) != NULL;
+    }
+
+    ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename, uid_t userId,
+                           int32_t flags);
+
+    bool isHardwareBacked(const android::String16& keyType) const;
+
+    ResponseCode getKeyForName(Blob* keyBlob, const android::String8& keyName, const uid_t uid,
+                               const BlobType type);
+
+    /**
+     * Returns any existing UserState or creates it if it doesn't exist.
+     */
+    UserState* getUserState(uid_t userId);
+
+    /**
+     * Returns any existing UserState or creates it if it doesn't exist.
+     */
+    UserState* getUserStateByUid(uid_t uid);
+
+    /**
+     * Returns NULL if the UserState doesn't already exist.
+     */
+    const UserState* getUserState(uid_t userId) const;
+
+    /**
+     * Returns NULL if the UserState doesn't already exist.
+     */
+    const UserState* getUserStateByUid(uid_t uid) const;
+
+  private:
+    static const char* sOldMasterKey;
+    static const char* sMetaDataFile;
+    static const android::String16 sRSAKeyType;
+    static const android::String16 sECKeyType;
+    Entropy* mEntropy;
+
+    keymaster2_device_t* mDevice;
+    keymaster2_device_t* mFallbackDevice;
+
+    android::Vector<UserState*> mMasterKeys;
+
+    android::Vector<grant_t*> mGrants;
+
+    typedef struct { uint32_t version; } keystore_metadata_t;
+
+    keystore_metadata_t mMetaData;
+
+    const grant_t* getGrant(const char* filename, uid_t uid) const;
+
+    /**
+     * Upgrade the key from the current version to whatever is newest.
+     */
+    bool upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
+                     const BlobType type, uid_t uid);
+
+    /**
+     * Takes a blob that is an PEM-encoded RSA key as a byte array and converts it to a DER-encoded
+     * PKCS#8 for import into a keymaster.  Then it overwrites the original blob with the new blob
+     * format that is returned from the keymaster.
+     */
+    ResponseCode importBlobAsKey(Blob* blob, const char* filename, uid_t uid);
+
+    void readMetaData();
+    void writeMetaData();
+
+    bool upgradeKeystore();
+};
+
+#endif  // KEYSTORE_KEYSTORE_H_
diff --git a/security/keystore/keystore.rc b/security/keystore/keystore.rc
new file mode 100644
index 0000000..a887594
--- /dev/null
+++ b/security/keystore/keystore.rc
@@ -0,0 +1,4 @@
+service keystore /system/bin/keystore /data/misc/keystore
+    class main
+    user keystore
+    group keystore drmrpc readproc
diff --git a/security/keystore/keystore_cli.cpp b/security/keystore/keystore_cli.cpp
new file mode 100644
index 0000000..bf6f4a0
--- /dev/null
+++ b/security/keystore/keystore_cli.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2009 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 <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <keystore/IKeystoreService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <keystore/keystore.h>
+
+using namespace android;
+
+static const char* responses[] = {
+    NULL,
+    /* [NO_ERROR]           = */ "No error",
+    /* [LOCKED]             = */ "Locked",
+    /* [UNINITIALIZED]      = */ "Uninitialized",
+    /* [SYSTEM_ERROR]       = */ "System error",
+    /* [PROTOCOL_ERROR]     = */ "Protocol error",
+    /* [PERMISSION_DENIED]  = */ "Permission denied",
+    /* [KEY_NOT_FOUND]      = */ "Key not found",
+    /* [VALUE_CORRUPTED]    = */ "Value corrupted",
+    /* [UNDEFINED_ACTION]   = */ "Undefined action",
+    /* [WRONG_PASSWORD]     = */ "Wrong password (last chance)",
+    /* [WRONG_PASSWORD + 1] = */ "Wrong password (2 tries left)",
+    /* [WRONG_PASSWORD + 2] = */ "Wrong password (3 tries left)",
+    /* [WRONG_PASSWORD + 3] = */ "Wrong password (4 tries left)",
+};
+
+#define NO_ARG_INT_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            int32_t ret = service->cmd(); \
+            if (ret < 0) { \
+                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
+                return 1; \
+            } else { \
+                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
+                return 0; \
+            } \
+        } \
+    } while (0)
+
+#define SINGLE_ARG_INT_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            if (argc < 3) { \
+                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
+                return 1; \
+            } \
+            int32_t ret = service->cmd(String16(argv[2])); \
+            if (ret < 0) { \
+                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
+                return 1; \
+            } else { \
+                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
+                return 0; \
+            } \
+        } \
+    } while (0)
+
+#define SINGLE_INT_ARG_INT_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            if (argc < 3) { \
+                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
+                return 1; \
+            } \
+            int32_t ret = service->cmd(atoi(argv[2])); \
+            if (ret < 0) { \
+                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
+                return 1; \
+            } else { \
+                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
+                return 0; \
+            } \
+        } \
+    } while (0)
+
+#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            if (argc < 3) { \
+                fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
+                return 1; \
+            } \
+            int uid = -1; \
+            if (argc > 3) { \
+                uid = atoi(argv[3]); \
+                fprintf(stderr, "Working with uid %d\n", uid); \
+            } \
+            int32_t ret = service->cmd(String16(argv[2]), uid); \
+            if (ret < 0) { \
+                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
+                return 1; \
+            } else { \
+                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
+                return 0; \
+            } \
+        } \
+    } while (0)
+
+#define STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            if (argc < 3) { \
+                fprintf(stderr, "Usage: %s " #cmd " <name> [<uid>, <flags>]\n", argv[0]); \
+                return 1; \
+            } \
+            uint8_t* data; \
+            size_t dataSize; \
+            read_input(&data, &dataSize); \
+            int uid = -1; \
+            if (argc > 3) { \
+                uid = atoi(argv[3]); \
+                fprintf(stderr, "Working with uid %d\n", uid); \
+            } \
+            int32_t flags = 0; \
+            if (argc > 4) { \
+                flags = int32_t(atoi(argv[4])); \
+                fprintf(stderr, "Using flags %04x\n", flags); \
+            } \
+            int32_t ret = service->cmd(String16(argv[2]), data, dataSize, uid, flags); \
+            free(data); \
+            if (ret < 0) { \
+                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
+                return 1; \
+            } else { \
+                printf(#cmd ": %s (%d)\n", responses[ret], ret); \
+                return 0; \
+            } \
+        } \
+    } while (0)
+
+#define SINGLE_ARG_DATA_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            if (argc < 3) { \
+                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
+                return 1; \
+            } \
+            uint8_t* data; \
+            size_t dataSize; \
+            int32_t ret = service->cmd(String16(argv[2]), &data, &dataSize); \
+            if (ret < 0) { \
+                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
+                return 1; \
+            } else if (ret) { \
+                fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
+                return 1; \
+            } else if (dataSize) { \
+                fwrite(data, dataSize, 1, stdout); \
+                fflush(stdout); \
+                free(data); \
+                return 0; \
+            } else { \
+                return 1; \
+            } \
+        } \
+    } while (0)
+
+static int list(const sp<IKeystoreService>& service, const String16& name, int uid) {
+    Vector<String16> matches;
+    int32_t ret = service->list(name, uid, &matches);
+    if (ret < 0) {
+        fprintf(stderr, "list: could not connect: %d\n", ret);
+        return 1;
+    } else if (ret != ::NO_ERROR) {
+        fprintf(stderr, "list: %s (%d)\n", responses[ret], ret);
+        return 1;
+    } else {
+        Vector<String16>::const_iterator it = matches.begin();
+        for (; it != matches.end(); ++it) {
+            printf("%s\n", String8(*it).string());
+        }
+        return 0;
+    }
+}
+
+#define BUF_SIZE 1024
+static void read_input(uint8_t** data, size_t* dataSize) {
+    char buffer[BUF_SIZE];
+    size_t contentSize = 0;
+    char *content = (char *) malloc(sizeof(char) * BUF_SIZE);
+
+    if (content == NULL) {
+        fprintf(stderr, "read_input: failed to allocate content");
+        exit(1);
+    }
+    content[0] = '\0';
+    while (fgets(buffer, BUF_SIZE, stdin)) {
+        char *old = content;
+        contentSize += strlen(buffer);
+        content = (char *) realloc(content, contentSize);
+        if (content == NULL) {
+            fprintf(stderr, "read_input: failed to reallocate content.");
+            free(old);
+            exit(1);
+        }
+        strcat(content, buffer);
+    }
+
+    if (ferror(stdin)) {
+        free(content);
+        fprintf(stderr, "read_input: error reading from stdin.");
+        exit(1);
+    }
+
+    *data = (uint8_t*) content;
+    *dataSize = contentSize;
+}
+
+int main(int argc, char* argv[])
+{
+    if (argc < 2) {
+        fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]);
+        return 1;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]);
+        return 1;
+    }
+
+    /*
+     * All the commands should return a value
+     */
+
+    SINGLE_INT_ARG_INT_RETURN(getState);
+
+    SINGLE_ARG_DATA_RETURN(get);
+
+    STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(insert);
+
+    SINGLE_ARG_PLUS_UID_INT_RETURN(del);
+
+    SINGLE_ARG_PLUS_UID_INT_RETURN(exist);
+
+    if (strcmp(argv[1], "list") == 0) {
+        return list(service, argc < 3 ? String16("") : String16(argv[2]),
+                argc < 4 ? -1 : atoi(argv[3]));
+    }
+
+    NO_ARG_INT_RETURN(reset);
+
+    // TODO: notifyUserPasswordChanged
+
+    SINGLE_INT_ARG_INT_RETURN(lock);
+
+    // TODO: unlock
+
+    SINGLE_INT_ARG_INT_RETURN(isEmpty);
+
+    // TODO: generate
+
+    SINGLE_ARG_DATA_RETURN(get_pubkey);
+
+    SINGLE_ARG_PLUS_UID_INT_RETURN(grant);
+
+    // TODO: ungrant
+
+    // TODO: getmtime
+
+    fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]);
+    return 1;
+}
diff --git a/security/keystore/keystore_cli_v2.cpp b/security/keystore/keystore_cli_v2.cpp
new file mode 100644
index 0000000..6c229db
--- /dev/null
+++ b/security/keystore/keystore_cli_v2.cpp
@@ -0,0 +1,479 @@
+// Copyright 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.
+
+#include <cstdio>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/strings/string_util.h"
+#include "keymaster/authorization_set.h"
+#include "keymaster/keymaster_tags.h"
+#include "keystore/keystore_client_impl.h"
+
+using base::CommandLine;
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+using keystore::KeystoreClient;
+
+namespace {
+
+struct TestCase {
+    std::string name;
+    bool required_for_brillo_pts;
+    AuthorizationSet parameters;
+};
+
+void PrintUsageAndExit() {
+    printf("Usage: keystore_client_v2 <command> [options]\n");
+    printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
+           "          list-brillo-tests\n"
+           "          add-entropy --input=<entropy>\n"
+           "          generate --name=<key_name>\n"
+           "          get-chars --name=<key_name>\n"
+           "          export --name=<key_name>\n"
+           "          delete --name=<key_name>\n"
+           "          delete-all\n"
+           "          exists --name=<key_name>\n"
+           "          list [--prefix=<key_name_prefix>]\n"
+           "          sign-verify --name=<key_name>\n"
+           "          [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n");
+    exit(1);
+}
+
+std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
+    return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
+}
+
+#ifndef KEYMASTER_NAME_TAGS
+#error KEYMASTER_NAME_TAGS must be defined
+#endif
+
+void PrintTags(const AuthorizationSet& parameters) {
+    const keymaster_key_param_t* iter = nullptr;
+    for (iter = parameters.begin(); iter != parameters.end(); ++iter) {
+        printf("  %s\n", keymaster::StringifyTag(iter->tag));
+    }
+}
+
+void PrintKeyCharacteristics(const AuthorizationSet& hardware_enforced_characteristics,
+                             const AuthorizationSet& software_enforced_characteristics) {
+    printf("Hardware:\n");
+    PrintTags(hardware_enforced_characteristics);
+    printf("Software:\n");
+    PrintTags(software_enforced_characteristics);
+}
+
+bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    AuthorizationSet hardware_enforced_characteristics;
+    AuthorizationSet software_enforced_characteristics;
+    int32_t result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
+                                           &software_enforced_characteristics);
+    const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
+    if (result != KM_ERROR_OK) {
+        LOG(ERROR) << "Failed to generate key: " << result;
+        printf("[%s] %s\n", kBoldRedAbort, name.c_str());
+        return false;
+    }
+    result = keystore->deleteKey("tmp");
+    if (result != KM_ERROR_OK) {
+        LOG(ERROR) << "Failed to delete key: " << result;
+        printf("[%s] %s\n", kBoldRedAbort, name.c_str());
+        return false;
+    }
+    printf("===============================================================\n");
+    printf("%s Key Characteristics:\n", name.c_str());
+    PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics);
+    bool hardware_backed = (hardware_enforced_characteristics.size() > 0);
+    if (software_enforced_characteristics.GetTagCount(KM_TAG_ALGORITHM) > 0 ||
+        software_enforced_characteristics.GetTagCount(KM_TAG_KEY_SIZE) > 0 ||
+        software_enforced_characteristics.GetTagCount(KM_TAG_RSA_PUBLIC_EXPONENT) > 0) {
+        VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
+        hardware_backed = false;
+    }
+    const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
+    const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
+    const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
+    printf("[%s] %s\n",
+           hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
+           name.c_str());
+
+    return (hardware_backed || !required);
+}
+
+AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
+    AuthorizationSetBuilder parameters;
+    parameters.RsaSigningKey(key_size, 65537)
+        .Digest(KM_DIGEST_SHA_2_256)
+        .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
+        .Padding(KM_PAD_RSA_PSS)
+        .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    if (!sha256_only) {
+        parameters.Digest(KM_DIGEST_SHA_2_224)
+            .Digest(KM_DIGEST_SHA_2_384)
+            .Digest(KM_DIGEST_SHA_2_512);
+    }
+    return parameters.build();
+}
+
+AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
+    AuthorizationSetBuilder parameters;
+    parameters.RsaEncryptionKey(key_size, 65537)
+        .Padding(KM_PAD_RSA_PKCS1_1_5_ENCRYPT)
+        .Padding(KM_PAD_RSA_OAEP)
+        .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    return parameters.build();
+}
+
+AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
+    AuthorizationSetBuilder parameters;
+    parameters.EcdsaSigningKey(key_size)
+        .Digest(KM_DIGEST_SHA_2_256)
+        .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    if (!sha256_only) {
+        parameters.Digest(KM_DIGEST_SHA_2_224)
+            .Digest(KM_DIGEST_SHA_2_384)
+            .Digest(KM_DIGEST_SHA_2_512);
+    }
+    return parameters.build();
+}
+
+AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
+    AuthorizationSetBuilder parameters;
+    parameters.AesEncryptionKey(key_size).Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    if (with_gcm_mode) {
+        parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_GCM)
+            .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 128);
+    } else {
+        parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_ECB);
+        parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+        parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CTR);
+        parameters.Padding(KM_PAD_NONE);
+    }
+    return parameters.build();
+}
+
+AuthorizationSet GetHMACParameters(uint32_t key_size, keymaster_digest_t digest) {
+    AuthorizationSetBuilder parameters;
+    parameters.HmacKey(key_size)
+        .Digest(digest)
+        .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 224)
+        .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    return parameters.build();
+}
+
+std::vector<TestCase> GetTestCases() {
+    TestCase test_cases[] = {
+        {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
+        {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
+        {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
+        {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
+        {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
+        {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
+        {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
+        {"ECDSA-P256 Sign", true, GetECDSAParameters(256, true)},
+        {"ECDSA-P256 Sign (more digests)", false, GetECDSAParameters(256, false)},
+        {"ECDSA-P224 Sign", false, GetECDSAParameters(224, false)},
+        {"ECDSA-P384 Sign", false, GetECDSAParameters(384, false)},
+        {"ECDSA-P521 Sign", false, GetECDSAParameters(521, false)},
+        {"AES-128", true, GetAESParameters(128, false)},
+        {"AES-256", true, GetAESParameters(256, false)},
+        {"AES-128-GCM", false, GetAESParameters(128, true)},
+        {"AES-256-GCM", false, GetAESParameters(256, true)},
+        {"HMAC-SHA256-16", true, GetHMACParameters(16, KM_DIGEST_SHA_2_256)},
+        {"HMAC-SHA256-32", true, GetHMACParameters(32, KM_DIGEST_SHA_2_256)},
+        {"HMAC-SHA256-64", false, GetHMACParameters(64, KM_DIGEST_SHA_2_256)},
+        {"HMAC-SHA224-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_224)},
+        {"HMAC-SHA384-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_384)},
+        {"HMAC-SHA512-32", false, GetHMACParameters(32, KM_DIGEST_SHA_2_512)},
+    };
+    return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
+}
+
+int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
+    const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
+    if (test_for_0_3) {
+        printf("%s: Testing for keymaster v0.3. "
+               "This does not meet Brillo requirements.\n", kBoldYellowWarning);
+    }
+    int test_count = 0;
+    int fail_count = 0;
+    std::vector<TestCase> test_cases = GetTestCases();
+    for (const auto& test_case : test_cases) {
+        if (!prefix.empty() &&
+            !base::StartsWith(test_case.name, prefix, base::CompareCase::SENSITIVE)) {
+            continue;
+        }
+        if (test_for_0_3 &&
+            (base::StartsWith(test_case.name, "AES", base::CompareCase::SENSITIVE) ||
+             base::StartsWith(test_case.name, "HMAC", base::CompareCase::SENSITIVE))) {
+            continue;
+        }
+        ++test_count;
+        if (!TestKey(test_case.name, test_case.required_for_brillo_pts, test_case.parameters)) {
+            VLOG(1) << "Test failed: " << test_case.name;
+            ++fail_count;
+        }
+    }
+    return fail_count;
+}
+
+int ListTestCases() {
+    const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
+    const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
+    std::vector<TestCase> test_cases = GetTestCases();
+    for (const auto& test_case : test_cases) {
+        printf("%s : %s\n", test_case.name.c_str(),
+               test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
+    }
+    return 0;
+}
+
+std::string ReadFile(const std::string& filename) {
+    std::string content;
+    base::FilePath path(filename);
+    if (!base::ReadFileToString(path, &content)) {
+        printf("Failed to read file: %s\n", filename.c_str());
+        exit(1);
+    }
+    return content;
+}
+
+void WriteFile(const std::string& filename, const std::string& content) {
+    base::FilePath path(filename);
+    int size = content.size();
+    if (base::WriteFile(path, content.data(), size) != size) {
+        printf("Failed to write file: %s\n", filename.c_str());
+        exit(1);
+    }
+}
+
+int AddEntropy(const std::string& input) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
+    printf("AddEntropy: %d\n", result);
+    return result;
+}
+
+int GenerateKey(const std::string& name) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    AuthorizationSetBuilder params;
+    params.RsaSigningKey(2048, 65537)
+        .Digest(KM_DIGEST_SHA_2_224)
+        .Digest(KM_DIGEST_SHA_2_256)
+        .Digest(KM_DIGEST_SHA_2_384)
+        .Digest(KM_DIGEST_SHA_2_512)
+        .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
+        .Padding(KM_PAD_RSA_PSS)
+        .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    AuthorizationSet hardware_enforced_characteristics;
+    AuthorizationSet software_enforced_characteristics;
+    int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
+                                           &software_enforced_characteristics);
+    printf("GenerateKey: %d\n", result);
+    if (result == KM_ERROR_OK) {
+        PrintKeyCharacteristics(hardware_enforced_characteristics,
+                                software_enforced_characteristics);
+    }
+    return result;
+}
+
+int GetCharacteristics(const std::string& name) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    AuthorizationSet hardware_enforced_characteristics;
+    AuthorizationSet software_enforced_characteristics;
+    int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
+                                                     &software_enforced_characteristics);
+    printf("GetCharacteristics: %d\n", result);
+    if (result == KM_ERROR_OK) {
+        PrintKeyCharacteristics(hardware_enforced_characteristics,
+                                software_enforced_characteristics);
+    }
+    return result;
+}
+
+int ExportKey(const std::string& name) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    std::string data;
+    int32_t result = keystore->exportKey(KM_KEY_FORMAT_X509, name, &data);
+    printf("ExportKey: %d (%zu)\n", result, data.size());
+    return result;
+}
+
+int DeleteKey(const std::string& name) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    int32_t result = keystore->deleteKey(name);
+    printf("DeleteKey: %d\n", result);
+    return result;
+}
+
+int DeleteAllKeys() {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    int32_t result = keystore->deleteAllKeys();
+    printf("DeleteAllKeys: %d\n", result);
+    return result;
+}
+
+int DoesKeyExist(const std::string& name) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
+    return 0;
+}
+
+int List(const std::string& prefix) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    std::vector<std::string> key_list;
+    if (!keystore->listKeys(prefix, &key_list)) {
+        printf("ListKeys failed.\n");
+        return 1;
+    }
+    printf("Keys:\n");
+    for (const auto& key_name : key_list) {
+        printf("  %s\n", key_name.c_str());
+    }
+    return 0;
+}
+
+int SignAndVerify(const std::string& name) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    AuthorizationSetBuilder sign_params;
+    sign_params.Padding(KM_PAD_RSA_PKCS1_1_5_SIGN);
+    sign_params.Digest(KM_DIGEST_SHA_2_256);
+    AuthorizationSet output_params;
+    keymaster_operation_handle_t handle;
+    int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
+                                              &output_params, &handle);
+    if (result != KM_ERROR_OK) {
+        printf("Sign: BeginOperation failed: %d\n", result);
+        return result;
+    }
+    AuthorizationSet empty_params;
+    size_t num_input_bytes_consumed;
+    std::string output_data;
+    result = keystore->updateOperation(handle, empty_params, "data_to_sign",
+                                       &num_input_bytes_consumed, &output_params, &output_data);
+    if (result != KM_ERROR_OK) {
+        printf("Sign: UpdateOperation failed: %d\n", result);
+        return result;
+    }
+    result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
+                                       &output_params, &output_data);
+    if (result != KM_ERROR_OK) {
+        printf("Sign: FinishOperation failed: %d\n", result);
+        return result;
+    }
+    printf("Sign: %zu bytes.\n", output_data.size());
+    // We have a signature, now verify it.
+    std::string signature_to_verify = output_data;
+    output_data.clear();
+    result = keystore->beginOperation(KM_PURPOSE_VERIFY, name, sign_params.build(), &output_params,
+                                      &handle);
+    if (result != KM_ERROR_OK) {
+        printf("Verify: BeginOperation failed: %d\n", result);
+        return result;
+    }
+    result = keystore->updateOperation(handle, empty_params, "data_to_sign",
+                                       &num_input_bytes_consumed, &output_params, &output_data);
+    if (result != KM_ERROR_OK) {
+        printf("Verify: UpdateOperation failed: %d\n", result);
+        return result;
+    }
+    result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
+                                       &output_data);
+    if (result == KM_ERROR_VERIFICATION_FAILED) {
+        printf("Verify: Failed to verify signature.\n");
+        return result;
+    }
+    if (result != KM_ERROR_OK) {
+        printf("Verify: FinishOperation failed: %d\n", result);
+        return result;
+    }
+    printf("Verify: OK\n");
+    return 0;
+}
+
+int Encrypt(const std::string& key_name, const std::string& input_filename,
+            const std::string& output_filename) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    std::string input = ReadFile(input_filename);
+    std::string output;
+    if (!keystore->encryptWithAuthentication(key_name, input, &output)) {
+        printf("EncryptWithAuthentication failed.\n");
+        return 1;
+    }
+    WriteFile(output_filename, output);
+    return 0;
+}
+
+int Decrypt(const std::string& key_name, const std::string& input_filename,
+            const std::string& output_filename) {
+    std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+    std::string input = ReadFile(input_filename);
+    std::string output;
+    if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
+        printf("DecryptWithAuthentication failed.\n");
+        return 1;
+    }
+    WriteFile(output_filename, output);
+    return 0;
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+    CommandLine::Init(argc, argv);
+    CommandLine* command_line = CommandLine::ForCurrentProcess();
+    CommandLine::StringVector args = command_line->GetArgs();
+    if (args.empty()) {
+        PrintUsageAndExit();
+    }
+    if (args[0] == "brillo-platform-test") {
+        return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"),
+                                  command_line->HasSwitch("test_for_0_3"));
+    } else if (args[0] == "list-brillo-tests") {
+        return ListTestCases();
+    } else if (args[0] == "add-entropy") {
+        return AddEntropy(command_line->GetSwitchValueASCII("input"));
+    } else if (args[0] == "generate") {
+        return GenerateKey(command_line->GetSwitchValueASCII("name"));
+    } else if (args[0] == "get-chars") {
+        return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
+    } else if (args[0] == "export") {
+        return ExportKey(command_line->GetSwitchValueASCII("name"));
+    } else if (args[0] == "delete") {
+        return DeleteKey(command_line->GetSwitchValueASCII("name"));
+    } else if (args[0] == "delete-all") {
+        return DeleteAllKeys();
+    } else if (args[0] == "exists") {
+        return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
+    } else if (args[0] == "list") {
+        return List(command_line->GetSwitchValueASCII("prefix"));
+    } else if (args[0] == "sign-verify") {
+        return SignAndVerify(command_line->GetSwitchValueASCII("name"));
+    } else if (args[0] == "encrypt") {
+        return Encrypt(command_line->GetSwitchValueASCII("name"),
+                       command_line->GetSwitchValueASCII("in"),
+                       command_line->GetSwitchValueASCII("out"));
+    } else if (args[0] == "decrypt") {
+        return Decrypt(command_line->GetSwitchValueASCII("name"),
+                       command_line->GetSwitchValueASCII("in"),
+                       command_line->GetSwitchValueASCII("out"));
+    } else {
+        PrintUsageAndExit();
+    }
+    return 0;
+}
diff --git a/security/keystore/keystore_client.proto b/security/keystore/keystore_client.proto
new file mode 100644
index 0000000..cd520dc
--- /dev/null
+++ b/security/keystore/keystore_client.proto
@@ -0,0 +1,26 @@
+// Copyright 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.
+
+package keystore;
+
+option optimize_for = LITE_RUNTIME;
+
+// Holds encrypted, authenticated data.
+message EncryptedData {
+  // The initialization vector used during encryption.
+  optional bytes init_vector = 1;
+  // MAC of (init_vector + encrypted_data).
+  optional bytes authentication_data = 2;
+  optional bytes encrypted_data = 3;
+}
diff --git a/security/keystore/keystore_client_impl.cpp b/security/keystore/keystore_client_impl.cpp
new file mode 100644
index 0000000..a46dfc7
--- /dev/null
+++ b/security/keystore/keystore_client_impl.cpp
@@ -0,0 +1,556 @@
+// Copyright 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 "keystore_client"
+
+#include "keystore/keystore_client_impl.h"
+
+#include <string>
+#include <vector>
+
+#include "binder/IBinder.h"
+#include "binder/IInterface.h"
+#include "binder/IServiceManager.h"
+#include "keystore/IKeystoreService.h"
+#include "keystore/keystore.h"
+#include "log/log.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
+
+#include "keystore_client.pb.h"
+
+using android::ExportResult;
+using android::KeyCharacteristics;
+using android::KeymasterArguments;
+using android::OperationResult;
+using android::String16;
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+
+namespace {
+
+// Use the UID of the current process.
+const int kDefaultUID = -1;
+const char kEncryptSuffix[] = "_ENC";
+const char kAuthenticateSuffix[] = "_AUTH";
+const uint32_t kAESKeySize = 256;      // bits
+const uint32_t kHMACKeySize = 256;     // bits
+const uint32_t kHMACOutputSize = 256;  // bits
+
+const uint8_t* StringAsByteArray(const std::string& s) {
+    return reinterpret_cast<const uint8_t*>(s.data());
+}
+
+std::string ByteArrayAsString(const uint8_t* data, size_t data_size) {
+    return std::string(reinterpret_cast<const char*>(data), data_size);
+}
+
+void CopyParameters(const AuthorizationSet& in, std::vector<keymaster_key_param_t>* out) {
+  keymaster_key_param_set_t tmp;
+  in.CopyToParamSet(&tmp);
+  out->assign(&tmp.params[0], &tmp.params[tmp.length]);
+  free(tmp.params);
+}
+
+}  // namespace
+
+namespace keystore {
+
+KeystoreClientImpl::KeystoreClientImpl() {
+    service_manager_ = android::defaultServiceManager();
+    keystore_binder_ = service_manager_->getService(String16("android.security.keystore"));
+    keystore_ = android::interface_cast<android::IKeystoreService>(keystore_binder_);
+}
+
+bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
+                                                   const std::string& data,
+                                                   std::string* encrypted_data) {
+    // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random
+    // IV. The authentication algorithm is HMAC-SHA256 and is computed over the
+    // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM
+    // because hardware support for GCM is not mandatory for all Brillo devices.
+    std::string encryption_key_name = key_name + kEncryptSuffix;
+    if (!createOrVerifyEncryptionKey(encryption_key_name)) {
+        return false;
+    }
+    std::string authentication_key_name = key_name + kAuthenticateSuffix;
+    if (!createOrVerifyAuthenticationKey(authentication_key_name)) {
+        return false;
+    }
+    AuthorizationSetBuilder encrypt_params;
+    encrypt_params.Padding(KM_PAD_PKCS7);
+    encrypt_params.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+    AuthorizationSet output_params;
+    std::string raw_encrypted_data;
+    if (!oneShotOperation(KM_PURPOSE_ENCRYPT, encryption_key_name, encrypt_params.build(), data,
+                          std::string(), /* signature_to_verify */
+                          &output_params, &raw_encrypted_data)) {
+        ALOGE("Encrypt: AES operation failed.");
+        return false;
+    }
+    keymaster_blob_t init_vector_blob;
+    if (!output_params.GetTagValue(keymaster::TAG_NONCE, &init_vector_blob)) {
+        ALOGE("Encrypt: Missing initialization vector.");
+        return false;
+    }
+    std::string init_vector =
+        ByteArrayAsString(init_vector_blob.data, init_vector_blob.data_length);
+
+    AuthorizationSetBuilder authenticate_params;
+    authenticate_params.Digest(KM_DIGEST_SHA_2_256);
+    authenticate_params.Authorization(keymaster::TAG_MAC_LENGTH, kHMACOutputSize);
+    std::string raw_authentication_data;
+    if (!oneShotOperation(KM_PURPOSE_SIGN, authentication_key_name, authenticate_params.build(),
+                          init_vector + raw_encrypted_data, std::string(), /* signature_to_verify */
+                          &output_params, &raw_authentication_data)) {
+        ALOGE("Encrypt: HMAC operation failed.");
+        return false;
+    }
+    EncryptedData protobuf;
+    protobuf.set_init_vector(init_vector);
+    protobuf.set_authentication_data(raw_authentication_data);
+    protobuf.set_encrypted_data(raw_encrypted_data);
+    if (!protobuf.SerializeToString(encrypted_data)) {
+        ALOGE("Encrypt: Failed to serialize EncryptedData protobuf.");
+        return false;
+    }
+    return true;
+}
+
+bool KeystoreClientImpl::decryptWithAuthentication(const std::string& key_name,
+                                                   const std::string& encrypted_data,
+                                                   std::string* data) {
+    EncryptedData protobuf;
+    if (!protobuf.ParseFromString(encrypted_data)) {
+        ALOGE("Decrypt: Failed to parse EncryptedData protobuf.");
+    }
+    // Verify authentication before attempting decryption.
+    std::string authentication_key_name = key_name + kAuthenticateSuffix;
+    AuthorizationSetBuilder authenticate_params;
+    authenticate_params.Digest(KM_DIGEST_SHA_2_256);
+    AuthorizationSet output_params;
+    std::string output_data;
+    if (!oneShotOperation(KM_PURPOSE_VERIFY, authentication_key_name, authenticate_params.build(),
+                          protobuf.init_vector() + protobuf.encrypted_data(),
+                          protobuf.authentication_data(), &output_params, &output_data)) {
+        ALOGE("Decrypt: HMAC operation failed.");
+        return false;
+    }
+    std::string encryption_key_name = key_name + kEncryptSuffix;
+    AuthorizationSetBuilder encrypt_params;
+    encrypt_params.Padding(KM_PAD_PKCS7);
+    encrypt_params.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+    encrypt_params.Authorization(keymaster::TAG_NONCE, protobuf.init_vector().data(),
+                                 protobuf.init_vector().size());
+    if (!oneShotOperation(KM_PURPOSE_DECRYPT, encryption_key_name, encrypt_params.build(),
+                          protobuf.encrypted_data(), std::string(), /* signature_to_verify */
+                          &output_params, data)) {
+        ALOGE("Decrypt: AES operation failed.");
+        return false;
+    }
+    return true;
+}
+
+bool KeystoreClientImpl::oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
+                                          const keymaster::AuthorizationSet& input_parameters,
+                                          const std::string& input_data,
+                                          const std::string& signature_to_verify,
+                                          keymaster::AuthorizationSet* output_parameters,
+                                          std::string* output_data) {
+    keymaster_operation_handle_t handle;
+    int32_t result =
+        beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
+    if (result != KM_ERROR_OK) {
+        ALOGE("BeginOperation failed: %d", result);
+        return false;
+    }
+    AuthorizationSet empty_params;
+    size_t num_input_bytes_consumed;
+    AuthorizationSet ignored_params;
+    result = updateOperation(handle, empty_params, input_data, &num_input_bytes_consumed,
+                             &ignored_params, output_data);
+    if (result != KM_ERROR_OK) {
+        ALOGE("UpdateOperation failed: %d", result);
+        return false;
+    }
+    result =
+        finishOperation(handle, empty_params, signature_to_verify, &ignored_params, output_data);
+    if (result != KM_ERROR_OK) {
+        ALOGE("FinishOperation failed: %d", result);
+        return false;
+    }
+    return true;
+}
+
+int32_t KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
+    return mapKeystoreError(keystore_->addRngEntropy(StringAsByteArray(entropy), entropy.size()));
+}
+
+int32_t KeystoreClientImpl::generateKey(const std::string& key_name,
+                                        const AuthorizationSet& key_parameters,
+                                        AuthorizationSet* hardware_enforced_characteristics,
+                                        AuthorizationSet* software_enforced_characteristics) {
+    String16 key_name16(key_name.data(), key_name.size());
+    KeymasterArguments key_arguments;
+    CopyParameters(key_parameters, &key_arguments.params);
+    KeyCharacteristics characteristics;
+    int32_t result =
+        keystore_->generateKey(key_name16, key_arguments, NULL /*entropy*/, 0 /*entropyLength*/,
+                               kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+    hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+    software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+    return mapKeystoreError(result);
+}
+
+int32_t
+KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name,
+                                          AuthorizationSet* hardware_enforced_characteristics,
+                                          AuthorizationSet* software_enforced_characteristics) {
+    String16 key_name16(key_name.data(), key_name.size());
+    keymaster_blob_t client_id_blob = {nullptr, 0};
+    keymaster_blob_t app_data_blob = {nullptr, 0};
+    KeyCharacteristics characteristics;
+    int32_t result = keystore_->getKeyCharacteristics(key_name16, &client_id_blob, &app_data_blob,
+                                                      &characteristics);
+    hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+    software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+    return mapKeystoreError(result);
+}
+
+int32_t KeystoreClientImpl::importKey(const std::string& key_name,
+                                      const AuthorizationSet& key_parameters,
+                                      keymaster_key_format_t key_format,
+                                      const std::string& key_data,
+                                      AuthorizationSet* hardware_enforced_characteristics,
+                                      AuthorizationSet* software_enforced_characteristics) {
+    String16 key_name16(key_name.data(), key_name.size());
+    KeymasterArguments key_arguments;
+    CopyParameters(key_parameters, &key_arguments.params);
+    KeyCharacteristics characteristics;
+    int32_t result =
+        keystore_->importKey(key_name16, key_arguments, key_format, StringAsByteArray(key_data),
+                             key_data.size(), kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+    hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+    software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+    return mapKeystoreError(result);
+}
+
+int32_t KeystoreClientImpl::exportKey(keymaster_key_format_t export_format,
+                                      const std::string& key_name, std::string* export_data) {
+    String16 key_name16(key_name.data(), key_name.size());
+    keymaster_blob_t client_id_blob = {nullptr, 0};
+    keymaster_blob_t app_data_blob = {nullptr, 0};
+    ExportResult export_result;
+    keystore_->exportKey(key_name16, export_format, &client_id_blob, &app_data_blob,
+                         &export_result);
+    *export_data = ByteArrayAsString(export_result.exportData.get(), export_result.dataLength);
+    return mapKeystoreError(export_result.resultCode);
+}
+
+int32_t KeystoreClientImpl::deleteKey(const std::string& key_name) {
+    String16 key_name16(key_name.data(), key_name.size());
+    return mapKeystoreError(keystore_->del(key_name16, kDefaultUID));
+}
+
+int32_t KeystoreClientImpl::deleteAllKeys() {
+    return mapKeystoreError(keystore_->clear_uid(kDefaultUID));
+}
+
+int32_t KeystoreClientImpl::beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+                                           const AuthorizationSet& input_parameters,
+                                           AuthorizationSet* output_parameters,
+                                           keymaster_operation_handle_t* handle) {
+    android::sp<android::IBinder> token(new android::BBinder);
+    String16 key_name16(key_name.data(), key_name.size());
+    KeymasterArguments input_arguments;
+    CopyParameters(input_parameters, &input_arguments.params);
+    OperationResult result;
+    keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_arguments,
+                     NULL /*entropy*/, 0 /*entropyLength*/, &result);
+    int32_t error_code = mapKeystoreError(result.resultCode);
+    if (error_code == KM_ERROR_OK) {
+        *handle = getNextVirtualHandle();
+        active_operations_[*handle] = result.token;
+        if (!result.outParams.params.empty()) {
+            output_parameters->Reinitialize(&*result.outParams.params.begin(),
+                                            result.outParams.params.size());
+        }
+    }
+    return error_code;
+}
+
+int32_t KeystoreClientImpl::updateOperation(keymaster_operation_handle_t handle,
+                                            const AuthorizationSet& input_parameters,
+                                            const std::string& input_data,
+                                            size_t* num_input_bytes_consumed,
+                                            AuthorizationSet* output_parameters,
+                                            std::string* output_data) {
+    if (active_operations_.count(handle) == 0) {
+        return KM_ERROR_INVALID_OPERATION_HANDLE;
+    }
+    KeymasterArguments input_arguments;
+    CopyParameters(input_parameters, &input_arguments.params);
+    OperationResult result;
+    keystore_->update(active_operations_[handle], input_arguments, StringAsByteArray(input_data),
+                      input_data.size(), &result);
+    int32_t error_code = mapKeystoreError(result.resultCode);
+    if (error_code == KM_ERROR_OK) {
+        *num_input_bytes_consumed = result.inputConsumed;
+        if (!result.outParams.params.empty()) {
+            output_parameters->Reinitialize(&*result.outParams.params.begin(),
+                                            result.outParams.params.size());
+        }
+        output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+    }
+    return error_code;
+}
+
+int32_t KeystoreClientImpl::finishOperation(keymaster_operation_handle_t handle,
+                                            const AuthorizationSet& input_parameters,
+                                            const std::string& signature_to_verify,
+                                            AuthorizationSet* output_parameters,
+                                            std::string* output_data) {
+    if (active_operations_.count(handle) == 0) {
+        return KM_ERROR_INVALID_OPERATION_HANDLE;
+    }
+    KeymasterArguments input_arguments;
+    CopyParameters(input_parameters, &input_arguments.params);
+    OperationResult result;
+    keystore_->finish(active_operations_[handle], input_arguments,
+                      StringAsByteArray(signature_to_verify), signature_to_verify.size(),
+                      NULL /*entropy*/, 0 /*entropyLength*/, &result);
+    int32_t error_code = mapKeystoreError(result.resultCode);
+    if (error_code == KM_ERROR_OK) {
+        if (!result.outParams.params.empty()) {
+            output_parameters->Reinitialize(&*result.outParams.params.begin(),
+                                            result.outParams.params.size());
+        }
+        output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+        active_operations_.erase(handle);
+    }
+    return error_code;
+}
+
+int32_t KeystoreClientImpl::abortOperation(keymaster_operation_handle_t handle) {
+    if (active_operations_.count(handle) == 0) {
+        return KM_ERROR_INVALID_OPERATION_HANDLE;
+    }
+    int32_t error_code = mapKeystoreError(keystore_->abort(active_operations_[handle]));
+    if (error_code == KM_ERROR_OK) {
+        active_operations_.erase(handle);
+    }
+    return error_code;
+}
+
+bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {
+    String16 key_name16(key_name.data(), key_name.size());
+    int32_t error_code = mapKeystoreError(keystore_->exist(key_name16, kDefaultUID));
+    return (error_code == KM_ERROR_OK);
+}
+
+bool KeystoreClientImpl::listKeys(const std::string& prefix,
+                                  std::vector<std::string>* key_name_list) {
+    String16 prefix16(prefix.data(), prefix.size());
+    android::Vector<String16> matches;
+    int32_t error_code = mapKeystoreError(keystore_->list(prefix16, kDefaultUID, &matches));
+    if (error_code == KM_ERROR_OK) {
+        for (const auto& match : matches) {
+            android::String8 key_name(match);
+            key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size()));
+        }
+        return true;
+    }
+    return false;
+}
+
+keymaster_operation_handle_t KeystoreClientImpl::getNextVirtualHandle() {
+    return next_virtual_handle_++;
+}
+
+int32_t KeystoreClientImpl::mapKeystoreError(int32_t keystore_error) {
+    // See notes in keystore_client.h for rationale.
+    if (keystore_error == ::NO_ERROR) {
+        return KM_ERROR_OK;
+    }
+    return keystore_error;
+}
+
+bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name) {
+    bool key_exists = doesKeyExist(key_name);
+    if (key_exists) {
+        bool verified = false;
+        if (!verifyEncryptionKeyAttributes(key_name, &verified)) {
+            return false;
+        }
+        if (!verified) {
+            int32_t result = deleteKey(key_name);
+            if (result != KM_ERROR_OK) {
+                ALOGE("Failed to delete invalid encryption key: %d", result);
+                return false;
+            }
+            key_exists = false;
+        }
+    }
+    if (!key_exists) {
+        AuthorizationSetBuilder key_parameters;
+        key_parameters.AesEncryptionKey(kAESKeySize)
+            .Padding(KM_PAD_PKCS7)
+            .Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC)
+            .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+        AuthorizationSet hardware_enforced_characteristics;
+        AuthorizationSet software_enforced_characteristics;
+        int32_t result =
+            generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+                        &software_enforced_characteristics);
+        if (result != KM_ERROR_OK) {
+            ALOGE("Failed to generate encryption key: %d", result);
+            return false;
+        }
+        if (hardware_enforced_characteristics.size() == 0) {
+            ALOGW("WARNING: Encryption key is not hardware-backed.");
+        }
+    }
+    return true;
+}
+
+bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name) {
+    bool key_exists = doesKeyExist(key_name);
+    if (key_exists) {
+        bool verified = false;
+        if (!verifyAuthenticationKeyAttributes(key_name, &verified)) {
+            return false;
+        }
+        if (!verified) {
+            int32_t result = deleteKey(key_name);
+            if (result != KM_ERROR_OK) {
+                ALOGE("Failed to delete invalid authentication key: %d", result);
+                return false;
+            }
+            key_exists = false;
+        }
+    }
+    if (!key_exists) {
+        AuthorizationSetBuilder key_parameters;
+        key_parameters.HmacKey(kHMACKeySize)
+            .Digest(KM_DIGEST_SHA_2_256)
+            .Authorization(keymaster::TAG_MIN_MAC_LENGTH, kHMACOutputSize)
+            .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+        AuthorizationSet hardware_enforced_characteristics;
+        AuthorizationSet software_enforced_characteristics;
+        int32_t result =
+            generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+                        &software_enforced_characteristics);
+        if (result != KM_ERROR_OK) {
+            ALOGE("Failed to generate authentication key: %d", result);
+            return false;
+        }
+        if (hardware_enforced_characteristics.size() == 0) {
+            ALOGW("WARNING: Authentication key is not hardware-backed.");
+        }
+    }
+    return true;
+}
+
+bool KeystoreClientImpl::verifyEncryptionKeyAttributes(const std::string& key_name,
+                                                       bool* verified) {
+    AuthorizationSet hardware_enforced_characteristics;
+    AuthorizationSet software_enforced_characteristics;
+    int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+                                           &software_enforced_characteristics);
+    if (result != KM_ERROR_OK) {
+        ALOGE("Failed to query encryption key: %d", result);
+        return false;
+    }
+    *verified = true;
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_RSA;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm)) ||
+        algorithm != KM_ALGORITHM_AES) {
+        ALOGW("Found encryption key with invalid algorithm.");
+        *verified = false;
+    }
+    uint32_t key_size = 0;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size)) ||
+        key_size != kAESKeySize) {
+        ALOGW("Found encryption key with invalid size.");
+        *verified = false;
+    }
+    keymaster_block_mode_t block_mode = KM_MODE_ECB;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_BLOCK_MODE, &block_mode) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_BLOCK_MODE, &block_mode)) ||
+        block_mode != KM_MODE_CBC) {
+        ALOGW("Found encryption key with invalid block mode.");
+        *verified = false;
+    }
+    keymaster_padding_t padding_mode = KM_PAD_NONE;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_PADDING, &padding_mode) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_PADDING, &padding_mode)) ||
+        padding_mode != KM_PAD_PKCS7) {
+        ALOGW("Found encryption key with invalid padding mode.");
+        *verified = false;
+    }
+    if (hardware_enforced_characteristics.size() == 0) {
+        ALOGW("WARNING: Encryption key is not hardware-backed.");
+    }
+    return true;
+}
+
+bool KeystoreClientImpl::verifyAuthenticationKeyAttributes(const std::string& key_name,
+                                                           bool* verified) {
+    AuthorizationSet hardware_enforced_characteristics;
+    AuthorizationSet software_enforced_characteristics;
+    int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+                                           &software_enforced_characteristics);
+    if (result != KM_ERROR_OK) {
+        ALOGE("Failed to query authentication key: %d", result);
+        return false;
+    }
+    *verified = true;
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_RSA;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_ALGORITHM, &algorithm)) ||
+        algorithm != KM_ALGORITHM_HMAC) {
+        ALOGW("Found authentication key with invalid algorithm.");
+        *verified = false;
+    }
+    uint32_t key_size = 0;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_KEY_SIZE, &key_size)) ||
+        key_size != kHMACKeySize) {
+        ALOGW("Found authentication key with invalid size.");
+        *verified = false;
+    }
+    uint32_t mac_size = 0;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_MIN_MAC_LENGTH, &mac_size) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_MIN_MAC_LENGTH,
+                                                        &mac_size)) ||
+        mac_size != kHMACOutputSize) {
+        ALOGW("Found authentication key with invalid minimum mac size.");
+        *verified = false;
+    }
+    keymaster_digest_t digest = KM_DIGEST_NONE;
+    if ((!hardware_enforced_characteristics.GetTagValue(keymaster::TAG_DIGEST, &digest) &&
+         !software_enforced_characteristics.GetTagValue(keymaster::TAG_DIGEST, &digest)) ||
+        digest != KM_DIGEST_SHA_2_256) {
+        ALOGW("Found authentication key with invalid digest list.");
+        *verified = false;
+    }
+    if (hardware_enforced_characteristics.size() == 0) {
+        ALOGW("WARNING: Authentication key is not hardware-backed.");
+    }
+    return true;
+}
+
+}  // namespace keystore
diff --git a/security/keystore/keystore_get.cpp b/security/keystore/keystore_get.cpp
new file mode 100644
index 0000000..45ad415
--- /dev/null
+++ b/security/keystore/keystore_get.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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 <keystore/IKeystoreService.h>
+#include <binder/IServiceManager.h>
+
+#include <keystore/keystore_get.h>
+
+using namespace android;
+
+ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        return -1;
+    }
+
+    size_t valueLength;
+    int32_t ret = service->get(String16(key, keyLength), value, &valueLength);
+    if (ret < 0) {
+        return -1;
+    } else if (ret != ::NO_ERROR) {
+        return -1;
+    } else {
+        return valueLength;
+    }
+}
diff --git a/security/keystore/keystore_keymaster_enforcement.h b/security/keystore/keystore_keymaster_enforcement.h
new file mode 100644
index 0000000..d20d7a6
--- /dev/null
+++ b/security/keystore/keystore_keymaster_enforcement.h
@@ -0,0 +1,88 @@
+/*
+ * 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 KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+#define KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+
+#include <time.h>
+
+#include <keymaster/keymaster_enforcement.h>
+
+/**
+ * This is a specialization of the KeymasterEnforcement class to be used by Keystore to enforce
+ * keymaster requirements on all key operation.
+ */
+class KeystoreKeymasterEnforcement : public keymaster::KeymasterEnforcement {
+  public:
+    KeystoreKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
+
+    uint32_t get_current_time() const override {
+        struct timespec tp;
+        int err = clock_gettime(CLOCK_MONOTONIC, &tp);
+        if (err || tp.tv_sec < 0)
+            return 0;
+        return static_cast<uint32_t>(tp.tv_sec);
+    }
+
+    bool activation_date_valid(uint64_t activation_date) const override {
+        time_t now = time(NULL);
+        if (now == static_cast<time_t>(-1)) {
+            // Failed to obtain current time -- fail safe: activation_date hasn't yet occurred.
+            return false;
+        } else if (now < 0) {
+            // Current time is prior to start of the epoch -- activation_date hasn't yet occurred.
+            return false;
+        }
+
+        // time(NULL) returns seconds since epoch and "loses" milliseconds information. We thus add
+        // 999 ms to now_date to avoid a situation where an activation_date of up to 999ms in the
+        // past may still be considered to still be in the future. This can be removed once
+        // time(NULL) is replaced by a millisecond-precise source of time.
+        uint64_t now_date = static_cast<uint64_t>(now) * 1000 + 999;
+        return now_date >= activation_date;
+    }
+
+    bool expiration_date_passed(uint64_t expiration_date) const override {
+        time_t now = time(NULL);
+        if (now == static_cast<time_t>(-1)) {
+            // Failed to obtain current time -- fail safe: expiration_date has passed.
+            return true;
+        } else if (now < 0) {
+            // Current time is prior to start of the epoch: expiration_date hasn't yet occurred.
+            return false;
+        }
+
+        // time(NULL) returns seconds since epoch and "loses" milliseconds information. As a result,
+        // expiration_date of up to 999 ms in the past may still be considered in the future. This
+        // is OK.
+        uint64_t now_date = static_cast<uint64_t>(now) * 1000;
+        return now_date > expiration_date;
+    }
+
+    bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const {
+        // Assume the token has not timed out, because AuthTokenTable would not have returned it if
+        // the timeout were past.  Secure hardware will also check timeouts if it supports them.
+        return false;
+    }
+
+    bool ValidateTokenSignature(const hw_auth_token_t&) const override {
+        // Non-secure world cannot validate token signatures because it doesn't have access to the
+        // signing key. Assume the token is good.
+        return true;
+    }
+};
+
+#endif  // KEYSTORE_KEYMASTER_ENFORCEMENT_H_
diff --git a/security/keystore/keystore_main.cpp b/security/keystore/keystore_main.cpp
new file mode 100644
index 0000000..a2b75f6
--- /dev/null
+++ b/security/keystore/keystore_main.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "keystore"
+
+#include <keymaster/soft_keymaster_device.h>
+#include <keymaster/soft_keymaster_logger.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <cutils/log.h>
+
+#include "entropy.h"
+#include "key_store_service.h"
+#include "keystore.h"
+#include "permissions.h"
+
+/* KeyStore is a secured storage for key-value pairs. In this implementation,
+ * each file stores one key-value pair. Keys are encoded in file names, and
+ * values are encrypted with checksums. The encryption key is protected by a
+ * user-defined password. To keep things simple, buffers are always larger than
+ * the maximum space we needed, so boundary checks on buffers are omitted. */
+
+using keymaster::SoftKeymasterDevice;
+
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster0_device_t* km0_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster0_open(mod, &km0_device);
+    if (rc) {
+        ALOGE("Error opening keystore keymaster0 device.");
+        goto err;
+    }
+
+    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
+        km0_device->common.close(&km0_device->common);
+        km0_device = NULL;
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster2_device();
+        return 0;
+    }
+
+    ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km0_device);
+    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by  keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km0_device)
+        km0_device->common.close(&km0_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster1_device_t* km1_device = nullptr;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster1_open(mod, &km1_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster1 device", rc);
+        goto err;
+    }
+
+    ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km1_device);
+    km1_device = nullptr;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km1_device)
+        km1_device->common.close(&km1_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
+    ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster2_device_t* km2_device = nullptr;
+
+    int rc = keymaster2_open(mod, &km2_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster2 device", rc);
+        goto err;
+    }
+
+    *dev = km2_device;
+    return 0;
+
+err:
+    if (km2_device)
+        km2_device->common.close(&km2_device->common);
+    *dev = nullptr;
+    return rc;
+}
+
+static int keymaster_device_initialize(keymaster2_device_t** dev) {
+    const hw_module_t* mod;
+
+    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    if (rc) {
+        ALOGI("Could not find any keystore module, using software-only implementation.");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = (new SoftKeymasterDevice)->keymaster2_device();
+        return 0;
+    }
+
+    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+        return keymaster0_device_initialize(mod, dev);
+    } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
+        return keymaster1_device_initialize(mod, dev);
+    } else {
+        return keymaster2_device_initialize(mod, dev);
+    }
+}
+
+// softkeymaster_logger appears not to be used in keystore, but it installs itself as the
+// logger used by SoftKeymasterDevice.
+static keymaster::SoftKeymasterLogger softkeymaster_logger;
+
+static int fallback_keymaster_device_initialize(keymaster2_device_t** dev) {
+    *dev = (new SoftKeymasterDevice)->keymaster2_device();
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    return 0;
+}
+
+static void keymaster_device_release(keymaster2_device_t* dev) {
+    dev->common.close(&dev->common);
+}
+
+int main(int argc, char* argv[]) {
+    if (argc < 2) {
+        ALOGE("A directory must be specified!");
+        return 1;
+    }
+    if (chdir(argv[1]) == -1) {
+        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
+        return 1;
+    }
+
+    Entropy entropy;
+    if (!entropy.open()) {
+        return 1;
+    }
+
+    keymaster2_device_t* dev;
+    if (keymaster_device_initialize(&dev)) {
+        ALOGE("keystore keymaster could not be initialized; exiting");
+        return 1;
+    }
+
+    keymaster2_device_t* fallback;
+    if (fallback_keymaster_device_initialize(&fallback)) {
+        ALOGE("software keymaster could not be initialized; exiting");
+        return 1;
+    }
+
+    if (configure_selinux() == -1) {
+        return -1;
+    }
+
+    KeyStore keyStore(&entropy, dev, fallback);
+    keyStore.initialize();
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<android::KeyStoreService> service = new android::KeyStoreService(&keyStore);
+    android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
+    if (ret != android::OK) {
+        ALOGE("Couldn't register binder service!");
+        return -1;
+    }
+
+    /*
+     * We're the only thread in existence, so we're just going to process
+     * Binder transaction as a single-threaded program.
+     */
+    android::IPCThreadState::self()->joinThreadPool();
+
+    keymaster_device_release(dev);
+    return 1;
+}
diff --git a/security/keystore/keystore_utils.cpp b/security/keystore/keystore_utils.cpp
new file mode 100644
index 0000000..bfcb43a
--- /dev/null
+++ b/security/keystore/keystore_utils.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 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 "keystore"
+
+#include "keystore_utils.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <keymaster/android_keymaster_utils.h>
+
+size_t readFully(int fd, uint8_t* data, size_t size) {
+    size_t remaining = size;
+    while (remaining > 0) {
+        ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, remaining));
+        if (n <= 0) {
+            return size - remaining;
+        }
+        data += n;
+        remaining -= n;
+    }
+    return size;
+}
+
+size_t writeFully(int fd, uint8_t* data, size_t size) {
+    size_t remaining = size;
+    while (remaining > 0) {
+        ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, remaining));
+        if (n < 0) {
+            ALOGW("write failed: %s", strerror(errno));
+            return size - remaining;
+        }
+        data += n;
+        remaining -= n;
+    }
+    return size;
+}
+
+void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+    if (keyType == EVP_PKEY_RSA) {
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
+    }
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
+    params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
+    params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
+    params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
+    uint64_t now = keymaster::java_time(time(NULL));
+    params->push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
+}
+
+uid_t get_app_id(uid_t uid) {
+    return uid % AID_USER;
+}
+
+uid_t get_user_id(uid_t uid) {
+    return uid / AID_USER;
+}
diff --git a/security/keystore/keystore_utils.h b/security/keystore/keystore_utils.h
new file mode 100644
index 0000000..eaa5eb3
--- /dev/null
+++ b/security/keystore/keystore_utils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 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 KEYSTORE_KEYSTORE_UTILS_H_
+#define KEYSTORE_KEYSTORE_UTILS_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include <UniquePtr.h>
+
+size_t readFully(int fd, uint8_t* data, size_t size);
+size_t writeFully(int fd, uint8_t* data, size_t size);
+
+void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params);
+
+/**
+ * Returns the app ID (in the Android multi-user sense) for the current
+ * UNIX UID.
+ */
+uid_t get_app_id(uid_t uid);
+
+/**
+ * Returns the user ID (in the Android multi-user sense) for the current
+ * UNIX UID.
+ */
+uid_t get_user_id(uid_t uid);
+
+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 PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
+#endif  // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/security/keystore/operation.cpp b/security/keystore/operation.cpp
new file mode 100644
index 0000000..e8ae8b7
--- /dev/null
+++ b/security/keystore/operation.cpp
@@ -0,0 +1,156 @@
+/*
+ * 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 "KeystoreOperation"
+
+#include "operation.h"
+
+#include <algorithm>
+
+namespace android {
+OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
+    : mDeathRecipient(deathRecipient) {}
+
+sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
+                                       keymaster_purpose_t purpose, const keymaster2_device_t* dev,
+                                       const sp<IBinder>& appToken,
+                                       keymaster_key_characteristics_t* characteristics,
+                                       bool pruneable) {
+    sp<IBinder> token = new BBinder();
+    mMap[token] = Operation(handle, keyid, purpose, dev, characteristics, appToken);
+    if (pruneable) {
+        mLru.push_back(token);
+    }
+    if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) {
+        appToken->linkToDeath(mDeathRecipient);
+    }
+    mAppTokenMap[appToken].push_back(token);
+    return token;
+}
+
+bool OperationMap::getOperation(const sp<IBinder>& token, keymaster_operation_handle_t* outHandle,
+                                uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
+                                const keymaster2_device_t** outDevice,
+                                const keymaster_key_characteristics_t** outCharacteristics) {
+    if (!outHandle || !outDevice) {
+        return false;
+    }
+    auto entry = mMap.find(token);
+    if (entry == mMap.end()) {
+        return false;
+    }
+    updateLru(token);
+
+    *outHandle = entry->second.handle;
+    *outKeyid = entry->second.keyid;
+    *outPurpose = entry->second.purpose;
+    *outDevice = entry->second.device;
+    if (outCharacteristics) {
+        *outCharacteristics = entry->second.characteristics.get();
+    }
+    return true;
+}
+
+void OperationMap::updateLru(const sp<IBinder>& token) {
+    auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
+    if (lruEntry != mLru.end()) {
+        mLru.erase(lruEntry);
+        mLru.push_back(token);
+    }
+}
+
+bool OperationMap::removeOperation(const sp<IBinder>& token) {
+    auto entry = mMap.find(token);
+    if (entry == mMap.end()) {
+        return false;
+    }
+    sp<IBinder> appToken = entry->second.appToken;
+    mMap.erase(entry);
+    auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
+    if (lruEntry != mLru.end()) {
+        mLru.erase(lruEntry);
+    }
+    removeOperationTracking(token, appToken);
+    return true;
+}
+
+void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) {
+    auto appEntry = mAppTokenMap.find(appToken);
+    if (appEntry == mAppTokenMap.end()) {
+        ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get());
+        return;
+    }
+    auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token);
+    appEntry->second.erase(tokenEntry);
+    // Stop listening for death if all operations tied to the token have finished.
+    if (appEntry->second.size() == 0) {
+        appToken->unlinkToDeath(mDeathRecipient);
+        mAppTokenMap.erase(appEntry);
+    }
+}
+
+bool OperationMap::hasPruneableOperation() const {
+    return mLru.size() != 0;
+}
+
+size_t OperationMap::getPruneableOperationCount() const {
+    return mLru.size();
+}
+
+sp<IBinder> OperationMap::getOldestPruneableOperation() {
+    if (!hasPruneableOperation()) {
+        return sp<IBinder>(NULL);
+    }
+    return mLru[0];
+}
+
+bool OperationMap::getOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t** outToken) {
+    auto entry = mMap.find(token);
+    if (entry == mMap.end()) {
+        return false;
+    }
+    *outToken = entry->second.authToken.get();
+    return true;
+}
+
+bool OperationMap::setOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t* authToken) {
+    auto entry = mMap.find(token);
+    if (entry == mMap.end()) {
+        return false;
+    }
+    entry->second.authToken.reset(new hw_auth_token_t);
+    *entry->second.authToken = *authToken;
+    return true;
+}
+
+std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) {
+    auto appEntry = mAppTokenMap.find(appToken);
+    if (appEntry != mAppTokenMap.end()) {
+        return appEntry->second;
+    } else {
+        return std::vector<sp<IBinder>>();
+    }
+}
+
+OperationMap::Operation::Operation(keymaster_operation_handle_t handle_, uint64_t keyid_,
+                                   keymaster_purpose_t purpose_, const keymaster2_device_t* device_,
+                                   keymaster_key_characteristics_t* characteristics_,
+                                   sp<IBinder> appToken_)
+    : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
+      characteristics(characteristics_), appToken(appToken_) {}
+
+OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) {}
+
+}  // namespace android
diff --git a/security/keystore/operation.h b/security/keystore/operation.h
new file mode 100644
index 0000000..263b5c9
--- /dev/null
+++ b/security/keystore/operation.h
@@ -0,0 +1,89 @@
+/*
+ * 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 KEYSTORE_OPERATION_H_
+#define KEYSTORE_OPERATION_H_
+
+#include <hardware/hw_auth_token.h>
+#include <hardware/keymaster2.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <utils/LruCache.h>
+#include <utils/StrongPointer.h>
+#include <map>
+#include <vector>
+
+namespace android {
+
+struct keymaster_key_characteristics_t_Delete {
+    void operator()(keymaster_key_characteristics_t* characteristics) const {
+        keymaster_free_characteristics(characteristics);
+        delete characteristics;
+    }
+};
+typedef std::unique_ptr<keymaster_key_characteristics_t, keymaster_key_characteristics_t_Delete>
+    Unique_keymaster_key_characteristics;
+
+/**
+ * OperationMap handles the translation of keymaster_operation_handle_t's and
+ * keymaster2_device_t's to opaque binder tokens that can be used to reference
+ * that operation at a later time by applications. It also does LRU tracking
+ * for operation pruning and keeps a mapping of clients to operations to allow
+ * for graceful handling of application death.
+ */
+class OperationMap {
+public:
+    explicit OperationMap(IBinder::DeathRecipient* deathRecipient);
+    sp<IBinder> addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
+                             keymaster_purpose_t purpose, const keymaster2_device_t* dev,
+                             const sp<IBinder>& appToken, keymaster_key_characteristics_t* characteristics,
+                             bool pruneable);
+    bool getOperation(const sp<IBinder>& token, keymaster_operation_handle_t* outHandle,
+                      uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
+                      const keymaster2_device_t** outDev,
+                      const keymaster_key_characteristics_t** outCharacteristics);
+    bool removeOperation(const sp<IBinder>& token);
+    bool hasPruneableOperation() const;
+    size_t getOperationCount() const { return mMap.size(); }
+    size_t getPruneableOperationCount() const;
+    bool getOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t** outToken);
+    bool setOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t* authToken);
+    sp<IBinder> getOldestPruneableOperation();
+    std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken);
+
+private:
+    void updateLru(const sp<IBinder>& token);
+    void removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken);
+    struct Operation {
+        Operation();
+        Operation(keymaster_operation_handle_t handle, uint64_t keyid, keymaster_purpose_t purpose,
+                  const keymaster2_device_t* device,
+                  keymaster_key_characteristics_t* characteristics, sp<IBinder> appToken);
+        keymaster_operation_handle_t handle;
+        uint64_t keyid;
+        keymaster_purpose_t purpose;
+        const keymaster2_device_t* device;
+        Unique_keymaster_key_characteristics characteristics;
+        sp<IBinder> appToken;
+        std::unique_ptr<hw_auth_token_t> authToken;
+    };
+    std::map<sp<IBinder>, struct Operation> mMap;
+    std::vector<sp<IBinder>> mLru;
+    std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap;
+    IBinder::DeathRecipient* mDeathRecipient;
+};
+} // namespace android
+#endif
diff --git a/security/keystore/permissions.cpp b/security/keystore/permissions.cpp
new file mode 100644
index 0000000..feacd8f
--- /dev/null
+++ b/security/keystore/permissions.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 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 "keystore"
+
+#include "permissions.h"
+
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include <selinux/android.h>
+
+#include "keystore_utils.h"
+
+/* perm_labels associcated with keystore_key SELinux class verbs. */
+const char* perm_labels[] = {
+    "get_state", "get",      "insert",    "delete",    "exist",    "list",
+    "reset",     "password", "lock",      "unlock",    "is_empty", "sign",
+    "verify",    "grant",    "duplicate", "clear_uid", "add_auth", "user_changed",
+};
+
+struct user_euid {
+    uid_t uid;
+    uid_t euid;
+};
+
+user_euid user_euids[] = {
+    {AID_VPN, AID_SYSTEM}, {AID_WIFI, AID_SYSTEM}, {AID_ROOT, AID_SYSTEM},
+};
+
+struct user_perm {
+    uid_t uid;
+    perm_t perms;
+};
+
+static user_perm user_perms[] = {
+    {AID_SYSTEM, static_cast<perm_t>((uint32_t)(~0))},
+    {AID_VPN, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
+    {AID_WIFI, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
+    {AID_ROOT, static_cast<perm_t>(P_GET)},
+};
+
+static const perm_t DEFAULT_PERMS = static_cast<perm_t>(P_GET_STATE | P_GET | P_INSERT | P_DELETE |
+                                                        P_EXIST | P_LIST | P_SIGN | P_VERIFY);
+
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+};
+
+const char* get_perm_label(perm_t perm) {
+    unsigned int index = ffs(perm);
+    if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) {
+        return perm_labels[index - 1];
+    } else {
+        ALOGE("Keystore: Failed to retrieve permission label.\n");
+        abort();
+    }
+}
+
+static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) {
+    struct audit_data* ad = reinterpret_cast<struct audit_data*>(data);
+    if (!ad) {
+        ALOGE("No keystore audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
+    return 0;
+}
+
+static char* tctx;
+static int ks_is_selinux_enabled;
+
+int configure_selinux() {
+    ks_is_selinux_enabled = is_selinux_enabled();
+    if (ks_is_selinux_enabled) {
+        union selinux_callback cb;
+        cb.func_audit = audit_callback;
+        selinux_set_callback(SELINUX_CB_AUDIT, cb);
+        cb.func_log = selinux_log_callback;
+        selinux_set_callback(SELINUX_CB_LOG, cb);
+        if (getcon(&tctx) != 0) {
+            ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n");
+            return -1;
+        }
+    } else {
+        ALOGI("SELinux: Keystore SELinux is disabled.\n");
+    }
+
+    return 0;
+}
+
+static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
+    if (!ks_is_selinux_enabled) {
+        return true;
+    }
+
+    audit_data ad;
+    char* sctx = NULL;
+    const char* selinux_class = "keystore_key";
+    const char* str_perm = get_perm_label(perm);
+
+    if (!str_perm) {
+        return false;
+    }
+
+    if (getpidcon(spid, &sctx) != 0) {
+        ALOGE("SELinux: Failed to get source pid context.\n");
+        return false;
+    }
+
+    ad.pid = spid;
+    ad.uid = uid;
+
+    bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
+                                        reinterpret_cast<void*>(&ad)) == 0;
+    freecon(sctx);
+    return allowed;
+}
+
+/**
+ * Returns the UID that the callingUid should act as. This is here for
+ * legacy support of the WiFi and VPN systems and should be removed
+ * when WiFi can operate in its own namespace.
+ */
+uid_t get_keystore_euid(uid_t uid) {
+    for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.uid == uid) {
+            return user.euid;
+        }
+    }
+
+    return uid;
+}
+
+bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
+    // All system users are equivalent for multi-user support.
+    if (get_app_id(uid) == AID_SYSTEM) {
+        uid = AID_SYSTEM;
+    }
+
+    for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) {
+        struct user_perm user = user_perms[i];
+        if (user.uid == uid) {
+            return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid);
+        }
+    }
+
+    return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid);
+}
+
+/**
+ * Returns true if the callingUid is allowed to interact in the targetUid's
+ * namespace.
+ */
+bool is_granted_to(uid_t callingUid, uid_t targetUid) {
+    if (callingUid == targetUid) {
+        return true;
+    }
+    for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.euid == callingUid && user.uid == targetUid) {
+            return true;
+        }
+    }
+
+    return false;
+}
diff --git a/security/keystore/permissions.h b/security/keystore/permissions.h
new file mode 100644
index 0000000..f5f1831
--- /dev/null
+++ b/security/keystore/permissions.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 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 KEYSTORE_PERMISSIONS_H_
+#define KEYSTORE_PERMISSIONS_H_
+
+#include <unistd.h>
+
+/* Here are the permissions, actions, users, and the main function. */
+enum perm_t {
+    P_GET_STATE = 1 << 0,
+    P_GET = 1 << 1,
+    P_INSERT = 1 << 2,
+    P_DELETE = 1 << 3,
+    P_EXIST = 1 << 4,
+    P_LIST = 1 << 5,
+    P_RESET = 1 << 6,
+    P_PASSWORD = 1 << 7,
+    P_LOCK = 1 << 8,
+    P_UNLOCK = 1 << 9,
+    P_IS_EMPTY = 1 << 10,
+    P_SIGN = 1 << 11,
+    P_VERIFY = 1 << 12,
+    P_GRANT = 1 << 13,
+    P_DUPLICATE = 1 << 14,
+    P_CLEAR_UID = 1 << 15,
+    P_ADD_AUTH = 1 << 16,
+    P_USER_CHANGED = 1 << 17,
+};
+
+const char* get_perm_label(perm_t perm);
+
+/**
+ * Returns the UID that the callingUid should act as. This is here for
+ * legacy support of the WiFi and VPN systems and should be removed
+ * when WiFi can operate in its own namespace.
+ */
+uid_t get_keystore_euid(uid_t uid);
+
+bool has_permission(uid_t uid, perm_t perm, pid_t spid);
+
+/**
+ * Returns true if the callingUid is allowed to interact in the targetUid's
+ * namespace.
+ */
+bool is_granted_to(uid_t callingUid, uid_t targetUid);
+
+int configure_selinux();
+
+#endif  // KEYSTORE_PERMISSIONS_H_
diff --git a/security/keystore/test-keystore b/security/keystore/test-keystore
new file mode 100755
index 0000000..071cfcd
--- /dev/null
+++ b/security/keystore/test-keystore
@@ -0,0 +1,297 @@
+#!/bin/bash
+#
+# Copyright 2011, 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.
+
+set -e
+
+prefix=$0
+log_file=$prefix.log
+baseline_file=$prefix.baseline
+
+function cleanup_output() {
+    rm -f $log_file
+    rm -f $baseline_file
+}
+
+function log() {
+    echo "$@"
+    append $log_file \# "$@"
+    append $baseline_file \# "$@"
+}
+
+function expect() {
+    append $baseline_file "$@"
+}
+
+function append() {
+    declare -r file=$1
+    shift
+    echo "$@" >> $file
+}
+
+function run() {
+    # strip out carriage returns from adb
+    # strip out date/time from ls -l
+    "$@" | tr -d '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
+}
+
+function keystore() {
+    declare -r user=$1
+    shift
+    run adb shell su $user keystore_cli "$@"
+}
+
+function keystore_in() {
+    declare -r user=$1
+    declare -r input=$2
+    shift; shift
+    run adb shell "echo '$input' | su $user keystore_cli $@"
+}
+
+function list_keystore_directory() {
+    run adb shell ls -al /data/misc/keystore$@
+}
+
+function compare() {
+    log "comparing $baseline_file and $log_file"
+    diff $baseline_file $log_file || (log $tag FAILED && exit 1)
+}
+
+function test_basic() {
+
+    #
+    # reset
+    #
+    log "reset keystore as system user"
+    keystore system reset
+    expect "reset: No error (1)"
+    list_keystore_directory
+    expect "-rw------- keystore keystore        4 .metadata"
+    expect "drwx------ keystore keystore          user_0"
+
+    #
+    # basic tests as system/root
+    #
+    log "root does not have permission to run test"
+    keystore root test
+    expect "test: Permission denied (6)"
+
+    log "but system user does"
+    keystore system test
+    expect "test: Uninitialized (3)"
+    list_keystore_directory
+    expect "-rw------- keystore keystore        4 .metadata"
+    expect "drwx------ keystore keystore          user_0"
+
+    log "password is now bar"
+    keystore system password bar
+    expect "password: No error (1)"
+    list_keystore_directory /user_0
+    expect "-rw------- keystore keystore       84 .masterkey"
+
+    log "no error implies initialized and unlocked"
+    keystore system test
+    expect "test: No error (1)"
+
+    log "saw with no argument"
+    keystore system saw
+
+    log "saw nothing"
+    keystore system saw ""
+
+    log "add key baz"
+    keystore_in system quux insert baz
+    expect "insert: No error (1)"
+
+    log "1000 is uid of system"
+    list_keystore_directory /user_0
+    expect "-rw------- keystore keystore       84 .masterkey"
+    expect "-rw------- keystore keystore       52 1000_baz"
+
+    log "saw baz"
+    keystore system saw
+    expect "baz"
+
+    log "get baz"
+    keystore system get baz
+    expect "quux"
+
+    log "root can read system user keys (as can wifi or vpn users)"
+    keystore root get baz
+    expect "quux"
+
+    #
+    # app user tests
+    #
+
+    # u0_a0 has uid 10000, as seen below
+    log "other uses cannot see the system keys"
+    keystore u0_a0 get baz
+
+    log "app user cannot use reset, password, lock, unlock"
+    keystore u0_a0 reset
+    expect "reset: Permission denied (6)"
+    keystore u0_a0 password some_pass
+    expect "password: Permission denied (6)"
+    keystore u0_a0 lock
+    expect "lock: Permission denied (6)"
+    keystore u0_a0 unlock some_pass
+    expect "unlock: Permission denied (6)"
+
+    log "install u0_a0 key"
+    keystore_in u0_a0 deadbeef insert 0x
+    expect "insert: No error (1)"
+    list_keystore_directory /user_0
+    expect "-rw------- keystore keystore       84 .masterkey"
+    expect "-rw------- keystore keystore       52 10000_0x"
+    expect "-rw------- keystore keystore       52 1000_baz"
+
+    log "get with no argument"
+    keystore u0_a0 get
+    expect "Usage: keystore_cli get <name>"
+
+    log "few get tests for an app"
+    keystore u0_a0 get 0x
+    expect "deadbeef"
+
+    keystore_in u0_a0 barney insert fred
+    expect "insert: No error (1)"
+
+    keystore u0_a0 saw
+    expect "0x"
+    expect "fred"
+
+    log "note that saw returns the suffix of prefix matches"
+    keystore u0_a0 saw fr # fred
+    expect "ed" # fred
+
+    #
+    # lock tests
+    #
+    log "lock the store as system"
+    keystore system lock
+    expect "lock: No error (1)"
+    keystore system test
+    expect "test: Locked (2)"
+
+    log "saw works while locked"
+    keystore u0_a0 saw
+    expect "0x"
+    expect "fred"
+
+    log "...and app can read keys..."
+    keystore u0_a0 get 0x
+    expect "deadbeef"
+
+    log "...but they cannot be deleted."
+    keystore u0_a0 exist 0x
+    expect "exist: No error (1)"
+    keystore u0_a0 del_key 0x
+    expect "del_key: Key not found (7)"
+
+    #
+    # password
+    #
+    log "wrong password"
+    keystore system unlock foo
+    expect "unlock: Wrong password (4 tries left) (13)"
+    log "right password"
+    keystore system unlock bar
+    expect "unlock: No error (1)"
+
+    log "make the password foo"
+    keystore system password foo
+    expect "password: No error (1)"
+
+    #
+    # final reset
+    #
+    log "reset wipes everything for all users"
+    keystore system reset
+    expect "reset: No error (1)"
+    list_keystore_directory
+    expect "-rw------- keystore keystore        4 .metadata"
+    expect "drwx------ keystore keystore          user_0"
+    list_keystore_directory /user_0
+
+    keystore system test
+    expect "test: Uninitialized (3)"
+}
+
+function test_grant() {
+    log "test granting"
+    keystore system reset
+    expect "reset: No error (1)"
+    keystore system password test_pass
+    expect "password: No error (1)"
+
+    keystore_in system granted_key_value insert granted_key
+    expect "insert: No error (1)"
+  
+    # Cannot read before grant.
+    keystore u10_a0 get granted_key
+    
+    # Grant and read.
+    log "System grants to u0_a1"
+    keystore system grant granted_key 10001 
+    expect "Working with uid 10001"
+    expect "grant: No error (1)"
+    keystore u0_a1 get 1000_granted_key
+    expect "granted_key_value"
+}
+
+function test_4599735() {
+    # http://b/4599735
+    log "start regression test for b/4599735"
+    keystore system reset
+    expect "reset: No error (1)"
+    list_keystore_directory /user_0
+
+    keystore system password foo
+    expect "password: No error (1)"
+
+    keystore_in system quux insert baz
+    expect "insert: No error (1)"
+
+    keystore root get baz
+    expect "quux"
+
+    keystore system lock
+    expect "lock: No error (1)"
+
+    keystore system password foo
+    expect "password: No error (1)"
+
+    log "after unlock, regression led to result of '8 Value corrupted'"
+    keystore root get baz
+    expect "quux"
+
+    keystore system reset
+    expect "reset: No error (1)"
+    log "end regression test for b/4599735"
+}
+
+function main() {
+    cleanup_output
+    log $tag START
+    test_basic
+    test_4599735
+    test_grant
+    compare
+    log $tag PASSED
+    cleanup_output
+}
+
+main
diff --git a/security/keystore/tests/Android.mk b/security/keystore/tests/Android.mk
new file mode 100644
index 0000000..be8c426
--- /dev/null
+++ b/security/keystore/tests/Android.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Unit test for AuthTokenTable
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror
+LOCAL_SRC_FILES := auth_token_table_test.cpp
+LOCAL_MODULE := auth_token_table_test
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libgtest_main libkeystore_test
+LOCAL_SHARED_LIBRARIES := libkeymaster_messages
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_NATIVE_TEST)
diff --git a/security/keystore/tests/Makefile b/security/keystore/tests/Makefile
new file mode 100644
index 0000000..5c1117f
--- /dev/null
+++ b/security/keystore/tests/Makefile
@@ -0,0 +1,116 @@
+##########
+# This makefile builds local unit tests that run locally on the development machine.  Note
+# that it may be necessary to install some libraries on the dev maching to make the tests
+# build.
+#
+# The same unit tests are also built by Android.mk to run on the target device.  The tests
+# should always build and pass in both places.  The on-device test is what really matters,
+# of course, but debugging is often somewhat easier on the dev platform.
+##########
+
+BASE=../../../..
+SUBS=system/core \
+	system/keymaster\
+	hardware/libhardware \
+	external/gtest
+GTEST=$(BASE)/external/gtest
+KEYMASTER=$(BASE)/system/keymaster
+
+INCLUDES=$(foreach dir,$(SUBS),-I $(BASE)/$(dir)/include) \
+	-I $(BASE)/libnativehelper/include/nativehelper \
+	-I $(GTEST) -Iinclude
+
+# Add USE_CLANG=1 to the make command line to build with clang, which has better error
+# reporting and diagnoses some conditions that GCC doesn't.
+ifdef USE_CLANG
+CC=/usr/bin/clang
+CXX=/usr/bin/clang
+CLANG_TEST_DEFINE=-DKEYMASTER_CLANG_TEST_BUILD
+COMPILER_SPECIFIC_ARGS=-std=c++11 $(CLANG_TEST_DEFINE)
+else
+COMPILER_SPECIFIC_ARGS=-std=c++0x -fprofile-arcs
+endif
+
+CPPFLAGS=$(INCLUDES) -g -O0 -MD
+CXXFLAGS=-Wall -Werror -Wno-unused -Winit-self -Wpointer-arith	-Wunused-parameter \
+        -Werror=sign-compare -Wmissing-declarations -ftest-coverage -fno-permissive \
+	-Wno-deprecated-declarations -fno-exceptions -DKEYMASTER_NAME_TAGS \
+	$(COMPILER_SPECIFIC_ARGS)
+
+# Uncomment to enable debug logging.
+# CXXFLAGS += -DDEBUG
+
+LDLIBS=-lpthread -lstdc++ -lgcov
+
+# This list of sources is used for dependency generation and cleanup.  Add each new source
+# file here (not headers).
+CPPSRCS=\
+	../auth_token_table.cpp \
+	auth_token_table_test.cpp
+
+# This list of binaries determes what gets built and run.  Add each new test binary here.
+BINARIES=\
+	auth_token_table_test
+
+.PHONY: coverage memcheck massif clean run
+
+%.run: %
+	./$<
+	touch $@
+
+run: $(BINARIES:=.run)
+
+auth_token_table_test: auth_token_table_test.o \
+	../auth_token_table.o \
+	$(GTEST)/src/gtest-all.o \
+	$(KEYMASTER)/authorization_set.o \
+	$(KEYMASTER)/logger.o \
+	$(KEYMASTER)/serializable.o
+
+coverage: coverage.info
+	genhtml coverage.info --output-directory coverage
+
+coverage.info: run
+	lcov --capture --directory=. --directory=.. -b . --output-file coverage.info
+
+%.coverage : %
+	$(MAKE) clean && $(MAKE) $<
+	./$<
+	lcov --capture --directory=. --output-file coverage.info
+	genhtml coverage.info --output-directory coverage
+#UNINIT_OPTS=--track-origins=yes
+UNINIT_OPTS=--undef-value-errors=no
+
+MEMCHECK_OPTS=--leak-check=full \
+	--show-reachable=yes \
+	--vgdb=full \
+	$(UNINIT_OPTS) \
+	--error-exitcode=1
+
+MASSIF_OPTS=--tool=massif \
+	--stacks=yes
+
+%.memcheck : %
+	valgrind $(MEMCHECK_OPTS) ./$< && \
+	touch $@
+
+%.massif : %
+	valgrind $(MASSIF_OPTS) --massif-out-file=$@ ./$<
+
+memcheck: $(BINARIES:=.memcheck)
+
+massif: $(BINARIES:=.massif)
+
+OBJS=$(CPPSRCS:.cpp=.o)
+DEPS=$(CPPSRCS:.cpp=.d)
+GCOV=$(CPPSRCS:.cpp=.gcov) $(CPPSRCS:.cpp=.gcda) $(CPPSRCS:.cpp=.gcno)
+
+clean:
+	rm -f $(OBJS) $(DEPS) $(BINARIES) $(GCOV) \
+		$(BINARIES:=.run) $(BINARIES:=.memcheck) $(BINARIES:=.massif) \
+		*gcov *gcno *gcda coverage.info
+	rm -rf coverage
+
+-include $(CPPSRCS:.cpp=.d)
+-include $(CCSRCS:.cc=.d)
+
diff --git a/security/keystore/tests/auth_token_table_test.cpp b/security/keystore/tests/auth_token_table_test.cpp
new file mode 100644
index 0000000..b1c0f49
--- /dev/null
+++ b/security/keystore/tests/auth_token_table_test.cpp
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/logger.h>
+
+#include "../auth_token_table.h"
+
+using std::vector;
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int result = RUN_ALL_TESTS();
+}
+
+inline bool operator==(const hw_auth_token_t& a, const hw_auth_token_t& b) {
+    return (memcmp(&a, &b, sizeof(a)) == 0);
+}
+
+namespace keymaster {
+namespace test {
+
+class StdoutLogger : public Logger {
+  public:
+    StdoutLogger() { set_instance(this); }
+
+    int log_msg(LogLevel level, const char* fmt, va_list args) const {
+        int output_len = 0;
+        switch (level) {
+        case DEBUG_LVL:
+            output_len = printf("DEBUG: ");
+            break;
+        case INFO_LVL:
+            output_len = printf("INFO: ");
+            break;
+        case WARNING_LVL:
+            output_len = printf("WARNING: ");
+            break;
+        case ERROR_LVL:
+            output_len = printf("ERROR: ");
+            break;
+        case SEVERE_LVL:
+            output_len = printf("SEVERE: ");
+            break;
+        }
+
+        output_len += vprintf(fmt, args);
+        output_len += printf("\n");
+        return output_len;
+    }
+};
+
+StdoutLogger logger;
+
+TEST(AuthTokenTableTest, Create) {
+    AuthTokenTable table;
+}
+
+static hw_auth_token_t* make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
+                                   uint64_t timestamp = 0) {
+    hw_auth_token_t* token = new hw_auth_token_t;
+    token->user_id = rsid;
+    token->authenticator_id = ssid;
+    token->authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
+    token->challenge = challenge;
+    token->timestamp = hton(timestamp);
+    return token;
+}
+
+static AuthorizationSet make_set(uint64_t rsid, uint32_t timeout = 10000) {
+    AuthorizationSetBuilder builder;
+    builder.Authorization(TAG_USER_ID, 10)
+        .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
+        .Authorization(TAG_USER_SECURE_ID, rsid);
+    // Use timeout == 0 to indicate tags that require auth per operation.
+    if (timeout != 0)
+        builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
+    return builder.build();
+}
+
+// Tests obviously run so fast that a real-time clock with a one-second granularity rarely changes
+// output during a test run.  This test clock "ticks" one second every time it's called.
+static time_t monotonic_clock() {
+    static time_t time = 0;
+    return time++;
+}
+
+TEST(AuthTokenTableTest, SimpleAddAndFindTokens) {
+    AuthTokenTable table;
+
+    table.AddAuthenticationToken(make_token(1, 2));
+    table.AddAuthenticationToken(make_token(3, 4));
+    EXPECT_EQ(2U, table.size());
+
+    const hw_auth_token_t* found;
+
+    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0, &found));
+    EXPECT_EQ(1U, found->user_id);
+    EXPECT_EQ(2U, found->authenticator_id);
+
+    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(1U, found->user_id);
+    EXPECT_EQ(2U, found->authenticator_id);
+
+    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), 0, &found));
+    EXPECT_EQ(3U, found->user_id);
+    EXPECT_EQ(4U, found->authenticator_id);
+
+    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(4), 0, &found));
+    EXPECT_EQ(3U, found->user_id);
+    EXPECT_EQ(4U, found->authenticator_id);
+
+    ASSERT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(5), 0, &found));
+}
+
+TEST(AuthTokenTableTest, FlushTable) {
+    AuthTokenTable table(3, monotonic_clock);
+
+    table.AddAuthenticationToken(make_token(1));
+    table.AddAuthenticationToken(make_token(2));
+    table.AddAuthenticationToken(make_token(3));
+
+    const hw_auth_token_t* found;
+
+    // All three should be in the table.
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), 0, &found));
+
+    table.Clear();
+    EXPECT_EQ(0U, table.size());
+}
+
+TEST(AuthTokenTableTest, TableOverflow) {
+    AuthTokenTable table(3, monotonic_clock);
+
+    table.AddAuthenticationToken(make_token(1));
+    table.AddAuthenticationToken(make_token(2));
+    table.AddAuthenticationToken(make_token(3));
+
+    const hw_auth_token_t* found;
+
+    // All three should be in the table.
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), 0, &found));
+
+    table.AddAuthenticationToken(make_token(4));
+
+    // Oldest should be gone.
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(1), 0, &found));
+
+    // Others should be there, including the new one (4).  Search for it first, then the others, so
+    // 4 becomes the least recently used.
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(4), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), 0, &found));
+
+    table.AddAuthenticationToken(make_token(5));
+
+    // 5 should have replaced 4.
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(4), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(5), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), 0, &found));
+
+    table.AddAuthenticationToken(make_token(6));
+    table.AddAuthenticationToken(make_token(7));
+
+    // 2 and 5 should be gone
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(5), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(6), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(7), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), 0, &found));
+
+    table.AddAuthenticationToken(make_token(8));
+    table.AddAuthenticationToken(make_token(9));
+    table.AddAuthenticationToken(make_token(10));
+
+    // Only the three most recent should be there.
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(1), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(3), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(4), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(5), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(6), 0, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(7), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(8), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(9), 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(10), 0, &found));
+}
+
+TEST(AuthTokenTableTest, AuthenticationNotRequired) {
+    AuthTokenTable table;
+    const hw_auth_token_t* found;
+
+    EXPECT_EQ(AuthTokenTable::AUTH_NOT_REQUIRED,
+              table.FindAuthorization(AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED),
+                                      0 /* no challenge */, &found));
+}
+
+TEST(AuthTokenTableTest, OperationHandleNotFound) {
+    AuthTokenTable table;
+    const hw_auth_token_t* found;
+
+    table.AddAuthenticationToken(make_token(1, 0, 1, 5));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */),
+                                      2 /* non-matching challenge */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1, 0 /* no timeout */),
+                                                          1 /* matching challenge */, &found));
+    table.MarkCompleted(1);
+    EXPECT_EQ(
+        AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+        table.FindAuthorization(make_set(1, 0 /* no timeout */), 1 /* used challenge */, &found));
+}
+
+TEST(AuthTokenTableTest, OperationHandleRequired) {
+    AuthTokenTable table;
+    const hw_auth_token_t* found;
+
+    table.AddAuthenticationToken(make_token(1));
+    EXPECT_EQ(
+        AuthTokenTable::OP_HANDLE_REQUIRED,
+        table.FindAuthorization(make_set(1, 0 /* no timeout */), 0 /* no op handle */, &found));
+}
+
+TEST(AuthTokenTableTest, AuthSidChanged) {
+    AuthTokenTable table;
+    const hw_auth_token_t* found;
+
+    table.AddAuthenticationToken(make_token(1, 3, /* op handle */ 1));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_WRONG_SID,
+              table.FindAuthorization(make_set(2, 0 /* no timeout */), 1 /* op handle */, &found));
+}
+
+TEST(AuthTokenTableTest, TokenExpired) {
+    AuthTokenTable table(5, monotonic_clock);
+    const hw_auth_token_t* found;
+
+    auto key_info = make_set(1, 5 /* five second timeout */);
+
+    // monotonic_clock "ticks" one second each time it's called, which is once per request, so the
+    // sixth request should fail, since key_info says the key is good for five seconds.
+    //
+    // Note that this tests the decision of the AuthTokenTable to reject a request it knows is
+    // expired.  An additional check of the secure timestamp (in the token) will be made by
+    // keymaster when the found token is passed to it.
+    table.AddAuthenticationToken(make_token(1, 0));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(key_info, 0 /* no op handle */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(key_info, 0 /* no op handle */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(key_info, 0 /* no op handle */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(key_info, 0 /* no op handle */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(key_info, 0 /* no op handle */, &found));
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_EXPIRED,
+              table.FindAuthorization(key_info, 0 /* no op handle */, &found));
+}
+
+TEST(AuthTokenTableTest, MarkNonexistentEntryCompleted) {
+    AuthTokenTable table;
+    // Marking a nonexistent entry completed is ignored.  This test is mainly for code coverage.
+    table.MarkCompleted(1);
+}
+
+TEST(AuthTokenTableTest, SupersededEntries) {
+    AuthTokenTable table;
+    const hw_auth_token_t* found;
+
+    // Add two identical tokens, without challenges.  The second should supersede the first, based
+    // on timestamp (fourth arg to make_token).
+    table.AddAuthenticationToken(make_token(1, 0, 0, 0));
+    table.AddAuthenticationToken(make_token(1, 0, 0, 1));
+    EXPECT_EQ(1U, table.size());
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0, &found));
+    EXPECT_EQ(1U, ntoh(found->timestamp));
+
+    // Add a third token, this with a different RSID.  It should not be superseded.
+    table.AddAuthenticationToken(make_token(2, 0, 0, 2));
+    EXPECT_EQ(2U, table.size());
+
+    // Add two more, superseding each of the two in the table.
+    table.AddAuthenticationToken(make_token(1, 0, 0, 3));
+    table.AddAuthenticationToken(make_token(2, 0, 0, 4));
+    EXPECT_EQ(2U, table.size());
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0, &found));
+    EXPECT_EQ(3U, ntoh(found->timestamp));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0, &found));
+    EXPECT_EQ(4U, ntoh(found->timestamp));
+
+    // Add another, this one with a challenge value.  It should supersede the old one since it is
+    // newer, and matches other than the challenge.
+    table.AddAuthenticationToken(make_token(1, 0, 1, 5));
+    EXPECT_EQ(2U, table.size());
+
+    // And another, also with a challenge.  Because of the challenge values, the one just added
+    // cannot be superseded.
+    table.AddAuthenticationToken(make_token(1, 0, 2, 6));
+    EXPECT_EQ(3U, table.size());
+
+    // Should be able to find each of them, by specifying their challenge, with a key that is not
+    // timed (timed keys don't care about challenges).
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1, 0 /* no timeout*/), 1 /* challenge */, &found));
+    EXPECT_EQ(5U, ntoh(found->timestamp));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 2 /* challenge */, &found));
+    EXPECT_EQ(6U, ntoh(found->timestamp));
+
+    // Add another, without a challenge, and the same timestamp as the last one.  This new one
+    // actually could be considered already-superseded, but the table doesn't handle that case,
+    // since it seems unlikely to occur in practice.
+    table.AddAuthenticationToken(make_token(1, 0, 0, 6));
+    EXPECT_EQ(4U, table.size());
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0 /* challenge */, &found));
+    EXPECT_EQ(6U, ntoh(found->timestamp));
+
+    // Add another without a challenge but an increased timestamp. This should supersede the
+    // previous challenge-free entry.
+    table.AddAuthenticationToken(make_token(1, 0, 0, 7));
+    EXPECT_EQ(4U, table.size());
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 2 /* challenge */, &found));
+    EXPECT_EQ(6U, ntoh(found->timestamp));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0 /* challenge */, &found));
+    EXPECT_EQ(7U, ntoh(found->timestamp));
+
+    // Mark the entry with challenge 2 as complete.  Since there's a newer challenge-free entry, the
+    // challenge entry will be superseded.
+    table.MarkCompleted(2);
+    EXPECT_EQ(3U, table.size());
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 2 /* challenge */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0 /* challenge */, &found));
+    EXPECT_EQ(7U, ntoh(found->timestamp));
+
+    // Add another SID 1 entry with a challenge.  It supersedes the previous SID 1 entry with
+    // no challenge (timestamp 7), but not the one with challenge 1 (timestamp 5).
+    table.AddAuthenticationToken(make_token(1, 0, 3, 8));
+    EXPECT_EQ(3U, table.size());
+
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 1 /* challenge */, &found));
+    EXPECT_EQ(5U, ntoh(found->timestamp));
+
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 3 /* challenge */, &found));
+    EXPECT_EQ(8U, ntoh(found->timestamp));
+
+    // SID 2 entry is still there.
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), 0 /* challenge */, &found));
+    EXPECT_EQ(4U, ntoh(found->timestamp));
+
+    // Mark the entry with challenge 3 as complete.  Since the older challenge 1 entry is
+    // incomplete, nothing is superseded.
+    table.MarkCompleted(3);
+    EXPECT_EQ(3U, table.size());
+
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 1 /* challenge */, &found));
+    EXPECT_EQ(5U, ntoh(found->timestamp));
+
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0 /* challenge */, &found));
+    EXPECT_EQ(8U, ntoh(found->timestamp));
+
+    // Mark the entry with challenge 1 as complete.  Since there's a newer one (with challenge 3,
+    // completed), the challenge 1 entry is superseded and removed.
+    table.MarkCompleted(1);
+    EXPECT_EQ(2U, table.size());
+    EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), 1 /* challenge */, &found));
+    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), 0 /* challenge */, &found));
+    EXPECT_EQ(8U, ntoh(found->timestamp));
+}
+
+}  // namespace keymaster
+}  // namespace test
diff --git a/security/keystore/user_state.cpp b/security/keystore/user_state.cpp
new file mode 100644
index 0000000..3da88c2
--- /dev/null
+++ b/security/keystore/user_state.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2016 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 "keystore"
+
+#include "user_state.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <openssl/evp.h>
+
+#include <cutils/log.h>
+
+#include "blob.h"
+#include "keystore_utils.h"
+
+UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
+    asprintf(&mUserDir, "user_%u", mUserId);
+    asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
+}
+
+UserState::~UserState() {
+    free(mUserDir);
+    free(mMasterKeyFile);
+}
+
+bool UserState::initialize() {
+    if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
+        ALOGE("Could not create directory '%s'", mUserDir);
+        return false;
+    }
+
+    if (access(mMasterKeyFile, R_OK) == 0) {
+        setState(STATE_LOCKED);
+    } else {
+        setState(STATE_UNINITIALIZED);
+    }
+
+    return true;
+}
+
+void UserState::setState(State state) {
+    mState = state;
+    if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
+        mRetry = MAX_RETRY;
+    }
+}
+
+void UserState::zeroizeMasterKeysInMemory() {
+    memset(mMasterKey, 0, sizeof(mMasterKey));
+    memset(mSalt, 0, sizeof(mSalt));
+    memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
+    memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
+}
+
+bool UserState::deleteMasterKey() {
+    setState(STATE_UNINITIALIZED);
+    zeroizeMasterKeysInMemory();
+    return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
+}
+
+ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
+    if (!generateMasterKey(entropy)) {
+        return SYSTEM_ERROR;
+    }
+    ResponseCode response = writeMasterKey(pw, entropy);
+    if (response != NO_ERROR) {
+        return response;
+    }
+    setupMasterKeys();
+    return ::NO_ERROR;
+}
+
+ResponseCode UserState::copyMasterKey(UserState* src) {
+    if (mState != STATE_UNINITIALIZED) {
+        return ::SYSTEM_ERROR;
+    }
+    if (src->getState() != STATE_NO_ERROR) {
+        return ::SYSTEM_ERROR;
+    }
+    memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
+    setupMasterKeys();
+    return copyMasterKeyFile(src);
+}
+
+ResponseCode UserState::copyMasterKeyFile(UserState* src) {
+    /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
+     * password so we cannot generate a new file with a new salt.
+     */
+    int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
+    if (in < 0) {
+        return ::SYSTEM_ERROR;
+    }
+    blob rawBlob;
+    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
+    if (close(in) != 0) {
+        return ::SYSTEM_ERROR;
+    }
+    int out =
+        TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+    if (out < 0) {
+        return ::SYSTEM_ERROR;
+    }
+    size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
+    if (close(out) != 0) {
+        return ::SYSTEM_ERROR;
+    }
+    if (outLength != length) {
+        ALOGW("blob not fully written %zu != %zu", outLength, length);
+        unlink(mMasterKeyFile);
+        return ::SYSTEM_ERROR;
+    }
+    return ::NO_ERROR;
+}
+
+ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
+    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
+    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
+    AES_KEY passwordAesKey;
+    AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
+    Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
+    return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
+}
+
+ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
+    int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
+    if (in < 0) {
+        return SYSTEM_ERROR;
+    }
+
+    // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
+    // to use with decryptBlob
+    blob rawBlob;
+    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
+    if (close(in) != 0) {
+        return SYSTEM_ERROR;
+    }
+    // find salt at EOF if present, otherwise we have an old file
+    uint8_t* salt;
+    if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
+        salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
+    } else {
+        salt = NULL;
+    }
+    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
+    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
+    AES_KEY passwordAesKey;
+    AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
+    Blob masterKeyBlob(rawBlob);
+    ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
+    if (response == SYSTEM_ERROR) {
+        return response;
+    }
+    if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
+        // If salt was missing, generate one and write a new master key file with the salt.
+        if (salt == NULL) {
+            if (!generateSalt(entropy)) {
+                return SYSTEM_ERROR;
+            }
+            response = writeMasterKey(pw, entropy);
+        }
+        if (response == NO_ERROR) {
+            memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
+            setupMasterKeys();
+        }
+        return response;
+    }
+    if (mRetry <= 0) {
+        reset();
+        return UNINITIALIZED;
+    }
+    --mRetry;
+    switch (mRetry) {
+    case 0:
+        return WRONG_PASSWORD_0;
+    case 1:
+        return WRONG_PASSWORD_1;
+    case 2:
+        return WRONG_PASSWORD_2;
+    case 3:
+        return WRONG_PASSWORD_3;
+    default:
+        return WRONG_PASSWORD_3;
+    }
+}
+
+bool UserState::reset() {
+    DIR* dir = opendir(getUserDirName());
+    if (!dir) {
+        // If the directory doesn't exist then nothing to do.
+        if (errno == ENOENT) {
+            return true;
+        }
+        ALOGW("couldn't open user directory: %s", strerror(errno));
+        return false;
+    }
+
+    struct dirent* file;
+    while ((file = readdir(dir)) != NULL) {
+        // skip . and ..
+        if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
+            continue;
+        }
+
+        unlinkat(dirfd(dir), file->d_name, 0);
+    }
+    closedir(dir);
+    return true;
+}
+
+void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+                                        uint8_t* salt) {
+    size_t saltSize;
+    if (salt != NULL) {
+        saltSize = SALT_SIZE;
+    } else {
+        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
+        salt = (uint8_t*)"keystore";
+        // sizeof = 9, not strlen = 8
+        saltSize = sizeof("keystore");
+    }
+
+    PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
+                           8192, keySize, key);
+}
+
+bool UserState::generateSalt(Entropy* entropy) {
+    return entropy->generate_random_data(mSalt, sizeof(mSalt));
+}
+
+bool UserState::generateMasterKey(Entropy* entropy) {
+    if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
+        return false;
+    }
+    if (!generateSalt(entropy)) {
+        return false;
+    }
+    return true;
+}
+
+void UserState::setupMasterKeys() {
+    AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
+    AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
+    setState(STATE_NO_ERROR);
+}
diff --git a/security/keystore/user_state.h b/security/keystore/user_state.h
new file mode 100644
index 0000000..902719c
--- /dev/null
+++ b/security/keystore/user_state.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 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 KEYSTORE_USER_STATE_H_
+#define KEYSTORE_USER_STATE_H_
+
+#include <sys/types.h>
+
+#include <openssl/aes.h>
+
+#include <utils/String8.h>
+
+#include <keystore/keystore.h>
+
+#include "entropy.h"
+
+class UserState {
+  public:
+    explicit UserState(uid_t userId);
+    ~UserState();
+
+    bool initialize();
+
+    uid_t getUserId() const { return mUserId; }
+    const char* getUserDirName() const { return mUserDir; }
+
+    const char* getMasterKeyFileName() const { return mMasterKeyFile; }
+
+    void setState(State state);
+    State getState() const { return mState; }
+
+    int8_t getRetry() const { return mRetry; }
+
+    void zeroizeMasterKeysInMemory();
+    bool deleteMasterKey();
+
+    ResponseCode initialize(const android::String8& pw, Entropy* entropy);
+
+    ResponseCode copyMasterKey(UserState* src);
+    ResponseCode copyMasterKeyFile(UserState* src);
+    ResponseCode writeMasterKey(const android::String8& pw, Entropy* entropy);
+    ResponseCode readMasterKey(const android::String8& pw, Entropy* entropy);
+
+    AES_KEY* getEncryptionKey() { return &mMasterKeyEncryption; }
+    AES_KEY* getDecryptionKey() { return &mMasterKeyDecryption; }
+
+    bool reset();
+
+  private:
+    static const int MASTER_KEY_SIZE_BYTES = 16;
+    static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
+
+    static const int MAX_RETRY = 4;
+    static const size_t SALT_SIZE = 16;
+
+    void generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+                                 uint8_t* salt);
+    bool generateSalt(Entropy* entropy);
+    bool generateMasterKey(Entropy* entropy);
+    void setupMasterKeys();
+
+    uid_t mUserId;
+
+    char* mUserDir;
+    char* mMasterKeyFile;
+
+    State mState;
+    int8_t mRetry;
+
+    uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
+    uint8_t mSalt[SALT_SIZE];
+
+    AES_KEY mMasterKeyEncryption;
+    AES_KEY mMasterKeyDecryption;
+};
+
+#endif  // KEYSTORE_USER_STATE_H_
diff --git a/security/softkeymaster/Android.mk b/security/softkeymaster/Android.mk
new file mode 100644
index 0000000..eb32c87
--- /dev/null
+++ b/security/softkeymaster/Android.mk
@@ -0,0 +1,44 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_MODULE := keystore.default
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := module.cpp
+LOCAL_C_INCLUDES := system/security/keystore
+LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
+LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder libsoftkeymaster
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_MODULE := libsoftkeymaster
+LOCAL_SRC_FILES := keymaster_openssl.cpp
+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)
diff --git a/security/softkeymaster/include/keymaster/softkeymaster.h b/security/softkeymaster/include/keymaster/softkeymaster.h
new file mode 100644
index 0000000..e86ba3d
--- /dev/null
+++ b/security/softkeymaster/include/keymaster/softkeymaster.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 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 <hardware/keymaster0.h>
+
+#ifndef SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
+#define SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
+
+int openssl_generate_keypair(const keymaster0_device_t* dev, const keymaster_keypair_t key_type,
+                             const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength);
+
+int openssl_import_keypair(const keymaster0_device_t* dev, const uint8_t* key,
+                           const size_t key_length, uint8_t** key_blob, size_t* key_blob_length);
+
+int openssl_get_keypair_public(const struct keymaster0_device* dev, const uint8_t* key_blob,
+                               const size_t key_blob_length, uint8_t** x509_data,
+                               size_t* x509_data_length);
+
+int openssl_sign_data(const keymaster0_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);
+
+int openssl_verify_data(const keymaster0_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);
+
+int openssl_open(const hw_module_t* module, const char* name, hw_device_t** device);
+
+extern struct keystore_module softkeymaster_module;
+
+#endif  // SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
diff --git a/security/softkeymaster/keymaster_openssl.cpp b/security/softkeymaster/keymaster_openssl.cpp
new file mode 100644
index 0000000..927b4a6
--- /dev/null
+++ b/security/softkeymaster/keymaster_openssl.cpp
@@ -0,0 +1,785 @@
+/*
+ * 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 <keystore/keystore.h>
+#include <keymaster/softkeymaster.h>
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster0.h>
+
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/rsa.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+#include <UniquePtr.h>
+
+// For debugging
+// #define LOG_NDEBUG 0
+
+#define LOG_TAG "OpenSSLKeyMaster"
+#include <cutils/log.h>
+
+struct BIGNUM_Delete {
+    void operator()(BIGNUM* p) const { BN_free(p); }
+};
+typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
+
+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 PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
+struct DSA_Delete {
+    void operator()(DSA* p) const { DSA_free(p); }
+};
+typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
+
+struct EC_KEY_Delete {
+    void operator()(EC_KEY* p) const { EC_KEY_free(p); }
+};
+typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
+
+struct EC_GROUP_Delete {
+    void operator()(EC_GROUP* p) const { EC_GROUP_free(p); }
+};
+typedef UniquePtr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
+
+struct RSA_Delete {
+    void operator()(RSA* p) const { RSA_free(p); }
+};
+typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
+
+struct Malloc_Free {
+    void operator()(void* p) const { free(p); }
+};
+
+typedef UniquePtr<keymaster0_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().
+ */
+template <typename T, typename Delete_T>
+inline void release_because_ownership_transferred(UniquePtr<T, Delete_T>& p) {
+    T* val __attribute__((unused)) = p.release();
+}
+
+/*
+ * Checks this thread's OpenSSL error queue and logs if
+ * necessary.
+ */
+static void logOpenSSLError(const char* location) {
+    int error = ERR_get_error();
+
+    if (error != 0) {
+        char message[256];
+        ERR_error_string_n(error, message, sizeof(message));
+        ALOGE("OpenSSL error in %s %d: %s", location, error, message);
+    }
+
+    ERR_clear_error();
+    ERR_remove_thread_state(NULL);
+}
+
+static int wrap_key(EVP_PKEY* pkey, int type, uint8_t** keyBlob, size_t* keyBlobLength) {
+    /*
+     * Find the length of each size. Public key is not needed anymore
+     * but must be kept for alignment purposes.
+     */
+    int publicLen = 0;
+    int privateLen = i2d_PrivateKey(pkey, NULL);
+
+    if (privateLen <= 0) {
+        ALOGE("private key size was too big");
+        return -1;
+    }
+
+    /* int type + int size + private key data + int size + public key data */
+    *keyBlobLength = get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + privateLen +
+                     sizeof(privateLen) + publicLen;
+
+    // derData will be returned to the caller, so allocate it with malloc.
+    UniquePtr<unsigned char, Malloc_Free> derData(
+        static_cast<unsigned char*>(malloc(*keyBlobLength)));
+    if (derData.get() == NULL) {
+        ALOGE("could not allocate memory for key blob");
+        return -1;
+    }
+    unsigned char* p = derData.get();
+
+    /* Write the magic value for software keys. */
+    p = add_softkey_header(p, *keyBlobLength);
+
+    /* Write key type to allocated buffer */
+    for (int i = sizeof(type) - 1; i >= 0; i--) {
+        *p++ = (type >> (8 * i)) & 0xFF;
+    }
+
+    /* Write public key to allocated buffer */
+    for (int i = sizeof(publicLen) - 1; i >= 0; i--) {
+        *p++ = (publicLen >> (8 * i)) & 0xFF;
+    }
+
+    /* Write private key to allocated buffer */
+    for (int i = sizeof(privateLen) - 1; i >= 0; i--) {
+        *p++ = (privateLen >> (8 * i)) & 0xFF;
+    }
+    if (i2d_PrivateKey(pkey, &p) != privateLen) {
+        logOpenSSLError("wrap_key");
+        return -1;
+    }
+
+    *keyBlob = derData.release();
+
+    return 0;
+}
+
+static EVP_PKEY* unwrap_key(const uint8_t* keyBlob, const size_t keyBlobLength) {
+    long publicLen = 0;
+    long privateLen = 0;
+    const uint8_t* p = keyBlob;
+    const uint8_t* const end = keyBlob + keyBlobLength;
+
+    if (keyBlob == NULL) {
+        ALOGE("supplied key blob was NULL");
+        return NULL;
+    }
+
+    int type = 0;
+    if (keyBlobLength < (get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + 1 +
+                         sizeof(privateLen) + 1)) {
+        ALOGE("key blob appears to be truncated");
+        return NULL;
+    }
+
+    if (!is_softkey(p, keyBlobLength)) {
+        ALOGE("cannot read key; it was not made by this keymaster");
+        return NULL;
+    }
+    p += get_softkey_header_size();
+
+    for (size_t i = 0; i < sizeof(type); i++) {
+        type = (type << 8) | *p++;
+    }
+
+    for (size_t i = 0; i < sizeof(type); i++) {
+        publicLen = (publicLen << 8) | *p++;
+    }
+    if (p + publicLen > end) {
+        ALOGE("public key length encoding error: size=%ld, end=%td", publicLen, end - p);
+        return NULL;
+    }
+
+    p += publicLen;
+    if (end - p < 2) {
+        ALOGE("private key truncated");
+        return NULL;
+    }
+    for (size_t i = 0; i < sizeof(type); i++) {
+        privateLen = (privateLen << 8) | *p++;
+    }
+    if (p + privateLen > end) {
+        ALOGE("private key length encoding error: size=%ld, end=%td", privateLen, end - p);
+        return NULL;
+    }
+
+    Unique_EVP_PKEY pkey(d2i_PrivateKey(type, nullptr, &p, privateLen));
+    if (pkey.get() == NULL) {
+        logOpenSSLError("unwrap_key");
+        return NULL;
+    }
+
+    return pkey.release();
+}
+
+static int generate_dsa_keypair(EVP_PKEY* pkey, const keymaster_dsa_keygen_params_t* dsa_params) {
+    if (dsa_params->key_size < 512) {
+        ALOGI("Requested DSA key size is too small (<512)");
+        return -1;
+    }
+
+    Unique_DSA dsa(DSA_new());
+
+    if (dsa_params->generator_len == 0 || dsa_params->prime_p_len == 0 ||
+        dsa_params->prime_q_len == 0 || dsa_params->generator == NULL ||
+        dsa_params->prime_p == NULL || dsa_params->prime_q == NULL) {
+        if (DSA_generate_parameters_ex(dsa.get(), dsa_params->key_size, NULL, 0, NULL, NULL,
+                                       NULL) != 1) {
+            logOpenSSLError("generate_dsa_keypair");
+            return -1;
+        }
+    } else {
+        dsa->g = BN_bin2bn(dsa_params->generator, dsa_params->generator_len, NULL);
+        if (dsa->g == NULL) {
+            logOpenSSLError("generate_dsa_keypair");
+            return -1;
+        }
+
+        dsa->p = BN_bin2bn(dsa_params->prime_p, dsa_params->prime_p_len, NULL);
+        if (dsa->p == NULL) {
+            logOpenSSLError("generate_dsa_keypair");
+            return -1;
+        }
+
+        dsa->q = BN_bin2bn(dsa_params->prime_q, dsa_params->prime_q_len, NULL);
+        if (dsa->q == NULL) {
+            logOpenSSLError("generate_dsa_keypair");
+            return -1;
+        }
+    }
+
+    if (DSA_generate_key(dsa.get()) != 1) {
+        logOpenSSLError("generate_dsa_keypair");
+        return -1;
+    }
+
+    if (EVP_PKEY_assign_DSA(pkey, dsa.get()) == 0) {
+        logOpenSSLError("generate_dsa_keypair");
+        return -1;
+    }
+    release_because_ownership_transferred(dsa);
+
+    return 0;
+}
+
+static int generate_ec_keypair(EVP_PKEY* pkey, const keymaster_ec_keygen_params_t* ec_params) {
+    Unique_EC_GROUP group;
+    switch (ec_params->field_size) {
+    case 224:
+        group.reset(EC_GROUP_new_by_curve_name(NID_secp224r1));
+        break;
+    case 256:
+        group.reset(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+        break;
+    case 384:
+        group.reset(EC_GROUP_new_by_curve_name(NID_secp384r1));
+        break;
+    case 521:
+        group.reset(EC_GROUP_new_by_curve_name(NID_secp521r1));
+        break;
+    default:
+        break;
+    }
+
+    if (group.get() == NULL) {
+        logOpenSSLError("generate_ec_keypair");
+        return -1;
+    }
+
+#if !defined(OPENSSL_IS_BORINGSSL)
+    EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
+    EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
+#endif
+
+    /* initialize EC key */
+    Unique_EC_KEY eckey(EC_KEY_new());
+    if (eckey.get() == NULL) {
+        logOpenSSLError("generate_ec_keypair");
+        return -1;
+    }
+
+    if (EC_KEY_set_group(eckey.get(), group.get()) != 1) {
+        logOpenSSLError("generate_ec_keypair");
+        return -1;
+    }
+
+    if (EC_KEY_generate_key(eckey.get()) != 1 || EC_KEY_check_key(eckey.get()) < 0) {
+        logOpenSSLError("generate_ec_keypair");
+        return -1;
+    }
+
+    if (EVP_PKEY_assign_EC_KEY(pkey, eckey.get()) == 0) {
+        logOpenSSLError("generate_ec_keypair");
+        return -1;
+    }
+    release_because_ownership_transferred(eckey);
+
+    return 0;
+}
+
+static int generate_rsa_keypair(EVP_PKEY* pkey, const keymaster_rsa_keygen_params_t* rsa_params) {
+    Unique_BIGNUM bn(BN_new());
+    if (bn.get() == NULL) {
+        logOpenSSLError("generate_rsa_keypair");
+        return -1;
+    }
+
+    if (BN_set_word(bn.get(), rsa_params->public_exponent) == 0) {
+        logOpenSSLError("generate_rsa_keypair");
+        return -1;
+    }
+
+    /* initialize RSA */
+    Unique_RSA rsa(RSA_new());
+    if (rsa.get() == NULL) {
+        logOpenSSLError("generate_rsa_keypair");
+        return -1;
+    }
+
+    if (!RSA_generate_key_ex(rsa.get(), rsa_params->modulus_size, bn.get(), NULL) ||
+        RSA_check_key(rsa.get()) < 0) {
+        logOpenSSLError("generate_rsa_keypair");
+        return -1;
+    }
+
+    if (EVP_PKEY_assign_RSA(pkey, rsa.get()) == 0) {
+        logOpenSSLError("generate_rsa_keypair");
+        return -1;
+    }
+    release_because_ownership_transferred(rsa);
+
+    return 0;
+}
+
+__attribute__((visibility("default"))) int openssl_generate_keypair(
+    const keymaster0_device_t*, const keymaster_keypair_t key_type, const void* key_params,
+    uint8_t** keyBlob, size_t* keyBlobLength) {
+    Unique_EVP_PKEY pkey(EVP_PKEY_new());
+    if (pkey.get() == NULL) {
+        logOpenSSLError("openssl_generate_keypair");
+        return -1;
+    }
+
+    if (key_params == NULL) {
+        ALOGW("key_params == null");
+        return -1;
+    } else if (key_type == TYPE_DSA) {
+        const keymaster_dsa_keygen_params_t* dsa_params =
+            (const keymaster_dsa_keygen_params_t*)key_params;
+        generate_dsa_keypair(pkey.get(), dsa_params);
+    } else if (key_type == TYPE_EC) {
+        const keymaster_ec_keygen_params_t* ec_params =
+            (const keymaster_ec_keygen_params_t*)key_params;
+        generate_ec_keypair(pkey.get(), ec_params);
+    } else if (key_type == TYPE_RSA) {
+        const keymaster_rsa_keygen_params_t* rsa_params =
+            (const keymaster_rsa_keygen_params_t*)key_params;
+        generate_rsa_keypair(pkey.get(), rsa_params);
+    } else {
+        ALOGW("Unsupported key type %d", key_type);
+        return -1;
+    }
+
+    if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), keyBlob, keyBlobLength)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+__attribute__((visibility("default"))) int openssl_import_keypair(const keymaster0_device_t*,
+                                                                  const uint8_t* key,
+                                                                  const size_t key_length,
+                                                                  uint8_t** key_blob,
+                                                                  size_t* key_blob_length) {
+    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;
+    }
+
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
+    if (pkcs8.get() == NULL) {
+        logOpenSSLError("openssl_import_keypair");
+        return -1;
+    }
+
+    /* assign to EVP */
+    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+    if (pkey.get() == NULL) {
+        logOpenSSLError("openssl_import_keypair");
+        return -1;
+    }
+
+    if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), key_blob, key_blob_length)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+__attribute__((visibility("default"))) int openssl_get_keypair_public(const keymaster0_device_t*,
+                                                                      const uint8_t* key_blob,
+                                                                      const size_t key_blob_length,
+                                                                      uint8_t** x509_data,
+                                                                      size_t* x509_data_length) {
+    if (x509_data == NULL || x509_data_length == NULL) {
+        ALOGW("output public key buffer == NULL");
+        return -1;
+    }
+
+    Unique_EVP_PKEY pkey(unwrap_key(key_blob, key_blob_length));
+    if (pkey.get() == NULL) {
+        return -1;
+    }
+
+    int len = i2d_PUBKEY(pkey.get(), NULL);
+    if (len <= 0) {
+        logOpenSSLError("openssl_get_keypair_public");
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> 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) {
+        logOpenSSLError("openssl_get_keypair_public");
+        return -1;
+    }
+
+    ALOGV("Length of x509 data is %d", len);
+    *x509_data_length = len;
+    *x509_data = key.release();
+
+    return 0;
+}
+
+static int sign_dsa(EVP_PKEY* pkey, keymaster_dsa_sign_params_t* sign_params, const uint8_t* data,
+                    const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
+    if (dsa.get() == NULL) {
+        logOpenSSLError("openssl_sign_dsa");
+        return -1;
+    }
+
+    unsigned int dsaSize = DSA_size(dsa.get());
+    UniquePtr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dsaSize)));
+    if (signedDataPtr.get() == NULL) {
+        logOpenSSLError("openssl_sign_dsa");
+        return -1;
+    }
+
+    unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
+    if (DSA_sign(0, data, dataLength, tmp, &dsaSize, dsa.get()) <= 0) {
+        logOpenSSLError("openssl_sign_dsa");
+        return -1;
+    }
+
+    *signedDataLength = dsaSize;
+    *signedData = signedDataPtr.release();
+
+    return 0;
+}
+
+static int sign_ec(EVP_PKEY* pkey, keymaster_ec_sign_params_t* sign_params, const uint8_t* data,
+                   const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
+    if (eckey.get() == NULL) {
+        logOpenSSLError("openssl_sign_ec");
+        return -1;
+    }
+
+    unsigned int ecdsaSize = ECDSA_size(eckey.get());
+    UniquePtr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(ecdsaSize)));
+    if (signedDataPtr.get() == NULL) {
+        logOpenSSLError("openssl_sign_ec");
+        return -1;
+    }
+
+    unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
+    if (ECDSA_sign(0, data, dataLength, tmp, &ecdsaSize, eckey.get()) <= 0) {
+        logOpenSSLError("openssl_sign_ec");
+        return -1;
+    }
+
+    *signedDataLength = ecdsaSize;
+    *signedData = signedDataPtr.release();
+
+    return 0;
+}
+
+static int sign_rsa(EVP_PKEY* pkey, keymaster_rsa_sign_params_t* sign_params, const uint8_t* data,
+                    const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    } else if (sign_params->padding_type != PADDING_NONE) {
+        ALOGW("Cannot handle padding type %d", sign_params->padding_type);
+        return -1;
+    }
+
+    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
+    if (rsa.get() == NULL) {
+        logOpenSSLError("openssl_sign_rsa");
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dataLength)));
+    if (signedDataPtr.get() == NULL) {
+        logOpenSSLError("openssl_sign_rsa");
+        return -1;
+    }
+
+    unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
+    if (RSA_private_encrypt(dataLength, data, tmp, rsa.get(), RSA_NO_PADDING) <= 0) {
+        logOpenSSLError("openssl_sign_rsa");
+        return -1;
+    }
+
+    *signedDataLength = dataLength;
+    *signedData = signedDataPtr.release();
+
+    return 0;
+}
+
+__attribute__((visibility("default"))) int openssl_sign_data(
+    const keymaster0_device_t*, 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 (data == NULL) {
+        ALOGW("input data to sign == NULL");
+        return -1;
+    } else if (signedData == NULL || signedDataLength == NULL) {
+        ALOGW("output signature buffer == NULL");
+        return -1;
+    }
+
+    Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
+    if (pkey.get() == NULL) {
+        return -1;
+    }
+
+    int type = EVP_PKEY_type(pkey->type);
+    if (type == EVP_PKEY_DSA) {
+        const keymaster_dsa_sign_params_t* sign_params =
+            reinterpret_cast<const keymaster_dsa_sign_params_t*>(params);
+        return sign_dsa(pkey.get(), const_cast<keymaster_dsa_sign_params_t*>(sign_params), data,
+                        dataLength, signedData, signedDataLength);
+    } else if (type == EVP_PKEY_EC) {
+        const keymaster_ec_sign_params_t* sign_params =
+            reinterpret_cast<const keymaster_ec_sign_params_t*>(params);
+        return sign_ec(pkey.get(), const_cast<keymaster_ec_sign_params_t*>(sign_params), data,
+                       dataLength, signedData, signedDataLength);
+    } else if (type == EVP_PKEY_RSA) {
+        const keymaster_rsa_sign_params_t* sign_params =
+            reinterpret_cast<const keymaster_rsa_sign_params_t*>(params);
+        return sign_rsa(pkey.get(), const_cast<keymaster_rsa_sign_params_t*>(sign_params), data,
+                        dataLength, signedData, signedDataLength);
+    } else {
+        ALOGW("Unsupported key type");
+        return -1;
+    }
+}
+
+static int verify_dsa(EVP_PKEY* pkey, keymaster_dsa_sign_params_t* sign_params,
+                      const uint8_t* signedData, const size_t signedDataLength,
+                      const uint8_t* signature, const size_t signatureLength) {
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
+    if (dsa.get() == NULL) {
+        logOpenSSLError("openssl_verify_dsa");
+        return -1;
+    }
+
+    if (DSA_verify(0, signedData, signedDataLength, signature, signatureLength, dsa.get()) <= 0) {
+        logOpenSSLError("openssl_verify_dsa");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int verify_ec(EVP_PKEY* pkey, keymaster_ec_sign_params_t* sign_params,
+                     const uint8_t* signedData, const size_t signedDataLength,
+                     const uint8_t* signature, const size_t signatureLength) {
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
+    if (eckey.get() == NULL) {
+        logOpenSSLError("openssl_verify_ec");
+        return -1;
+    }
+
+    if (ECDSA_verify(0, signedData, signedDataLength, signature, signatureLength, eckey.get()) <=
+        0) {
+        logOpenSSLError("openssl_verify_ec");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int verify_rsa(EVP_PKEY* pkey, keymaster_rsa_sign_params_t* sign_params,
+                      const uint8_t* signedData, const size_t signedDataLength,
+                      const uint8_t* signature, const size_t signatureLength) {
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    } else if (sign_params->padding_type != PADDING_NONE) {
+        ALOGW("Cannot handle padding type %d", sign_params->padding_type);
+        return -1;
+    } else if (signatureLength != signedDataLength) {
+        ALOGW("signed data length must be signature length");
+        return -1;
+    }
+
+    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
+    if (rsa.get() == NULL) {
+        logOpenSSLError("openssl_verify_data");
+        return -1;
+    }
+
+    UniquePtr<uint8_t[]> dataPtr(new uint8_t[signedDataLength]);
+    if (dataPtr.get() == NULL) {
+        logOpenSSLError("openssl_verify_data");
+        return -1;
+    }
+
+    unsigned char* tmp = reinterpret_cast<unsigned char*>(dataPtr.get());
+    if (!RSA_public_decrypt(signatureLength, signature, tmp, rsa.get(), RSA_NO_PADDING)) {
+        logOpenSSLError("openssl_verify_data");
+        return -1;
+    }
+
+    int result = 0;
+    for (size_t i = 0; i < signedDataLength; i++) {
+        result |= tmp[i] ^ signedData[i];
+    }
+
+    return result == 0 ? 0 : -1;
+}
+
+__attribute__((visibility("default"))) int openssl_verify_data(
+    const keymaster0_device_t*, 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 (signedData == NULL || signature == NULL) {
+        ALOGW("data or signature buffers == NULL");
+        return -1;
+    }
+
+    Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
+    if (pkey.get() == NULL) {
+        return -1;
+    }
+
+    int type = EVP_PKEY_type(pkey->type);
+    if (type == EVP_PKEY_DSA) {
+        const keymaster_dsa_sign_params_t* sign_params =
+            reinterpret_cast<const keymaster_dsa_sign_params_t*>(params);
+        return verify_dsa(pkey.get(), const_cast<keymaster_dsa_sign_params_t*>(sign_params),
+                          signedData, signedDataLength, signature, signatureLength);
+    } else if (type == EVP_PKEY_RSA) {
+        const keymaster_rsa_sign_params_t* sign_params =
+            reinterpret_cast<const keymaster_rsa_sign_params_t*>(params);
+        return verify_rsa(pkey.get(), const_cast<keymaster_rsa_sign_params_t*>(sign_params),
+                          signedData, signedDataLength, signature, signatureLength);
+    } else if (type == EVP_PKEY_EC) {
+        const keymaster_ec_sign_params_t* sign_params =
+            reinterpret_cast<const keymaster_ec_sign_params_t*>(params);
+        return verify_ec(pkey.get(), const_cast<keymaster_ec_sign_params_t*>(sign_params),
+                         signedData, signedDataLength, signature, signatureLength);
+    } else {
+        ALOGW("Unsupported key type %d", type);
+        return -1;
+    }
+}
+
+/* Close an opened OpenSSL instance */
+static int openssl_close(hw_device_t* dev) {
+    delete dev;
+    return 0;
+}
+
+/*
+ * Generic device handling
+ */
+__attribute__((visibility("default"))) int openssl_open(const hw_module_t* module, const char* name,
+                                                        hw_device_t** device) {
+    if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
+        return -EINVAL;
+
+    Unique_keymaster_device_t dev(new keymaster0_device_t);
+    if (dev.get() == NULL)
+        return -ENOMEM;
+
+    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_SOFTWARE_ONLY | 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;
+
+    ERR_load_crypto_strings();
+    ERR_load_BIO_strings();
+
+    *device = reinterpret_cast<hw_device_t*>(dev.release());
+
+    return 0;
+}
+
+static struct hw_module_methods_t keystore_module_methods = {
+    .open = openssl_open,
+};
+
+struct keystore_module softkeymaster_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/security/softkeymaster/module.cpp b/security/softkeymaster/module.cpp
new file mode 100644
index 0000000..0dcbadd
--- /dev/null
+++ b/security/softkeymaster/module.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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 <keymaster/softkeymaster.h>
+
+#include <keystore/keystore.h>
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster0.h>
+
+struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
+    = softkeymaster_module;