Merge "Update BoringSSL structs in keystore-engine."
am: 975e1aae69

Change-Id: I4cd2a30d7281476eb30083dc04187784f8dad445
diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk
index b4ba269..8988857 100644
--- a/keystore-engine/Android.mk
+++ b/keystore-engine/Android.mk
@@ -19,19 +19,48 @@
 LOCAL_MODULE := libkeystore-engine
 
 LOCAL_SRC_FILES := \
-	android_engine.cpp
+	android_engine.cpp \
+	keystore_backend_binder.cpp
 
 LOCAL_MODULE_TAGS := optional
 LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror
 
 LOCAL_SHARED_LIBRARIES += \
-	libcrypto \
-	liblog \
-	libcutils \
-	libutils \
 	libbinder \
-	libkeystore_binder
+	libcrypto \
+	libcutils \
+	libhidlbase \
+	libkeystore_binder \
+	liblog \
+	libutils
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+# This builds a variant of libkeystore-engine that uses a HIDL HAL
+# owned by the WiFi user to perform signing operations.
+LOCAL_MODULE := libkeystore-engine-wifi-hidl
+
+LOCAL_SRC_FILES := \
+	android_engine.cpp \
+	keystore_backend_hidl.cpp
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror -DBACKEND_WIFI_HIDL
+
+LOCAL_SHARED_LIBRARIES += \
+	android.system.wifi.keystore@1.0 \
+	libcrypto \
+	liblog \
+	libhidlbase \
+	libhidltransport \
+	libcutils \
+	libutils
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_VENDOR_MODULE := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
index dfa714e..d4d1e84 100644
--- a/keystore-engine/android_engine.cpp
+++ b/keystore-engine/android_engine.cpp
@@ -20,13 +20,17 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
+#define LOG_TAG "keystore-engine"
 #include <UniquePtr.h>
 
+#include <pthread.h>
 #include <sys/socket.h>
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <cutils/log.h>
+
 #include <openssl/bn.h>
 #include <openssl/ec.h>
 #include <openssl/ec_key.h>
@@ -36,14 +40,13 @@
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
 
-#include <binder/IServiceManager.h>
-#include <keystore/keystore.h>
-#include <keystore/IKeystoreService.h>
-
-using namespace android;
+#ifndef BACKEND_WIFI_HIDL
+#include "keystore_backend_binder.h"
+#else
+#include "keystore_backend_hidl.h"
+#endif
 
 namespace {
-
 extern const RSA_METHOD keystore_rsa_method;
 extern const ECDSA_METHOD keystore_ecdsa_method;
 
@@ -107,11 +110,17 @@
 
 pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
 KeystoreEngine *g_keystore_engine;
+KeystoreBackend *g_keystore_backend;
 
 /* 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;
+#ifndef BACKEND_WIFI_HIDL
+    g_keystore_backend = new KeystoreBackendBinder;
+#else
+    g_keystore_backend = new KeystoreBackendHidl;
+#endif
 }
 
 /* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
@@ -139,33 +148,25 @@
 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);
 
+    ensure_keystore_engine();
+
     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);
+    int32_t ret = g_keystore_backend->sign(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) {
+    } else if (reply_len == 0 || reply == NULL) {
         ALOGW("No valid signature returned");
-        free(reply);
         return 0;
     }
 
@@ -174,20 +175,20 @@
          * 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);
+        ALOGW("Reply len %zu greater than expected %zu", reply_len, len);
+        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. */
+        ALOGW("Reply len %zu lesser than expected %zu", reply_len, len);
         memset(out, 0, len);
-        memcpy(out + len - reply_len, reply, reply_len);
+        memcpy(out + len - reply_len, &reply[0], reply_len);
     } else {
-        memcpy(out, reply, len);
+        memcpy(out, &reply[0], len);
     }
 
-    free(reply);
-
     ALOGV("rsa=%p keystore_rsa_priv_dec successful", rsa);
     return 1;
 }
@@ -227,44 +228,33 @@
                       unsigned int* sig_len, EC_KEY* ec_key) {
     ALOGV("ecdsa_sign(%p, %u, %p)", digest, (unsigned) digest_len, ec_key);
 
+    ensure_keystore_engine();
+
     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);
+    int32_t ret = g_keystore_backend->sign(
+            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) {
+    } else if (reply_len == 0 || reply == NULL) {
         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);
+    // Reviewer: should't sig_len be checked here? Or is it just assumed that it is at least ecdsa_size?
+    memcpy(sig, &reply[0], reply_len);
     *sig_len = reply_len;
 
     ALOGV("ecdsa_sign(%p, %u, %p) => success", digest, (unsigned)digest_len,
@@ -391,36 +381,26 @@
 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;
-    }
+    ensure_keystore_engine();
 
     uint8_t *pubkey = NULL;
     size_t pubkey_len;
-    int32_t ret = service->get_pubkey(String16(key_id), &pubkey, &pubkey_len);
+    int32_t ret = g_keystore_backend->get_pubkey(key_id, &pubkey, &pubkey_len);
     if (ret < 0) {
         ALOGW("could not contact keystore");
         return NULL;
-    } else if (ret != 0) {
+    } else if (ret != 0 || pubkey == NULL) {
         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: {
diff --git a/keystore-engine/keystore_backend.h b/keystore-engine/keystore_backend.h
new file mode 100644
index 0000000..88c94b3
--- /dev/null
+++ b/keystore-engine/keystore_backend.h
@@ -0,0 +1,37 @@
+/* Copyright 2017 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. */
+
+#ifndef ANDROID_KEYSTORE_BACKEND_H
+#define ANDROID_KEYSTORE_BACKEND_H
+
+#include <stdint.h>
+
+class KeystoreBackend {
+  public:
+    virtual ~KeystoreBackend() {}
+    virtual int32_t sign(const char *key_id, const uint8_t* in, size_t len,
+                         uint8_t** reply, size_t* reply_len) = 0;
+    virtual int32_t get_pubkey(const char *key_id, uint8_t** pubkey,
+                               size_t* reply_len) = 0;
+};
+
+#endif  // ANDROID_KEYSTORE_BACKEND_H
diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp
new file mode 100644
index 0000000..dce8242
--- /dev/null
+++ b/keystore-engine/keystore_backend_binder.cpp
@@ -0,0 +1,82 @@
+/* Copyright 2017 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 "keystore_backend_binder.h"
+
+#include <binder/IServiceManager.h>
+#include <keystore/keystore.h>
+#include <keystore/IKeystoreService.h>
+#include <keystore/keystore_hidl_support.h>
+
+using namespace android;
+using keystore::blob2hidlVec;
+using keystore::hidl_vec;
+
+namespace {
+const char keystore_service_name[] = "android.security.keystore";
+};
+
+int32_t KeystoreBackendBinder::sign(
+        const char *key_id, const uint8_t* in, size_t len, uint8_t** reply,
+        size_t* reply_len) {
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16(keystore_service_name));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return -1;
+    }
+
+    auto inBlob = blob2hidlVec(in ,len);
+    hidl_vec<uint8_t> reply_vec;
+    auto ret = service->sign(String16(key_id), inBlob, &reply_vec);
+    if (!ret.isOk()) {
+        return -1;
+    }
+
+    *reply = reply_vec.releaseData();
+    *reply_len = reply_vec.size();
+    return 0;
+}
+
+int32_t KeystoreBackendBinder::get_pubkey(
+        const char *key_id, uint8_t** pubkey, size_t* pubkey_len) {
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16(keystore_service_name));
+    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+
+    if (service == NULL) {
+        ALOGE("could not contact keystore");
+        return -1;
+    }
+
+    hidl_vec<uint8_t> pubkey_vec;
+    auto ret = service->get_pubkey(String16(key_id), &pubkey_vec);
+    if (!ret.isOk()) {
+        return -1;
+    }
+
+    *pubkey = pubkey_vec.releaseData();
+    *pubkey_len = pubkey_vec.size();
+    return 0;
+}
diff --git a/keystore-engine/keystore_backend_binder.h b/keystore-engine/keystore_backend_binder.h
new file mode 100644
index 0000000..1db90f7
--- /dev/null
+++ b/keystore-engine/keystore_backend_binder.h
@@ -0,0 +1,38 @@
+/* Copyright 2017 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. */
+
+#ifndef ANDROID_KEYSTORE_BACKEND_BINDER_H
+#define ANDROID_KEYSTORE_BACKEND_BINDER_H
+
+#include "keystore_backend.h"
+
+class KeystoreBackendBinder : public KeystoreBackend {
+  public:
+    KeystoreBackendBinder() {}
+    virtual ~KeystoreBackendBinder() {}
+    int32_t sign(const char *key_id, const uint8_t* in, size_t len,
+                 uint8_t** reply, size_t* reply_len) override;
+    int32_t get_pubkey(const char *key_id, uint8_t** pubkey,
+                     size_t* reply_len) override;
+};
+
+#endif  // ANDROID_KEYSTORE_BACKEND_BINDER_H
diff --git a/keystore-engine/keystore_backend_hidl.cpp b/keystore-engine/keystore_backend_hidl.cpp
new file mode 100644
index 0000000..9a84e67
--- /dev/null
+++ b/keystore-engine/keystore_backend_hidl.cpp
@@ -0,0 +1,91 @@
+/* Copyright 2017 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 "keystore_backend_hidl.h"
+
+#include <android/system/wifi/keystore/1.0/IKeystore.h>
+#include <log/log.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::sp;
+using android::system::wifi::keystore::V1_0::IKeystore;
+
+int32_t KeystoreBackendHidl::sign(
+        const char *key_id, const uint8_t* in, size_t len, uint8_t** reply,
+        size_t* reply_len) {
+    if (key_id == NULL || in == NULL || reply == NULL || reply_len == NULL) {
+        ALOGE("Null pointer argument passed");
+        return -1;
+    }
+
+    sp<IKeystore> service = IKeystore::tryGetService();
+    if (service == NULL) {
+        ALOGE("could not contact keystore HAL");
+        return -1;
+    }
+
+    bool success = false;
+    auto cb = [&](IKeystore::KeystoreStatusCode status,
+                  hidl_vec<uint8_t> signedData) {
+      if (status == IKeystore::KeystoreStatusCode::SUCCESS) {
+          *reply_len = signedData.size();
+          *reply = signedData.releaseData();
+          success = true;
+      }
+    };
+    Return<void> ret = service->sign(
+        key_id, std::vector<uint8_t>(in, in + len), cb);
+    if (!ret.isOk() || !success) {
+        return 1;
+    }
+    return 0;
+}
+
+int32_t KeystoreBackendHidl::get_pubkey(
+        const char *key_id, uint8_t** pubkey, size_t* pubkey_len) {
+    if (key_id == NULL || pubkey == NULL || pubkey_len == NULL) {
+        ALOGE("Null pointer argument passed");
+        return -1;
+    }
+
+    sp<IKeystore> service = IKeystore::tryGetService();
+    if (service == NULL) {
+        ALOGE("could not contact keystore HAL");
+        return -1;
+    }
+
+    bool success = false;
+    auto cb = [&](IKeystore::KeystoreStatusCode status,
+                  hidl_vec<uint8_t> publicKey) {
+      if (status == IKeystore::KeystoreStatusCode::SUCCESS) {
+          *pubkey_len = publicKey.size();
+          *pubkey = publicKey.releaseData();
+          success = true;
+      }
+    };
+    Return<void> ret = service->getPublicKey(key_id, cb);
+    if (!ret.isOk() || !success) {
+        return 1;
+    }
+    return 0;
+}
diff --git a/keystore-engine/keystore_backend_hidl.h b/keystore-engine/keystore_backend_hidl.h
new file mode 100644
index 0000000..fd38f69
--- /dev/null
+++ b/keystore-engine/keystore_backend_hidl.h
@@ -0,0 +1,38 @@
+/* Copyright 2017 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. */
+
+#ifndef ANDROID_KEYSTORE_BACKEND_HIDL_H
+#define ANDROID_KEYSTORE_BACKEND_HIDL_H
+
+#include "keystore_backend.h"
+
+class KeystoreBackendHidl : public KeystoreBackend {
+  public:
+    KeystoreBackendHidl() {}
+    virtual ~KeystoreBackendHidl() {}
+    int32_t sign(const char *key_id, const uint8_t* in, size_t len,
+                 uint8_t** reply, size_t* reply_len) override;
+    int32_t get_pubkey(const char *key_id, uint8_t** pubkey,
+                     size_t* reply_len) override;
+};
+
+#endif  // ANDROID_KEYSTORE_BACKEND_HIDL_H
diff --git a/keystore/.clang-format b/keystore/.clang-format
index 5747e19..b0dc94c 100644
--- a/keystore/.clang-format
+++ b/keystore/.clang-format
@@ -3,7 +3,7 @@
 UseTab: Never
 BreakBeforeBraces: Attach
 AllowShortFunctionsOnASingleLine: Inline
-AllowShortIfStatementsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: true
 IndentCaseLabels: false
 ColumnLimit: 100
 PointerBindsToType: true
diff --git a/keystore/Android.mk b/keystore/Android.mk
index f17d5eb..f87675d 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -22,6 +22,7 @@
 $(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
 endef
 
+ifneq ($(TARGET_BUILD_PDK),true)
 include $(CLEAR_VARS)
 ifeq ($(USE_32_BIT_KEYSTORE), true)
 LOCAL_MULTILIB := 32
@@ -32,18 +33,23 @@
 	blob.cpp \
 	entropy.cpp \
 	key_store_service.cpp \
+	keystore_attestation_id.cpp \
 	keyblob_utils.cpp \
 	keystore.cpp \
 	keystore_main.cpp \
 	keystore_utils.cpp \
+	legacy_keymaster_device_wrapper.cpp \
+	keymaster_enforcement.cpp \
 	operation.cpp \
 	permissions.cpp \
-	user_state.cpp
+	user_state.cpp \
+	../../../frameworks/base/core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl
 LOCAL_SHARED_LIBRARIES := \
 	libbinder \
 	libcutils \
 	libcrypto \
 	libhardware \
+	libwifikeystorehal \
 	libkeystore_binder \
 	liblog \
 	libsoftkeymaster \
@@ -51,7 +57,13 @@
 	libselinux \
 	libsoftkeymasterdevice \
 	libkeymaster_messages \
-	libkeymaster1
+	libkeymaster1 \
+	libhwbinder \
+	libhidlbase \
+	libhidltransport \
+	android.hardware.keymaster@3.0 \
+	android.system.wifi.keystore@1.0
+LOCAL_HEADER_LIBRARIES := libbase_headers
 LOCAL_MODULE := keystore
 LOCAL_MODULE_TAGS := optional
 LOCAL_INIT_RC := keystore.rc
@@ -59,7 +71,9 @@
 LOCAL_CLANG := true
 LOCAL_SANITIZE := integer
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_AIDL_INCLUDES := frameworks/base/core/java/
 include $(BUILD_EXECUTABLE)
+endif
 
 include $(CLEAR_VARS)
 ifeq ($(USE_32_BIT_KEYSTORE), true)
@@ -67,7 +81,10 @@
 endif
 LOCAL_CFLAGS := -Wall -Wextra -Werror
 LOCAL_SRC_FILES := keystore_cli.cpp
-LOCAL_SHARED_LIBRARIES := libcutils libcrypto libkeystore_binder libutils liblog libbinder
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto libkeystore_binder libutils liblog libbinder \
+	libhwbinder \
+	libhidlbase \
+	android.hardware.keymaster@3.0
 LOCAL_MODULE := keystore_cli
 LOCAL_MODULE_TAGS := debug
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -81,8 +98,11 @@
 LOCAL_SRC_FILES := keystore_cli_v2.cpp
 LOCAL_SHARED_LIBRARIES := \
 	libchrome \
-	libkeymaster_messages \
-	libkeystore_binder
+	libkeystore_binder \
+	libhwbinder \
+	libhidlbase \
+	android.hardware.keymaster@3.0
+
 LOCAL_MODULE := keystore_cli_v2
 LOCAL_MODULE_TAGS := debug
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/gtest/include
@@ -97,28 +117,61 @@
 LOCAL_CFLAGS := -Wall -Wextra -Werror
 LOCAL_SRC_FILES := \
 	IKeystoreService.cpp \
+	KeyAttestationApplicationId.cpp \
+	KeyAttestationPackageInfo.cpp \
+	Signature.cpp \
 	keyblob_utils.cpp \
 	keystore_client.proto \
 	keystore_client_impl.cpp \
-	keystore_get.cpp
+	keystore_get.cpp \
+	authorization_set.cpp \
+	keystore_tags_utils.cpp \
+	keystore_aidl_hidl_marshalling_utils.cpp
 LOCAL_SHARED_LIBRARIES := \
 	libbinder \
-	libkeymaster_messages \
 	liblog \
 	libprotobuf-cpp-lite \
-	libsoftkeymasterdevice \
-	libutils
+	libutils \
+	libhwbinder \
+	libhidlbase \
+	android.hardware.keymaster@3.0
 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_EXPORT_SHARED_LIBRARY_HEADERS := libbinder \
+	libhwbinder \
+	libhidlbase \
+	android.hardware.keymaster@3.0
 LOCAL_CLANG := true
 LOCAL_SANITIZE := integer
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_SHARED_LIBRARY)
 
+# Library for keystore clients using the WiFi HIDL interface
+include $(CLEAR_VARS)
+LOCAL_CFLAGS := -Wall -Wextra -Werror
+LOCAL_SRC_FILES := \
+	keystore_get_wifi_hidl.cpp
+LOCAL_SHARED_LIBRARIES := \
+	android.system.wifi.keystore@1.0 \
+	libbase \
+	libhidlbase \
+	libhidltransport \
+	liblog \
+	libutils
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE := libkeystore-wifi-hidl
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_VENDOR_MODULE := true
+include $(BUILD_SHARED_LIBRARY)
+
 # Library for unit tests
 include $(CLEAR_VARS)
 ifeq ($(USE_32_BIT_KEYSTORE), true)
@@ -129,7 +182,12 @@
 LOCAL_MODULE := libkeystore_test
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_STATIC_LIBRARIES := libgtest_main
-LOCAL_SHARED_LIBRARIES := libkeymaster_messages
+LOCAL_SHARED_LIBRARIES := libkeymaster_messages \
+	libutils \
+	libhwbinder \
+	libhidlbase \
+	android.hardware.keymaster@3.0
+
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_STATIC_LIBRARY)
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index acd6968..344687b 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -19,28 +19,31 @@
 #include <sys/limits.h>
 #include <sys/types.h>
 
+#include <algorithm>
+#include <limits>
+
 #define LOG_TAG "KeystoreService"
 #include <utils/Log.h>
 
-#include <binder/Parcel.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
 
 #include <keystore/IKeystoreService.h>
+#include <keystore/keystore_hidl_support.h>
+
+#include "keystore_aidl_hidl_marshalling_utils.h"
 
 namespace android {
+using namespace ::keystore;
 
 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* data, size_t len) : mData(data), mSize(len) {}
 
-KeystoreArg::~KeystoreArg() {
-}
+KeystoreArg::~KeystoreArg() {}
 
-const void *KeystoreArg::data() const {
+const void* KeystoreArg::data() const {
     return mData;
 }
 
@@ -48,36 +51,18 @@
     return mSize;
 }
 
-OperationResult::OperationResult() : resultCode(0), token(), handle(0), inputConsumed(0),
-    data(NULL), dataLength(0) {
-}
+OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
 
-OperationResult::~OperationResult() {
-}
+OperationResult::~OperationResult() {}
 
 status_t OperationResult::readFromParcel(const Parcel* inn) {
     const Parcel& in = *inn;
-    resultCode = in.readInt32();
+    resultCode = ErrorCode(in.readInt32());
     token = in.readStrongBinder();
-    handle = static_cast<keymaster_operation_handle_t>(in.readInt64());
+    handle = static_cast<uint64_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);
+    data = readKeymasterBlob(in);
+    outParams = readParamSetFromParcel(in);
     return OK;
 }
 
@@ -86,322 +71,28 @@
     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);
+    writeKeymasterBlob(data, out);
+    writeParamSetToParcel(outParams, out);
     return OK;
 }
 
-ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
-}
+ExportResult::ExportResult() : resultCode() {}
 
-ExportResult::~ExportResult() {
-}
+ExportResult::~ExportResult() {}
 
 status_t ExportResult::readFromParcel(const Parcel* inn) {
     const Parcel& in = *inn;
-    resultCode = in.readInt32();
-    ssize_t length = in.readInt32();
-    dataLength = 0;
-    if (length > 0) {
-        const void* buf = in.readInplace(length);
-        if (buf) {
-            exportData.reset(reinterpret_cast<uint8_t*>(malloc(length)));
-            if (exportData.get()) {
-                memcpy(exportData.get(), buf, length);
-                dataLength = (size_t) length;
-            } else {
-                ALOGE("Failed to allocate ExportData buffer");
-            }
-        } else {
-            ALOGE("Failed to readInplace ExportData data");
-        }
-    }
+    resultCode = ErrorCode(in.readInt32());
+    exportData = readKeymasterBlob(in);
     return OK;
 }
 
 status_t ExportResult::writeToParcel(Parcel* out) const {
     out->writeInt32(resultCode);
-    out->writeInt32(dataLength);
-    if (exportData && dataLength) {
-        void* buf = out->writeInplace(dataLength);
-        if (buf) {
-            memcpy(buf, exportData.get(), dataLength);
-        } else {
-            ALOGE("Failed to writeInplace ExportResult data.");
-        }
-    }
+    writeKeymasterBlob(exportData, out);
     return OK;
 }
 
-KeymasterArguments::KeymasterArguments() {
-}
-
-KeymasterArguments::~KeymasterArguments() {
-    keymaster_free_param_values(params.data(), params.size());
-}
-
-void KeymasterArguments::readFromParcel(const Parcel& in) {
-    ssize_t length = in.readInt32();
-    size_t ulength = (size_t) length;
-    if (length < 0) {
-        ulength = 0;
-    }
-    keymaster_free_param_values(params.data(), params.size());
-    params.clear();
-    for(size_t i = 0; i < ulength; i++) {
-        keymaster_key_param_t param;
-        if (!readKeymasterArgumentFromParcel(in, &param)) {
-            ALOGE("Error reading keymaster argument from parcel");
-            break;
-        }
-        params.push_back(param);
-    }
-}
-
-void KeymasterArguments::writeToParcel(Parcel* out) const {
-    out->writeInt32(params.size());
-    for (auto param : params) {
-        out->writeInt32(1);
-        writeKeymasterArgumentToParcel(param, out);
-    }
-}
-
-KeyCharacteristics::KeyCharacteristics() {
-    memset((void*) &characteristics, 0, sizeof(characteristics));
-}
-
-KeyCharacteristics::~KeyCharacteristics() {
-    keymaster_free_characteristics(&characteristics);
-}
-
-status_t KeyCharacteristics::readFromParcel(const Parcel* inn) {
-    const Parcel& in = *inn;
-    size_t length = 0;
-    keymaster_key_param_t* params = readParamList(in, &length);
-    characteristics.sw_enforced.params = params;
-    characteristics.sw_enforced.length = length;
-
-    params = readParamList(in, &length);
-    characteristics.hw_enforced.params = params;
-    characteristics.hw_enforced.length = length;
-    return OK;
-}
-
-status_t KeyCharacteristics::writeToParcel(Parcel* out) const {
-    if (characteristics.sw_enforced.params) {
-        out->writeInt32(characteristics.sw_enforced.length);
-        for (size_t i = 0; i < characteristics.sw_enforced.length; i++) {
-            out->writeInt32(1);
-            writeKeymasterArgumentToParcel(characteristics.sw_enforced.params[i], out);
-        }
-    } else {
-        out->writeInt32(0);
-    }
-    if (characteristics.hw_enforced.params) {
-        out->writeInt32(characteristics.hw_enforced.length);
-        for (size_t i = 0; i < characteristics.hw_enforced.length; i++) {
-            out->writeInt32(1);
-            writeKeymasterArgumentToParcel(characteristics.hw_enforced.params[i], out);
-        }
-    } else {
-        out->writeInt32(0);
-    }
-    return OK;
-}
-
-KeymasterCertificateChain::KeymasterCertificateChain() {
-    memset(&chain, 0, sizeof(chain));
-}
-
-KeymasterCertificateChain::~KeymasterCertificateChain() {
-    keymaster_free_cert_chain(&chain);
-}
-
-static bool readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
-    if (in.readInt32() != 1) {
-        return false;
-    }
-
-    ssize_t length = in.readInt32();
-    if (length <= 0) {
-        return false;
-    }
-
-    blob->data = static_cast<const uint8_t*>(malloc(length));
-    if (!blob->data)
-        return false;
-
-    const void* buf = in.readInplace(length);
-    if (!buf)
-        return false;
-
-    blob->data_length = static_cast<size_t>(length);
-    memcpy(const_cast<uint8_t*>(blob->data), buf, length);
-
-    return true;
-}
-
-void KeymasterCertificateChain::readFromParcel(const Parcel& in) {
-    keymaster_free_cert_chain(&chain);
-
-    ssize_t count = in.readInt32();
-    size_t ucount = count;
-    if (count <= 0) {
-        return;
-    }
-
-    chain.entries = reinterpret_cast<keymaster_blob_t*>(malloc(sizeof(keymaster_blob_t) * ucount));
-    if (!chain.entries) {
-        ALOGE("Error allocating memory for certificate chain");
-        return;
-    }
-
-    memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount);
-    for (size_t i = 0; i < ucount; ++i) {
-        if (!readKeymasterBlob(in, &chain.entries[i])) {
-            ALOGE("Error reading certificate from parcel");
-            keymaster_free_cert_chain(&chain);
-            return;
-        }
-    }
-}
-
-void KeymasterCertificateChain::writeToParcel(Parcel* out) const {
-    out->writeInt32(chain.entry_count);
-    for (size_t i = 0; i < chain.entry_count; ++i) {
-        if (chain.entries[i].data) {
-            out->writeInt32(chain.entries[i].data_length);
-            void* buf = out->writeInplace(chain.entries[i].data_length);
-            if (buf) {
-                memcpy(buf, chain.entries[i].data, chain.entries[i].data_length);
-            } else {
-                ALOGE("Failed to writeInplace keymaster cert chain entry");
-            }
-        } else {
-            out->writeInt32(0); // Tell Java side this object is NULL.
-            ALOGE("Found NULL certificate chain entry");
-        }
-    }
-}
-
-void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out) {
-    switch (keymaster_tag_get_type(param.tag)) {
-        case KM_ENUM:
-        case KM_ENUM_REP: {
-            out->writeInt32(param.tag);
-            out->writeInt32(param.enumerated);
-            break;
-        }
-        case KM_UINT:
-        case KM_UINT_REP: {
-            out->writeInt32(param.tag);
-            out->writeInt32(param.integer);
-            break;
-        }
-        case KM_ULONG:
-        case KM_ULONG_REP: {
-            out->writeInt32(param.tag);
-            out->writeInt64(param.long_integer);
-            break;
-        }
-        case KM_DATE: {
-            out->writeInt32(param.tag);
-            out->writeInt64(param.date_time);
-            break;
-        }
-        case KM_BOOL: {
-            out->writeInt32(param.tag);
-            break;
-        }
-        case KM_BIGNUM:
-        case KM_BYTES: {
-            out->writeInt32(param.tag);
-            out->writeInt32(param.blob.data_length);
-            void* buf = out->writeInplace(param.blob.data_length);
-            if (buf) {
-                memcpy(buf, param.blob.data, param.blob.data_length);
-            } else {
-                ALOGE("Failed to writeInplace keymaster blob param");
-            }
-            break;
-        }
-        default: {
-            ALOGE("Failed to write argument: Unsupported keymaster_tag_t %d", param.tag);
-        }
-    }
-}
-
-
-bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out) {
-    if (in.readInt32() == 0) {
-        return false;
-    }
-    keymaster_tag_t tag = static_cast<keymaster_tag_t>(in.readInt32());
-    switch (keymaster_tag_get_type(tag)) {
-        case KM_ENUM:
-        case KM_ENUM_REP: {
-            uint32_t value = in.readInt32();
-            *out = keymaster_param_enum(tag, value);
-            break;
-        }
-        case KM_UINT:
-        case KM_UINT_REP: {
-            uint32_t value = in.readInt32();
-            *out = keymaster_param_int(tag, value);
-            break;
-        }
-        case KM_ULONG:
-        case KM_ULONG_REP: {
-            uint64_t value = in.readInt64();
-            *out = keymaster_param_long(tag, value);
-            break;
-        }
-        case KM_DATE: {
-            uint64_t value = in.readInt64();
-            *out = keymaster_param_date(tag, value);
-            break;
-        }
-        case KM_BOOL: {
-            *out = keymaster_param_bool(tag);
-            break;
-        }
-        case KM_BIGNUM:
-        case KM_BYTES: {
-            ssize_t length = in.readInt32();
-            uint8_t* data = NULL;
-            size_t ulength = 0;
-            if (length >= 0) {
-                ulength = (size_t) length;
-                // use malloc here so we can use keymaster_free_param_values
-                // consistently.
-                data = reinterpret_cast<uint8_t*>(malloc(ulength));
-                const void* buf = in.readInplace(ulength);
-                if (!buf || !data) {
-                    ALOGE("Failed to allocate buffer for keymaster blob param");
-                    free(data);
-                    return false;
-                }
-                memcpy(data, buf, ulength);
-            }
-            *out = keymaster_param_blob(tag, data, ulength);
-            break;
-        }
-        default: {
-            ALOGE("Unsupported keymaster_tag_t %d", tag);
-            return false;
-        }
-    }
-    return true;
-}
-
 /**
  * Read a byte array from in. The data at *data is still owned by the parcel
  */
@@ -420,77 +111,31 @@
     }
 }
 
-// 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)
-    {
-    }
+class BpKeystoreService : public BpInterface<IKeystoreService> {
+  public:
+    explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {}
 
     // test ping
-    virtual int32_t getState(int32_t userId)
-    {
+    KeyStoreServiceReturnCode getState(int32_t userId) override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("getState() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         return ret;
     }
 
-    virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength)
-    {
+    KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
+                                  hidl_vec<uint8_t>* item) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -498,58 +143,40 @@
         status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("get() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return 0;
+        auto resultItem = readBlobAsByteArray(reply);
+        if (item) *item = resultItem.value();
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
-            int32_t flags)
-    {
+    KeyStoreServiceReturnCode insert(const String16& name, const hidl_vec<uint8_t>& item, int uid,
+                                     int32_t flags) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(itemLength);
-        void* buf = data.writeInplace(itemLength);
-        memcpy(buf, item, itemLength);
+        writeBlobAsByteArray(item, &data);
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("import() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t del(const String16& name, int uid)
-    {
+    KeyStoreServiceReturnCode del(const String16& name, int uid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -557,19 +184,17 @@
         status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("del() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("del() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t exist(const String16& name, int uid)
-    {
+    KeyStoreServiceReturnCode exist(const String16& name, int uid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -577,19 +202,18 @@
         status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("exist() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("exist() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches)
-    {
+    KeyStoreServiceReturnCode list(const String16& prefix, int uid,
+                                   Vector<String16>* matches) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(prefix);
@@ -597,81 +221,74 @@
         status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("list() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t reset()
-    {
+    KeyStoreServiceReturnCode reset() override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("reset() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t onUserPasswordChanged(int32_t userId, const String16& password)
-    {
+    KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
+                                                    const String16& password) override {
         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);
+        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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onUserPasswordChanged() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t lock(int32_t userId)
-    {
+    KeyStoreServiceReturnCode lock(int32_t userId) override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("lock() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t unlock(int32_t userId, const String16& password)
-    {
+    KeyStoreServiceReturnCode unlock(int32_t userId, const String16& password) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeInt32(userId);
@@ -679,19 +296,17 @@
         status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("unlock() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("unlock() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual bool isEmpty(int32_t userId)
-    {
+    bool isEmpty(int32_t userId) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeInt32(userId);
@@ -701,17 +316,16 @@
             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;
+        return reply.readInt32() != 0;
     }
 
-    virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
-            int32_t flags, Vector<sp<KeystoreArg> >* args)
-    {
+    KeyStoreServiceReturnCode generate(const String16& name, int32_t uid, int32_t keyType,
+                                       int32_t keySize, int32_t flags,
+                                       Vector<sp<KeystoreArg>>* args) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -721,7 +335,7 @@
         data.writeInt32(flags);
         data.writeInt32(1);
         data.writeInt32(args->size());
-        for (Vector<sp<KeystoreArg> >::iterator it = args->begin(); it != args->end(); ++it) {
+        for (Vector<sp<KeystoreArg>>::iterator it = args->begin(); it != args->end(); ++it) {
             sp<KeystoreArg> item = *it;
             size_t keyLength = item->size();
             data.writeInt32(keyLength);
@@ -731,142 +345,104 @@
         status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("generate() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("generate() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength, int uid,
-            int flags)
-    {
+    KeyStoreServiceReturnCode import(const String16& name, const hidl_vec<uint8_t>& key, int uid,
+                                     int flags) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(keyLength);
-        void* buf = data.writeInplace(keyLength);
-        memcpy(buf, key, keyLength);
+        writeBlobAsByteArray(key, &data);
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("import() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out,
-            size_t* outLength)
-    {
+    KeyStoreServiceReturnCode sign(const String16& name, const hidl_vec<uint8_t>& in,
+                                   hidl_vec<uint8_t>* out) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(inLength);
-        void* buf = data.writeInplace(inLength);
-        memcpy(buf, in, inLength);
+        writeBlobAsByteArray(in, &data);
         status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("import() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return 0;
+        auto outBlob = readBlobAsByteArray(reply);
+        if (out) {
+            // don't need to check outBlob.isOk()
+            // if !outBlob.isOk() the wrapped value is default constructed and therefore empty,
+            // as expected.
+            *out = outBlob.value();
+        }
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength,
-            const uint8_t* signature, size_t signatureLength)
-    {
+    KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in,
+                                     const hidl_vec<uint8_t>& signature) override {
         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);
+        writeBlobAsByteArray(in, &data);
+        writeBlobAsByteArray(signature, &data);
         status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("verify() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("verify() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength)
-    {
+    KeyStoreServiceReturnCode get_pubkey(const String16& name, hidl_vec<uint8_t>* pubkey) override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return 0;
-     }
+        auto resultKey = readBlobAsByteArray(reply);
+        if (pubkey) *pubkey = resultKey.value();
+        return ResponseCode(reply.readInt32());
+    }
 
-    virtual int32_t grant(const String16& name, int32_t granteeUid)
-    {
+    KeyStoreServiceReturnCode grant(const String16& name, int32_t granteeUid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -874,19 +450,17 @@
         status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("grant() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("grant() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t ungrant(const String16& name, int32_t granteeUid)
-    {
+    KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -894,19 +468,17 @@
         status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("ungrant() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("ungrant() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    int64_t getmtime(const String16& name, int32_t uid)
-    {
+    int64_t getmtime(const String16& name, int32_t uid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -917,17 +489,15 @@
             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;
+        return reply.readInt64();
     }
 
-    virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-            int32_t destUid)
-    {
+    KeyStoreServiceReturnCode duplicate(const String16& srcKey, int32_t srcUid,
+                                        const String16& destKey, int32_t destUid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(srcKey);
@@ -937,19 +507,17 @@
         status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("duplicate() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("duplicate() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t is_hardware_backed(const String16& keyType)
-    {
+    int32_t is_hardware_backed(const String16& keyType) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(keyType);
@@ -959,151 +527,132 @@
             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;
+        return reply.readInt32();
     }
 
-    virtual int32_t clear_uid(int64_t uid)
-    {
+    KeyStoreServiceReturnCode clear_uid(int64_t uid) override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("clear_uid() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
-    {
+    KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeByteArray(bufLength, buf);
+        writeBlobAsByteArray(entropy, &data);
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("addRngEntropy() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     };
 
-    virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
-                                const uint8_t* entropy, size_t entropyLength, int uid, int flags,
-                                KeyCharacteristics* outCharacteristics)
-    {
+    KeyStoreServiceReturnCode generateKey(const String16& name,
+                                          const hidl_vec<KeyParameter>& params,
+                                          const hidl_vec<uint8_t>& entropy, int uid, int flags,
+                                          KeyCharacteristics* outCharacteristics) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(entropyLength, entropy);
+        nullable(writeParamSetToParcel, params, &data);
+        writeBlobAsByteArray(entropy, &data);
         data.writeInt32(uid);
         data.writeInt32(flags);
         status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("generateKey() could not contact remote: %d\n", status);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("generateKey() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (outCharacteristics) {
-            reply.readParcelable(outCharacteristics);
+            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
         }
         return ret;
     }
-    virtual int32_t getKeyCharacteristics(const String16& name,
-                                          const keymaster_blob_t* clientId,
-                                          const keymaster_blob_t* appData,
-                                          int32_t uid, KeyCharacteristics* outCharacteristics)
-    {
+    KeyStoreServiceReturnCode
+    getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
+                          const hidl_vec<uint8_t>& appData, int32_t uid,
+                          KeyCharacteristics* outCharacteristics) override {
         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);
-        }
+        writeBlobAsByteArray(clientId, &data);
+        writeBlobAsByteArray(appData, &data);
         data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
-                                             data, &reply);
+        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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("getKeyCharacteristics() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (outCharacteristics) {
-            reply.readParcelable(outCharacteristics);
+            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
         }
         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)
-    {
+    KeyStoreServiceReturnCode importKey(const String16& name, const hidl_vec<KeyParameter>& params,
+                                        KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid,
+                                        int flags,
+                                        KeyCharacteristics* outCharacteristics) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeInt32(format);
-        data.writeByteArray(keyLength, keyData);
+        nullable(writeParamSetToParcel, params, &data);
+        data.writeInt32(uint32_t(format));
+        writeBlobAsByteArray(keyData, &data);
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("importKey() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (outCharacteristics) {
-            reply.readParcelable(outCharacteristics);
+            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
         }
         return ret;
     }
 
-    virtual void exportKey(const String16& name, keymaster_key_format_t format,
-                           const keymaster_blob_t* clientId,
-                           const keymaster_blob_t* appData, int32_t uid, ExportResult* result)
-    {
+    void exportKey(const String16& name, KeyFormat format, const hidl_vec<uint8_t>& clientId,
+                   const hidl_vec<uint8_t>& appData, int32_t uid, ExportResult* result) override {
         if (!result) {
             return;
         }
@@ -1111,39 +660,29 @@
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(format);
-        if (clientId) {
-            data.writeByteArray(clientId->data_length, clientId->data);
-        } else {
-            data.writeInt32(-1);
-        }
-        if (appData) {
-            data.writeByteArray(appData->data_length, appData->data);
-        } else {
-            data.writeInt32(-1);
-        }
+        data.writeInt32(int32_t(format));
+        writeBlobAsByteArray(clientId, &data);
+        writeBlobAsByteArray(appData, &data);
         data.writeInt32(uid);
         status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("exportKey() could not contact remote: %d\n", status);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("exportKey() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    virtual void begin(const sp<IBinder>& appToken, const String16& name,
-                       keymaster_purpose_t purpose, bool pruneable,
-                       const KeymasterArguments& params, const uint8_t* entropy,
-                       size_t entropyLength, int32_t uid, OperationResult* result)
-    {
+    void begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
+               bool pruneable, const hidl_vec<KeyParameter>& params,
+               const hidl_vec<uint8_t>& entropy, int32_t uid, OperationResult* result) override {
         if (!result) {
             return;
         }
@@ -1151,147 +690,134 @@
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeStrongBinder(appToken);
         data.writeString16(name);
-        data.writeInt32(purpose);
+        data.writeInt32(int32_t(purpose));
         data.writeInt32(pruneable ? 1 : 0);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(entropyLength, entropy);
+        nullable(writeParamSetToParcel, params, &data);
+        writeBlobAsByteArray(entropy, &data);
         data.writeInt32(uid);
         status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("begin() could not contact remote: %d\n", status);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("begin() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
-                        const uint8_t* opData, size_t dataLength, OperationResult* result)
-    {
+    void update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+                const hidl_vec<uint8_t>& opData, OperationResult* result) override {
         if (!result) {
             return;
         }
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeStrongBinder(token);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(dataLength, opData);
+        nullable(writeParamSetToParcel, params, &data);
+        writeBlobAsByteArray(opData, &data);
         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;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("update() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
-                        const uint8_t* signature, size_t signatureLength,
-                        const uint8_t* entropy, size_t entropyLength,
-                        OperationResult* result)
-    {
+    void finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+                const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
+                OperationResult* result) override {
         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);
+        nullable(writeParamSetToParcel, params, &data);
+        writeBlobAsByteArray(signature, &data);
+        writeBlobAsByteArray(entropy, &data);
         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;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("finish() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    virtual int32_t abort(const sp<IBinder>& token)
-    {
+    KeyStoreServiceReturnCode abort(const sp<IBinder>& token) override {
         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;
+            return ResponseCode::SYSTEM_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 ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual bool isOperationAuthorized(const sp<IBinder>& token)
-    {
+    bool isOperationAuthorized(const sp<IBinder>& token) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeStrongBinder(token);
-        status_t status = remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data,
-                                             &reply);
+        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;
+        return reply.readInt32() == 1;
     }
 
-    virtual int32_t addAuthToken(const uint8_t* token, size_t length)
-    {
+    KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("addAuthToken() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     };
 
-    virtual int32_t onUserAdded(int32_t userId, int32_t parentId)
-    {
+    KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeInt32(userId);
@@ -1299,609 +825,537 @@
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onUserAdded() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t onUserRemoved(int32_t userId)
-    {
+    KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override {
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onUserRemoved() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
-                              KeymasterCertificateChain* outChain) {
-        if (!outChain)
-            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    KeyStoreServiceReturnCode attestKey(const String16& name, const hidl_vec<KeyParameter>& params,
+                                        hidl_vec<hidl_vec<uint8_t>>* outChain) override {
+        if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL;
 
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
-        data.writeInt32(1);  // params is not NULL.
-        params.writeToParcel(&data);
+        nullable(writeParamSetToParcel, params, &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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("attestKey() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (reply.readInt32() != 0) {
-            outChain->readFromParcel(reply);
+            *outChain = readCertificateChainFromParcel(reply);
         }
         return ret;
     }
 
-    virtual int32_t onDeviceOffBody()
-    {
+    KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params,
+                                              hidl_vec<hidl_vec<uint8_t>>* outChain) override {
+        if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL;
+
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        nullable(writeParamSetToParcel, params, &data);
+
+        status_t status = remote()->transact(BnKeystoreService::ATTEST_DEVICE_IDS, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("attestDeviceIds() count not contact remote: %d\n", status);
+            return ResponseCode::SYSTEM_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        ResponseCode ret = ResponseCode(reply.readInt32());
+        if (err < 0) {
+            ALOGD("attestDeviceIds() caught exception %d\n", err);
+            return ResponseCode::SYSTEM_ERROR;
+        }
+        if (reply.readInt32() != 0) {
+            *outChain = readCertificateChainFromParcel(reply);
+        }
+        return ret;
+    }
+
+    KeyStoreServiceReturnCode onDeviceOffBody() override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         status_t status = remote()->transact(BnKeystoreService::ON_DEVICE_OFF_BODY, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("onDeviceOffBody() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onDeviceOffBody() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
-
 };
 
 IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
 
 // ----------------------------------------------------------------------
 
-status_t BnKeystoreService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    switch(code) {
-        case GET_STATE: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            int32_t userId = data.readInt32();
-            int32_t ret = getState(userId);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case GET: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            int32_t uid = data.readInt32();
-            void* out = NULL;
-            size_t outSize = 0;
-            int32_t ret = get(name, uid, (uint8_t**) &out, &outSize);
-            reply->writeNoException();
-            if (ret == 1) {
-                reply->writeInt32(outSize);
-                void* buf = reply->writeInplace(outSize);
-                memcpy(buf, out, outSize);
-                free(out);
-            } else {
-                reply->writeInt32(-1);
+status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                       uint32_t flags) {
+    switch (code) {
+    case GET_STATE: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        int32_t userId = data.readInt32();
+        int32_t ret = getState(userId);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case GET: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        int32_t uid = data.readInt32();
+        hidl_vec<uint8_t> out;
+        auto ret = get(name, uid, &out);
+        reply->writeNoException();
+        if (ret.isOk()) {
+            writeBlobAsByteArray(out, reply);
+        } else {
+            reply->writeInt32(-1);
+        }
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case INSERT: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto in = readBlobAsByteArray(data);
+        int uid = data.readInt32();
+        int32_t flags = data.readInt32();
+        int32_t ret = insert(name, in.value(), 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;
             }
-            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);
-                        }
+            if (numArgs > 0) {
+                for (size_t i = 0; i < (size_t)numArgs; i++) {
+                    ssize_t inSize = data.readInt32();
+                    if (inSize >= 0 && (size_t)inSize <= data.dataAvail()) {
+                        sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize), inSize);
+                        args.push_back(arg);
+                    } else {
+                        args.push_back(NULL);
                     }
                 }
             }
-            int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case IMPORT: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            ssize_t inSize = data.readInt32();
-            const void* in;
-            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
-                in = data.readInplace(inSize);
-            } else {
-                in = NULL;
-                inSize = 0;
-            }
-            int uid = data.readInt32();
-            int32_t flags = data.readInt32();
-            int32_t ret = import(name, (const uint8_t*) in, (size_t) inSize, uid, flags);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case SIGN: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            ssize_t inSize = data.readInt32();
-            const void* in;
-            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
-                in = data.readInplace(inSize);
-            } else {
-                in = NULL;
-                inSize = 0;
-            }
-            void* out = NULL;
-            size_t outSize = 0;
-            int32_t ret = sign(name, (const uint8_t*) in, (size_t) inSize, (uint8_t**) &out, &outSize);
-            reply->writeNoException();
-            if (outSize > 0 && out != NULL) {
-                reply->writeInt32(outSize);
-                void* buf = reply->writeInplace(outSize);
-                memcpy(buf, out, outSize);
-                delete[] reinterpret_cast<uint8_t*>(out);
-            } else {
-                reply->writeInt32(-1);
-            }
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case VERIFY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            ssize_t inSize = data.readInt32();
-            const void* in;
-            if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
-                in = data.readInplace(inSize);
-            } else {
-                in = NULL;
-                inSize = 0;
-            }
-            ssize_t sigSize = data.readInt32();
-            const void* sig;
-            if (sigSize >= 0 && (size_t) sigSize <= data.dataAvail()) {
-                sig = data.readInplace(sigSize);
-            } else {
-                sig = NULL;
-                sigSize = 0;
-            }
-            bool ret = verify(name, (const uint8_t*) in, (size_t) inSize, (const uint8_t*) sig,
-                    (size_t) sigSize);
-            reply->writeNoException();
-            reply->writeInt32(ret ? 1 : 0);
-            return NO_ERROR;
-        } break;
-        case GET_PUBKEY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            void* out = NULL;
-            size_t outSize = 0;
-            int32_t ret = get_pubkey(name, (unsigned char**) &out, &outSize);
-            reply->writeNoException();
-            if (outSize > 0 && out != NULL) {
-                reply->writeInt32(outSize);
-                void* buf = reply->writeInplace(outSize);
-                memcpy(buf, out, outSize);
-                free(out);
-            } else {
-                reply->writeInt32(-1);
-            }
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case GRANT: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            int32_t granteeUid = data.readInt32();
-            int32_t ret = grant(name, granteeUid);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case UNGRANT: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            int32_t granteeUid = data.readInt32();
-            int32_t ret = ungrant(name, granteeUid);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case GETMTIME: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            int32_t uid = data.readInt32();
-            int64_t ret = getmtime(name, uid);
-            reply->writeNoException();
-            reply->writeInt64(ret);
-            return NO_ERROR;
-        } break;
-        case DUPLICATE: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 srcKey = data.readString16();
-            int32_t srcUid = data.readInt32();
-            String16 destKey = data.readString16();
-            int32_t destUid = data.readInt32();
-            int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        } break;
-        case IS_HARDWARE_BACKED: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 keyType = data.readString16();
-            int32_t ret = is_hardware_backed(keyType);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
         }
-        case CLEAR_UID: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            int64_t uid = data.readInt64();
-            int32_t ret = clear_uid(uid);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        }
-        case ADD_RNG_ENTROPY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            const uint8_t* bytes = NULL;
-            size_t size = 0;
-            readByteArray(data, &bytes, &size);
-            int32_t ret = addRngEntropy(bytes, size);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            return NO_ERROR;
-        }
-        case GENERATE_KEY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            KeymasterArguments args;
-            if (data.readInt32() != 0) {
-                args.readFromParcel(data);
-            }
-            const uint8_t* entropy = NULL;
-            size_t entropyLength = 0;
-            readByteArray(data, &entropy, &entropyLength);
-            int32_t uid = data.readInt32();
-            int32_t flags = data.readInt32();
-            KeyCharacteristics outCharacteristics;
-            int32_t ret = generateKey(name, args, entropy, entropyLength, uid, flags,
-                                      &outCharacteristics);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            reply->writeParcelable(outCharacteristics);
-            return NO_ERROR;
-        }
-        case GET_KEY_CHARACTERISTICS: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
-            std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
-            int32_t uid = data.readInt32();
-            KeyCharacteristics outCharacteristics;
-            int ret = getKeyCharacteristics(name, clientId.get(), appData.get(), uid,
-                                            &outCharacteristics);
-            if (clientId.get() && clientId->data) {
-                free(const_cast<void*>(static_cast<const void*>(clientId->data)));
-            }
-            if (appData.get() && appData->data) {
-                free(const_cast<void*>(static_cast<const void*>(appData->data)));
-            }
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            reply->writeParcelable(outCharacteristics);
-            return NO_ERROR;
-        }
-        case IMPORT_KEY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            KeymasterArguments args;
-            if (data.readInt32() != 0) {
-                args.readFromParcel(data);
-            }
-            keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
-            const uint8_t* keyData = NULL;
-            size_t keyLength = 0;
-            readByteArray(data, &keyData, &keyLength);
-            int32_t uid = data.readInt32();
-            int32_t flags = data.readInt32();
-            KeyCharacteristics outCharacteristics;
-            int32_t ret = importKey(name, args, format, keyData, keyLength, uid, flags,
-                                    &outCharacteristics);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            reply->writeParcelable(outCharacteristics);
-            return NO_ERROR;
-        }
-        case EXPORT_KEY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
-            std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
-            std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
-            int32_t uid = data.readInt32();
-            ExportResult result;
-            exportKey(name, format, clientId.get(), appData.get(), uid, &result);
-            if (clientId.get() && clientId->data) {
-                free(const_cast<void*>(static_cast<const void*>(clientId->data)));
-            }
-            if (appData.get() && appData->data) {
-                free(const_cast<void*>(static_cast<const void*>(appData->data)));
-            }
-            reply->writeNoException();
-            reply->writeParcelable(result);
+        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();
+        auto in = readBlobAsByteArray(data);
+        int uid = data.readInt32();
+        int32_t flags = data.readInt32();
+        auto ret = import(name, in.value(), uid, flags);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case SIGN: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto in = readBlobAsByteArray(data);
+        hidl_vec<uint8_t> out;
+        auto ret = sign(name, in.value(), &out);
+        reply->writeNoException();
+        writeBlobAsByteArray(out, reply);
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case VERIFY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto in = readBlobAsByteArray(data);
+        auto signature = readBlobAsByteArray(data);
+        auto ret = verify(name, in.value(), signature.value());
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case GET_PUBKEY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        hidl_vec<uint8_t> out;
+        auto ret = get_pubkey(name, &out);
+        reply->writeNoException();
+        writeBlobAsByteArray(out, reply);
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case GRANT: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        int32_t granteeUid = data.readInt32();
+        int32_t ret = grant(name, granteeUid);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case UNGRANT: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        int32_t granteeUid = data.readInt32();
+        int32_t ret = ungrant(name, granteeUid);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case GETMTIME: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        int32_t uid = data.readInt32();
+        int64_t ret = getmtime(name, uid);
+        reply->writeNoException();
+        reply->writeInt64(ret);
+        return NO_ERROR;
+    } break;
+    case DUPLICATE: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 srcKey = data.readString16();
+        int32_t srcUid = data.readInt32();
+        String16 destKey = data.readString16();
+        int32_t destUid = data.readInt32();
+        int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    } break;
+    case IS_HARDWARE_BACKED: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 keyType = data.readString16();
+        int32_t ret = is_hardware_backed(keyType);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    }
+    case CLEAR_UID: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        int64_t uid = data.readInt64();
+        int32_t ret = clear_uid(uid);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    }
+    case ADD_RNG_ENTROPY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        auto entropy = readBlobAsByteArray(data);
+        auto ret = addRngEntropy(entropy.value());
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        return NO_ERROR;
+    }
+    case GENERATE_KEY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto params = nullable(readParamSetFromParcel, data);
+        auto entropy = readBlobAsByteArray(data);
+        int32_t uid = data.readInt32();
+        int32_t flags = data.readInt32();
+        KeyCharacteristics outCharacteristics;
+        int32_t ret =
+            generateKey(name, params.value(), entropy.value(), uid, flags, &outCharacteristics);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
+        return NO_ERROR;
+    }
+    case GET_KEY_CHARACTERISTICS: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto clientId = nullable(readKeymasterBlob, data, true);
+        auto appData = nullable(readKeymasterBlob, data, true);
+        int32_t uid = data.readInt32();
+        KeyCharacteristics outCharacteristics;
+        int ret = getKeyCharacteristics(name, clientId.value(), appData.value(), uid,
+                                        &outCharacteristics);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
+        return NO_ERROR;
+    }
+    case IMPORT_KEY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto args = nullable(readParamSetFromParcel, data);
+        KeyFormat format = static_cast<KeyFormat>(data.readInt32());
+        auto keyData = readBlobAsByteArray(data);
+        int32_t uid = data.readInt32();
+        int32_t flags = data.readInt32();
+        KeyCharacteristics outCharacteristics;
+        int32_t ret =
+            importKey(name, args.value(), format, keyData.value(), uid, flags, &outCharacteristics);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
+        return NO_ERROR;
+    }
+    case EXPORT_KEY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        KeyFormat format = static_cast<KeyFormat>(data.readInt32());
+        auto clientId = nullable(readKeymasterBlob, data, true);
+        auto appData = nullable(readKeymasterBlob, data, true);
+        int32_t uid = data.readInt32();
+        ExportResult result;
+        exportKey(name, format, clientId.value(), appData.value(), uid, &result);
+        reply->writeNoException();
+        reply->writeParcelable(result);
 
-            return NO_ERROR;
-        }
-        case BEGIN: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            sp<IBinder> token = data.readStrongBinder();
-            String16 name = data.readString16();
-            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(data.readInt32());
-            bool pruneable = data.readInt32() != 0;
-            KeymasterArguments args;
-            if (data.readInt32() != 0) {
-                args.readFromParcel(data);
-            }
-            const uint8_t* entropy = NULL;
-            size_t entropyLength = 0;
-            readByteArray(data, &entropy, &entropyLength);
-            int32_t uid = data.readInt32();
-            OperationResult result;
-            begin(token, name, purpose, pruneable, args, entropy, entropyLength, uid, &result);
-            reply->writeNoException();
-            reply->writeParcelable(result);
+        return NO_ERROR;
+    }
+    case BEGIN: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        sp<IBinder> token = data.readStrongBinder();
+        String16 name = data.readString16();
+        KeyPurpose purpose = static_cast<KeyPurpose>(data.readInt32());
+        bool pruneable = data.readInt32() != 0;
+        auto args = nullable(readParamSetFromParcel, data);
+        auto entropy = readBlobAsByteArray(data);
+        int32_t uid = data.readInt32();
+        OperationResult result;
+        begin(token, name, purpose, pruneable, args.value(), entropy.value(), uid, &result);
+        reply->writeNoException();
+        reply->writeParcelable(result);
 
-            return NO_ERROR;
-        }
-        case UPDATE: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            sp<IBinder> token = data.readStrongBinder();
-            KeymasterArguments args;
-            if (data.readInt32() != 0) {
-                args.readFromParcel(data);
-            }
-            const uint8_t* buf = NULL;
-            size_t bufLength = 0;
-            readByteArray(data, &buf, &bufLength);
-            OperationResult result;
-            update(token, args, buf, bufLength, &result);
-            reply->writeNoException();
-            reply->writeParcelable(result);
+        return NO_ERROR;
+    }
+    case UPDATE: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        sp<IBinder> token = data.readStrongBinder();
+        auto args = nullable(readParamSetFromParcel, data);
+        auto buf = readBlobAsByteArray(data);
+        OperationResult result;
+        update(token, args.value(), buf.value(), &result);
+        reply->writeNoException();
+        reply->writeParcelable(result);
 
-            return NO_ERROR;
-        }
-        case FINISH: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            sp<IBinder> token = data.readStrongBinder();
-            KeymasterArguments args;
-            if (data.readInt32() != 0) {
-                args.readFromParcel(data);
-            }
-            const uint8_t* signature = NULL;
-            size_t signatureLength = 0;
-            readByteArray(data, &signature, &signatureLength);
-            const uint8_t* entropy = NULL;
-            size_t entropyLength = 0;
-            readByteArray(data, &entropy, &entropyLength);
-            OperationResult result;
-            finish(token, args, signature, signatureLength, entropy, entropyLength,  &result);
-            reply->writeNoException();
-            reply->writeParcelable(result);
+        return NO_ERROR;
+    }
+    case FINISH: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        sp<IBinder> token = data.readStrongBinder();
+        auto args = nullable(readParamSetFromParcel, data);
+        auto signature = readBlobAsByteArray(data);
+        auto entropy = readBlobAsByteArray(data);
+        OperationResult result;
+        finish(token, args.value(), signature.value(), entropy.value(), &result);
+        reply->writeNoException();
+        reply->writeParcelable(result);
 
-            return NO_ERROR;
-        }
-        case ABORT: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            sp<IBinder> token = data.readStrongBinder();
-            int32_t result = abort(token);
-            reply->writeNoException();
-            reply->writeInt32(result);
+        return NO_ERROR;
+    }
+    case 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 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 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_ADDED: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        int32_t userId = data.readInt32();
+        int32_t parentId = data.readInt32();
+        int32_t result = onUserAdded(userId, parentId);
+        reply->writeNoException();
+        reply->writeInt32(result);
 
-            return NO_ERROR;
-        }
-        case ON_USER_REMOVED: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            int32_t userId = data.readInt32();
-            int32_t result = onUserRemoved(userId);
-            reply->writeNoException();
-            reply->writeInt32(result);
+        return NO_ERROR;
+    }
+    case ON_USER_REMOVED: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        int32_t userId = data.readInt32();
+        int32_t result = onUserRemoved(userId);
+        reply->writeNoException();
+        reply->writeInt32(result);
 
-            return NO_ERROR;
-        }
-        case ATTEST_KEY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            String16 name = data.readString16();
-            KeymasterArguments params;
-            if (data.readInt32() != 0) {
-                params.readFromParcel(data);
-            }
-            KeymasterCertificateChain chain;
-            int ret = attestKey(name, params, &chain);
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            reply->writeInt32(1);
-            chain.writeToParcel(reply);
+        return NO_ERROR;
+    }
+    case ATTEST_KEY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        String16 name = data.readString16();
+        auto params = nullable(readParamSetFromParcel, data);
+        hidl_vec<hidl_vec<uint8_t>> chain;
+        int ret = attestKey(name, params.value(), &chain);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        nullable(writeCertificateChainToParcel, chain, reply);
 
-            return NO_ERROR;
-        }
-        case ON_DEVICE_OFF_BODY: {
-            CHECK_INTERFACE(IKeystoreService, data, reply);
-            int32_t ret = onDeviceOffBody();
-            reply->writeNoException();
-            reply->writeInt32(ret);
+        return NO_ERROR;
+    }
 
-            return NO_ERROR;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
+    case ATTEST_DEVICE_IDS: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        auto params = nullable(readParamSetFromParcel, data);
+        hidl_vec<hidl_vec<uint8_t>> chain;
+        int ret = attestDeviceIds(params.value(), &chain);
+        reply->writeNoException();
+        reply->writeInt32(ret);
+        nullable(writeCertificateChainToParcel, chain, reply);
+
+        return NO_ERROR;
+    }
+
+    case ON_DEVICE_OFF_BODY: {
+        CHECK_INTERFACE(IKeystoreService, data, reply);
+        int32_t ret = onDeviceOffBody();
+        reply->writeNoException();
+        reply->writeInt32(ret);
+
+        return NO_ERROR;
+    }
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
 // ----------------------------------------------------------------------------
 
-}; // namespace android
+};  // namespace android
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
new file mode 100644
index 0000000..1352124
--- /dev/null
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -0,0 +1,40 @@
+/*
+**
+** Copyright 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 "include/keystore/KeyAttestationApplicationId.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+status_t KeyAttestationApplicationId::writeToParcel(Parcel* parcel) const {
+    return parcel->writeParcelableVector(packageInfos_);
+}
+
+status_t KeyAttestationApplicationId::readFromParcel(const Parcel* parcel) {
+    std::unique_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> temp_vector;
+    auto rc = parcel->readParcelableVector(&temp_vector);
+    if (rc != NO_ERROR) return rc;
+    packageInfos_.reset(temp_vector.release());
+    return NO_ERROR;
+}
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
new file mode 100644
index 0000000..a84c246
--- /dev/null
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -0,0 +1,49 @@
+/*
+**
+** Copyright 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 "include/keystore/KeyAttestationPackageInfo.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
+    auto rc = parcel->writeString16(packageName_);
+    if (rc != NO_ERROR) return rc;
+    rc = parcel->writeInt32(versionCode_);
+    if (rc != NO_ERROR) return rc;
+    return parcel->writeParcelableVector(signatures_);
+}
+
+status_t KeyAttestationPackageInfo::readFromParcel(const Parcel* parcel) {
+    auto rc = parcel->readString16(&packageName_);
+    if (rc != NO_ERROR) return rc;
+    rc = parcel->readInt32(&versionCode_);
+    if (rc != NO_ERROR) return rc;
+
+    std::unique_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> temp_vector;
+    rc = parcel->readParcelableVector(&temp_vector);
+    if (rc != NO_ERROR) return rc;
+    signatures_.reset(temp_vector.release());
+    return NO_ERROR;
+}
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
diff --git a/keystore/Signature.cpp b/keystore/Signature.cpp
new file mode 100644
index 0000000..1566df9
--- /dev/null
+++ b/keystore/Signature.cpp
@@ -0,0 +1,36 @@
+/*
+**
+** Copyright 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 "include/keystore/Signature.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace content {
+namespace pm {
+
+status_t Signature::writeToParcel(Parcel* parcel) const {
+    return parcel->writeByteVector(sig_data_);
+}
+
+status_t Signature::readFromParcel(const Parcel* parcel) {
+    return parcel->readByteVector(&sig_data_);
+}
+
+}  // namespace pm
+}  // namespace content
+}  // namespace android
diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp
index f0f4981..3f476cd 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -21,10 +21,36 @@
 
 #include <algorithm>
 
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/logger.h>
+#include <cutils/log.h>
 
-namespace keymaster {
+namespace keystore {
+
+template <typename IntType, uint32_t byteOrder> struct choose_hton;
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
+    inline static IntType hton(const IntType& value) {
+        IntType result = 0;
+        const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
+        unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
+        for (int i = sizeof(IntType) - 1; i >= 0; --i) {
+            *(outbytes++) = inbytes[i];
+        }
+        return result;
+    }
+};
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
+    inline static IntType hton(const IntType& value) { return value; }
+};
+
+template <typename IntType> inline IntType hton(const IntType& value) {
+    return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
+
+template <typename IntType> inline IntType ntoh(const IntType& value) {
+    // same operation and hton
+    return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
 
 //
 // Some trivial template wrappers around std algorithms, so they take containers not ranges.
@@ -49,48 +75,43 @@
     return time.tv_sec;
 }
 
-void AuthTokenTable::AddAuthenticationToken(const hw_auth_token_t* auth_token) {
+void AuthTokenTable::AddAuthenticationToken(const HardwareAuthToken* 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);
+        ALOGW("Auth token table filled up; replacing oldest entry");
         *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))
+inline bool is_secret_key_operation(Algorithm algorithm, KeyPurpose purpose) {
+    if ((algorithm != Algorithm::RSA && algorithm != Algorithm::EC))
         return true;
-    if (purpose == KM_PURPOSE_SIGN || purpose == KM_PURPOSE_DECRYPT)
+    if (purpose == KeyPurpose::SIGN || purpose == KeyPurpose::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 KeyRequiresAuthentication(const AuthorizationSet& key_info, KeyPurpose purpose) {
+    auto algorithm = defaultOr(key_info.GetTagValue(TAG_ALGORITHM), Algorithm::AES);
+    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;
+inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info, KeyPurpose purpose) {
+    auto algorithm = defaultOr(key_info.GetTagValue(TAG_ALGORITHM), Algorithm::AES);
+    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;
+                                                        KeyPurpose purpose, uint64_t op_handle,
+                                                        const HardwareAuthToken** 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);
+    auto auth_type =
+        defaultOr(key_info.GetTagValue(TAG_USER_AUTH_TYPE), HardwareAuthenticatorType::NONE);
 
     std::vector<uint64_t> key_sids;
     ExtractSids(key_info, &key_sids);
@@ -101,44 +122,41 @@
         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;
+AuthTokenTable::Error
+AuthTokenTable::FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
+                                           HardwareAuthenticatorType auth_type, uint64_t op_handle,
+                                           const HardwareAuthToken** 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 == entries_.end()) return AUTH_TOKEN_NOT_FOUND;
 
-    if (!matching_op->SatisfiesAuth(sids, auth_type))
-        return AUTH_TOKEN_WRONG_SID;
+    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,
+                                                             HardwareAuthenticatorType auth_type,
                                                              const AuthorizationSet& key_info,
-                                                             const hw_auth_token_t** found) {
+                                                             const HardwareAuthToken** 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;
+    if (!newest_match) return AUTH_TOKEN_NOT_FOUND;
 
-    uint32_t timeout;
-    key_info.GetTagValue(TAG_AUTH_TIMEOUT, &timeout);
+    auto timeout = defaultOr(key_info.GetTagValue(TAG_AUTH_TIMEOUT), 0);
+
     time_t now = clock_function_();
     if (static_cast<int64_t>(newest_match->time_received()) + timeout < static_cast<int64_t>(now))
         return AUTH_TOKEN_EXPIRED;
 
-    if (key_info.GetTagValue(TAG_ALLOW_WHILE_ON_BODY)) {
+    if (key_info.GetTagValue(TAG_ALLOW_WHILE_ON_BODY).isOk()) {
         if (static_cast<int64_t>(newest_match->time_received()) <
             static_cast<int64_t>(last_off_body_)) {
             return AUTH_TOKEN_EXPIRED;
@@ -153,8 +171,8 @@
 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);
+        if (param.tag == Tag::USER_SECURE_ID)
+            sids->push_back(authorizationValue(TAG_USER_SECURE_ID, param).value());
 }
 
 void AuthTokenTable::RemoveEntriesSupersededBy(const Entry& entry) {
@@ -175,38 +193,35 @@
                        [&](Entry& e) { return e.Supersedes(entry); });
 }
 
-void AuthTokenTable::MarkCompleted(const keymaster_operation_handle_t op_handle) {
+void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
     auto found = find_if(entries_, [&](Entry& e) { return e.token()->challenge == op_handle; });
-    if (found == entries_.end())
-        return;
+    if (found == entries_.end()) return;
 
     assert(!IsSupersededBySomeEntry(*found));
     found->mark_completed();
 
-    if (IsSupersededBySomeEntry(*found))
-        entries_.erase(found);
+    if (IsSupersededBySomeEntry(*found)) entries_.erase(found);
 }
 
-AuthTokenTable::Entry::Entry(const hw_auth_token_t* token, time_t current_time)
+AuthTokenTable::Entry::Entry(const HardwareAuthToken* token, time_t current_time)
     : token_(token), time_received_(current_time), last_use_(current_time),
-      operation_completed_(token_->challenge == 0) {
-}
+      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)));
+HardwareAuthenticatorType AuthTokenTable::Entry::authenticator_type() const {
+    HardwareAuthenticatorType result = static_cast<HardwareAuthenticatorType>(
+        ntoh(static_cast<uint32_t>(token_->authenticatorType)));
     return result;
 }
 
 bool AuthTokenTable::Entry::SatisfiesAuth(const std::vector<uint64_t>& sids,
-                                          hw_authenticator_type_t auth_type) {
+                                          HardwareAuthenticatorType auth_type) {
     for (auto sid : sids)
-        if ((sid == token_->authenticator_id) ||
-            (sid == token_->user_id && (auth_type & authenticator_type()) != 0))
+        if ((sid == token_->authenticatorId) ||
+            (sid == token_->userId && (auth_type & authenticator_type()) != 0))
             return true;
     return false;
 }
@@ -216,12 +231,11 @@
 }
 
 bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const {
-    if (!entry.completed())
-        return false;
+    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 &&
+    return (token_->userId == entry.token_->userId &&
+            token_->authenticatorType == entry.token_->authenticatorType &&
+            token_->authenticatorType == entry.token_->authenticatorType &&
             timestamp_host_order() > entry.timestamp_host_order());
 }
 
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index 4d54a39..6f7aab1 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -18,12 +18,14 @@
 #include <vector>
 
 #include <hardware/hw_auth_token.h>
-#include <keymaster/authorization_set.h>
+#include <keystore/authorization_set.h>
 
 #ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
 #define KEYSTORE_AUTH_TOKEN_TABLE_H_
 
-namespace keymaster {
+namespace keystore {
+
+using android::hardware::keymaster::V3_0::HardwareAuthToken;
 
 namespace test {
 class AuthTokenTableTest;
@@ -42,7 +44,8 @@
 class AuthTokenTable {
   public:
     explicit AuthTokenTable(size_t max_entries = 32, time_t (*clock_function)() = clock_gettime_raw)
-        : max_entries_(max_entries), last_off_body_(clock_function()), clock_function_(clock_function) {}
+        : max_entries_(max_entries), last_off_body_(clock_function()),
+          clock_function_(clock_function) {}
 
     enum Error {
         OK,
@@ -58,7 +61,7 @@
     /**
      * Add an authorization token to the table.  The table takes ownership of the argument.
      */
-    void AddAuthenticationToken(const hw_auth_token_t* token);
+    void AddAuthenticationToken(const HardwareAuthToken* token);
 
     /**
      * Find an authorization token that authorizes the operation specified by \p operation_handle on
@@ -70,30 +73,14 @@
      *
      * 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);
-    }
+    Error FindAuthorization(const AuthorizationSet& key_info, KeyPurpose purpose,
+                            uint64_t op_handle, const HardwareAuthToken** 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 MarkCompleted(const uint64_t op_handle);
 
     /**
      * Update the last_off_body_ timestamp so that tokens which remain authorized only so long as
@@ -110,7 +97,7 @@
 
     class Entry {
       public:
-        Entry(const hw_auth_token_t* token, time_t current_time);
+        Entry(const HardwareAuthToken* token, time_t current_time);
         Entry(Entry&& entry) { *this = std::move(entry); }
 
         void operator=(Entry&& rhs) {
@@ -125,36 +112,34 @@
         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 SatisfiesAuth(const std::vector<uint64_t>& sids, HardwareAuthenticatorType auth_type);
 
         bool is_newer_than(const Entry* entry) {
-            if (!entry)
-                return true;
+            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(); }
+        const HardwareAuthToken* 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;
+        HardwareAuthenticatorType authenticator_type() const;
 
       private:
-        std::unique_ptr<const hw_auth_token_t> token_;
+        std::unique_ptr<const HardwareAuthToken> 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);
+                                     HardwareAuthenticatorType auth_type, uint64_t op_handle,
+                                     const HardwareAuthToken** 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);
+                                 HardwareAuthenticatorType auth_type,
+                                 const AuthorizationSet& key_info, const HardwareAuthToken** found);
     void ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids);
     void RemoveEntriesSupersededBy(const Entry& entry);
     bool IsSupersededBySomeEntry(const Entry& entry);
diff --git a/keystore/authorization_set.cpp b/keystore/authorization_set.cpp
new file mode 100644
index 0000000..e30b32d
--- /dev/null
+++ b/keystore/authorization_set.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <keystore/authorization_set.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits>
+#include <ostream>
+#include <istream>
+
+#include <new>
+
+namespace keystore {
+
+inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) return a.tag < b.tag;
+    int retval;
+    switch (typeFromTag(a.tag)) {
+    case TagType::INVALID:
+    case TagType::BOOL:
+        return false;
+    case TagType::ENUM:
+    case TagType::ENUM_REP:
+    case TagType::UINT:
+    case TagType::UINT_REP:
+        return a.f.integer < b.f.integer;
+    case TagType::ULONG:
+    case TagType::ULONG_REP:
+        return a.f.longInteger < b.f.longInteger;
+    case TagType::DATE:
+        return a.f.dateTime < b.f.dateTime;
+    case TagType::BIGNUM:
+    case TagType::BYTES:
+        // Handle the empty cases.
+        if (a.blob.size() == 0)
+            return b.blob.size() != 0;
+        if (b.blob.size() == 0) return false;
+
+        retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
+        // if one is the prefix of the other the longer wins
+        if (retval == 0) return a.blob.size() < b.blob.size();
+        // Otherwise a is less if a is less.
+        else return retval < 0;
+    }
+    return false;
+}
+
+inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) return false;
+
+    switch (typeFromTag(a.tag)) {
+    case TagType::INVALID:
+    case TagType::BOOL:
+        return true;
+    case TagType::ENUM:
+    case TagType::ENUM_REP:
+    case TagType::UINT:
+    case TagType::UINT_REP:
+        return a.f.integer == b.f.integer;
+    case TagType::ULONG:
+    case TagType::ULONG_REP:
+        return a.f.longInteger == b.f.longInteger;
+    case TagType::DATE:
+        return a.f.dateTime == b.f.dateTime;
+    case TagType::BIGNUM:
+    case TagType::BYTES:
+        if (a.blob.size() != b.blob.size()) return false;
+        return a.blob.size() == 0 ||
+                memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
+    }
+    return false;
+}
+
+void AuthorizationSet::Sort() {
+    std::sort(data_.begin(), data_.end(), keyParamLess);
+}
+
+void AuthorizationSet::Deduplicate() {
+    if (data_.empty()) return;
+
+    Sort();
+    std::vector<KeyParameter> result;
+
+    auto curr = data_.begin();
+    auto prev = curr++;
+    for (; curr != data_.end(); ++prev, ++curr) {
+        if (prev->tag == Tag::INVALID) continue;
+
+        if (!keyParamEqual(*prev, *curr)) {
+            result.emplace_back(std::move(*prev));
+        }
+    }
+    result.emplace_back(std::move(*prev));
+
+    std::swap(data_, result);
+}
+
+void AuthorizationSet::Union(const AuthorizationSet& other) {
+    data_.insert(data_.end(), other.data_.begin(), other.data_.end());
+    Deduplicate();
+}
+
+void AuthorizationSet::Subtract(const AuthorizationSet& other) {
+    Deduplicate();
+
+    auto i = other.begin();
+    while (i != other.end()) {
+        int pos = -1;
+        do {
+            pos = find(i->tag, pos);
+            if (pos != -1 && keyParamEqual(*i, data_[pos])) {
+                data_.erase(data_.begin() + pos);
+                break;
+            }
+        } while (pos != -1);
+        ++i;
+    }
+}
+
+int AuthorizationSet::find(Tag tag, int begin) const {
+    auto iter = data_.begin() + (1 + begin);
+
+    while (iter != data_.end() && iter->tag != tag) ++iter;
+
+    if (iter != data_.end()) return iter - data_.begin();
+    return -1;
+}
+
+bool AuthorizationSet::erase(int index) {
+    auto pos = data_.begin() + index;
+    if (pos != data_.end()) {
+        data_.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+KeyParameter& AuthorizationSet::operator[](int at) {
+    return data_[at];
+}
+
+const KeyParameter& AuthorizationSet::operator[](int at) const {
+    return data_[at];
+}
+
+void AuthorizationSet::Clear() {
+    data_.clear();
+}
+
+size_t AuthorizationSet::GetTagCount(Tag tag) const {
+    size_t count = 0;
+    for (int pos = -1; (pos = find(tag, pos)) != -1;)
+        ++count;
+    return count;
+}
+
+NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+    int pos = find(tag);
+    if (pos == -1) return {};
+    return data_[pos];
+}
+
+/**
+ * Persistent format is:
+ * | 32 bit indirect_size         |
+ * --------------------------------
+ * | indirect_size bytes of data  | this is where the blob data is stored
+ * --------------------------------
+ * | 32 bit element_count         | number of entries
+ * | 32 bit elements_size         | total bytes used by entries (entries have variable length)
+ * --------------------------------
+ * | elementes_size bytes of data | where the elements are stored
+ */
+
+/**
+ * Persistent format of blobs and bignums:
+ * | 32 bit tag             |
+ * | 32 bit blob_length     |
+ * | 32 bit indirect_offset |
+ */
+
+struct OutStreams {
+    std::ostream& indirect;
+    std::ostream& elements;
+};
+
+OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
+    uint32_t buffer;
+
+    // write blob_length
+    auto blob_length = blob.size();
+    if (blob_length > std::numeric_limits<uint32_t>::max()) {
+        out.elements.setstate(std::ios_base::badbit);
+        return out;
+    }
+    buffer = blob_length;
+    out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+    // write indirect_offset
+    auto offset = out.indirect.tellp();
+    if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
+            uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check
+        out.elements.setstate(std::ios_base::badbit);
+        return out;
+    }
+    buffer = offset;
+    out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+    // write blob to indirect stream
+    if(blob_length)
+        out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
+
+    return out;
+}
+
+template <typename T>
+OutStreams& serializeParamValue(OutStreams& out, const T& value) {
+    out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
+    return out;
+}
+
+OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
+    // skip invalid entries.
+    return out;
+}
+template <typename T>
+OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
+    out.elements.write(reinterpret_cast<const char*>(&param.tag), sizeof(int32_t));
+    return serializeParamValue(out, accessTagValue(ttag, param));
+}
+
+template <typename... T>
+struct choose_serializer;
+template <typename... Tags>
+struct choose_serializer<MetaList<Tags...>> {
+    static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+        return choose_serializer<Tags...>::serialize(out, param);
+    }
+};
+template <>
+struct choose_serializer<> {
+    static OutStreams& serialize(OutStreams& out, const KeyParameter&) {
+        return out;
+    }
+};
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
+    static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+        if (param.tag == tag) {
+            return keystore::serialize(TypedTag<tag_type, tag>(), out, param);
+        } else {
+            return choose_serializer<Tail...>::serialize(out, param);
+        }
+    }
+};
+
+OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+    return choose_serializer<all_tags_t>::serialize(out, param);
+}
+
+std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
+    std::stringstream indirect;
+    std::stringstream elements;
+    OutStreams streams = { indirect, elements };
+    for (const auto& param: params) {
+        serialize(streams, param);
+    }
+    if (indirect.bad() || elements.bad()) {
+        out.setstate(std::ios_base::badbit);
+        return out;
+    }
+    auto pos = indirect.tellp();
+    if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+        out.setstate(std::ios_base::badbit);
+        return out;
+    }
+    uint32_t indirect_size = pos;
+    pos = elements.tellp();
+    if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+        out.setstate(std::ios_base::badbit);
+        return out;
+    }
+    uint32_t elements_size = pos;
+    uint32_t element_count = params.size();
+
+    out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
+
+    pos = out.tellp();
+    if (indirect_size)
+        out << indirect.rdbuf();
+    assert(out.tellp() - pos == indirect_size);
+
+    out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
+    out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
+
+    pos = out.tellp();
+    if (elements_size)
+        out << elements.rdbuf();
+    assert(out.tellp() - pos == elements_size);
+
+    return out;
+}
+
+struct InStreams {
+    std::istream& indirect;
+    std::istream& elements;
+};
+
+InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
+    uint32_t blob_length = 0;
+    uint32_t offset = 0;
+    in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
+    blob->resize(blob_length);
+    in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
+    in.indirect.seekg(offset);
+    in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
+    return in;
+}
+
+template <typename T>
+InStreams& deserializeParamValue(InStreams& in, T* value) {
+    in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
+    return in;
+}
+
+InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
+    // there should be no invalid KeyParamaters but if handle them as zero sized.
+    return in;
+}
+
+template <typename T>
+InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
+    return deserializeParamValue(in, &accessTagValue(ttag, *param));
+}
+
+template <typename... T>
+struct choose_deserializer;
+template <typename... Tags>
+struct choose_deserializer<MetaList<Tags...>> {
+    static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+        return choose_deserializer<Tags...>::deserialize(in, param);
+    }
+};
+template <>
+struct choose_deserializer<> {
+    static InStreams& deserialize(InStreams& in, KeyParameter*) {
+        // encountered an unknown tag -> fail parsing
+        in.elements.setstate(std::ios_base::badbit);
+        return in;
+    }
+};
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
+    static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+        if (param->tag == tag) {
+            return keystore::deserialize(TypedTag<tag_type, tag>(), in, param);
+        } else {
+            return choose_deserializer<Tail...>::deserialize(in, param);
+        }
+    }
+};
+
+InStreams& deserialize(InStreams& in, KeyParameter* param) {
+    in.elements.read(reinterpret_cast<char*>(&param->tag), sizeof(Tag));
+    return choose_deserializer<all_tags_t>::deserialize(in, param);
+}
+
+std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
+    uint32_t indirect_size = 0;
+    in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
+    std::string indirect_buffer(indirect_size, '\0');
+    if (indirect_buffer.size() != indirect_size) {
+        in.setstate(std::ios_base::badbit);
+        return in;
+    }
+    in.read(&indirect_buffer[0], indirect_buffer.size());
+
+    uint32_t element_count = 0;
+    in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
+    uint32_t elements_size = 0;
+    in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
+
+    std::string elements_buffer(elements_size, '\0');
+    if(elements_buffer.size() != elements_size) {
+        in.setstate(std::ios_base::badbit);
+        return in;
+    }
+    in.read(&elements_buffer[0], elements_buffer.size());
+
+    if (in.bad()) return in;
+
+    // TODO write one-shot stream buffer to avoid copying here
+    std::stringstream indirect(indirect_buffer);
+    std::stringstream elements(elements_buffer);
+    InStreams streams = { indirect, elements };
+
+    params->resize(element_count);
+
+    for (uint32_t i = 0; i < element_count; ++i) {
+        deserialize(streams, &(*params)[i]);
+    }
+    return in;
+}
+void AuthorizationSet::Serialize(std::ostream* out) const {
+    serialize(*out, data_);
+}
+void AuthorizationSet::Deserialize(std::istream* in) {
+    deserialize(*in, &data_);
+}
+
+}  // namespace keystore
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 8b08f07..237d896 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -71,12 +71,28 @@
     return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
 }
 
+bool Blob::isSuperEncrypted() const {
+    return mBlob.flags & KEYSTORE_FLAG_SUPER_ENCRYPTED;
+}
+
+bool Blob::isCriticalToDeviceEncryption() const {
+    return mBlob.flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
+}
+
+inline uint8_t setFlag(uint8_t flags, bool set, KeyStoreFlag flag) {
+    return set ? (flags | flag) : (flags & ~flag);
+}
+
 void Blob::setEncrypted(bool encrypted) {
-    if (encrypted) {
-        mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
-    } else {
-        mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
-    }
+    mBlob.flags = setFlag(mBlob.flags, encrypted, KEYSTORE_FLAG_ENCRYPTED);
+}
+
+void Blob::setSuperEncrypted(bool superEncrypted) {
+    mBlob.flags = setFlag(mBlob.flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED);
+}
+
+void Blob::setCriticalToDeviceEncryption(bool critical) {
+    mBlob.flags = setFlag(mBlob.flags, critical, KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
 }
 
 void Blob::setFallback(bool fallback) {
@@ -90,15 +106,15 @@
 ResponseCode Blob::writeBlob(const char* filename, AES_KEY* aes_key, State state,
                              Entropy* entropy) {
     ALOGV("writing blob %s", filename);
-    if (isEncrypted()) {
+    if (isEncrypted() || isSuperEncrypted()) {
         if (state != STATE_NO_ERROR) {
             ALOGD("couldn't insert encrypted blob while not unlocked");
-            return LOCKED;
+            return ResponseCode::LOCKED;
         }
 
         if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
             ALOGW("Could not read random data for: %s", filename);
-            return SYSTEM_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
     }
 
@@ -115,7 +131,7 @@
 
     mBlob.length = htonl(mBlob.length);
 
-    if (isEncrypted()) {
+    if (isEncrypted() || isSuperEncrypted()) {
         MD5(mBlob.digested, digestedLength, mBlob.digest);
 
         uint8_t vector[AES_BLOCK_SIZE];
@@ -132,60 +148,60 @@
         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;
+        return ResponseCode::SYSTEM_ERROR;
     }
     size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
     if (close(out) != 0) {
-        return SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     if (writtenBytes != fileLength) {
         ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
         unlink(tmpFileName);
-        return SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     if (rename(tmpFileName, filename) == -1) {
         ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
-        return SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
-    return NO_ERROR;
+    return ResponseCode::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;
+        return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::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;
+        return ResponseCode::SYSTEM_ERROR;
     }
 
     if (fileLength == 0) {
-        return VALUE_CORRUPTED;
+        return ResponseCode::VALUE_CORRUPTED;
     }
 
-    if (isEncrypted() && (state != STATE_NO_ERROR)) {
-        return LOCKED;
+    if ((isEncrypted() || isSuperEncrypted()) && (state != STATE_NO_ERROR)) {
+        return ResponseCode::LOCKED;
     }
 
     size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
     if (fileLength < headerLength) {
-        return VALUE_CORRUPTED;
+        return ResponseCode::VALUE_CORRUPTED;
     }
 
     ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
     if (encryptedLength < 0) {
-        return VALUE_CORRUPTED;
+        return ResponseCode::VALUE_CORRUPTED;
     }
 
     ssize_t digestedLength;
-    if (isEncrypted()) {
+    if (isEncrypted() || isSuperEncrypted()) {
         if (encryptedLength % AES_BLOCK_SIZE != 0) {
-            return VALUE_CORRUPTED;
+            return ResponseCode::VALUE_CORRUPTED;
         }
 
         AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, mBlob.vector,
@@ -194,7 +210,7 @@
         uint8_t computedDigest[MD5_DIGEST_LENGTH];
         MD5(mBlob.digested, digestedLength, computedDigest);
         if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
-            return VALUE_CORRUPTED;
+            return ResponseCode::VALUE_CORRUPTED;
         }
     } else {
         digestedLength = encryptedLength;
@@ -203,11 +219,11 @@
     ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
     mBlob.length = ntohl(mBlob.length);
     if (mBlob.length < 0 || mBlob.length > maxValueLength) {
-        return VALUE_CORRUPTED;
+        return ResponseCode::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;
+    return ResponseCode::NO_ERROR;
 }
diff --git a/keystore/blob.h b/keystore/blob.h
index d4b5a84..06f9ea5 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -95,6 +95,12 @@
     bool isEncrypted() const;
     void setEncrypted(bool encrypted);
 
+    bool isSuperEncrypted() const;
+    void setSuperEncrypted(bool superEncrypted);
+
+    bool isCriticalToDeviceEncryption() const;
+    void setCriticalToDeviceEncryption(bool critical);
+
     bool isFallback() const { return mBlob.flags & KEYSTORE_FLAG_FALLBACK; }
     void setFallback(bool fallback);
 
diff --git a/keystore/defaults.h b/keystore/defaults.h
index 9232dd0..6f7ff2d 100644
--- a/keystore/defaults.h
+++ b/keystore/defaults.h
@@ -24,19 +24,19 @@
  */
 
 /* DSA */
-#define DSA_DEFAULT_KEY_SIZE 1024
-#define DSA_MIN_KEY_SIZE 512
-#define DSA_MAX_KEY_SIZE 8192
+constexpr int32_t DSA_DEFAULT_KEY_SIZE = 1024;
+constexpr int32_t DSA_MIN_KEY_SIZE = 512;
+constexpr int32_t DSA_MAX_KEY_SIZE = 8192;
 
 /* EC */
-#define EC_DEFAULT_KEY_SIZE 256
-#define EC_MIN_KEY_SIZE 192
-#define EC_MAX_KEY_SIZE 521
+constexpr int32_t EC_DEFAULT_KEY_SIZE = 256;
+constexpr int32_t EC_MIN_KEY_SIZE = 192;
+constexpr int32_t 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
+constexpr int32_t RSA_DEFAULT_KEY_SIZE = 2048;
+constexpr int32_t RSA_DEFAULT_EXPONENT = 0x10001;
+constexpr int32_t RSA_MIN_KEY_SIZE = 512;
+constexpr int32_t RSA_MAX_KEY_SIZE = 8192;
 
 #endif /* KEYSTORE_DEFAULTS_H_ */
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index 1a2f554..18bd8eb 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -17,23 +17,25 @@
 #ifndef KEYSTORE_IKEYSTORESERVICE_H
 #define KEYSTORE_IKEYSTORESERVICE_H
 
-#include <hardware/keymaster_defs.h>
-#include <utils/RefBase.h>
+#include "keystore.h"
+#include "keystore_return_types.h"
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
+#include <keystore/keymaster_tags.h>
+#include <utils/RefBase.h>
 #include <vector>
 
 namespace android {
 
 class KeystoreArg : public RefBase {
-public:
-    KeystoreArg(const void *data, size_t len);
+  public:
+    KeystoreArg(const void* data, size_t len);
     ~KeystoreArg();
 
     const void* data() const;
     size_t size() const;
 
-private:
+  private:
     const void* mData;
     size_t mSize;
 };
@@ -42,16 +44,6 @@
     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 : public ::android::Parcelable {
     OperationResult();
@@ -59,13 +51,12 @@
     status_t readFromParcel(const Parcel* in) override;
     status_t writeToParcel(Parcel* out) const override;
 
-    int resultCode;
+    ::keystore::KeyStoreServiceReturnCode resultCode;
     sp<IBinder> token;
-    keymaster_operation_handle_t handle;
+    uint64_t handle;
     int inputConsumed;
-    std::unique_ptr<uint8_t[], MallocDeleter> data;
-    size_t dataLength;
-    KeymasterArguments outParams;
+    ::keystore::hidl_vec<uint8_t> data;
+    ::keystore::hidl_vec<::keystore::KeyParameter> outParams;
 };
 
 // struct for serializing the results of export
@@ -75,41 +66,15 @@
     status_t readFromParcel(const Parcel* in) override;
     status_t writeToParcel(Parcel* out) const override;
 
-    int resultCode;
-    std::unique_ptr<uint8_t[], MallocDeleter> exportData;
-    size_t dataLength;
+    ::keystore::KeyStoreServiceReturnCode resultCode;
+    ::keystore::hidl_vec<uint8_t> exportData;
 };
 
-// struct for serializing keymaster_key_characteristics_t's
-struct KeyCharacteristics : public ::android::Parcelable {
-    KeyCharacteristics();
-    ~KeyCharacteristics();
-    status_t readFromParcel(const Parcel* in) override;
-    status_t writeToParcel(Parcel* out) const override;
-
-    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:
+class IKeystoreService : public IInterface {
+  public:
     enum {
         GET_STATE = IBinder::FIRST_CALL_TRANSACTION + 0,
         GET = IBinder::FIRST_CALL_TRANSACTION + 1,
@@ -147,119 +112,144 @@
         ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33,
         ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34,
         ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35,
-        ON_DEVICE_OFF_BODY = IBinder::FIRST_CALL_TRANSACTION + 36,
+        ATTEST_DEVICE_IDS = IBinder::FIRST_CALL_TRANSACTION + 36,
+        ON_DEVICE_OFF_BODY = IBinder::FIRST_CALL_TRANSACTION + 37,
     };
 
     DECLARE_META_INTERFACE(KeystoreService);
 
-    virtual int32_t getState(int32_t userId) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode getState(int32_t userId) = 0;
 
-    virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
+                                                      ::keystore::hidl_vec<uint8_t>* item) = 0;
 
-    virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
-            int32_t flags) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode insert(const String16& name,
+                                                         const ::keystore::hidl_vec<uint8_t>& item,
+                                                         int uid, int32_t flags) = 0;
 
-    virtual int32_t del(const String16& name, int uid) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode del(const String16& name, int uid) = 0;
 
-    virtual int32_t exist(const String16& name, int uid) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode exist(const String16& name, int uid) = 0;
 
-    virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode list(const String16& prefix, int uid,
+                                                       Vector<String16>* matches) = 0;
 
-    virtual int32_t reset() = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode reset() = 0;
 
-    virtual int32_t onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
 
-    virtual int32_t lock(int32_t userId) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode lock(int32_t userId) = 0;
 
-    virtual int32_t unlock(int32_t userId, const String16& password) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode 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 ::keystore::KeyStoreServiceReturnCode 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 ::keystore::KeyStoreServiceReturnCode import(const String16& name,
+                                                         const ::keystore::hidl_vec<uint8_t>& data,
+                                                         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 ::keystore::KeyStoreServiceReturnCode sign(const String16& name,
+                                                       const ::keystore::hidl_vec<uint8_t>& data,
+                                                       ::keystore::hidl_vec<uint8_t>* out) = 0;
 
-    virtual int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
-            const uint8_t* signature, size_t signatureLength) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    verify(const String16& name, const ::keystore::hidl_vec<uint8_t>& data,
+           const ::keystore::hidl_vec<uint8_t>& signature) = 0;
 
-    virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    get_pubkey(const String16& name, ::keystore::hidl_vec<uint8_t>* pubKey) = 0;
 
-    virtual int32_t grant(const String16& name, int32_t granteeUid) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode grant(const String16& name,
+                                                        int32_t granteeUid) = 0;
 
-    virtual int32_t ungrant(const String16& name, int32_t granteeUid) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode ungrant(const String16& name,
+                                                          int32_t granteeUid) = 0;
 
     virtual int64_t getmtime(const String16& name, int32_t uid) = 0;
 
-    virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-            int32_t destUid) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    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 ::keystore::KeyStoreServiceReturnCode clear_uid(int64_t uid) = 0;
 
-    virtual int32_t addRngEntropy(const uint8_t* data, size_t dataLength) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    addRngEntropy(const ::keystore::hidl_vec<uint8_t>& entropy) = 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 ::keystore::KeyStoreServiceReturnCode
+    generateKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+                const ::keystore::hidl_vec<uint8_t>& entropy, int uid, int flags,
+                ::keystore::KeyCharacteristics* outCharacteristics) = 0;
 
-    virtual int32_t getKeyCharacteristics(const String16& name,
-                                          const keymaster_blob_t* clientId,
-                                          const keymaster_blob_t* appData,
-                                          int32_t uid,
-                                          KeyCharacteristics* outCharacteristics) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    getKeyCharacteristics(const String16& name, const ::keystore::hidl_vec<uint8_t>& clientId,
+                          const ::keystore::hidl_vec<uint8_t>& appData, int32_t uid,
+                          ::keystore::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 ::keystore::KeyStoreServiceReturnCode
+    importKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+              ::keystore::KeyFormat format, const ::keystore::hidl_vec<uint8_t>& key, int uid,
+              int flags, ::keystore::KeyCharacteristics* outCharacteristics) = 0;
 
-    virtual void exportKey(const String16& name, keymaster_key_format_t format,
-                           const keymaster_blob_t* clientId,
-                           const keymaster_blob_t* appData, int32_t uid, ExportResult* result) = 0;
+    virtual void exportKey(const String16& name, ::keystore::KeyFormat format,
+                           const ::keystore::hidl_vec<uint8_t>& clientId,
+                           const ::keystore::hidl_vec<uint8_t>& appData, int uid,
+                           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, int32_t uid, OperationResult* result) = 0;
+                       ::keystore::KeyPurpose purpose, bool pruneable,
+                       const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+                       const ::keystore::hidl_vec<uint8_t>& entropy, int32_t uid,
+                       OperationResult* opResult) = 0;
 
-    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
-                        const uint8_t* data, size_t dataLength, OperationResult* result) = 0;
+    virtual void update(const sp<IBinder>& token,
+                        const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+                        const ::keystore::hidl_vec<uint8_t>& data, OperationResult* opResult) = 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 void finish(const sp<IBinder>& token,
+                        const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+                        const ::keystore::hidl_vec<uint8_t>& signature,
+                        const ::keystore::hidl_vec<uint8_t>& entropy,
+                        OperationResult* opResult) = 0;
 
-    virtual int32_t abort(const sp<IBinder>& handle) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode 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 ::keystore::KeyStoreServiceReturnCode addAuthToken(const uint8_t* token,
+                                                               size_t length) = 0;
 
-    virtual int32_t onUserAdded(int32_t userId, int32_t parentId) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) = 0;
 
-    virtual int32_t onUserRemoved(int32_t userId) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode onUserRemoved(int32_t userId) = 0;
 
-    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
-                              KeymasterCertificateChain* outChain) = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode
+    attestKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+              ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0;
 
-    virtual int32_t onDeviceOffBody() = 0;
+    virtual ::keystore::KeyStoreServiceReturnCode attestDeviceIds(
+            const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
+            ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0;
+
+    virtual ::keystore::KeyStoreServiceReturnCode onDeviceOffBody() = 0;
 };
 
 // ----------------------------------------------------------------------------
 
-class BnKeystoreService: public BnInterface<IKeystoreService> {
-public:
+class BnKeystoreService : public BnInterface<IKeystoreService> {
+  public:
     virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-            uint32_t flags = 0);
+                                uint32_t flags = 0);
 };
 
-} // namespace android
+}  // namespace android
 
 #endif
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
new file mode 100644
index 0000000..a7ce210
--- /dev/null
+++ b/keystore/include/keystore/KeyAttestationApplicationId.h
@@ -0,0 +1,51 @@
+// Copyright 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_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
+
+#include "KeyAttestationPackageInfo.h"
+#include "utils.h"
+#include <binder/Parcelable.h>
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+class KeyAttestationApplicationId : public Parcelable {
+  public:
+    typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
+        ConstKeyAttestationPackageInfoIterator;
+
+    status_t writeToParcel(Parcel*) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    ConstKeyAttestationPackageInfoIterator pinfos_begin() const {
+        return ConstKeyAttestationPackageInfoIterator(packageInfos_);
+    }
+    ConstKeyAttestationPackageInfoIterator pinfos_end() const {
+        return ConstKeyAttestationPackageInfoIterator();
+    }
+
+  private:
+    std::shared_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> packageInfos_;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namsepace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
new file mode 100644
index 0000000..b938e83
--- /dev/null
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -0,0 +1,53 @@
+// Copyright 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_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
+
+#include "Signature.h"
+#include "utils.h"
+#include <binder/Parcelable.h>
+#include <memory>
+#include <stdint.h>
+#include <vector>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+class KeyAttestationPackageInfo : public Parcelable {
+  public:
+    typedef SharedNullableIterator<const content::pm::Signature, std::vector>
+        ConstSignatureIterator;
+
+    status_t writeToParcel(Parcel*) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    const std::unique_ptr<String16>& package_name() const { return packageName_; }
+    int32_t version_code() const { return versionCode_; }
+
+    ConstSignatureIterator sigs_begin() const { return ConstSignatureIterator(signatures_); }
+    ConstSignatureIterator sigs_end() const { return ConstSignatureIterator(); }
+
+  private:
+    std::unique_ptr<String16> packageName_;
+    int32_t versionCode_;
+    std::shared_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> signatures_;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
diff --git a/keystore/include/keystore/Signature.h b/keystore/include/keystore/Signature.h
new file mode 100644
index 0000000..59b77bf
--- /dev/null
+++ b/keystore/include/keystore/Signature.h
@@ -0,0 +1,43 @@
+// Copyright 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_INCLUDE_KEYSTORE_SIGNATURE_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
+
+#include <binder/Parcelable.h>
+#include <stdint.h>
+#include <vector>
+
+namespace android {
+namespace content {
+namespace pm {
+
+class Signature : public Parcelable {
+  public:
+    status_t writeToParcel(Parcel*) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    const std::vector<uint8_t>& data() const & { return sig_data_; }
+    std::vector<uint8_t>& data() & { return sig_data_; }
+    std::vector<uint8_t>&& data() && { return std::move(sig_data_); }
+
+  private:
+    std::vector<uint8_t> sig_data_;
+};
+
+}  // namespace pm
+}  // namespace content
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
diff --git a/keystore/include/keystore/authorization_set.h b/keystore/include/keystore/authorization_set.h
new file mode 100644
index 0000000..0e57a19
--- /dev/null
+++ b/keystore/include/keystore/authorization_set.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
+#define SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
+
+#include "keymaster_tags.h"
+#include <vector>
+
+namespace keystore {
+
+class AuthorizationSetBuilder;
+
+/**
+ * An ordered collection of KeyParameters. It provides memory ownership and some convenient
+ * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
+ * For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>.
+ */
+class AuthorizationSet {
+  public:
+    /**
+     * Construct an empty, dynamically-allocated, growable AuthorizationSet.
+     */
+    AuthorizationSet() {};
+
+    // Copy constructor.
+    AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
+
+    // Move constructor.
+    AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
+
+    // Constructor from hidl_vec<KeyParameter>
+    AuthorizationSet(const hidl_vec<KeyParameter>& other) {
+        *this = other;
+    }
+
+    // Copy assignment.
+    AuthorizationSet& operator=(const AuthorizationSet& other) {
+        data_ = other.data_;
+        return *this;
+    }
+
+    // Move assignment.
+    AuthorizationSet& operator=(AuthorizationSet&& other) {
+        data_ = std::move(other.data_);
+        return *this;
+    }
+
+    AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) {
+        if (other.size() > 0) {
+            data_.resize(other.size());
+            for (size_t i = 0; i < data_.size(); ++i) {
+                /* This makes a deep copy even of embedded blobs.
+                 * See assignment operator/copy constructor of hidl_vec.*/
+                data_[i] = other[i];
+            }
+        }
+        return *this;
+    }
+
+    /**
+     * Clear existing authorization set data
+     */
+    void Clear();
+
+    ~AuthorizationSet() = default;
+
+    /**
+     * Returns the size of the set.
+     */
+    size_t size() const { return data_.size(); }
+
+    /**
+     * Returns true if the set is empty.
+     */
+    bool empty() const { return size() == 0; }
+
+    /**
+     * Returns the data in the set, directly. Be careful with this.
+     */
+    const KeyParameter* data() const { return data_.data(); }
+
+    /**
+     * Sorts the set
+     */
+    void Sort();
+
+    /**
+     * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
+     * AuthorizationSetBuilder).
+     */
+    void Deduplicate();
+
+    /**
+     * Adds all elements from \p set that are not already present in this AuthorizationSet.  As a
+     * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
+     */
+    void Union(const AuthorizationSet& set);
+
+    /**
+     * Removes all elements in \p set from this AuthorizationSet.
+     */
+    void Subtract(const AuthorizationSet& set);
+
+    /**
+     * Returns the offset of the next entry that matches \p tag, starting from the element after \p
+     * begin.  If not found, returns -1.
+     */
+    int find(Tag tag, int begin = -1) const;
+
+    /**
+     * Removes the entry at the specified index. Returns true if successful, false if the index was
+     * out of bounds.
+     */
+    bool erase(int index);
+
+    /**
+     * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
+     */
+    std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
+
+    /**
+     * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
+     */
+    std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
+
+    /**
+     * Returns the nth element of the set.
+     * Like for std::vector::operator[] there is no range check performed. Use of out of range
+     * indices is undefined.
+     */
+    KeyParameter& operator[](int n);
+
+    /**
+     * Returns the nth element of the set.
+     * Like for std::vector::operator[] there is no range check performed. Use of out of range
+     * indices is undefined.
+     */
+    const KeyParameter& operator[](int n) const;
+
+    /**
+     * Returns true if the set contains at least one instance of \p tag
+     */
+    bool Contains(Tag tag) const {
+        return find(tag) != -1;
+    }
+
+    template <TagType tag_type, Tag tag, typename ValueT>
+    bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+        for (const auto& param: data_) {
+            auto entry = authorizationValue(ttag, param);
+            if (entry.isOk() && entry.value() == value) return true;
+        }
+        return false;
+    }
+    /**
+     * Returns the number of \p tag entries.
+     */
+    size_t GetTagCount(Tag tag) const;
+
+    template <typename T>
+    inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+        auto entry = GetEntry(tag);
+        if (entry.isOk()) return authorizationValue(tag, entry.value());
+        return {};
+    }
+
+    void push_back(const KeyParameter& param) {
+        data_.push_back(param);
+    }
+    void push_back(KeyParameter&& param) {
+        data_.push_back(std::move(param));
+    }
+
+    /**
+     * Append the tag and enumerated value to the set.
+     * "val" may be exactly one parameter unless a boolean parameter is added.
+     * In this case "val" is omitted. This condition is checked at compile time by Authorization()
+     */
+    template <typename TypedTagT, typename... Value>
+    void push_back(TypedTagT tag, Value&&... val) {
+        push_back(Authorization(tag, std::forward<Value>(val)...));
+    }
+
+    template <typename Iterator>
+    void append(Iterator begin, Iterator end) {
+        while (begin != end) {
+            push_back(*begin);
+            ++begin;
+        }
+    }
+
+    hidl_vec<KeyParameter> hidl_data() const {
+        hidl_vec<KeyParameter> result;
+        result.setToExternal(const_cast<KeyParameter*>(data()), size());
+        return result;
+    }
+
+    void Serialize(std::ostream* out) const;
+    void Deserialize(std::istream* in);
+
+  private:
+    NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+
+    std::vector<KeyParameter> data_;
+};
+
+class AuthorizationSetBuilder: public AuthorizationSet {
+  public:
+    template <typename TagType, typename... ValueType>
+    AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
+        push_back(ttag, std::forward<ValueType>(value)...);
+        return *this;
+    }
+
+    template <Tag tag>
+    AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
+                                           size_t data_length) {
+        hidl_vec<uint8_t> new_blob;
+        new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
+        push_back(ttag, std::move(new_blob));
+        return *this;
+    }
+
+    template <Tag tag>
+    AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
+                                           size_t data_length) {
+        return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
+    }
+
+    AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
+    AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
+    AuthorizationSetBuilder& AesKey(uint32_t key_size);
+    AuthorizationSetBuilder& HmacKey(uint32_t key_size);
+
+    AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
+    AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
+    AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
+    AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
+
+    AuthorizationSetBuilder& SigningKey();
+    AuthorizationSetBuilder& EncryptionKey();
+    AuthorizationSetBuilder& NoDigestOrPadding();
+    AuthorizationSetBuilder& EcbMode();
+
+    AuthorizationSetBuilder& Digest(Digest digest) {
+        return Authorization(TAG_DIGEST, digest);
+    }
+
+    AuthorizationSetBuilder& Padding(PaddingMode padding) {
+        return Authorization(TAG_PADDING, padding);
+    }
+};
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
+                                                                uint64_t public_exponent) {
+    Authorization(TAG_ALGORITHM, Algorithm::RSA);
+    Authorization(TAG_KEY_SIZE, key_size);
+    Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
+    return *this;
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::EC);
+    Authorization(TAG_KEY_SIZE, key_size);
+    return *this;
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::AES);
+    return Authorization(TAG_KEY_SIZE, key_size);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::HMAC);
+    Authorization(TAG_KEY_SIZE, key_size);
+    return SigningKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
+                                                                       uint64_t public_exponent) {
+    RsaKey(key_size, public_exponent);
+    return SigningKey();
+}
+
+inline AuthorizationSetBuilder&
+AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
+    RsaKey(key_size, public_exponent);
+    return EncryptionKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
+    EcdsaKey(key_size);
+    return SigningKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
+    AesKey(key_size);
+    return EncryptionKey();
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
+    Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
+    return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
+    Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
+    return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
+    Authorization(TAG_DIGEST, Digest::NONE);
+    return Authorization(TAG_PADDING, PaddingMode::NONE);
+}
+
+inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
+    return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
+}
+
+}  // namespace keystore
+
+#endif  // SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
diff --git a/keystore/include/keystore/keymaster_tags.h b/keystore/include/keystore/keymaster_tags.h
new file mode 100644
index 0000000..05a33cd
--- /dev/null
+++ b/keystore/include/keystore/keymaster_tags.h
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+
+/**
+ * This header contains various definitions that make working with keymaster tags safer and easier.
+ *
+ * It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose
+ * of making it impossible to make certain classes of mistakes when operating on keymaster
+ * authorizations.  For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE
+ * and then to assign Algorithm::RSA to algorithm element of its union. But because the user
+ * must choose the union field, there could be a mismatch which the compiler has now way to
+ * diagnose.
+ *
+ * The machinery in this header solves these problems by describing which union field corresponds
+ * to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a
+ * numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG,
+ * we declare types for each of the tags defined in hardware/interfaces/keymaster/2.0/types.hal.
+ *
+ * The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance
+ * TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag
+ * to its value c++ type and the correct union element of KeyParameter. This is done by means of
+ * the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping
+ * a typed tag to the corresponding c++ type, and access function, accessTagValue returning a
+ * reference to the correct element of KeyParameter.
+ * E.g.:
+ *      given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)"
+ *      yields a reference to param.f.purpose
+ * If used in an assignment the compiler can now check the compatibility of the assigned value.
+ *
+ * For convenience we also provide the constructor like function Authorization().
+ * Authorization takes a typed tag and a value and checks at compile time whether the value given
+ * is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the
+ * given tag and value and returns it by value.
+ *
+ * The second convenience function, authorizationValue, allows access to the KeyParameter value in
+ * a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped
+ * by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped
+ * reference.
+ * E.g.:
+ *      auto param = Authorization(TAG_ALGORITM, Algorithm::RSA);
+ *      auto value1 = authorizationValue(TAG_PURPOSE, param);
+ *      auto value2 = authorizationValue(TAG_ALGORITM, param);
+ * value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access.
+ */
+
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+#include <hardware/hw_auth_token.h>
+#include <type_traits>
+
+namespace keystore {
+
+using ::android::hardware::keymaster::V3_0::Algorithm;
+using ::android::hardware::keymaster::V3_0::BlockMode;
+using ::android::hardware::keymaster::V3_0::Digest;
+using ::android::hardware::keymaster::V3_0::EcCurve;
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
+using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V3_0::KeyBlobUsageRequirements;
+using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V3_0::KeyDerivationFunction;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::KeyOrigin;
+using ::android::hardware::keymaster::V3_0::KeyParameter;
+using ::android::hardware::keymaster::V3_0::KeyPurpose;
+using ::android::hardware::keymaster::V3_0::PaddingMode;
+using ::android::hardware::keymaster::V3_0::Tag;
+using ::android::hardware::keymaster::V3_0::TagType;
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have.  We
+// need these old values to be able to support old keys that use them.
+static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
+static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+
+constexpr TagType typeFromTag(Tag tag) {
+    return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
+}
+
+/**
+ * TypedTag is a templatized version of Tag, which provides compile-time checking of
+ * keymaster tag types. Instances are convertible to Tag, so they can be used wherever
+ * Tag is expected, and because they encode the tag type it's possible to create
+ * function overloads that only operate on tags with a particular type.
+ */
+template <TagType tag_type, Tag tag> struct TypedTag {
+    inline TypedTag() {
+        // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
+        // 'tag_type'.  Attempting to instantiate a tag with the wrong type will result in a compile
+        // error (no match for template specialization StaticAssert<false>), with no run-time cost.
+        static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
+    }
+    operator Tag() const { return tag; }
+};
+
+template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; };
+
+template <Tag tag> struct Tag2String;
+
+#define _TAGS_STRINGIFY(x) #x
+#define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x)
+
+#define DECLARE_TYPED_TAG(name)                                                                    \
+    typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t;                                 \
+    extern TAG_##name##_t TAG_##name;                                                              \
+    template <> struct Tag2String<Tag::name> {                                                     \
+        static const char* value() { return "Tag::" TAGS_STRINGIFY(name); }                        \
+    }
+
+DECLARE_TYPED_TAG(INVALID);
+DECLARE_TYPED_TAG(KEY_SIZE);
+DECLARE_TYPED_TAG(MAC_LENGTH);
+DECLARE_TYPED_TAG(CALLER_NONCE);
+DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
+DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
+DECLARE_TYPED_TAG(ECIES_SINGLE_HASH_MODE);
+DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
+DECLARE_TYPED_TAG(ACTIVE_DATETIME);
+DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
+DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
+DECLARE_TYPED_TAG(ALL_USERS);
+DECLARE_TYPED_TAG(USER_ID);
+DECLARE_TYPED_TAG(USER_SECURE_ID);
+DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
+DECLARE_TYPED_TAG(AUTH_TIMEOUT);
+DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
+DECLARE_TYPED_TAG(ALL_APPLICATIONS);
+DECLARE_TYPED_TAG(APPLICATION_ID);
+DECLARE_TYPED_TAG(APPLICATION_DATA);
+DECLARE_TYPED_TAG(CREATION_DATETIME);
+DECLARE_TYPED_TAG(ROLLBACK_RESISTANT);
+DECLARE_TYPED_TAG(ROOT_OF_TRUST);
+DECLARE_TYPED_TAG(ASSOCIATED_DATA);
+DECLARE_TYPED_TAG(NONCE);
+DECLARE_TYPED_TAG(AUTH_TOKEN);
+DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
+DECLARE_TYPED_TAG(OS_VERSION);
+DECLARE_TYPED_TAG(OS_PATCHLEVEL);
+DECLARE_TYPED_TAG(UNIQUE_ID);
+DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
+DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
+
+DECLARE_TYPED_TAG(PURPOSE);
+DECLARE_TYPED_TAG(ALGORITHM);
+DECLARE_TYPED_TAG(BLOCK_MODE);
+DECLARE_TYPED_TAG(DIGEST);
+DECLARE_TYPED_TAG(PADDING);
+DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
+DECLARE_TYPED_TAG(ORIGIN);
+DECLARE_TYPED_TAG(USER_AUTH_TYPE);
+DECLARE_TYPED_TAG(KDF);
+DECLARE_TYPED_TAG(EC_CURVE);
+
+template <typename... Elems> struct MetaList {};
+
+using all_tags_t = MetaList<
+    TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
+    TAG_RSA_PUBLIC_EXPONENT_t, TAG_ECIES_SINGLE_HASH_MODE_t, TAG_INCLUDE_UNIQUE_ID_t,
+    TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+    TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_ALL_USERS_t, TAG_USER_ID_t,
+    TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
+    TAG_ALL_APPLICATIONS_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t,
+    TAG_ROLLBACK_RESISTANT_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
+    TAG_AUTH_TOKEN_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
+    TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
+    TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
+    TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_KDF_t, TAG_EC_CURVE_t>;
+
+/* implementation in keystore_utils.cpp */
+extern const char* stringifyTag(Tag tag);
+
+template <typename TypedTagType> struct TypedTag2ValueType;
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                                              \
+    template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                        \
+        typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;                    \
+    };                                                                                             \
+    template <Tag tag>                                                                             \
+    inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param)                 \
+        ->const decltype(param.field_name)& {                                                      \
+        return param.field_name;                                                                   \
+    }                                                                                              \
+    template <Tag tag>                                                                             \
+    inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param)                       \
+        ->decltype(param.field_name)& {                                                            \
+        return param.field_name;                                                                   \
+    }
+
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
+
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name)                                        \
+    template <> struct TypedTag2ValueType<decltype(typed_tag)> {                                   \
+        typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;                    \
+    };                                                                                             \
+    inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param)                     \
+        ->const decltype(param.field_name)& {                                                      \
+        return param.field_name;                                                                   \
+    }                                                                                              \
+    inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)                           \
+        ->decltype(param.field_name)& {                                                            \
+        return param.field_name;                                                                   \
+    }
+
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_KDF, f.keyDerivationFunction)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
+
+template <TagType tag_type, Tag tag, typename ValueT>
+inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
+    KeyParameter param;
+    param.tag = tag;
+    param.f.longInteger = 0;
+    accessTagValue(ttag, param) = std::forward<ValueT>(value);
+    return param;
+}
+
+// the boolean case
+template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
+    KeyParameter param;
+    param.tag = tag;
+    param.f.boolValue = true;
+    return param;
+}
+
+template <typename... Pack> struct FirstOrNoneHelper;
+template <typename First> struct FirstOrNoneHelper<First> { typedef First type; };
+template <> struct FirstOrNoneHelper<> {
+    struct type {};
+};
+
+template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
+
+template <TagType tag_type, Tag tag, typename... Args>
+inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
+    static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
+                  "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
+    static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
+                  "Authorization other then TagType::BOOL take exactly one parameter.");
+    static_assert(
+        tag_type == TagType::BOOL ||
+            std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
+                                typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
+        "Invalid argument type for given tag.");
+
+    return makeKeyParameter(ttag, std::forward<Args>(args)...);
+}
+
+/**
+ * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
+ * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
+ * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
+ * wrapped value. In this case the pointer will be NULL though, and the value will be default
+ * constructed.
+ */
+template <typename ValueT> class NullOr {
+    template <typename T> struct reference_initializer {
+        static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+    };
+    template <typename T> struct pointer_initializer {
+        static T init() { return nullptr; }
+    };
+    template <typename T> struct value_initializer {
+        static T init() { return T(); }
+    };
+    template <typename T>
+    using initializer_t =
+        std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
+                           std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
+                                              value_initializer<T>>>;
+
+  public:
+    NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
+    NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
+
+    bool isOk() const { return !null_; }
+
+    const ValueT& value() const & { return value_; }
+    ValueT& value() & { return value_; }
+    ValueT&& value() && { return std::move(value_); }
+
+  private:
+    ValueT value_;
+    bool null_;
+};
+
+template <typename T> std::remove_reference_t<T> NullOrOr(T&& v) {
+    if (v.isOk()) return v;
+    return {};
+}
+
+template <typename Head, typename... Tail>
+std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
+    if (head.isOk()) return head;
+    return NullOrOr(std::forward<Tail>(tail)...);
+}
+
+template <typename Default, typename Wrapped>
+std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+    static_assert(std::is_convertible<std::remove_reference_t<Default>,
+                                      std::remove_reference_t<Wrapped>>::value,
+                  "Type of default value must match the type wrapped by NullOr");
+    if (optional.isOk()) return optional.value();
+    return def;
+}
+
+template <TagType tag_type, Tag tag>
+inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&>
+authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+    if (tag != param.tag) return {};
+    return accessTagValue(ttag, param);
+}
+
+}  // namespace keymaster
+
+#endif  // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index dcb6032..7260363 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -26,7 +26,7 @@
     STATE_UNINITIALIZED = 3,
 };
 
-enum ResponseCode {
+enum class ResponseCode: int32_t {
     NO_ERROR          =  STATE_NO_ERROR, // 1
     LOCKED            =  STATE_LOCKED, // 2
     UNINITIALIZED     =  STATE_UNINITIALIZED, // 3
@@ -47,10 +47,21 @@
 /*
  * All the flags for import and insert calls.
  */
-enum {
+enum KeyStoreFlag : uint8_t {
     KEYSTORE_FLAG_NONE = 0,
     KEYSTORE_FLAG_ENCRYPTED = 1 << 0,
     KEYSTORE_FLAG_FALLBACK = 1 << 1,
+    // KEYSTORE_FLAG_SUPER_ENCRYPTED is for blobs that are already encrypted by keymaster but have
+    // an additional layer of password-based encryption applied.  The same encryption scheme is used
+    // as KEYSTORE_FLAG_ENCRYPTED, but it's safe to remove super-encryption when the password is
+    // cleared, rather than deleting blobs, and the error returned when attempting to use a
+    // super-encrypted blob while keystore is locked is different.
+    KEYSTORE_FLAG_SUPER_ENCRYPTED = 1 << 2,
+    // KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION is for blobs that are part of device encryption
+    // flow so it receives special treatment from keystore. For example this blob will not be super
+    // encrypted, and it will be stored separately under an unique UID instead. This flag should
+    // only be available to system uid.
+    KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3,
 };
 
 /**
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
index cec29f7..2ba7fd4 100644
--- a/keystore/include/keystore/keystore_client.h
+++ b/keystore/include/keystore/keystore_client.h
@@ -19,16 +19,21 @@
 #include <string>
 #include <vector>
 
-#include "hardware/keymaster_defs.h"
-#include "keymaster/authorization_set.h"
+#include <android-base/macros.h>
+
+#include "authorization_set.h"
+#include "keystore.h"
+#include "keystore_return_types.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]
+//   - encourage the use of keystore::AuthorizationSet[Builder]
 //   - be convenient for native services integrating with keystore
 //   - be safely mocked for unit testing (e.g. pure virtual methods)
 //
@@ -73,79 +78,79 @@
     // 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,
+    virtual bool oneShotOperation(KeyPurpose purpose, const std::string& key_name,
+                                  const keystore::AuthorizationSet& input_parameters,
                                   const std::string& input_data,
                                   const std::string& signature_to_verify,
-                                  keymaster::AuthorizationSet* output_parameters,
+                                  keystore::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;
+    virtual KeyStoreNativeReturnCode 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;
+    virtual KeyStoreNativeReturnCode generateKey(const std::string& key_name,
+                                const keystore::AuthorizationSet& key_parameters,
+                                keystore::AuthorizationSet* hardware_enforced_characteristics,
+                                keystore::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
+    virtual KeyStoreNativeReturnCode
     getKeyCharacteristics(const std::string& key_name,
-                          keymaster::AuthorizationSet* hardware_enforced_characteristics,
-                          keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+                          keystore::AuthorizationSet* hardware_enforced_characteristics,
+                          keystore::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;
+    virtual KeyStoreNativeReturnCode importKey(const std::string& key_name,
+                              const keystore::AuthorizationSet& key_parameters,
+                              KeyFormat key_format, const std::string& key_data,
+                              keystore::AuthorizationSet* hardware_enforced_characteristics,
+                              keystore::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,
+    virtual KeyStoreNativeReturnCode exportKey(KeyFormat 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;
+    virtual KeyStoreNativeReturnCode 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;
+    virtual KeyStoreNativeReturnCode 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;
+    virtual KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
+                                   const keystore::AuthorizationSet& input_parameters,
+                                   keystore::AuthorizationSet* output_parameters,
+                                   uint64_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,
+    virtual KeyStoreNativeReturnCode updateOperation(uint64_t handle,
+                                    const keystore::AuthorizationSet& input_parameters,
                                     const std::string& input_data, size_t* num_input_bytes_consumed,
-                                    keymaster::AuthorizationSet* output_parameters,
+                                    keystore::AuthorizationSet* output_parameters,
                                     std::string* output_data) = 0;
 
     // Finishes the operation associated with |handle| using the given
@@ -153,15 +158,15 @@
     // 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,
+    virtual KeyStoreNativeReturnCode finishOperation(uint64_t handle,
+                                    const keystore::AuthorizationSet& input_parameters,
                                     const std::string& signature_to_verify,
-                                    keymaster::AuthorizationSet* output_parameters,
+                                    keystore::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;
+    virtual KeyStoreNativeReturnCode abortOperation(uint64_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.
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
index 21f68f9..eb02275 100644
--- a/keystore/include/keystore/keystore_client_impl.h
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -15,16 +15,16 @@
 #ifndef KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
 #define KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
 
-#include "keystore/keystore_client.h"
+#include "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"
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include "IKeystoreService.h"
+#include <utils/StrongPointer.h>
 
 namespace keystore {
 
@@ -38,54 +38,54 @@
                                    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,
+    bool oneShotOperation(KeyPurpose purpose, const std::string& key_name,
+                          const keystore::AuthorizationSet& input_parameters,
                           const std::string& input_data, const std::string& signature_to_verify,
-                          keymaster::AuthorizationSet* output_parameters,
+                          keystore::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
+    KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy) override;
+    KeyStoreNativeReturnCode generateKey(const std::string& key_name,
+                        const keystore::AuthorizationSet& key_parameters,
+                        keystore::AuthorizationSet* hardware_enforced_characteristics,
+                        keystore::AuthorizationSet* software_enforced_characteristics) override;
+    KeyStoreNativeReturnCode
     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,
+                          keystore::AuthorizationSet* hardware_enforced_characteristics,
+                          keystore::AuthorizationSet* software_enforced_characteristics) override;
+    KeyStoreNativeReturnCode importKey(const std::string& key_name,
+                      const keystore::AuthorizationSet& key_parameters,
+                      KeyFormat key_format, const std::string& key_data,
+                      keystore::AuthorizationSet* hardware_enforced_characteristics,
+                      keystore::AuthorizationSet* software_enforced_characteristics) override;
+    KeyStoreNativeReturnCode exportKey(KeyFormat 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,
+    KeyStoreNativeReturnCode deleteKey(const std::string& key_name) override;
+    KeyStoreNativeReturnCode deleteAllKeys() override;
+    KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
+                           const keystore::AuthorizationSet& input_parameters,
+                           keystore::AuthorizationSet* output_parameters,
+                           uint64_t* handle) override;
+    KeyStoreNativeReturnCode updateOperation(uint64_t handle,
+                            const keystore::AuthorizationSet& input_parameters,
                             const std::string& input_data, size_t* num_input_bytes_consumed,
-                            keymaster::AuthorizationSet* output_parameters,
+                            keystore::AuthorizationSet* output_parameters,
                             std::string* output_data) override;
-    int32_t finishOperation(keymaster_operation_handle_t handle,
-                            const keymaster::AuthorizationSet& input_parameters,
+    KeyStoreNativeReturnCode finishOperation(uint64_t handle,
+                            const keystore::AuthorizationSet& input_parameters,
                             const std::string& signature_to_verify,
-                            keymaster::AuthorizationSet* output_parameters,
+                            keystore::AuthorizationSet* output_parameters,
                             std::string* output_data) override;
-    int32_t abortOperation(keymaster_operation_handle_t handle) override;
+    KeyStoreNativeReturnCode abortOperation(uint64_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();
+    uint64_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);
+//    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.
@@ -108,8 +108,8 @@
     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_;
+    uint64_t next_virtual_handle_ = 1;
+    std::map<uint64_t, android::sp<android::IBinder>> active_operations_;
 
     DISALLOW_COPY_AND_ASSIGN(KeystoreClientImpl);
 };
diff --git a/keystore/include/keystore/keystore_hidl_support.h b/keystore/include/keystore/keystore_hidl_support.h
new file mode 100644
index 0000000..3c64d2a
--- /dev/null
+++ b/keystore/include/keystore/keystore_hidl_support.h
@@ -0,0 +1,130 @@
+/*
+ **
+ ** Copyright 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_HIDL_SUPPORT_H_
+#define KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+#include <keystore/keymaster_tags.h>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+namespace keystore {
+
+inline static std::ostream& formatArgs(std::ostream& out) {
+    return out;
+}
+
+template <typename First, typename... Args>
+inline static std::ostream& formatArgs(std::ostream& out, First&& first, Args&&... args) {
+    out << first;
+    return formatArgs(out, args...);
+}
+
+template <typename... Args> inline static std::string argsToString(Args&&... args) {
+    std::stringstream s;
+    formatArgs(s, args...);
+    return s.str();
+}
+
+template <typename... Msgs>
+inline static ErrorCode ksHandleHidlError(const Return<ErrorCode>& error, Msgs&&... msgs) {
+    if (!error.isOk()) {
+        ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
+              argsToString(msgs...).c_str());
+        return ErrorCode::UNKNOWN_ERROR;
+    }
+    return ErrorCode(error);
+}
+template <typename... Msgs>
+inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... msgs) {
+    if (!error.isOk()) {
+        ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
+              argsToString(msgs...).c_str());
+        return ErrorCode::UNKNOWN_ERROR;
+    }
+    return ErrorCode::OK;
+}
+
+#define KS_HANDLE_HIDL_ERROR(rc)                                                                   \
+    ::keystore::ksHandleHidlError(rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__)
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length,
+                                             bool inPlace = true) {
+    hidl_vec<uint8_t> result;
+    if (inPlace)
+        result.setToExternal(const_cast<unsigned char*>(data), length);
+    else {
+        result.resize(length);
+        memcpy(&result[0], data, length);
+    }
+    return result;
+}
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(
+        reinterpret_cast<uint8_t*>(const_cast<std::string::value_type*>(value.data())),
+        static_cast<size_t>(value.size()));
+    return result;
+}
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<uint8_t*>(blob.data()), static_cast<size_t>(blob.size()));
+    return result;
+}
+
+template <typename T, typename OutIter>
+inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
+    const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
+    return std::copy(value_ptr, value_ptr + sizeof(value), dest);
+}
+
+inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
+    static_assert(
+        std::is_same<decltype(token.hmac), ::android::hardware::hidl_array<uint8_t, 32>>::value,
+        "This function assumes token HMAC is 32 bytes, but it might not be.");
+    static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+                          sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+                          sizeof(token.timestamp) + 32 /* HMAC size */
+                      == sizeof(hw_auth_token_t),
+                  "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+    hidl_vec<uint8_t> result;
+    result.resize(sizeof(hw_auth_token_t));
+    auto pos = result.begin();
+    *pos++ = 0;  // Version byte
+    pos = copy_bytes_to_iterator(token.challenge, pos);
+    pos = copy_bytes_to_iterator(token.userId, pos);
+    pos = copy_bytes_to_iterator(token.authenticatorId, pos);
+    pos = copy_bytes_to_iterator(token.authenticatorType, pos);
+    pos = copy_bytes_to_iterator(token.timestamp, pos);
+    pos = std::copy(token.hmac.data(), token.hmac.data() + token.hmac.size(), pos);
+
+    return result;
+}
+
+inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) {
+    return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
+}
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
diff --git a/keystore/include/keystore/keystore_return_types.h b/keystore/include/keystore/keystore_return_types.h
new file mode 100644
index 0000000..70380c3
--- /dev/null
+++ b/keystore/include/keystore/keystore_return_types.h
@@ -0,0 +1,186 @@
+/*
+**
+** Copyright 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_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
+
+#include "keystore.h"
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+
+namespace keystore {
+
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+
+class KeyStoreServiceReturnCode;
+class KeyStoreNativeReturnCode;
+
+/**
+ * The keystore service return code is a bit tricky. It can return error codes from two name spaces:
+ * ErrorCode, which has negative error codes and use 0 for ERROR_OK;
+ * ResponseCode, which has positive error codes and uses 1 for NO_ERROR.
+ * This class can be initialized by both. And when accessed through the operator int32_t () it
+ * always returns ResponseCode::NO_ERROR (1) on success, even if it was initialized with
+ * ErrorCode::OK (0), because this is what (java) clients expect.
+ *
+ * !!! Do not confuse this with KeyStoreNativeReturnCode which always converts to 0 on success. !!!
+ */
+class KeyStoreServiceReturnCode {
+  public:
+    KeyStoreServiceReturnCode() : errorCode_(0) {}
+    KeyStoreServiceReturnCode(const ErrorCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+    KeyStoreServiceReturnCode(const ResponseCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+    KeyStoreServiceReturnCode(const KeyStoreServiceReturnCode& errorCode)
+        : errorCode_(errorCode.errorCode_) {}
+    KeyStoreServiceReturnCode(const KeyStoreNativeReturnCode& errorCode);
+    inline KeyStoreServiceReturnCode& operator=(const ErrorCode& errorCode) {
+        errorCode_ = int32_t(errorCode);
+        return *this;
+    }
+    inline KeyStoreServiceReturnCode& operator=(const ResponseCode& errorCode) {
+        errorCode_ = int32_t(errorCode);
+        return *this;
+    }
+    inline KeyStoreServiceReturnCode& operator=(const KeyStoreServiceReturnCode& errorCode) {
+        errorCode_ = errorCode.errorCode_;
+        return *this;
+    }
+    inline bool isOk() const {
+        return errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) ||
+               errorCode_ == static_cast<int32_t>(ErrorCode::OK);
+    }
+    inline operator int32_t() const {
+        if (!errorCode_) return static_cast<int32_t>(ResponseCode::NO_ERROR);
+        return errorCode_;
+    }
+    inline bool operator==(const ResponseCode& rhs) const {
+        return (rhs == ResponseCode::NO_ERROR &&
+                errorCode_ == static_cast<int32_t>(ErrorCode::OK)) ||
+               errorCode_ == int32_t(rhs);
+    }
+    inline bool operator==(const ErrorCode& rhs) const {
+        return (rhs == ErrorCode::OK &&
+                errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) ||
+               errorCode_ == int32_t(rhs);
+    }
+    inline bool operator!=(const ResponseCode& rhs) const { return !(*this == rhs); }
+    inline bool operator!=(const ErrorCode& rhs) const { return !(*this == rhs); }
+
+  private:
+    int32_t errorCode_;
+};
+
+inline bool operator==(const ResponseCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+    return rhs == lhs;
+}
+inline bool operator==(const ErrorCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+    return rhs == lhs;
+}
+inline bool operator!=(const ResponseCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+    return rhs != lhs;
+}
+inline bool operator!=(const ErrorCode& lhs, const KeyStoreServiceReturnCode& rhs) {
+    return rhs != lhs;
+}
+
+inline std::ostream& operator<<(std::ostream& out, const KeyStoreServiceReturnCode& error) {
+    return out << int32_t(error);
+}
+
+/**
+ * The keystore native return code is a bit tricky. It can return error codes from two name spaces:
+ * ErrorCode, which has negative error codes and use 0 for ERROR_OK;
+ * ResponseCode, which has positive error codes and uses 1 for NO_ERROR.
+ * This class can be initialized by both. And when accessed through the operator int32_t () it
+ * always returns ErrorCode::OK (0) on success, even if it was initialized with
+ * ResponseCode::NO_ERROR (1), because this is what (native) clients expect.
+ *
+ * !!! Do not this confuse with KeyStoreServiceReturnCode which always converts to 1 on success. !!!
+ */
+class KeyStoreNativeReturnCode {
+  public:
+    KeyStoreNativeReturnCode() : errorCode_(0) {}
+    KeyStoreNativeReturnCode(const ErrorCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+    KeyStoreNativeReturnCode(const ResponseCode& errorCode) : errorCode_(int32_t(errorCode)) {}
+    KeyStoreNativeReturnCode(const KeyStoreNativeReturnCode& errorCode)
+        : errorCode_(errorCode.errorCode_) {}
+    KeyStoreNativeReturnCode(const KeyStoreServiceReturnCode& errorcode);
+    inline KeyStoreNativeReturnCode& operator=(const ErrorCode& errorCode) {
+        errorCode_ = int32_t(errorCode);
+        return *this;
+    }
+    inline KeyStoreNativeReturnCode& operator=(const ResponseCode& errorCode) {
+        errorCode_ = int32_t(errorCode);
+        return *this;
+    }
+    inline KeyStoreNativeReturnCode& operator=(const KeyStoreNativeReturnCode& errorCode) {
+        errorCode_ = errorCode.errorCode_;
+        return *this;
+    }
+    inline bool isOk() const {
+        return errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) ||
+               errorCode_ == static_cast<int32_t>(ErrorCode::OK);
+    }
+    inline operator int32_t() const {
+        if (errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) {
+            return static_cast<int32_t>(ErrorCode::OK);
+        }
+        return errorCode_;
+    }
+    inline bool operator==(const ResponseCode& rhs) const {
+        return (rhs == ResponseCode::NO_ERROR &&
+                errorCode_ == static_cast<int32_t>(ErrorCode::OK)) ||
+               errorCode_ == int32_t(rhs);
+    }
+    inline bool operator==(const ErrorCode& rhs) const {
+        return (rhs == ErrorCode::OK &&
+                errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) ||
+               errorCode_ == int32_t(rhs);
+    }
+    inline bool operator!=(const ResponseCode& rhs) const { return !(*this == rhs); }
+    inline bool operator!=(const ErrorCode& rhs) const { return !(*this == rhs); }
+
+  private:
+    int32_t errorCode_;
+};
+
+inline bool operator==(const ResponseCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+    return rhs == lhs;
+}
+inline bool operator==(const ErrorCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+    return rhs == lhs;
+}
+inline bool operator!=(const ResponseCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+    return rhs != lhs;
+}
+inline bool operator!=(const ErrorCode& lhs, const KeyStoreNativeReturnCode& rhs) {
+    return rhs != lhs;
+}
+
+inline KeyStoreNativeReturnCode::KeyStoreNativeReturnCode(
+    const KeyStoreServiceReturnCode& errorCode)
+    : errorCode_(int32_t(errorCode)) {}
+inline KeyStoreServiceReturnCode::KeyStoreServiceReturnCode(
+    const KeyStoreNativeReturnCode& errorCode)
+    : errorCode_(int32_t(errorCode)) {}
+
+inline std::ostream& operator<<(std::ostream& out, const KeyStoreNativeReturnCode& error) {
+    return out << int32_t(error);
+}
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
diff --git a/keystore/include/keystore/utils.h b/keystore/include/keystore/utils.h
new file mode 100644
index 0000000..f95ae71
--- /dev/null
+++ b/keystore/include/keystore/utils.h
@@ -0,0 +1,96 @@
+// TODO: Insert description here. (generated by jdanis)
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
+
+#include <iterator>
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace security {
+
+/*
+ * This iterator abstracts from a collection of the form
+ * std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
+ * such that it is defined both for nulled outer pointer and
+ * nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
+ * like the end iterator yielding an empty collection. Nulled
+ * entries are skipped so that the iterator is always dereferencable unless
+ * it is equal to end.
+ * The default constructor always yields an iterator equal to end.
+ * The same iterator invalidation rules apply as they do for the iterators
+ * of the corresponding collection.
+ */
+template <typename T, template <typename...> class Coll = std::vector>
+class SharedNullableIterator {
+  public:
+    typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
+    typedef std::shared_ptr<CollectionType> CollectionPtr;
+
+    SharedNullableIterator() {}
+    SharedNullableIterator(const std::shared_ptr<CollectionType>& coll) : coll_(coll) { init(); }
+    SharedNullableIterator(std::shared_ptr<CollectionType>&& coll) : coll_(coll) { init(); }
+
+    SharedNullableIterator(const SharedNullableIterator& other)
+        : coll_(other.coll_), cur_(other.cur_) {}
+    SharedNullableIterator(SharedNullableIterator&& other)
+        : coll_(std::move(other.coll_)), cur_(std::move(other.cur_)) {}
+
+    SharedNullableIterator& operator++() {
+        inc();
+        return *this;
+    }
+    SharedNullableIterator operator++(int) {
+        SharedNullableIterator retval(*this);
+        ++(*this);
+        return retval;
+    }
+    T& operator*() const { return **cur_; }
+
+    T* operator->() const { return &**cur_; }
+
+    bool operator==(const SharedNullableIterator& other) const {
+        return cur_ == other.cur_ || (is_end() && other.is_end());
+    }
+    bool operator!=(const SharedNullableIterator& other) const { return !(*this == other); }
+
+    SharedNullableIterator& operator=(const SharedNullableIterator&) = default;
+    SharedNullableIterator& operator=(SharedNullableIterator&&) = default;
+
+  private:
+    inline bool is_end() const { return !coll_ || cur_ == coll_->end(); }
+    inline void inc() {
+        if (!is_end()) {
+            do {
+                ++cur_;
+                // move forward to the next non null member or stay at end
+            } while (cur_ != coll_->end() && !(*cur_));
+        }
+    }
+    void init() {
+        if (coll_) {
+            // move forward to the first non null member
+            for (cur_ = coll_->begin(); cur_ != coll_->end() && !(*cur_); ++cur_) {
+            }
+        }
+    }
+
+    CollectionPtr coll_;
+    typename CollectionType::iterator cur_;
+};
+
+}  // namespace security
+}  // namespace android
+
+namespace std {
+template <typename T, template <typename...> class COLL>
+struct iterator_traits<android::security::SharedNullableIterator<T, COLL>> {
+    typedef T& reference;
+    typedef T value_type;
+    typedef T* pointer;
+    typedef forward_iterator_tag iterator_category;
+};
+}
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index d68c367..248fa00 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -14,39 +14,112 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "keystore"
+
 #include "key_store_service.h"
 
 #include <fcntl.h>
 #include <sys/stat.h>
 
+#include <algorithm>
 #include <sstream>
 
+#include <binder/IInterface.h>
 #include <binder/IPCThreadState.h>
+#include <binder/IPermissionController.h>
+#include <binder/IServiceManager.h>
 
 #include <private/android_filesystem_config.h>
 
-#include <hardware/keymaster_defs.h>
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
 
 #include "defaults.h"
+#include "keystore_attestation_id.h"
+#include "keystore_keymaster_enforcement.h"
 #include "keystore_utils.h"
+#include <keystore/keystore_hidl_support.h>
 
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
-using keymaster::TAG_APPLICATION_DATA;
-using keymaster::TAG_APPLICATION_ID;
+namespace keystore {
 
-namespace android {
+using namespace android;
 
-const size_t MAX_OPERATIONS = 15;
+namespace {
+
+constexpr size_t kMaxOperations = 15;
+constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
+const char* kTimestampFilePath = "timestamp";
 
 struct BIGNUM_Delete {
     void operator()(BIGNUM* p) const { BN_free(p); }
 };
 typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
 
-struct Malloc_Delete {
-    void operator()(uint8_t* p) const { free(p); }
-};
+bool containsTag(const hidl_vec<KeyParameter>& params, Tag tag) {
+    return params.end() != std::find_if(params.begin(), params.end(),
+                                        [&](auto& param) { return param.tag == tag; });
+}
+
+bool isAuthenticationBound(const hidl_vec<KeyParameter>& params) {
+    return !containsTag(params, Tag::NO_AUTH_REQUIRED);
+}
+
+std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() {
+    struct stat sbuf;
+    if (stat(kTimestampFilePath, &sbuf) == 0) {
+        double diff_secs = difftime(time(NULL), sbuf.st_ctime);
+        return {ResponseCode::NO_ERROR, diff_secs < kIdRotationPeriod};
+    }
+
+    if (errno != ENOENT) {
+        ALOGE("Failed to stat \"timestamp\" file, with error %d", errno);
+        return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
+    }
+
+    int fd = creat(kTimestampFilePath, 0600);
+    if (fd < 0) {
+        ALOGE("Couldn't create \"timestamp\" file, with error %d", errno);
+        return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
+    }
+
+    if (close(fd)) {
+        ALOGE("Couldn't close \"timestamp\" file, with error %d", errno);
+        return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
+    }
+
+    return {ResponseCode::NO_ERROR, true};
+}
+
+constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024;
+
+KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, AuthorizationSet* params) {
+    KeyStoreServiceReturnCode responseCode;
+    bool factoryResetSinceIdRotation;
+    std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation();
+
+    if (!responseCode.isOk()) return responseCode;
+    if (factoryResetSinceIdRotation) params->push_back(TAG_RESET_SINCE_ID_ROTATION);
+
+    auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
+    if (!asn1_attestation_id_result.isOk()) {
+        ALOGE("failed to gather attestation_id");
+        return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING;
+    }
+    std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;
+
+    /*
+     * The attestation application ID cannot be longer than
+     * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, so we truncate if too long.
+     */
+    if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) {
+        asn1_attestation_id.resize(KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE);
+    }
+
+    params->push_back(TAG_ATTESTATION_APPLICATION_ID, asn1_attestation_id);
+
+    return ResponseCode::NO_ERROR;
+}
+
+}  // anonymous namespace
 
 void KeyStoreService::binderDied(const wp<IBinder>& who) {
     auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
@@ -55,116 +128,125 @@
     }
 }
 
-int32_t KeyStoreService::getState(int32_t userId) {
+KeyStoreServiceReturnCode KeyStoreService::getState(int32_t userId) {
     if (!checkBinderPermission(P_GET_STATE)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
-    return mKeyStore->getState(userId);
+    return ResponseCode(mKeyStore->getState(userId));
 }
 
-int32_t KeyStoreService::get(const String16& name, int32_t uid, uint8_t** item,
-                             size_t* itemLength) {
+KeyStoreServiceReturnCode KeyStoreService::get(const String16& name, int32_t uid,
+                                               hidl_vec<uint8_t>* item) {
     uid_t targetUid = getEffectiveUid(uid);
     if (!checkBinderPermission(P_GET, targetUid)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     String8 name8(name);
     Blob keyBlob;
 
-    ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
-    if (responseCode != ::NO_ERROR) {
-        *item = NULL;
-        *itemLength = 0;
-        return responseCode;
+    KeyStoreServiceReturnCode rc =
+        mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
+    if (!rc.isOk()) {
+        if (item) *item = hidl_vec<uint8_t>();
+        return rc;
     }
 
-    *item = (uint8_t*)malloc(keyBlob.getLength());
-    memcpy(*item, keyBlob.getValue(), keyBlob.getLength());
-    *itemLength = keyBlob.getLength();
+    // Do not replace this with "if (item) *item = blob2hidlVec(keyBlob)"!
+    // blob2hidlVec creates a hidl_vec<uint8_t> that references, but not owns, the data in keyBlob
+    // the subsequent assignment (*item = resultBlob) makes a deep copy, so that *item will own the
+    // corresponding resources.
+    auto resultBlob = blob2hidlVec(keyBlob);
+    if (item) {
+        *item = resultBlob;
+    }
 
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::insert(const String16& name, const uint8_t* item, size_t itemLength,
-                                int targetUid, int32_t flags) {
+KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
+                                                  const hidl_vec<uint8_t>& item, int targetUid,
+                                                  int32_t flags) {
     targetUid = getEffectiveUid(targetUid);
-    int32_t result =
+    auto result =
         checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (result != ::NO_ERROR) {
+    if (!result.isOk()) {
         return result;
     }
 
     String8 name8(name);
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_GENERIC));
 
-    Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
+    Blob keyBlob(&item[0], item.size(), 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) {
+KeyStoreServiceReturnCode KeyStoreService::del(const String16& name, int targetUid) {
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_DELETE, targetUid)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
     String8 name8(name);
+    ALOGI("del %s %d", name8.string(), targetUid);
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
-    int32_t result = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
-    if (result != ::NO_ERROR) {
+    ResponseCode result = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
+    if (result != ResponseCode::NO_ERROR) {
         return result;
     }
 
     // Also delete any characteristics files
-    String8 chrFilename(mKeyStore->getKeyNameForUidWithDir(
-        name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
+    String8 chrFilename(
+        mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
     return mKeyStore->del(chrFilename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
 }
 
-int32_t KeyStoreService::exist(const String16& name, int targetUid) {
+KeyStoreServiceReturnCode KeyStoreService::exist(const String16& name, int targetUid) {
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_EXIST, targetUid)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     String8 name8(name);
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
 
     if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
     }
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::list(const String16& prefix, int targetUid, Vector<String16>* matches) {
+KeyStoreServiceReturnCode KeyStoreService::list(const String16& prefix, int targetUid,
+                                                Vector<String16>* matches) {
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_LIST, targetUid)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
     const String8 prefix8(prefix);
     String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid, TYPE_ANY));
 
-    if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ::NO_ERROR) {
-        return ::SYSTEM_ERROR;
+    if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
+        return ResponseCode::SYSTEM_ERROR;
     }
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::reset() {
+KeyStoreServiceReturnCode KeyStoreService::reset() {
     if (!checkBinderPermission(P_RESET)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     mKeyStore->resetUser(get_user_id(callingUid), false);
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password) {
+KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
+                                                                 const String16& password) {
     if (!checkBinderPermission(P_PASSWORD)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     const String8 password8(password);
@@ -175,7 +257,7 @@
     if (password.size() == 0) {
         ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
         mKeyStore->resetUser(userId, true);
-        return ::NO_ERROR;
+        return ResponseCode::NO_ERROR;
     } else {
         switch (mKeyStore->getState(userId)) {
         case ::STATE_UNINITIALIZED: {
@@ -193,13 +275,13 @@
             return mKeyStore->initializeUser(password8, userId);
         }
         }
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
 }
 
-int32_t KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
+KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
     if (!checkBinderPermission(P_USER_CHANGED)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     // Sanity check that the new user has an empty keystore.
@@ -215,37 +297,37 @@
         // parent profile, forever.
         return mKeyStore->copyMasterKey(parentId, userId);
     } else {
-        return ::NO_ERROR;
+        return ResponseCode::NO_ERROR;
     }
 }
 
-int32_t KeyStoreService::onUserRemoved(int32_t userId) {
+KeyStoreServiceReturnCode KeyStoreService::onUserRemoved(int32_t userId) {
     if (!checkBinderPermission(P_USER_CHANGED)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     mKeyStore->resetUser(userId, false);
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::lock(int32_t userId) {
+KeyStoreServiceReturnCode KeyStoreService::lock(int32_t userId) {
     if (!checkBinderPermission(P_LOCK)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     State state = mKeyStore->getState(userId);
     if (state != ::STATE_NO_ERROR) {
         ALOGD("calling lock in state: %d", state);
-        return state;
+        return ResponseCode(state);
     }
 
     mKeyStore->lock(userId);
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::unlock(int32_t userId, const String16& pw) {
+KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16& pw) {
     if (!checkBinderPermission(P_UNLOCK)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     State state = mKeyStore->getState(userId);
@@ -261,7 +343,7 @@
             ALOGE("unlock called on keystore in unknown state: %d", state);
             break;
         }
-        return state;
+        return ResponseCode(state);
     }
 
     const String8 password8(pw);
@@ -277,43 +359,44 @@
     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) {
+KeyStoreServiceReturnCode 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 =
+    auto result =
         checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (result != ::NO_ERROR) {
+    if (!result.isOk()) {
         return result;
     }
 
-    KeymasterArguments params;
-    add_legacy_key_authorizations(keyType, &params.params);
+    keystore::AuthorizationSet params;
+    add_legacy_key_authorizations(keyType, &params);
 
     switch (keyType) {
     case EVP_PKEY_EC: {
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+        params.push_back(TAG_ALGORITHM, 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;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+        params.push_back(TAG_KEY_SIZE, keySize);
         break;
     }
     case EVP_PKEY_RSA: {
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+        params.push_back(TAG_ALGORITHM, 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;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+        params.push_back(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;
+            return ResponseCode::SYSTEM_ERROR;
         } else if (args->size() == 1) {
             const sp<KeystoreArg>& expArg = args->itemAt(0);
             if (expArg != NULL) {
@@ -321,84 +404,88 @@
                     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;
+                    return ResponseCode::SYSTEM_ERROR;
                 }
                 exponent = BN_get_word(pubExpBn.get());
                 if (exponent == 0xFFFFFFFFL) {
                     ALOGW("cannot represent public exponent as a long value");
-                    return ::SYSTEM_ERROR;
+                    return ResponseCode::SYSTEM_ERROR;
                 }
             } else {
                 ALOGW("public exponent not read");
-                return ::SYSTEM_ERROR;
+                return ResponseCode::SYSTEM_ERROR;
             }
         }
-        params.params.push_back(keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, exponent));
+        params.push_back(TAG_RSA_PUBLIC_EXPONENT, exponent);
         break;
     }
     default: {
         ALOGW("Unsupported key type %d", keyType);
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     }
 
-    int32_t rc = generateKey(name, params, NULL, 0, targetUid, flags,
-                             /*outCharacteristics*/ NULL);
-    if (rc != ::NO_ERROR) {
-        ALOGW("generate failed: %d", rc);
+    auto rc = generateKey(name, params.hidl_data(), hidl_vec<uint8_t>(), targetUid, flags,
+                          /*outCharacteristics*/ NULL);
+    if (!rc.isOk()) {
+        ALOGW("generate failed: %d", int32_t(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;
+KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
+                                                  const hidl_vec<uint8_t>& data, int targetUid,
+                                                  int32_t flags) {
 
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, length));
+    const uint8_t* ptr = &data[0];
+
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, data.size()));
     if (!pkcs8.get()) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
     if (!pkey.get()) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     int type = EVP_PKEY_type(pkey->type);
-    KeymasterArguments params;
-    add_legacy_key_authorizations(type, &params.params);
+    AuthorizationSet params;
+    add_legacy_key_authorizations(type, &params);
     switch (type) {
     case EVP_PKEY_RSA:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+        params.push_back(TAG_ALGORITHM, Algorithm::RSA);
         break;
     case EVP_PKEY_EC:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+        params.push_back(TAG_ALGORITHM, Algorithm::EC);
         break;
     default:
         ALOGW("Unsupported key type %d", type);
-        return ::SYSTEM_ERROR;
+        return ResponseCode::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);
+
+    auto rc = importKey(name, params.hidl_data(), KeyFormat::PKCS8, data, targetUid, flags,
+                        /*outCharacteristics*/ NULL);
+
+    if (!rc.isOk()) {
+        ALOGW("importKey failed: %d", int32_t(rc));
     }
     return translateResultToLegacyResult(rc);
 }
 
-int32_t KeyStoreService::sign(const String16& name, const uint8_t* data, size_t length,
-                              uint8_t** out, size_t* outLength) {
+KeyStoreServiceReturnCode KeyStoreService::sign(const String16& name, const hidl_vec<uint8_t>& data,
+                                                hidl_vec<uint8_t>* out) {
     if (!checkBinderPermission(P_SIGN)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
-    return doLegacySignVerify(name, data, length, out, outLength, NULL, 0, KM_PURPOSE_SIGN);
+    return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
 }
 
-int32_t KeyStoreService::verify(const String16& name, const uint8_t* data, size_t dataLength,
-                                const uint8_t* signature, size_t signatureLength) {
+KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
+                                                  const hidl_vec<uint8_t>& data,
+                                                  const hidl_vec<uint8_t>& signature) {
     if (!checkBinderPermission(P_VERIFY)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
-    return doLegacySignVerify(name, data, dataLength, NULL, NULL, signature, signatureLength,
-                              KM_PURPOSE_VERIFY);
+    return doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY);
 }
 
 /*
@@ -412,23 +499,23 @@
  * "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) {
+KeyStoreServiceReturnCode KeyStoreService::get_pubkey(const String16& name,
+                                                      hidl_vec<uint8_t>* pubKey) {
     ExportResult result;
-    exportKey(name, KM_KEY_FORMAT_X509, NULL, NULL, UID_SELF, &result);
-    if (result.resultCode != ::NO_ERROR) {
-        ALOGW("export failed: %d", result.resultCode);
+    exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
+    if (!result.resultCode.isOk()) {
+        ALOGW("export failed: %d", int32_t(result.resultCode));
         return translateResultToLegacyResult(result.resultCode);
     }
 
-    *pubkey = result.exportData.release();
-    *pubkeyLength = result.dataLength;
-    return ::NO_ERROR;
+    if (pubKey) *pubKey = std::move(result.exportData);
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::grant(const String16& name, int32_t granteeUid) {
+KeyStoreServiceReturnCode KeyStoreService::grant(const String16& name, int32_t granteeUid) {
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
-    if (result != ::NO_ERROR) {
+    auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+    if (!result.isOk()) {
         return result;
     }
 
@@ -436,17 +523,17 @@
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
 
     if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
     }
 
     mKeyStore->addGrant(filename.string(), granteeUid);
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
+KeyStoreServiceReturnCode KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
-    if (result != ::NO_ERROR) {
+    auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+    if (!result.isOk()) {
         return result;
     }
 
@@ -454,10 +541,11 @@
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
 
     if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
     }
 
-    return mKeyStore->removeGrant(filename.string(), granteeUid) ? ::NO_ERROR : ::KEY_NOT_FOUND;
+    return mKeyStore->removeGrant(filename.string(), granteeUid) ? ResponseCode::NO_ERROR
+                                                                 : ResponseCode::KEY_NOT_FOUND;
 }
 
 int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
@@ -493,26 +581,26 @@
 }
 
 // TODO(tuckeris): This is dead code, remove it.  Don't bother copying over key characteristics here
-int32_t KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-                                   int32_t destUid) {
+KeyStoreServiceReturnCode 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;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     State state = mKeyStore->getState(get_user_id(callingUid));
     if (!isKeystoreUnlocked(state)) {
         ALOGD("calling duplicate in state: %d", state);
-        return state;
+        return ResponseCode(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;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     if (destUid == -1) {
@@ -524,12 +612,12 @@
             ALOGD("can only duplicate from caller to other or to same uid: "
                   "calling=%d, srcUid=%d, destUid=%d",
                   callingUid, srcUid, destUid);
-            return ::PERMISSION_DENIED;
+            return ResponseCode::PERMISSION_DENIED;
         }
 
         if (!is_granted_to(callingUid, destUid)) {
             ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
-            return ::PERMISSION_DENIED;
+            return ResponseCode::PERMISSION_DENIED;
         }
     }
 
@@ -541,13 +629,13 @@
 
     if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
         ALOGD("destination already exists: %s", targetFile.string());
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
 
     Blob keyBlob;
     ResponseCode responseCode =
         mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
-    if (responseCode != ::NO_ERROR) {
+    if (responseCode != ResponseCode::NO_ERROR) {
         return responseCode;
     }
 
@@ -558,159 +646,146 @@
     return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
 }
 
-int32_t KeyStoreService::clear_uid(int64_t targetUid64) {
+KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
     uid_t targetUid = getEffectiveUid(targetUid64);
     if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
+    ALOGI("clear_uid %" PRId64, targetUid64);
 
     String8 prefix = String8::format("%u_", targetUid);
     Vector<String16> aliases;
-    if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ::NO_ERROR) {
-        return ::SYSTEM_ERROR;
+    if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
+        return ResponseCode::SYSTEM_ERROR;
     }
 
     for (uint32_t i = 0; i < aliases.size(); i++) {
         String8 name8(aliases[i]);
         String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
+
+        if (get_app_id(targetUid) == AID_SYSTEM) {
+            Blob keyBlob;
+            ResponseCode responseCode =
+                mKeyStore->get(filename.string(), &keyBlob, ::TYPE_ANY, get_user_id(targetUid));
+            if (responseCode == ResponseCode::NO_ERROR && keyBlob.isCriticalToDeviceEncryption()) {
+                // Do not clear keys critical to device encryption under system uid.
+                continue;
+            }
+        }
+
         mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
 
         // del() will fail silently if no cached characteristics are present for this alias.
-        String8 chr_filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid,
-            ::TYPE_KEY_CHARACTERISTICS));
+        String8 chr_filename(
+            mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
         mKeyStore->del(chr_filename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
     }
-    return ::NO_ERROR;
+    return ResponseCode::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;
+KeyStoreServiceReturnCode KeyStoreService::addRngEntropy(const hidl_vec<uint8_t>& entropy) {
+    const auto& device = mKeyStore->getDevice();
+    return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
 }
 
-int32_t KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
-                                     const uint8_t* entropy, size_t entropyLength, int uid,
-                                     int flags, KeyCharacteristics* outCharacteristics) {
+KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
+                                                       const hidl_vec<KeyParameter>& params,
+                                                       const hidl_vec<uint8_t>& entropy, int uid,
+                                                       int flags,
+                                                       KeyCharacteristics* outCharacteristics) {
     uid = getEffectiveUid(uid);
-    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (rc != ::NO_ERROR) {
+    KeyStoreServiceReturnCode rc =
+        checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (!rc.isOk()) {
         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;
+    if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
+        ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
+        return ResponseCode::PERMISSION_DENIED;
     }
 
-    // Capture characteristics before they're potentially stripped by the device
-    AuthorizationSet keyCharacteristics(opParams.data(), opParams.size());
-    if (keyCharacteristics.is_valid() != AuthorizationSet::Error::OK) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
+        if (!checkBinderPermission(P_GEN_UNIQUE_ID)) return ResponseCode::PERMISSION_DENIED;
     }
-    UniquePtr<uint8_t[]> kc_buf;
-    kc_buf.reset(new (std::nothrow) uint8_t[keyCharacteristics.SerializedSize()]);
-    if (!kc_buf.get()) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-    keyCharacteristics.Serialize(kc_buf.get(), kc_buf.get() + keyCharacteristics.SerializedSize());
+
+    bool usingFallback = false;
+    auto& dev = mKeyStore->getDevice();
+    AuthorizationSet keyCharacteristics = params;
 
     // 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) {
+    rc = addRngEntropy(entropy);
+    if (!rc.isOk()) {
         return rc;
     }
 
-    // Write the key:
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
+    KeyStoreServiceReturnCode error;
+    auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
+                       const KeyCharacteristics& keyCharacteristics) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
+        if (outCharacteristics) *outCharacteristics = keyCharacteristics;
 
-    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
-    keyBlob.setFallback(isFallback);
-    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+        // Write the key
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
 
-    free(const_cast<uint8_t*>(blob.key_material));
-    rc = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+        Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
+        keyBlob.setFallback(usingFallback);
+        keyBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
+        if (isAuthenticationBound(params) && !keyBlob.isCriticalToDeviceEncryption()) {
+            keyBlob.setSuperEncrypted(true);
+        }
+        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
 
-    if (rc != ::NO_ERROR) {
+        error = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+    };
+
+    rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params, hidl_cb));
+    if (!rc.isOk()) {
         return rc;
     }
+    if (!error.isOk()) {
+        ALOGE("Failed to generate key -> falling back to software keymaster");
+        usingFallback = true;
+        auto fallback = mKeyStore->getFallbackDevice();
+        if (!fallback.isOk()) {
+            return error;
+        }
+        rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params, hidl_cb));
+        if (!rc.isOk()) {
+            return rc;
+        }
+        if (!error.isOk()) {
+            return error;
+        }
+    }
 
     // Write the characteristics:
+    String8 name8(name);
     String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
 
-    Blob charBlob(kc_buf.get(), keyCharacteristics.SerializedSize(),
-        NULL, 0, ::TYPE_KEY_CHARACTERISTICS);
-    charBlob.setFallback(isFallback);
+    std::stringstream kc_stream;
+    keyCharacteristics.Serialize(&kc_stream);
+    if (kc_stream.bad()) {
+        return ResponseCode::SYSTEM_ERROR;
+    }
+    auto kc_buf = kc_stream.str();
+    Blob charBlob(reinterpret_cast<const uint8_t*>(kc_buf.data()), kc_buf.size(), NULL, 0,
+                  ::TYPE_KEY_CHARACTERISTICS);
+    charBlob.setFallback(usingFallback);
     charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
 
     return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
 }
 
-int32_t KeyStoreService::getKeyCharacteristics(const String16& name,
-                                               const keymaster_blob_t* clientId,
-                                               const keymaster_blob_t* appData, int32_t uid,
-                                               KeyCharacteristics* outCharacteristics) {
+KeyStoreServiceReturnCode
+KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData, int32_t uid,
+                                       KeyCharacteristics* outCharacteristics) {
     if (!outCharacteristics) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+        return ErrorCode::UNEXPECTED_NULL_POINTER;
     }
 
     uid_t targetUid = getEffectiveUid(uid);
@@ -718,330 +793,368 @@
     if (!is_granted_to(callingUid, targetUid)) {
         ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
               targetUid);
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
 
     Blob keyBlob;
     String8 name8(name);
-    int rc;
 
-    ResponseCode responseCode =
+    KeyStoreServiceReturnCode rc =
         mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        return responseCode;
+    if (!rc.isOk()) {
+        return rc;
     }
-    keymaster_key_blob_t key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
-    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
-    keymaster_key_characteristics_t out = {};
-    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_KEY_REQUIRES_UPGRADE) {
-        AuthorizationSet upgradeParams;
-        if (clientId && clientId->data && clientId->data_length) {
-            upgradeParams.push_back(TAG_APPLICATION_ID, *clientId);
+
+    auto hidlKeyBlob = blob2hidlVec(keyBlob);
+    auto& dev = mKeyStore->getDevice(keyBlob);
+
+    KeyStoreServiceReturnCode error;
+
+    auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
         }
-        if (appData && appData->data && appData->data_length) {
-            upgradeParams.push_back(TAG_APPLICATION_DATA, *appData);
+        *outCharacteristics = keyCharacteristics;
+    };
+
+    rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
+    if (!rc.isOk()) {
+        return rc;
+    }
+
+    if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
+        AuthorizationSet upgradeParams;
+        if (clientId.size()) {
+            upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+        }
+        if (appData.size()) {
+            upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
         }
         rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
-        if (rc != ::NO_ERROR) {
+        if (!rc.isOk()) {
             return rc;
         }
-        key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
-        rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
-    }
-    if (rc != KM_ERROR_OK) {
-        return rc;
-    }
 
-    outCharacteristics->characteristics = out;
-    return ::NO_ERROR;
+        auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
+
+        rc = KS_HANDLE_HIDL_ERROR(
+            dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
+        if (!rc.isOk()) {
+            return rc;
+        }
+        // Note that, on success, "error" will have been updated by the hidlCB callback.
+        // So it is fine to return "error" below.
+    }
+    return 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) {
+KeyStoreServiceReturnCode
+KeyStoreService::importKey(const String16& name, const hidl_vec<KeyParameter>& params,
+                           KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid, int flags,
+                           KeyCharacteristics* outCharacteristics) {
     uid = getEffectiveUid(uid);
-    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (rc != ::NO_ERROR) {
+    KeyStoreServiceReturnCode rc =
+        checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (!rc.isOk()) {
         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 ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
+        ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
+        return ResponseCode::PERMISSION_DENIED;
     }
 
-    // Capture characteristics before they're potentially stripped
-    AuthorizationSet keyCharacteristics(opParams.data(), opParams.size());
-    if (keyCharacteristics.is_valid() != AuthorizationSet::Error::OK) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-    UniquePtr<uint8_t[]> kc_buf;
-    kc_buf.reset(new (std::nothrow) uint8_t[keyCharacteristics.SerializedSize()]);
-    if (!kc_buf.get()) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-    keyCharacteristics.Serialize(kc_buf.get(), kc_buf.get() + keyCharacteristics.SerializedSize());
+    bool usingFallback = false;
+    auto& dev = mKeyStore->getDevice();
 
-    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;
-    }
-
-    // Write the key:
     String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
 
-    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
-    keyBlob.setFallback(isFallback);
-    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+    KeyStoreServiceReturnCode error;
 
-    free(const_cast<uint8_t*>(blob.key_material));
-    rc = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+    auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+                      const KeyCharacteristics& keyCharacteristics) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
 
-    if (rc != ::NO_ERROR) {
+        if (outCharacteristics) *outCharacteristics = keyCharacteristics;
+
+        // Write the key:
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
+
+        Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
+        ksBlob.setFallback(usingFallback);
+        ksBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
+        if (isAuthenticationBound(params) && !ksBlob.isCriticalToDeviceEncryption()) {
+            ksBlob.setSuperEncrypted(true);
+        }
+        ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+        error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(uid));
+    };
+
+    rc = KS_HANDLE_HIDL_ERROR(dev->importKey(params, format, keyData, hidlCb));
+    // possible hidl error
+    if (!rc.isOk()) {
         return rc;
     }
+    // now check error from callback
+    if (!error.isOk()) {
+        ALOGE("Failed to import key -> falling back to software keymaster");
+        usingFallback = true;
+        auto fallback = mKeyStore->getFallbackDevice();
+        if (!fallback.isOk()) {
+            return error;
+        }
+        rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params, format, keyData, hidlCb));
+        // possible hidl error
+        if (!rc.isOk()) {
+            return rc;
+        }
+        // now check error from callback
+        if (!error.isOk()) {
+            return error;
+        }
+    }
 
     // Write the characteristics:
     String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
 
-    Blob charBlob(kc_buf.get(), keyCharacteristics.SerializedSize(),
-        NULL, 0, ::TYPE_KEY_CHARACTERISTICS);
-    charBlob.setFallback(isFallback);
+    AuthorizationSet opParams = params;
+    std::stringstream kcStream;
+    opParams.Serialize(&kcStream);
+    if (kcStream.bad()) return ResponseCode::SYSTEM_ERROR;
+    auto kcBuf = kcStream.str();
+
+    Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
+                  ::TYPE_KEY_CHARACTERISTICS);
+    charBlob.setFallback(usingFallback);
     charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
 
     return mKeyStore->put(cFilename.string(), &charBlob, 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,
+void KeyStoreService::exportKey(const String16& name, KeyFormat format,
+                                const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
                                 int32_t uid, ExportResult* result) {
 
     uid_t targetUid = getEffectiveUid(uid);
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     if (!is_granted_to(callingUid, targetUid)) {
         ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
-        result->resultCode = ::PERMISSION_DENIED;
+        result->resultCode = ResponseCode::PERMISSION_DENIED;
         return;
     }
 
     Blob keyBlob;
     String8 name8(name);
-    int rc;
 
-    ResponseCode responseCode =
-        mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        result->resultCode = responseCode;
+    result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
+    if (!result->resultCode.isOk()) {
         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);
-    if (rc == KM_ERROR_KEY_REQUIRES_UPGRADE) {
-        AuthorizationSet upgradeParams;
-        if (clientId && clientId->data && clientId->data_length) {
-            upgradeParams.push_back(TAG_APPLICATION_ID, *clientId);
-        }
-        if (appData && appData->data && appData->data_length) {
-            upgradeParams.push_back(TAG_APPLICATION_DATA, *appData);
-        }
-        rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
-        if (rc != ::NO_ERROR) {
-            result->resultCode = rc;
+
+    auto key = blob2hidlVec(keyBlob);
+    auto& dev = mKeyStore->getDevice(keyBlob);
+
+    auto hidlCb = [&](ErrorCode ret, const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
+        result->resultCode = ret;
+        if (!result->resultCode.isOk()) {
             return;
         }
-        key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
-        rc = dev->export_key(dev, format, &key, clientId, appData, &output);
+        result->exportData = keyMaterial;
+    };
+    KeyStoreServiceReturnCode rc =
+        KS_HANDLE_HIDL_ERROR(dev->exportKey(format, key, clientId, appData, hidlCb));
+    // Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
+    // callback hidlCb.
+    if (!rc.isOk()) {
+        result->resultCode = rc;
     }
 
-    result->exportData.reset(const_cast<uint8_t*>(output.data));
-    result->dataLength = output.data_length;
-    result->resultCode = rc ? rc : ::NO_ERROR;
+    if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
+        AuthorizationSet upgradeParams;
+        if (clientId.size()) {
+            upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+        }
+        if (appData.size()) {
+            upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
+        }
+        result->resultCode = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
+        if (!result->resultCode.isOk()) {
+            return;
+        }
+
+        auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
+
+        result->resultCode = KS_HANDLE_HIDL_ERROR(
+            dev->exportKey(format, upgradedHidlKeyBlob, clientId, appData, hidlCb));
+        if (!result->resultCode.isOk()) {
+            return;
+        }
+    }
 }
 
-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, int32_t uid, OperationResult* result) {
+static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
+    if (token) {
+        params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
+    }
+}
+
+void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
+                            bool pruneable, const hidl_vec<KeyParameter>& params,
+                            const hidl_vec<uint8_t>& entropy, int32_t uid,
+                            OperationResult* result) {
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     uid_t targetUid = getEffectiveUid(uid);
     if (!is_granted_to(callingUid, targetUid)) {
         ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid);
-        result->resultCode = ::PERMISSION_DENIED;
+        result->resultCode = ResponseCode::PERMISSION_DENIED;
         return;
     }
     if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
         ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
-        result->resultCode = ::PERMISSION_DENIED;
+        result->resultCode = ResponseCode::PERMISSION_DENIED;
         return;
     }
-    if (!checkAllowedOperationParams(params.params)) {
-        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+    if (!checkAllowedOperationParams(params)) {
+        result->resultCode = ErrorCode::INVALID_ARGUMENT;
         return;
     }
     Blob keyBlob;
     String8 name8(name);
-    ResponseCode responseCode =
-        mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        result->resultCode = responseCode;
+    result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
+    if (result->resultCode == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
+        result->resultCode = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+    }
+    if (!result->resultCode.isOk()) {
         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 == KM_ERROR_KEY_REQUIRES_UPGRADE) {
-        int32_t rc = upgradeKeyBlob(name, targetUid,
-                                    AuthorizationSet(opParams.data(), opParams.size()), &keyBlob);
-        if (rc != ::NO_ERROR) {
-            result->resultCode = rc;
+
+    auto key = blob2hidlVec(keyBlob);
+    auto& dev = mKeyStore->getDevice(keyBlob);
+    AuthorizationSet opParams = params;
+    KeyCharacteristics characteristics;
+    result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
+
+    if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
+        result->resultCode = upgradeKeyBlob(name, targetUid, opParams, &keyBlob);
+        if (!result->resultCode.isOk()) {
             return;
         }
-        key = {keyBlob.getValue(), static_cast<size_t>(keyBlob.getLength())};
-        err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
+        key = blob2hidlVec(keyBlob);
+        result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
     }
-    if (err) {
-        result->resultCode = err;
+    if (!result->resultCode.isOk()) {
         return;
     }
-    const hw_auth_token_t* authToken = NULL;
+
+    const HardwareAuthToken* authToken = NULL;
 
     // Merge these characteristics with the ones cached when the key was generated or imported
     Blob charBlob;
     AuthorizationSet persistedCharacteristics;
-    responseCode = mKeyStore->getKeyForName(&charBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
-    if (responseCode == ::NO_ERROR) {
-        const uint8_t* serializedCharacteristics = charBlob.getValue();
-        persistedCharacteristics.Deserialize(&serializedCharacteristics,
-            serializedCharacteristics + charBlob.getLength());
+    result->resultCode =
+        mKeyStore->getKeyForName(&charBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
+    if (result->resultCode.isOk()) {
+        // TODO write one shot stream buffer to avoid copying (twice here)
+        std::string charBuffer(reinterpret_cast<const char*>(charBlob.getValue()),
+                               charBlob.getLength());
+        std::stringstream charStream(charBuffer);
+        persistedCharacteristics.Deserialize(&charStream);
     } else {
         ALOGD("Unable to read cached characteristics for key");
     }
 
     // Replace the sw_enforced set with those persisted to disk, minus hw_enforced
-    persistedCharacteristics.Union(characteristics.get()->sw_enforced);
-    persistedCharacteristics.Difference(characteristics.get()->hw_enforced);
-    persistedCharacteristics.CopyToParamSet(&characteristics.get()->sw_enforced);
+    AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
+    AuthorizationSet teeEnforced = characteristics.teeEnforced;
+    persistedCharacteristics.Union(softwareEnforced);
+    persistedCharacteristics.Subtract(teeEnforced);
+    characteristics.softwareEnforced = persistedCharacteristics.hidl_data();
 
-    int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
+    result->resultCode = getAuthToken(characteristics, 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);
+    if (!result->resultCode.isOk() && result->resultCode != ResponseCode::OP_AUTH_NEEDED) return;
+
+    addAuthTokenToParams(&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;
+    if (entropy.size()) {
+        result->resultCode = addRngEntropy(entropy);
+        if (!result->resultCode.isOk()) {
             return;
         }
     }
-    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
 
     // Create a keyid for this key.
-    keymaster::km_id_t keyid;
+    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;
+        result->resultCode = ErrorCode::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;
+    AuthorizationSet key_auths = characteristics.teeEnforced;
+    key_auths.append(&characteristics.softwareEnforced[0],
+                     &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);
+
+    result->resultCode = enforcement_policy.AuthorizeOperation(
+        purpose, keyid, key_auths, opParams, 0 /* op_handle */, true /* is_begin_operation */);
+    if (!result->resultCode.isOk()) {
         return;
     }
 
-    keymaster_key_param_set_t outParams = {NULL, 0};
-
-    // If there are more than MAX_OPERATIONS, abort the oldest operation that was started as
+    // If there are more than kMaxOperations, abort the oldest operation that was started as
     // pruneable.
-    while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) {
+    while (mOperationMap.getOperationCount() >= kMaxOperations) {
         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);
+    auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
+                      uint64_t operationHandle) {
+        result->resultCode = ret;
+        if (!result->resultCode.isOk()) {
+            return;
+        }
+        result->handle = operationHandle;
+        result->outParams = outParams;
+    };
+
+    ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
+    if (rc != ErrorCode::OK) {
+        ALOGW("Got error %d from begin()", rc);
     }
 
     // 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");
+    while (rc == ErrorCode::TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
+        ALOGW("Ran out of operation handles");
         if (!pruneOperation()) {
             break;
         }
-        err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+        rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
     }
-    if (err) {
-        result->resultCode = err;
+    if (rc != ErrorCode::OK) {
+        result->resultCode = rc;
         return;
     }
 
-    sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev, appToken,
-                                                            characteristics.release(), pruneable);
+    // Note: The operation map takes possession of the contents of "characteristics".
+    // It is safe to use characteristics after the following line but it will be empty.
+    sp<IBinder> operationToken = mOperationMap.addOperation(
+        result->handle, keyid, purpose, dev, appToken, std::move(characteristics), pruneable);
+    assert(characteristics.teeEnforced.size() == 0);
+    assert(characteristics.softwareEnforced.size() == 0);
+
     if (authToken) {
         mOperationMap.setOperationAuthToken(operationToken, authToken);
     }
@@ -1050,224 +1163,343 @@
     // 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;
+    // All fields but "token" were set in the begin operation's callback.
     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;
+void KeyStoreService::update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+                             const hidl_vec<uint8_t>& data, OperationResult* result) {
+    if (!checkAllowedOperationParams(params)) {
+        result->resultCode = ErrorCode::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;
+    km_device_t dev;
+    uint64_t handle;
+    KeyPurpose purpose;
+    km_id_t keyid;
+    const KeyCharacteristics* characteristics;
     if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+        result->resultCode = ErrorCode::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;
+    AuthorizationSet opParams = params;
+    result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
+    if (!result->resultCode.isOk()) {
         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);
+    AuthorizationSet key_auths(characteristics->teeEnforced);
+    key_auths.append(&characteristics->softwareEnforced[0],
+                     &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
     result->resultCode = enforcement_policy.AuthorizeOperation(
-        purpose, keyid, key_auths, operation_params, handle, false /* is_begin_operation */);
-    if (result->resultCode) {
+        purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
+    if (!result->resultCode.isOk()) {
         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);
+    auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
+                      const hidl_vec<KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
+        result->resultCode = ret;
+        if (!result->resultCode.isOk()) {
+            return;
+        }
+        result->inputConsumed = inputConsumed;
+        result->outParams = outParams;
+        result->data = output;
+    };
+
+    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->update(handle, opParams.hidl_data(),
+                                                        data, hidlCb));
+    // just a reminder: on success result->resultCode was set in the callback. So we only overwrite
+    // it if there was a communication error indicated by the ErrorCode.
+    if (!rc.isOk()) {
+        result->resultCode = rc;
     }
 }
 
-void KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
-                             const uint8_t* signature, size_t signatureLength,
-                             const uint8_t* entropy, size_t entropyLength,
+void KeyStoreService::finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
+                             const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
                              OperationResult* result) {
-    if (!checkAllowedOperationParams(params.params)) {
-        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+    if (!checkAllowedOperationParams(params)) {
+        result->resultCode = ErrorCode::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;
+    km_device_t dev;
+    uint64_t handle;
+    KeyPurpose purpose;
+    km_id_t keyid;
+    const KeyCharacteristics* characteristics;
     if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+        result->resultCode = ErrorCode::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;
+    AuthorizationSet opParams = params;
+    result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
+    if (!result->resultCode.isOk()) {
         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;
+
+    if (entropy.size()) {
+        result->resultCode = addRngEntropy(entropy);
+        if (!result->resultCode.isOk()) {
             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;
-    }
+    AuthorizationSet key_auths(characteristics->teeEnforced);
+    key_auths.append(&characteristics->softwareEnforced[0],
+                     &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
+    result->resultCode = enforcement_policy.AuthorizeOperation(
+        purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
+    if (!result->resultCode.isOk()) return;
 
-    err =
-        dev->finish(dev, handle, &inParams, &input /* TODO(swillden): wire up input to finish() */,
-                    &sig, &outParams, &output);
+    auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
+                      const hidl_vec<uint8_t>& output) {
+        result->resultCode = ret;
+        if (!result->resultCode.isOk()) {
+            return;
+        }
+        result->outParams = outParams;
+        result->data = output;
+    };
+
+    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->finish(
+        handle, opParams.hidl_data(),
+        hidl_vec<uint8_t>() /* TODO(swillden): wire up input to finish() */, signature, hidlCb));
     // 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);
+    // just a reminder: on success result->resultCode was set in the callback. So we only overwrite
+    // it if there was a communication error indicated by the ErrorCode.
+    if (!rc.isOk()) {
+        result->resultCode = rc;
     }
 }
 
-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;
+KeyStoreServiceReturnCode KeyStoreService::abort(const sp<IBinder>& token) {
+    km_device_t dev;
+    uint64_t handle;
+    KeyPurpose purpose;
+    km_id_t keyid;
     if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
-        return KM_ERROR_INVALID_OPERATION_HANDLE;
+        return ErrorCode::INVALID_OPERATION_HANDLE;
     }
     mOperationMap.removeOperation(token);
-    int32_t rc;
-    if (!dev->abort) {
-        rc = KM_ERROR_UNIMPLEMENTED;
-    } else {
-        rc = dev->abort(dev, handle);
-    }
+
+    ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->abort(handle));
     mAuthTokenTable.MarkCompleted(handle);
-    if (rc) {
-        return rc;
-    }
-    return ::NO_ERROR;
+    return rc;
 }
 
 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;
+    km_device_t dev;
+    uint64_t handle;
+    const KeyCharacteristics* characteristics;
+    KeyPurpose purpose;
+    km_id_t keyid;
     if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
         return false;
     }
-    const hw_auth_token_t* authToken = NULL;
+    const HardwareAuthToken* authToken = NULL;
     mOperationMap.getOperationAuthToken(token, &authToken);
-    std::vector<keymaster_key_param_t> ignored;
-    int32_t authResult = addOperationAuthTokenIfNeeded(token, &ignored);
-    return authResult == ::NO_ERROR;
+    AuthorizationSet ignored;
+    auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
+    return authResult.isOk();
 }
 
-int32_t KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+    // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
+    // receive a HardwareAuthToken, rather than an opaque byte array.
+
     if (!checkBinderPermission(P_ADD_AUTH)) {
         ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
     if (length != sizeof(hw_auth_token_t)) {
-        return KM_ERROR_INVALID_ARGUMENT;
+        return ErrorCode::INVALID_ARGUMENT;
     }
-    hw_auth_token_t* authToken = new hw_auth_token_t;
-    memcpy(reinterpret_cast<void*>(authToken), token, sizeof(hw_auth_token_t));
+
+    hw_auth_token_t authToken;
+    memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
+    if (authToken.version != 0) {
+        return ErrorCode::INVALID_ARGUMENT;
+    }
+
+    std::unique_ptr<HardwareAuthToken> hidlAuthToken(new HardwareAuthToken);
+    hidlAuthToken->challenge = authToken.challenge;
+    hidlAuthToken->userId = authToken.user_id;
+    hidlAuthToken->authenticatorId = authToken.authenticator_id;
+    hidlAuthToken->authenticatorType = authToken.authenticator_type;
+    hidlAuthToken->timestamp = authToken.timestamp;
+    static_assert(
+        std::is_same<decltype(hidlAuthToken->hmac),
+                     ::android::hardware::hidl_array<uint8_t, sizeof(authToken.hmac)>>::value,
+        "This function assumes token HMAC is 32 bytes, but it might not be.");
+    std::copy(authToken.hmac, authToken.hmac + sizeof(authToken.hmac), hidlAuthToken->hmac.data());
+
     // The table takes ownership of authToken.
-    mAuthTokenTable.AddAuthenticationToken(authToken);
-    return ::NO_ERROR;
+    mAuthTokenTable.AddAuthenticationToken(hidlAuthToken.release());
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
-                                   KeymasterCertificateChain* outChain) {
-    if (!outChain)
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+bool isDeviceIdAttestationRequested(const hidl_vec<KeyParameter>& params) {
+    for (size_t i = 0; i < params.size(); ++i) {
+        switch (params[i].tag) {
+        case Tag::ATTESTATION_ID_BRAND:
+        case Tag::ATTESTATION_ID_DEVICE:
+        case Tag::ATTESTATION_ID_IMEI:
+        case Tag::ATTESTATION_ID_MANUFACTURER:
+        case Tag::ATTESTATION_ID_MEID:
+        case Tag::ATTESTATION_ID_MODEL:
+        case Tag::ATTESTATION_ID_PRODUCT:
+        case Tag::ATTESTATION_ID_SERIAL:
+            return true;
+        default:
+            break;
+        }
+    }
+    return false;
+}
 
-    if (!checkAllowedOperationParams(params.params)) {
-        return KM_ERROR_INVALID_ARGUMENT;
+KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name,
+                                                     const hidl_vec<KeyParameter>& params,
+                                                     hidl_vec<hidl_vec<uint8_t>>* outChain) {
+    if (!outChain) {
+        return ErrorCode::OUTPUT_PARAMETER_NULL;
+    }
+
+    if (!checkAllowedOperationParams(params)) {
+        return ErrorCode::INVALID_ARGUMENT;
+    }
+
+    if (isDeviceIdAttestationRequested(params)) {
+        // There is a dedicated attestDeviceIds() method for device ID attestation.
+        return ErrorCode::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;
+    AuthorizationSet mutableParams = params;
+    KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
+    if (!rc.isOk()) {
+        return rc;
     }
 
-    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)
+    Blob keyBlob;
+    String8 name8(name);
+    rc = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (!rc.isOk()) {
         return rc;
-    return ::NO_ERROR;
+    }
+
+    KeyStoreServiceReturnCode error;
+    auto hidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
+        if (outChain) *outChain = certChain;
+    };
+
+    auto hidlKey = blob2hidlVec(keyBlob);
+    auto& dev = mKeyStore->getDevice(keyBlob);
+    rc = KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb));
+    if (!rc.isOk()) {
+        return rc;
+    }
+    return error;
 }
 
-int32_t KeyStoreService::onDeviceOffBody() {
+KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyParameter>& params,
+                                                           hidl_vec<hidl_vec<uint8_t>>* outChain) {
+    if (!outChain) {
+        return ErrorCode::OUTPUT_PARAMETER_NULL;
+    }
+
+    if (!checkAllowedOperationParams(params)) {
+        return ErrorCode::INVALID_ARGUMENT;
+    }
+
+    if (!isDeviceIdAttestationRequested(params)) {
+        // There is an attestKey() method for attesting keys without device ID attestation.
+        return ErrorCode::INVALID_ARGUMENT;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+    if (binder == 0) {
+        return ErrorCode::CANNOT_ATTEST_IDS;
+    }
+    if (!interface_cast<IPermissionController>(binder)->checkPermission(
+            String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
+            IPCThreadState::self()->getCallingPid(), callingUid)) {
+        return ErrorCode::CANNOT_ATTEST_IDS;
+    }
+
+    AuthorizationSet mutableParams = params;
+    KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
+    if (!rc.isOk()) {
+        return rc;
+    }
+
+    // Generate temporary key.
+    auto& dev = mKeyStore->getDevice();
+    KeyStoreServiceReturnCode error;
+    hidl_vec<uint8_t> hidlKey;
+
+    AuthorizationSet keyCharacteristics;
+    keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
+    keyCharacteristics.push_back(TAG_ALGORITHM, Algorithm::EC);
+    keyCharacteristics.push_back(TAG_DIGEST, Digest::SHA_2_256);
+    keyCharacteristics.push_back(TAG_NO_AUTH_REQUIRED);
+    keyCharacteristics.push_back(TAG_EC_CURVE, EcCurve::P_256);
+    auto generateHidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
+                              const KeyCharacteristics&) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
+        hidlKey = hidlKeyBlob;
+    };
+
+    rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(keyCharacteristics.hidl_data(), generateHidlCb));
+    if (!rc.isOk()) {
+        return rc;
+    }
+    if (!error.isOk()) {
+        return error;
+    }
+
+    // Attest key and device IDs.
+    auto attestHidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
+        *outChain = certChain;
+    };
+    KeyStoreServiceReturnCode attestationRc =
+            KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), attestHidlCb));
+
+    // Delete temporary key.
+    KeyStoreServiceReturnCode deletionRc = KS_HANDLE_HIDL_ERROR(dev->deleteKey(hidlKey));
+
+    if (!attestationRc.isOk()) {
+        return attestationRc;
+    }
+    if (!error.isOk()) {
+        return error;
+    }
+    return deletionRc;
+}
+
+KeyStoreServiceReturnCode KeyStoreService::onDeviceOffBody() {
     // TODO(tuckeris): add permission check.  This should be callable from ClockworkHome only.
     mAuthTokenTable.onDeviceOffBody();
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
 /**
@@ -1354,17 +1586,19 @@
  * otherwise the state of keystore when not unlocked and checkUnlocked is
  * true.
  */
-int32_t KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
-                                                               bool checkUnlocked) {
+KeyStoreServiceReturnCode
+KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
+                                                       bool checkUnlocked) {
     if (!checkBinderPermission(permission, targetUid)) {
-        return ::PERMISSION_DENIED;
+        return ResponseCode::PERMISSION_DENIED;
     }
     State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
     if (checkUnlocked && !isKeystoreUnlocked(state)) {
-        return state;
+        // All State values coincide with ResponseCodes
+        return static_cast<ResponseCode>(state);
     }
 
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
 bool KeyStoreService::isKeystoreUnlocked(State state) {
@@ -1378,43 +1612,16 @@
     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
+ * Check that all KeyParameter'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:
+bool KeyStoreService::checkAllowedOperationParams(const hidl_vec<KeyParameter>& params) {
+    for (size_t i = 0; i < params.size(); ++i) {
+        switch (params[i].tag) {
+        case Tag::ATTESTATION_APPLICATION_ID:
+        case Tag::AUTH_TOKEN:
+        case Tag::RESET_SINCE_ID_ROTATION:
             return false;
         default:
             break;
@@ -1423,30 +1630,32 @@
     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;
+ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>& key,
+                                                       km_device_t* dev,
+                                                       const AuthorizationSet& params,
+                                                       KeyCharacteristics* out) {
+    hidl_vec<uint8_t> appId;
+    hidl_vec<uint8_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;
+        if (param.tag == Tag::APPLICATION_ID) {
+            appId = authorizationValue(TAG_APPLICATION_ID, param).value();
+        } else if (param.tag == Tag::APPLICATION_DATA) {
+            appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
         }
     }
-    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;
+    ErrorCode error = ErrorCode::OK;
+
+    auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
+        error = ret;
+        if (error != ErrorCode::OK) {
+            return;
+        }
+        if (out) *out = keyCharacteristics;
+    };
+
+    ErrorCode rc = KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, appId, appData, hidlCb));
+    if (rc != ErrorCode::OK) {
+        return rc;
     }
     return error;
 }
@@ -1454,49 +1663,41 @@
 /**
  * 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.
+ * Returns ResponseCode::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) {
+KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
+                                                        uint64_t handle, KeyPurpose purpose,
+                                                        const HardwareAuthToken** 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]);
+    AuthorizationSet allCharacteristics;
+    for (size_t i = 0; i < characteristics.softwareEnforced.size(); i++) {
+        allCharacteristics.push_back(characteristics.softwareEnforced[i]);
     }
-    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
-        allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
+    for (size_t i = 0; i < characteristics.teeEnforced.size(); i++) {
+        allCharacteristics.push_back(characteristics.teeEnforced[i]);
     }
-    keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
-        allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
+    AuthTokenTable::Error err =
+        mAuthTokenTable.FindAuthorization(allCharacteristics, 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;
+    case AuthTokenTable::OK:
+    case AuthTokenTable::AUTH_NOT_REQUIRED:
+        return ResponseCode::NO_ERROR;
+    case AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
+    case AuthTokenTable::AUTH_TOKEN_EXPIRED:
+    case AuthTokenTable::AUTH_TOKEN_WRONG_SID:
+        return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+    case AuthTokenTable::OP_HANDLE_REQUIRED:
+        return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
+                                  : KeyStoreServiceReturnCode(ResponseCode::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)));
+        return ErrorCode::INVALID_ARGUMENT;
     }
 }
 
@@ -1505,185 +1706,199 @@
  * 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.
+ * Returns ResponseCode::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;
+KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
+                                                                         AuthorizationSet* params) {
+    const HardwareAuthToken* authToken = nullptr;
     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;
+        km_device_t dev;
+        uint64_t handle;
+        const KeyCharacteristics* characteristics = nullptr;
+        KeyPurpose purpose;
+        km_id_t keyid;
         if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-            return KM_ERROR_INVALID_OPERATION_HANDLE;
+            return ErrorCode::INVALID_OPERATION_HANDLE;
         }
-        int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
-        if (result != ::NO_ERROR) {
+        auto result = getAuthToken(*characteristics, handle, purpose, &authToken);
+        if (!result.isOk()) {
             return result;
         }
         if (authToken) {
             mOperationMap.setOperationAuthToken(token, authToken);
         }
     }
-    addAuthToParams(params, authToken);
-    return ::NO_ERROR;
+    addAuthTokenToParams(params, authToken);
+    return ResponseCode::NO_ERROR;
 }
 
 /**
  * Translate a result value to a legacy return value. All keystore errors are
  * preserved and keymaster errors become SYSTEM_ERRORs
  */
-int32_t KeyStoreService::translateResultToLegacyResult(int32_t result) {
+KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
     if (result > 0) {
-        return result;
+        return static_cast<ResponseCode>(result);
     }
-    return ::SYSTEM_ERROR;
+    return ResponseCode::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];
-        }
+static NullOr<const Algorithm&>
+getKeyAlgoritmFromKeyCharacteristics(const KeyCharacteristics& characteristics) {
+    for (size_t i = 0; i < characteristics.teeEnforced.size(); ++i) {
+        auto algo = authorizationValue(TAG_ALGORITHM, characteristics.teeEnforced[i]);
+        if (algo.isOk()) return algo.value();
     }
-    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];
-        }
+    for (size_t i = 0; i < characteristics.softwareEnforced.size(); ++i) {
+        auto algo = authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced[i]);
+        if (algo.isOk()) return algo.value();
     }
-    return NULL;
+    return {};
 }
 
-void KeyStoreService::addLegacyBeginParams(const String16& name,
-                                           std::vector<keymaster_key_param_t>& params) {
+void KeyStoreService::addLegacyBeginParams(const String16& name, AuthorizationSet* 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));
+    params->push_back(TAG_DIGEST, Digest::NONE);
+    params->push_back(TAG_PADDING, PaddingMode::NONE);
 
     // Look up the algorithm of the key.
     KeyCharacteristics characteristics;
-    int32_t rc = getKeyCharacteristics(name, NULL, NULL, UID_SELF, &characteristics);
-    if (rc != ::NO_ERROR) {
+    auto rc = getKeyCharacteristics(name, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF,
+                                    &characteristics);
+    if (!rc.isOk()) {
         ALOGE("Failed to get key characteristics");
         return;
     }
-    keymaster_key_param_t* algorithm = getKeyAlgorithm(&characteristics.characteristics);
-    if (!algorithm) {
+    auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics);
+    if (!algorithm.isOk()) {
         ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
         return;
     }
-    params.push_back(*algorithm);
+    params->push_back(TAG_ALGORITHM, algorithm.value());
 }
 
-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) {
+KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& name,
+                                                              const hidl_vec<uint8_t>& data,
+                                                              hidl_vec<uint8_t>* out,
+                                                              const hidl_vec<uint8_t>& signature,
+                                                              KeyPurpose purpose) {
 
     std::basic_stringstream<uint8_t> outBuffer;
     OperationResult result;
-    KeymasterArguments inArgs;
-    addLegacyBeginParams(name, inArgs.params);
+    AuthorizationSet inArgs;
+    addLegacyBeginParams(name, &inArgs);
     sp<IBinder> appToken(new BBinder);
     sp<IBinder> token;
 
-    begin(appToken, name, purpose, true, inArgs, NULL, 0, UID_SELF, &result);
-    if (result.resultCode != ResponseCode::NO_ERROR) {
-        if (result.resultCode == ::KEY_NOT_FOUND) {
+    begin(appToken, name, purpose, true, inArgs.hidl_data(), hidl_vec<uint8_t>(), UID_SELF,
+          &result);
+    if (!result.resultCode.isOk()) {
+        if (result.resultCode == ResponseCode::KEY_NOT_FOUND) {
             ALOGW("Key not found");
         } else {
-            ALOGW("Error in begin: %d", result.resultCode);
+            ALOGW("Error in begin: %d", int32_t(result.resultCode));
         }
         return translateResultToLegacyResult(result.resultCode);
     }
-    inArgs.params.clear();
+    inArgs.Clear();
     token = result.token;
     size_t consumed = 0;
     size_t lastConsumed = 0;
+    hidl_vec<uint8_t> data_view;
     do {
-        update(token, inArgs, data + consumed, length - consumed, &result);
+        data_view.setToExternal(const_cast<uint8_t*>(&data[consumed]), data.size() - consumed);
+        update(token, inArgs.hidl_data(), data_view, &result);
         if (result.resultCode != ResponseCode::NO_ERROR) {
-            ALOGW("Error in update: %d", result.resultCode);
+            ALOGW("Error in update: %d", int32_t(result.resultCode));
             return translateResultToLegacyResult(result.resultCode);
         }
         if (out) {
-            outBuffer.write(result.data.get(), result.dataLength);
+            outBuffer.write(&result.data[0], result.data.size());
         }
         lastConsumed = result.inputConsumed;
         consumed += lastConsumed;
-    } while (consumed < length && lastConsumed > 0);
+    } while (consumed < data.size() && lastConsumed > 0);
 
-    if (consumed != length) {
-        ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
-        return ::SYSTEM_ERROR;
+    if (consumed != data.size()) {
+        ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, data.size());
+        return ResponseCode::SYSTEM_ERROR;
     }
 
-    finish(token, inArgs, signature, signatureLength, NULL, 0, &result);
+    finish(token, inArgs.hidl_data(), signature, hidl_vec<uint8_t>(), &result);
     if (result.resultCode != ResponseCode::NO_ERROR) {
-        ALOGW("Error in finish: %d", result.resultCode);
+        ALOGW("Error in finish: %d", int32_t(result.resultCode));
         return translateResultToLegacyResult(result.resultCode);
     }
     if (out) {
-        outBuffer.write(result.data.get(), result.dataLength);
+        outBuffer.write(&result.data[0], result.data.size());
     }
 
     if (out) {
         auto buf = outBuffer.str();
-        *out = new uint8_t[buf.size()];
-        memcpy(*out, buf.c_str(), buf.size());
-        *outLength = buf.size();
+        out->resize(buf.size());
+        memcpy(&(*out)[0], buf.data(), out->size());
     }
 
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
-int32_t KeyStoreService::upgradeKeyBlob(const String16& name, uid_t uid,
-                                        const AuthorizationSet& params, Blob* blob) {
+KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name, uid_t uid,
+                                                          const AuthorizationSet& params,
+                                                          Blob* blob) {
     // Read the blob rather than assuming the caller provided the right name/uid/blob triplet.
     String8 name8(name);
     ResponseCode responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
+    if (responseCode != ResponseCode::NO_ERROR) {
         return responseCode;
     }
+    ALOGI("upgradeKeyBlob %s %d", name8.string(), uid);
 
-    keymaster_key_blob_t key = {blob->getValue(), static_cast<size_t>(blob->getLength())};
-    auto* dev = mKeyStore->getDeviceForBlob(*blob);
-    keymaster_key_blob_t upgraded_key;
-    int32_t rc = dev->upgrade_key(dev, &key, &params, &upgraded_key);
-    if (rc != KM_ERROR_OK) {
-        return rc;
-    }
-    UniquePtr<uint8_t, Malloc_Delete> upgraded_key_deleter(
-        const_cast<uint8_t*>(upgraded_key.key_material));
+    auto hidlKey = blob2hidlVec(*blob);
+    auto& dev = mKeyStore->getDevice(*blob);
 
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
-    rc = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(uid));
-    if (rc != ::NO_ERROR) {
+    KeyStoreServiceReturnCode error;
+    auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
+
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
+        error = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(uid));
+        if (!error.isOk()) {
+            ALOGI("upgradeKeyBlob keystore->del failed %d", (int)error);
+            return;
+        }
+
+        Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
+                     0 /* infoLength */, ::TYPE_KEYMASTER_10);
+        newBlob.setFallback(blob->isFallback());
+        newBlob.setEncrypted(blob->isEncrypted());
+        newBlob.setSuperEncrypted(blob->isSuperEncrypted());
+        newBlob.setCriticalToDeviceEncryption(blob->isCriticalToDeviceEncryption());
+
+        error = mKeyStore->put(filename.string(), &newBlob, get_user_id(uid));
+        if (!error.isOk()) {
+            ALOGI("upgradeKeyBlob keystore->put failed %d", (int)error);
+            return;
+        }
+
+        // Re-read blob for caller.  We can't use newBlob because writing it modified it.
+        error = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
+    };
+
+    KeyStoreServiceReturnCode rc =
+        KS_HANDLE_HIDL_ERROR(dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
+    if (!rc.isOk()) {
         return rc;
     }
 
-    Blob newBlob(upgraded_key.key_material, upgraded_key.key_material_size, nullptr /* info */,
-                 0 /* infoLength */, ::TYPE_KEYMASTER_10);
-    newBlob.setFallback(blob->isFallback());
-    newBlob.setEncrypted(blob->isEncrypted());
-
-    rc = mKeyStore->put(filename.string(), &newBlob, get_user_id(uid));
-
-    // Re-read blob for caller.  We can't use newBlob because writing it modified it.
-    responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        return responseCode;
-    }
-
-    return rc;
+    return error;
 }
 
-}  // namespace android
+}  // namespace keystore
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
index cfbc91f..3b4ef85 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -19,7 +19,7 @@
 
 #include <keystore/IKeystoreService.h>
 
-#include <keymaster/authorization_set.h>
+#include <keystore/authorization_set.h>
 
 #include "auth_token_table.h"
 #include "keystore.h"
@@ -27,42 +27,48 @@
 #include "operation.h"
 #include "permissions.h"
 
-namespace android {
+namespace keystore {
 
-class KeyStoreService : public BnKeystoreService, public IBinder::DeathRecipient {
+class KeyStoreService : public android::BnKeystoreService, public android::IBinder::DeathRecipient {
+    typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+
   public:
     explicit KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
 
-    void binderDied(const wp<IBinder>& who);
+    void binderDied(const android::wp<android::IBinder>& who);
 
-    int32_t getState(int32_t userId);
+    KeyStoreServiceReturnCode getState(int32_t userId) override;
 
-    int32_t get(const String16& name, int32_t uid, 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);
+    KeyStoreServiceReturnCode get(const android::String16& name, int32_t uid,
+                                  hidl_vec<uint8_t>* item) override;
+    KeyStoreServiceReturnCode insert(const android::String16& name, const hidl_vec<uint8_t>& item,
+                                     int targetUid, int32_t flags) override;
+    KeyStoreServiceReturnCode del(const android::String16& name, int targetUid) override;
+    KeyStoreServiceReturnCode exist(const android::String16& name, int targetUid) override;
+    KeyStoreServiceReturnCode list(const android::String16& prefix, int targetUid,
+                                   android::Vector<android::String16>* matches) override;
 
-    int32_t reset();
+    KeyStoreServiceReturnCode reset() override;
 
-    int32_t onUserPasswordChanged(int32_t userId, const String16& password);
-    int32_t onUserAdded(int32_t userId, int32_t parentId);
-    int32_t onUserRemoved(int32_t userId);
+    KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
+                                                    const android::String16& password) override;
+    KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override;
+    KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override;
 
-    int32_t lock(int32_t userId);
-    int32_t unlock(int32_t userId, const String16& pw);
+    KeyStoreServiceReturnCode lock(int32_t userId) override;
+    KeyStoreServiceReturnCode unlock(int32_t userId, const android::String16& pw) override;
 
-    bool isEmpty(int32_t userId);
+    bool isEmpty(int32_t userId) override;
 
-    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);
+    KeyStoreServiceReturnCode
+    generate(const android::String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
+             int32_t flags, android::Vector<android::sp<android::KeystoreArg>>* args) override;
+    KeyStoreServiceReturnCode import(const android::String16& name, const hidl_vec<uint8_t>& data,
+                                     int targetUid, int32_t flags) override;
+    KeyStoreServiceReturnCode sign(const android::String16& name, const hidl_vec<uint8_t>& data,
+                                   hidl_vec<uint8_t>* out) override;
+    KeyStoreServiceReturnCode verify(const android::String16& name, const hidl_vec<uint8_t>& data,
+                                     const hidl_vec<uint8_t>& signature) override;
 
     /*
      * TODO: The abstraction between things stored in hardware and regular blobs
@@ -75,51 +81,60 @@
      * "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);
+    KeyStoreServiceReturnCode get_pubkey(const android::String16& name,
+                                         hidl_vec<uint8_t>* pubKey) override;
 
-    int32_t grant(const String16& name, int32_t granteeUid);
-    int32_t ungrant(const String16& name, int32_t granteeUid);
+    KeyStoreServiceReturnCode grant(const android::String16& name, int32_t granteeUid) override;
+    KeyStoreServiceReturnCode ungrant(const android::String16& name, int32_t granteeUid) override;
 
-    int64_t getmtime(const String16& name, int32_t uid);
+    int64_t getmtime(const android::String16& name, int32_t uid) override;
 
-    int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-                      int32_t destUid);
+    KeyStoreServiceReturnCode duplicate(const android::String16& srcKey, int32_t srcUid,
+                                        const android::String16& destKey, int32_t destUid) override;
 
-    int32_t is_hardware_backed(const String16& keyType);
+    int32_t is_hardware_backed(const android::String16& keyType) override;
 
-    int32_t clear_uid(int64_t targetUid64);
+    KeyStoreServiceReturnCode clear_uid(int64_t targetUid64) override;
 
-    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, int32_t uid,
-                                  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, int32_t uid,
-                   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, int32_t uid, 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);
+    KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override;
+    KeyStoreServiceReturnCode generateKey(const android::String16& name,
+                                          const hidl_vec<KeyParameter>& params,
+                                          const hidl_vec<uint8_t>& entropy, int uid, int flags,
+                                          KeyCharacteristics* outCharacteristics) override;
+    KeyStoreServiceReturnCode
+    getKeyCharacteristics(const android::String16& name, const hidl_vec<uint8_t>& clientId,
+                          const hidl_vec<uint8_t>& appData, int32_t uid,
+                          KeyCharacteristics* outCharacteristics) override;
+    KeyStoreServiceReturnCode importKey(const android::String16& name,
+                                        const hidl_vec<KeyParameter>& params, KeyFormat format,
+                                        const hidl_vec<uint8_t>& keyData, int uid, int flags,
+                                        KeyCharacteristics* outCharacteristics) override;
+    void exportKey(const android::String16& name, KeyFormat format,
+                   const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData, int32_t uid,
+                   android::ExportResult* result) override;
+    void begin(const sp<android::IBinder>& appToken, const android::String16& name,
+               KeyPurpose purpose, bool pruneable, const hidl_vec<KeyParameter>& params,
+               const hidl_vec<uint8_t>& entropy, int32_t uid,
+               android::OperationResult* result) override;
+    void update(const sp<android::IBinder>& token, const hidl_vec<KeyParameter>& params,
+                const hidl_vec<uint8_t>& data, android::OperationResult* result) override;
+    void finish(const sp<android::IBinder>& token, const hidl_vec<KeyParameter>& params,
+                const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
+                android::OperationResult* result) override;
+    KeyStoreServiceReturnCode abort(const sp<android::IBinder>& token) override;
 
-    bool isOperationAuthorized(const sp<IBinder>& token);
+    bool isOperationAuthorized(const sp<android::IBinder>& token) override;
 
-    int32_t addAuthToken(const uint8_t* token, size_t length);
+    KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override;
 
-    int32_t attestKey(const String16& name, const KeymasterArguments& params,
-                      KeymasterCertificateChain* outChain) override;
+    KeyStoreServiceReturnCode attestKey(const android::String16& name,
+                                        const hidl_vec<KeyParameter>& params,
+                                        hidl_vec<hidl_vec<uint8_t>>* outChain) override;
 
-    int32_t onDeviceOffBody();
+    KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params,
+                                              hidl_vec<hidl_vec<uint8_t>>* outChain) override;
+
+    KeyStoreServiceReturnCode onDeviceOffBody() override;
 
   private:
     static const int32_t UID_SELF = -1;
@@ -164,23 +179,20 @@
      * 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);
+    KeyStoreServiceReturnCode 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);
+    bool checkAllowedOperationParams(const hidl_vec<KeyParameter>& 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);
+    ErrorCode getOperationCharacteristics(const hidl_vec<uint8_t>& key, km_device_t* dev,
+                                          const AuthorizationSet& params, KeyCharacteristics* out);
 
     /**
      * Get the auth token for this operation from the auth token table.
@@ -192,11 +204,10 @@
      *         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);
+    KeyStoreServiceReturnCode getAuthToken(const KeyCharacteristics& characteristics,
+                                           uint64_t handle, KeyPurpose purpose,
+                                           const HardwareAuthToken** authToken,
+                                           bool failOnTokenMissing = true);
 
     /**
      * Add the auth token for the operation to the param list if the operation
@@ -209,22 +220,22 @@
      *         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);
+    KeyStoreServiceReturnCode addOperationAuthTokenIfNeeded(const sp<android::IBinder>& token,
+                                                            AuthorizationSet* 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);
+    KeyStoreServiceReturnCode translateResultToLegacyResult(int32_t result);
 
-    keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics);
+    void addLegacyBeginParams(const android::String16& name, AuthorizationSet* params);
 
-    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);
+    KeyStoreServiceReturnCode doLegacySignVerify(const android::String16& name,
+                                                 const hidl_vec<uint8_t>& data,
+                                                 hidl_vec<uint8_t>* out,
+                                                 const hidl_vec<uint8_t>& signature,
+                                                 KeyPurpose purpose);
 
     /**
      * Upgrade a key blob under alias "name", returning the new blob in "blob".  If "blob"
@@ -234,15 +245,15 @@
      *         KM_ERROR_VERSION_MISMATCH if called on a key whose patch level is greater than or
      *         equal to the current system patch level.
      */
-    int32_t upgradeKeyBlob(const String16& name, uid_t targetUid,
-                           const keymaster::AuthorizationSet& params, Blob* blob);
+    KeyStoreServiceReturnCode upgradeKeyBlob(const android::String16& name, uid_t targetUid,
+                                             const AuthorizationSet& params, Blob* blob);
 
     ::KeyStore* mKeyStore;
     OperationMap mOperationMap;
-    keymaster::AuthTokenTable mAuthTokenTable;
+    keystore::AuthTokenTable mAuthTokenTable;
     KeystoreKeymasterEnforcement enforcement_policy;
 };
 
-};  // namespace android
+};  // namespace keystore
 
 #endif  // KEYSTORE_KEYSTORE_SERVICE_H_
diff --git a/keystore/keymaster_enforcement.cpp b/keystore/keymaster_enforcement.cpp
new file mode 100644
index 0000000..4cee57d
--- /dev/null
+++ b/keystore/keymaster_enforcement.cpp
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore"
+
+#include "keymaster_enforcement.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+
+#include <cutils/log.h>
+#include <hardware/hw_auth_token.h>
+#include <list>
+
+namespace keystore {
+
+class AccessTimeMap {
+  public:
+    explicit AccessTimeMap(uint32_t max_size) : max_size_(max_size) {}
+
+    /* If the key is found, returns true and fills \p last_access_time.  If not found returns
+     * false. */
+    bool LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const;
+
+    /* Updates the last key access time with the currentTime parameter.  Adds the key if
+     * needed, returning false if key cannot be added because list is full. */
+    bool UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout);
+
+  private:
+    struct AccessTime {
+        km_id_t keyid;
+        uint32_t access_time;
+        uint32_t timeout;
+    };
+    std::list<AccessTime> last_access_list_;
+    const uint32_t max_size_;
+};
+
+class AccessCountMap {
+  public:
+    explicit AccessCountMap(uint32_t max_size) : max_size_(max_size) {}
+
+    /* If the key is found, returns true and fills \p count.  If not found returns
+     * false. */
+    bool KeyAccessCount(km_id_t keyid, uint32_t* count) const;
+
+    /* Increments key access count, adding an entry if the key has never been used.  Returns
+     * false if the list has reached maximum size. */
+    bool IncrementKeyAccessCount(km_id_t keyid);
+
+  private:
+    struct AccessCount {
+        km_id_t keyid;
+        uint64_t access_count;
+    };
+    std::list<AccessCount> access_count_list_;
+    const uint32_t max_size_;
+};
+
+bool is_public_key_algorithm(const AuthorizationSet& auth_set) {
+    auto algorithm = auth_set.GetTagValue(TAG_ALGORITHM);
+    return algorithm.isOk() &&
+           (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC);
+}
+
+static ErrorCode authorized_purpose(const KeyPurpose purpose, const AuthorizationSet& auth_set) {
+    switch (purpose) {
+    case KeyPurpose::VERIFY:
+    case KeyPurpose::ENCRYPT:
+    case KeyPurpose::SIGN:
+    case KeyPurpose::DECRYPT:
+        if (auth_set.Contains(TAG_PURPOSE, purpose)) return ErrorCode::OK;
+        return ErrorCode::INCOMPATIBLE_PURPOSE;
+
+    default:
+        return ErrorCode::UNSUPPORTED_PURPOSE;
+    }
+}
+
+inline bool is_origination_purpose(KeyPurpose purpose) {
+    return purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN;
+}
+
+inline bool is_usage_purpose(KeyPurpose purpose) {
+    return purpose == KeyPurpose::DECRYPT || purpose == KeyPurpose::VERIFY;
+}
+
+KeymasterEnforcement::KeymasterEnforcement(uint32_t max_access_time_map_size,
+                                           uint32_t max_access_count_map_size)
+    : access_time_map_(new (std::nothrow) AccessTimeMap(max_access_time_map_size)),
+      access_count_map_(new (std::nothrow) AccessCountMap(max_access_count_map_size)) {}
+
+KeymasterEnforcement::~KeymasterEnforcement() {
+    delete access_time_map_;
+    delete access_count_map_;
+}
+
+ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
+                                                   const AuthorizationSet& auth_set,
+                                                   const AuthorizationSet& operation_params,
+                                                   uint64_t op_handle, bool is_begin_operation) {
+    if (is_public_key_algorithm(auth_set)) {
+        switch (purpose) {
+        case KeyPurpose::ENCRYPT:
+        case KeyPurpose::VERIFY:
+            /* Public key operations are always authorized. */
+            return ErrorCode::OK;
+
+        case KeyPurpose::DECRYPT:
+        case KeyPurpose::SIGN:
+        case KeyPurpose::DERIVE_KEY:
+            break;
+        case KeyPurpose::WRAP_KEY:
+            return ErrorCode::INCOMPATIBLE_PURPOSE;
+        };
+    };
+
+    if (is_begin_operation)
+        return AuthorizeBegin(purpose, keyid, auth_set, operation_params);
+    else
+        return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+}
+
+// For update and finish the only thing to check is user authentication, and then only if it's not
+// timeout-based.
+ErrorCode KeymasterEnforcement::AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set,
+                                                        const AuthorizationSet& operation_params,
+                                                        uint64_t op_handle) {
+    int auth_type_index = -1;
+    for (size_t pos = 0; pos < auth_set.size(); ++pos) {
+        switch (auth_set[pos].tag) {
+        case Tag::NO_AUTH_REQUIRED:
+        case Tag::AUTH_TIMEOUT:
+            // If no auth is required or if auth is timeout-based, we have nothing to check.
+            return ErrorCode::OK;
+
+        case Tag::USER_AUTH_TYPE:
+            auth_type_index = pos;
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    // Note that at this point we should be able to assume that authentication is required, because
+    // authentication is required if KM_TAG_NO_AUTH_REQUIRED is absent.  However, there are legacy
+    // keys which have no authentication-related tags, so we assume that absence is equivalent to
+    // presence of KM_TAG_NO_AUTH_REQUIRED.
+    //
+    // So, if we found KM_TAG_USER_AUTH_TYPE or if we find KM_TAG_USER_SECURE_ID then authentication
+    // is required.  If we find neither, then we assume authentication is not required and return
+    // success.
+    bool authentication_required = (auth_type_index != -1);
+    for (auto& param : auth_set) {
+        auto user_secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
+        if (user_secure_id.isOk()) {
+            authentication_required = true;
+            int auth_timeout_index = -1;
+            if (AuthTokenMatches(auth_set, operation_params, user_secure_id.value(),
+                                 auth_type_index, auth_timeout_index, op_handle,
+                                 false /* is_begin_operation */))
+                return ErrorCode::OK;
+        }
+    }
+
+    if (authentication_required) return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+
+    return ErrorCode::OK;
+}
+
+ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
+                                               const AuthorizationSet& auth_set,
+                                               const AuthorizationSet& operation_params) {
+    // Find some entries that may be needed to handle KM_TAG_USER_SECURE_ID
+    int auth_timeout_index = -1;
+    int auth_type_index = -1;
+    int no_auth_required_index = -1;
+    for (size_t pos = 0; pos < auth_set.size(); ++pos) {
+        switch (auth_set[pos].tag) {
+        case Tag::AUTH_TIMEOUT:
+            auth_timeout_index = pos;
+            break;
+        case Tag::USER_AUTH_TYPE:
+            auth_type_index = pos;
+            break;
+        case Tag::NO_AUTH_REQUIRED:
+            no_auth_required_index = pos;
+            break;
+        default:
+            break;
+        }
+    }
+
+    ErrorCode error = authorized_purpose(purpose, auth_set);
+    if (error != ErrorCode::OK) return error;
+
+    // If successful, and if key has a min time between ops, this will be set to the time limit
+    uint32_t min_ops_timeout = UINT32_MAX;
+
+    bool update_access_count = false;
+    bool caller_nonce_authorized_by_key = false;
+    bool authentication_required = false;
+    bool auth_token_matched = false;
+
+    for (auto& param : auth_set) {
+
+        // KM_TAG_PADDING_OLD and KM_TAG_DIGEST_OLD aren't actually members of the enum, so we can't
+        // switch on them.  There's nothing to validate for them, though, so just ignore them.
+        if (int32_t(param.tag) == KM_TAG_PADDING_OLD || int32_t(param.tag) == KM_TAG_DIGEST_OLD)
+            continue;
+
+        switch (param.tag) {
+
+        case Tag::ACTIVE_DATETIME: {
+            auto date = authorizationValue(TAG_ACTIVE_DATETIME, param);
+            if (date.isOk() && !activation_date_valid(date.value()))
+                return ErrorCode::KEY_NOT_YET_VALID;
+            break;
+        }
+        case Tag::ORIGINATION_EXPIRE_DATETIME: {
+            auto date = authorizationValue(TAG_ORIGINATION_EXPIRE_DATETIME, param);
+            if (is_origination_purpose(purpose) && date.isOk() &&
+                expiration_date_passed(date.value()))
+                return ErrorCode::KEY_EXPIRED;
+            break;
+        }
+        case Tag::USAGE_EXPIRE_DATETIME: {
+            auto date = authorizationValue(TAG_USAGE_EXPIRE_DATETIME, param);
+            if (is_usage_purpose(purpose) && date.isOk() && expiration_date_passed(date.value()))
+                return ErrorCode::KEY_EXPIRED;
+            break;
+        }
+        case Tag::MIN_SECONDS_BETWEEN_OPS: {
+            auto min_ops_timeout = authorizationValue(TAG_MIN_SECONDS_BETWEEN_OPS, param);
+            if (min_ops_timeout.isOk() && !MinTimeBetweenOpsPassed(min_ops_timeout.value(), keyid))
+                return ErrorCode::KEY_RATE_LIMIT_EXCEEDED;
+            break;
+        }
+        case Tag::MAX_USES_PER_BOOT: {
+            auto max_users = authorizationValue(TAG_MAX_USES_PER_BOOT, param);
+            update_access_count = true;
+            if (max_users.isOk() && !MaxUsesPerBootNotExceeded(keyid, max_users.value()))
+                return ErrorCode::KEY_MAX_OPS_EXCEEDED;
+            break;
+        }
+        case Tag::USER_SECURE_ID:
+            if (no_auth_required_index != -1) {
+                // Key has both KM_TAG_USER_SECURE_ID and KM_TAG_NO_AUTH_REQUIRED
+                return ErrorCode::INVALID_KEY_BLOB;
+            }
+
+            if (auth_timeout_index != -1) {
+                auto secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
+                authentication_required = true;
+                if (secure_id.isOk() &&
+                    AuthTokenMatches(auth_set, operation_params, secure_id.value(), auth_type_index,
+                                     auth_timeout_index, 0 /* op_handle */,
+                                     true /* is_begin_operation */))
+                    auth_token_matched = true;
+            }
+            break;
+
+        case Tag::CALLER_NONCE:
+            caller_nonce_authorized_by_key = true;
+            break;
+
+        /* Tags should never be in key auths. */
+        case Tag::INVALID:
+        case Tag::AUTH_TOKEN:
+        case Tag::ROOT_OF_TRUST:
+        case Tag::APPLICATION_DATA:
+        case Tag::ATTESTATION_CHALLENGE:
+        case Tag::ATTESTATION_APPLICATION_ID:
+        case Tag::ATTESTATION_ID_BRAND:
+        case Tag::ATTESTATION_ID_DEVICE:
+        case Tag::ATTESTATION_ID_PRODUCT:
+        case Tag::ATTESTATION_ID_SERIAL:
+        case Tag::ATTESTATION_ID_IMEI:
+        case Tag::ATTESTATION_ID_MEID:
+        case Tag::ATTESTATION_ID_MANUFACTURER:
+        case Tag::ATTESTATION_ID_MODEL:
+            return ErrorCode::INVALID_KEY_BLOB;
+
+        /* Tags used for cryptographic parameters in keygen.  Nothing to enforce. */
+        case Tag::PURPOSE:
+        case Tag::ALGORITHM:
+        case Tag::KEY_SIZE:
+        case Tag::BLOCK_MODE:
+        case Tag::DIGEST:
+        case Tag::MAC_LENGTH:
+        case Tag::PADDING:
+        case Tag::NONCE:
+        case Tag::MIN_MAC_LENGTH:
+        case Tag::KDF:
+        case Tag::EC_CURVE:
+
+        /* Tags not used for operations. */
+        case Tag::BLOB_USAGE_REQUIREMENTS:
+        case Tag::EXPORTABLE:
+
+        /* Algorithm specific parameters not used for access control. */
+        case Tag::RSA_PUBLIC_EXPONENT:
+        case Tag::ECIES_SINGLE_HASH_MODE:
+
+        /* Informational tags. */
+        case Tag::CREATION_DATETIME:
+        case Tag::ORIGIN:
+        case Tag::ROLLBACK_RESISTANT:
+
+        /* Tags handled when KM_TAG_USER_SECURE_ID is handled */
+        case Tag::NO_AUTH_REQUIRED:
+        case Tag::USER_AUTH_TYPE:
+        case Tag::AUTH_TIMEOUT:
+
+        /* Tag to provide data to operations. */
+        case Tag::ASSOCIATED_DATA:
+
+        /* Tags that are implicitly verified by secure side */
+        case Tag::ALL_APPLICATIONS:
+        case Tag::APPLICATION_ID:
+        case Tag::OS_VERSION:
+        case Tag::OS_PATCHLEVEL:
+
+        /* Ignored pending removal */
+        case Tag::USER_ID:
+        case Tag::ALL_USERS:
+
+        /* TODO(swillden): Handle these */
+        case Tag::INCLUDE_UNIQUE_ID:
+        case Tag::UNIQUE_ID:
+        case Tag::RESET_SINCE_ID_ROTATION:
+        case Tag::ALLOW_WHILE_ON_BODY:
+            break;
+
+        case Tag::BOOTLOADER_ONLY:
+            return ErrorCode::INVALID_KEY_BLOB;
+        }
+    }
+
+    if (authentication_required && !auth_token_matched) {
+        ALOGE("Auth required but no matching auth token found");
+        return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+    }
+
+    if (!caller_nonce_authorized_by_key && is_origination_purpose(purpose) &&
+        operation_params.Contains(Tag::NONCE))
+        return ErrorCode::CALLER_NONCE_PROHIBITED;
+
+    if (min_ops_timeout != UINT32_MAX) {
+        if (!access_time_map_) {
+            ALOGE("Rate-limited keys table not allocated.  Rate-limited keys disabled");
+            return ErrorCode::MEMORY_ALLOCATION_FAILED;
+        }
+
+        if (!access_time_map_->UpdateKeyAccessTime(keyid, get_current_time(), min_ops_timeout)) {
+            ALOGE("Rate-limited keys table full.  Entries will time out.");
+            return ErrorCode::TOO_MANY_OPERATIONS;
+        }
+    }
+
+    if (update_access_count) {
+        if (!access_count_map_) {
+            ALOGE("Usage-count limited keys tabel not allocated.  Count-limited keys disabled");
+            return ErrorCode::MEMORY_ALLOCATION_FAILED;
+        }
+
+        if (!access_count_map_->IncrementKeyAccessCount(keyid)) {
+            ALOGE("Usage count-limited keys table full, until reboot.");
+            return ErrorCode::TOO_MANY_OPERATIONS;
+        }
+    }
+
+    return ErrorCode::OK;
+}
+
+class EvpMdCtx {
+  public:
+    EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
+    ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
+
+    EVP_MD_CTX* get() { return &ctx_; }
+
+  private:
+    EVP_MD_CTX ctx_;
+};
+
+/* static */
+bool KeymasterEnforcement::CreateKeyId(const hidl_vec<uint8_t>& key_blob, km_id_t* keyid) {
+    EvpMdCtx ctx;
+
+    uint8_t hash[EVP_MAX_MD_SIZE];
+    unsigned int hash_len;
+    if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
+        EVP_DigestUpdate(ctx.get(), &key_blob[0], key_blob.size()) &&
+        EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
+        assert(hash_len >= sizeof(*keyid));
+        memcpy(keyid, hash, sizeof(*keyid));
+        return true;
+    }
+
+    return false;
+}
+
+bool KeymasterEnforcement::MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid) {
+    if (!access_time_map_) return false;
+
+    uint32_t last_access_time;
+    if (!access_time_map_->LastKeyAccessTime(keyid, &last_access_time)) return true;
+    return min_time_between <= static_cast<int64_t>(get_current_time()) - last_access_time;
+}
+
+bool KeymasterEnforcement::MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses) {
+    if (!access_count_map_) return false;
+
+    uint32_t key_access_count;
+    if (!access_count_map_->KeyAccessCount(keyid, &key_access_count)) return true;
+    return key_access_count < max_uses;
+}
+
+template <typename IntType, uint32_t byteOrder> struct choose_hton;
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
+    inline static IntType hton(const IntType& value) {
+        IntType result = 0;
+        const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
+        unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
+        for (int i = sizeof(IntType) - 1; i >= 0; --i) {
+            *(outbytes++) = inbytes[i];
+        }
+        return result;
+    }
+};
+
+template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
+    inline static IntType hton(const IntType& value) { return value; }
+};
+
+template <typename IntType> inline IntType hton(const IntType& value) {
+    return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
+
+template <typename IntType> inline IntType ntoh(const IntType& value) {
+    // same operation and hton
+    return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
+}
+
+bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
+                                            const AuthorizationSet& operation_params,
+                                            const uint64_t user_secure_id,
+                                            const int auth_type_index, const int auth_timeout_index,
+                                            const uint64_t op_handle,
+                                            bool is_begin_operation) const {
+    assert(auth_type_index < static_cast<int>(auth_set.size()));
+    assert(auth_timeout_index < static_cast<int>(auth_set.size()));
+
+    auto auth_token_blob = operation_params.GetTagValue(TAG_AUTH_TOKEN);
+    if (!auth_token_blob.isOk()) {
+        ALOGE("Authentication required, but auth token not provided");
+        return false;
+    }
+
+    if (auth_token_blob.value().size() != sizeof(hw_auth_token_t)) {
+        ALOGE("Bug: Auth token is the wrong size (%zu expected, %zu found)",
+              sizeof(hw_auth_token_t), auth_token_blob.value().size());
+        return false;
+    }
+
+    hw_auth_token_t auth_token;
+    memcpy(&auth_token, &auth_token_blob.value()[0], sizeof(hw_auth_token_t));
+    if (auth_token.version != HW_AUTH_TOKEN_VERSION) {
+        ALOGE("Bug: Auth token is the version %hhu (or is not an auth token). Expected %d",
+              auth_token.version, HW_AUTH_TOKEN_VERSION);
+        return false;
+    }
+
+    if (!ValidateTokenSignature(auth_token)) {
+        ALOGE("Auth token signature invalid");
+        return false;
+    }
+
+    if (auth_timeout_index == -1 && op_handle && op_handle != auth_token.challenge) {
+        ALOGE("Auth token has the challenge %" PRIu64 ", need %" PRIu64, auth_token.challenge,
+              op_handle);
+        return false;
+    }
+
+    if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
+        ALOGI("Auth token SIDs %" PRIu64 " and %" PRIu64 " do not match key SID %" PRIu64,
+              auth_token.user_id, auth_token.authenticator_id, user_secure_id);
+        return false;
+    }
+
+    if (auth_type_index < 0 || auth_type_index > static_cast<int>(auth_set.size())) {
+        ALOGE("Auth required but no auth type found");
+        return false;
+    }
+
+    assert(auth_set[auth_type_index].tag == KM_TAG_USER_AUTH_TYPE);
+    auto key_auth_type_mask = authorizationValue(TAG_USER_AUTH_TYPE, auth_set[auth_type_index]);
+    if (!key_auth_type_mask.isOk()) return false;
+
+    uint32_t token_auth_type = ntoh(auth_token.authenticator_type);
+    if ((uint32_t(key_auth_type_mask.value()) & token_auth_type) == 0) {
+        ALOGE("Key requires match of auth type mask 0%uo, but token contained 0%uo",
+              key_auth_type_mask.value(), token_auth_type);
+        return false;
+    }
+
+    if (auth_timeout_index != -1 && is_begin_operation) {
+        assert(auth_set[auth_timeout_index].tag == KM_TAG_AUTH_TIMEOUT);
+        auto auth_token_timeout =
+            authorizationValue(TAG_AUTH_TIMEOUT, auth_set[auth_timeout_index]);
+        if (!auth_token_timeout.isOk()) return false;
+
+        if (auth_token_timed_out(auth_token, auth_token_timeout.value())) {
+            ALOGE("Auth token has timed out");
+            return false;
+        }
+    }
+
+    // Survived the whole gauntlet.  We have authentage!
+    return true;
+}
+
+bool AccessTimeMap::LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const {
+    for (auto& entry : last_access_list_)
+        if (entry.keyid == keyid) {
+            *last_access_time = entry.access_time;
+            return true;
+        }
+    return false;
+}
+
+bool AccessTimeMap::UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout) {
+    for (auto iter = last_access_list_.begin(); iter != last_access_list_.end();) {
+        if (iter->keyid == keyid) {
+            iter->access_time = current_time;
+            return true;
+        }
+
+        // Expire entry if possible.
+        assert(current_time >= iter->access_time);
+        if (current_time - iter->access_time >= iter->timeout)
+            iter = last_access_list_.erase(iter);
+        else
+            ++iter;
+    }
+
+    if (last_access_list_.size() >= max_size_) return false;
+
+    AccessTime new_entry;
+    new_entry.keyid = keyid;
+    new_entry.access_time = current_time;
+    new_entry.timeout = timeout;
+    last_access_list_.push_front(new_entry);
+    return true;
+}
+
+bool AccessCountMap::KeyAccessCount(km_id_t keyid, uint32_t* count) const {
+    for (auto& entry : access_count_list_)
+        if (entry.keyid == keyid) {
+            *count = entry.access_count;
+            return true;
+        }
+    return false;
+}
+
+bool AccessCountMap::IncrementKeyAccessCount(km_id_t keyid) {
+    for (auto& entry : access_count_list_)
+        if (entry.keyid == keyid) {
+            // Note that the 'if' below will always be true because KM_TAG_MAX_USES_PER_BOOT is a
+            // uint32_t, and as soon as entry.access_count reaches the specified maximum value
+            // operation requests will be rejected and access_count won't be incremented any more.
+            // And, besides, UINT64_MAX is huge.  But we ensure that it doesn't wrap anyway, out of
+            // an abundance of caution.
+            if (entry.access_count < UINT64_MAX) ++entry.access_count;
+            return true;
+        }
+
+    if (access_count_list_.size() >= max_size_) return false;
+
+    AccessCount new_entry;
+    new_entry.keyid = keyid;
+    new_entry.access_count = 1;
+    access_count_list_.push_front(new_entry);
+    return true;
+}
+}; /* namespace keystore */
diff --git a/keystore/keymaster_enforcement.h b/keystore/keymaster_enforcement.h
new file mode 100644
index 0000000..4f22f01
--- /dev/null
+++ b/keystore/keymaster_enforcement.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_KEYMASTER_ENFORCEMENT_H
+#define KEYSTORE_KEYMASTER_ENFORCEMENT_H
+
+#include <stdio.h>
+
+#include <keystore/authorization_set.h>
+
+namespace keystore {
+
+typedef uint64_t km_id_t;
+
+class KeymasterEnforcementContext {
+  public:
+    virtual ~KeymasterEnforcementContext() {}
+    /*
+     * Get current time.
+     */
+};
+
+class AccessTimeMap;
+class AccessCountMap;
+
+class KeymasterEnforcement {
+  public:
+    /**
+     * Construct a KeymasterEnforcement.
+     */
+    KeymasterEnforcement(uint32_t max_access_time_map_size, uint32_t max_access_count_map_size);
+    virtual ~KeymasterEnforcement();
+
+    /**
+     * Iterates through the authorization set and returns the corresponding keymaster error. Will
+     * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+     * the given operation params and handle. Used for encrypt, decrypt sign, and verify.
+     */
+    ErrorCode AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
+                                 const AuthorizationSet& auth_set,
+                                 const AuthorizationSet& operation_params, uint64_t op_handle,
+                                 bool is_begin_operation);
+
+    /**
+     * Iterates through the authorization set and returns the corresponding keymaster error. Will
+     * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+     * the given operation params. Used for encrypt, decrypt sign, and verify.
+     */
+    ErrorCode AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
+                             const AuthorizationSet& auth_set,
+                             const AuthorizationSet& operation_params);
+
+    /**
+     * Iterates through the authorization set and returns the corresponding keymaster error. Will
+     * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+     * the given operation params and handle. Used for encrypt, decrypt sign, and verify.
+     */
+    ErrorCode AuthorizeUpdate(const AuthorizationSet& auth_set,
+                              const AuthorizationSet& operation_params, uint64_t op_handle) {
+        return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+    }
+
+    /**
+     * Iterates through the authorization set and returns the corresponding keymaster error. Will
+     * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with
+     * the given operation params and handle. Used for encrypt, decrypt sign, and verify.
+     */
+    ErrorCode AuthorizeFinish(const AuthorizationSet& auth_set,
+                              const AuthorizationSet& operation_params, uint64_t op_handle) {
+        return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+    }
+
+    /**
+     * Creates a key ID for use in subsequent calls to AuthorizeOperation.  Clients needn't use this
+     * method of creating key IDs, as long as they use something consistent and unique.  This method
+     * hashes the key blob.
+     *
+     * Returns false if an error in the crypto library prevents creation of an ID.
+     */
+    static bool CreateKeyId(const hidl_vec<uint8_t>& key_blob, km_id_t* keyid);
+
+    //
+    // Methods that must be implemented by subclasses
+    //
+    // The time-related methods address the fact that different enforcement contexts may have
+    // different time-related capabilities.  In particular:
+    //
+    // - They may or may not be able to check dates against real-world clocks.
+    //
+    // - They may or may not be able to check timestampls against authentication trustlets (minters
+    //   of hw_auth_token_t structs).
+    //
+    // - They must have some time source for relative times, but may not be able to provide more
+    //   than reliability and monotonicity.
+
+    /*
+     * Returns true if the specified activation date has passed, or if activation cannot be
+     * enforced.
+     */
+    virtual bool activation_date_valid(uint64_t activation_date) const = 0;
+
+    /*
+     * Returns true if the specified expiration date has passed.  Returns false if it has not, or if
+     * expiration cannot be enforced.
+     */
+    virtual bool expiration_date_passed(uint64_t expiration_date) const = 0;
+
+    /*
+     * Returns true if the specified auth_token is older than the specified timeout.
+     */
+    virtual bool auth_token_timed_out(const hw_auth_token_t& token, uint32_t timeout) const = 0;
+
+    /*
+     * Get current time in seconds from some starting point.  This value is used to compute relative
+     * times between events.  It must be monotonically increasing, and must not skip or lag.  It
+     * need not have any relation to any external time standard (other than the duration of
+     * "second").
+     *
+     * On POSIX systems, it's recommented to use clock_gettime(CLOCK_MONOTONIC, ...) to implement
+     * this method.
+     */
+    virtual uint32_t get_current_time() const = 0;
+
+    /*
+     * Returns true if the specified auth_token has a valid signature, or if signature validation is
+     * not available.
+     */
+    virtual bool ValidateTokenSignature(const hw_auth_token_t& token) const = 0;
+
+  private:
+    ErrorCode AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set,
+                                      const AuthorizationSet& operation_params, uint64_t op_handle);
+
+    bool MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid);
+    bool MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses);
+    bool AuthTokenMatches(const AuthorizationSet& auth_set,
+                          const AuthorizationSet& operation_params, const uint64_t user_secure_id,
+                          const int auth_type_index, const int auth_timeout_index,
+                          const uint64_t op_handle, bool is_begin_operation) const;
+
+    AccessTimeMap* access_time_map_;
+    AccessCountMap* access_count_map_;
+};
+
+}; /* namespace keystore */
+
+#endif  // KEYSTORE_KEYMASTER_ENFORCEMENT_H
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 0b86e83..bc2e0dc 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "keystore"
+
 #include "keystore.h"
 
 #include <dirent.h>
@@ -25,16 +27,23 @@
 
 #include <keystore/IKeystoreService.h>
 
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+
 #include "keystore_utils.h"
 #include "permissions.h"
+#include <keystore/keystore_hidl_support.h>
 
 const char* KeyStore::sOldMasterKey = ".masterkey";
 const char* KeyStore::sMetaDataFile = ".metadata";
 
 const android::String16 KeyStore::sRSAKeyType("RSA");
 
-KeyStore::KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback)
-    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback) {
+using namespace keystore;
+
+KeyStore::KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
+                   bool allowNewFallback)
+    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback),
+      mAllowNewFallback(allowNewFallback) {
     memset(&mMetaData, '\0', sizeof(mMetaData));
 }
 
@@ -57,7 +66,7 @@
         writeMetaData();
     }
 
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
 ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
@@ -154,7 +163,7 @@
     android::String8 prefix("");
     android::Vector<android::String16> aliases;
     UserState* userState = getUserState(userId);
-    if (list(prefix, &aliases, userId) != ::NO_ERROR) {
+    if (list(prefix, &aliases, userId) != ResponseCode::NO_ERROR) {
         return;
     }
     for (uint32_t i = 0; i < aliases.size(); i++) {
@@ -166,13 +175,28 @@
             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());
+            switch (rc) {
+            case ResponseCode::SYSTEM_ERROR:
+            case ResponseCode::VALUE_CORRUPTED:
+                // If we can't read blobs, delete them.
+                shouldDelete = true;
+                break;
+
+            case ResponseCode::NO_ERROR:
+            case ResponseCode::LOCKED:
+                // Delete encrypted blobs but keep unencrypted blobs and super-encrypted blobs.  We
+                // need to keep super-encrypted blobs so we can report that the user is
+                // unauthenticated if a caller tries to use them, rather than reporting that they
+                // don't exist.
+                shouldDelete = blob.isEncrypted();
+                break;
+
+            default:
+                ALOGE("Got unexpected return code %d from KeyStore::get()", rc);
+                // This shouldn't happen.  To be on the safe side, delete it.
+                shouldDelete = true;
+                break;
+            }
         }
         if (shouldDelete) {
             del(filename, ::TYPE_ANY, userId);
@@ -236,7 +260,7 @@
     UserState* userState = getUserState(userId);
     ResponseCode rc =
         keyBlob->readBlob(filename, userState->getDecryptionKey(), userState->getState());
-    if (rc != NO_ERROR) {
+    if (rc != ResponseCode::NO_ERROR) {
         return rc;
     }
 
@@ -247,28 +271,24 @@
          * it's written.
          */
         if (upgradeBlob(filename, keyBlob, version, type, userId)) {
-            if ((rc = this->put(filename, keyBlob, userId)) != NO_ERROR ||
+            if ((rc = this->put(filename, keyBlob, userId)) != ResponseCode::NO_ERROR ||
                 (rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
-                                        userState->getState())) != NO_ERROR) {
+                                        userState->getState())) != ResponseCode::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.
+     * This will upgrade software-backed keys to hardware-backed keys.
      */
-    if (rc == NO_ERROR && type == TYPE_KEY_PAIR &&
-        mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2 &&
-        keyBlob->isFallback()) {
+    if (rc == ResponseCode::NO_ERROR && type == TYPE_KEY_PAIR && 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) {
+        // The HAL allowed the import, reget the key to have the "fresh" version.
+        if (imported == ResponseCode::NO_ERROR) {
             rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
         }
     }
@@ -281,7 +301,7 @@
 
     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 ResponseCode::KEY_NOT_FOUND;
     }
 
     return rc;
@@ -296,38 +316,27 @@
 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) {
+    if (rc == ResponseCode::VALUE_CORRUPTED) {
         // The file is corrupt, the best we can do is rm it.
-        return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+        return (unlink(filename) && errno != ENOENT) ?
+                ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
     }
-    if (rc != ::NO_ERROR) {
+    if (rc != ResponseCode::NO_ERROR) {
         return rc;
     }
 
-    if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
+    auto& dev = getDevice(keyBlob);
+
+    if (keyBlob.getType() == ::TYPE_KEY_PAIR || keyBlob.getType() == ::TYPE_KEYMASTER_10) {
+        auto ret = KS_HANDLE_HIDL_ERROR(dev->deleteKey(blob2hidlVec(keyBlob)));
+
         // 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;
+        if (ret != ErrorCode::OK && ret != ErrorCode::UNIMPLEMENTED)
+            return ResponseCode::SYSTEM_ERROR;
     }
 
-    return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+    return (unlink(filename) && errno != ENOENT) ?
+            ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
 }
 
 /*
@@ -376,7 +385,7 @@
     DIR* dir = opendir(userState->getUserDirName());
     if (!dir) {
         ALOGW("can't open directory for user: %s", strerror(errno));
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
 
     struct dirent* file;
@@ -407,7 +416,7 @@
         }
     }
     closedir(dir);
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
 void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
@@ -436,74 +445,74 @@
                                  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;
+        return ResponseCode::SYSTEM_ERROR;
     }
     Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
     if (!pkey.get()) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     int type = EVP_PKEY_type(pkey->type);
-    android::KeymasterArguments params;
-    add_legacy_key_authorizations(type, &params.params);
+    AuthorizationSet params;
+    add_legacy_key_authorizations(type, &params);
     switch (type) {
     case EVP_PKEY_RSA:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+        params.push_back(TAG_ALGORITHM, Algorithm::RSA);
         break;
     case EVP_PKEY_EC:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+        params.push_back(TAG_ALGORITHM, Algorithm::EC);
         break;
     default:
         ALOGW("Unsupported key type %d", type);
-        return ::SYSTEM_ERROR;
+        return ResponseCode::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);
+    AuthorizationSet opParams(params);
+    hidl_vec<uint8_t> blob;
 
-        /*
-         * 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;
+    ErrorCode error;
+    auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+            const KeyCharacteristics& /* ignored */) {
+        error = ret;
+        if (error != ErrorCode::OK) return;
+        blob = keyBlob;
+    };
+    auto input = blob2hidlVec(key, keyLen);
 
-        if (error) {
-            ALOGE("Keymaster error while importing key pair with fallback: %d", error);
-            return SYSTEM_ERROR;
-        }
+    ErrorCode rc = KS_HANDLE_HIDL_ERROR(
+            mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
+    if (rc != ErrorCode::OK) return ResponseCode::SYSTEM_ERROR;
+    if (error != ErrorCode::OK) {
+        ALOGE("Keymaster error %d importing key pair", error);
+        return ResponseCode::SYSTEM_ERROR;
     }
 
-    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
-    free(const_cast<uint8_t*>(blob.key_material));
+    Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10);
 
     keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-    keyBlob.setFallback(isFallback);
+    keyBlob.setFallback(false);
 
     return put(filename, &keyBlob, userId);
 }
 
-bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
+bool KeyStore::isHardwareBacked(const android::String16& /*keyType*/) const {
+    using ::android::hardware::hidl_string;
     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);
+    bool isSecure = false;
+    auto hidlcb = [&] (bool _isSecure, bool, bool, bool, bool, const hidl_string&,
+                       const hidl_string&) {
+        isSecure = _isSecure;
+    };
+    auto rc = mDevice->getHardwareFeatures(hidlcb);
+    if (!rc.isOk()) {
+        ALOGE("Communication with keymaster HAL failed while retrieving hardware features (%s)",
+                rc.description().c_str());
+        return false;
     }
+    return isSecure;
 }
 
 ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
@@ -512,7 +521,7 @@
     uid_t userId = get_user_id(uid);
 
     ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
-    if (responseCode == NO_ERROR) {
+    if (responseCode == ResponseCode::NO_ERROR) {
         return responseCode;
     }
 
@@ -521,7 +530,7 @@
     if (euid != uid) {
         filepath8 = getKeyNameForUidWithDir(keyName, euid, type);
         responseCode = get(filepath8.string(), keyBlob, type, userId);
-        if (responseCode == NO_ERROR) {
+        if (responseCode == ResponseCode::NO_ERROR) {
             return responseCode;
         }
     }
@@ -531,7 +540,7 @@
     char* end;
     strtoul(filename8.string(), &end, 10);
     if (end[0] != '_' || end[1] == 0) {
-        return KEY_NOT_FOUND;
+        return ResponseCode::KEY_NOT_FOUND;
     }
     filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
                                          filename8.string());
@@ -645,32 +654,32 @@
     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;
+        return ResponseCode::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;
+        return ResponseCode::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;
+        return ResponseCode::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;
+        return ResponseCode::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) {
+    if (rc != ResponseCode::NO_ERROR) {
         return rc;
     }
 
diff --git a/keystore/keystore.h b/keystore/keystore.h
index 278a0a0..8ff8899 100644
--- a/keystore/keystore.h
+++ b/keystore/keystore.h
@@ -19,27 +19,43 @@
 
 #include "user_state.h"
 
-#include <hardware/keymaster2.h>
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
 
 #include <utils/Vector.h>
 
 #include "blob.h"
+#include "include/keystore/keymaster_tags.h"
 
 typedef struct {
     uint32_t uid;
     const uint8_t* filename;
 } grant_t;
 
+using ::keystore::NullOr;
+
 class KeyStore {
+    typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+
   public:
-    KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback);
+    KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
+             bool allowNewFallback);
     ~KeyStore();
 
-    keymaster2_device_t* getDevice() const { return mDevice; }
+    km_device_t& getDevice() { return mDevice; }
 
-    keymaster2_device_t* getFallbackDevice() const { return mFallbackDevice; }
+    NullOr<km_device_t&> getFallbackDevice() {
+        // we only return the fallback device if the creation of new fallback key blobs is
+        // allowed. (also see getDevice below)
+        if (mAllowNewFallback) {
+            return mFallbackDevice;
+        } else {
+            return {};
+        }
+    }
 
-    keymaster2_device_t* getDeviceForBlob(const Blob& blob) const {
+    km_device_t& getDevice(const Blob& blob) {
+        // We return a device, based on the nature of the blob to provide backward
+        // compatibility with old key blobs generated using the fallback device.
         return blob.isFallback() ? mFallbackDevice : mDevice;
     }
 
@@ -115,8 +131,9 @@
     static const android::String16 sRSAKeyType;
     Entropy* mEntropy;
 
-    keymaster2_device_t* mDevice;
-    keymaster2_device_t* mFallbackDevice;
+    km_device_t mDevice;
+    km_device_t mFallbackDevice;
+    bool mAllowNewFallback;
 
     android::Vector<UserState*> mMasterKeys;
 
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.cpp b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
new file mode 100644
index 0000000..3137ae1
--- /dev/null
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
@@ -0,0 +1,225 @@
+/*
+**
+** Copyright 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 "KeystoreService"
+#include <utils/Log.h>
+
+#include "keystore_aidl_hidl_marshalling_utils.h"
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in, bool inPlace) {
+    ssize_t length = in.readInt32();
+    if (length <= 0) {
+        return {};
+    }
+
+    const void* buf = in.readInplace(length);
+    if (!buf) return {};
+
+    return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace);
+}
+
+android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out) {
+    int32_t size = int32_t(std::min<size_t>(blob.size(), std::numeric_limits<int32_t>::max()));
+
+    auto rc = out->writeInt32(size);
+    if (rc != ::android::OK) return rc;
+
+    if (!size) return ::android::OK;
+
+    return out->write(&blob[0], size);
+}
+
+NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace) {
+    // The distinction from readKeymasterBob is that the byte array is not prefixed with a presence
+    // value, instead a -1 in the length field indicates NULL.
+    ssize_t length = in.readInt32();
+    if (length < 0) {
+        return {};
+    }
+
+    if (length == 0) {
+        return hidl_vec<uint8_t>();
+    }
+
+    const void* buf = in.readInplace(length);
+    if (!buf) return hidl_vec<uint8_t>();
+
+    return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace);
+}
+
+android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob,
+                                       android::Parcel* out) {
+    if (!blob.isOk()) {
+        return out->writeInt32(-1);
+    }
+    int32_t size =
+        int32_t(std::min<size_t>(blob.value().size(), std::numeric_limits<int32_t>::max()));
+
+    auto rc = out->writeInt32(size);
+    if (rc != ::android::OK) return rc;
+
+    if (!size) return ::android::OK;
+
+    return out->write(&blob.value()[0], size);
+}
+
+NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) {
+    if (in.readInt32() == 0) {
+        return {};
+    }
+    KeyParameter result;
+
+    Tag tag = static_cast<Tag>(in.readInt32());
+    result.tag = tag;
+    switch (typeFromTag(tag)) {
+    case TagType::ENUM:
+    case TagType::ENUM_REP:
+    case TagType::UINT:
+    case TagType::UINT_REP:
+        result.f.integer = in.readInt32();
+        break;
+    case TagType::ULONG:
+    case TagType::ULONG_REP:
+    case TagType::DATE:
+        result.f.longInteger = in.readInt64();
+        break;
+    case TagType::BOOL:
+        result.f.boolValue = true;
+        break;
+    case TagType::BIGNUM:
+    case TagType::BYTES:
+        result.blob = readKeymasterBlob(in);
+        break;
+    default:
+        ALOGE("Unsupported KeyParameter tag %d", tag);
+        return {};
+    }
+    return result;
+}
+
+android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out) {
+    auto tag = param.tag;
+    auto rc = out->writeInt32(uint32_t(tag));
+    if (rc != ::android::OK) return rc;
+    switch (typeFromTag(param.tag)) {
+    case TagType::ENUM:
+    case TagType::ENUM_REP:
+    case TagType::UINT:
+    case TagType::UINT_REP:
+        rc = out->writeInt32(param.f.integer);
+        break;
+    case TagType::ULONG:
+    case TagType::ULONG_REP:
+    case TagType::DATE:
+        rc = out->writeInt64(param.f.longInteger);
+        break;
+    case TagType::BOOL:
+        // nothing to do here presence indicates true
+        break;
+    case TagType::BIGNUM:
+    case TagType::BYTES:
+        rc = writeKeymasterBlob(param.blob, out);
+        break;
+    default:
+        ALOGE("Failed to write KeyParameter: Unsupported tag %d", param.tag);
+        rc = android::BAD_VALUE;
+        break;
+    }
+    return rc;
+}
+
+hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in) {
+    ssize_t length = in.readInt32();
+    size_t ulength = (size_t)length;
+    if (length < 0) {
+        ulength = 0;
+    }
+    hidl_vec<KeyParameter> result;
+    result.resize(ulength);
+    for (size_t i = 0; i < ulength; ++i) {
+        auto param = readKeyParameterFromParcel(in);
+        if (!param.isOk()) {
+            ALOGE("Error reading KeyParameter from parcel");
+            return {};
+        }
+        result[i] = param.value();
+    }
+    return result;
+}
+
+android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params,
+                                        android::Parcel* out) {
+    int32_t size = int32_t(std::min<size_t>(params.size(), std::numeric_limits<int32_t>::max()));
+
+    auto rc = out->writeInt32(size);
+    if (rc != ::android::OK) return rc;
+    for (int32_t i = 0; i < size; ++i) {
+        rc = out->writeInt32(1);
+        if (rc != ::android::OK) return rc;
+        rc = writeKeyParameterToParcel(params[i], out);
+        if (rc != ::android::OK) return rc;
+    }
+    return rc;
+}
+
+KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in) {
+    KeyCharacteristics result;
+    result.softwareEnforced = readParamSetFromParcel(in);
+    result.teeEnforced = readParamSetFromParcel(in);
+    return result;
+}
+
+android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara,
+                                                  android::Parcel* out) {
+    auto rc = writeParamSetToParcel(keyChara.softwareEnforced, out);
+    if (rc != ::android::OK) return rc;
+
+    return writeParamSetToParcel(keyChara.teeEnforced, out);
+}
+
+hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in) {
+    hidl_vec<hidl_vec<uint8_t>> result;
+
+    ssize_t count = in.readInt32();
+    size_t ucount = count;
+    if (count <= 0) {
+        return result;
+    }
+
+    result.resize(ucount);
+
+    for (size_t i = 0; i < ucount; ++i) {
+        result[i] = readKeymasterBlob(in);
+    }
+    return result;
+}
+
+android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
+                                                android::Parcel* out) {
+    int32_t count = int32_t(std::min<size_t>(certs.size(), std::numeric_limits<int32_t>::max()));
+    auto rc = out->writeInt32(count);
+
+    for (int32_t i = 0; i < count; ++i) {
+        rc = writeKeymasterBlob(certs[i], out);
+        if (rc != ::android::OK) return rc;
+    }
+    return rc;
+}
+}
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.h b/keystore/keystore_aidl_hidl_marshalling_utils.h
new file mode 100644
index 0000000..fcd02ae
--- /dev/null
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.h
@@ -0,0 +1,83 @@
+/*
+**
+** Copyright 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_AIDL_HIDL_MARSHALLING_UTILS_H_
+#define KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
+
+#include <binder/Parcel.h>
+#include <keystore/keymaster_tags.h>
+#include <utility>
+
+namespace keystore {
+
+template <typename Fn, typename... Args>
+inline auto nullable(Fn fn, const android::Parcel& in, Args&&... args)
+    -> NullOr<decltype(fn(in, std::forward<Args>(args)...))> {
+    if (in.readInt32() != 1) {
+        return {};
+    }
+
+    return fn(in, std::forward<Args>(args)...);
+}
+template <typename Fn, typename Arg>
+inline android::status_t nullable(Fn fn, const NullOr<Arg>& arg, android::Parcel* out) {
+    if (!arg.isOk()) {
+        return out->writeInt32(0);
+    }
+    auto rc = out->writeInt32(1);
+    if (rc != ::android::OK) return rc;
+
+    return fn(arg.value(), out);
+}
+template <typename Fn, typename Arg>
+inline android::status_t nullable(Fn fn, Arg&& arg, android::Parcel* out) {
+    auto rc = out->writeInt32(1);
+    if (rc != ::android::OK) return rc;
+
+    return fn(std::forward<Arg>(arg), out);
+}
+
+inline android::status_t nullable(android::Parcel* out) {
+    return out->writeInt32(0);
+}
+
+/**
+ * makes a copy only if inPlace is false
+ */
+hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in, bool inPlace = true);
+android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out);
+
+NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace = true);
+android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob,
+                                       android::Parcel* out);
+
+NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in);
+android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out);
+
+hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in);
+android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params, android::Parcel* out);
+
+KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in);
+android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara,
+                                                  android::Parcel* out);
+
+hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in);
+android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
+                                                android::Parcel* out);
+}
+
+#endif  // KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
new file mode 100644
index 0000000..830482b
--- /dev/null
+++ b/keystore/keystore_attestation_id.cpp
@@ -0,0 +1,245 @@
+/*
+ * 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_attestation_id.h"
+
+#define LOG_TAG "keystore_att_id"
+
+#include <cutils/log.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+
+#include <android/security/keymaster/BpKeyAttestationApplicationIdProvider.h>
+#include <android/security/keymaster/IKeyAttestationApplicationIdProvider.h>
+#include <keystore/KeyAttestationApplicationId.h>
+#include <keystore/KeyAttestationPackageInfo.h>
+#include <keystore/Signature.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/sha.h>
+
+#include <utils/String8.h>
+
+namespace android {
+
+namespace {
+
+static std::vector<uint8_t> signature2SHA256(const content::pm::Signature& sig) {
+    std::vector<uint8_t> digest_buffer(SHA256_DIGEST_LENGTH);
+    SHA256(sig.data().data(), sig.data().size(), digest_buffer.data());
+    return digest_buffer;
+}
+
+using ::android::security::keymaster::BpKeyAttestationApplicationIdProvider;
+
+class KeyAttestationApplicationIdProvider : public BpKeyAttestationApplicationIdProvider {
+  public:
+    KeyAttestationApplicationIdProvider();
+
+    static KeyAttestationApplicationIdProvider& get();
+
+  private:
+    android::sp<android::IServiceManager> service_manager_;
+};
+
+KeyAttestationApplicationIdProvider& KeyAttestationApplicationIdProvider::get() {
+    static KeyAttestationApplicationIdProvider mpm;
+    return mpm;
+}
+
+KeyAttestationApplicationIdProvider::KeyAttestationApplicationIdProvider()
+    : BpKeyAttestationApplicationIdProvider(
+          android::defaultServiceManager()->getService(String16("sec_key_att_app_id_provider"))) {}
+
+DECLARE_STACK_OF(ASN1_OCTET_STRING);
+
+typedef struct km_attestation_package_info {
+    ASN1_OCTET_STRING* package_name;
+    ASN1_INTEGER* version;
+} KM_ATTESTATION_PACKAGE_INFO;
+
+ASN1_SEQUENCE(KM_ATTESTATION_PACKAGE_INFO) = {
+    ASN1_SIMPLE(KM_ATTESTATION_PACKAGE_INFO, package_name, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(KM_ATTESTATION_PACKAGE_INFO, version, ASN1_INTEGER),
+} ASN1_SEQUENCE_END(KM_ATTESTATION_PACKAGE_INFO);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ATTESTATION_PACKAGE_INFO);
+
+DECLARE_STACK_OF(KM_ATTESTATION_PACKAGE_INFO);
+
+typedef struct km_attestation_application_id {
+    STACK_OF(KM_ATTESTATION_PACKAGE_INFO) * package_infos;
+    STACK_OF(ASN1_OCTET_STRING) * signature_digests;
+} KM_ATTESTATION_APPLICATION_ID;
+
+ASN1_SEQUENCE(KM_ATTESTATION_APPLICATION_ID) = {
+    ASN1_SET_OF(KM_ATTESTATION_APPLICATION_ID, package_infos, KM_ATTESTATION_PACKAGE_INFO),
+    ASN1_SET_OF(KM_ATTESTATION_APPLICATION_ID, signature_digests, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(KM_ATTESTATION_APPLICATION_ID);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ATTESTATION_APPLICATION_ID);
+}
+
+}  // namespace android
+
+namespace std {
+template <> struct default_delete<android::KM_ATTESTATION_PACKAGE_INFO> {
+    void operator()(android::KM_ATTESTATION_PACKAGE_INFO* p) {
+        android::KM_ATTESTATION_PACKAGE_INFO_free(p);
+    }
+};
+template <> struct default_delete<ASN1_OCTET_STRING> {
+    void operator()(ASN1_OCTET_STRING* p) { ASN1_OCTET_STRING_free(p); }
+};
+template <> struct default_delete<android::KM_ATTESTATION_APPLICATION_ID> {
+    void operator()(android::KM_ATTESTATION_APPLICATION_ID* p) {
+        android::KM_ATTESTATION_APPLICATION_ID_free(p);
+    }
+};
+}  // namespace std
+
+namespace android {
+namespace security {
+namespace {
+
+using ::android::security::keymaster::KeyAttestationApplicationId;
+using ::android::security::keymaster::KeyAttestationPackageInfo;
+
+status_t build_attestation_package_info(const KeyAttestationPackageInfo& pinfo,
+    std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO>* attestation_package_info_ptr) {
+
+    if (!attestation_package_info_ptr) return BAD_VALUE;
+    auto& attestation_package_info = *attestation_package_info_ptr;
+
+    attestation_package_info.reset(KM_ATTESTATION_PACKAGE_INFO_new());
+    if (!attestation_package_info.get()) return NO_MEMORY;
+
+    if (!pinfo.package_name()) {
+        ALOGE("Key attestation package info lacks package name");
+        return BAD_VALUE;
+    }
+
+    std::string pkg_name(String8(*pinfo.package_name()).string());
+    if (!ASN1_OCTET_STRING_set(attestation_package_info->package_name,
+                               reinterpret_cast<const unsigned char*>(pkg_name.data()),
+                               pkg_name.size())) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (!ASN1_INTEGER_set(attestation_package_info->version, pinfo.version_code())) {
+        return UNKNOWN_ERROR;
+    }
+    return NO_ERROR;
+}
+
+StatusOr<std::vector<uint8_t>>
+build_attestation_application_id(const KeyAttestationApplicationId& key_attestation_id) {
+    auto attestation_id =
+        std::unique_ptr<KM_ATTESTATION_APPLICATION_ID>(KM_ATTESTATION_APPLICATION_ID_new());
+
+    auto attestation_pinfo_stack = reinterpret_cast<_STACK*>(attestation_id->package_infos);
+
+    if (key_attestation_id.pinfos_begin() == key_attestation_id.pinfos_end()) return BAD_VALUE;
+
+    for (auto pinfo = key_attestation_id.pinfos_begin(); pinfo != key_attestation_id.pinfos_end();
+         ++pinfo) {
+        if (!pinfo->package_name()) {
+            ALOGE("Key attestation package info lacks package name");
+            return BAD_VALUE;
+        }
+        std::string package_name(String8(*pinfo->package_name()).string());
+        std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO> attestation_package_info;
+        auto rc = build_attestation_package_info(*pinfo, &attestation_package_info);
+        if (rc != NO_ERROR) {
+            ALOGE("Building DER attestation package info failed %d", rc);
+            return rc;
+        }
+        if (!sk_push(attestation_pinfo_stack, attestation_package_info.get())) {
+            return NO_MEMORY;
+        }
+        // if push succeeded, the stack takes ownership
+        attestation_package_info.release();
+    }
+
+    /** Apps can only share a uid iff they were signed with the same certificate(s). Because the
+     *  signature field actually holds the signing certificate, rather than a signature, we can
+     *  simply use the set of signature digests of the first package info.
+     */
+    const auto& pinfo = *key_attestation_id.pinfos_begin();
+    std::vector<std::vector<uint8_t>> signature_digests;
+
+    for (auto sig = pinfo.sigs_begin(); sig != pinfo.sigs_end(); ++sig) {
+        signature_digests.push_back(signature2SHA256(*sig));
+    }
+
+    auto signature_digest_stack = reinterpret_cast<_STACK*>(attestation_id->signature_digests);
+    for (auto si : signature_digests) {
+        auto asn1_item = std::unique_ptr<ASN1_OCTET_STRING>(ASN1_OCTET_STRING_new());
+        if (!asn1_item) return NO_MEMORY;
+        if (!ASN1_OCTET_STRING_set(asn1_item.get(), si.data(), si.size())) {
+            return UNKNOWN_ERROR;
+        }
+        if (!sk_push(signature_digest_stack, asn1_item.get())) {
+            return NO_MEMORY;
+        }
+        asn1_item.release();  // if push succeeded, the stack takes ownership
+    }
+
+    int len = i2d_KM_ATTESTATION_APPLICATION_ID(attestation_id.get(), nullptr);
+    if (len < 0) return UNKNOWN_ERROR;
+
+    std::vector<uint8_t> result(len);
+    uint8_t* p = result.data();
+    len = i2d_KM_ATTESTATION_APPLICATION_ID(attestation_id.get(), &p);
+    if (len < 0) return UNKNOWN_ERROR;
+
+    return result;
+}
+
+/* The following function are not used. They are mentioned here to silence
+ * warnings about them not being used.
+ */
+void unused_functions_silencer() __attribute__((unused));
+void unused_functions_silencer() {
+    i2d_KM_ATTESTATION_PACKAGE_INFO(nullptr, nullptr);
+    d2i_KM_ATTESTATION_APPLICATION_ID(nullptr, nullptr, 0);
+    d2i_KM_ATTESTATION_PACKAGE_INFO(nullptr, nullptr, 0);
+}
+
+}  // namespace
+
+StatusOr<std::vector<uint8_t>> gather_attestation_application_id(uid_t uid) {
+    auto& pm = KeyAttestationApplicationIdProvider::get();
+
+    /* Get the attestation application ID from package manager */
+    KeyAttestationApplicationId key_attestation_id;
+    auto status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+    if (!status.isOk()) {
+        ALOGE("package manager request for key attestation ID failed with: %s",
+              status.exceptionMessage().string());
+        return FAILED_TRANSACTION;
+    }
+
+    /* DER encode the attestation application ID */
+    return build_attestation_application_id(key_attestation_id);
+}
+
+}  // namespace security
+}  // namespace android
diff --git a/keystore/keystore_attestation_id.h b/keystore/keystore_attestation_id.h
new file mode 100644
index 0000000..8d20550
--- /dev/null
+++ b/keystore/keystore_attestation_id.h
@@ -0,0 +1,62 @@
+/*
+ * 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_ATTESTATION_ID_H_
+#define KEYSTORE_KEYSTORE_ATTESTATION_ID_H_
+
+#include <utils/Errors.h>
+#include <vector>
+
+namespace android {
+namespace security {
+
+template <typename T> class StatusOr {
+  public:
+    StatusOr(const status_t error) : _status(error), _value() {}
+    StatusOr(const T& value) : _status(NO_ERROR), _value(value) {}
+    StatusOr(T&& value) : _status(NO_ERROR), _value(value) {}
+
+    operator const T&() const { return _value; }
+    operator T&() { return _value; }
+    operator T &&() && { return std::move(_value); }
+
+    bool isOk() const { return NO_ERROR == _status; }
+
+    ::android::status_t status() const { return _status; }
+
+    const T& value() const & { return _value; }
+    T& value() & { return _value; }
+    T&& value() && { return std::move(_value); }
+
+  private:
+    ::android::status_t _status;
+    T _value;
+};
+
+/**
+ * Gathers the attestation id for the application determined by uid by querying the package manager
+ * As of this writing uids can be shared in android, which is why the asn.1 encoded attestation
+ * application id may contain more than one package info followed by a set of digests of the
+ * packages signing certificates.
+ *
+ * @returns the asn.1 encoded attestation application id or an error code. Check the result with
+ *          .isOk() before accessing.
+ */
+StatusOr<std::vector<uint8_t>> gather_attestation_application_id(uid_t uid);
+
+}  // namespace security
+}  // namespace android
+#endif  // KEYSTORE_KEYSTORE_ATTESTATION_ID_H_
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index d9781e0..24af024 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -26,6 +26,7 @@
 #include <keystore/keystore.h>
 
 using namespace android;
+using namespace keystore;
 
 static const char* responses[] = {
     NULL,
@@ -124,14 +125,13 @@
                 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
                 return 1; \
             } \
-            uint8_t* data; \
-            size_t dataSize; \
+            hidl_vec<uint8_t> data; \
             int uid = -1; \
             if (argc > 3) { \
                 uid = atoi(argv[3]); \
                 fprintf(stderr, "Running as uid %d\n", uid); \
             } \
-            int32_t ret = service->cmd(String16(argv[2]), uid, &data, &dataSize); \
+            int32_t ret = service->cmd(String16(argv[2]), uid, &data); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -139,9 +139,8 @@
                 fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
                 return 1; \
             } else { \
-                fwrite(data, dataSize, 1, stdout); \
+                fwrite(&data[0], data.size(), 1, stdout); \
                 fflush(stdout); \
-                free(data); \
                 return 0; \
             } \
         } \
@@ -175,9 +174,8 @@
                 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); \
+            hidl_vec<uint8_t> data; \
+            int32_t ret = service->cmd(String16(argv[2]), &data); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -185,9 +183,8 @@
                 fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
                 return 1; \
             } else { \
-                fwrite(data, dataSize, 1, stdout); \
+                fwrite(&data[0], data.size(), 1, stdout); \
                 fflush(stdout); \
-                free(data); \
                 return 0; \
             } \
         } \
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 6c229db..95fc491 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -20,16 +20,17 @@
 #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/authorization_set.h"
+#include "keystore/keymaster_tags.h"
 #include "keystore/keystore_client_impl.h"
 
 using base::CommandLine;
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
+using keystore::AuthorizationSet;
+//using keymaster::AuthorizationSetBuilder;
 using keystore::KeystoreClient;
 
 namespace {
+using namespace keystore;
 
 struct TestCase {
     std::string name;
@@ -55,17 +56,13 @@
 }
 
 std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
-    return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
+    return std::unique_ptr<KeystoreClient>(
+            static_cast<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));
+    for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
+        printf("  %s\n", stringifyTag(iter->tag));
     }
 }
 
@@ -81,16 +78,16 @@
     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    int32_t result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
+    auto result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
                                            &software_enforced_characteristics);
     const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
-    if (result != KM_ERROR_OK) {
+    if (!result.isOk()) {
         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) {
+    if (!result.isOk()) {
         LOG(ERROR) << "Failed to delete key: " << result;
         printf("[%s] %s\n", kBoldRedAbort, name.c_str());
         return false;
@@ -99,9 +96,9 @@
     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) {
+    if (software_enforced_characteristics.GetTagCount(TAG_ALGORITHM) > 0 ||
+        software_enforced_characteristics.GetTagCount(TAG_KEY_SIZE) > 0 ||
+        software_enforced_characteristics.GetTagCount(TAG_RSA_PUBLIC_EXPONENT) > 0) {
         VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
         hardware_backed = false;
     }
@@ -118,62 +115,62 @@
 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);
+        .Digest(Digest::SHA_2_256)
+        .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+        .Padding(PaddingMode::RSA_PSS)
+        .Authorization(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);
+        parameters.Digest(Digest::SHA_2_224)
+            .Digest(Digest::SHA_2_384)
+            .Digest(Digest::SHA_2_512);
     }
-    return parameters.build();
+    return parameters;
 }
 
 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();
+        .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
+        .Padding(PaddingMode::RSA_OAEP)
+        .Authorization(TAG_NO_AUTH_REQUIRED);
+    return parameters;
 }
 
 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);
+        .Digest(Digest::SHA_2_256)
+        .Authorization(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);
+        parameters.Digest(Digest::SHA_2_224)
+            .Digest(Digest::SHA_2_384)
+            .Digest(Digest::SHA_2_512);
     }
-    return parameters.build();
+    return parameters;
 }
 
 AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
     AuthorizationSetBuilder parameters;
-    parameters.AesEncryptionKey(key_size).Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+    parameters.AesEncryptionKey(key_size).Authorization(TAG_NO_AUTH_REQUIRED);
     if (with_gcm_mode) {
-        parameters.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_GCM)
-            .Authorization(keymaster::TAG_MIN_MAC_LENGTH, 128);
+        parameters.Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+            .Authorization(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);
+        parameters.Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
+        parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
+        parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CTR);
+        parameters.Padding(PaddingMode::NONE);
     }
-    return parameters.build();
+    return parameters;
 }
 
-AuthorizationSet GetHMACParameters(uint32_t key_size, keymaster_digest_t digest) {
+AuthorizationSet GetHMACParameters(uint32_t key_size, Digest 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();
+        .Authorization(TAG_MIN_MAC_LENGTH, 224)
+        .Authorization(TAG_NO_AUTH_REQUIRED);
+    return parameters;
 }
 
 std::vector<TestCase> GetTestCases() {
@@ -194,12 +191,12 @@
         {"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)},
+        {"HMAC-SHA256-16", true, GetHMACParameters(16, Digest::SHA_2_256)},
+        {"HMAC-SHA256-32", true, GetHMACParameters(32, Digest::SHA_2_256)},
+        {"HMAC-SHA256-64", false, GetHMACParameters(64, Digest::SHA_2_256)},
+        {"HMAC-SHA224-32", false, GetHMACParameters(32, Digest::SHA_2_224)},
+        {"HMAC-SHA384-32", false, GetHMACParameters(32, Digest::SHA_2_384)},
+        {"HMAC-SHA512-32", false, GetHMACParameters(32, Digest::SHA_2_512)},
     };
     return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
 }
@@ -273,19 +270,19 @@
     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);
+        .Digest(Digest::SHA_2_224)
+        .Digest(Digest::SHA_2_256)
+        .Digest(Digest::SHA_2_384)
+        .Digest(Digest::SHA_2_512)
+        .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+        .Padding(PaddingMode::RSA_PSS)
+        .Authorization(TAG_NO_AUTH_REQUIRED);
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
+    auto result = keystore->generateKey(name, params, &hardware_enforced_characteristics,
                                            &software_enforced_characteristics);
-    printf("GenerateKey: %d\n", result);
-    if (result == KM_ERROR_OK) {
+    printf("GenerateKey: %d\n", int32_t(result));
+    if (result.isOk()) {
         PrintKeyCharacteristics(hardware_enforced_characteristics,
                                 software_enforced_characteristics);
     }
@@ -296,10 +293,10 @@
     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
+    auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
                                                      &software_enforced_characteristics);
-    printf("GetCharacteristics: %d\n", result);
-    if (result == KM_ERROR_OK) {
+    printf("GetCharacteristics: %d\n", int32_t(result));
+    if (result.isOk()) {
         PrintKeyCharacteristics(hardware_enforced_characteristics,
                                 software_enforced_characteristics);
     }
@@ -309,7 +306,7 @@
 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);
+    int32_t result = keystore->exportKey(KeyFormat::X509, name, &data);
     printf("ExportKey: %d (%zu)\n", result, data.size());
     return result;
 }
@@ -351,14 +348,14 @@
 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);
+    sign_params.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
+    sign_params.Digest(Digest::SHA_2_256);
     AuthorizationSet output_params;
-    keymaster_operation_handle_t handle;
-    int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
+    uint64_t handle;
+    auto result = keystore->beginOperation(KeyPurpose::SIGN, name, sign_params,
                                               &output_params, &handle);
-    if (result != KM_ERROR_OK) {
-        printf("Sign: BeginOperation failed: %d\n", result);
+    if (!result.isOk()) {
+        printf("Sign: BeginOperation failed: %d\n", int32_t(result));
         return result;
     }
     AuthorizationSet empty_params;
@@ -366,40 +363,40 @@
     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);
+    if (!result.isOk()) {
+        printf("Sign: UpdateOperation failed: %d\n", int32_t(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);
+    if (!result.isOk()) {
+        printf("Sign: FinishOperation failed: %d\n", int32_t(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,
+    result = keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params,
                                       &handle);
-    if (result != KM_ERROR_OK) {
-        printf("Verify: BeginOperation failed: %d\n", result);
+    if (!result.isOk()) {
+        printf("Verify: BeginOperation failed: %d\n", int32_t(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);
+    if (!result.isOk()) {
+        printf("Verify: UpdateOperation failed: %d\n", int32_t(result));
         return result;
     }
     result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
                                        &output_data);
-    if (result == KM_ERROR_VERIFICATION_FAILED) {
+    if (result == ErrorCode::VERIFICATION_FAILED) {
         printf("Verify: Failed to verify signature.\n");
         return result;
     }
-    if (result != KM_ERROR_OK) {
-        printf("Verify: FinishOperation failed: %d\n", result);
+    if (!result.isOk()) {
+        printf("Verify: FinishOperation failed: %d\n", int32_t(result));
         return result;
     }
     printf("Verify: OK\n");
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index c3d8f35..f9df134 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -19,24 +19,25 @@
 #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 <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"
+#include <keystore/authorization_set.h>
+#include <keystore/keystore_hidl_support.h>
 
 using android::ExportResult;
-using android::KeyCharacteristics;
-using android::KeymasterArguments;
+using keystore::KeyCharacteristics;
 using android::OperationResult;
 using android::String16;
-using keymaster::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
+using keystore::AuthorizationSet;
+using keystore::AuthorizationSetBuilder;
 
 namespace {
 
@@ -44,24 +45,9 @@
 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);
-}
+constexpr uint32_t kAESKeySize = 256;      // bits
+constexpr uint32_t kHMACKeySize = 256;     // bits
+constexpr uint32_t kHMACOutputSize = 256;  // bits
 
 }  // namespace
 
@@ -89,29 +75,28 @@
         return false;
     }
     AuthorizationSetBuilder encrypt_params;
-    encrypt_params.Padding(KM_PAD_PKCS7);
-    encrypt_params.Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_CBC);
+    encrypt_params.Padding(PaddingMode::PKCS7);
+    encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
     AuthorizationSet output_params;
     std::string raw_encrypted_data;
-    if (!oneShotOperation(KM_PURPOSE_ENCRYPT, encryption_key_name, encrypt_params.build(), data,
+    if (!oneShotOperation(KeyPurpose::ENCRYPT, encryption_key_name, encrypt_params, 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)) {
+    auto init_vector_blob = output_params.GetTagValue(TAG_NONCE);
+    if (!init_vector_blob.isOk()){
         ALOGE("Encrypt: Missing initialization vector.");
         return false;
     }
-    std::string init_vector =
-        ByteArrayAsString(init_vector_blob.data, init_vector_blob.data_length);
+    std::string init_vector = hidlVec2String(init_vector_blob.value());
 
     AuthorizationSetBuilder authenticate_params;
-    authenticate_params.Digest(KM_DIGEST_SHA_2_256);
-    authenticate_params.Authorization(keymaster::TAG_MAC_LENGTH, kHMACOutputSize);
+    authenticate_params.Digest(Digest::SHA_2_256);
+    authenticate_params.Authorization(TAG_MAC_LENGTH, kHMACOutputSize);
     std::string raw_authentication_data;
-    if (!oneShotOperation(KM_PURPOSE_SIGN, authentication_key_name, authenticate_params.build(),
+    if (!oneShotOperation(KeyPurpose::SIGN, authentication_key_name, authenticate_params,
                           init_vector + raw_encrypted_data, std::string(), /* signature_to_verify */
                           &output_params, &raw_authentication_data)) {
         ALOGE("Encrypt: HMAC operation failed.");
@@ -138,10 +123,10 @@
     // Verify authentication before attempting decryption.
     std::string authentication_key_name = key_name + kAuthenticateSuffix;
     AuthorizationSetBuilder authenticate_params;
-    authenticate_params.Digest(KM_DIGEST_SHA_2_256);
+    authenticate_params.Digest(Digest::SHA_2_256);
     AuthorizationSet output_params;
     std::string output_data;
-    if (!oneShotOperation(KM_PURPOSE_VERIFY, authentication_key_name, authenticate_params.build(),
+    if (!oneShotOperation(KeyPurpose::VERIFY, authentication_key_name, authenticate_params,
                           protobuf.init_vector() + protobuf.encrypted_data(),
                           protobuf.authentication_data(), &output_params, &output_data)) {
         ALOGE("Decrypt: HMAC operation failed.");
@@ -149,11 +134,11 @@
     }
     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(),
+    encrypt_params.Padding(PaddingMode::PKCS7);
+    encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
+    encrypt_params.Authorization(TAG_NONCE, protobuf.init_vector().data(),
                                  protobuf.init_vector().size());
-    if (!oneShotOperation(KM_PURPOSE_DECRYPT, encryption_key_name, encrypt_params.build(),
+    if (!oneShotOperation(KeyPurpose::DECRYPT, encryption_key_name, encrypt_params,
                           protobuf.encrypted_data(), std::string(), /* signature_to_verify */
                           &output_params, data)) {
         ALOGE("Decrypt: AES operation failed.");
@@ -162,17 +147,17 @@
     return true;
 }
 
-bool KeystoreClientImpl::oneShotOperation(keymaster_purpose_t purpose, const std::string& key_name,
-                                          const keymaster::AuthorizationSet& input_parameters,
+bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string& key_name,
+                                          const AuthorizationSet& input_parameters,
                                           const std::string& input_data,
                                           const std::string& signature_to_verify,
-                                          keymaster::AuthorizationSet* output_parameters,
+                                          AuthorizationSet* output_parameters,
                                           std::string* output_data) {
-    keymaster_operation_handle_t handle;
-    int32_t result =
+    uint64_t handle;
+    auto result =
         beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
-    if (result != KM_ERROR_OK) {
-        ALOGE("BeginOperation failed: %d", result);
+    if (!result.isOk()) {
+        ALOGE("BeginOperation failed: %d", int32_t(result));
         return false;
     }
     AuthorizationSet empty_params;
@@ -180,174 +165,172 @@
     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);
+    if (!result.isOk()) {
+        ALOGE("UpdateOperation failed: %d", int32_t(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);
+    if (!result.isOk()) {
+        ALOGE("FinishOperation failed: %d", int32_t(result));
         return false;
     }
     return true;
 }
 
-int32_t KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
-    return mapKeystoreError(keystore_->addRngEntropy(StringAsByteArray(entropy), entropy.size()));
+KeyStoreNativeReturnCode KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
+    return keystore_->addRngEntropy(blob2hidlVec(entropy));
 }
 
-int32_t KeystoreClientImpl::generateKey(const std::string& key_name,
+KeyStoreNativeReturnCode 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*/,
+    auto result =
+        keystore_->generateKey(key_name16, key_parameters.hidl_data(), hidl_vec<uint8_t>(),
                                kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
-    hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
-    software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
-    return mapKeystoreError(result);
+
+    /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
+     * There are no references to Parcel memory after that, and ownership of the newly acquired
+     * memory is with the AuthorizationSet objects. */
+    *hardware_enforced_characteristics = characteristics.teeEnforced;
+    *software_enforced_characteristics = characteristics.softwareEnforced;
+    return result;
 }
 
-int32_t
+KeyStoreNativeReturnCode
 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,
+    auto result = keystore_->getKeyCharacteristics(key_name16, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
                                                       kDefaultUID, &characteristics);
-    hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
-    software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
-    return mapKeystoreError(result);
+
+    /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
+     * There are no references to Parcel memory after that, and ownership of the newly acquired
+     * memory is with the AuthorizationSet objects. */
+    *hardware_enforced_characteristics = characteristics.teeEnforced;
+    *software_enforced_characteristics = characteristics.softwareEnforced;
+    return result;
 }
 
-int32_t KeystoreClientImpl::importKey(const std::string& key_name,
+KeyStoreNativeReturnCode KeystoreClientImpl::importKey(const std::string& key_name,
                                       const AuthorizationSet& key_parameters,
-                                      keymaster_key_format_t key_format,
+                                      KeyFormat 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);
+    auto hidlKeyData = blob2hidlVec(key_data);
     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);
+    auto result = keystore_->importKey(key_name16, key_parameters.hidl_data(), key_format,
+            hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+
+    /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
+     * There are no references to Parcel memory after that, and ownership of the newly acquired
+     * memory is with the AuthorizationSet objects. */
+    *hardware_enforced_characteristics = characteristics.teeEnforced;
+    *software_enforced_characteristics = characteristics.softwareEnforced;
+    return result;
 }
 
-int32_t KeystoreClientImpl::exportKey(keymaster_key_format_t export_format,
+KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat 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,
+    keystore_->exportKey(key_name16, export_format, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
                          kDefaultUID, &export_result);
-    *export_data = ByteArrayAsString(export_result.exportData.get(), export_result.dataLength);
-    return mapKeystoreError(export_result.resultCode);
+    *export_data = hidlVec2String(export_result.exportData);
+    return export_result.resultCode;
 }
 
-int32_t KeystoreClientImpl::deleteKey(const std::string& key_name) {
+KeyStoreNativeReturnCode KeystoreClientImpl::deleteKey(const std::string& key_name) {
     String16 key_name16(key_name.data(), key_name.size());
-    return mapKeystoreError(keystore_->del(key_name16, kDefaultUID));
+    return keystore_->del(key_name16, kDefaultUID);
 }
 
-int32_t KeystoreClientImpl::deleteAllKeys() {
-    return mapKeystoreError(keystore_->clear_uid(kDefaultUID));
+KeyStoreNativeReturnCode KeystoreClientImpl::deleteAllKeys() {
+    return keystore_->clear_uid(kDefaultUID);
 }
 
-int32_t KeystoreClientImpl::beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+KeyStoreNativeReturnCode KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_name,
                                            const AuthorizationSet& input_parameters,
                                            AuthorizationSet* output_parameters,
-                                           keymaster_operation_handle_t* handle) {
+                                           uint64_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*/, kDefaultUID, &result);
-    int32_t error_code = mapKeystoreError(result.resultCode);
-    if (error_code == KM_ERROR_OK) {
+    keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_parameters.hidl_data(),
+                     hidl_vec<uint8_t>(), kDefaultUID, &result);
+    if (result.resultCode.isOk()) {
         *handle = getNextVirtualHandle();
         active_operations_[*handle] = result.token;
-        if (!result.outParams.params.empty()) {
-            output_parameters->Reinitialize(&*result.outParams.params.begin(),
-                                            result.outParams.params.size());
+        if (result.outParams.size()) {
+            *output_parameters = result.outParams;
         }
     }
-    return error_code;
+    return result.resultCode;
 }
 
-int32_t KeystoreClientImpl::updateOperation(keymaster_operation_handle_t handle,
+KeyStoreNativeReturnCode KeystoreClientImpl::updateOperation(uint64_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;
+        return ErrorCode::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) {
+    auto hidlInputData = blob2hidlVec(input_data);
+    keystore_->update(active_operations_[handle], input_parameters.hidl_data(), hidlInputData,
+            &result);
+
+    if (result.resultCode.isOk()) {
         *num_input_bytes_consumed = result.inputConsumed;
-        if (!result.outParams.params.empty()) {
-            output_parameters->Reinitialize(&*result.outParams.params.begin(),
-                                            result.outParams.params.size());
+        if (result.outParams.size()) {
+            *output_parameters = result.outParams;
         }
-        output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+        // TODO verify that append should not be assign
+        output_data->append(hidlVec2String(result.data));
     }
-    return error_code;
+    return result.resultCode;
 }
 
-int32_t KeystoreClientImpl::finishOperation(keymaster_operation_handle_t handle,
+KeyStoreNativeReturnCode KeystoreClientImpl::finishOperation(uint64_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;
+        return ErrorCode::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());
+    auto hidlSignature = blob2hidlVec(signature_to_verify);
+    keystore_->finish(active_operations_[handle], input_parameters.hidl_data(),
+                      hidlSignature,
+                      hidl_vec<uint8_t>(), &result);
+
+    if (result.resultCode.isOk()) {
+        if (result.outParams.size()) {
+            *output_parameters = result.outParams;
         }
-        output_data->append(ByteArrayAsString(result.data.get(), result.dataLength));
+        // TODO verify that append should not be assign
+        output_data->append(hidlVec2String(result.data));
         active_operations_.erase(handle);
     }
-    return error_code;
+    return result.resultCode;
 }
 
-int32_t KeystoreClientImpl::abortOperation(keymaster_operation_handle_t handle) {
+KeyStoreNativeReturnCode KeystoreClientImpl::abortOperation(uint64_t handle) {
     if (active_operations_.count(handle) == 0) {
-        return KM_ERROR_INVALID_OPERATION_HANDLE;
+        return ErrorCode::INVALID_OPERATION_HANDLE;
     }
-    int32_t error_code = mapKeystoreError(keystore_->abort(active_operations_[handle]));
-    if (error_code == KM_ERROR_OK) {
+    auto error_code = keystore_->abort(active_operations_[handle]);
+    if (error_code.isOk()) {
         active_operations_.erase(handle);
     }
     return error_code;
@@ -355,16 +338,16 @@
 
 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);
+    auto error_code = keystore_->exist(key_name16, kDefaultUID);
+    return error_code.isOk();
 }
 
 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) {
+    auto error_code = keystore_->list(prefix16, kDefaultUID, &matches);
+    if (error_code.isOk()) {
         for (const auto& match : matches) {
             android::String8 key_name(match);
             key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size()));
@@ -374,18 +357,10 @@
     return false;
 }
 
-keymaster_operation_handle_t KeystoreClientImpl::getNextVirtualHandle() {
+uint64_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) {
@@ -394,9 +369,9 @@
             return false;
         }
         if (!verified) {
-            int32_t result = deleteKey(key_name);
-            if (result != KM_ERROR_OK) {
-                ALOGE("Failed to delete invalid encryption key: %d", result);
+            auto result = deleteKey(key_name);
+            if (!result.isOk()) {
+                ALOGE("Failed to delete invalid encryption key: %d", int32_t(result));
                 return false;
             }
             key_exists = false;
@@ -405,16 +380,16 @@
     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);
+            .Padding(PaddingMode::PKCS7)
+            .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+            .Authorization(TAG_NO_AUTH_REQUIRED);
         AuthorizationSet hardware_enforced_characteristics;
         AuthorizationSet software_enforced_characteristics;
-        int32_t result =
-            generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+        auto result =
+            generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
                         &software_enforced_characteristics);
-        if (result != KM_ERROR_OK) {
-            ALOGE("Failed to generate encryption key: %d", result);
+        if (!result.isOk()) {
+            ALOGE("Failed to generate encryption key: %d", int32_t(result));
             return false;
         }
         if (hardware_enforced_characteristics.size() == 0) {
@@ -432,9 +407,9 @@
             return false;
         }
         if (!verified) {
-            int32_t result = deleteKey(key_name);
-            if (result != KM_ERROR_OK) {
-                ALOGE("Failed to delete invalid authentication key: %d", result);
+            auto result = deleteKey(key_name);
+            if (!result.isOk()) {
+                ALOGE("Failed to delete invalid authentication key: %d", int32_t(result));
                 return false;
             }
             key_exists = false;
@@ -443,16 +418,16 @@
     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);
+            .Digest(Digest::SHA_2_256)
+            .Authorization(TAG_MIN_MAC_LENGTH, kHMACOutputSize)
+            .Authorization(TAG_NO_AUTH_REQUIRED);
         AuthorizationSet hardware_enforced_characteristics;
         AuthorizationSet software_enforced_characteristics;
-        int32_t result =
-            generateKey(key_name, key_parameters.build(), &hardware_enforced_characteristics,
+        auto result =
+            generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
                         &software_enforced_characteristics);
-        if (result != KM_ERROR_OK) {
-            ALOGE("Failed to generate authentication key: %d", result);
+        if (!result.isOk()) {
+            ALOGE("Failed to generate authentication key: %d", int32_t(result));
             return false;
         }
         if (hardware_enforced_characteristics.size() == 0) {
@@ -466,38 +441,34 @@
                                                        bool* verified) {
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+    auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
                                            &software_enforced_characteristics);
-    if (result != KM_ERROR_OK) {
-        ALOGE("Failed to query encryption key: %d", result);
+    if (!result.isOk()) {
+        ALOGE("Failed to query encryption key: %d", int32_t(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) {
+    auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
+            software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
+    if (!algorithm.isOk() || algorithm.value() != 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) {
+    auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
+            software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE));
+    if (!key_size.isOk() || key_size.value() != 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) {
+    auto block_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE),
+            software_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE));
+    if (!block_mode.isOk() || block_mode.value() != BlockMode::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) {
+    auto padding_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_PADDING),
+            software_enforced_characteristics.GetTagValue(TAG_PADDING));
+    if (!padding_mode.isOk() || padding_mode.value() != PaddingMode::PKCS7) {
         ALOGW("Found encryption key with invalid padding mode.");
         *verified = false;
     }
@@ -511,39 +482,34 @@
                                                            bool* verified) {
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    int32_t result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
+    auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
                                            &software_enforced_characteristics);
-    if (result != KM_ERROR_OK) {
-        ALOGE("Failed to query authentication key: %d", result);
+    if (!result.isOk()) {
+        ALOGE("Failed to query authentication key: %d", int32_t(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) {
+    auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
+            software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
+    if (!algorithm.isOk() || algorithm.value() != 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) {
+    auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
+            software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE));
+    if (!key_size.isOk() || key_size.value() != 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) {
+    auto mac_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH),
+            software_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH));
+    if (!mac_size.isOk() || mac_size.value() != 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) {
+    auto digest = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_DIGEST),
+            software_enforced_characteristics.GetTagValue(TAG_DIGEST));
+    if (!digest.isOk() || digest.value() != Digest::SHA_2_256) {
         ALOGW("Found authentication key with invalid digest list.");
         *verified = false;
     }
diff --git a/keystore/keystore_get.cpp b/keystore/keystore_get.cpp
index 2783816..8fb7f80 100644
--- a/keystore/keystore_get.cpp
+++ b/keystore/keystore_get.cpp
@@ -20,6 +20,7 @@
 #include <keystore/keystore_get.h>
 
 using namespace android;
+using namespace keystore;
 
 ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
     sp<IServiceManager> sm = defaultServiceManager();
@@ -30,13 +31,15 @@
         return -1;
     }
 
-    size_t valueLength;
-    int32_t ret = service->get(String16(key, keyLength), -1, value, &valueLength);
-    if (ret < 0) {
-        return -1;
-    } else if (ret != ::NO_ERROR) {
-        return -1;
-    } else {
-        return valueLength;
+    hidl_vec<uint8_t> result;
+    auto ret = service->get(String16(key, keyLength), -1, &result);
+    if (!ret.isOk()) return -1;
+
+    if (value) {
+        *value = reinterpret_cast<uint8_t*>(malloc(result.size()));
+        if (!*value) return -1;
+        memcpy(*value, &result[0], result.size());
     }
+    return result.size();
+
 }
diff --git a/keystore/keystore_get_wifi_hidl.cpp b/keystore/keystore_get_wifi_hidl.cpp
new file mode 100644
index 0000000..79639b6
--- /dev/null
+++ b/keystore/keystore_get_wifi_hidl.cpp
@@ -0,0 +1,60 @@
+/* Copyright 2017 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 <android/system/wifi/keystore/1.0/IKeystore.h>
+#include <log/log.h>
+
+#include <keystore/keystore_get.h>
+
+using namespace android;
+
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::sp;
+using android::system::wifi::keystore::V1_0::IKeystore;
+
+ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
+    if (key == NULL || keyLength == 0 || value == NULL) {
+        ALOGE("Null pointer argument passed");
+        return -1;
+    }
+
+    sp<IKeystore> service = IKeystore::tryGetService();
+    if (service == NULL) {
+        ALOGE("could not contact keystore HAL");
+        return -1;
+    }
+
+    ssize_t return_size;
+    bool success = false;
+    auto cb = [&](IKeystore::KeystoreStatusCode status, hidl_vec<uint8_t> returnedValue) {
+        if (status == IKeystore::KeystoreStatusCode::SUCCESS) {
+            return_size = returnedValue.size();
+            *value = returnedValue.releaseData();
+            success = true;
+        }
+    };
+
+    Return<void> ret = service->getBlob(hidl_string(key, keyLength), cb);
+    return ret.isOk() && success ? return_size : -1;
+}
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
index d20d7a6..0389201 100644
--- a/keystore/keystore_keymaster_enforcement.h
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef KEYSTORE_KEYMASTER_ENFORCEMENT_H_
-#define KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+#ifndef KEYSTORE_KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+#define KEYSTORE_KEYSTORE_KEYMASTER_ENFORCEMENT_H_
 
 #include <time.h>
 
-#include <keymaster/keymaster_enforcement.h>
+#include "keymaster_enforcement.h"
 
+namespace keystore {
 /**
  * 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 {
+class KeystoreKeymasterEnforcement : public KeymasterEnforcement {
   public:
     KeystoreKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
 
@@ -85,4 +86,6 @@
     }
 };
 
-#endif  // KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+} // namespace keystore
+
+#endif  // KEYSTORE_KEYSTORE_KEYMASTER_ENFORCEMENT_H_
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
index e84fb37..a739c5e 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -17,19 +17,22 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "keystore"
 
-#include <keymaster/keymaster_configuration.h>
-#include <keymaster/soft_keymaster_device.h>
-#include <keymaster/soft_keymaster_logger.h>
-
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
+#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
+#include <android/system/wifi/keystore/1.0/IKeystore.h>
+#include <wifikeystorehal/keystore.h>
+
 #include <cutils/log.h>
 
 #include "entropy.h"
 #include "key_store_service.h"
 #include "keystore.h"
 #include "permissions.h"
+#include "legacy_keymaster_device_wrapper.h"
+#include "include/keystore/keystore_hidl_support.h"
+#include "include/keystore/keystore_return_types.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
@@ -37,159 +40,16 @@
  * 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::AuthorizationSet;
-using keymaster::AuthorizationSetBuilder;
-using keymaster::SoftKeymasterDevice;
+using ::android::system::wifi::keystore::V1_0::IKeystore;
+using ::android::system::wifi::keystore::V1_0::implementation::Keystore;
+using ::android::hardware::configureRpcThreadpool;
 
-static int configure_keymaster_devices(keymaster2_device_t* main, keymaster2_device_t* fallback) {
-    keymaster_error_t error = keymaster::ConfigureDevice(main);
-    if (error != KM_ERROR_OK) {
-        return -1;
-    }
-
-    error = keymaster::ConfigureDevice(fallback);
-    if (error != KM_ERROR_OK) {
-        return -1;
-    }
-
-    return 0;
-}
-
-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);
-}
+/**
+ * TODO implement keystore daemon using binderized keymaster HAL.
+ */
 
 int main(int argc, char* argv[]) {
+    using android::hardware::hidl_string;
     if (argc < 2) {
         ALOGE("A directory must be specified!");
         return 1;
@@ -204,43 +64,60 @@
         return 1;
     }
 
-    keymaster2_device_t* dev;
-    if (keymaster_device_initialize(&dev)) {
-        ALOGE("keystore keymaster could not be initialized; exiting");
-        return 1;
+    auto dev = android::hardware::keymaster::V3_0::IKeymasterDevice::getService();
+    if (dev.get() == nullptr) {
+        return -1;
     }
-
-    keymaster2_device_t* fallback;
-    if (fallback_keymaster_device_initialize(&fallback)) {
-        ALOGE("software keymaster could not be initialized; exiting");
-        return 1;
-    }
-
-    if (configure_keymaster_devices(dev, fallback)) {
-        ALOGE("Keymaster devices could not be configured; exiting");
-        return 1;
+    auto fallback = android::keystore::makeSoftwareKeymasterDevice();
+    if (dev.get() == nullptr) {
+        return -1;
     }
 
     if (configure_selinux() == -1) {
         return -1;
     }
 
-    KeyStore keyStore(&entropy, dev, fallback);
+    bool allowNewFallbackDevice = false;
+
+    keystore::KeyStoreServiceReturnCode rc;
+    rc = KS_HANDLE_HIDL_ERROR(dev->getHardwareFeatures(
+            [&] (bool, bool, bool, bool supportsAttestation, bool, const hidl_string&,
+                 const hidl_string&) {
+                // Attestation support indicates the hardware is keymaster 2.0 or higher.
+                // For these devices we will not allow the fallback device for import or generation
+                // of keys. The fallback device is only used for legacy keys present on the device.
+                allowNewFallbackDevice = !supportsAttestation;
+            }));
+
+    if (!rc.isOk()) {
+        return -1;
+    }
+
+    KeyStore keyStore(&entropy, dev, fallback, allowNewFallbackDevice);
     keyStore.initialize();
     android::sp<android::IServiceManager> sm = android::defaultServiceManager();
-    android::sp<android::KeyStoreService> service = new android::KeyStoreService(&keyStore);
+    android::sp<keystore::KeyStoreService> service = new keystore::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;
     }
 
+    /**
+     * Register the wifi keystore HAL service to run in passthrough mode.
+     * This will spawn off a new thread which will service the HIDL
+     * transactions.
+     */
+    configureRpcThreadpool(1, false /* callerWillJoin */);
+    android::sp<IKeystore> wifiKeystoreHalService = new Keystore();
+    android::status_t err = wifiKeystoreHalService->registerAsService();
+    if (ret != android::OK) {
+        ALOGE("Cannot register wifi keystore HAL service: %d", err);
+    }
+
     /*
-     * We're the only thread in existence, so we're just going to process
-     * Binder transaction as a single-threaded program.
+     * This thread is just going to process Binder transactions.
      */
     android::IPCThreadState::self()->joinThreadPool();
-
-    keymaster_device_release(dev);
     return 1;
 }
diff --git a/keystore/keystore_tags_utils.cpp b/keystore/keystore_tags_utils.cpp
new file mode 100644
index 0000000..278348a
--- /dev/null
+++ b/keystore/keystore_tags_utils.cpp
@@ -0,0 +1,46 @@
+/*
+**
+** Copyright 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/keymaster_tags.h>
+
+namespace keystore {
+
+template<typename TagList>
+struct TagStringifier;
+
+template<typename ... Tags>
+struct TagStringifier<MetaList<Tags...>> {
+    template<TagType tag_type, Tag tag>
+    static TypedTag<tag_type, tag> chooseString(TypedTag<tag_type, tag> ttag, Tag runtime_tag,
+            const char** result) {
+        if (tag == runtime_tag) {
+            *result = Tag2String<tag>::value();
+        }
+        return ttag;
+    }
+    static const char* stringify(Tag tag) {
+        const char* result = "unknown tag";
+        [] (Tags&&...) {}(chooseString(Tags(), tag, &result)...);
+        return result;
+    }
+};
+
+const char* stringifyTag(Tag tag) {
+    return TagStringifier<all_tags_t>::stringify(tag);
+}
+
+}
diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp
index 4617afd..0d3f0ec 100644
--- a/keystore/keystore_utils.cpp
+++ b/keystore/keystore_utils.cpp
@@ -26,6 +26,9 @@
 #include <private/android_filesystem_config.h>
 
 #include <keymaster/android_keymaster_utils.h>
+#include <keystore/authorization_set.h>
+#include <keystore/keystore_client.h>
+#include <keystore/IKeystoreService.h>
 
 size_t readFully(int fd, uint8_t* data, size_t size) {
     size_t remaining = size;
@@ -58,30 +61,31 @@
     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));
+void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params) {
+    using namespace keystore;
+    params->push_back(TAG_PURPOSE, KeyPurpose::SIGN);
+    params->push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
+    params->push_back(TAG_PURPOSE, KeyPurpose::ENCRYPT);
+    params->push_back(TAG_PURPOSE, KeyPurpose::DECRYPT);
+    params->push_back(TAG_PADDING, PaddingMode::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(TAG_PADDING, PaddingMode::RSA_PKCS1_1_5_SIGN);
+        params->push_back(TAG_PADDING, PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
+        params->push_back(TAG_PADDING, PaddingMode::RSA_PSS);
+        params->push_back(TAG_PADDING, PaddingMode::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));
+    params->push_back(TAG_DIGEST, Digest::NONE);
+    params->push_back(TAG_DIGEST, Digest::MD5);
+    params->push_back(TAG_DIGEST, Digest::SHA1);
+    params->push_back(TAG_DIGEST, Digest::SHA_2_224);
+    params->push_back(TAG_DIGEST, Digest::SHA_2_256);
+    params->push_back(TAG_DIGEST, Digest::SHA_2_384);
+    params->push_back(TAG_DIGEST, Digest::SHA_2_512);
+    params->push_back(TAG_ALL_USERS);
+    params->push_back(TAG_NO_AUTH_REQUIRED);
+    params->push_back(TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX);
+    params->push_back(TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX);
+    params->push_back(TAG_ACTIVE_DATETIME, 0);
 }
 
 uid_t get_app_id(uid_t uid) {
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
index eaa5eb3..0f7922a 100644
--- a/keystore/keystore_utils.h
+++ b/keystore/keystore_utils.h
@@ -28,10 +28,14 @@
 
 #include <UniquePtr.h>
 
+#include <keystore/authorization_set.h>
+
+#include "blob.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);
+void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params);
 
 /**
  * Returns the app ID (in the Android multi-user sense) for the current
@@ -55,4 +59,14 @@
 };
 typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
 
+namespace keystore {
+
+inline static hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<uint8_t*>(blob.getValue()), blob.getLength());
+    return result;
+}
+
+} // namespace keystore
+
 #endif  // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/legacy_keymaster_device_wrapper.cpp b/keystore/legacy_keymaster_device_wrapper.cpp
new file mode 100644
index 0000000..187252e
--- /dev/null
+++ b/keystore/legacy_keymaster_device_wrapper.cpp
@@ -0,0 +1,543 @@
+/*
+ **
+ ** Copyright 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 "android.hardware.keymaster@3.0-impl"
+
+#include "legacy_keymaster_device_wrapper.h"
+
+#include <cutils/log.h>
+
+#include <hardware/keymaster2.h>
+#include <hardware/keymaster_defs.h>
+#include <keymaster/keymaster_configuration.h>
+#include <keymaster/soft_keymaster_device.h>
+
+namespace android {
+namespace keystore {
+
+using ::keymaster::SoftKeymasterDevice;
+
+LegacyKeymasterDeviceWrapper::LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev)
+    : keymaster_device_(dev) {}
+
+LegacyKeymasterDeviceWrapper::~LegacyKeymasterDeviceWrapper() {
+    if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
+}
+
+static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+    return keymaster_tag_get_type(tag);
+}
+
+/**
+ * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
+ * cast to make the compiler happy. One of two thigs should happen though:
+ * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
+ *      single point of truth. Then this cast function can go away.
+ */
+inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
+    return keymaster_tag_t(value);
+}
+inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
+    return Tag(value);
+}
+inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+    return keymaster_purpose_t(value);
+}
+inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+    return keymaster_key_format_t(value);
+}
+inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+    return ErrorCode(value);
+}
+
+class KmParamSet : public keymaster_key_param_set_t {
+  public:
+    KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
+        params = new keymaster_key_param_t[keyParams.size()];
+        length = keyParams.size();
+        for (size_t i = 0; i < keyParams.size(); ++i) {
+            auto tag = legacy_enum_conversion(keyParams[i].tag);
+            switch (typeFromTag(tag)) {
+            case KM_ENUM:
+            case KM_ENUM_REP:
+                params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+                break;
+            case KM_UINT:
+            case KM_UINT_REP:
+                params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+                break;
+            case KM_ULONG:
+            case KM_ULONG_REP:
+                params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+                break;
+            case KM_DATE:
+                params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+                break;
+            case KM_BOOL:
+                if (keyParams[i].f.boolValue)
+                    params[i] = keymaster_param_bool(tag);
+                else
+                    params[i].tag = KM_TAG_INVALID;
+                break;
+            case KM_BIGNUM:
+            case KM_BYTES:
+                params[i] =
+                    keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
+                break;
+            case KM_INVALID:
+            default:
+                params[i].tag = KM_TAG_INVALID;
+                /* just skip */
+                break;
+            }
+        }
+    }
+    KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+        other.length = 0;
+        other.params = nullptr;
+    }
+    KmParamSet(const KmParamSet&) = delete;
+    ~KmParamSet() { delete[] params; }
+};
+
+inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
+    return KmParamSet(params);
+}
+
+inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
+    /* hidl unmarshals funny pointers if the the blob is empty */
+    if (blob.size()) return {&blob[0], blob.size()};
+    return {};
+}
+
+inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
+    /* hidl unmarshals funny pointers if the the blob is empty */
+    if (blob.size()) return {&blob[0], blob.size()};
+    return {};
+}
+
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
+    return result;
+}
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
+    return result;
+}
+
+inline static hidl_vec<hidl_vec<uint8_t>>
+kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
+    hidl_vec<hidl_vec<uint8_t>> result;
+    if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
+
+    result.resize(cert_chain->entry_count);
+    for (size_t i = 0; i < cert_chain->entry_count; ++i) {
+        auto& entry = cert_chain->entries[i];
+        result[i] = kmBlob2hidlVec(entry);
+    }
+
+    return result;
+}
+
+static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
+    hidl_vec<KeyParameter> result;
+    if (set.length == 0 || set.params == nullptr) return result;
+
+    result.resize(set.length);
+    keymaster_key_param_t* params = set.params;
+    for (size_t i = 0; i < set.length; ++i) {
+        auto tag = params[i].tag;
+        result[i].tag = legacy_enum_conversion(tag);
+        switch (typeFromTag(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP:
+            result[i].f.integer = params[i].enumerated;
+            break;
+        case KM_UINT:
+        case KM_UINT_REP:
+            result[i].f.integer = params[i].integer;
+            break;
+        case KM_ULONG:
+        case KM_ULONG_REP:
+            result[i].f.longInteger = params[i].long_integer;
+            break;
+        case KM_DATE:
+            result[i].f.dateTime = params[i].date_time;
+            break;
+        case KM_BOOL:
+            result[i].f.boolValue = params[i].boolean;
+            break;
+        case KM_BIGNUM:
+        case KM_BYTES:
+            result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
+                                         params[i].blob.data_length);
+            break;
+        case KM_INVALID:
+        default:
+            params[i].tag = KM_TAG_INVALID;
+            /* just skip */
+            break;
+        }
+    }
+    return result;
+}
+
+// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+Return<void> LegacyKeymasterDeviceWrapper::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
+    _hidl_cb(false, false, false, false, false, "Fallback Device", "Google Android Security");
+    return Void();
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::addRngEntropy(const hidl_vec<uint8_t>& data) {
+    return legacy_enum_conversion(
+        keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::generateKey(const hidl_vec<KeyParameter>& keyParams,
+                                                       generateKey_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    // convert the parameter set to something our backend understands
+    auto kmParams = hidlParams2KmParamSet(keyParams);
+
+    auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
+                                              &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    // send results off to the client
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+    // free buffers that we are responsible for
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::getKeyCharacteristics(
+    const hidl_vec<uint8_t>& keyBlob, const hidl_vec<uint8_t>& clientId,
+    const hidl_vec<uint8_t>& appData, getKeyCharacteristics_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+
+    // result variables the backend understands
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    auto kmClientId = hidlVec2KmBlob(clientId);
+    auto kmAppData = hidlVec2KmBlob(appData);
+
+    auto rc = keymaster_device_->get_key_characteristics(
+        keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
+        clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
+        &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
+
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::importKey(const hidl_vec<KeyParameter>& params,
+                                                     KeyFormat keyFormat,
+                                                     const hidl_vec<uint8_t>& keyData,
+                                                     importKey_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    auto kmParams = hidlParams2KmParamSet(params);
+    auto kmKeyData = hidlVec2KmBlob(keyData);
+
+    auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
+                                            legacy_enum_conversion(keyFormat), &kmKeyData,
+                                            &key_blob, &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+    // free buffers that we are responsible for
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::exportKey(KeyFormat exportFormat,
+                                                     const hidl_vec<uint8_t>& keyBlob,
+                                                     const hidl_vec<uint8_t>& clientId,
+                                                     const hidl_vec<uint8_t>& appData,
+                                                     exportKey_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_blob_t out_blob = {};
+
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    auto kmClientId = hidlVec2KmBlob(clientId);
+    auto kmAppData = hidlVec2KmBlob(appData);
+
+    auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
+                                            keyBlob.size() ? &kmKeyBlob : nullptr,
+                                            clientId.size() ? &kmClientId : nullptr,
+                                            appData.size() ? &kmAppData : nullptr, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
+        resultKeyBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+    // free buffers that we are responsible for
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                                                     const hidl_vec<KeyParameter>& attestParams,
+                                                     attestKey_cb _hidl_cb) {
+
+    hidl_vec<hidl_vec<uint8_t>> resultCertChain;
+
+    for (size_t i = 0; i < attestParams.size(); ++i) {
+        switch (attestParams[i].tag) {
+            case Tag::ATTESTATION_ID_BRAND:
+            case Tag::ATTESTATION_ID_DEVICE:
+            case Tag::ATTESTATION_ID_PRODUCT:
+            case Tag::ATTESTATION_ID_SERIAL:
+            case Tag::ATTESTATION_ID_IMEI:
+            case Tag::ATTESTATION_ID_MEID:
+            case Tag::ATTESTATION_ID_MANUFACTURER:
+            case Tag::ATTESTATION_ID_MODEL:
+                // Device id attestation may only be supported if the device is able to permanently
+                // destroy its knowledge of the ids. This device is unable to do this, so it must
+                // never perform any device id attestation.
+                _hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain);
+                return Void();
+            default:
+                break;
+        }
+    }
+
+    keymaster_cert_chain_t cert_chain = {};
+
+    auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
+    auto kmAttestParams = hidlParams2KmParamSet(attestParams);
+
+    auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
+                                            &cert_chain);
+
+    if (rc == KM_ERROR_OK) {
+        resultCertChain = kmCertChain2Hidl(&cert_chain);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultCertChain);
+
+    keymaster_free_cert_chain(&cert_chain);
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                                                      const hidl_vec<KeyParameter>& upgradeParams,
+                                                      upgradeKey_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob = {};
+
+    auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
+    auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
+
+    auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
+                                             &kmUpgradeParams, &key_blob);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+
+    return Void();
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteAllKeys() {
+    return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::destroyAttestationIds() {
+    return ErrorCode::UNIMPLEMENTED;
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                                                 const hidl_vec<KeyParameter>& inParams,
+                                                 begin_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<KeyParameter> resultParams;
+    uint64_t resultOpHandle = 0;
+
+    // result variables the backend understands
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_operation_handle_t& operation_handle = resultOpHandle;
+
+    auto kmKey = hidlVec2KmKeyBlob(key);
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+
+    auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
+                                       &kmInParams, &out_params, &operation_handle);
+
+    if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
+
+    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
+
+    keymaster_free_param_set(&out_params);
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::update(uint64_t operationHandle,
+                                                  const hidl_vec<KeyParameter>& inParams,
+                                                  const hidl_vec<uint8_t>& input,
+                                                  update_cb _hidl_cb) {
+    // result variables for the wire
+    uint32_t resultConsumed = 0;
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+
+    // result variables the backend understands
+    size_t consumed = 0;
+    keymaster_key_param_set_t out_params = {};
+    keymaster_blob_t out_blob = {};
+
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+    auto kmInput = hidlVec2KmBlob(input);
+
+    auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+                                        &consumed, &out_params, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        resultConsumed = consumed;
+        resultParams = kmParamSet2Hidl(out_params);
+        resultBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
+
+    keymaster_free_param_set(&out_params);
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<void> LegacyKeymasterDeviceWrapper::finish(uint64_t operationHandle,
+                                                  const hidl_vec<KeyParameter>& inParams,
+                                                  const hidl_vec<uint8_t>& input,
+                                                  const hidl_vec<uint8_t>& signature,
+                                                  finish_cb _hidl_cb) {
+    // result variables for the wire
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+
+    // result variables the backend understands
+    keymaster_key_param_set_t out_params = {};
+    keymaster_blob_t out_blob = {};
+
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+    auto kmInput = hidlVec2KmBlob(input);
+    auto kmSignature = hidlVec2KmBlob(signature);
+
+    auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+                                        &kmSignature, &out_params, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        resultParams = kmParamSet2Hidl(out_params);
+        resultBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
+
+    keymaster_free_param_set(&out_params);
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<ErrorCode> LegacyKeymasterDeviceWrapper::abort(uint64_t operationHandle) {
+    return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
+}
+
+sp<IKeymasterDevice> makeSoftwareKeymasterDevice() {
+    keymaster2_device_t* dev = nullptr;
+    dev = (new SoftKeymasterDevice)->keymaster2_device();
+
+    auto kmrc = ::keymaster::ConfigureDevice(dev);
+    if (kmrc != KM_ERROR_OK) {
+        dev->common.close(&dev->common);
+        return nullptr;
+    }
+
+    return new LegacyKeymasterDeviceWrapper(dev);
+}
+
+}  // namespace keystore
+}  // namespace android
diff --git a/keystore/legacy_keymaster_device_wrapper.h b/keystore/legacy_keymaster_device_wrapper.h
new file mode 100644
index 0000000..ad26221
--- /dev/null
+++ b/keystore/legacy_keymaster_device_wrapper.h
@@ -0,0 +1,90 @@
+/*
+ **
+ ** Copyright 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 LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
+#define LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+
+struct keymaster2_device;
+typedef struct keymaster2_device keymaster2_device_t;
+
+namespace android {
+namespace keystore {
+
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::KeyParameter;
+using ::android::hardware::keymaster::V3_0::KeyPurpose;
+using ::android::hardware::keymaster::V3_0::Tag;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class LegacyKeymasterDeviceWrapper : public IKeymasterDevice {
+  public:
+    LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev);
+    virtual ~LegacyKeymasterDeviceWrapper();
+
+    // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+    Return<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override;
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override;
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override;
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override;
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override;
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<ErrorCode> deleteAllKeys() override;
+    Return<ErrorCode> destroyAttestationIds() override;
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) override;
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, update_cb _hidl_cb) override;
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        finish_cb _hidl_cb) override;
+    Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+  private:
+    keymaster2_device_t* keymaster_device_;
+};
+
+sp<IKeymasterDevice> makeSoftwareKeymasterDevice();
+
+}  // namespace keystore
+}  // namespace android
+
+#endif  // LEGACY_KEYMASTER_DEVICE_WRAPPER_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index e8ae8b7..8c39716 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -19,17 +19,18 @@
 
 #include <algorithm>
 
-namespace android {
+namespace keystore {
+using 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,
+sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
+                                       const OperationMap::km_device_t& dev,
                                        const sp<IBinder>& appToken,
-                                       keymaster_key_characteristics_t* characteristics,
-                                       bool pruneable) {
+                                       KeyCharacteristics&& characteristics, bool pruneable) {
     sp<IBinder> token = new BBinder();
-    mMap[token] = Operation(handle, keyid, purpose, dev, characteristics, appToken);
+    mMap[token] = Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken);
     if (pruneable) {
         mLru.push_back(token);
     }
@@ -40,10 +41,9 @@
     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) {
+bool OperationMap::getOperation(const sp<IBinder>& token, uint64_t* outHandle, uint64_t* outKeyid,
+                                KeyPurpose* outPurpose, km_device_t* outDevice,
+                                const KeyCharacteristics** outCharacteristics) {
     if (!outHandle || !outDevice) {
         return false;
     }
@@ -58,7 +58,7 @@
     *outPurpose = entry->second.purpose;
     *outDevice = entry->second.device;
     if (outCharacteristics) {
-        *outCharacteristics = entry->second.characteristics.get();
+        *outCharacteristics = &entry->second.characteristics;
     }
     return true;
 }
@@ -116,7 +116,8 @@
     return mLru[0];
 }
 
-bool OperationMap::getOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t** outToken) {
+bool OperationMap::getOperationAuthToken(const sp<IBinder>& token,
+                                         const HardwareAuthToken** outToken) {
     auto entry = mMap.find(token);
     if (entry == mMap.end()) {
         return false;
@@ -125,12 +126,13 @@
     return true;
 }
 
-bool OperationMap::setOperationAuthToken(const sp<IBinder>& token, const hw_auth_token_t* authToken) {
+bool OperationMap::setOperationAuthToken(const sp<IBinder>& token,
+                                         const HardwareAuthToken* authToken) {
     auto entry = mMap.find(token);
     if (entry == mMap.end()) {
         return false;
     }
-    entry->second.authToken.reset(new hw_auth_token_t);
+    entry->second.authToken.reset(new HardwareAuthToken);
     *entry->second.authToken = *authToken;
     return true;
 }
@@ -144,13 +146,13 @@
     }
 }
 
-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_)
+OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_,
+                                   const OperationMap::km_device_t& device_,
+                                   KeyCharacteristics&& 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) {}
+OperationMap::Operation::Operation()
+    : handle(0), keyid(0), device(nullptr), characteristics(), appToken(nullptr) {}
 
 }  // namespace android
diff --git a/keystore/operation.h b/keystore/operation.h
index 263b5c9..e69b43a 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -17,73 +17,74 @@
 #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 <keystore/keymaster_tags.h>
+#include <map>
 #include <utils/LruCache.h>
 #include <utils/StrongPointer.h>
-#include <map>
 #include <vector>
 
-namespace android {
+namespace keystore {
 
-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;
+using ::android::IBinder;
+using ::android::sp;
 
 /**
- * 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.
+ * OperationMap handles the translation of uint64_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:
+    typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+
+  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);
+    android::sp<android::IBinder> addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
+                                               const km_device_t& dev,
+                                               const android::sp<android::IBinder>& appToken,
+                                               KeyCharacteristics&& characteristics,
+                                               bool pruneable);
+    bool getOperation(const android::sp<android::IBinder>& token, uint64_t* outHandle,
+                      uint64_t* outKeyid, KeyPurpose* outPurpose, km_device_t* outDev,
+                      const KeyCharacteristics** outCharacteristics);
+    bool removeOperation(const android::sp<android::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);
+    bool getOperationAuthToken(const android::sp<android::IBinder>& token,
+                               const HardwareAuthToken** outToken);
+    bool setOperationAuthToken(const android::sp<android::IBinder>& token,
+                               const HardwareAuthToken* authToken);
+    android::sp<android::IBinder> getOldestPruneableOperation();
+    std::vector<android::sp<android::IBinder>>
+    getOperationsForToken(const android::sp<android::IBinder>& appToken);
 
-private:
-    void updateLru(const sp<IBinder>& token);
-    void removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken);
+  private:
+    void updateLru(const android::sp<android::IBinder>& token);
+    void removeOperationTracking(const android::sp<android::IBinder>& token,
+                                 const android::sp<android::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;
+        Operation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, const km_device_t& device,
+                  KeyCharacteristics&& characteristics, android::sp<android::IBinder> appToken);
+        uint64_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;
+        KeyPurpose purpose;
+        km_device_t device;
+        KeyCharacteristics characteristics;
+        android::sp<android::IBinder> appToken;
+        std::unique_ptr<HardwareAuthToken> 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;
+    std::map<android::sp<android::IBinder>, Operation> mMap;
+    std::vector<android::sp<android::IBinder>> mLru;
+    std::map<android::sp<android::IBinder>, std::vector<android::sp<android::IBinder>>>
+        mAppTokenMap;
+    android::IBinder::DeathRecipient* mDeathRecipient;
 };
-} // namespace android
+
+}  // namespace keystore
+
 #endif
diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp
index 1d3fb8f..1ba91d9 100644
--- a/keystore/permissions.cpp
+++ b/keystore/permissions.cpp
@@ -28,9 +28,25 @@
 
 /* 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",
+    "get_state",
+    "get",
+    "insert",
+    "delete",
+    "exist",
+    "list",
+    "reset",
+    "password",
+    "lock",
+    "unlock",
+    "is_empty",
+    "sign",
+    "verify",
+    "grant",
+    "duplicate",
+    "clear_uid",
+    "add_auth",
+    "user_changed",
+    "gen_unique_id",
 };
 
 struct user_euid {
@@ -40,6 +56,7 @@
 
 user_euid user_euids[] = {
     {AID_VPN, AID_SYSTEM}, {AID_WIFI, AID_SYSTEM}, {AID_ROOT, AID_SYSTEM},
+    {AID_WIFI, AID_KEYSTORE}, {AID_KEYSTORE, AID_WIFI}
 };
 
 struct user_perm {
@@ -54,8 +71,9 @@
     {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);
+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 |
+    P_GEN_UNIQUE_ID /* Only privileged apps can do this, but enforcement is done by SELinux */);
 
 struct audit_data {
     pid_t pid;
diff --git a/keystore/permissions.h b/keystore/permissions.h
index f5f1831..80d0e04 100644
--- a/keystore/permissions.h
+++ b/keystore/permissions.h
@@ -39,6 +39,7 @@
     P_CLEAR_UID = 1 << 15,
     P_ADD_AUTH = 1 << 16,
     P_USER_CHANGED = 1 << 17,
+    P_GEN_UNIQUE_ID = 1 << 18,
 };
 
 const char* get_perm_label(perm_t perm);
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
index 3da88c2..bd4f979 100644
--- a/keystore/user_state.cpp
+++ b/keystore/user_state.cpp
@@ -31,7 +31,9 @@
 #include "blob.h"
 #include "keystore_utils.h"
 
-UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
+
+UserState::UserState(uid_t userId) :
+        mUserId(userId), mState(STATE_UNINITIALIZED), mRetry(MAX_RETRY) {
     asprintf(&mUserDir, "user_%u", mUserId);
     asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
 }
@@ -78,22 +80,22 @@
 
 ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
     if (!generateMasterKey(entropy)) {
-        return SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     ResponseCode response = writeMasterKey(pw, entropy);
-    if (response != NO_ERROR) {
+    if (response != ResponseCode::NO_ERROR) {
         return response;
     }
     setupMasterKeys();
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
 ResponseCode UserState::copyMasterKey(UserState* src) {
     if (mState != STATE_UNINITIALIZED) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     if (src->getState() != STATE_NO_ERROR) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
     setupMasterKeys();
@@ -106,28 +108,28 @@
      */
     int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
     if (in < 0) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     blob rawBlob;
     size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
     if (close(in) != 0) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::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;
+        return ResponseCode::SYSTEM_ERROR;
     }
     size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
     if (close(out) != 0) {
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     if (outLength != length) {
         ALOGW("blob not fully written %zu != %zu", outLength, length);
         unlink(mMasterKeyFile);
-        return ::SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
-    return ::NO_ERROR;
+    return ResponseCode::NO_ERROR;
 }
 
 ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
@@ -142,7 +144,7 @@
 ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
     int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
     if (in < 0) {
-        return SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
 
     // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
@@ -150,7 +152,7 @@
     blob rawBlob;
     size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
     if (close(in) != 0) {
-        return SYSTEM_ERROR;
+        return ResponseCode::SYSTEM_ERROR;
     }
     // find salt at EOF if present, otherwise we have an old file
     uint8_t* salt;
@@ -165,18 +167,18 @@
     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) {
+    if (response == ResponseCode::SYSTEM_ERROR) {
         return response;
     }
-    if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
+    if (response == ResponseCode::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;
+                return ResponseCode::SYSTEM_ERROR;
             }
             response = writeMasterKey(pw, entropy);
         }
-        if (response == NO_ERROR) {
+        if (response == ResponseCode::NO_ERROR) {
             memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
             setupMasterKeys();
         }
@@ -184,20 +186,20 @@
     }
     if (mRetry <= 0) {
         reset();
-        return UNINITIALIZED;
+        return ResponseCode::UNINITIALIZED;
     }
     --mRetry;
     switch (mRetry) {
     case 0:
-        return WRONG_PASSWORD_0;
+        return ResponseCode::WRONG_PASSWORD_0;
     case 1:
-        return WRONG_PASSWORD_1;
+        return ResponseCode::WRONG_PASSWORD_1;
     case 2:
-        return WRONG_PASSWORD_2;
+        return ResponseCode::WRONG_PASSWORD_2;
     case 3:
-        return WRONG_PASSWORD_3;
+        return ResponseCode::WRONG_PASSWORD_3;
     default:
-        return WRONG_PASSWORD_3;
+        return ResponseCode::WRONG_PASSWORD_3;
     }
 }