Merge pi-dev-plus-aosp-without-vendor into stage-aosp-master

Bug: 79597307
Change-Id: I54d3ce36c7f04cf56852fbd267896d728191e6c2
diff --git a/keystore/.clang-format b/.clang-format
similarity index 100%
copy from keystore/.clang-format
copy to .clang-format
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..c8dbf77
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,5 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
diff --git a/keystore/.clang-format b/keystore-engine/.clang-format
similarity index 100%
rename from keystore/.clang-format
rename to keystore-engine/.clang-format
diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk
index 8988857..c995dfc 100644
--- a/keystore-engine/Android.mk
+++ b/keystore-engine/Android.mk
@@ -30,6 +30,7 @@
 	libcrypto \
 	libcutils \
 	libhidlbase \
+	libkeystore_aidl \
 	libkeystore_binder \
 	liblog \
 	libutils
diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp
index dce8242..f9e7be0 100644
--- a/keystore-engine/keystore_backend_binder.cpp
+++ b/keystore-engine/keystore_backend_binder.cpp
@@ -22,11 +22,12 @@
 
 #include "keystore_backend_binder.h"
 
+#include <android/security/IKeystoreService.h>
 #include <binder/IServiceManager.h>
 #include <keystore/keystore.h>
-#include <keystore/IKeystoreService.h>
 #include <keystore/keystore_hidl_support.h>
 
+using android::security::IKeystoreService;
 using namespace android;
 using keystore::blob2hidlVec;
 using keystore::hidl_vec;
@@ -35,9 +36,8 @@
 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) {
+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);
@@ -47,20 +47,21 @@
         return -1;
     }
 
-    auto inBlob = blob2hidlVec(in ,len);
-    hidl_vec<uint8_t> reply_vec;
+    auto inBlob = blob2hidlVec(in, len);
+    std::vector<uint8_t> reply_vec;
     auto ret = service->sign(String16(key_id), inBlob, &reply_vec);
     if (!ret.isOk()) {
         return -1;
     }
 
-    *reply = reply_vec.releaseData();
+    hidl_vec<uint8_t> reply_hidl(reply_vec);  // makes copy
+    *reply = reply_hidl.releaseData();
     *reply_len = reply_vec.size();
     return 0;
 }
 
-int32_t KeystoreBackendBinder::get_pubkey(
-        const char *key_id, uint8_t** pubkey, size_t* pubkey_len) {
+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);
@@ -70,13 +71,14 @@
         return -1;
     }
 
-    hidl_vec<uint8_t> pubkey_vec;
+    std::vector<uint8_t> pubkey_vec;
     auto ret = service->get_pubkey(String16(key_id), &pubkey_vec);
     if (!ret.isOk()) {
         return -1;
     }
 
-    *pubkey = pubkey_vec.releaseData();
+    hidl_vec<uint8_t> hidl_pubkey(pubkey_vec);  // makes copy
+    *pubkey = hidl_pubkey.releaseData();        // caller should clean up memory.
     *pubkey_len = pubkey_vec.size();
     return 0;
 }
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 8addecd..37bc6a8 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -21,39 +21,49 @@
 
     srcs: [
         ":IKeyAttestationApplicationIdProvider.aidl",
+        "KeyStore.cpp",
         "auth_token_table.cpp",
         "blob.cpp",
+        "confirmation_manager.cpp",
         "entropy.cpp",
         "grant_store.cpp",
+        "key_config.proto",
+        "key_proto_handler.cpp",
         "key_store_service.cpp",
         "keyblob_utils.cpp",
         "keymaster_enforcement.cpp",
-        "keystore.cpp",
         "keystore_attestation_id.cpp",
         "keystore_main.cpp",
         "keystore_utils.cpp",
         "legacy_keymaster_device_wrapper.cpp",
         "operation.cpp",
+        "operation_config.proto",
+        "operation_proto_handler.cpp",
         "permissions.cpp",
         "user_state.cpp",
     ],
     shared_libs: [
+        "android.hardware.confirmationui@1.0",
         "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
         "android.system.wifi.keystore@1.0",
+        "libbase",
         "libbinder",
         "libcrypto",
-        "libcutils",
         "libhardware",
         "libhidlbase",
         "libhidltransport",
         "libhwbinder",
+        "libkeymaster4support",
         "libkeymaster_messages",
         "libkeymaster_portable",
-        "libkeymaster_staging",
+        "libkeystore_aidl",
         "libkeystore_binder",
+        "libkeystore_parcelables",
         "liblog",
+        "libprotobuf-cpp-lite",
         "libselinux",
-        "libsoftkeymaster",
+        "libservices",
         "libsoftkeymasterdevice",
         "libutils",
         "libwifikeystorehal",
@@ -68,6 +78,8 @@
             enabled: false,
         },
     },
+
+    required: ["keystore_cli_v2"],
 }
 
 cc_binary {
@@ -76,13 +88,15 @@
 
     srcs: ["keystore_cli.cpp"],
     shared_libs: [
-        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
         "libbinder",
         "libcrypto",
         "libcutils",
         "libhidlbase",
         "libhwbinder",
+        "libkeystore_aidl", // for IKeyStoreService.asInterface()
         "libkeystore_binder",
+        "libkeystore_parcelables",
         "liblog",
         "libutils",
     ],
@@ -98,39 +112,73 @@
     ],
     srcs: ["keystore_cli_v2.cpp"],
     shared_libs: [
-        "android.hardware.keymaster@3.0",
+        "android.hardware.confirmationui@1.0",
+        "libbinder",
+        "android.hardware.keymaster@4.0",
         "libchrome",
+        "libutils",
         "libhidlbase",
         "libhwbinder",
+        "libkeymaster4support",
+        "libkeystore_aidl",
         "libkeystore_binder",
+        "libkeystore_parcelables",
     ],
 
     local_include_dirs: ["include"],
 }
 
+cc_library_shared {
+    name: "libkeystore_parcelables",
+    defaults: ["keystore_defaults"],
+    export_include_dirs: ["include"],
+    srcs: [
+        "KeyAttestationApplicationId.cpp",
+        "KeyAttestationPackageInfo.cpp",
+        "KeymasterArguments.cpp",
+        "KeystoreArguments.cpp",
+        "OperationResult.cpp",
+        "Signature.cpp",
+        "keystore_aidl_hidl_marshalling_utils.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.keymaster@4.0",
+        "libbinder",
+        "libhardware",
+        "libhidlbase",
+        "libhwbinder",
+        "libkeymaster4support",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libutils",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.keymaster@4.0",
+        "libbinder",
+        "libhidlbase",
+        "libhwbinder",
+        "libkeymaster4support",
+    ],
+}
 // Library for keystore clients
 cc_library_shared {
     name: "libkeystore_binder",
     defaults: ["keystore_defaults"],
 
     srcs: [
-        "IKeystoreService.cpp",
-        "KeyAttestationApplicationId.cpp",
-        "KeyAttestationPackageInfo.cpp",
-        "Signature.cpp",
-        "authorization_set.cpp",
         "keyblob_utils.cpp",
-        "keystore_aidl_hidl_marshalling_utils.cpp",
         "keystore_client.proto",
         "keystore_client_impl.cpp",
         "keystore_get.cpp",
-        "keystore_tags_utils.cpp",
     ],
     shared_libs: [
-        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
         "libbinder",
         "libhidlbase",
         "libhwbinder",
+        "libkeymaster4support",
+        "libkeystore_aidl",
+        "libkeystore_parcelables",
         "liblog",
         "libprotobuf-cpp-lite",
         "libutils",
@@ -140,12 +188,18 @@
         type: "lite",
         export_proto_headers: true,
     },
+    aidl: {
+        export_aidl_headers: true,
+        include_dirs: ["frameworks/base/core/java/"],
+    },
     export_include_dirs: ["include"],
     export_shared_lib_headers: [
-        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
         "libbinder",
         "libhidlbase",
         "libhwbinder",
+        "libkeystore_aidl",
+        "libkeystore_parcelables",
     ],
 }
 
@@ -174,22 +228,61 @@
     name: "libkeystore_test",
     defaults: ["keystore_defaults"],
 
-    srcs: ["auth_token_table.cpp"],
+    srcs: [
+        "auth_token_table.cpp",
+    ],
+    cflags: [ "-O0", ],
     static_libs: ["libgtest_main"],
     shared_libs: [
-        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
         "libhidlbase",
         "libhwbinder",
-        "libkeymaster_messages",
+        "libkeymaster4support",
         "libutils",
     ],
     export_shared_lib_headers: [
-        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
         "libhidlbase",
         "libhwbinder",
+        "libkeymaster4support",
     ],
 
     export_include_dirs: ["include"],
 }
 
+filegroup {
+    name: "keystore_aidl",
+    srcs: [
+        "binder/android/security/IConfirmationPromptCallback.aidl",
+        "binder/android/security/IKeystoreService.aidl",
+    ],
+}
+
+cc_library_shared {
+    name: "libkeystore_aidl",
+    srcs: [":keystore_aidl"],
+    aidl: {
+        export_aidl_headers: true,
+        include_dirs: [
+            "system/security/keystore/binder",
+        ],
+    },
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libkeystore_parcelables",
+        "liblog",
+        "libselinux",
+        "libutils",
+    ],
+    export_shared_lib_headers: [
+        "libbinder",
+        "libkeystore_parcelables",
+    ],
+}
+
 subdirs = ["tests"]
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
deleted file mode 100644
index eee9942..0000000
--- a/keystore/IKeystoreService.cpp
+++ /dev/null
@@ -1,1361 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/limits.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <limits>
-
-#define LOG_TAG "KeystoreService"
-#include <utils/Log.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;
-
-KeystoreArg::KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {}
-
-KeystoreArg::~KeystoreArg() {}
-
-const void* KeystoreArg::data() const {
-    return mData;
-}
-
-size_t KeystoreArg::size() const {
-    return mSize;
-}
-
-OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
-
-OperationResult::~OperationResult() {}
-
-status_t OperationResult::readFromParcel(const Parcel* inn) {
-    const Parcel& in = *inn;
-    resultCode = ErrorCode(in.readInt32());
-    token = in.readStrongBinder();
-    handle = static_cast<uint64_t>(in.readInt64());
-    inputConsumed = in.readInt32();
-    data = readKeymasterBlob(in);
-    outParams = readParamSetFromParcel(in);
-    return OK;
-}
-
-status_t OperationResult::writeToParcel(Parcel* out) const {
-    out->writeInt32(resultCode);
-    out->writeStrongBinder(token);
-    out->writeInt64(handle);
-    out->writeInt32(inputConsumed);
-    writeKeymasterBlob(data, out);
-    writeParamSetToParcel(outParams, out);
-    return OK;
-}
-
-ExportResult::ExportResult() : resultCode() {}
-
-ExportResult::~ExportResult() {}
-
-status_t ExportResult::readFromParcel(const Parcel* inn) {
-    const Parcel& in = *inn;
-    resultCode = ErrorCode(in.readInt32());
-    exportData = readKeymasterBlob(in);
-    return OK;
-}
-
-status_t ExportResult::writeToParcel(Parcel* out) const {
-    out->writeInt32(resultCode);
-    writeKeymasterBlob(exportData, out);
-    return OK;
-}
-
-/**
- * Read a byte array from in. The data at *data is still owned by the parcel
- */
-static void readByteArray(const Parcel& in, const uint8_t** data, size_t* length) {
-    ssize_t slength = in.readInt32();
-    if (slength > 0) {
-        *data = reinterpret_cast<const uint8_t*>(in.readInplace(slength));
-        if (*data) {
-            *length = static_cast<size_t>(slength);
-        } else {
-            *length = 0;
-        }
-    } else {
-        *data = NULL;
-        *length = 0;
-    }
-}
-
-class BpKeystoreService : public BpInterface<IKeystoreService> {
-  public:
-    explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {}
-
-    // test ping
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        ResponseCode ret = ResponseCode(reply.readInt32());
-        if (err < 0) {
-            ALOGD("getState() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ret;
-    }
-
-    KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
-                                  hidl_vec<uint8_t>* item) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("get() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("get() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        auto resultItem = readBlobAsByteArray(reply);
-        if (item) *item = resultItem.value();
-        return ResponseCode(reply.readInt32());
-    }
-
-    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);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("import() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    KeyStoreServiceReturnCode del(const String16& name, int uid) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("del() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("del() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    KeyStoreServiceReturnCode exist(const String16& name, int uid) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("exist() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("exist() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    KeyStoreServiceReturnCode list(const String16& prefix, int uid,
-                                   Vector<String16>* matches) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(prefix);
-        data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("list() could not contact remote: %d\n", status);
-            return 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());
-        }
-        if (err < 0) {
-            ALOGD("list() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("reset() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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);
-        if (status != NO_ERROR) {
-            ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("onUserPasswordChanged() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("lock() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    KeyStoreServiceReturnCode unlock(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::UNLOCK, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("unlock() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("unlock() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    bool isEmpty(int32_t userId) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeInt32(userId);
-        status_t status = remote()->transact(BnKeystoreService::IS_EMPTY, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("isEmpty() could not contact remote: %d\n", status);
-            return false;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("isEmpty() caught exception %d\n", err);
-            return false;
-        }
-        return reply.readInt32() != 0;
-    }
-
-    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);
-        data.writeInt32(uid);
-        data.writeInt32(keyType);
-        data.writeInt32(keySize);
-        data.writeInt32(flags);
-        data.writeInt32(1);
-        data.writeInt32(args->size());
-        for (Vector<sp<KeystoreArg>>::iterator it = args->begin(); it != args->end(); ++it) {
-            sp<KeystoreArg> item = *it;
-            size_t keyLength = item->size();
-            data.writeInt32(keyLength);
-            void* buf = data.writeInplace(keyLength);
-            memcpy(buf, item->data(), keyLength);
-        }
-        status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("generate() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("generate() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("import() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("import() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        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());
-    }
-
-    KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in,
-                                     const hidl_vec<uint8_t>& signature) override {
-        Parcel data, reply;
-
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("verify() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("get_pubkey() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        auto resultKey = readBlobAsByteArray(reply);
-        if (pubkey) *pubkey = resultKey.value();
-        return ResponseCode(reply.readInt32());
-    }
-
-    String16 grant(const String16& name, int32_t granteeUid) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeInt32(granteeUid);
-        status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("grant() could not contact remote: %d\n", status);
-            return String16();
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("grant() caught exception %d\n", err);
-            return String16();
-        }
-        return reply.readString16();
-    }
-
-    KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeInt32(granteeUid);
-        status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("ungrant() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("ungrant() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    int64_t getmtime(const String16& name, int32_t uid) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("getmtime() could not contact remote: %d\n", status);
-            return -1;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("getmtime() caught exception %d\n", err);
-            return -1;
-        }
-        return reply.readInt64();
-    }
-
-    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);
-        data.writeInt32(srcUid);
-        data.writeString16(destKey);
-        data.writeInt32(destUid);
-        status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("duplicate() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("duplicate() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    int32_t is_hardware_backed(const String16& keyType) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(keyType);
-        status_t status = remote()->transact(BnKeystoreService::IS_HARDWARE_BACKED, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("is_hardware_backed() could not contact remote: %d\n", status);
-            return -1;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("is_hardware_backed() caught exception %d\n", err);
-            return -1;
-        }
-        return reply.readInt32();
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("clear_uid() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("addRngEntropy() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    };
-
-    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);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        ResponseCode ret = ResponseCode(reply.readInt32());
-        if (err < 0) {
-            ALOGD("generateKey() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        if (outCharacteristics) {
-            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
-        }
-        return ret;
-    }
-    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);
-        writeBlobAsByteArray(clientId, &data);
-        writeBlobAsByteArray(appData, &data);
-        data.writeInt32(uid);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        ResponseCode ret = ResponseCode(reply.readInt32());
-        if (err < 0) {
-            ALOGD("getKeyCharacteristics() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        if (outCharacteristics) {
-            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
-        }
-        return ret;
-    }
-    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);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        ResponseCode ret = ResponseCode(reply.readInt32());
-        if (err < 0) {
-            ALOGD("importKey() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        if (outCharacteristics) {
-            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
-        }
-        return ret;
-    }
-
-    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;
-        }
-
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeString16(name);
-        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 = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("exportKey() caught exception %d\n", err);
-            result->resultCode = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-
-        reply.readParcelable(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;
-        }
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeStrongBinder(appToken);
-        data.writeString16(name);
-        data.writeInt32(int32_t(purpose));
-        data.writeInt32(pruneable ? 1 : 0);
-        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 = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("begin() caught exception %d\n", err);
-            result->resultCode = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-
-        reply.readParcelable(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);
-        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 = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("update() caught exception %d\n", err);
-            result->resultCode = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-
-        reply.readParcelable(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);
-        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 = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("finish() caught exception %d\n", err);
-            result->resultCode = ResponseCode::SYSTEM_ERROR;
-            return;
-        }
-
-        reply.readParcelable(result);
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("abort() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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);
-        if (status != NO_ERROR) {
-            ALOGD("isOperationAuthorized() could not contact remote: %d\n", status);
-            return false;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("isOperationAuthorized() caught exception %d\n", err);
-            return false;
-        }
-        return reply.readInt32() == 1;
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("addAuthToken() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    };
-
-    KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeInt32(userId);
-        data.writeInt32(parentId);
-        status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply);
-        if (status != NO_ERROR) {
-            ALOGD("onUserAdded() could not contact remote: %d\n", status);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("onUserAdded() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("onUserRemoved() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        return ResponseCode(reply.readInt32());
-    }
-
-    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);
-        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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        ResponseCode ret = ResponseCode(reply.readInt32());
-        if (err < 0) {
-            ALOGD("attestKey() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        if (reply.readInt32() != 0) {
-            *outChain = readCertificateChainFromParcel(reply);
-        }
-        return ret;
-    }
-
-    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 ResponseCode::SYSTEM_ERROR;
-        }
-        int32_t err = reply.readExceptionCode();
-        if (err < 0) {
-            ALOGD("onDeviceOffBody() caught exception %d\n", err);
-            return ResponseCode::SYSTEM_ERROR;
-        }
-        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();
-        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;
-            }
-            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();
-        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();
-        String16 ret = grant(name, granteeUid);
-        reply->writeNoException();
-        reply->writeString16(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();
-        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();
-        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();
-        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 IS_OPERATION_AUTHORIZED: {
-        CHECK_INTERFACE(IKeystoreService, data, reply);
-        sp<IBinder> token = data.readStrongBinder();
-        bool result = isOperationAuthorized(token);
-        reply->writeNoException();
-        reply->writeInt32(result ? 1 : 0);
-
-        return NO_ERROR;
-    }
-    case ADD_AUTH_TOKEN: {
-        CHECK_INTERFACE(IKeystoreService, data, reply);
-        const uint8_t* token_bytes = NULL;
-        size_t size = 0;
-        readByteArray(data, &token_bytes, &size);
-        int32_t result = addAuthToken(token_bytes, size);
-        reply->writeNoException();
-        reply->writeInt32(result);
-
-        return NO_ERROR;
-    }
-    case ON_USER_ADDED: {
-        CHECK_INTERFACE(IKeystoreService, data, reply);
-        int32_t userId = data.readInt32();
-        int32_t parentId = data.readInt32();
-        int32_t result = onUserAdded(userId, parentId);
-        reply->writeNoException();
-        reply->writeInt32(result);
-
-        return NO_ERROR;
-    }
-    case ON_USER_REMOVED: {
-        CHECK_INTERFACE(IKeystoreService, data, reply);
-        int32_t userId = data.readInt32();
-        int32_t result = onUserRemoved(userId);
-        reply->writeNoException();
-        reply->writeInt32(result);
-
-        return NO_ERROR;
-    }
-    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 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
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
index 1352124..4bc939d 100644
--- a/keystore/KeyAttestationApplicationId.cpp
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -23,6 +23,14 @@
 namespace security {
 namespace keymaster {
 
+KeyAttestationApplicationId::KeyAttestationApplicationId() = default;
+
+KeyAttestationApplicationId::KeyAttestationApplicationId(
+        std::unique_ptr<KeyAttestationPackageInfo> package) :
+    packageInfos_(new std::vector<std::unique_ptr<KeyAttestationPackageInfo>>()) {
+    packageInfos_->push_back(std::move(package));
+}
+
 status_t KeyAttestationApplicationId::writeToParcel(Parcel* parcel) const {
     return parcel->writeParcelableVector(packageInfos_);
 }
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
index a84c246..75fbb7a 100644
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -23,10 +23,17 @@
 namespace security {
 namespace keymaster {
 
+KeyAttestationPackageInfo::KeyAttestationPackageInfo() = default;
+
+KeyAttestationPackageInfo::KeyAttestationPackageInfo(const String16& packageName,
+                                                     int64_t versionCode,
+                                                     SharedSignaturesVector signatures)
+    : packageName_(new String16(packageName)), versionCode_(versionCode), signatures_(signatures) {}
+
 status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
     auto rc = parcel->writeString16(packageName_);
     if (rc != NO_ERROR) return rc;
-    rc = parcel->writeInt32(versionCode_);
+    rc = parcel->writeInt64(versionCode_);
     if (rc != NO_ERROR) return rc;
     return parcel->writeParcelableVector(signatures_);
 }
@@ -34,10 +41,10 @@
 status_t KeyAttestationPackageInfo::readFromParcel(const Parcel* parcel) {
     auto rc = parcel->readString16(&packageName_);
     if (rc != NO_ERROR) return rc;
-    rc = parcel->readInt32(&versionCode_);
+    rc = parcel->readInt64(&versionCode_);
     if (rc != NO_ERROR) return rc;
 
-    std::unique_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> temp_vector;
+    std::unique_ptr<SignaturesVector> temp_vector;
     rc = parcel->readParcelableVector(&temp_vector);
     if (rc != NO_ERROR) return rc;
     signatures_.reset(temp_vector.release());
diff --git a/keystore/keystore.cpp b/keystore/KeyStore.cpp
similarity index 81%
rename from keystore/keystore.cpp
rename to keystore/KeyStore.cpp
index a61ef73..f197d91 100644
--- a/keystore/keystore.cpp
+++ b/keystore/KeyStore.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "keystore"
 
-#include "keystore.h"
+#include "KeyStore.h"
 
 #include <dirent.h>
 #include <fcntl.h>
@@ -26,26 +26,47 @@
 #include <utils/String16.h>
 #include <utils/String8.h>
 
-#include <keystore/IKeystoreService.h>
-
+#include <android-base/scopeguard.h>
 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <android/security/IKeystoreService.h>
+#include <log/log_event_list.h>
+
+#include <private/android_logger.h>
 
 #include "keystore_utils.h"
 #include "permissions.h"
 #include <keystore/keystore_hidl_support.h>
 
-const char* KeyStore::sOldMasterKey = ".masterkey";
-const char* KeyStore::sMetaDataFile = ".metadata";
+namespace keystore {
 
-const android::String16 KeyStore::sRSAKeyType("RSA");
+const char* KeyStore::kOldMasterKey = ".masterkey";
+const char* KeyStore::kMetaDataFile = ".metadata";
 
-using namespace keystore;
+const android::String16 KeyStore::kRsaKeyType("RSA");
+const android::String16 KeyStore::kEcKeyType("EC");
+
 using android::String8;
 
-KeyStore::KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
-                   bool allowNewFallback)
-    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback),
-      mAllowNewFallback(allowNewFallback) {
+sp<Keymaster>& KeymasterDevices::operator[](SecurityLevel secLevel) {
+    static_assert(uint32_t(SecurityLevel::SOFTWARE) == 0 &&
+                      uint32_t(SecurityLevel::TRUSTED_ENVIRONMENT) == 1 &&
+                      uint32_t(SecurityLevel::STRONGBOX) == 2,
+                  "Numeric values of security levels have changed");
+    return at(static_cast<uint32_t>(secLevel));
+}
+
+sp<Keymaster> KeymasterDevices::operator[](SecurityLevel secLevel) const {
+    if (static_cast<uint32_t>(secLevel) > static_cast<uint32_t>(SecurityLevel::STRONGBOX)) {
+        LOG(ERROR) << "Invalid security level requested";
+        return nullptr;
+    }
+    return (*const_cast<KeymasterDevices*>(this))[secLevel];
+}
+
+KeyStore::KeyStore(Entropy* entropy, const KeymasterDevices& kmDevices,
+                   SecurityLevel minimalAllowedSecurityLevelForNewKeys)
+    : mEntropy(entropy), mKmDevices(kmDevices),
+      mAllowNewFallback(minimalAllowedSecurityLevelForNewKeys == SecurityLevel::SOFTWARE) {
     memset(&mMetaData, '\0', sizeof(mMetaData));
 }
 
@@ -131,8 +152,8 @@
     }
 }
 
-android::String8 KeyStore::getKeyNameForUid(
-    const android::String8& keyName, uid_t uid, const BlobType type) {
+android::String8 KeyStore::getKeyNameForUid(const android::String8& keyName, uid_t uid,
+                                            const BlobType type) {
     std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
     encode_key(encoded.data(), keyName);
     if (type == TYPE_KEY_CHARACTERISTICS) {
@@ -142,8 +163,8 @@
     }
 }
 
-android::String8 KeyStore::getKeyNameForUidWithDir(
-    const android::String8& keyName, uid_t uid, const BlobType type) {
+android::String8 KeyStore::getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid,
+                                                   const BlobType type) {
     std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
     encode_key(encoded.data(), keyName);
 
@@ -157,7 +178,7 @@
 }
 
 NullOr<android::String8> KeyStore::getBlobFileNameIfExists(const android::String8& alias, uid_t uid,
-                                                          const BlobType type) {
+                                                           const BlobType type) {
     android::String8 filepath8(getKeyNameForUidWithDir(alias, uid, type));
 
     if (!access(filepath8.string(), R_OK | W_OK)) return filepath8;
@@ -172,14 +193,14 @@
     // They might be using a granted key.
     auto grant = mGrants.get(uid, alias.string());
     if (grant) {
-        filepath8 = String8::format("%s/%s", grant->owner_dir_name_.c_str(),
-                getKeyNameForUid(String8(grant->alias_.c_str()), grant->owner_uid_, type).c_str());
+        filepath8 = String8::format(
+            "%s/%s", grant->owner_dir_name_.c_str(),
+            getKeyNameForUid(String8(grant->alias_.c_str()), grant->owner_uid_, type).c_str());
         if (!access(filepath8.string(), R_OK | W_OK)) return filepath8;
     }
     return {};
 }
 
-
 void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
     android::String8 prefix("");
     android::Vector<android::String16> aliases;
@@ -224,9 +245,9 @@
 
             // del() will fail silently if no cached characteristics are present for this alias.
             android::String8 chr_filename(aliases[i]);
-            chr_filename = android::String8::format("%s/%s", userState->getUserDirName(),
-                                            getKeyName(chr_filename,
-                                                TYPE_KEY_CHARACTERISTICS).string());
+            chr_filename = android::String8::format(
+                "%s/%s", userState->getUserDirName(),
+                getKeyName(chr_filename, TYPE_KEY_CHARACTERISTICS).string());
             del(chr_filename, ::TYPE_KEY_CHARACTERISTICS, userId);
         }
     }
@@ -277,10 +298,19 @@
     userState->setState(STATE_LOCKED);
 }
 
+static void maybeLogKeyIntegrityViolation(const char* filename, const BlobType type);
+
 ResponseCode KeyStore::get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
     UserState* userState = getUserState(userId);
-    ResponseCode rc =
-        keyBlob->readBlob(filename, userState->getEncryptionKey(), userState->getState());
+    ResponseCode rc;
+
+    auto logOnScopeExit = android::base::make_scope_guard([&] {
+        if (rc == ResponseCode::VALUE_CORRUPTED) {
+            maybeLogKeyIntegrityViolation(filename, type);
+        }
+    });
+
+    rc = keyBlob->readBlob(filename, userState->getEncryptionKey(), userState->getState());
     if (rc != ResponseCode::NO_ERROR) {
         return rc;
     }
@@ -351,25 +381,29 @@
             // remove possible grants
             mGrants.removeAllGrantsToKey(uid, alias);
         }
-        return (unlink(filename) && errno != ENOENT) ?
-                ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
+        return (unlink(filename) && errno != ENOENT) ? ResponseCode::SYSTEM_ERROR
+                                                     : ResponseCode::NO_ERROR;
     }
     if (rc != ResponseCode::NO_ERROR) {
         return rc;
     }
 
-    auto& dev = getDevice(keyBlob);
+    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 (ret != ErrorCode::OK && ret != ErrorCode::UNIMPLEMENTED)
-            return ResponseCode::SYSTEM_ERROR;
+        bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED;
+        if (__android_log_security() && uidAlias.isOk()) {
+            android_log_event_list(SEC_TAG_KEY_DESTROYED)
+                << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY;
+        }
+        if (!success) return ResponseCode::SYSTEM_ERROR;
     }
 
-    rc = (unlink(filename) && errno != ENOENT) ?
-            ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
+    rc =
+        (unlink(filename) && errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
 
     if (rc == ResponseCode::NO_ERROR && keyBlob.getType() != ::TYPE_KEY_CHARACTERISTICS) {
         // now that we have successfully deleted a key, let's make sure there are no stale grants
@@ -419,8 +453,8 @@
 
 static NullOr<std::tuple<uid_t, std::string>> filename2UidAlias(const std::string& filepath) {
     auto filenamebase = filepath.find_last_of('/');
-    std::string filename = filenamebase == std::string::npos ? filepath :
-            filepath.substr(filenamebase + 1);
+    std::string filename =
+        filenamebase == std::string::npos ? filepath : filepath.substr(filenamebase + 1);
 
     if (filename[0] == '.') return {};
 
@@ -524,16 +558,26 @@
     hidl_vec<uint8_t> blob;
 
     ErrorCode error;
-    auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
-            const KeyCharacteristics& /* ignored */) {
+    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);
 
+    SecurityLevel securityLevel = flagsToSecurityLevel(flags);
+    auto kmDevice = getDevice(securityLevel);
+    if (!kmDevice) {
+        // As of this writing the only caller is KeyStore::get in an attempt to import legacy
+        // software keys. It only ever requests TEE as target which must always be present.
+        // If we see this error, we probably have a new and unanticipated caller.
+        ALOGE("No implementation for security level %d. Cannot import key.", securityLevel);
+        return ResponseCode::SYSTEM_ERROR;
+    }
+
     ErrorCode rc = KS_HANDLE_HIDL_ERROR(
-            mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
+        kmDevice->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);
@@ -543,30 +587,23 @@
     Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10);
 
     keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-    keyBlob.setFallback(false);
+    keyBlob.setSecurityLevel(securityLevel);
 
     return put(filename, &keyBlob, userId);
 }
 
-bool KeyStore::isHardwareBacked(const android::String16& /*keyType*/) const {
-    using ::android::hardware::hidl_string;
-    if (mDevice == NULL) {
+bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
+    // if strongbox device is present TEE must also be present and of sufficiently high version
+    // to support all keys in hardware
+    if (getDevice(SecurityLevel::STRONGBOX)) return true;
+    if (!getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)) {
         ALOGW("can't get keymaster device");
         return false;
     }
 
-    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;
+    auto version = getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)->halVersion();
+    if (keyType == kRsaKeyType) return true;  // All versions support RSA
+    return keyType == kEcKeyType && version.supportsEc;
 }
 
 ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
@@ -574,8 +611,7 @@
     auto filepath8 = getBlobFileNameIfExists(keyName, uid, type);
     uid_t userId = get_user_id(uid);
 
-    if (filepath8.isOk())
-        return get(filepath8.value().string(), keyBlob, type, userId);
+    if (filepath8.isOk()) return get(filepath8.value().string(), keyBlob, type, userId);
 
     return ResponseCode::KEY_NOT_FOUND;
 }
@@ -704,7 +740,7 @@
 }
 
 void KeyStore::readMetaData() {
-    int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
+    int in = TEMP_FAILURE_RETRY(open(kMetaDataFile, O_RDONLY));
     if (in < 0) {
         return;
     }
@@ -729,7 +765,7 @@
               sizeof(mMetaData));
     }
     close(out);
-    rename(tmpFileName, sMetaDataFile);
+    rename(tmpFileName, kMetaDataFile);
 }
 
 bool KeyStore::upgradeKeystore() {
@@ -742,8 +778,8 @@
         userState->initialize();
 
         // Migrate the old .masterkey file to user 0.
-        if (access(sOldMasterKey, R_OK) == 0) {
-            if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
+        if (access(kOldMasterKey, R_OK) == 0) {
+            if (rename(kOldMasterKey, userState->getMasterKeyFileName()) < 0) {
                 ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
                 return false;
             }
@@ -802,3 +838,17 @@
 
     return upgraded;
 }
+
+static void maybeLogKeyIntegrityViolation(const char* filename, const BlobType type) {
+    if (!__android_log_security() || (type != TYPE_KEY_PAIR && type != TYPE_KEYMASTER_10)) return;
+
+    auto uidAlias = filename2UidAlias(filename);
+    uid_t uid = -1;
+    std::string alias;
+
+    if (uidAlias.isOk()) std::tie(uid, alias) = std::move(uidAlias).value();
+
+    log_key_integrity_violation(alias.c_str(), uid);
+}
+
+}  // namespace keystore
diff --git a/keystore/keystore.h b/keystore/KeyStore.h
similarity index 75%
rename from keystore/keystore.h
rename to keystore/KeyStore.h
index a0b747f..23476d2 100644
--- a/keystore/keystore.h
+++ b/keystore/KeyStore.h
@@ -17,43 +17,57 @@
 #ifndef KEYSTORE_KEYSTORE_H_
 #define KEYSTORE_KEYSTORE_H_
 
-#include "user_state.h"
-
 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-
+#include <keymasterV4_0/Keymaster.h>
 #include <utils/Vector.h>
 
-#include "blob.h"
-#include "include/keystore/keymaster_tags.h"
-#include "grant_store.h"
+#include <keystore/keymaster_types.h>
 
-using ::keystore::NullOr;
+#include "blob.h"
+#include "grant_store.h"
+#include "user_state.h"
+
+namespace keystore {
+
+using ::android::sp;
+using keymaster::support::Keymaster;
+
+class KeymasterDevices : public std::array<sp<Keymaster>, 3> {
+  public:
+    sp<Keymaster>& operator[](SecurityLevel secLevel);
+    sp<Keymaster> operator[](SecurityLevel secLevel) const;
+};
 
 class KeyStore {
-    typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
-
   public:
-    KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
-             bool allowNewFallback);
+    KeyStore(Entropy* entropy, const KeymasterDevices& kmDevices,
+             SecurityLevel minimalAllowedSecurityLevelForNewKeys);
     ~KeyStore();
 
-    km_device_t& getDevice() { return mDevice; }
+    sp<Keymaster> getDevice(SecurityLevel securityLevel) const { return mKmDevices[securityLevel]; }
 
-    NullOr<km_device_t&> getFallbackDevice() {
+    std::pair<sp<Keymaster>, SecurityLevel> getMostSecureDevice() const {
+        SecurityLevel level = SecurityLevel::STRONGBOX;
+        do {
+            if (mKmDevices[level].get()) {
+                return {mKmDevices[level], level};
+            }
+            level = static_cast<SecurityLevel>(static_cast<uint32_t>(level) - 1);
+        } while (level != SecurityLevel::SOFTWARE);
+        return {nullptr, SecurityLevel::SOFTWARE};
+    }
+
+    sp<Keymaster> getFallbackDevice() const {
         // we only return the fallback device if the creation of new fallback key blobs is
         // allowed. (also see getDevice below)
         if (mAllowNewFallback) {
-            return mFallbackDevice;
+            return mKmDevices[SecurityLevel::SOFTWARE];
         } else {
-            return {};
+            return nullptr;
         }
     }
 
-    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;
-    }
+    sp<Keymaster> getDevice(const Blob& blob) { return mKmDevices[blob.getSecurityLevel()]; }
 
     ResponseCode initialize();
 
@@ -71,7 +85,7 @@
     android::String8 getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid,
                                              const BlobType type);
     NullOr<android::String8> getBlobFileNameIfExists(const android::String8& alias, uid_t uid,
-                                                    const BlobType type);
+                                                     const BlobType type);
 
     /*
      * Delete entries owned by userId. If keepUnencryptedEntries is true
@@ -122,13 +136,13 @@
     const UserState* getUserStateByUid(uid_t uid) const;
 
   private:
-    static const char* sOldMasterKey;
-    static const char* sMetaDataFile;
-    static const android::String16 sRSAKeyType;
+    static const char* kOldMasterKey;
+    static const char* kMetaDataFile;
+    static const android::String16 kRsaKeyType;
+    static const android::String16 kEcKeyType;
     Entropy* mEntropy;
 
-    km_device_t mDevice;
-    km_device_t mFallbackDevice;
+    KeymasterDevices mKmDevices;
     bool mAllowNewFallback;
 
     android::Vector<UserState*> mMasterKeys;
@@ -158,4 +172,6 @@
     bool upgradeKeystore();
 };
 
+}  // namespace keystore
+
 #endif  // KEYSTORE_KEYSTORE_H_
diff --git a/keystore/KeymasterArguments.cpp b/keystore/KeymasterArguments.cpp
new file mode 100644
index 0000000..829156c
--- /dev/null
+++ b/keystore/KeymasterArguments.cpp
@@ -0,0 +1,42 @@
+/*
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "include/keystore/KeymasterArguments.h"
+#include "keystore_aidl_hidl_marshalling_utils.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+using ::android::status_t;
+status_t KeymasterArguments::readFromParcel(const android::Parcel* in) {
+    data_ = keystore::readParamSetFromParcel(*in);
+    return OK;
+};
+
+status_t KeymasterArguments::writeToParcel(android::Parcel* out) const {
+    return keystore::writeParamSetToParcel(data_, out);
+};
+
+KeymasterArguments::KeymasterArguments(const hardware::hidl_vec<keystore::KeyParameter>& other)
+    : data_(other) {}
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
diff --git a/keystore/KeystoreArguments.cpp b/keystore/KeystoreArguments.cpp
new file mode 100644
index 0000000..fe53c29
--- /dev/null
+++ b/keystore/KeystoreArguments.cpp
@@ -0,0 +1,61 @@
+/*
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "include/keystore/KeystoreArguments.h"
+#include "keystore_aidl_hidl_marshalling_utils.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+
+using ::android::security::KeystoreArg;
+using ::android::security::KeystoreArguments;
+
+const ssize_t MAX_GENERATE_ARGS = 3;
+status_t KeystoreArguments::readFromParcel(const android::Parcel* in) {
+    ssize_t numArgs = in->readInt32();
+    if (numArgs > MAX_GENERATE_ARGS) {
+        return BAD_VALUE;
+    }
+    if (numArgs > 0) {
+        for (size_t i = 0; i < static_cast<size_t>(numArgs); i++) {
+            ssize_t inSize = in->readInt32();
+            if (inSize >= 0 && static_cast<size_t>(inSize) <= in->dataAvail()) {
+                sp<KeystoreArg> arg = new KeystoreArg(in->readInplace(inSize), inSize);
+                args.push_back(arg);
+            } else {
+                args.push_back(NULL);
+            }
+        }
+    }
+    return OK;
+};
+
+status_t KeystoreArguments::writeToParcel(android::Parcel* out) const {
+    out->writeInt32(args.size());
+    for (sp<KeystoreArg> item : args) {
+        size_t keyLength = item->size();
+        out->writeInt32(keyLength);
+        void* buf = out->writeInplace(keyLength);
+        memcpy(buf, item->data(), keyLength);
+    }
+    return OK;
+}
+
+}  // namespace security
+}  // namespace android
diff --git a/keystore/OperationResult.cpp b/keystore/OperationResult.cpp
new file mode 100644
index 0000000..53c8d62
--- /dev/null
+++ b/keystore/OperationResult.cpp
@@ -0,0 +1,60 @@
+/*
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "include/keystore/OperationResult.h"
+
+#include <utility>
+
+#include <binder/Parcel.h>
+
+#include <keystore/keymaster_types.h>
+
+#include "keystore_aidl_hidl_marshalling_utils.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+using keystore::keymaster::ErrorCode;
+using ::android::status_t;
+
+OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
+
+status_t OperationResult::readFromParcel(const Parcel* inn) {
+    const Parcel& in = *inn;
+    resultCode = ErrorCode(in.readInt32());
+    token = in.readStrongBinder();
+    handle = static_cast<uint64_t>(in.readInt64());
+    inputConsumed = in.readInt32();
+    data = keystore::readKeymasterBlob(in);
+    outParams = keystore::readParamSetFromParcel(in);
+    return OK;
+}
+
+status_t OperationResult::writeToParcel(Parcel* out) const {
+    out->writeInt32(resultCode);
+    out->writeStrongBinder(token);
+    out->writeInt64(handle);
+    out->writeInt32(inputConsumed);
+    keystore::writeKeymasterBlob(data, out);
+    keystore::writeParamSetToParcel(outParams, out);
+    return OK;
+}
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp
index 8b81e47..3c51c70 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -77,13 +77,12 @@
     return time.tv_sec;
 }
 
-void AuthTokenTable::AddAuthenticationToken(const HardwareAuthToken* auth_token) {
-    Entry new_entry(auth_token, clock_function_());
-    //STOPSHIP: debug only, to be removed
-    ALOGD("AddAuthenticationToken: timestamp = %llu (%llu), time_received = %lld",
-        static_cast<unsigned long long>(new_entry.timestamp_host_order()),
-        static_cast<unsigned long long>(auth_token->timestamp),
-        static_cast<long long>(new_entry.time_received()));
+void AuthTokenTable::AddAuthenticationToken(HardwareAuthToken&& auth_token) {
+    Entry new_entry(std::move(auth_token), clock_function_());
+    // STOPSHIP: debug only, to be removed
+    ALOGD("AddAuthenticationToken: timestamp = %llu, time_received = %lld",
+          static_cast<unsigned long long>(new_entry.token().timestamp),
+          static_cast<long long>(new_entry.time_received()));
 
     RemoveEntriesSupersededBy(new_entry);
     if (entries_.size() >= max_entries_) {
@@ -95,10 +94,8 @@
 }
 
 inline bool is_secret_key_operation(Algorithm algorithm, KeyPurpose purpose) {
-    if ((algorithm != Algorithm::RSA && algorithm != Algorithm::EC))
-        return true;
-    if (purpose == KeyPurpose::SIGN || purpose == KeyPurpose::DECRYPT)
-        return true;
+    if ((algorithm != Algorithm::RSA && algorithm != Algorithm::EC)) return true;
+    if (purpose == KeyPurpose::SIGN || purpose == KeyPurpose::DECRYPT) return true;
     return false;
 }
 
@@ -137,13 +134,13 @@
     if (op_handle == 0) return OP_HANDLE_REQUIRED;
 
     auto matching_op = find_if(
-        entries_, [&](Entry& e) { return e.token()->challenge == op_handle && !e.completed(); });
+        entries_, [&](Entry& e) { return e.token().challenge == op_handle && !e.completed(); });
 
     if (matching_op == entries_.end()) return AUTH_TOKEN_NOT_FOUND;
 
     if (!matching_op->SatisfiesAuth(sids, auth_type)) return AUTH_TOKEN_WRONG_SID;
 
-    *found = matching_op->token();
+    *found = &matching_op->token();
     return OK;
 }
 
@@ -172,7 +169,7 @@
     }
 
     newest_match->UpdateLastUse(now);
-    *found = newest_match->token();
+    *found = &newest_match->token();
     return OK;
 }
 
@@ -202,7 +199,7 @@
 }
 
 void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
-    auto found = find_if(entries_, [&](Entry& e) { return e.token()->challenge == op_handle; });
+    auto found = find_if(entries_, [&](Entry& e) { return e.token().challenge == op_handle; });
     if (found == entries_.end()) return;
 
     assert(!IsSupersededBySomeEntry(*found));
@@ -211,26 +208,15 @@
     if (IsSupersededBySomeEntry(*found)) entries_.erase(found);
 }
 
-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) {}
-
-uint64_t AuthTokenTable::Entry::timestamp_host_order() const {
-    return ntoh(token_->timestamp);
-}
-
-HardwareAuthenticatorType AuthTokenTable::Entry::authenticator_type() const {
-    HardwareAuthenticatorType result = static_cast<HardwareAuthenticatorType>(
-        ntoh(static_cast<uint32_t>(token_->authenticatorType)));
-    return result;
-}
+AuthTokenTable::Entry::Entry(HardwareAuthToken&& token, time_t current_time)
+    : token_(std::move(token)), time_received_(current_time), last_use_(current_time),
+      operation_completed_(token_.challenge == 0) {}
 
 bool AuthTokenTable::Entry::SatisfiesAuth(const std::vector<uint64_t>& sids,
                                           HardwareAuthenticatorType auth_type) {
-    for (auto sid : sids)
-        if ((sid == token_->authenticatorId) ||
-            (sid == token_->userId && (auth_type & authenticator_type()) != 0))
-            return true;
+    for (auto sid : sids) {
+        if (SatisfiesAuth(sid, auth_type)) return true;
+    }
     return false;
 }
 
@@ -241,10 +227,9 @@
 bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const {
     if (!entry.completed()) return false;
 
-    return (token_->userId == entry.token_->userId &&
-            token_->authenticatorType == entry.token_->authenticatorType &&
-            token_->authenticatorId == entry.token_->authenticatorId &&
-            timestamp_host_order() > entry.timestamp_host_order());
+    return (token_.userId == entry.token_.userId &&
+            token_.authenticatorType == entry.token_.authenticatorType &&
+            token_.authenticatorId == entry.token_.authenticatorId && is_newer_than(&entry));
 }
 
-}  // namespace keymaster
+}  // namespace keystore
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index 422c710..db60003 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -17,15 +17,14 @@
 #include <memory>
 #include <vector>
 
-#include <hardware/hw_auth_token.h>
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
 
 #ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
 #define KEYSTORE_AUTH_TOKEN_TABLE_H_
 
 namespace keystore {
 
-using android::hardware::keymaster::V3_0::HardwareAuthToken;
+using keymaster::HardwareAuthToken;
 
 namespace test {
 class AuthTokenTableTest;
@@ -59,9 +58,9 @@
     };
 
     /**
-     * Add an authorization token to the table.  The table takes ownership of the argument.
+     * Add an authorization token to the table.
      */
-    void AddAuthenticationToken(const HardwareAuthToken* token);
+    void AddAuthenticationToken(HardwareAuthToken&& auth_token);
 
     /**
      * Find an authorization token that authorizes the operation specified by \p operation_handle on
@@ -97,7 +96,7 @@
 
     class Entry {
       public:
-        Entry(const HardwareAuthToken* token, time_t current_time);
+        Entry(HardwareAuthToken&& token, time_t current_time);
         Entry(Entry&& entry) { *this = std::move(entry); }
 
         void operator=(Entry&& rhs) {
@@ -114,21 +113,30 @@
         bool Supersedes(const Entry& entry) const;
         bool SatisfiesAuth(const std::vector<uint64_t>& sids, HardwareAuthenticatorType auth_type);
 
-        bool is_newer_than(const Entry* entry) {
+        bool is_newer_than(const Entry* entry) const {
             if (!entry) return true;
-            return timestamp_host_order() > entry->timestamp_host_order();
+            uint64_t ts = token_.timestamp;
+            uint64_t other_ts = entry->token_.timestamp;
+            // Normally comparing timestamp_host_order alone is sufficient, but here is an
+            // additional hack to compare time_received value for some devices where their auth
+            // tokens contain fixed timestamp (due to the a stuck secure RTC on them)
+            return (ts > other_ts) ||
+                   ((ts == other_ts) && (time_received_ > entry->time_received_));
         }
 
         void mark_completed() { operation_completed_ = true; }
 
-        const HardwareAuthToken* token() { return token_.get(); }
+        const HardwareAuthToken& token() const & { return token_; }
         time_t time_received() const { return time_received_; }
         bool completed() const { return operation_completed_; }
-        uint64_t timestamp_host_order() const;
-        HardwareAuthenticatorType authenticator_type() const;
 
       private:
-        std::unique_ptr<const HardwareAuthToken> token_;
+        bool SatisfiesAuth(uint64_t sid, HardwareAuthenticatorType auth_type) const {
+            return (sid == token_.userId || sid == token_.authenticatorId) &&
+                   (auth_type & token_.authenticatorType) != 0;
+        }
+
+        HardwareAuthToken token_;
         time_t time_received_;
         time_t last_use_;
         bool operation_completed_;
@@ -150,6 +158,6 @@
     time_t (*clock_function_)();
 };
 
-}  // namespace keymaster
+}  // namespace keystore
 
 #endif  // KEYSTORE_AUTH_TOKEN_TABLE_H_
diff --git a/keystore/authorization_set.cpp b/keystore/authorization_set.cpp
index e30b32d..537fe3d 100644
--- a/keystore/authorization_set.cpp
+++ b/keystore/authorization_set.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
 
 #include <assert.h>
 #include <stddef.h>
diff --git a/keystore/binder/android/security/IConfirmationPromptCallback.aidl b/keystore/binder/android/security/IConfirmationPromptCallback.aidl
new file mode 100644
index 0000000..96a1a04
--- /dev/null
+++ b/keystore/binder/android/security/IConfirmationPromptCallback.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+/**
+ * This must be kept manually in sync with system/security/keystore until AIDL
+ * can generate both Java and C++ bindings.
+ *
+ * @hide
+ */
+interface IConfirmationPromptCallback {
+    oneway void onConfirmationPromptCompleted(in int result, in byte[] dataThatWasConfirmed);
+}
diff --git a/keystore/binder/android/security/IKeystoreService.aidl b/keystore/binder/android/security/IKeystoreService.aidl
new file mode 100644
index 0000000..db55062
--- /dev/null
+++ b/keystore/binder/android/security/IKeystoreService.aidl
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.security.keymaster.ExportResult;
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterCertificateChain;
+import android.security.keymaster.KeymasterBlob;
+import android.security.keymaster.OperationResult;
+import android.security.KeystoreArguments;
+
+/**
+ * This must be kept manually in sync with system/security/keystore until AIDL
+ * can generate both Java and C++ bindings.
+ *
+ * @hide
+ */
+interface IKeystoreService {
+    int getState(int userId);
+    byte[] get(String name, int uid);
+    int insert(String name, in byte[] item, int uid, int flags);
+    int del(String name, int uid);
+    int exist(String name, int uid);
+    String[] list(String namePrefix, int uid);
+    int reset();
+    int onUserPasswordChanged(int userId, String newPassword);
+    int lock(int userId);
+    int unlock(int userId, String userPassword);
+    int isEmpty(int userId);
+    int generate(String name, int uid, int keyType, int keySize, int flags,
+        in KeystoreArguments args);
+    int import_key(String name, in byte[] data, int uid, int flags);
+    byte[] sign(String name, in byte[] data);
+    int verify(String name, in byte[] data, in byte[] signature);
+    byte[] get_pubkey(String name);
+    String grant(String name, int granteeUid);
+    int ungrant(String name, int granteeUid);
+    long getmtime(String name, int uid);
+    int is_hardware_backed(String string);
+    int clear_uid(long uid);
+
+    // Keymaster 0.4 methods
+    int addRngEntropy(in byte[] data, int flags);
+    int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid,
+        int flags, out KeyCharacteristics characteristics);
+    int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appData,
+        int uid, out KeyCharacteristics characteristics);
+    int importKey(String alias, in KeymasterArguments arguments, int format,
+        in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics);
+    ExportResult exportKey(String alias, int format, in KeymasterBlob clientId,
+        in KeymasterBlob appData, int uid);
+    OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
+        in KeymasterArguments params, in byte[] entropy, int uid);
+    OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
+    OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature,
+        in byte[] entropy);
+    int abort(IBinder handle);
+    boolean isOperationAuthorized(IBinder token);
+    int addAuthToken(in byte[] authToken);
+    int onUserAdded(int userId, int parentId);
+    int onUserRemoved(int userId);
+    int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain);
+    int attestDeviceIds(in KeymasterArguments params, out KeymasterCertificateChain chain);
+    int onDeviceOffBody();
+    int importWrappedKey(in String wrappedKeyAlias, in byte[] wrappedKey,
+        in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments,
+        in long rootSid, in long fingerprintSid,
+        out KeyCharacteristics characteristics);
+    int presentConfirmationPrompt(IBinder listener, String promptText, in byte[] extraData,
+        in String locale, in int uiOptionsAsFlags);
+    int cancelConfirmationPrompt(IBinder listener);
+    boolean isConfirmationPromptSupported();
+    int onKeyguardVisibilityChanged(in boolean isShowing, in int userId);
+}
diff --git a/keystore/binder/android/security/KeystoreArguments.aidl b/keystore/binder/android/security/KeystoreArguments.aidl
new file mode 100644
index 0000000..dc8ed50
--- /dev/null
+++ b/keystore/binder/android/security/KeystoreArguments.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+/* @hide */
+parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/ExportResult.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/ExportResult.aidl
index 0dcbadd..1748653 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/ExportResult.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,12 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <keymaster/softkeymaster.h>
 
-#include <keystore/keystore.h>
+package android.security.keymaster;
 
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = softkeymaster_module;
+/* @hide */
+parcelable ExportResult cpp_header "keystore/ExportResult.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
index 0dcbadd..32e75ad 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,12 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <keymaster/softkeymaster.h>
 
-#include <keystore/keystore.h>
+package android.security.keymaster;
 
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = softkeymaster_module;
+/* @hide */
+parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeymasterArguments.aidl
similarity index 65%
rename from softkeymaster/module.cpp
rename to keystore/binder/android/security/keymaster/KeymasterArguments.aidl
index 0dcbadd..44d9f09 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeymasterArguments.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,12 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <keymaster/softkeymaster.h>
 
-#include <keystore/keystore.h>
+package android.security.keymaster;
 
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = softkeymaster_module;
+/* @hide */
+parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeymasterBlob.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/KeymasterBlob.aidl
index 0dcbadd..5c5db9e 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeymasterBlob.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,12 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <keymaster/softkeymaster.h>
 
-#include <keystore/keystore.h>
+package android.security.keymaster;
 
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = softkeymaster_module;
+/* @hide */
+parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
index 0dcbadd..ddb5cae 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,12 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <keymaster/softkeymaster.h>
 
-#include <keystore/keystore.h>
+package android.security.keymaster;
 
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = softkeymaster_module;
+/* @hide */
+parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/OperationResult.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/OperationResult.aidl
index 0dcbadd..db689d4 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/OperationResult.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,12 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <keymaster/softkeymaster.h>
 
-#include <keystore/keystore.h>
+package android.security.keymaster;
 
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
-    = softkeymaster_module;
+/* @hide */
+parcelable OperationResult cpp_header "keystore/OperationResult.h";
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 625d057..d21c691 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -114,13 +114,13 @@
     out_pos += out_len;
     if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
         ALOGD("Failed to decrypt blob; ciphertext or tag is likely corrupted");
-        return ResponseCode::SYSTEM_ERROR;
+        return ResponseCode::VALUE_CORRUPTED;
     }
     out_pos += out_len;
     if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
         ALOGD("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
               out_pos - out_tmp.get());
-        return ResponseCode::SYSTEM_ERROR;
+        return ResponseCode::VALUE_CORRUPTED;
     }
 
     std::copy(out_tmp.get(), out_pos, out);
@@ -327,3 +327,12 @@
 
     return ResponseCode::NO_ERROR;
 }
+
+keystore::SecurityLevel Blob::getSecurityLevel() const {
+    return keystore::flagsToSecurityLevel(mBlob.flags);
+}
+
+void Blob::setSecurityLevel(keystore::SecurityLevel secLevel) {
+    mBlob.flags &= ~(KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX);
+    mBlob.flags |= keystore::securityLevelToFlags(secLevel);
+}
diff --git a/keystore/blob.h b/keystore/blob.h
index 5335037..665e07a 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -22,6 +22,7 @@
 #include <openssl/aes.h>
 #include <openssl/md5.h>
 
+#include <keystore/keymaster_types.h>
 #include <keystore/keystore.h>
 
 constexpr size_t kValueSize = 32768;
@@ -117,6 +118,9 @@
     BlobType getType() const { return BlobType(mBlob.type); }
     void setType(BlobType type) { mBlob.type = uint8_t(type); }
 
+    keystore::SecurityLevel getSecurityLevel() const;
+    void setSecurityLevel(keystore::SecurityLevel);
+
     ResponseCode writeBlob(const std::string& filename, const uint8_t* aes_key, State state,
                            Entropy* entropy);
     ResponseCode readBlob(const std::string& filename, const uint8_t* aes_key, State state);
diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp
new file mode 100644
index 0000000..0dee4aa
--- /dev/null
+++ b/keystore/confirmation_manager.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ConfirmationManager"
+
+#include "confirmation_manager.h"
+
+#include <android/hardware/confirmationui/1.0/IConfirmationResultCallback.h>
+#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
+#include <android/hardware/confirmationui/1.0/types.h>
+#include <android/security/BpConfirmationPromptCallback.h>
+#include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/Parcel.h>
+
+#include "keystore_aidl_hidl_marshalling_utils.h"
+
+namespace keystore {
+
+using android::IBinder;
+using android::sp;
+using android::String16;
+using android::String8;
+using android::wp;
+using android::binder::Status;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::confirmationui::V1_0::IConfirmationResultCallback;
+using android::hardware::confirmationui::V1_0::IConfirmationUI;
+using android::hardware::confirmationui::V1_0::UIOption;
+
+using android::security::BpConfirmationPromptCallback;
+using std::lock_guard;
+using std::mutex;
+using std::vector;
+
+ConfirmationManager::ConfirmationManager(IBinder::DeathRecipient* deathRecipient)
+    : IConfirmationResultCallback(), mDeathRecipient(deathRecipient) {}
+
+// Called by keystore main thread.
+Status ConfirmationManager::presentConfirmationPrompt(const sp<IBinder>& listener,
+                                                      const String16& promptText,
+                                                      const hidl_vec<uint8_t>& extraData,
+                                                      const String16& locale, int uiOptionsAsFlags,
+                                                      int32_t* aidl_return) {
+    lock_guard<mutex> lock(mMutex);
+
+    if (mCurrentListener != nullptr) {
+        *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OperationPending);
+        return Status::ok();
+    }
+
+    sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
+    if (confirmationUI == nullptr) {
+        ALOGW("Error getting confirmationUI service\n");
+        *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::Unimplemented);
+        return Status::ok();
+    }
+
+    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+    if (!mRateLimiting.tryPrompt(callingUid)) {
+        *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::SystemError);
+        return Status::ok();
+    }
+
+    String8 promptText8(promptText);
+    String8 locale8(locale);
+    vector<UIOption> uiOptionsVector;
+    for (int n = 0; n < 32; n++) {
+        if (uiOptionsAsFlags & (1 << n)) {
+            uiOptionsVector.push_back(UIOption(n));
+        }
+    }
+    ConfirmationResponseCode responseCode;
+    responseCode = confirmationUI->promptUserConfirmation(sp<IConfirmationResultCallback>(this),
+                                                          promptText8.string(), extraData,
+                                                          locale8.string(), uiOptionsVector);
+    if (responseCode != ConfirmationResponseCode::OK) {
+        ALOGW("Unexpecxted responseCode %d from promptUserConfirmation\n", responseCode);
+        *aidl_return = static_cast<int32_t>(responseCode);
+        return Status::ok();
+    }
+
+    listener->linkToDeath(mDeathRecipient);
+    confirmationUI->linkToDeath(this, 0);
+    mCurrentListener = listener;
+    mCurrentConfirmationUI = confirmationUI;
+
+    *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
+    return Status::ok();
+}
+
+// Called by keystore main thread.
+Status ConfirmationManager::cancelConfirmationPrompt(const sp<IBinder>& listener,
+                                                     int32_t* aidl_return) {
+    mMutex.lock();
+    if (mCurrentListener != listener) {
+        // If the prompt was displayed by another application, return
+        // OperationPending.
+        mMutex.unlock();
+        *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OperationPending);
+        return Status::ok();
+    }
+    mMutex.unlock();
+
+    finalizeTransaction(ConfirmationResponseCode::Aborted, {}, true);
+
+    *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
+    return Status::ok();
+}
+
+// Called by keystore main thread.
+Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
+    sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
+    if (confirmationUI == nullptr) {
+        ALOGW("Error getting confirmationUI service\n");
+        *aidl_return = false;
+        return Status::ok();
+    }
+
+    *aidl_return = true;
+    return Status::ok();
+}
+
+void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode,
+                                              hidl_vec<uint8_t> dataThatWasConfirmed,
+                                              bool callAbortOnHal) {
+    // Note that confirmationUI->abort() may make the remote HAL process do an IPC call back
+    // into our process resulting in confirmationResultCallback() to be called... this in turn
+    // calls finalizeTransaction(). So we have to be careful a) not holding any locks;
+    // and b) ensure state has been cleared; before doing this...
+
+    mMutex.lock();
+    mRateLimiting.processResult(responseCode);
+    sp<IBinder> listener = mCurrentListener;
+    if (mCurrentListener != nullptr) {
+        mCurrentListener->unlinkToDeath(mDeathRecipient);
+        mCurrentListener = nullptr;
+    }
+    sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
+    if (mCurrentConfirmationUI != nullptr) {
+        mCurrentConfirmationUI->unlinkToDeath(this);
+        mCurrentConfirmationUI = nullptr;
+    }
+    mMutex.unlock();
+
+    // Tell the HAL to shut down the confirmation dialog, if requested.
+    if (confirmationUI != nullptr && callAbortOnHal) {
+        confirmationUI->abort();
+    }
+
+    // Deliver result to the application that started the operation.
+    if (listener != nullptr) {
+        sp<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
+        Status status = obj->onConfirmationPromptCompleted(static_cast<int32_t>(responseCode),
+                                                           dataThatWasConfirmed);
+        if (!status.isOk()) {
+            ALOGW("Error sending onConfirmationPromptCompleted - status: %s\n",
+                  status.toString8().c_str());
+        }
+    }
+}
+
+// Called by hwbinder thread (not keystore main thread).
+Return<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
+                                         const hidl_vec<uint8_t>& dataThatWasConfirmed,
+                                         const hidl_vec<uint8_t>& confirmationToken) {
+    finalizeTransaction(responseCode, dataThatWasConfirmed, false);
+    lock_guard<mutex> lock(mMutex);
+    mLatestConfirmationToken = confirmationToken;
+    return Return<void>();
+}
+
+// Called by keystore main thread.
+hidl_vec<uint8_t> ConfirmationManager::getLatestConfirmationToken() {
+    lock_guard<mutex> lock(mMutex);
+    return mLatestConfirmationToken;
+}
+
+void ConfirmationManager::binderDied(const wp<IBinder>& who) {
+    // This is also called for other binders so need to check it's for
+    // us before acting on it.
+    mMutex.lock();
+    if (who == mCurrentListener) {
+        // Clear this so we don't call back into the already dead
+        // binder in finalizeTransaction().
+        mCurrentListener->unlinkToDeath(mDeathRecipient);
+        mCurrentListener = nullptr;
+        mMutex.unlock();
+        ALOGW("The process which requested the confirmation dialog died.\n");
+        finalizeTransaction(ConfirmationResponseCode::SystemError, {}, true);
+    } else {
+        mMutex.unlock();
+    }
+}
+
+void ConfirmationManager::serviceDied(uint64_t /* cookie */,
+                                      const wp<android::hidl::base::V1_0::IBase>& /* who */) {
+    ALOGW("The ConfirmationUI HAL died.\n");
+    finalizeTransaction(ConfirmationResponseCode::SystemError, {}, false);
+}
+
+}  // namespace keystore
diff --git a/keystore/confirmation_manager.h b/keystore/confirmation_manager.h
new file mode 100644
index 0000000..46b623c
--- /dev/null
+++ b/keystore/confirmation_manager.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_CONFIRMATION_MANAGER_H_
+#define KEYSTORE_CONFIRMATION_MANAGER_H_
+
+#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
+#include <android/hardware/confirmationui/1.0/types.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/Status.h>
+#include <keystore/keymaster_types.h>
+#include <map>
+#include <mutex>
+#include <utils/LruCache.h>
+#include <utils/StrongPointer.h>
+#include <vector>
+
+#include "confirmationui_rate_limiting.h"
+
+namespace keystore {
+
+using android::binder::Status;
+using android::hardware::confirmationui::V1_0::IConfirmationResultCallback;
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+
+class ConfirmationManager;
+
+class ConfirmationManager : public android::hardware::hidl_death_recipient,
+                            public IConfirmationResultCallback {
+  public:
+    explicit ConfirmationManager(android::IBinder::DeathRecipient* deathRecipient);
+
+    // Calls into the confirmationui HAL to start a new prompt.
+    //
+    // Returns OperationPending if another application is already
+    // showing a confirmation. Otherwise returns the return code from
+    // the HAL.
+    Status presentConfirmationPrompt(const android::sp<android::IBinder>& listener,
+                                     const android::String16& promptText,
+                                     const hidl_vec<uint8_t>& extraData,
+                                     const android::String16& locale, int uiOptionsAsFlags,
+                                     int32_t* aidl_return);
+
+    // Calls into the confirmationui HAL to cancel displaying a
+    // prompt.
+    //
+    // Returns OperatingPending if another application is showing a
+    // confirmation. Otherwise returns the return code from the HAL.
+    Status cancelConfirmationPrompt(const android::sp<android::IBinder>& listener,
+                                    int32_t* aidl_return);
+
+    // Checks if the confirmationUI HAL is available.
+    Status isConfirmationPromptSupported(bool* aidl_return);
+
+    // Gets the latest confirmation token received from the ConfirmationUI HAL.
+    hidl_vec<uint8_t> getLatestConfirmationToken();
+
+    // Called by KeyStoreService when a client binder has died.
+    void binderDied(const android::wp<android::IBinder>& who);
+
+    // hidl_death_recipient overrides:
+    virtual void serviceDied(uint64_t cookie,
+                             const android::wp<android::hidl::base::V1_0::IBase>& who) override;
+
+    // IConfirmationResultCallback overrides:
+    android::hardware::Return<void> result(ConfirmationResponseCode responseCode,
+                                           const hidl_vec<uint8_t>& dataThatWasConfirmed,
+                                           const hidl_vec<uint8_t>& confirmationToken) override;
+
+  private:
+    friend class ConfirmationResultCallback;
+
+    void finalizeTransaction(ConfirmationResponseCode responseCode,
+                             hidl_vec<uint8_t> dataThatWasConfirmed, bool callAbortOnHal);
+
+    // This mutex protects all data below it.
+    std::mutex mMutex;
+
+    // The mCurrentListener and mCurrentConfirmationUI fields are set
+    // if and only if a prompt is currently showing.
+    android::sp<android::IBinder> mCurrentListener;
+    android::sp<android::hardware::confirmationui::V1_0::IConfirmationUI> mCurrentConfirmationUI;
+    android::IBinder::DeathRecipient* mDeathRecipient;
+    hidl_vec<uint8_t> mLatestConfirmationToken;
+    RateLimiting<> mRateLimiting;
+};
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_CONFIRMATION_MANAGER_H_
diff --git a/keystore/confirmationui_rate_limiting.h b/keystore/confirmationui_rate_limiting.h
new file mode 100644
index 0000000..12c20fa
--- /dev/null
+++ b/keystore/confirmationui_rate_limiting.h
@@ -0,0 +1,124 @@
+/*
+**
+** Copyright 2018, 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_CONFIRMATIONUI_RATE_LIMITING_H_
+#define KEYSTORE_CONFIRMATIONUI_RATE_LIMITING_H_
+
+#include <android/hardware/confirmationui/1.0/types.h>
+#include <chrono>
+#include <stdint.h>
+#include <sys/types.h>
+#include <tuple>
+#include <unordered_map>
+
+namespace keystore {
+
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+
+using std::chrono::time_point;
+using std::chrono::duration;
+
+template <typename Clock = std::chrono::steady_clock> class RateLimiting {
+  private:
+    struct Slot {
+        Slot() : previous_start{}, prompt_start{}, counter(0) {}
+        typename Clock::time_point previous_start;
+        typename Clock::time_point prompt_start;
+        uint32_t counter;
+    };
+
+    std::unordered_map<uid_t, Slot> slots_;
+
+    uint_t latest_requester_;
+
+    static std::chrono::seconds getBackoff(uint32_t counter) {
+        using namespace std::chrono_literals;
+        switch (counter) {
+        case 0:
+        case 1:
+        case 2:
+            return 0s;
+        case 3:
+        case 4:
+        case 5:
+            return 30s;
+        default:
+            return 60s * (1ULL << (counter - 6));
+        }
+    }
+
+  public:
+    // Exposes the number of used slots. This is only used by the test to verify the assumption
+    // about used counter slots.
+    size_t usedSlots() const { return slots_.size(); }
+    void doGC() {
+        using namespace std::chrono_literals;
+        using std::chrono::system_clock;
+        using std::chrono::time_point_cast;
+        auto then = Clock::now() - 24h;
+        auto iter = slots_.begin();
+        while (iter != slots_.end()) {
+            if (iter->second.prompt_start <= then) {
+                iter = slots_.erase(iter);
+            } else {
+                ++iter;
+            }
+        }
+    }
+
+    bool tryPrompt(uid_t id) {
+        using namespace std::chrono_literals;
+        // remove slots that have not been touched in 24 hours
+        doGC();
+        auto& slot = slots_[id];
+        auto now = Clock::now();
+        if (!slot.counter || slot.prompt_start <= now - getBackoff(slot.counter)) {
+            latest_requester_ = id;
+            slot.counter += 1;
+            slot.previous_start = slot.prompt_start;
+            slot.prompt_start = now;
+            return true;
+        }
+        return false;
+    }
+
+    void processResult(ConfirmationResponseCode rc) {
+        switch (rc) {
+        case ConfirmationResponseCode::OK:
+            // reset the counter slot
+            slots_.erase(latest_requester_);
+            return;
+        case ConfirmationResponseCode::Canceled:
+            // nothing to do here
+            return;
+        default:;
+        }
+
+        // roll back latest request
+        auto& slot = slots_[latest_requester_];
+        if (slot.counter <= 1) {
+            slots_.erase(latest_requester_);
+            return;
+        }
+        slot.counter -= 1;
+        slot.prompt_start = slot.previous_start;
+    }
+};
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_CONFIRMATIONUI_RATE_LIMITING_H_
diff --git a/keystore/include/keystore/ExportResult.h b/keystore/include/keystore/ExportResult.h
new file mode 100644
index 0000000..b548942
--- /dev/null
+++ b/keystore/include/keystore/ExportResult.h
@@ -0,0 +1,40 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_EXPORTRESULT_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_EXPORTRESULT_H_
+
+#include <binder/Parcelable.h>
+
+#include "keystore_return_types.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+struct ExportResult : public ::android::Parcelable {
+    ExportResult();
+    ~ExportResult();
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+    ::keystore::KeyStoreServiceReturnCode resultCode;
+    hardware::hidl_vec<uint8_t> exportData;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_EXPORTRESULT_H_
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
deleted file mode 100644
index a045679..0000000
--- a/keystore/include/keystore/IKeystoreService.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_IKEYSTORESERVICE_H
-#define KEYSTORE_IKEYSTORESERVICE_H
-
-#include "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);
-    ~KeystoreArg();
-
-    const void* data() const;
-    size_t size() const;
-
-  private:
-    const void* mData;
-    size_t mSize;
-};
-
-struct MallocDeleter {
-    void operator()(uint8_t* p) { free(p); }
-};
-
-// struct for serializing the results of begin/update/finish
-struct OperationResult : public ::android::Parcelable {
-    OperationResult();
-    ~OperationResult();
-    status_t readFromParcel(const Parcel* in) override;
-    status_t writeToParcel(Parcel* out) const override;
-
-    ::keystore::KeyStoreServiceReturnCode resultCode;
-    sp<IBinder> token;
-    uint64_t handle;
-    int inputConsumed;
-    ::keystore::hidl_vec<uint8_t> data;
-    ::keystore::hidl_vec<::keystore::KeyParameter> outParams;
-};
-
-// struct for serializing the results of export
-struct ExportResult : public ::android::Parcelable {
-    ExportResult();
-    ~ExportResult();
-    status_t readFromParcel(const Parcel* in) override;
-    status_t writeToParcel(Parcel* out) const override;
-
-    ::keystore::KeyStoreServiceReturnCode resultCode;
-    ::keystore::hidl_vec<uint8_t> exportData;
-};
-
-/*
- * This must be kept manually in sync with frameworks/base's IKeystoreService.java
- */
-class IKeystoreService : public IInterface {
-  public:
-    enum {
-        GET_STATE = IBinder::FIRST_CALL_TRANSACTION + 0,
-        GET = IBinder::FIRST_CALL_TRANSACTION + 1,
-        INSERT = IBinder::FIRST_CALL_TRANSACTION + 2,
-        DEL = IBinder::FIRST_CALL_TRANSACTION + 3,
-        EXIST = IBinder::FIRST_CALL_TRANSACTION + 4,
-        LIST = IBinder::FIRST_CALL_TRANSACTION + 5,
-        RESET = IBinder::FIRST_CALL_TRANSACTION + 6,
-        ON_USER_PASSWORD_CHANGED = IBinder::FIRST_CALL_TRANSACTION + 7,
-        LOCK = IBinder::FIRST_CALL_TRANSACTION + 8,
-        UNLOCK = IBinder::FIRST_CALL_TRANSACTION + 9,
-        IS_EMPTY = IBinder::FIRST_CALL_TRANSACTION + 10,
-        GENERATE = IBinder::FIRST_CALL_TRANSACTION + 11,
-        IMPORT = IBinder::FIRST_CALL_TRANSACTION + 12,
-        SIGN = IBinder::FIRST_CALL_TRANSACTION + 13,
-        VERIFY = IBinder::FIRST_CALL_TRANSACTION + 14,
-        GET_PUBKEY = IBinder::FIRST_CALL_TRANSACTION + 15,
-        GRANT = IBinder::FIRST_CALL_TRANSACTION + 16,
-        UNGRANT = IBinder::FIRST_CALL_TRANSACTION + 17,
-        GETMTIME = IBinder::FIRST_CALL_TRANSACTION + 18,
-        DUPLICATE = IBinder::FIRST_CALL_TRANSACTION + 19,
-        IS_HARDWARE_BACKED = IBinder::FIRST_CALL_TRANSACTION + 20,
-        CLEAR_UID = IBinder::FIRST_CALL_TRANSACTION + 21,
-        ADD_RNG_ENTROPY = IBinder::FIRST_CALL_TRANSACTION + 22,
-        GENERATE_KEY = IBinder::FIRST_CALL_TRANSACTION + 23,
-        GET_KEY_CHARACTERISTICS = IBinder::FIRST_CALL_TRANSACTION + 24,
-        IMPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 25,
-        EXPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 26,
-        BEGIN = IBinder::FIRST_CALL_TRANSACTION + 27,
-        UPDATE = IBinder::FIRST_CALL_TRANSACTION + 28,
-        FINISH = IBinder::FIRST_CALL_TRANSACTION + 29,
-        ABORT = IBinder::FIRST_CALL_TRANSACTION + 30,
-        IS_OPERATION_AUTHORIZED = IBinder::FIRST_CALL_TRANSACTION + 31,
-        ADD_AUTH_TOKEN = IBinder::FIRST_CALL_TRANSACTION + 32,
-        ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33,
-        ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34,
-        ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35,
-        ATTEST_DEVICE_IDS = IBinder::FIRST_CALL_TRANSACTION + 36,
-        ON_DEVICE_OFF_BODY = IBinder::FIRST_CALL_TRANSACTION + 37,
-    };
-
-    DECLARE_META_INTERFACE(KeystoreService);
-
-    virtual ::keystore::KeyStoreServiceReturnCode getState(int32_t userId) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
-                                                      ::keystore::hidl_vec<uint8_t>* item) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode insert(const String16& name,
-                                                         const ::keystore::hidl_vec<uint8_t>& item,
-                                                         int uid, int32_t flags) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode del(const String16& name, int uid) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode exist(const String16& name, int uid) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode list(const String16& prefix, int uid,
-                                                       Vector<String16>* matches) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode reset() = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode
-    onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode lock(int32_t userId) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode unlock(int32_t userId,
-                                                         const String16& password) = 0;
-
-    virtual bool isEmpty(int32_t userId) = 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 ::keystore::KeyStoreServiceReturnCode import(const String16& name,
-                                                         const ::keystore::hidl_vec<uint8_t>& data,
-                                                         int uid, int32_t flags) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode sign(const String16& name,
-                                                       const ::keystore::hidl_vec<uint8_t>& data,
-                                                       ::keystore::hidl_vec<uint8_t>* out) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode
-    verify(const String16& name, const ::keystore::hidl_vec<uint8_t>& data,
-           const ::keystore::hidl_vec<uint8_t>& signature) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode
-    get_pubkey(const String16& name, ::keystore::hidl_vec<uint8_t>* pubKey) = 0;
-
-    virtual String16 grant(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 ::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 ::keystore::KeyStoreServiceReturnCode clear_uid(int64_t uid) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode
-    addRngEntropy(const ::keystore::hidl_vec<uint8_t>& entropy) = 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 ::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 ::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, ::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,
-                       ::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 ::keystore::hidl_vec<::keystore::KeyParameter>& params,
-                        const ::keystore::hidl_vec<uint8_t>& data, OperationResult* opResult) = 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 ::keystore::KeyStoreServiceReturnCode abort(const sp<IBinder>& handle) = 0;
-
-    virtual bool isOperationAuthorized(const sp<IBinder>& handle) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode addAuthToken(const uint8_t* token,
-                                                               size_t length) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) = 0;
-
-    virtual ::keystore::KeyStoreServiceReturnCode onUserRemoved(int32_t userId) = 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 ::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:
-    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-                                uint32_t flags = 0);
-};
-
-}  // namespace android
-
-#endif
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
index a7ce210..c612929 100644
--- a/keystore/include/keystore/KeyAttestationApplicationId.h
+++ b/keystore/include/keystore/KeyAttestationApplicationId.h
@@ -15,12 +15,13 @@
 #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>
 
+#include <binder/Parcelable.h>
+
+#include "KeyAttestationPackageInfo.h"
+
 namespace android {
 namespace security {
 namespace keymaster {
@@ -29,6 +30,8 @@
   public:
     typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
         ConstKeyAttestationPackageInfoIterator;
+    KeyAttestationApplicationId();
+    KeyAttestationApplicationId(std::unique_ptr<KeyAttestationPackageInfo> package);
 
     status_t writeToParcel(Parcel*) const override;
     status_t readFromParcel(const Parcel* parcel) override;
@@ -46,6 +49,6 @@
 
 }  // namespace keymaster
 }  // namespace security
-}  // namsepace android
+}  // namespace android
 
 #endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
index b938e83..92d4863 100644
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -15,12 +15,15 @@
 #ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
 #define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
 
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include <binder/Parcelable.h>
+
 #include "Signature.h"
 #include "utils.h"
-#include <binder/Parcelable.h>
-#include <memory>
-#include <stdint.h>
-#include <vector>
 
 namespace android {
 namespace security {
@@ -30,20 +33,27 @@
   public:
     typedef SharedNullableIterator<const content::pm::Signature, std::vector>
         ConstSignatureIterator;
+    typedef std::vector<std::unique_ptr<content::pm::Signature>>
+        SignaturesVector;
+    typedef std::shared_ptr<SignaturesVector> SharedSignaturesVector;
+
+    KeyAttestationPackageInfo(const String16& packageName, int64_t versionCode,
+                              SharedSignaturesVector signatures);
+    KeyAttestationPackageInfo();
 
     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_; }
+    int64_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_;
+    int64_t versionCode_;
+    SharedSignaturesVector signatures_;
 };
 
 }  // namespace keymaster
diff --git a/keystore/include/keystore/KeyCharacteristics.h b/keystore/include/keystore/KeyCharacteristics.h
new file mode 100644
index 0000000..7fc89c6
--- /dev/null
+++ b/keystore/include/keystore/KeyCharacteristics.h
@@ -0,0 +1,45 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYCHARACTERISTICS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYCHARACTERISTICS_H_
+
+#include <binder/Parcelable.h>
+
+#include "KeymasterArguments.h"
+#include "keymaster_types.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// Parcelable version of keystore::KeyCharacteristics
+struct KeyCharacteristics : public ::android::Parcelable {
+    KeyCharacteristics(){};
+    explicit KeyCharacteristics(const keystore::KeyCharacteristics& other) {
+        softwareEnforced = KeymasterArguments(other.softwareEnforced);
+        hardwareEnforced = KeymasterArguments(other.hardwareEnforced);
+    }
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+    KeymasterArguments softwareEnforced;
+    KeymasterArguments hardwareEnforced;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYCHARACTERISTICS_H_
diff --git a/keystore/include/keystore/KeymasterArguments.h b/keystore/include/keystore/KeymasterArguments.h
new file mode 100644
index 0000000..99074f8
--- /dev/null
+++ b/keystore/include/keystore/KeymasterArguments.h
@@ -0,0 +1,44 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERARGUMENTS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERARGUMENTS_H_
+
+#include <binder/Parcelable.h>
+
+#include <keystore/keymaster_types.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// struct for serializing/deserializing a list of KeyParameters
+struct KeymasterArguments : public Parcelable {
+    KeymasterArguments(){};
+    explicit KeymasterArguments(const hardware::hidl_vec<keystore::KeyParameter>& other);
+
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+    const inline hardware::hidl_vec<keystore::KeyParameter>& getParameters() const { return data_; }
+
+  private:
+    hardware::hidl_vec<keystore::KeyParameter> data_;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERARGUMENTS_H_
diff --git a/keystore/include/keystore/KeymasterBlob.h b/keystore/include/keystore/KeymasterBlob.h
new file mode 100644
index 0000000..fc849bd
--- /dev/null
+++ b/keystore/include/keystore/KeymasterBlob.h
@@ -0,0 +1,40 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERBLOB_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERBLOB_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// Parcelable which wraps hardware::hidl_vec<uint8_t>
+struct KeymasterBlob : public ::android::Parcelable {
+    KeymasterBlob(){};
+    explicit KeymasterBlob(hardware::hidl_vec<uint8_t> data) : data_(data) {}
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+    const hardware::hidl_vec<uint8_t>& getData() const { return data_; }
+
+  private:
+    hardware::hidl_vec<uint8_t> data_;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERBLOB_H_
diff --git a/keystore/include/keystore/KeymasterCertificateChain.h b/keystore/include/keystore/KeymasterCertificateChain.h
new file mode 100644
index 0000000..132862c
--- /dev/null
+++ b/keystore/include/keystore/KeymasterCertificateChain.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// struct for serializing keymaster_cert_chain_t's
+struct KeymasterCertificateChain : public ::android::Parcelable {
+    KeymasterCertificateChain(){};
+    explicit KeymasterCertificateChain(hardware::hidl_vec<hardware::hidl_vec<uint8_t>> other)
+        : chain(std::move(other)) {}
+
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+  private:
+    // The structure is only used as output and doesn't have getter.
+    hardware::hidl_vec<hardware::hidl_vec<uint8_t>> chain;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_
diff --git a/keystore/include/keystore/KeystoreArg.h b/keystore/include/keystore/KeystoreArg.h
new file mode 100644
index 0000000..a5e68f2
--- /dev/null
+++ b/keystore/include/keystore/KeystoreArg.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+namespace security {
+
+// Simple pair of generic pointer and length of corresponding data structure.
+class KeystoreArg : public RefBase {
+  public:
+    KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {}
+    ~KeystoreArg() {}
+
+    const void* data() const { return mData; }
+    size_t size() const { return mSize; }
+
+  private:
+    const void* mData;  // provider of the data must handle memory clean-up.
+    size_t mSize;
+};
+
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H
diff --git a/keystore/include/keystore/KeystoreArguments.h b/keystore/include/keystore/KeystoreArguments.h
new file mode 100644
index 0000000..c0a8b0a
--- /dev/null
+++ b/keystore/include/keystore/KeystoreArguments.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_
+
+#include <binder/Parcelable.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+#include "KeystoreArg.h"
+#include "keystore_return_types.h"
+
+namespace android {
+namespace security {
+
+// Parcelable KeystoreArguments.java which simply holds byte[][].
+struct KeystoreArguments : public ::android::Parcelable, public RefBase {
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+    const Vector<sp<KeystoreArg>>& getArguments() const { return args; }
+
+  private:
+    Vector<sp<KeystoreArg>> args;
+};
+
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_
diff --git a/keystore/include/keystore/OperationResult.h b/keystore/include/keystore/OperationResult.h
new file mode 100644
index 0000000..2ceda9a
--- /dev/null
+++ b/keystore/include/keystore/OperationResult.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_OPERATIONRESULT_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_OPERATIONRESULT_H_
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+#include "keymaster_types.h"
+#include "keystore_return_types.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+struct OperationResult : public ::android::Parcelable {
+    OperationResult();
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+    // Native code may need to use KeyStoreNativeReturnCode
+    ::keystore::KeyStoreServiceReturnCode resultCode;
+    sp<IBinder> token;
+    uint64_t handle;
+    int inputConsumed;
+    ::keystore::hidl_vec<uint8_t> data;
+    ::keystore::hidl_vec<::keystore::KeyParameter> outParams;
+};
+
+}  // namespace keymaster
+}  // namespace security
+}  // namespace android
+
+#endif  // KEYSTORE_INCLUDE_KEYSTORE_OPERATIONRESULT_H_
diff --git a/keystore/include/keystore/Signature.h b/keystore/include/keystore/Signature.h
index 59b77bf..3c996bb 100644
--- a/keystore/include/keystore/Signature.h
+++ b/keystore/include/keystore/Signature.h
@@ -15,10 +15,10 @@
 #ifndef KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
 #define KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
 
-#include <binder/Parcelable.h>
-#include <stdint.h>
 #include <vector>
 
+#include <binder/Parcelable.h>
+
 namespace android {
 namespace content {
 namespace pm {
diff --git a/keystore/include/keystore/authorization_set.h b/keystore/include/keystore/authorization_set.h
deleted file mode 100644
index 0e57a19..0000000
--- a/keystore/include/keystore/authorization_set.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 05a33cd..0000000
--- a/keystore/include/keystore/keymaster_tags.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * 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/keymaster_types.h b/keystore/include/keystore/keymaster_types.h
new file mode 100644
index 0000000..f3c6907
--- /dev/null
+++ b/keystore/include/keystore/keymaster_types.h
@@ -0,0 +1,104 @@
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_
+#define SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_
+
+#include <android/hardware/keymaster/3.0/types.h>
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+
+#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/keymaster_tags.h>
+
+/**
+ * This header lifts the types from the current Keymaster version into the keystore namespace.
+ */
+
+namespace keystore {
+
+// Changing this namespace alias will change the keymaster version.
+namespace keymaster = ::android::hardware::keymaster::V4_0;
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+
+using keymaster::IKeymasterDevice;
+using keymaster::SecurityLevel;
+
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+
+using keymaster::Algorithm;
+using keymaster::BlockMode;
+using keymaster::Digest;
+using keymaster::EcCurve;
+using keymaster::ErrorCode;
+using keymaster::HardwareAuthenticatorType;
+using keymaster::HardwareAuthToken;
+using keymaster::HmacSharingParameters;
+using keymaster::KeyCharacteristics;
+using keymaster::KeyFormat;
+using keymaster::KeyParameter;
+using keymaster::KeyPurpose;
+using keymaster::OperationHandle;
+using keymaster::PaddingMode;
+using keymaster::SecurityLevel;
+using keymaster::Tag;
+using keymaster::TagType;
+using keymaster::VerificationToken;
+
+using keymaster::TAG_ACTIVE_DATETIME;
+using keymaster::TAG_ALGORITHM;
+using keymaster::TAG_ALLOW_WHILE_ON_BODY;
+using keymaster::TAG_APPLICATION_DATA;
+using keymaster::TAG_APPLICATION_ID;
+using keymaster::TAG_ATTESTATION_APPLICATION_ID;
+using keymaster::TAG_AUTH_TIMEOUT;
+using keymaster::TAG_BLOB_USAGE_REQUIREMENTS;
+using keymaster::TAG_BLOCK_MODE;
+using keymaster::TAG_DIGEST;
+using keymaster::TAG_EC_CURVE;
+using keymaster::TAG_KEY_SIZE;
+using keymaster::TAG_MAC_LENGTH;
+using keymaster::TAG_MAX_USES_PER_BOOT;
+using keymaster::TAG_MIN_MAC_LENGTH;
+using keymaster::TAG_MIN_SECONDS_BETWEEN_OPS;
+using keymaster::TAG_NO_AUTH_REQUIRED;
+using keymaster::TAG_NONCE;
+using keymaster::TAG_ORIGIN;
+using keymaster::TAG_ORIGINATION_EXPIRE_DATETIME;
+using keymaster::TAG_PADDING;
+using keymaster::TAG_PURPOSE;
+using keymaster::TAG_RESET_SINCE_ID_ROTATION;
+using keymaster::TAG_RSA_PUBLIC_EXPONENT;
+using keymaster::TAG_USAGE_EXPIRE_DATETIME;
+using keymaster::TAG_USER_AUTH_TYPE;
+using keymaster::TAG_USER_ID;
+using keymaster::TAG_USER_SECURE_ID;
+
+using keymaster::NullOr;
+
+using Km3HardwareAuthToken = ::android::hardware::keymaster::V3_0::HardwareAuthToken;
+using Km3HardwareAuthenticatorType =
+    ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
+
+// 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.
+constexpr int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
+constexpr int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+
+}  // namespace keystore
+
+#endif  // SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index 7260363..07f645f 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -26,6 +26,7 @@
     STATE_UNINITIALIZED = 3,
 };
 
+// must be in sync with KeyStore.java,
 enum class ResponseCode: int32_t {
     NO_ERROR          =  STATE_NO_ERROR, // 1
     LOCKED            =  STATE_LOCKED, // 2
@@ -62,25 +63,7 @@
     // 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,
+    KEYSTORE_FLAG_STRONGBOX = 1 << 4,
 };
 
-/**
- * Returns the size of the softkey magic header value for measuring
- * and allocating purposes.
- */
-size_t get_softkey_header_size();
-
-/**
- * Adds the magic softkey header to a key blob.
- *
- * Returns NULL if the destination array is too small. Otherwise it
- * returns the offset directly after the magic value.
- */
-uint8_t* add_softkey_header(uint8_t* key_blob, size_t key_blob_length);
-
-/**
- * Returns true if the key blob has a magic softkey header at the beginning.
- */
-bool is_softkey(const uint8_t* key_blob, const size_t key_blob_length);
-
 #endif
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
index 2ba7fd4..d6a4807 100644
--- a/keystore/include/keystore/keystore_client.h
+++ b/keystore/include/keystore/keystore_client.h
@@ -21,14 +21,12 @@
 
 #include <android-base/macros.h>
 
-#include "authorization_set.h"
+#include "keymaster_types.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)
@@ -64,7 +62,7 @@
     // Note: implementations may generate more than one key but they will always
     // have |key_name| as a prefix.
     virtual bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
-                                           std::string* encrypted_data) = 0;
+                                           int32_t flags, std::string* encrypted_data) = 0;
 
     // Decrypts and authenticates |encrypted_data| as output by
     // EncryptWithAuthentication using the key(s) identified by |key_name|. On
@@ -87,17 +85,18 @@
 
     // Adds |entropy| to the random number generator. Returns KM_ERROR_OK on
     // success and a Keystore ResponseCode or keymaster_error_t on failure.
-    virtual KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy) = 0;
+    virtual KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy,
+                                                                     int32_t flags) = 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 KeyStoreNativeReturnCode generateKey(const std::string& key_name,
-                                const keystore::AuthorizationSet& key_parameters,
-                                keystore::AuthorizationSet* hardware_enforced_characteristics,
-                                keystore::AuthorizationSet* software_enforced_characteristics) = 0;
+    virtual KeyStoreNativeReturnCode
+    generateKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters,
+                int32_t flags, 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
@@ -112,17 +111,17 @@
     // [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 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;
+    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 KeyStoreNativeReturnCode exportKey(KeyFormat export_format, const std::string& key_name,
-                              std::string* export_data) = 0;
+                                               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.
@@ -137,32 +136,30 @@
     // |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 KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
-                                   const keystore::AuthorizationSet& input_parameters,
-                                   keystore::AuthorizationSet* output_parameters,
-                                   uint64_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 KeyStoreNativeReturnCode updateOperation(uint64_t handle,
-                                    const keystore::AuthorizationSet& input_parameters,
-                                    const std::string& input_data, size_t* num_input_bytes_consumed,
-                                    keystore::AuthorizationSet* output_parameters,
-                                    std::string* output_data) = 0;
+    virtual KeyStoreNativeReturnCode
+    updateOperation(uint64_t handle, const keystore::AuthorizationSet& input_parameters,
+                    const std::string& input_data, size_t* num_input_bytes_consumed,
+                    keystore::AuthorizationSet* output_parameters, std::string* output_data) = 0;
 
     // Finishes the operation associated with |handle| using the given
     // |input_parameters| and, if necessary, a |signature_to_verify|. On success,
     // any |output_parameters| are populated and |output_data| is appended.
     // Returns KM_ERROR_OK on success and a Keystore ResponseCode or
     // keymaster_error_t on failure.
-    virtual KeyStoreNativeReturnCode finishOperation(uint64_t handle,
-                                    const keystore::AuthorizationSet& input_parameters,
-                                    const std::string& signature_to_verify,
-                                    keystore::AuthorizationSet* output_parameters,
-                                    std::string* output_data) = 0;
+    virtual KeyStoreNativeReturnCode
+    finishOperation(uint64_t handle, const keystore::AuthorizationSet& input_parameters,
+                    const std::string& signature_to_verify,
+                    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.
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
index eb02275..9edd082 100644
--- a/keystore/include/keystore/keystore_client_impl.h
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -17,13 +17,13 @@
 
 #include "keystore_client.h"
 
-#include <string>
 #include <map>
+#include <string>
 #include <vector>
 
+#include <android/security/IKeystoreService.h>
 #include <binder/IBinder.h>
 #include <binder/IServiceManager.h>
-#include "IKeystoreService.h"
 #include <utils/StrongPointer.h>
 
 namespace keystore {
@@ -35,7 +35,7 @@
 
     // KeystoreClient methods.
     bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
-                                   std::string* encrypted_data) override;
+                                   int32_t flags, std::string* encrypted_data) override;
     bool decryptWithAuthentication(const std::string& key_name, const std::string& encrypted_data,
                                    std::string* data) override;
     bool oneShotOperation(KeyPurpose purpose, const std::string& key_name,
@@ -43,38 +43,40 @@
                           const std::string& input_data, const std::string& signature_to_verify,
                           keystore::AuthorizationSet* output_parameters,
                           std::string* output_data) override;
-    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 addRandomNumberGeneratorEntropy(const std::string& entropy,
+                                                             int32_t flags) override;
+    KeyStoreNativeReturnCode
+    generateKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters,
+                int32_t flags, keystore::AuthorizationSet* hardware_enforced_characteristics,
+                keystore::AuthorizationSet* software_enforced_characteristics) override;
     KeyStoreNativeReturnCode
     getKeyCharacteristics(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
+    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;
+                                       std::string* export_data) override;
     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;
+                                            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,
-                            keystore::AuthorizationSet* output_parameters,
-                            std::string* output_data) override;
+                                             const keystore::AuthorizationSet& input_parameters,
+                                             const std::string& input_data,
+                                             size_t* num_input_bytes_consumed,
+                                             keystore::AuthorizationSet* output_parameters,
+                                             std::string* output_data) override;
     KeyStoreNativeReturnCode finishOperation(uint64_t handle,
-                            const keystore::AuthorizationSet& input_parameters,
-                            const std::string& signature_to_verify,
-                            keystore::AuthorizationSet* output_parameters,
-                            std::string* output_data) override;
+                                             const keystore::AuthorizationSet& input_parameters,
+                                             const std::string& signature_to_verify,
+                                             keystore::AuthorizationSet* output_parameters,
+                                             std::string* output_data) 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;
@@ -85,15 +87,15 @@
 
     // 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.
-    bool createOrVerifyEncryptionKey(const std::string& key_name);
+    bool createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags);
 
     // Creates an authentication key suitable for EncryptWithAuthentication or
     // verifies attributes if the key already exists. Returns true on success.
-    bool createOrVerifyAuthenticationKey(const std::string& key_name);
+    bool createOrVerifyAuthenticationKey(const std::string& key_name, int32_t flags);
 
     // Verifies attributes of an encryption key suitable for
     // EncryptWithAuthentication. Returns true on success and populates |verified|
@@ -107,7 +109,7 @@
 
     android::sp<android::IServiceManager> service_manager_;
     android::sp<android::IBinder> keystore_binder_;
-    android::sp<android::IKeystoreService> keystore_;
+    android::sp<android::security::IKeystoreService> keystore_;
     uint64_t next_virtual_handle_ = 1;
     std::map<uint64_t, android::sp<android::IBinder>> active_operations_;
 
diff --git a/keystore/include/keystore/keystore_client_mock.h b/keystore/include/keystore/keystore_client_mock.h
index 2d1f499..b16367f 100644
--- a/keystore/include/keystore/keystore_client_mock.h
+++ b/keystore/include/keystore/keystore_client_mock.h
@@ -15,8 +15,8 @@
 #ifndef KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
 #define KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
 
-#include "gmock/gmock.h"
 #include "keystore/keystore_client.h"
+#include "gmock/gmock.h"
 
 using testing::_;
 
diff --git a/keystore/include/keystore/keystore_get.h b/keystore/include/keystore/keystore_get.h
index 4bddd70..4c3d838 100644
--- a/keystore/include/keystore/keystore_get.h
+++ b/keystore/include/keystore/keystore_get.h
@@ -30,7 +30,7 @@
  * length. The third argument is a pointer to an array that will be malloc()
  * and the caller is responsible for calling free() on the buffer.
  */
-ssize_t keystore_get(const char *key, size_t length, uint8_t** value);
+ssize_t keystore_get(const char* key, size_t length, uint8_t** value);
 
 #ifdef __cplusplus
 }
diff --git a/keystore/include/keystore/keystore_hidl_support.h b/keystore/include/keystore/keystore_hidl_support.h
index 3c64d2a..781b153 100644
--- a/keystore/include/keystore/keystore_hidl_support.h
+++ b/keystore/include/keystore/keystore_hidl_support.h
@@ -18,15 +18,24 @@
 #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>
 
+#include <android-base/logging.h>
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hardware/hw_auth_token.h>
+#include <hidl/Status.h>
+#include <keymasterV4_0/keymaster_utils.h>
+
+#include <keystore/keymaster_types.h>
+
 namespace keystore {
 
+using android::hardware::keymaster::V4_0::support::blob2hidlVec;
+using android::hardware::keymaster::V4_0::support::hidlVec2AuthToken;
+using android::hardware::keymaster::V4_0::support::authToken2HidlVec;
+
 inline static std::ostream& formatArgs(std::ostream& out) {
     return out;
 }
@@ -65,46 +74,22 @@
 #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.");
+constexpr size_t kHmacSize = 32;
+
+inline static hidl_vec<uint8_t> authToken2HidlVec(const Km3HardwareAuthToken& token) {
+    static_assert(std::is_same<decltype(token.hmac),
+                               ::android::hardware::hidl_array<uint8_t, kHmacSize>>::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),
+                          sizeof(token.timestamp) + kHmacSize ==
+                      sizeof(hw_auth_token_t),
                   "HardwareAuthToken content size does not match hw_auth_token_t size");
 
     hidl_vec<uint8_t> result;
@@ -121,6 +106,38 @@
     return result;
 }
 
+template <typename T, typename InIter>
+inline static InIter copy_bytes_from_iterator(T* value, InIter src) {
+    uint8_t* value_ptr = reinterpret_cast<uint8_t*>(value);
+    std::copy(src, src + sizeof(T), value_ptr);
+    return src + sizeof(T);
+}
+
+inline static Km3HardwareAuthToken hidlVec2Km3AuthToken(const hidl_vec<uint8_t>& buffer) {
+    Km3HardwareAuthToken token;
+    static_assert(std::is_same<decltype(token.hmac),
+                               ::android::hardware::hidl_array<uint8_t, kHmacSize>>::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) + kHmacSize ==
+                      sizeof(hw_auth_token_t),
+                  "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+    if (buffer.size() != sizeof(hw_auth_token_t)) return {};
+
+    auto pos = buffer.begin();
+    ++pos;  // skip first byte
+    pos = copy_bytes_from_iterator(&token.challenge, pos);
+    pos = copy_bytes_from_iterator(&token.userId, pos);
+    pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
+    pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
+    pos = copy_bytes_from_iterator(&token.timestamp, pos);
+    pos = std::copy(pos, pos + token.hmac.size(), &token.hmac[0]);
+
+    return token;
+}
+
 inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) {
     return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
 }
diff --git a/keystore/include/keystore/keystore_return_types.h b/keystore/include/keystore/keystore_return_types.h
index 70380c3..fa4a224 100644
--- a/keystore/include/keystore/keystore_return_types.h
+++ b/keystore/include/keystore/keystore_return_types.h
@@ -18,12 +18,12 @@
 #ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
 #define KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
 
+#include "keymaster_types.h"
 #include "keystore.h"
-#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
 
 namespace keystore {
 
-using ::android::hardware::keymaster::V3_0::ErrorCode;
+using keymaster::ErrorCode;
 
 class KeyStoreServiceReturnCode;
 class KeyStoreNativeReturnCode;
@@ -46,6 +46,7 @@
     KeyStoreServiceReturnCode(const KeyStoreServiceReturnCode& errorCode)
         : errorCode_(errorCode.errorCode_) {}
     KeyStoreServiceReturnCode(const KeyStoreNativeReturnCode& errorCode);
+    explicit inline KeyStoreServiceReturnCode(const int32_t& errorCode) : errorCode_(errorCode) {}
     inline KeyStoreServiceReturnCode& operator=(const ErrorCode& errorCode) {
         errorCode_ = int32_t(errorCode);
         return *this;
@@ -62,8 +63,9 @@
         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);
+        if (!errorCode_) return static_cast<int32_t>(ResponseCode::NO_ERROR /* 1 */);
         return errorCode_;
     }
     inline bool operator==(const ResponseCode& rhs) const {
@@ -117,6 +119,7 @@
     KeyStoreNativeReturnCode(const ResponseCode& errorCode) : errorCode_(int32_t(errorCode)) {}
     KeyStoreNativeReturnCode(const KeyStoreNativeReturnCode& errorCode)
         : errorCode_(errorCode.errorCode_) {}
+    explicit inline KeyStoreNativeReturnCode(const int32_t& errorCode) : errorCode_(errorCode) {}
     KeyStoreNativeReturnCode(const KeyStoreServiceReturnCode& errorcode);
     inline KeyStoreNativeReturnCode& operator=(const ErrorCode& errorCode) {
         errorCode_ = int32_t(errorCode);
@@ -135,8 +138,8 @@
                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);
+        if (errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) /* 1 */) {
+            return static_cast<int32_t>(ErrorCode::OK) /* 0 */;
         }
         return errorCode_;
     }
diff --git a/keystore/key_config.proto b/keystore/key_config.proto
new file mode 100644
index 0000000..0b1a398
--- /dev/null
+++ b/keystore/key_config.proto
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+
+package keystore;
+
+option optimize_for = LITE_RUNTIME;
+
+message KeyConfig {
+  // What type of encryption algorithm is this key being generated/imported for
+  // e.g. AES, RSA, etc
+  optional string algorithm = 1;
+
+  // Size of the key being generated/imported
+  optional int32 key_size = 2;
+
+  // Log whether the key was generated, imported, securely imported, or derived.
+  optional string origin = 3;
+
+  // What auth types does this key require? If none, then no auth required.
+  optional string user_auth_type = 4;
+
+  // If user authentication is required, is the requirement time based? If it
+  // is not time based then this field will not be used and the key is per
+  // operation. Per operation keys must be user authenticated on each usage.
+  optional int32 user_auth_key_timeout = 5;
+
+  // Track which padding modes this key supports.
+  repeated string padding = 6;
+
+  // Track which digests this key supports
+  repeated string digest = 7;
+
+  // Check what block mode is being used depending on the mode of encryption
+  repeated string block_mode = 8;
+
+  // Was the key generated/imported successfully?
+  optional bool was_creation_successful = 9;
+
+  // What purposes can this key be used for?
+  repeated string purpose = 10;
+
+  // Which ec curve was selected if elliptic curve cryptography is in use
+  optional string ec_curve = 11;
+
+  // Standalone or is a file system required
+  optional string key_blob_usage_reqs = 12;
+}
diff --git a/keystore/key_proto_handler.cpp b/keystore/key_proto_handler.cpp
new file mode 100644
index 0000000..3bf8c06
--- /dev/null
+++ b/keystore/key_proto_handler.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "KeystoreOperation"
+
+#include "key_proto_handler.h"
+
+#include <android/os/DropBoxManager.h>
+#include <google/protobuf/message_lite.h>
+#include <keymasterV4_0/Keymaster.h>
+#include <keystore/keymaster_types.h>
+#include <utils/String16.h>
+
+#include "key_config.pb.h"
+
+namespace keystore {
+
+void checkEnforcedCharacteristics(const hidl_vec<KeyParameter>& keyParams, KeyConfig* keyConfig) {
+    for (auto& keyParam : keyParams) {
+        switch (keyParam.tag) {
+        case Tag::PURPOSE:
+            keyConfig->add_purpose(toString(accessTagValue(TAG_PURPOSE, keyParam)));
+            break;
+        case Tag::ALGORITHM:
+            keyConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, keyParam)));
+            break;
+        case Tag::KEY_SIZE:
+            keyConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, keyParam));
+            break;
+        case Tag::BLOCK_MODE:
+            keyConfig->add_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, keyParam)));
+            break;
+        case Tag::PADDING:
+            keyConfig->add_padding(toString(accessTagValue(TAG_PADDING, keyParam)));
+            break;
+        case Tag::DIGEST:
+            keyConfig->add_digest(toString(accessTagValue(TAG_DIGEST, keyParam)));
+            break;
+        case Tag::EC_CURVE:
+            keyConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, keyParam)));
+            break;
+        case Tag::AUTH_TIMEOUT:
+            keyConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, keyParam));
+            break;
+        case Tag::ORIGIN:
+            keyConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, keyParam)));
+            break;
+        case Tag::BLOB_USAGE_REQUIREMENTS:
+            keyConfig->set_key_blob_usage_reqs(
+                toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, keyParam)));
+            break;
+        case Tag::USER_AUTH_TYPE:
+            keyConfig->set_user_auth_type(toString(accessTagValue(TAG_USER_AUTH_TYPE, keyParam)));
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
+                                     bool wasCreationSuccessful) {
+    KeyConfig keyConfig;
+    checkEnforcedCharacteristics(keyParams, &keyConfig);
+    auto dropbox = std::make_unique<android::os::DropBoxManager>();
+    keyConfig.set_was_creation_successful(wasCreationSuccessful);
+
+    size_t size = keyConfig.ByteSize();
+    auto data = std::make_unique<uint8_t[]>(size);
+    keyConfig.SerializeWithCachedSizesToArray(data.get());
+    dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
+}
+
+}  // namespace keystore
diff --git a/keystore/key_proto_handler.h b/keystore/key_proto_handler.h
new file mode 100644
index 0000000..a2f6a24
--- /dev/null
+++ b/keystore/key_proto_handler.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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_KEY_PROTO_HANDLER_H_
+#define KEYSTORE_KEY_PROTO_HANDLER_H_
+
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
+                                     bool wasCreationSuccessful);
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_KEY_PROTO_HANDLER_H_
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index eb5fe86..9d035c8 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "keystore"
 
 #include "key_store_service.h"
+#include "include/keystore/KeystoreArg.h"
 
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -24,30 +25,47 @@
 #include <algorithm>
 #include <sstream>
 
+#include <android-base/scopeguard.h>
 #include <binder/IInterface.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IPermissionController.h>
 #include <binder/IServiceManager.h>
+#include <log/log_event_list.h>
 
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 
 #include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
 
 #include "defaults.h"
+#include "key_proto_handler.h"
 #include "keystore_attestation_id.h"
 #include "keystore_keymaster_enforcement.h"
 #include "keystore_utils.h"
 #include <keystore/keystore_hidl_support.h>
 
+#include <hardware/hw_auth_token.h>
+
 namespace keystore {
 
 using namespace android;
 
 namespace {
 
+using ::android::binder::Status;
+using android::security::KeystoreArg;
+using android::security::keymaster::ExportResult;
+using android::security::keymaster::KeymasterArguments;
+using android::security::keymaster::KeymasterBlob;
+using android::security::keymaster::KeymasterCertificateChain;
+using android::security::keymaster::OperationResult;
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+
 constexpr size_t kMaxOperations = 15;
 constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
 const char* kTimestampFilePath = "timestamp";
+const int ID_ATTESTATION_REQUEST_GENERIC_INFO = 1 << 0;
+const int ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID = 1 << 1;
 
 struct BIGNUM_Delete {
     void operator()(BIGNUM* p) const { BN_free(p); }
@@ -124,55 +142,53 @@
 void KeyStoreService::binderDied(const wp<IBinder>& who) {
     auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
     for (const auto& token : operations) {
-        abort(token);
+        int32_t unused_result;
+        abort(token, &unused_result);
     }
+    mConfirmationManager->binderDied(who);
 }
 
-KeyStoreServiceReturnCode KeyStoreService::getState(int32_t userId) {
+Status KeyStoreService::getState(int32_t userId, int32_t* aidl_return) {
     if (!checkBinderPermission(P_GET_STATE)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
-
-    return ResponseCode(mKeyStore->getState(userId));
+    *aidl_return = mKeyStore->getState(userId);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::get(const String16& name, int32_t uid,
-                                               hidl_vec<uint8_t>* item) {
+Status KeyStoreService::get(const String16& name, int32_t uid, ::std::vector<uint8_t>* item) {
     uid_t targetUid = getEffectiveUid(uid);
     if (!checkBinderPermission(P_GET, targetUid)) {
-        return ResponseCode::PERMISSION_DENIED;
+        // see keystore/keystore.h
+        return Status::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
     }
 
     String8 name8(name);
     Blob keyBlob;
-
     KeyStoreServiceReturnCode rc =
         mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
     if (!rc.isOk()) {
-        if (item) *item = hidl_vec<uint8_t>();
-        return rc;
+        *item = ::std::vector<uint8_t>();
+        // Return empty array if key is not found
+        // TODO: consider having returned value nullable or parse exception on the client.
+        return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
     }
-
-    // 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 ResponseCode::NO_ERROR;
+    // The static_cast here is needed to prevent a move, forcing a deep copy.
+    if (item) *item = static_cast<const hidl_vec<uint8_t>&>(blob2hidlVec(keyBlob));
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
-                                                  const hidl_vec<uint8_t>& item, int targetUid,
-                                                  int32_t flags) {
+Status KeyStoreService::insert(const String16& name, const ::std::vector<uint8_t>& item,
+                               int targetUid, int32_t flags, int32_t* aidl_return) {
     targetUid = getEffectiveUid(targetUid);
-    auto result =
+    KeyStoreServiceReturnCode result =
         checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
     if (!result.isOk()) {
-        return result;
+        *aidl_return = static_cast<int32_t>(result);
+        return Status::ok();
     }
 
     String8 name8(name);
@@ -181,72 +197,93 @@
     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));
+    *aidl_return =
+        static_cast<int32_t>(mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid)));
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::del(const String16& name, int targetUid) {
+Status KeyStoreService::del(const String16& name, int targetUid, int32_t* aidl_return) {
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_DELETE, targetUid)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
     String8 name8(name);
     ALOGI("del %s %d", name8.string(), targetUid);
     auto filename = mKeyStore->getBlobFileNameIfExists(name8, targetUid, ::TYPE_ANY);
-    if (!filename.isOk()) return ResponseCode::KEY_NOT_FOUND;
+    if (!filename.isOk()) {
+        *aidl_return = static_cast<int32_t>(ResponseCode::KEY_NOT_FOUND);
+        return Status::ok();
+    }
 
-    ResponseCode result = mKeyStore->del(filename.value().string(), ::TYPE_ANY,
-            get_user_id(targetUid));
+    ResponseCode result =
+        mKeyStore->del(filename.value().string(), ::TYPE_ANY, get_user_id(targetUid));
     if (result != ResponseCode::NO_ERROR) {
-        return result;
+        *aidl_return = static_cast<int32_t>(result);
+        return Status::ok();
     }
 
     filename = mKeyStore->getBlobFileNameIfExists(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS);
     if (filename.isOk()) {
-        return mKeyStore->del(filename.value().string(), ::TYPE_KEY_CHARACTERISTICS,
-                get_user_id(targetUid));
+        *aidl_return = static_cast<int32_t>(mKeyStore->del(
+            filename.value().string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid)));
+        return Status::ok();
     }
-    return ResponseCode::NO_ERROR;
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::exist(const String16& name, int targetUid) {
+Status KeyStoreService::exist(const String16& name, int targetUid, int32_t* aidl_return) {
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_EXIST, targetUid)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     auto filename = mKeyStore->getBlobFileNameIfExists(String8(name), targetUid, ::TYPE_ANY);
-    return filename.isOk() ? ResponseCode::NO_ERROR : ResponseCode::KEY_NOT_FOUND;
+    *aidl_return = static_cast<int32_t>(filename.isOk() ? ResponseCode::NO_ERROR
+                                                        : ResponseCode::KEY_NOT_FOUND);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::list(const String16& prefix, int targetUid,
-                                                Vector<String16>* matches) {
+Status KeyStoreService::list(const String16& prefix, int targetUid,
+                             ::std::vector<::android::String16>* matches) {
     targetUid = getEffectiveUid(targetUid);
     if (!checkBinderPermission(P_LIST, targetUid)) {
-        return ResponseCode::PERMISSION_DENIED;
+        return Status::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
     }
     const String8 prefix8(prefix);
     String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid, TYPE_ANY));
-
-    if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
-        return ResponseCode::SYSTEM_ERROR;
+    android::Vector<android::String16> matches_internal;
+    if (mKeyStore->list(filename, &matches_internal, get_user_id(targetUid)) !=
+        ResponseCode::NO_ERROR) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
     }
-    return ResponseCode::NO_ERROR;
+    matches->clear();
+    for (size_t i = 0; i < matches_internal.size(); ++i) {
+        matches->push_back(matches_internal[i]);
+    }
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::reset() {
+Status KeyStoreService::reset(int32_t* aidl_return) {
     if (!checkBinderPermission(P_RESET)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     mKeyStore->resetUser(get_user_id(callingUid), false);
-    return ResponseCode::NO_ERROR;
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
-                                                                 const String16& password) {
+Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password,
+                                              int32_t* aidl_return) {
     if (!checkBinderPermission(P_PASSWORD)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     const String8 password8(password);
@@ -257,31 +294,37 @@
     if (password.size() == 0) {
         ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
         mKeyStore->resetUser(userId, true);
-        return ResponseCode::NO_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+        return Status::ok();
     } else {
         switch (mKeyStore->getState(userId)) {
         case ::STATE_UNINITIALIZED: {
             // generate master key, encrypt with password, write to file,
             // initialize mMasterKey*.
-            return mKeyStore->initializeUser(password8, userId);
+            *aidl_return = static_cast<int32_t>(mKeyStore->initializeUser(password8, userId));
+            return Status::ok();
         }
         case ::STATE_NO_ERROR: {
             // rewrite master key with new password.
-            return mKeyStore->writeMasterKey(password8, userId);
+            *aidl_return = static_cast<int32_t>(mKeyStore->writeMasterKey(password8, userId));
+            return Status::ok();
         }
         case ::STATE_LOCKED: {
             ALOGE("Changing user %d's password while locked, clearing old encryption", userId);
             mKeyStore->resetUser(userId, true);
-            return mKeyStore->initializeUser(password8, userId);
+            *aidl_return = static_cast<int32_t>(mKeyStore->initializeUser(password8, userId));
+            return Status::ok();
         }
         }
-        return ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
 }
 
-KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
+Status KeyStoreService::onUserAdded(int32_t userId, int32_t parentId, int32_t* aidl_return) {
     if (!checkBinderPermission(P_USER_CHANGED)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     // Sanity check that the new user has an empty keystore.
@@ -295,39 +338,48 @@
         // password of the parent profile is not known here, the best we can do is copy the parent's
         // master key and master key file. This makes this profile use the same master key as the
         // parent profile, forever.
-        return mKeyStore->copyMasterKey(parentId, userId);
+        *aidl_return = static_cast<int32_t>(mKeyStore->copyMasterKey(parentId, userId));
+        return Status::ok();
     } else {
-        return ResponseCode::NO_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+        return Status::ok();
     }
 }
 
-KeyStoreServiceReturnCode KeyStoreService::onUserRemoved(int32_t userId) {
+Status KeyStoreService::onUserRemoved(int32_t userId, int32_t* aidl_return) {
     if (!checkBinderPermission(P_USER_CHANGED)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     mKeyStore->resetUser(userId, false);
-    return ResponseCode::NO_ERROR;
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::lock(int32_t userId) {
+Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) {
     if (!checkBinderPermission(P_LOCK)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     State state = mKeyStore->getState(userId);
     if (state != ::STATE_NO_ERROR) {
         ALOGD("calling lock in state: %d", state);
-        return ResponseCode(state);
+        *aidl_return = static_cast<int32_t>(ResponseCode(state));
+        return Status::ok();
     }
 
+    enforcement_policy.set_device_locked(true, userId);
     mKeyStore->lock(userId);
-    return ResponseCode::NO_ERROR;
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16& pw) {
+Status KeyStoreService::unlock(int32_t userId, const String16& pw, int32_t* aidl_return) {
     if (!checkBinderPermission(P_UNLOCK)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     State state = mKeyStore->getState(userId);
@@ -343,30 +395,38 @@
             ALOGE("unlock called on keystore in unknown state: %d", state);
             break;
         }
-        return ResponseCode(state);
+        *aidl_return = static_cast<int32_t>(ResponseCode(state));
+        return Status::ok();
     }
 
+    enforcement_policy.set_device_locked(false, userId);
     const String8 password8(pw);
     // read master key, decrypt with password, initialize mMasterKey*.
-    return mKeyStore->readMasterKey(password8, userId);
+    *aidl_return = static_cast<int32_t>(mKeyStore->readMasterKey(password8, userId));
+    return Status::ok();
 }
 
-bool KeyStoreService::isEmpty(int32_t userId) {
+Status KeyStoreService::isEmpty(int32_t userId, int32_t* aidl_return) {
     if (!checkBinderPermission(P_IS_EMPTY)) {
-        return false;
+        *aidl_return = static_cast<int32_t>(false);
+        return Status::ok();
     }
 
-    return mKeyStore->isEmpty(userId);
+    *aidl_return = static_cast<int32_t>(mKeyStore->isEmpty(userId));
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_t targetUid,
-                                                    int32_t keyType, int32_t keySize, int32_t flags,
-                                                    Vector<sp<KeystoreArg>>* args) {
+Status KeyStoreService::generate(const String16& name, int32_t targetUid, int32_t keyType,
+                                 int32_t keySize, int32_t flags,
+                                 const ::android::security::KeystoreArguments& keystoreArgs,
+                                 int32_t* aidl_return) {
+    const Vector<sp<KeystoreArg>>* args = &(keystoreArgs.getArguments());
     targetUid = getEffectiveUid(targetUid);
-    auto result =
+    KeyStoreServiceReturnCode result =
         checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
     if (!result.isOk()) {
-        return result;
+        *aidl_return = static_cast<int32_t>(result);
+        return Status::ok();
     }
 
     keystore::AuthorizationSet params;
@@ -379,7 +439,8 @@
             keySize = EC_DEFAULT_KEY_SIZE;
         } else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
             ALOGI("invalid key size %d", keySize);
-            return ResponseCode::SYSTEM_ERROR;
+            *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+            return Status::ok();
         }
         params.push_back(TAG_KEY_SIZE, keySize);
         break;
@@ -390,13 +451,15 @@
             keySize = RSA_DEFAULT_KEY_SIZE;
         } else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
             ALOGI("invalid key size %d", keySize);
-            return ResponseCode::SYSTEM_ERROR;
+            *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+            return Status::ok();
         }
         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 ResponseCode::SYSTEM_ERROR;
+            *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+            return Status::ok();
         } else if (args->size() == 1) {
             const sp<KeystoreArg>& expArg = args->itemAt(0);
             if (expArg != NULL) {
@@ -404,16 +467,19 @@
                     reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
                 if (pubExpBn.get() == NULL) {
                     ALOGI("Could not convert public exponent to BN");
-                    return ResponseCode::SYSTEM_ERROR;
+                    *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+                    return Status::ok();
                 }
                 exponent = BN_get_word(pubExpBn.get());
                 if (exponent == 0xFFFFFFFFL) {
                     ALOGW("cannot represent public exponent as a long value");
-                    return ResponseCode::SYSTEM_ERROR;
+                    *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+                    return Status::ok();
                 }
             } else {
                 ALOGW("public exponent not read");
-                return ResponseCode::SYSTEM_ERROR;
+                *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+                return Status::ok();
             }
         }
         params.push_back(TAG_RSA_PUBLIC_EXPONENT, exponent);
@@ -421,31 +487,36 @@
     }
     default: {
         ALOGW("Unsupported key type %d", keyType);
-        return ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
     }
 
-    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));
+    int32_t aidl_result;
+    android::security::keymaster::KeyCharacteristics unused_characteristics;
+    auto rc = generateKey(name, KeymasterArguments(params.hidl_data()), ::std::vector<uint8_t>(),
+                          targetUid, flags, &unused_characteristics, &aidl_result);
+    if (!KeyStoreServiceReturnCode(aidl_result).isOk()) {
+        ALOGW("generate failed: %d", int32_t(aidl_result));
     }
-    return translateResultToLegacyResult(rc);
+    *aidl_return = aidl_result;
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
-                                                  const hidl_vec<uint8_t>& data, int targetUid,
-                                                  int32_t flags) {
+Status KeyStoreService::import_key(const String16& name, const ::std::vector<uint8_t>& data,
+                                   int targetUid, int32_t flags, int32_t* aidl_return) {
 
     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 ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
     Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
     if (!pkey.get()) {
-        return ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
     int type = EVP_PKEY_type(pkey->type);
     AuthorizationSet params;
@@ -459,33 +530,47 @@
         break;
     default:
         ALOGW("Unsupported key type %d", type);
-        return ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
 
-    auto rc = importKey(name, params.hidl_data(), KeyFormat::PKCS8, data, targetUid, flags,
-                        /*outCharacteristics*/ NULL);
+    int import_result;
+    auto rc = importKey(name, KeymasterArguments(params.hidl_data()),
+                        static_cast<int32_t>(KeyFormat::PKCS8), data, targetUid, flags,
+                        /*outCharacteristics*/ NULL, &import_result);
 
-    if (!rc.isOk()) {
-        ALOGW("importKey failed: %d", int32_t(rc));
+    if (!KeyStoreServiceReturnCode(import_result).isOk()) {
+        ALOGW("importKey failed: %d", int32_t(import_result));
     }
-    return translateResultToLegacyResult(rc);
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::sign(const String16& name, const hidl_vec<uint8_t>& data,
-                                                hidl_vec<uint8_t>* out) {
+Status KeyStoreService::sign(const String16& name, const ::std::vector<uint8_t>& data,
+                             ::std::vector<uint8_t>* out) {
     if (!checkBinderPermission(P_SIGN)) {
-        return ResponseCode::PERMISSION_DENIED;
+        return Status::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
     }
-    return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
+    hidl_vec<uint8_t> legacy_out;
+    KeyStoreServiceReturnCode res =
+        doLegacySignVerify(name, data, &legacy_out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
+    if (!res.isOk()) {
+        return Status::fromServiceSpecificError((res));
+    }
+    *out = legacy_out;
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
-                                                  const hidl_vec<uint8_t>& data,
-                                                  const hidl_vec<uint8_t>& signature) {
+Status KeyStoreService::verify(const String16& name, const ::std::vector<uint8_t>& data,
+                               const ::std::vector<uint8_t>& signature, int32_t* aidl_return) {
     if (!checkBinderPermission(P_VERIFY)) {
-        return ResponseCode::PERMISSION_DENIED;
+        return Status::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
     }
-    return doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY);
+    *aidl_return = static_cast<int32_t>(
+        doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY));
+    return Status::ok();
 }
 
 /*
@@ -499,72 +584,88 @@
  * "del_key" since the Java code doesn't really communicate what it's
  * intentions are.
  */
-KeyStoreServiceReturnCode KeyStoreService::get_pubkey(const String16& name,
-                                                      hidl_vec<uint8_t>* pubKey) {
-    ExportResult result;
-    exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
+Status KeyStoreService::get_pubkey(const String16& name, ::std::vector<uint8_t>* pubKey) {
+    android::security::keymaster::ExportResult result;
+    KeymasterBlob clientId;
+    KeymasterBlob appData;
+    exportKey(name, static_cast<int32_t>(KeyFormat::X509), clientId, appData, UID_SELF, &result);
     if (!result.resultCode.isOk()) {
         ALOGW("export failed: %d", int32_t(result.resultCode));
-        return translateResultToLegacyResult(result.resultCode);
+        return Status::fromServiceSpecificError(static_cast<int32_t>(result.resultCode));
     }
 
     if (pubKey) *pubKey = std::move(result.exportData);
-    return ResponseCode::NO_ERROR;
+    return Status::ok();
 }
 
-String16 KeyStoreService::grant(const String16& name, int32_t granteeUid) {
+Status KeyStoreService::grant(const String16& name, int32_t granteeUid,
+                              ::android::String16* aidl_return) {
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+    auto result =
+        checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
     if (!result.isOk()) {
-        return String16();
+        *aidl_return = String16();
+        return Status::ok();
     }
 
     String8 name8(name);
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
 
     if (access(filename.string(), R_OK) == -1) {
-        return String16();
+        *aidl_return = String16();
+        return Status::ok();
     }
 
-    return String16(mKeyStore->addGrant(String8(name).string(), callingUid, granteeUid).c_str());
+    *aidl_return =
+        String16(mKeyStore->addGrant(String8(name).string(), callingUid, granteeUid).c_str());
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
+Status KeyStoreService::ungrant(const String16& name, int32_t granteeUid, int32_t* aidl_return) {
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+    KeyStoreServiceReturnCode result =
+        checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
     if (!result.isOk()) {
-        return result;
+        *aidl_return = static_cast<int32_t>(result);
+        return Status::ok();
     }
 
     String8 name8(name);
     String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
 
     if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
+        *aidl_return = static_cast<int32_t>((errno != ENOENT) ? ResponseCode::SYSTEM_ERROR
+                                                              : ResponseCode::KEY_NOT_FOUND);
+        return Status::ok();
     }
 
-    return mKeyStore->removeGrant(name8, callingUid, granteeUid) ? ResponseCode::NO_ERROR
-                                                     : ResponseCode::KEY_NOT_FOUND;
+    *aidl_return = static_cast<int32_t>(mKeyStore->removeGrant(name8, callingUid, granteeUid)
+                                            ? ResponseCode::NO_ERROR
+                                            : ResponseCode::KEY_NOT_FOUND);
+    return Status::ok();
 }
 
-int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
+Status KeyStoreService::getmtime(const String16& name, int32_t uid, int64_t* time) {
     uid_t targetUid = getEffectiveUid(uid);
     if (!checkBinderPermission(P_GET, targetUid)) {
         ALOGW("permission denied for %d: getmtime", targetUid);
-        return -1L;
+        *time = -1L;
+        return Status::ok();
     }
 
     auto filename = mKeyStore->getBlobFileNameIfExists(String8(name), targetUid, ::TYPE_ANY);
 
     if (!filename.isOk()) {
         ALOGW("could not access %s for getmtime", filename.value().string());
-        return -1L;
+        *time = -1L;
+        return Status::ok();
     }
 
     int fd = TEMP_FAILURE_RETRY(open(filename.value().string(), O_NOFOLLOW, O_RDONLY));
     if (fd < 0) {
         ALOGW("could not open %s for getmtime", filename.value().string());
-        return -1L;
+        *time = -1L;
+        return Status::ok();
     }
 
     struct stat s;
@@ -572,82 +673,24 @@
     close(fd);
     if (ret == -1) {
         ALOGW("could not stat %s for getmtime", filename.value().string());
-        return -1L;
+        *time = -1L;
+        return Status::ok();
     }
 
-    return static_cast<int64_t>(s.st_mtime);
+    *time = static_cast<int64_t>(s.st_mtime);
+    return Status::ok();
 }
 
-// TODO(tuckeris): This is dead code, remove it.  Don't bother copying over key characteristics here
-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 ResponseCode::PERMISSION_DENIED;
-    }
-
-    State state = mKeyStore->getState(get_user_id(callingUid));
-    if (!isKeystoreUnlocked(state)) {
-        ALOGD("calling duplicate in state: %d", 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 ResponseCode::PERMISSION_DENIED;
-    }
-
-    if (destUid == -1) {
-        destUid = callingUid;
-    }
-
-    if (srcUid != destUid) {
-        if (static_cast<uid_t>(srcUid) != callingUid) {
-            ALOGD("can only duplicate from caller to other or to same uid: "
-                  "calling=%d, srcUid=%d, destUid=%d",
-                  callingUid, srcUid, destUid);
-            return ResponseCode::PERMISSION_DENIED;
-        }
-
-        if (!is_granted_to(callingUid, destUid)) {
-            ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
-            return ResponseCode::PERMISSION_DENIED;
-        }
-    }
-
-    String8 source8(srcKey);
-    String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid, ::TYPE_ANY));
-
-    String8 target8(destKey);
-    String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid, ::TYPE_ANY));
-
-    if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
-        ALOGD("destination already exists: %s", targetFile.string());
-        return ResponseCode::SYSTEM_ERROR;
-    }
-
-    Blob keyBlob;
-    ResponseCode responseCode =
-        mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
-    if (responseCode != ResponseCode::NO_ERROR) {
-        return responseCode;
-    }
-
-    return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
+Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
+    *aidl_return = static_cast<int32_t>(mKeyStore->isHardwareBacked(keyType) ? 1 : 0);
+    return Status::ok();
 }
 
-int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
-    return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
-}
-
-KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
+Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* aidl_return) {
     uid_t targetUid = getEffectiveUid(targetUid64);
     if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
     ALOGI("clear_uid %" PRId64, targetUid64);
 
@@ -656,7 +699,8 @@
     String8 prefix = String8::format("%u_", targetUid);
     Vector<String16> aliases;
     if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
-        return ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
 
     for (uint32_t i = 0; i < aliases.size(); i++) {
@@ -680,61 +724,93 @@
             mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
         mKeyStore->del(chr_filename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
     }
-    return ResponseCode::NO_ERROR;
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::addRngEntropy(const hidl_vec<uint8_t>& entropy) {
-    const auto& device = mKeyStore->getDevice();
-    return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
+Status KeyStoreService::addRngEntropy(const ::std::vector<uint8_t>& entropy, int32_t flags,
+                                      int32_t* aidl_return) {
+    auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags));
+    if (!device) {
+        *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+    } else {
+        *aidl_return = static_cast<int32_t>(
+            KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy))));
+    }
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
-                                                       const hidl_vec<KeyParameter>& params,
-                                                       const hidl_vec<uint8_t>& entropy, int uid,
-                                                       int flags,
-                                                       KeyCharacteristics* outCharacteristics) {
+Status
+KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
+                             const ::std::vector<uint8_t>& entropy, int uid, int flags,
+                             android::security::keymaster::KeyCharacteristics* outCharacteristics,
+                             int32_t* aidl_return) {
+    // TODO(jbires): remove this getCallingUid call upon implementation of b/25646100
+    uid_t originalUid = IPCThreadState::self()->getCallingUid();
     uid = getEffectiveUid(uid);
+    auto logOnScopeExit = android::base::make_scope_guard([&] {
+        if (__android_log_security()) {
+            android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED)
+                << int32_t(*aidl_return == static_cast<int32_t>(ResponseCode::NO_ERROR))
+                << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
+        }
+    });
     KeyStoreServiceReturnCode rc =
         checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
     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;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
-    if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
-        if (!checkBinderPermission(P_GEN_UNIQUE_ID)) return ResponseCode::PERMISSION_DENIED;
+    if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) {
+        // TODO(jbires): remove uid checking upon implementation of b/25646100
+        if (!checkBinderPermission(P_GEN_UNIQUE_ID) ||
+            originalUid != IPCThreadState::self()->getCallingUid()) {
+            *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+            return Status::ok();
+        }
     }
 
-    bool usingFallback = false;
-    auto& dev = mKeyStore->getDevice();
-    AuthorizationSet keyCharacteristics = params;
+    SecurityLevel securityLevel = flagsToSecurityLevel(flags);
+    auto dev = mKeyStore->getDevice(securityLevel);
+    if (!dev) {
+        *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+        return Status::ok();
+    }
+    AuthorizationSet keyCharacteristics = params.getParameters();
 
     // TODO: Seed from Linux RNG before this.
-    rc = addRngEntropy(entropy);
+    rc = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy));
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
 
     KeyStoreServiceReturnCode error;
-    auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
+    auto hidl_cb = [&](ErrorCode ret, const ::std::vector<uint8_t>& hidlKeyBlob,
                        const KeyCharacteristics& keyCharacteristics) {
         error = ret;
         if (!error.isOk()) {
             return;
         }
-        if (outCharacteristics) *outCharacteristics = keyCharacteristics;
+        if (outCharacteristics)
+            *outCharacteristics =
+                ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
 
         // Write the key
         String8 name8(name);
         String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
 
         Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
-        keyBlob.setFallback(usingFallback);
+        keyBlob.setSecurityLevel(securityLevel);
         keyBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
-        if (isAuthenticationBound(params) && !keyBlob.isCriticalToDeviceEncryption()) {
+        if (isAuthenticationBound(params.getParameters()) &&
+            !keyBlob.isCriticalToDeviceEncryption()) {
             keyBlob.setSuperEncrypted(true);
         }
         keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -742,24 +818,49 @@
         error = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
     };
 
-    rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params, hidl_cb));
+    rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params.getParameters(), hidl_cb));
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
     if (!error.isOk()) {
         ALOGE("Failed to generate key -> falling back to software keymaster");
-        usingFallback = true;
-        auto fallback = mKeyStore->getFallbackDevice();
-        if (!fallback.isOk()) {
-            return error;
+        uploadKeyCharacteristicsAsProto(params.getParameters(), false /* wasCreationSuccessful */);
+        securityLevel = SecurityLevel::SOFTWARE;
+
+        // No fall back for 3DES
+        for (auto& param : params.getParameters()) {
+            auto algorithm = authorizationValue(TAG_ALGORITHM, param);
+            if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) {
+                *aidl_return = static_cast<int32_t>(ErrorCode::UNSUPPORTED_ALGORITHM);
+                return Status::ok();
+            }
         }
-        rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params, hidl_cb));
+
+        auto fallback = mKeyStore->getFallbackDevice();
+        if (!fallback) {
+            *aidl_return = static_cast<int32_t>(error);
+            return Status::ok();
+        }
+        rc = KS_HANDLE_HIDL_ERROR(fallback->generateKey(params.getParameters(), hidl_cb));
         if (!rc.isOk()) {
-            return rc;
+            *aidl_return = static_cast<int32_t>(rc);
+            return Status::ok();
         }
         if (!error.isOk()) {
-            return error;
+            *aidl_return = static_cast<int32_t>(error);
+            return Status::ok();
         }
+    } else {
+        uploadKeyCharacteristicsAsProto(params.getParameters(), true /* wasCreationSuccessful */);
+    }
+
+    if (!containsTag(params.getParameters(), Tag::USER_ID)) {
+        // Most Java processes don't have access to this tag
+        KeyParameter user_id;
+        user_id.tag = Tag::USER_ID;
+        user_id.f.integer = mActiveUserId;
+        keyCharacteristics.push_back(user_id);
     }
 
     // Write the characteristics:
@@ -769,23 +870,28 @@
     std::stringstream kc_stream;
     keyCharacteristics.Serialize(&kc_stream);
     if (kc_stream.bad()) {
-        return ResponseCode::SYSTEM_ERROR;
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
     }
     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.setSecurityLevel(securityLevel);
     charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
 
-    return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
+    *aidl_return =
+        static_cast<int32_t>(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid)));
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode
-KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
-                                       const hidl_vec<uint8_t>& appData, int32_t uid,
-                                       KeyCharacteristics* outCharacteristics) {
+Status KeyStoreService::getKeyCharacteristics(
+    const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId,
+    const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
+    ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* aidl_return) {
     if (!outCharacteristics) {
-        return ErrorCode::UNEXPECTED_NULL_POINTER;
+        *aidl_return =
+            static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::UNEXPECTED_NULL_POINTER));
+        return Status::ok();
     }
 
     uid_t targetUid = getEffectiveUid(uid);
@@ -793,7 +899,8 @@
     if (!is_granted_to(callingUid, targetUid)) {
         ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
               targetUid);
-        return ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
     Blob keyBlob;
@@ -809,7 +916,8 @@
          */
         rc = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
         if (!rc.isOk()) {
-            return rc;
+            *aidl_return = static_cast<int32_t>(rc);
+            return Status::ok();
         }
         AuthorizationSet keyCharacteristics;
         // TODO write one shot stream buffer to avoid copying (twice here)
@@ -818,94 +926,122 @@
         std::stringstream charStream(charBuffer);
         keyCharacteristics.Deserialize(&charStream);
 
-        outCharacteristics->softwareEnforced = keyCharacteristics.hidl_data();
-        return rc;
+        outCharacteristics->softwareEnforced = KeymasterArguments(keyCharacteristics.hidl_data());
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     } else if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
 
     auto hidlKeyBlob = blob2hidlVec(keyBlob);
-    auto& dev = mKeyStore->getDevice(keyBlob);
+    auto dev = mKeyStore->getDevice(keyBlob);
 
     KeyStoreServiceReturnCode error;
 
     auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
         error = ret;
         if (!error.isOk()) {
+            if (error == ErrorCode::INVALID_KEY_BLOB) {
+                log_key_integrity_violation(name8, targetUid);
+            }
             return;
         }
-        *outCharacteristics = keyCharacteristics;
+        *outCharacteristics =
+            ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
     };
 
-    rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
+    rc = KS_HANDLE_HIDL_ERROR(
+        dev->getKeyCharacteristics(hidlKeyBlob, clientId.getData(), appData.getData(), hidlCb));
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
 
     if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
         AuthorizationSet upgradeParams;
-        if (clientId.size()) {
-            upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+        if (clientId.getData().size()) {
+            upgradeParams.push_back(TAG_APPLICATION_ID, clientId.getData());
         }
-        if (appData.size()) {
-            upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
+        if (appData.getData().size()) {
+            upgradeParams.push_back(TAG_APPLICATION_DATA, appData.getData());
         }
         rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
         if (!rc.isOk()) {
-            return rc;
+            *aidl_return = static_cast<int32_t>(rc);
+            return Status::ok();
         }
 
         auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
 
-        rc = KS_HANDLE_HIDL_ERROR(
-            dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
+        rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(
+            upgradedHidlKeyBlob, clientId.getData(), appData.getData(), hidlCb));
         if (!rc.isOk()) {
-            return rc;
+            *aidl_return = static_cast<int32_t>(rc);
+            return Status::ok();
         }
         // Note that, on success, "error" will have been updated by the hidlCB callback.
         // So it is fine to return "error" below.
     }
-    return error;
+    *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(error));
+    return Status::ok();
 }
 
-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) {
+Status
+KeyStoreService::importKey(const String16& name, const KeymasterArguments& params, int32_t format,
+                           const ::std::vector<uint8_t>& keyData, int uid, int flags,
+                           ::android::security::keymaster::KeyCharacteristics* outCharacteristics,
+                           int32_t* aidl_return) {
+
     uid = getEffectiveUid(uid);
+    auto logOnScopeExit = android::base::make_scope_guard([&] {
+        if (__android_log_security()) {
+            android_log_event_list(SEC_TAG_KEY_IMPORTED)
+                << int32_t(*aidl_return == static_cast<int32_t>(ResponseCode::NO_ERROR))
+                << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
+        }
+    });
     KeyStoreServiceReturnCode rc =
         checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
     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;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
 
-    bool usingFallback = false;
-    auto& dev = mKeyStore->getDevice();
+    SecurityLevel securityLevel = flagsToSecurityLevel(flags);
+    auto dev = mKeyStore->getDevice(securityLevel);
+    if (!dev) {
+        *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+        return Status::ok();
+    }
 
     String8 name8(name);
 
     KeyStoreServiceReturnCode error;
 
-    auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+    auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& keyBlob,
                       const KeyCharacteristics& keyCharacteristics) {
         error = ret;
         if (!error.isOk()) {
             return;
         }
-
-        if (outCharacteristics) *outCharacteristics = keyCharacteristics;
+        if (outCharacteristics)
+            *outCharacteristics =
+                ::android::security::keymaster::KeyCharacteristics(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.setSecurityLevel(securityLevel);
         ksBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
-        if (isAuthenticationBound(params) && !ksBlob.isCriticalToDeviceEncryption()) {
+        if (isAuthenticationBound(params.getParameters()) &&
+            !ksBlob.isCriticalToDeviceEncryption()) {
             ksBlob.setSuperEncrypted(true);
         }
         ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -913,57 +1049,91 @@
         error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(uid));
     };
 
-    rc = KS_HANDLE_HIDL_ERROR(dev->importKey(params, format, keyData, hidlCb));
+    rc = KS_HANDLE_HIDL_ERROR(
+        dev->importKey(params.getParameters(), KeyFormat(format), keyData, hidlCb));
     // possible hidl error
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
     // 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;
+        uploadKeyCharacteristicsAsProto(params.getParameters(), false /* wasCreationSuccessful */);
+        securityLevel = SecurityLevel::SOFTWARE;
+
+        // No fall back for 3DES
+        for (auto& param : params.getParameters()) {
+            auto algorithm = authorizationValue(TAG_ALGORITHM, param);
+            if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) {
+                *aidl_return = static_cast<int32_t>(ErrorCode::UNSUPPORTED_ALGORITHM);
+                return Status::ok();
+            }
         }
-        rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params, format, keyData, hidlCb));
+
+        auto fallback = mKeyStore->getFallbackDevice();
+        if (!fallback) {
+            *aidl_return = static_cast<int32_t>(error);
+            return Status::ok();
+        }
+        rc = KS_HANDLE_HIDL_ERROR(
+            fallback->importKey(params.getParameters(), KeyFormat(format), keyData, hidlCb));
         // possible hidl error
         if (!rc.isOk()) {
-            return rc;
+            *aidl_return = static_cast<int32_t>(rc);
+            return Status::ok();
         }
         // now check error from callback
         if (!error.isOk()) {
-            return error;
+            *aidl_return = static_cast<int32_t>(error);
+            return Status::ok();
         }
+    } else {
+        uploadKeyCharacteristicsAsProto(params.getParameters(), true /* wasCreationSuccessful */);
     }
 
     // Write the characteristics:
     String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
 
-    AuthorizationSet opParams = params;
+    AuthorizationSet opParams = params.getParameters();
+    if (!containsTag(params.getParameters(), Tag::USER_ID)) {
+        // Most Java processes don't have access to this tag
+        KeyParameter user_id;
+        user_id.tag = Tag::USER_ID;
+        user_id.f.integer = mActiveUserId;
+        opParams.push_back(user_id);
+    }
+
     std::stringstream kcStream;
     opParams.Serialize(&kcStream);
-    if (kcStream.bad()) return ResponseCode::SYSTEM_ERROR;
+    if (kcStream.bad()) {
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
+    }
     auto kcBuf = kcStream.str();
 
     Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
                   ::TYPE_KEY_CHARACTERISTICS);
-    charBlob.setFallback(usingFallback);
+    charBlob.setSecurityLevel(securityLevel);
     charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
 
-    return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
+    *aidl_return =
+        static_cast<int32_t>(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid)));
+
+    return Status::ok();
 }
 
-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) {
+Status KeyStoreService::exportKey(const String16& name, int32_t format,
+                                  const ::android::security::keymaster::KeymasterBlob& clientId,
+                                  const ::android::security::keymaster::KeymasterBlob& 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 = ResponseCode::PERMISSION_DENIED;
-        return;
+        return Status::ok();
     }
 
     Blob keyBlob;
@@ -971,21 +1141,24 @@
 
     result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
     if (!result->resultCode.isOk()) {
-        return;
+        return Status::ok();
     }
 
     auto key = blob2hidlVec(keyBlob);
-    auto& dev = mKeyStore->getDevice(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()) {
+            if (result->resultCode == ErrorCode::INVALID_KEY_BLOB) {
+                log_key_integrity_violation(name8, targetUid);
+            }
             return;
         }
         result->exportData = keyMaterial;
     };
-    KeyStoreServiceReturnCode rc =
-        KS_HANDLE_HIDL_ERROR(dev->exportKey(format, key, clientId, appData, hidlCb));
+    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+        dev->exportKey(KeyFormat(format), key, clientId.getData(), appData.getData(), hidlCb));
     // Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
     // callback hidlCb.
     if (!rc.isOk()) {
@@ -994,83 +1167,77 @@
 
     if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
         AuthorizationSet upgradeParams;
-        if (clientId.size()) {
-            upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+        if (clientId.getData().size()) {
+            upgradeParams.push_back(TAG_APPLICATION_ID, clientId.getData());
         }
-        if (appData.size()) {
-            upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
+        if (appData.getData().size()) {
+            upgradeParams.push_back(TAG_APPLICATION_DATA, appData.getData());
         }
         result->resultCode = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
         if (!result->resultCode.isOk()) {
-            return;
+            return Status::ok();
         }
 
         auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
 
-        result->resultCode = KS_HANDLE_HIDL_ERROR(
-            dev->exportKey(format, upgradedHidlKeyBlob, clientId, appData, hidlCb));
+        result->resultCode = KS_HANDLE_HIDL_ERROR(dev->exportKey(
+            KeyFormat(format), upgradedHidlKeyBlob, clientId.getData(), appData.getData(), hidlCb));
         if (!result->resultCode.isOk()) {
-            return;
+            return Status::ok();
         }
     }
+    return Status::ok();
 }
 
-static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
-    if (token) {
-        params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
-    }
-}
+Status KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, int32_t purpose,
+                              bool pruneable, const KeymasterArguments& params,
+                              const ::std::vector<uint8_t>& entropy, int32_t uid,
+                              OperationResult* result) {
+    auto keyPurpose = static_cast<KeyPurpose>(purpose);
 
-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 = ResponseCode::PERMISSION_DENIED;
-        return;
+        return Status::ok();
     }
     if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
         ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
         result->resultCode = ResponseCode::PERMISSION_DENIED;
-        return;
+        return Status::ok();
     }
-    if (!checkAllowedOperationParams(params)) {
+    if (!checkAllowedOperationParams(params.getParameters())) {
         result->resultCode = ErrorCode::INVALID_ARGUMENT;
-        return;
+        return Status::ok();
     }
+
     Blob keyBlob;
     String8 name8(name);
     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;
-    }
+    if (!result->resultCode.isOk()) return Status::ok();
 
     auto key = blob2hidlVec(keyBlob);
-    auto& dev = mKeyStore->getDevice(keyBlob);
-    AuthorizationSet opParams = params;
+    auto dev = mKeyStore->getDevice(keyBlob);
+    AuthorizationSet opParams = params.getParameters();
     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;
+            return Status::ok();
         }
         key = blob2hidlVec(keyBlob);
         result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
     }
     if (!result->resultCode.isOk()) {
-        return;
+        return Status::ok();
     }
 
-    const HardwareAuthToken* authToken = NULL;
-
     // Merge these characteristics with the ones cached when the key was generated or imported
     Blob charBlob;
     AuthorizationSet persistedCharacteristics;
@@ -1088,28 +1255,30 @@
 
     // Replace the sw_enforced set with those persisted to disk, minus hw_enforced
     AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
-    AuthorizationSet teeEnforced = characteristics.teeEnforced;
+    AuthorizationSet hardwareEnforced = characteristics.hardwareEnforced;
     persistedCharacteristics.Union(softwareEnforced);
-    persistedCharacteristics.Subtract(teeEnforced);
+    persistedCharacteristics.Subtract(hardwareEnforced);
     characteristics.softwareEnforced = persistedCharacteristics.hidl_data();
 
-    auto authResult = getAuthToken(characteristics, 0, purpose, &authToken,
-                                   /*failOnTokenMissing*/ false);
+    KeyStoreServiceReturnCode authResult;
+    HardwareAuthToken authToken;
+    std::tie(authResult, authToken) =
+        getAuthToken(characteristics, 0 /* no challenge */, keyPurpose,
+                     /*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.isOk() && authResult != ResponseCode::OP_AUTH_NEEDED) {
         result->resultCode = authResult;
-        return;
+        return Status::ok();
     }
 
-    addAuthTokenToParams(&opParams, authToken);
-
     // Add entropy to the device first.
     if (entropy.size()) {
-        result->resultCode = addRngEntropy(entropy);
+        result->resultCode = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy));
         if (!result->resultCode.isOk()) {
-            return;
+            return Status::ok();
         }
     }
 
@@ -1118,18 +1287,19 @@
     if (!enforcement_policy.CreateKeyId(key, &keyid)) {
         ALOGE("Failed to create a key ID for authorization checking.");
         result->resultCode = ErrorCode::UNKNOWN_ERROR;
-        return;
+        return Status::ok();
     }
 
     // Check that all key authorization policy requirements are met.
-    AuthorizationSet key_auths = characteristics.teeEnforced;
-    key_auths.append(&characteristics.softwareEnforced[0],
-                     &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);
+    AuthorizationSet key_auths = characteristics.hardwareEnforced;
+    key_auths.append(characteristics.softwareEnforced.begin(),
+                     characteristics.softwareEnforced.end());
 
-    result->resultCode = enforcement_policy.AuthorizeOperation(
-        purpose, keyid, key_auths, opParams, 0 /* op_handle */, true /* is_begin_operation */);
+    result->resultCode =
+        enforcement_policy.AuthorizeOperation(keyPurpose, keyid, key_auths, opParams, authToken,
+                                              0 /* op_handle */, true /* is_begin_operation */);
     if (!result->resultCode.isOk()) {
-        return;
+        return Status::ok();
     }
 
     // If there are more than kMaxOperations, abort the oldest operation that was started as
@@ -1145,13 +1315,17 @@
                       uint64_t operationHandle) {
         result->resultCode = ret;
         if (!result->resultCode.isOk()) {
+            if (result->resultCode == ErrorCode::INVALID_KEY_BLOB) {
+                log_key_integrity_violation(name8, targetUid);
+            }
             return;
         }
         result->handle = operationHandle;
         result->outParams = outParams;
     };
 
-    ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
+    ErrorCode rc =
+        KS_HANDLE_HIDL_ERROR(dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
     if (rc != ErrorCode::OK) {
         ALOGW("Got error %d from begin()", rc);
     }
@@ -1163,24 +1337,44 @@
         if (!pruneOperation()) {
             break;
         }
-        rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
+        rc = KS_HANDLE_HIDL_ERROR(
+            dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
     }
     if (rc != ErrorCode::OK) {
         result->resultCode = rc;
-        return;
+        return Status::ok();
+    }
+
+    VerificationToken verificationToken;
+    if (authResult.isOk() && authToken.mac.size() &&
+        dev->halVersion().securityLevel == SecurityLevel::STRONGBOX) {
+        // This operation needs an auth token, but the device is a STRONGBOX, so it can't check the
+        // timestamp in the auth token.  Get a VerificationToken from the TEE, which will be passed
+        // to update() and begin().
+        rc = KS_HANDLE_HIDL_ERROR(mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)
+                                      ->verifyAuthorization(result->handle,
+                                                            {} /* parametersToVerify */, authToken,
+                                                            [&](auto error, const auto& token) {
+                                                                result->resultCode = error;
+                                                                verificationToken = token;
+                                                            }));
+
+        if (rc != ErrorCode::OK) result->resultCode = rc;
+        if (result->resultCode != ErrorCode::OK) return Status::ok();
     }
 
     // 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);
+    sp<IBinder> operationToken =
+        mOperationMap.addOperation(result->handle, keyid, keyPurpose, dev, appToken,
+                                   std::move(characteristics), params.getParameters(), pruneable);
+    assert(characteristics.hardwareEnforced.size() == 0);
     assert(characteristics.softwareEnforced.size() == 0);
     result->token = operationToken;
 
-    if (authToken) {
-        mOperationMap.setOperationAuthToken(operationToken, authToken);
-    }
+    mOperationMap.setOperationAuthToken(operationToken, std::move(authToken));
+    mOperationMap.setOperationVerificationToken(operationToken, std::move(verificationToken));
+
     // Return the authentication lookup result. If this is a per operation
     // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
     // application should get an auth token using the handle before the
@@ -1191,234 +1385,254 @@
     }
 
     // Other result fields were set in the begin operation's callback.
+    return Status::ok();
 }
 
-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;
-    }
-    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 = ErrorCode::INVALID_OPERATION_HANDLE;
-        return;
-    }
-    AuthorizationSet opParams = params;
-    result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
-    if (!result->resultCode.isOk()) {
+void KeyStoreService::appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics,
+                                                      std::vector<KeyParameter>* params) {
+    if (!(containsTag(keyCharacteristics.softwareEnforced, Tag::TRUSTED_CONFIRMATION_REQUIRED) ||
+          containsTag(keyCharacteristics.hardwareEnforced, Tag::TRUSTED_CONFIRMATION_REQUIRED))) {
         return;
     }
 
-    // Check that all key authorization policy requirements are met.
-    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()) {
+    hidl_vec<uint8_t> confirmationToken = mConfirmationManager->getLatestConfirmationToken();
+    if (confirmationToken.size() == 0) {
         return;
     }
 
+    params->push_back(
+        Authorization(keymaster::TAG_CONFIRMATION_TOKEN, std::move(confirmationToken)));
+    ALOGD("Appending confirmation token\n");
+}
+
+Status KeyStoreService::update(const sp<IBinder>& token, const KeymasterArguments& params,
+                               const ::std::vector<uint8_t>& data, OperationResult* result) {
+    if (!checkAllowedOperationParams(params.getParameters())) {
+        result->resultCode = ErrorCode::INVALID_ARGUMENT;
+        return Status::ok();
+    }
+
+    auto getOpResult = mOperationMap.getOperation(token);
+    if (!getOpResult.isOk()) {
+        result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
+        return Status::ok();
+    }
+    const auto& op = getOpResult.value();
+
+    HardwareAuthToken authToken;
+    std::tie(result->resultCode, authToken) = getOperationAuthTokenIfNeeded(token);
+    if (!result->resultCode.isOk()) return Status::ok();
+
+    // Check that all key authorization policy requirements are met.
+    AuthorizationSet key_auths(op.characteristics.hardwareEnforced);
+    key_auths.append(op.characteristics.softwareEnforced.begin(),
+                     op.characteristics.softwareEnforced.end());
+
+    result->resultCode = enforcement_policy.AuthorizeOperation(
+        op.purpose, op.keyid, key_auths, params.getParameters(), authToken, op.handle,
+        false /* is_begin_operation */);
+    if (!result->resultCode.isOk()) return Status::ok();
+
+    std::vector<KeyParameter> inParams = params.getParameters();
+
     auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
-                      const hidl_vec<KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
+                      const hidl_vec<KeyParameter>& outParams,
+                      const ::std::vector<uint8_t>& output) {
         result->resultCode = ret;
-        if (!result->resultCode.isOk()) {
-            return;
+        if (result->resultCode.isOk()) {
+            result->inputConsumed = inputConsumed;
+            result->outParams = outParams;
+            result->data = output;
         }
-        result->inputConsumed = inputConsumed;
-        result->outParams = outParams;
-        result->data = output;
     };
 
-    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->update(handle, opParams.hidl_data(),
-                                                        data, hidlCb));
+    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+        op.device->update(op.handle, inParams, data, authToken, op.verificationToken, 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;
-    }
+    if (!rc.isOk()) result->resultCode = rc;
+
+    return Status::ok();
 }
 
-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)) {
-        result->resultCode = ErrorCode::INVALID_ARGUMENT;
-        return;
-    }
-    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)) {
+Status KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                               const ::std::vector<uint8_t>& signature,
+                               const ::std::vector<uint8_t>& entropy, OperationResult* result) {
+    auto getOpResult = mOperationMap.getOperation(token);
+    if (!getOpResult.isOk()) {
         result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
-        return;
+        return Status::ok();
     }
-    AuthorizationSet opParams = params;
-    result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
-    if (!result->resultCode.isOk()) {
-        return;
+    const auto& op = std::move(getOpResult.value());
+    if (!checkAllowedOperationParams(params.getParameters())) {
+        result->resultCode = ErrorCode::INVALID_ARGUMENT;
+        return Status::ok();
     }
 
+    HardwareAuthToken authToken;
+    std::tie(result->resultCode, authToken) = getOperationAuthTokenIfNeeded(token);
+    if (!result->resultCode.isOk()) return Status::ok();
+
     if (entropy.size()) {
-        result->resultCode = addRngEntropy(entropy);
+        result->resultCode = KS_HANDLE_HIDL_ERROR(op.device->addRngEntropy(entropy));
         if (!result->resultCode.isOk()) {
-            return;
+            return Status::ok();
         }
     }
 
     // Check that all key authorization policy requirements are met.
-    AuthorizationSet key_auths(characteristics->teeEnforced);
-    key_auths.append(&characteristics->softwareEnforced[0],
-                     &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
+    AuthorizationSet key_auths(op.characteristics.hardwareEnforced);
+    key_auths.append(op.characteristics.softwareEnforced.begin(),
+                     op.characteristics.softwareEnforced.end());
+
+    std::vector<KeyParameter> inParams = params.getParameters();
+    appendConfirmationTokenIfNeeded(op.characteristics, &inParams);
+
     result->resultCode = enforcement_policy.AuthorizeOperation(
-        purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
-    if (!result->resultCode.isOk()) return;
+        op.purpose, op.keyid, key_auths, params.getParameters(), authToken, op.handle,
+        false /* is_begin_operation */);
+    if (!result->resultCode.isOk()) return Status::ok();
 
     auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
-                      const hidl_vec<uint8_t>& output) {
+                      const ::std::vector<uint8_t>& output) {
         result->resultCode = ret;
-        if (!result->resultCode.isOk()) {
-            return;
+        if (result->resultCode.isOk()) {
+            result->outParams = outParams;
+            result->data = output;
         }
-        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);
+    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+        op.device->finish(op.handle, inParams,
+                          ::std::vector<uint8_t>() /* TODO(swillden): wire up input to finish() */,
+                          signature, authToken, op.verificationToken, hidlCb));
 
+    bool wasOpSuccessful = true;
     // 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;
+        wasOpSuccessful = false;
     }
+
+    // removeOperation() will free the memory 'op' used, so the order is important
+    mAuthTokenTable.MarkCompleted(op.handle);
+    mOperationMap.removeOperation(token, wasOpSuccessful);
+    return Status::ok();
 }
 
-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 ErrorCode::INVALID_OPERATION_HANDLE;
+Status KeyStoreService::abort(const sp<IBinder>& token, int32_t* aidl_return) {
+    auto getOpResult = mOperationMap.removeOperation(token, false /* wasOpSuccessful */);
+    if (!getOpResult.isOk()) {
+        *aidl_return = static_cast<int32_t>(ErrorCode::INVALID_OPERATION_HANDLE);
+        return Status::ok();
     }
-    mOperationMap.removeOperation(token);
+    auto op = std::move(getOpResult.value());
+    mAuthTokenTable.MarkCompleted(op.handle);
 
-    ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->abort(handle));
-    mAuthTokenTable.MarkCompleted(handle);
-    return rc;
+    ErrorCode error_code = KS_HANDLE_HIDL_ERROR(op.device->abort(op.handle));
+    *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(error_code));
+    return Status::ok();
 }
 
-bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
-    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 HardwareAuthToken* authToken = NULL;
-    mOperationMap.getOperationAuthToken(token, &authToken);
+Status KeyStoreService::isOperationAuthorized(const sp<IBinder>& token, bool* aidl_return) {
     AuthorizationSet ignored;
-    auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
-    return authResult.isOk();
+    KeyStoreServiceReturnCode rc;
+    std::tie(rc, std::ignore) = getOperationAuthTokenIfNeeded(token);
+    *aidl_return = rc.isOk();
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVector,
+                                     int32_t* aidl_return) {
+
     // 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 ResponseCode::PERMISSION_DENIED;
+        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+        return Status::ok();
     }
-    if (length != sizeof(hw_auth_token_t)) {
-        return ErrorCode::INVALID_ARGUMENT;
+    if (authTokenAsVector.size() != sizeof(hw_auth_token_t)) {
+        *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+        return Status::ok();
     }
 
     hw_auth_token_t authToken;
-    memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
+    memcpy(reinterpret_cast<void*>(&authToken), authTokenAsVector.data(), sizeof(hw_auth_token_t));
     if (authToken.version != 0) {
-        return ErrorCode::INVALID_ARGUMENT;
+        *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+        return Status::ok();
     }
 
-    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(hidlAuthToken.release());
-    return ResponseCode::NO_ERROR;
+    mAuthTokenTable.AddAuthenticationToken(hidlVec2AuthToken(hidl_vec<uint8_t>(authTokenAsVector)));
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
 }
 
-bool isDeviceIdAttestationRequested(const hidl_vec<KeyParameter>& params) {
-    for (size_t i = 0; i < params.size(); ++i) {
-        switch (params[i].tag) {
+int isDeviceIdAttestationRequested(const KeymasterArguments& params) {
+    const hardware::hidl_vec<KeyParameter> paramsVec = params.getParameters();
+    int result = 0;
+    for (size_t i = 0; i < paramsVec.size(); ++i) {
+        switch (paramsVec[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:
+            result |= ID_ATTESTATION_REQUEST_GENERIC_INFO;
             break;
+        case Tag::ATTESTATION_ID_IMEI:
+        case Tag::ATTESTATION_ID_MEID:
+        case Tag::ATTESTATION_ID_SERIAL:
+            result |= ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
+            break;
+        default:
+            continue;
         }
     }
-    return false;
+    return result;
 }
 
-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;
+Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
+                                  ::android::security::keymaster::KeymasterCertificateChain* chain,
+                                  int32_t* aidl_return) {
+    // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
+    if (!checkAllowedOperationParams(params.getParameters())) {
+        *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+        return Status::ok();
     }
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
 
-    AuthorizationSet mutableParams = params;
+    int needsIdAttestation = isDeviceIdAttestationRequested(params);
+    bool needsUniqueIdAttestation = needsIdAttestation & ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
+    bool isPrimaryUserSystemUid = (callingUid == AID_SYSTEM);
+    bool isSomeUserSystemUid = (get_app_id(callingUid) == AID_SYSTEM);
+    // Allow system context from any user to request attestation with basic device information,
+    // while only allow system context from user 0 (device owner) to request attestation with
+    // unique device ID.
+    if ((needsIdAttestation && !isSomeUserSystemUid) ||
+        (needsUniqueIdAttestation && !isPrimaryUserSystemUid)) {
+        *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+        return Status::ok();
+    }
+
+    AuthorizationSet mutableParams = params.getParameters();
     KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
 
     Blob keyBlob;
     String8 name8(name);
     rc = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
 
     KeyStoreServiceReturnCode error;
@@ -1427,54 +1641,73 @@
         if (!error.isOk()) {
             return;
         }
-        if (outChain) *outChain = certChain;
+        if (chain) {
+            *chain = KeymasterCertificateChain(certChain);
+        }
     };
 
     auto hidlKey = blob2hidlVec(keyBlob);
-    auto& dev = mKeyStore->getDevice(keyBlob);
+    auto dev = mKeyStore->getDevice(keyBlob);
     rc = KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb));
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
-    return error;
+    *aidl_return = static_cast<int32_t>(error);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyParameter>& params,
-                                                           hidl_vec<hidl_vec<uint8_t>>* outChain) {
-    if (!outChain) {
-        return ErrorCode::OUTPUT_PARAMETER_NULL;
-    }
+Status
+KeyStoreService::attestDeviceIds(const KeymasterArguments& params,
+                                 ::android::security::keymaster::KeymasterCertificateChain* chain,
+                                 int32_t* aidl_return) {
+    // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
 
-    if (!checkAllowedOperationParams(params)) {
-        return ErrorCode::INVALID_ARGUMENT;
+    if (!checkAllowedOperationParams(params.getParameters())) {
+        *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+        return Status::ok();
     }
 
     if (!isDeviceIdAttestationRequested(params)) {
         // There is an attestKey() method for attesting keys without device ID attestation.
-        return ErrorCode::INVALID_ARGUMENT;
+        *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+        return Status::ok();
     }
 
     uid_t callingUid = IPCThreadState::self()->getCallingUid();
     sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
     if (binder == 0) {
-        return ErrorCode::CANNOT_ATTEST_IDS;
+        *aidl_return =
+            static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::CANNOT_ATTEST_IDS));
+        return Status::ok();
     }
     if (!interface_cast<IPermissionController>(binder)->checkPermission(
             String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
             IPCThreadState::self()->getCallingPid(), callingUid)) {
-        return ErrorCode::CANNOT_ATTEST_IDS;
+        *aidl_return =
+            static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::CANNOT_ATTEST_IDS));
+        return Status::ok();
     }
 
-    AuthorizationSet mutableParams = params;
+    AuthorizationSet mutableParams = params.getParameters();
     KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
 
     // Generate temporary key.
-    auto& dev = mKeyStore->getDevice();
+    sp<Keymaster> dev;
+    SecurityLevel securityLevel;
+    std::tie(dev, securityLevel) = mKeyStore->getMostSecureDevice();
+
+    if (securityLevel == SecurityLevel::SOFTWARE) {
+        *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+        return Status::ok();
+    }
+
     KeyStoreServiceReturnCode error;
-    hidl_vec<uint8_t> hidlKey;
+    ::std::vector<uint8_t> hidlKey;
 
     AuthorizationSet keyCharacteristics;
     keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
@@ -1482,7 +1715,7 @@
     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,
+    auto generateHidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& hidlKeyBlob,
                               const KeyCharacteristics&) {
         error = ret;
         if (!error.isOk()) {
@@ -1493,10 +1726,12 @@
 
     rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(keyCharacteristics.hidl_data(), generateHidlCb));
     if (!rc.isOk()) {
-        return rc;
+        *aidl_return = static_cast<int32_t>(rc);
+        return Status::ok();
     }
     if (!error.isOk()) {
-        return error;
+        *aidl_return = static_cast<int32_t>(error);
+        return Status::ok();
     }
 
     // Attest key and device IDs.
@@ -1505,27 +1740,140 @@
         if (!error.isOk()) {
             return;
         }
-        *outChain = certChain;
+        *chain = ::android::security::keymaster::KeymasterCertificateChain(certChain);
     };
     KeyStoreServiceReturnCode attestationRc =
-            KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), attestHidlCb));
+        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;
+        *aidl_return = static_cast<int32_t>(attestationRc);
+        return Status::ok();
     }
     if (!error.isOk()) {
-        return error;
+        *aidl_return = static_cast<int32_t>(error);
+        return Status::ok();
     }
-    return deletionRc;
+    *aidl_return = static_cast<int32_t>(deletionRc);
+    return Status::ok();
 }
 
-KeyStoreServiceReturnCode KeyStoreService::onDeviceOffBody() {
+Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) {
     // TODO(tuckeris): add permission check.  This should be callable from ClockworkHome only.
     mAuthTokenTable.onDeviceOffBody();
-    return ResponseCode::NO_ERROR;
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+    return Status::ok();
+}
+
+#define AIDL_RETURN(rc)                                                                            \
+    (*_aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(rc)), Status::ok())
+
+Status KeyStoreService::importWrappedKey(
+    const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey,
+    const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey,
+    const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid,
+    ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* _aidl_return) {
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    if (!checkBinderPermission(P_INSERT, callingUid)) {
+        return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
+    }
+
+    Blob wrappingKeyBlob;
+    String8 wrappingKeyName8(wrappingKeyAlias);
+    KeyStoreServiceReturnCode rc =
+        mKeyStore->getKeyForName(&wrappingKeyBlob, wrappingKeyName8, callingUid, TYPE_KEYMASTER_10);
+    if (!rc.isOk()) {
+        return AIDL_RETURN(rc);
+    }
+
+    SecurityLevel securityLevel = wrappingKeyBlob.getSecurityLevel();
+    auto dev = mKeyStore->getDevice(securityLevel);
+    if (!dev) {
+        return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+    }
+
+    auto hidlWrappingKey = blob2hidlVec(wrappingKeyBlob);
+    String8 wrappedKeyAlias8(wrappedKeyAlias);
+
+    KeyStoreServiceReturnCode error;
+
+    auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& keyBlob,
+                      const KeyCharacteristics& keyCharacteristics) {
+        error = ret;
+        if (!error.isOk()) {
+            return;
+        }
+        if (outCharacteristics) {
+            *outCharacteristics =
+                ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
+        }
+
+        // Write the key:
+        String8 filename(
+            mKeyStore->getKeyNameForUidWithDir(wrappedKeyAlias8, callingUid, ::TYPE_KEYMASTER_10));
+
+        Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
+        ksBlob.setSecurityLevel(securityLevel);
+
+        if (containsTag(keyCharacteristics.hardwareEnforced, Tag::USER_SECURE_ID)) {
+            ksBlob.setSuperEncrypted(true);
+        }
+
+        error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(callingUid));
+    };
+
+    rc = KS_HANDLE_HIDL_ERROR(dev->importWrappedKey(wrappedKey, hidlWrappingKey, maskingKey,
+                                                    params.getParameters(), rootSid, fingerprintSid,
+                                                    hidlCb));
+
+    // possible hidl error
+    if (!rc.isOk()) {
+        return AIDL_RETURN(rc);
+    }
+    // now check error from callback
+    if (!error.isOk()) {
+        return AIDL_RETURN(error);
+    }
+
+    // Write the characteristics:
+    String8 cFilename(mKeyStore->getKeyNameForUidWithDir(wrappedKeyAlias8, callingUid,
+                                                         ::TYPE_KEY_CHARACTERISTICS));
+
+    AuthorizationSet opParams = params.getParameters();
+    std::stringstream kcStream;
+    opParams.Serialize(&kcStream);
+    if (kcStream.bad()) {
+        return AIDL_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.setSecurityLevel(securityLevel);
+
+    return AIDL_RETURN(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(callingUid)));
+}
+
+Status KeyStoreService::presentConfirmationPrompt(const sp<IBinder>& listener,
+                                                  const String16& promptText,
+                                                  const ::std::vector<uint8_t>& extraData,
+                                                  const String16& locale, int32_t uiOptionsAsFlags,
+                                                  int32_t* aidl_return) {
+    return mConfirmationManager->presentConfirmationPrompt(listener, promptText, extraData, locale,
+                                                           uiOptionsAsFlags, aidl_return);
+}
+
+Status KeyStoreService::cancelConfirmationPrompt(const sp<IBinder>& listener,
+                                                 int32_t* aidl_return) {
+    return mConfirmationManager->cancelConfirmationPrompt(listener, aidl_return);
+}
+
+Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) {
+    return mConfirmationManager->isConfirmationPromptSupported(aidl_return);
 }
 
 /**
@@ -1537,7 +1885,8 @@
     size_t op_count_before_abort = mOperationMap.getOperationCount();
     // We mostly ignore errors from abort() because all we care about is whether at least
     // one operation has been removed.
-    int abort_error = abort(oldest);
+    int32_t abort_error;
+    abort(oldest, &abort_error);
     if (mOperationMap.getOperationCount() >= op_count_before_abort) {
         ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
         return false;
@@ -1639,14 +1988,13 @@
 }
 
 /**
- * Check that all KeyParameter's provided by the application are
- * allowed. Any parameter that keystore adds itself should be disallowed here.
+ * Check that all KeyParameters provided by the application are allowed. Any parameter that keystore
+ * adds itself should be disallowed here.
  */
 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:
@@ -1657,14 +2005,14 @@
 }
 
 ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>& key,
-                                                       km_device_t* dev,
+                                                       sp<Keymaster>* dev,
                                                        const AuthorizationSet& params,
                                                        KeyCharacteristics* out) {
-    hidl_vec<uint8_t> appId;
-    hidl_vec<uint8_t> appData;
+    ::std::vector<uint8_t> clientId;
+    ::std::vector<uint8_t> appData;
     for (auto param : params) {
         if (param.tag == Tag::APPLICATION_ID) {
-            appId = authorizationValue(TAG_APPLICATION_ID, param).value();
+            clientId = authorizationValue(TAG_APPLICATION_ID, param).value();
         } else if (param.tag == Tag::APPLICATION_DATA) {
             appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
         }
@@ -1679,7 +2027,8 @@
         if (out) *out = keyCharacteristics;
     };
 
-    ErrorCode rc = KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, appId, appData, hidlCb));
+    ErrorCode rc =
+        KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, clientId, appData, hidlCb));
     if (rc != ErrorCode::OK) {
         return rc;
     }
@@ -1696,36 +2045,44 @@
  *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
  *         token for the operation
  */
-KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
-                                                        uint64_t handle, KeyPurpose purpose,
-                                                        const HardwareAuthToken** authToken,
-                                                        bool failOnTokenMissing) {
+std::pair<KeyStoreServiceReturnCode, HardwareAuthToken>
+KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle,
+                              KeyPurpose purpose, bool failOnTokenMissing) {
 
-    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.teeEnforced.size(); i++) {
-        allCharacteristics.push_back(characteristics.teeEnforced[i]);
-    }
-    AuthTokenTable::Error err =
-        mAuthTokenTable.FindAuthorization(allCharacteristics, purpose, handle, authToken);
+    AuthorizationSet allCharacteristics(characteristics.softwareEnforced);
+    allCharacteristics.append(characteristics.hardwareEnforced.begin(),
+                              characteristics.hardwareEnforced.end());
+
+    const HardwareAuthToken* authToken = nullptr;
+    AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
+        allCharacteristics, static_cast<KeyPurpose>(purpose), handle, &authToken);
+
+    KeyStoreServiceReturnCode rc;
+
     switch (err) {
     case AuthTokenTable::OK:
     case AuthTokenTable::AUTH_NOT_REQUIRED:
-        return ResponseCode::NO_ERROR;
+        rc = ResponseCode::NO_ERROR;
+        break;
+
     case AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
     case AuthTokenTable::AUTH_TOKEN_EXPIRED:
     case AuthTokenTable::AUTH_TOKEN_WRONG_SID:
-        ALOGE("getAuthToken failed: %d", err); //STOPSHIP: debug only, to be removed
-        return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+        ALOGE("getAuthToken failed: %d", err);  // STOPSHIP: debug only, to be removed
+        rc = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+        break;
+
     case AuthTokenTable::OP_HANDLE_REQUIRED:
-        return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
-                                  : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
+        rc = failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
+                                : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
+        break;
+
     default:
         ALOGE("Unexpected FindAuthorization return value %d", err);
-        return ErrorCode::INVALID_ARGUMENT;
+        rc = ErrorCode::INVALID_ARGUMENT;
     }
+
+    return {rc, authToken ? std::move(*authToken) : HardwareAuthToken()};
 }
 
 /**
@@ -1739,29 +2096,23 @@
  *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
  *         operation token.
  */
-KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
-                                                                         AuthorizationSet* params) {
-    const HardwareAuthToken* authToken = nullptr;
-    mOperationMap.getOperationAuthToken(token, &authToken);
-    if (!authToken) {
-        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 ErrorCode::INVALID_OPERATION_HANDLE;
-        }
-        auto result = getAuthToken(*characteristics, handle, purpose, &authToken);
-        if (!result.isOk()) {
-            return result;
-        }
-        if (authToken) {
-            mOperationMap.setOperationAuthToken(token, authToken);
-        }
+std::pair<KeyStoreServiceReturnCode, const HardwareAuthToken&>
+KeyStoreService::getOperationAuthTokenIfNeeded(const sp<IBinder>& token) {
+    static HardwareAuthToken emptyToken = {};
+
+    auto getOpResult = mOperationMap.getOperation(token);
+    if (!getOpResult.isOk()) return {ErrorCode::INVALID_OPERATION_HANDLE, emptyToken};
+    const auto& op = getOpResult.value();
+
+    if (!op.hasAuthToken()) {
+        KeyStoreServiceReturnCode rc;
+        HardwareAuthToken found;
+        std::tie(rc, found) = getAuthToken(op.characteristics, op.handle, op.purpose);
+        if (!rc.isOk()) return {rc, emptyToken};
+        mOperationMap.setOperationAuthToken(token, std::move(found));
     }
-    addAuthTokenToParams(params, authToken);
-    return ResponseCode::NO_ERROR;
+
+    return {ResponseCode::NO_ERROR, op.authToken};
 }
 
 /**
@@ -1769,21 +2120,19 @@
  * preserved and keymaster errors become SYSTEM_ERRORs
  */
 KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
-    if (result > 0) {
-        return static_cast<ResponseCode>(result);
-    }
+    if (result > 0) return static_cast<ResponseCode>(result);
     return ResponseCode::SYSTEM_ERROR;
 }
 
-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();
+static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
+    const ::android::security::keymaster::KeyCharacteristics& characteristics) {
+    for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
+        auto algo = authorizationValue(TAG_ALGORITHM, param);
+        if (algo.isOk()) return algo;
     }
-    for (size_t i = 0; i < characteristics.softwareEnforced.size(); ++i) {
-        auto algo = authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced[i]);
-        if (algo.isOk()) return algo.value();
+    for (const auto& param : characteristics.softwareEnforced.getParameters()) {
+        auto algo = authorizationValue(TAG_ALGORITHM, param);
+        if (algo.isOk()) return algo;
     }
     return {};
 }
@@ -1794,9 +2143,11 @@
     params->push_back(TAG_PADDING, PaddingMode::NONE);
 
     // Look up the algorithm of the key.
-    KeyCharacteristics characteristics;
-    auto rc = getKeyCharacteristics(name, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF,
-                                    &characteristics);
+    ::android::security::keymaster::KeyCharacteristics characteristics;
+    int32_t result;
+    auto rc = getKeyCharacteristics(name, ::android::security::keymaster::KeymasterBlob(),
+                                    ::android::security::keymaster::KeymasterBlob(), UID_SELF,
+                                    &characteristics, &result);
     if (!rc.isOk()) {
         ALOGE("Failed to get key characteristics");
         return;
@@ -1822,8 +2173,8 @@
     sp<IBinder> appToken(new BBinder);
     sp<IBinder> token;
 
-    begin(appToken, name, purpose, true, inArgs.hidl_data(), hidl_vec<uint8_t>(), UID_SELF,
-          &result);
+    begin(appToken, name, static_cast<int32_t>(purpose), true,
+          KeymasterArguments(inArgs.hidl_data()), ::std::vector<uint8_t>(), UID_SELF, &result);
     if (!result.resultCode.isOk()) {
         if (result.resultCode == ResponseCode::KEY_NOT_FOUND) {
             ALOGW("Key not found");
@@ -1839,7 +2190,7 @@
     hidl_vec<uint8_t> data_view;
     do {
         data_view.setToExternal(const_cast<uint8_t*>(&data[consumed]), data.size() - consumed);
-        update(token, inArgs.hidl_data(), data_view, &result);
+        update(token, KeymasterArguments(inArgs.hidl_data()), data_view, &result);
         if (result.resultCode != ResponseCode::NO_ERROR) {
             ALOGW("Error in update: %d", int32_t(result.resultCode));
             return translateResultToLegacyResult(result.resultCode);
@@ -1856,7 +2207,8 @@
         return ResponseCode::SYSTEM_ERROR;
     }
 
-    finish(token, inArgs.hidl_data(), signature, hidl_vec<uint8_t>(), &result);
+    finish(token, KeymasterArguments(inArgs.hidl_data()), signature, ::std::vector<uint8_t>(),
+           &result);
     if (result.resultCode != ResponseCode::NO_ERROR) {
         ALOGW("Error in finish: %d", int32_t(result.resultCode));
         return translateResultToLegacyResult(result.resultCode);
@@ -1879,19 +2231,23 @@
                                                           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);
+    KeyStoreServiceReturnCode responseCode =
+        mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
     if (responseCode != ResponseCode::NO_ERROR) {
         return responseCode;
     }
     ALOGI("upgradeKeyBlob %s %d", name8.string(), uid);
 
     auto hidlKey = blob2hidlVec(*blob);
-    auto& dev = mKeyStore->getDevice(*blob);
+    auto dev = mKeyStore->getDevice(*blob);
 
     KeyStoreServiceReturnCode error;
-    auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+    auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& upgradedKeyBlob) {
         error = ret;
         if (!error.isOk()) {
+            if (error == ErrorCode::INVALID_KEY_BLOB) {
+                log_key_integrity_violation(name8, uid);
+            }
             return;
         }
 
@@ -1908,7 +2264,7 @@
 
         Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
                      0 /* infoLength */, ::TYPE_KEYMASTER_10);
-        newBlob.setFallback(blob->isFallback());
+        newBlob.setSecurityLevel(blob->getSecurityLevel());
         newBlob.setEncrypted(blob->isEncrypted());
         newBlob.setSuperEncrypted(blob->isSuperEncrypted());
         newBlob.setCriticalToDeviceEncryption(blob->isCriticalToDeviceEncryption());
@@ -1932,4 +2288,15 @@
     return error;
 }
 
+Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
+                                                    int32_t* aidl_return) {
+    enforcement_policy.set_device_locked(isShowing, userId);
+    if (!isShowing) {
+        mActiveUserId = userId;
+    }
+    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+
+    return Status::ok();
+}
+
 }  // namespace keystore
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
index 4060bd1..0056342 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -17,59 +17,67 @@
 #ifndef KEYSTORE_KEYSTORE_SERVICE_H_
 #define KEYSTORE_KEYSTORE_SERVICE_H_
 
-#include <keystore/IKeystoreService.h>
-
-#include <keystore/authorization_set.h>
+#include <android/security/BnKeystoreService.h>
 
 #include "auth_token_table.h"
-#include "keystore.h"
+#include "confirmation_manager.h"
+
+#include "KeyStore.h"
 #include "keystore_keymaster_enforcement.h"
 #include "operation.h"
 #include "permissions.h"
 
 namespace keystore {
 
-class KeyStoreService : public android::BnKeystoreService, public android::IBinder::DeathRecipient {
-    typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
-
+// Class provides implementation for generated BnKeystoreService.h based on
+// gen/aidl/android/security/BnKeystoreService.h generated from
+// java/android/security/IKeystoreService.aidl Note that all generated methods return binder::Status
+// and use last arguments to send actual result to the caller. Private methods don't need to handle
+// binder::Status. Input parameters cannot be null unless annotated with @nullable in .aidl file.
+class KeyStoreService : public android::security::BnKeystoreService,
+                        android::IBinder::DeathRecipient {
   public:
-    explicit KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
+    explicit KeyStoreService(KeyStore* keyStore)
+        : mKeyStore(keyStore), mOperationMap(this),
+          mConfirmationManager(new ConfirmationManager(this)), mActiveUserId(0) {}
+    virtual ~KeyStoreService() = default;
 
     void binderDied(const android::wp<android::IBinder>& who);
 
-    KeyStoreServiceReturnCode getState(int32_t userId) override;
-
-    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;
-
-    KeyStoreServiceReturnCode reset() override;
-
-    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;
-
-    KeyStoreServiceReturnCode lock(int32_t userId) override;
-    KeyStoreServiceReturnCode unlock(int32_t userId, const android::String16& pw) override;
-
-    bool isEmpty(int32_t userId) override;
-
-    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;
-
+    ::android::binder::Status getState(int32_t userId, int32_t* _aidl_return) override;
+    ::android::binder::Status get(const ::android::String16& name, int32_t uid,
+                                  ::std::vector<uint8_t>* _aidl_return) override;
+    ::android::binder::Status insert(const ::android::String16& name,
+                                     const ::std::vector<uint8_t>& item, int32_t uid, int32_t flags,
+                                     int32_t* _aidl_return) override;
+    ::android::binder::Status del(const ::android::String16& name, int32_t uid,
+                                  int32_t* _aidl_return) override;
+    ::android::binder::Status exist(const ::android::String16& name, int32_t uid,
+                                    int32_t* _aidl_return) override;
+    ::android::binder::Status list(const ::android::String16& namePrefix, int32_t uid,
+                                   ::std::vector<::android::String16>* _aidl_return) override;
+    ::android::binder::Status reset(int32_t* _aidl_return) override;
+    ::android::binder::Status onUserPasswordChanged(int32_t userId,
+                                                    const ::android::String16& newPassword,
+                                                    int32_t* _aidl_return) override;
+    ::android::binder::Status lock(int32_t userId, int32_t* _aidl_return) override;
+    ::android::binder::Status unlock(int32_t userId, const ::android::String16& userPassword,
+                                     int32_t* _aidl_return) override;
+    ::android::binder::Status isEmpty(int32_t userId, int32_t* _aidl_return) override;
+    ::android::binder::Status generate(const ::android::String16& name, int32_t uid,
+                                       int32_t keyType, int32_t keySize, int32_t flags,
+                                       const ::android::security::KeystoreArguments& args,
+                                       int32_t* _aidl_return) override;
+    ::android::binder::Status import_key(const ::android::String16& name,
+                                         const ::std::vector<uint8_t>& data, int32_t uid,
+                                         int32_t flags, int32_t* _aidl_return) override;
+    ::android::binder::Status sign(const ::android::String16& name,
+                                   const ::std::vector<uint8_t>& data,
+                                   ::std::vector<uint8_t>* _aidl_return) override;
+    ::android::binder::Status verify(const ::android::String16& name,
+                                     const ::std::vector<uint8_t>& data,
+                                     const ::std::vector<uint8_t>& signature,
+                                     int32_t* _aidl_return) override;
     /*
      * TODO: The abstraction between things stored in hardware and regular blobs
      * of data stored on the filesystem should be moved down to keystore itself.
@@ -81,60 +89,96 @@
      * "del_key" since the Java code doesn't really communicate what it's
      * intentions are.
      */
-    KeyStoreServiceReturnCode get_pubkey(const android::String16& name,
-                                         hidl_vec<uint8_t>* pubKey) override;
+    ::android::binder::Status get_pubkey(const ::android::String16& name,
+                                         ::std::vector<uint8_t>* _aidl_return) override;
+    ::android::binder::Status grant(const ::android::String16& name, int32_t granteeUid,
+                                    ::android::String16* _aidl_return) override;
+    ::android::binder::Status ungrant(const ::android::String16& name, int32_t granteeUid,
+                                      int32_t* _aidl_return) override;
+    ::android::binder::Status getmtime(const ::android::String16& name, int32_t uid,
+                                       int64_t* _aidl_return) override;
+    ::android::binder::Status is_hardware_backed(const ::android::String16& string,
+                                                 int32_t* _aidl_return) override;
+    ::android::binder::Status clear_uid(int64_t uid, int32_t* _aidl_return) override;
+    ::android::binder::Status addRngEntropy(const ::std::vector<uint8_t>& data, int32_t flags,
+                                            int32_t* _aidl_return) override;
+    ::android::binder::Status
+    generateKey(const ::android::String16& alias,
+                const ::android::security::keymaster::KeymasterArguments& arguments,
+                const ::std::vector<uint8_t>& entropy, int32_t uid, int32_t flags,
+                ::android::security::keymaster::KeyCharacteristics* characteristics,
+                int32_t* _aidl_return) override;
+    ::android::binder::Status
+    getKeyCharacteristics(const ::android::String16& alias,
+                          const ::android::security::keymaster::KeymasterBlob& clientId,
+                          const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid,
+                          ::android::security::keymaster::KeyCharacteristics* characteristics,
+                          int32_t* _aidl_return) override;
+    ::android::binder::Status
+    importKey(const ::android::String16& alias,
+              const ::android::security::keymaster::KeymasterArguments& arguments, int32_t format,
+              const ::std::vector<uint8_t>& keyData, int32_t uid, int32_t flags,
+              ::android::security::keymaster::KeyCharacteristics* characteristics,
+              int32_t* _aidl_return) override;
+    ::android::binder::Status
+    exportKey(const ::android::String16& alias, int32_t format,
+              const ::android::security::keymaster::KeymasterBlob& clientId,
+              const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid,
+              ::android::security::keymaster::ExportResult* _aidl_return) override;
+    ::android::binder::Status
+    begin(const ::android::sp<::android::IBinder>& appToken, const ::android::String16& alias,
+          int32_t purpose, bool pruneable,
+          const ::android::security::keymaster::KeymasterArguments& params,
+          const ::std::vector<uint8_t>& entropy, int32_t uid,
+          ::android::security::keymaster::OperationResult* _aidl_return) override;
+    ::android::binder::Status
+    update(const ::android::sp<::android::IBinder>& token,
+           const ::android::security::keymaster::KeymasterArguments& params,
+           const ::std::vector<uint8_t>& input,
+           ::android::security::keymaster::OperationResult* _aidl_return) override;
+    ::android::binder::Status
+    finish(const ::android::sp<::android::IBinder>& token,
+           const ::android::security::keymaster::KeymasterArguments& params,
+           const ::std::vector<uint8_t>& signature, const ::std::vector<uint8_t>& entropy,
+           ::android::security::keymaster::OperationResult* _aidl_return) override;
+    ::android::binder::Status abort(const ::android::sp<::android::IBinder>& handle,
+                                    int32_t* _aidl_return) override;
+    ::android::binder::Status isOperationAuthorized(const ::android::sp<::android::IBinder>& token,
+                                                    bool* _aidl_return) override;
+    ::android::binder::Status addAuthToken(const ::std::vector<uint8_t>& authToken,
+                                           int32_t* _aidl_return) override;
+    ::android::binder::Status onUserAdded(int32_t userId, int32_t parentId,
+                                          int32_t* _aidl_return) override;
+    ::android::binder::Status onUserRemoved(int32_t userId, int32_t* _aidl_return) override;
+    ::android::binder::Status
+    attestKey(const ::android::String16& alias,
+              const ::android::security::keymaster::KeymasterArguments& params,
+              ::android::security::keymaster::KeymasterCertificateChain* chain,
+              int32_t* _aidl_return) override;
+    ::android::binder::Status
+    attestDeviceIds(const ::android::security::keymaster::KeymasterArguments& params,
+                    ::android::security::keymaster::KeymasterCertificateChain* chain,
+                    int32_t* _aidl_return) override;
+    ::android::binder::Status onDeviceOffBody(int32_t* _aidl_return) override;
 
-    android::String16 grant(const android::String16& name, int32_t granteeUid) override;
-    KeyStoreServiceReturnCode ungrant(const android::String16& name, int32_t granteeUid) override;
+    ::android::binder::Status importWrappedKey(
+        const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey,
+        const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey,
+        const ::android::security::keymaster::KeymasterArguments& params, int64_t rootSid,
+        int64_t fingerprintSid, ::android::security::keymaster::KeyCharacteristics* characteristics,
+        int32_t* _aidl_return) override;
 
-    int64_t getmtime(const android::String16& name, int32_t uid) override;
+    ::android::binder::Status presentConfirmationPrompt(
+        const ::android::sp<::android::IBinder>& listener, const ::android::String16& promptText,
+        const ::std::vector<uint8_t>& extraData, const ::android::String16& locale,
+        int32_t uiOptionsAsFlags, int32_t* _aidl_return) override;
+    ::android::binder::Status
+    cancelConfirmationPrompt(const ::android::sp<::android::IBinder>& listener,
+                             int32_t* _aidl_return) override;
+    ::android::binder::Status isConfirmationPromptSupported(bool* _aidl_return) override;
 
-    KeyStoreServiceReturnCode duplicate(const android::String16& srcKey, int32_t srcUid,
-                                        const android::String16& destKey, int32_t destUid) override;
-
-    int32_t is_hardware_backed(const android::String16& keyType) override;
-
-    KeyStoreServiceReturnCode clear_uid(int64_t targetUid64) override;
-
-    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<android::IBinder>& token) override;
-
-    KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override;
-
-    KeyStoreServiceReturnCode attestKey(const android::String16& name,
-                                        const hidl_vec<KeyParameter>& params,
-                                        hidl_vec<hidl_vec<uint8_t>>* outChain) override;
-
-    KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params,
-                                              hidl_vec<hidl_vec<uint8_t>>* outChain) override;
-
-    KeyStoreServiceReturnCode onDeviceOffBody() override;
+    ::android::binder::Status onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
+                                                          int32_t* _aidl_return);
 
   private:
     static const int32_t UID_SELF = -1;
@@ -191,37 +235,34 @@
      */
     bool checkAllowedOperationParams(const hidl_vec<KeyParameter>& params);
 
-    ErrorCode getOperationCharacteristics(const hidl_vec<uint8_t>& key, km_device_t* dev,
+    ErrorCode getOperationCharacteristics(const hidl_vec<uint8_t>& key, sp<Keymaster>* dev,
                                           const AuthorizationSet& params, KeyCharacteristics* out);
 
     /**
      * Get the auth token for this operation from the auth token table.
      *
-     * Returns ::NO_ERROR if the auth token was set or none was required.
-     *         ::OP_AUTH_NEEDED if it is a per op authorization, no
-     *         authorization token exists for that operation and
-     *         failOnTokenMissing is false.
-     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
-     *         token for the operation
+     * Returns NO_ERROR if the auth token was found or none was required.  If not needed, the
+     *             token will be empty (which keymaster interprets as no auth token).
+     *         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
      */
-    KeyStoreServiceReturnCode getAuthToken(const KeyCharacteristics& characteristics,
-                                           uint64_t handle, KeyPurpose purpose,
-                                           const HardwareAuthToken** authToken,
-                                           bool failOnTokenMissing = true);
+    std::pair<KeyStoreServiceReturnCode, HardwareAuthToken>
+    getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose,
+                 bool failOnTokenMissing = true);
 
     /**
-     * Add the auth token for the operation to the param list if the operation
-     * requires authorization. Uses the cached result in the OperationMap if available
-     * otherwise gets the token from the AuthTokenTable and caches the result.
+     * Get the auth token for the operation if the operation requires authorization. Uses the cached
+     * result in the OperationMap if available otherwise gets the token from the AuthTokenTable and
+     * caches the result.
      *
-     * Returns ::NO_ERROR if the auth token was added or not needed.
-     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
-     *         authenticated.
-     *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
-     *         operation token.
+     * Returns NO_ERROR if the auth token was found or not needed.  If not needed, the token will
+     *             be empty (which keymaster interprets as no auth token).
+     *         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.
      */
-    KeyStoreServiceReturnCode addOperationAuthTokenIfNeeded(const sp<android::IBinder>& token,
-                                                            AuthorizationSet* params);
+    std::pair<KeyStoreServiceReturnCode, const HardwareAuthToken&>
+    getOperationAuthTokenIfNeeded(const sp<android::IBinder>& token);
 
     /**
      * Translate a result value to a legacy return value. All keystore errors are
@@ -248,10 +289,18 @@
     KeyStoreServiceReturnCode upgradeKeyBlob(const android::String16& name, uid_t targetUid,
                                              const AuthorizationSet& params, Blob* blob);
 
-    ::KeyStore* mKeyStore;
+    /**
+     * Adds a Confirmation Token to the key parameters if needed.
+     */
+    void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics,
+                                         std::vector<KeyParameter>* params);
+
+    KeyStore* mKeyStore;
     OperationMap mOperationMap;
+    android::sp<ConfirmationManager> mConfirmationManager;
     keystore::AuthTokenTable mAuthTokenTable;
     KeystoreKeymasterEnforcement enforcement_policy;
+    int32_t mActiveUserId;
 };
 
 };  // namespace keystore
diff --git a/keystore/keymaster_enforcement.cpp b/keystore/keymaster_enforcement.cpp
index 4cee57d..5a6e591 100644
--- a/keystore/keymaster_enforcement.cpp
+++ b/keystore/keymaster_enforcement.cpp
@@ -29,6 +29,8 @@
 #include <hardware/hw_auth_token.h>
 #include <list>
 
+#include <keystore/keystore_hidl_support.h>
+
 namespace keystore {
 
 class AccessTimeMap {
@@ -115,6 +117,7 @@
 ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
                                                    const AuthorizationSet& auth_set,
                                                    const AuthorizationSet& operation_params,
+                                                   const HardwareAuthToken& auth_token,
                                                    uint64_t op_handle, bool is_begin_operation) {
     if (is_public_key_algorithm(auth_set)) {
         switch (purpose) {
@@ -125,23 +128,23 @@
 
         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);
+        return AuthorizeBegin(purpose, keyid, auth_set, operation_params, auth_token);
     else
-        return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+        return AuthorizeUpdateOrFinish(auth_set, auth_token, 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,
+                                                        const HardwareAuthToken& auth_token,
                                                         uint64_t op_handle) {
     int auth_type_index = -1;
     for (size_t pos = 0; pos < auth_set.size(); ++pos) {
@@ -174,9 +177,9 @@
         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 */))
+            if (auth_token.mac.size() &&
+                AuthTokenMatches(auth_set, auth_token, user_secure_id.value(), auth_type_index,
+                                 auth_timeout_index, op_handle, false /* is_begin_operation */))
                 return ErrorCode::OK;
         }
     }
@@ -188,7 +191,8 @@
 
 ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
                                                const AuthorizationSet& auth_set,
-                                               const AuthorizationSet& operation_params) {
+                                               const AuthorizationSet& operation_params,
+                                               NullOr<const HardwareAuthToken&> auth_token) {
     // Find some entries that may be needed to handle KM_TAG_USER_SECURE_ID
     int auth_timeout_index = -1;
     int auth_type_index = -1;
@@ -219,6 +223,8 @@
     bool caller_nonce_authorized_by_key = false;
     bool authentication_required = false;
     bool auth_token_matched = false;
+    bool unlocked_device_required = false;
+    int32_t user_id = -1;
 
     for (auto& param : auth_set) {
 
@@ -270,21 +276,28 @@
             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 */,
+                if (secure_id.isOk() && auth_token.isOk() &&
+                    AuthTokenMatches(auth_set, auth_token.value(), secure_id.value(),
+                                     auth_type_index, auth_timeout_index, 0 /* op_handle */,
                                      true /* is_begin_operation */))
                     auth_token_matched = true;
             }
             break;
 
+        case Tag::USER_ID:
+            user_id = authorizationValue(TAG_USER_ID, param).value();
+            break;
+
         case Tag::CALLER_NONCE:
             caller_nonce_authorized_by_key = true;
             break;
 
+        case Tag::UNLOCKED_DEVICE_REQUIRED:
+            unlocked_device_required = 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:
@@ -309,21 +322,18 @@
         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:
+        case Tag::ROLLBACK_RESISTANCE:
 
         /* Tags handled when KM_TAG_USER_SECURE_ID is handled */
         case Tag::NO_AUTH_REQUIRED:
@@ -334,20 +344,21 @@
         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::BOOT_PATCHLEVEL:
         case Tag::OS_PATCHLEVEL:
-
-        /* Ignored pending removal */
-        case Tag::USER_ID:
-        case Tag::ALL_USERS:
+        case Tag::OS_VERSION:
+        case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
+        case Tag::VENDOR_PATCHLEVEL:
 
         /* 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:
+        case Tag::HARDWARE_TYPE:
+        case Tag::TRUSTED_CONFIRMATION_REQUIRED:
+        case Tag::CONFIRMATION_TOKEN:
             break;
 
         case Tag::BOOTLOADER_ONLY:
@@ -355,6 +366,19 @@
         }
     }
 
+    if (unlocked_device_required && is_device_locked(user_id)) {
+        switch (purpose) {
+        case KeyPurpose::ENCRYPT:
+        case KeyPurpose::VERIFY:
+            /* These are okay */
+            break;
+        case KeyPurpose::DECRYPT:
+        case KeyPurpose::SIGN:
+        case KeyPurpose::WRAP_KEY:
+            return ErrorCode::DEVICE_LOCKED;
+        };
+    }
+
     if (authentication_required && !auth_token_matched) {
         ALOGE("Auth required but no matching auth token found");
         return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
@@ -463,7 +487,7 @@
 }
 
 bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
-                                            const AuthorizationSet& operation_params,
+                                            const HardwareAuthToken& auth_token,
                                             const uint64_t user_secure_id,
                                             const int auth_type_index, const int auth_timeout_index,
                                             const uint64_t op_handle,
@@ -471,26 +495,6 @@
     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;
@@ -502,9 +506,9 @@
         return false;
     }
 
-    if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
+    if (user_secure_id != auth_token.userId && user_secure_id != auth_token.authenticatorId) {
         ALOGI("Auth token SIDs %" PRIu64 " and %" PRIu64 " do not match key SID %" PRIu64,
-              auth_token.user_id, auth_token.authenticator_id, user_secure_id);
+              auth_token.userId, auth_token.authenticatorId, user_secure_id);
         return false;
     }
 
@@ -513,19 +517,18 @@
         return false;
     }
 
-    assert(auth_set[auth_type_index].tag == KM_TAG_USER_AUTH_TYPE);
+    assert(auth_set[auth_type_index].tag == 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) {
+    if ((uint32_t(key_auth_type_mask.value()) & auth_token.authenticatorType) == 0) {
         ALOGE("Key requires match of auth type mask 0%uo, but token contained 0%uo",
-              key_auth_type_mask.value(), token_auth_type);
+              key_auth_type_mask.value(), auth_token.authenticatorType);
         return false;
     }
 
     if (auth_timeout_index != -1 && is_begin_operation) {
-        assert(auth_set[auth_timeout_index].tag == KM_TAG_AUTH_TIMEOUT);
+        assert(auth_set[auth_timeout_index].tag == TAG_AUTH_TIMEOUT);
         auto auth_token_timeout =
             authorizationValue(TAG_AUTH_TIMEOUT, auth_set[auth_timeout_index]);
         if (!auth_token_timeout.isOk()) return false;
diff --git a/keystore/keymaster_enforcement.h b/keystore/keymaster_enforcement.h
index 4f22f01..6e6c54f 100644
--- a/keystore/keymaster_enforcement.h
+++ b/keystore/keymaster_enforcement.h
@@ -19,7 +19,7 @@
 
 #include <stdio.h>
 
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
 
 namespace keystore {
 
@@ -51,7 +51,8 @@
      */
     ErrorCode AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
                                  const AuthorizationSet& auth_set,
-                                 const AuthorizationSet& operation_params, uint64_t op_handle,
+                                 const AuthorizationSet& operation_params,
+                                 const HardwareAuthToken& auth_token, uint64_t op_handle,
                                  bool is_begin_operation);
 
     /**
@@ -61,16 +62,17 @@
      */
     ErrorCode AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
                              const AuthorizationSet& auth_set,
-                             const AuthorizationSet& operation_params);
+                             const AuthorizationSet& operation_params,
+                             NullOr<const HardwareAuthToken&> auth_token);
 
     /**
      * 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);
+    ErrorCode AuthorizeUpdate(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token,
+                              uint64_t op_handle) {
+        return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle);
     }
 
     /**
@@ -78,9 +80,9 @@
      * 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);
+    ErrorCode AuthorizeFinish(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token,
+                              uint64_t op_handle) {
+        return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle);
     }
 
     /**
@@ -121,7 +123,7 @@
     /*
      * 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;
+    virtual bool auth_token_timed_out(const HardwareAuthToken& token, uint32_t timeout) const = 0;
 
     /*
      * Get current time in seconds from some starting point.  This value is used to compute relative
@@ -138,18 +140,23 @@
      * 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;
+    virtual bool ValidateTokenSignature(const HardwareAuthToken& token) const = 0;
+
+    /*
+     * Returns true if the device screen is currently locked for the specified user.
+     */
+    virtual bool is_device_locked(int32_t userId) const = 0;
 
   private:
     ErrorCode AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set,
-                                      const AuthorizationSet& operation_params, uint64_t op_handle);
+                                      const HardwareAuthToken& auth_token, 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;
+    bool AuthTokenMatches(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token,
+                          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_;
diff --git a/keystore/keystore.rc b/keystore/keystore.rc
index 5dac937..132039a 100644
--- a/keystore/keystore.rc
+++ b/keystore/keystore.rc
@@ -1,5 +1,5 @@
 service keystore /system/bin/keystore /data/misc/keystore
     class main
     user keystore
-    group keystore drmrpc readproc
+    group keystore drmrpc readproc log
     writepid /dev/cpuset/foreground/tasks
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.cpp b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
index 3137ae1..db9b983 100644
--- a/keystore/keystore_aidl_hidl_marshalling_utils.cpp
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
@@ -15,15 +15,21 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "KeystoreService"
-#include <utils/Log.h>
-
 #include "keystore_aidl_hidl_marshalling_utils.h"
+
+#include <keystore/ExportResult.h>
+#include <keystore/KeyCharacteristics.h>
+#include <keystore/KeymasterBlob.h>
+#include <keystore/KeymasterCertificateChain.h>
+#include <keystore/KeystoreArg.h>
+#include <keystore/keymaster_types.h>
 #include <keystore/keystore_hidl_support.h>
 
 namespace keystore {
 
+// reads byte[]
 hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in, bool inPlace) {
+
     ssize_t length = in.readInt32();
     if (length <= 0) {
         return {};
@@ -43,44 +49,23 @@
 
     if (!size) return ::android::OK;
 
-    return out->write(&blob[0], size);
+    return out->write(blob.data(), 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 {};
-    }
+android::status_t writeKeymasterBlob(const ::std::vector<int32_t>& blob, android::Parcel* out) {
 
-    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()));
+    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.value()[0], size);
+    return out->write(blob.data(), size);
 }
 
 NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) {
+    // Method must be in sync with KeymasterArgument.java
     if (in.readInt32() == 0) {
         return {};
     }
@@ -105,7 +90,7 @@
         break;
     case TagType::BIGNUM:
     case TagType::BYTES:
-        result.blob = readKeymasterBlob(in);
+        result.blob = readKeymasterBlob(in);  // byte array
         break;
     default:
         ALOGE("Unsupported KeyParameter tag %d", tag);
@@ -115,6 +100,9 @@
 }
 
 android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out) {
+    // Method must be in sync with with KeymasterArgument.java
+    // Presence flag must be written by caller.
+
     auto tag = param.tag;
     auto rc = out->writeInt32(uint32_t(tag));
     if (rc != ::android::OK) return rc;
@@ -146,7 +134,8 @@
 }
 
 hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in) {
-    ssize_t length = in.readInt32();
+
+    ssize_t length = in.readInt32();  // -1 for null
     size_t ulength = (size_t)length;
     if (length < 0) {
         ulength = 0;
@@ -171,7 +160,7 @@
     auto rc = out->writeInt32(size);
     if (rc != ::android::OK) return rc;
     for (int32_t i = 0; i < size; ++i) {
-        rc = out->writeInt32(1);
+        rc = out->writeInt32(1);  // writeTypedObject presence flag.
         if (rc != ::android::OK) return rc;
         rc = writeKeyParameterToParcel(params[i], out);
         if (rc != ::android::OK) return rc;
@@ -179,21 +168,6 @@
     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;
 
@@ -209,7 +183,7 @@
         result[i] = readKeymasterBlob(in);
     }
     return result;
-}
+};
 
 android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
                                                 android::Parcel* out) {
@@ -222,4 +196,63 @@
     }
     return rc;
 }
+
+};  // namespace keystore
+
+// Implementation for  keystore parcelables.
+// TODO: split implementation into separate classes
+namespace android {
+namespace security {
+namespace keymaster {
+
+using ::android::status_t;
+using ::keystore::keymaster::ErrorCode;
+
+ExportResult::ExportResult() : resultCode() {}
+
+ExportResult::~ExportResult() {}
+
+status_t ExportResult::readFromParcel(const Parcel* inn) {
+    const Parcel& in = *inn;
+    resultCode = ErrorCode(in.readInt32());
+    exportData = keystore::readKeymasterBlob(in);
+    return OK;
 }
+
+status_t ExportResult::writeToParcel(Parcel* out) const {
+    out->writeInt32(resultCode);
+    return keystore::writeKeymasterBlob(exportData, out);
+}
+
+status_t KeyCharacteristics::readFromParcel(const Parcel* in) {
+    softwareEnforced.readFromParcel(in);
+    return hardwareEnforced.readFromParcel(in);
+}
+
+status_t KeyCharacteristics::writeToParcel(Parcel* out) const {
+    softwareEnforced.writeToParcel(out);
+    return hardwareEnforced.writeToParcel(out);
+}
+
+status_t KeymasterBlob::readFromParcel(const Parcel* in) {
+    data_ = keystore::readKeymasterBlob(*in, true /* in place */);
+    return OK;
+}
+
+status_t KeymasterBlob::writeToParcel(Parcel* out) const {
+    return keystore::writeKeymasterBlob(data_, out);
+}
+
+status_t KeymasterCertificateChain::readFromParcel(const Parcel* in) {
+    chain = keystore::readCertificateChainFromParcel(*in);
+    return OK;
+}
+
+status_t KeymasterCertificateChain::writeToParcel(Parcel* out) const {
+    return keystore::writeCertificateChainToParcel(chain, out);
+}
+
+}  // namespace keymaster
+}  // namespace security
+
+}  // namespace android
diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.h b/keystore/keystore_aidl_hidl_marshalling_utils.h
index fcd02ae..13edbd2 100644
--- a/keystore/keystore_aidl_hidl_marshalling_utils.h
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.h
@@ -18,10 +18,12 @@
 #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>
 
+#include <binder/Parcel.h>
+
+#include <keystore/keymaster_types.h>
+
 namespace keystore {
 
 template <typename Fn, typename... Args>
@@ -71,13 +73,7 @@
 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
index 830482b..3d34ac5 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -34,7 +34,10 @@
 #include <keystore/KeyAttestationPackageInfo.h>
 #include <keystore/Signature.h>
 
+#include <private/android_filesystem_config.h> /* for AID_SYSTEM */
+
 #include <openssl/asn1t.h>
+#include <openssl/bn.h>
 #include <openssl/sha.h>
 
 #include <utils/String8.h>
@@ -43,7 +46,9 @@
 
 namespace {
 
-static std::vector<uint8_t> signature2SHA256(const content::pm::Signature& sig) {
+constexpr const char* kAttestationSystemPackageName = "AndroidSystem";
+
+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;
@@ -95,7 +100,8 @@
     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
 
 }  // namespace android
 
@@ -143,10 +149,20 @@
         return UNKNOWN_ERROR;
     }
 
-    if (!ASN1_INTEGER_set(attestation_package_info->version, pinfo.version_code())) {
+    BIGNUM* bn_version = BN_new();
+    if (bn_version == nullptr) {
+        return NO_MEMORY;
+    }
+    if (BN_set_u64(bn_version, static_cast<uint64_t>(pinfo.version_code())) != 1) {
+        BN_free(bn_version);
         return UNKNOWN_ERROR;
     }
-    return NO_ERROR;
+    status_t retval = NO_ERROR;
+    if (BN_to_ASN1_INTEGER(bn_version, attestation_package_info->version) == nullptr) {
+        retval = UNKNOWN_ERROR;
+    }
+    BN_free(bn_version);
+    return retval;
 }
 
 StatusOr<std::vector<uint8_t>>
@@ -226,15 +242,23 @@
 }  // 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;
+
+    if (uid == AID_SYSTEM) {
+        /* Use a fixed ID for system callers */
+        auto pinfo = std::make_unique<KeyAttestationPackageInfo>(
+            String16(kAttestationSystemPackageName), 1 /* version code */,
+            std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
+        key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
+    } else {
+        /* Get the attestation application ID from package manager */
+        auto& pm = KeyAttestationApplicationIdProvider::get();
+        auto status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+        if (!status.isOk()) {
+            ALOGE("package manager request for key attestation ID failed with: %s %d",
+                  status.exceptionMessage().string(), status.exceptionCode());
+            return FAILED_TRANSACTION;
+        }
     }
 
     /* DER encode the attestation application ID */
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index 24af024..1e100fc 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -18,8 +18,9 @@
 #include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
+#include <vector>
 
-#include <keystore/IKeystoreService.h>
+#include <android/security/IKeystoreService.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
@@ -27,6 +28,7 @@
 
 using namespace android;
 using namespace keystore;
+using android::security::IKeystoreService;
 
 static const char* responses[] = {
     NULL,
@@ -48,7 +50,8 @@
 #define NO_ARG_INT_RETURN(cmd) \
     do { \
         if (strcmp(argv[1], #cmd) == 0) { \
-            int32_t ret = service->cmd(); \
+            int32_t ret = -1; \
+            service->cmd(&ret); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -66,7 +69,8 @@
                 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                 return 1; \
             } \
-            int32_t ret = service->cmd(String16(argv[2])); \
+            int32_t ret = -1; \
+            service->cmd(String16(argv[2]), &ret); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -84,7 +88,8 @@
                 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                 return 1; \
             } \
-            int32_t ret = service->cmd(atoi(argv[2])); \
+            int32_t ret = -1; \
+            service->cmd(atoi(argv[2]), &ret); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -107,7 +112,8 @@
                 uid = atoi(argv[3]); \
                 fprintf(stderr, "Running as uid %d\n", uid); \
             } \
-            int32_t ret = service->cmd(String16(argv[2]), uid); \
+            int32_t ret = -1; \
+            service->cmd(String16(argv[2]), uid, &ret); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -125,18 +131,15 @@
                 fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
                 return 1; \
             } \
-            hidl_vec<uint8_t> data; \
+            std::vector<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); \
-            if (ret < 0) { \
-                fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
-                return 1; \
-            } else if (ret != ::NO_ERROR) { \
-                fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
+            ::android::binder::Status ret = service->cmd(String16(argv[2]), uid, &data); \
+            if (!ret.isOk()) { \
+                fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
                 return 1; \
             } else { \
                 fwrite(&data[0], data.size(), 1, stdout); \
@@ -146,7 +149,7 @@
         } \
     } while (0)
 
-#define STING_ARG_DATA_STDIN_INT_RETURN(cmd) \
+#define STRING_ARG_DATA_STDIN_INT_RETURN(cmd) \
     do { \
         if (strcmp(argv[1], #cmd) == 0) { \
             if (argc < 3) { \
@@ -156,7 +159,8 @@
             uint8_t* data; \
             size_t dataSize; \
             read_input(&data, &dataSize); \
-            int32_t ret = service->cmd(String16(argv[2]), data, dataSize); \
+            int32_t ret = -1; \
+            service->cmd(String16(argv[2]), data, dataSize, &ret); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -174,13 +178,10 @@
                 fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                 return 1; \
             } \
-            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; \
-            } else if (ret != ::NO_ERROR) { \
-                fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
+            std::vector<uint8_t> data; \
+            ::android::binder::Status ret = service->cmd(String16(argv[2]), &data); \
+            if (!ret.isOk()) { \
+                fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \
                 return 1; \
             } else { \
                 fwrite(&data[0], data.size(), 1, stdout); \
@@ -191,16 +192,14 @@
     } while (0)
 
 static int list(const sp<IKeystoreService>& service, const String16& name, int uid) {
-    Vector<String16> matches;
-    int32_t ret = service->list(name, uid, &matches);
-    if (ret < 0) {
-        fprintf(stderr, "list: could not connect: %d\n", ret);
-        return 1;
-    } else if (ret != ::NO_ERROR) {
-        fprintf(stderr, "list: %s (%d)\n", responses[ret], ret);
+    std::vector<String16> matches;
+    ::android::binder::Status ret = service->list(name, uid, &matches);
+
+    if (!ret.isOk()) {
+        fprintf(stderr, "list: exception (%d)\n", ret.exceptionCode());
         return 1;
     } else {
-        Vector<String16>::const_iterator it = matches.begin();
+        std::vector<String16>::const_iterator it = matches.begin();
         for (; it != matches.end(); ++it) {
             printf("%s\n", String8(*it).string());
         }
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 95fc491..6377ec1 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -17,18 +17,34 @@
 #include <string>
 #include <vector>
 
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_util.h"
-#include "keystore/authorization_set.h"
-#include "keystore/keymaster_tags.h"
-#include "keystore/keystore_client_impl.h"
+#include <base/command_line.h>
+#include <base/files/file_util.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_split.h>
+#include <base/strings/string_util.h>
+#include <base/strings/utf_string_conversions.h>
+#include <base/threading/platform_thread.h>
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_client_impl.h>
+
+#include <android/hardware/confirmationui/1.0/types.h>
+#include <android/security/BnConfirmationPromptCallback.h>
+#include <android/security/IKeystoreService.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+//#include <keystore/keystore.h>
 
 using base::CommandLine;
-using keystore::AuthorizationSet;
-//using keymaster::AuthorizationSetBuilder;
 using keystore::KeystoreClient;
 
+using android::sp;
+using android::String16;
+using android::security::IKeystoreService;
+using base::CommandLine;
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+
 namespace {
 using namespace keystore;
 
@@ -42,8 +58,8 @@
     printf("Usage: keystore_client_v2 <command> [options]\n");
     printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
            "          list-brillo-tests\n"
-           "          add-entropy --input=<entropy>\n"
-           "          generate --name=<key_name>\n"
+           "          add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
+           "          generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
            "          get-chars --name=<key_name>\n"
            "          export --name=<key_name>\n"
            "          delete --name=<key_name>\n"
@@ -51,18 +67,23 @@
            "          exists --name=<key_name>\n"
            "          list [--prefix=<key_name_prefix>]\n"
            "          sign-verify --name=<key_name>\n"
-           "          [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n");
+           "          [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
+           "                       [--seclevel=software|strongbox|tee(default)]\n"
+           "          confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
+           "                       --locale=<locale> [--ui_options=<list_of_ints>]\n"
+           "                       --cancel_after=<seconds>\n");
     exit(1);
 }
 
 std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
     return std::unique_ptr<KeystoreClient>(
-            static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
+        static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
 }
 
 void PrintTags(const AuthorizationSet& parameters) {
     for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
-        printf("  %s\n", stringifyTag(iter->tag));
+        auto tag_str = toString(iter->tag);
+        printf("  %s\n", tag_str.c_str());
     }
 }
 
@@ -78,8 +99,9 @@
     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    auto result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
-                                           &software_enforced_characteristics);
+    auto result =
+        keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics,
+                              &software_enforced_characteristics);
     const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
     if (!result.isOk()) {
         LOG(ERROR) << "Failed to generate key: " << result;
@@ -120,9 +142,7 @@
         .Padding(PaddingMode::RSA_PSS)
         .Authorization(TAG_NO_AUTH_REQUIRED);
     if (!sha256_only) {
-        parameters.Digest(Digest::SHA_2_224)
-            .Digest(Digest::SHA_2_384)
-            .Digest(Digest::SHA_2_512);
+        parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
     }
     return parameters;
 }
@@ -142,9 +162,7 @@
         .Digest(Digest::SHA_2_256)
         .Authorization(TAG_NO_AUTH_REQUIRED);
     if (!sha256_only) {
-        parameters.Digest(Digest::SHA_2_224)
-            .Digest(Digest::SHA_2_384)
-            .Digest(Digest::SHA_2_512);
+        parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
     }
     return parameters;
 }
@@ -205,7 +223,8 @@
     const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
     if (test_for_0_3) {
         printf("%s: Testing for keymaster v0.3. "
-               "This does not meet Brillo requirements.\n", kBoldYellowWarning);
+               "This does not meet Brillo requirements.\n",
+               kBoldYellowWarning);
     }
     int test_count = 0;
     int fail_count = 0;
@@ -259,14 +278,14 @@
     }
 }
 
-int AddEntropy(const std::string& input) {
+int AddEntropy(const std::string& input, int32_t flags) {
     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
-    int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
+    int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags);
     printf("AddEntropy: %d\n", result);
     return result;
 }
 
-int GenerateKey(const std::string& name) {
+int GenerateKey(const std::string& name, int32_t flags) {
     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
     AuthorizationSetBuilder params;
     params.RsaSigningKey(2048, 65537)
@@ -279,8 +298,8 @@
         .Authorization(TAG_NO_AUTH_REQUIRED);
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
-    auto result = keystore->generateKey(name, params, &hardware_enforced_characteristics,
-                                           &software_enforced_characteristics);
+    auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics,
+                                        &software_enforced_characteristics);
     printf("GenerateKey: %d\n", int32_t(result));
     if (result.isOk()) {
         PrintKeyCharacteristics(hardware_enforced_characteristics,
@@ -294,7 +313,7 @@
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
     auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
-                                                     &software_enforced_characteristics);
+                                                  &software_enforced_characteristics);
     printf("GetCharacteristics: %d\n", int32_t(result));
     if (result.isOk()) {
         PrintKeyCharacteristics(hardware_enforced_characteristics,
@@ -352,8 +371,8 @@
     sign_params.Digest(Digest::SHA_2_256);
     AuthorizationSet output_params;
     uint64_t handle;
-    auto result = keystore->beginOperation(KeyPurpose::SIGN, name, sign_params,
-                                              &output_params, &handle);
+    auto result =
+        keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle);
     if (!result.isOk()) {
         printf("Sign: BeginOperation failed: %d\n", int32_t(result));
         return result;
@@ -377,8 +396,8 @@
     // We have a signature, now verify it.
     std::string signature_to_verify = output_data;
     output_data.clear();
-    result = keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params,
-                                      &handle);
+    result =
+        keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle);
     if (!result.isOk()) {
         printf("Verify: BeginOperation failed: %d\n", int32_t(result));
         return result;
@@ -404,11 +423,11 @@
 }
 
 int Encrypt(const std::string& key_name, const std::string& input_filename,
-            const std::string& output_filename) {
+            const std::string& output_filename, int32_t flags) {
     std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
     std::string input = ReadFile(input_filename);
     std::string output;
-    if (!keystore->encryptWithAuthentication(key_name, input, &output)) {
+    if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) {
         printf("EncryptWithAuthentication failed.\n");
         return 1;
     }
@@ -429,6 +448,130 @@
     return 0;
 }
 
+uint32_t securityLevelOption2Flags(const CommandLine& cmd) {
+    if (cmd.HasSwitch("seclevel")) {
+        auto str = cmd.GetSwitchValueASCII("seclevel");
+        if (str == "strongbox") {
+            return KEYSTORE_FLAG_STRONGBOX;
+        } else if (str == "software") {
+            return KEYSTORE_FLAG_FALLBACK;
+        }
+    }
+    return KEYSTORE_FLAG_NONE;
+}
+
+class ConfirmationListener : public android::security::BnConfirmationPromptCallback {
+  public:
+    ConfirmationListener() {}
+
+    virtual ::android::binder::Status
+    onConfirmationPromptCompleted(int32_t result,
+                                  const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
+        ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(result);
+        printf("Confirmation prompt completed\n"
+               "responseCode = %d\n",
+               responseCode);
+        printf("dataThatWasConfirmed[%zd] = {", dataThatWasConfirmed.size());
+        size_t newLineCountDown = 16;
+        bool hasPrinted = false;
+        for (uint8_t element : dataThatWasConfirmed) {
+            if (hasPrinted) {
+                printf(", ");
+            }
+            if (newLineCountDown == 0) {
+                printf("\n  ");
+                newLineCountDown = 32;
+            }
+            printf("0x%02x", element);
+            hasPrinted = true;
+        }
+        printf("}\n");
+        exit(0);
+    }
+};
+
+int Confirmation(const std::string& promptText, const std::string& extraDataHex,
+                 const std::string& locale, const std::string& uiOptionsStr,
+                 const std::string& cancelAfter) {
+    sp<android::IServiceManager> sm = android::defaultServiceManager();
+    sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
+    sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(binder);
+    if (service == NULL) {
+        printf("error: could not connect to keystore service.\n");
+        return 1;
+    }
+
+    if (promptText.size() == 0) {
+        printf("The --prompt_text parameter cannot be empty.\n");
+        return 1;
+    }
+
+    std::vector<uint8_t> extraData;
+    if (!base::HexStringToBytes(extraDataHex, &extraData)) {
+        printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
+        return 1;
+    }
+
+    std::vector<std::string> pieces =
+        base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+    int uiOptionsAsFlags = 0;
+    for (auto& p : pieces) {
+        int value;
+        if (!base::StringToInt(p, &value)) {
+            printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
+            return 1;
+        }
+        uiOptionsAsFlags |= (1 << value);
+    }
+
+    double cancelAfterValue = 0.0;
+
+    if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
+        printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
+        return 1;
+    }
+
+    String16 promptText16(promptText.data(), promptText.size());
+    String16 locale16(locale.data(), locale.size());
+
+    sp<ConfirmationListener> listener = new ConfirmationListener();
+
+    int32_t aidl_return;
+    android::binder::Status status = service->presentConfirmationPrompt(
+        listener, promptText16, extraData, locale16, uiOptionsAsFlags, &aidl_return);
+    if (!status.isOk()) {
+        printf("Presenting confirmation prompt failed with binder status '%s'.\n",
+               status.toString8().c_str());
+        return 1;
+    }
+    ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
+    if (responseCode != ConfirmationResponseCode::OK) {
+        printf("Presenting confirmation prompt failed with response code %d.\n", responseCode);
+        return 1;
+    }
+
+    if (cancelAfterValue > 0.0) {
+        printf("Sleeping %.1f seconds before canceling prompt...\n", cancelAfterValue);
+        base::PlatformThread::Sleep(base::TimeDelta::FromSecondsD(cancelAfterValue));
+        status = service->cancelConfirmationPrompt(listener, &aidl_return);
+        if (!status.isOk()) {
+            printf("Canceling confirmation prompt failed with binder status '%s'.\n",
+                   status.toString8().c_str());
+            return 1;
+        }
+        responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
+        if (responseCode != ConfirmationResponseCode::OK) {
+            printf("Canceling confirmation prompt failed with response code %d.\n", responseCode);
+            return 1;
+        }
+    }
+
+    printf("Waiting for prompt to complete - use Ctrl+C to abort...\n");
+    // Use the main thread to process Binder transactions.
+    android::IPCThreadState::self()->joinThreadPool();
+    return 0;
+}
+
 }  // namespace
 
 int main(int argc, char** argv) {
@@ -444,9 +587,11 @@
     } else if (args[0] == "list-brillo-tests") {
         return ListTestCases();
     } else if (args[0] == "add-entropy") {
-        return AddEntropy(command_line->GetSwitchValueASCII("input"));
+        return AddEntropy(command_line->GetSwitchValueASCII("input"),
+                          securityLevelOption2Flags(*command_line));
     } else if (args[0] == "generate") {
-        return GenerateKey(command_line->GetSwitchValueASCII("name"));
+        return GenerateKey(command_line->GetSwitchValueASCII("name"),
+                           securityLevelOption2Flags(*command_line));
     } else if (args[0] == "get-chars") {
         return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
     } else if (args[0] == "export") {
@@ -462,13 +607,19 @@
     } else if (args[0] == "sign-verify") {
         return SignAndVerify(command_line->GetSwitchValueASCII("name"));
     } else if (args[0] == "encrypt") {
-        return Encrypt(command_line->GetSwitchValueASCII("name"),
-                       command_line->GetSwitchValueASCII("in"),
-                       command_line->GetSwitchValueASCII("out"));
+        return Encrypt(
+            command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"),
+            command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line));
     } else if (args[0] == "decrypt") {
         return Decrypt(command_line->GetSwitchValueASCII("name"),
                        command_line->GetSwitchValueASCII("in"),
                        command_line->GetSwitchValueASCII("out"));
+    } else if (args[0] == "confirmation") {
+        return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
+                            command_line->GetSwitchValueASCII("extra_data"),
+                            command_line->GetSwitchValueASCII("locale"),
+                            command_line->GetSwitchValueASCII("ui_options"),
+                            command_line->GetSwitchValueASCII("cancel_after"));
     } else {
         PrintUsageAndExit();
     }
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index f9df134..6d998ad 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -19,25 +19,19 @@
 #include <string>
 #include <vector>
 
+#include <android/security/IKeystoreService.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/keymaster_types.h>
 #include <keystore/keystore_hidl_support.h>
 
-using android::ExportResult;
-using keystore::KeyCharacteristics;
-using android::OperationResult;
-using android::String16;
-using keystore::AuthorizationSet;
-using keystore::AuthorizationSetBuilder;
+#include "keystore_client.pb.h"
 
 namespace {
 
@@ -49,6 +43,13 @@
 constexpr uint32_t kHMACKeySize = 256;     // bits
 constexpr uint32_t kHMACOutputSize = 256;  // bits
 
+using android::String16;
+using android::security::keymaster::ExportResult;
+using android::security::keymaster::OperationResult;
+using keystore::AuthorizationSet;
+using keystore::AuthorizationSetBuilder;
+using keystore::KeyCharacteristics;
+using keystore::KeyStoreServiceReturnCode;
 }  // namespace
 
 namespace keystore {
@@ -56,22 +57,22 @@
 KeystoreClientImpl::KeystoreClientImpl() {
     service_manager_ = android::defaultServiceManager();
     keystore_binder_ = service_manager_->getService(String16("android.security.keystore"));
-    keystore_ = android::interface_cast<android::IKeystoreService>(keystore_binder_);
+    keystore_ = android::interface_cast<android::security::IKeystoreService>(keystore_binder_);
 }
 
 bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
-                                                   const std::string& data,
+                                                   const std::string& data, int32_t flags,
                                                    std::string* encrypted_data) {
     // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random
     // IV. The authentication algorithm is HMAC-SHA256 and is computed over the
     // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM
     // because hardware support for GCM is not mandatory for all Brillo devices.
     std::string encryption_key_name = key_name + kEncryptSuffix;
-    if (!createOrVerifyEncryptionKey(encryption_key_name)) {
+    if (!createOrVerifyEncryptionKey(encryption_key_name, flags)) {
         return false;
     }
     std::string authentication_key_name = key_name + kAuthenticateSuffix;
-    if (!createOrVerifyAuthenticationKey(authentication_key_name)) {
+    if (!createOrVerifyAuthenticationKey(authentication_key_name, flags)) {
         return false;
     }
     AuthorizationSetBuilder encrypt_params;
@@ -86,7 +87,7 @@
         return false;
     }
     auto init_vector_blob = output_params.GetTagValue(TAG_NONCE);
-    if (!init_vector_blob.isOk()){
+    if (!init_vector_blob.isOk()) {
         ALOGE("Encrypt: Missing initialization vector.");
         return false;
     }
@@ -154,8 +155,7 @@
                                           AuthorizationSet* output_parameters,
                                           std::string* output_data) {
     uint64_t handle;
-    auto result =
-        beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
+    auto result = beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
     if (!result.isOk()) {
         ALOGE("BeginOperation failed: %d", int32_t(result));
         return false;
@@ -178,26 +178,32 @@
     return true;
 }
 
-KeyStoreNativeReturnCode KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
-    return keystore_->addRngEntropy(blob2hidlVec(entropy));
+KeyStoreNativeReturnCode
+KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy, int32_t flags) {
+    int32_t result;
+    auto binder_result = keystore_->addRngEntropy(blob2hidlVec(entropy), flags, &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+    return KeyStoreNativeReturnCode(result);
 }
 
-KeyStoreNativeReturnCode KeystoreClientImpl::generateKey(const std::string& key_name,
-                                        const AuthorizationSet& key_parameters,
-                                        AuthorizationSet* hardware_enforced_characteristics,
-                                        AuthorizationSet* software_enforced_characteristics) {
+KeyStoreNativeReturnCode
+KeystoreClientImpl::generateKey(const std::string& key_name, const AuthorizationSet& key_parameters,
+                                int32_t flags, AuthorizationSet* hardware_enforced_characteristics,
+                                AuthorizationSet* software_enforced_characteristics) {
     String16 key_name16(key_name.data(), key_name.size());
-    KeyCharacteristics characteristics;
-    auto result =
-        keystore_->generateKey(key_name16, key_parameters.hidl_data(), hidl_vec<uint8_t>(),
-                               kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+    ::android::security::keymaster::KeyCharacteristics characteristics;
+    int32_t result;
+    auto binder_result = keystore_->generateKey(
+        key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
+        hidl_vec<uint8_t>() /* entropy */, kDefaultUID, flags, &characteristics, &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
 
     /* 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;
+    *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
+    *software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
+    return KeyStoreNativeReturnCode(result);
 }
 
 KeyStoreNativeReturnCode
@@ -205,66 +211,80 @@
                                           AuthorizationSet* hardware_enforced_characteristics,
                                           AuthorizationSet* software_enforced_characteristics) {
     String16 key_name16(key_name.data(), key_name.size());
-    KeyCharacteristics characteristics;
-    auto result = keystore_->getKeyCharacteristics(key_name16, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
-                                                      kDefaultUID, &characteristics);
+    ::android::security::keymaster::KeyCharacteristics characteristics;
+    int32_t result;
+    auto binder_result = keystore_->getKeyCharacteristics(
+        key_name16, android::security::keymaster::KeymasterBlob(),
+        android::security::keymaster::KeymasterBlob(), kDefaultUID, &characteristics, &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;
+    *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
+    *software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
+    return KeyStoreNativeReturnCode(result);
 }
 
-KeyStoreNativeReturnCode KeystoreClientImpl::importKey(const std::string& key_name,
-                                      const AuthorizationSet& key_parameters,
-                                      KeyFormat key_format,
-                                      const std::string& key_data,
-                                      AuthorizationSet* hardware_enforced_characteristics,
-                                      AuthorizationSet* software_enforced_characteristics) {
+KeyStoreNativeReturnCode
+KeystoreClientImpl::importKey(const std::string& key_name, const AuthorizationSet& key_parameters,
+                              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());
     auto hidlKeyData = blob2hidlVec(key_data);
-    KeyCharacteristics characteristics;
-    auto result = keystore_->importKey(key_name16, key_parameters.hidl_data(), key_format,
-            hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
-
+    ::android::security::keymaster::KeyCharacteristics characteristics;
+    int32_t result;
+    auto binder_result = keystore_->importKey(
+        key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
+        (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics, &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;
+    *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
+    *software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
+    return KeyStoreNativeReturnCode(result);
 }
 
 KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat export_format,
-                                      const std::string& key_name, std::string* export_data) {
+                                                       const std::string& key_name,
+                                                       std::string* export_data) {
     String16 key_name16(key_name.data(), key_name.size());
     ExportResult export_result;
-    keystore_->exportKey(key_name16, export_format, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
-                         kDefaultUID, &export_result);
+    auto binder_result = keystore_->exportKey(
+        key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(),
+        android::security::keymaster::KeymasterBlob(), kDefaultUID, &export_result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
     *export_data = hidlVec2String(export_result.exportData);
     return export_result.resultCode;
 }
 
 KeyStoreNativeReturnCode KeystoreClientImpl::deleteKey(const std::string& key_name) {
     String16 key_name16(key_name.data(), key_name.size());
-    return keystore_->del(key_name16, kDefaultUID);
+    int32_t result;
+    auto binder_result = keystore_->del(key_name16, kDefaultUID, &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+    return KeyStoreNativeReturnCode(result);
 }
 
 KeyStoreNativeReturnCode KeystoreClientImpl::deleteAllKeys() {
-    return keystore_->clear_uid(kDefaultUID);
+    int32_t result;
+    auto binder_result = keystore_->clear_uid(kDefaultUID, &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+    return KeyStoreNativeReturnCode(result);
 }
 
-KeyStoreNativeReturnCode KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_name,
-                                           const AuthorizationSet& input_parameters,
-                                           AuthorizationSet* output_parameters,
-                                           uint64_t* handle) {
+KeyStoreNativeReturnCode
+KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_name,
+                                   const AuthorizationSet& input_parameters,
+                                   AuthorizationSet* output_parameters, uint64_t* handle) {
     android::sp<android::IBinder> token(new android::BBinder);
     String16 key_name16(key_name.data(), key_name.size());
     OperationResult result;
-    keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_parameters.hidl_data(),
-                     hidl_vec<uint8_t>(), kDefaultUID, &result);
+    auto binder_result = keystore_->begin(
+        token, key_name16, (int)purpose, true /*pruneable*/,
+        android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
+        hidl_vec<uint8_t>() /* entropy */, kDefaultUID, &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
     if (result.resultCode.isOk()) {
         *handle = getNextVirtualHandle();
         active_operations_[*handle] = result.token;
@@ -275,19 +295,20 @@
     return result.resultCode;
 }
 
-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) {
+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 ErrorCode::INVALID_OPERATION_HANDLE;
     }
     OperationResult result;
     auto hidlInputData = blob2hidlVec(input_data);
-    keystore_->update(active_operations_[handle], input_parameters.hidl_data(), hidlInputData,
-            &result);
+    auto binder_result = keystore_->update(
+        active_operations_[handle],
+        android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
+        hidlInputData, &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
 
     if (result.resultCode.isOk()) {
         *num_input_bytes_consumed = result.inputConsumed;
@@ -300,19 +321,20 @@
     return result.resultCode;
 }
 
-KeyStoreNativeReturnCode KeystoreClientImpl::finishOperation(uint64_t handle,
-                                            const AuthorizationSet& input_parameters,
-                                            const std::string& signature_to_verify,
-                                            AuthorizationSet* output_parameters,
-                                            std::string* output_data) {
+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 ErrorCode::INVALID_OPERATION_HANDLE;
     }
     OperationResult result;
     auto hidlSignature = blob2hidlVec(signature_to_verify);
-    keystore_->finish(active_operations_[handle], input_parameters.hidl_data(),
-                      hidlSignature,
-                      hidl_vec<uint8_t>(), &result);
+    auto binder_result = keystore_->finish(
+        active_operations_[handle],
+        android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
+        (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(), &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
 
     if (result.resultCode.isOk()) {
         if (result.outParams.size()) {
@@ -329,39 +351,43 @@
     if (active_operations_.count(handle) == 0) {
         return ErrorCode::INVALID_OPERATION_HANDLE;
     }
-    auto error_code = keystore_->abort(active_operations_[handle]);
-    if (error_code.isOk()) {
+    int32_t result;
+    // Current implementation does not return exceptions in android::binder::Status
+    auto binder_result = keystore_->abort(active_operations_[handle], &result);
+    if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+    if (KeyStoreNativeReturnCode(result).isOk()) {
         active_operations_.erase(handle);
     }
-    return error_code;
+    return KeyStoreNativeReturnCode(result);
 }
 
 bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {
     String16 key_name16(key_name.data(), key_name.size());
-    auto error_code = keystore_->exist(key_name16, kDefaultUID);
-    return error_code.isOk();
+    int32_t result;
+    auto binder_result = keystore_->exist(key_name16, kDefaultUID, &result);
+    if (!binder_result.isOk()) return false;  // binder error
+    return result;
 }
 
 bool KeystoreClientImpl::listKeys(const std::string& prefix,
                                   std::vector<std::string>* key_name_list) {
     String16 prefix16(prefix.data(), prefix.size());
-    android::Vector<String16> matches;
-    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()));
-        }
-        return true;
+    std::vector<::android::String16> matches;
+    auto binder_result = keystore_->list(prefix16, kDefaultUID, &matches);
+    if (!binder_result.isOk()) return false;
+
+    for (const auto& match : matches) {
+        android::String8 key_name(match);
+        key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size()));
     }
-    return false;
+    return true;
 }
 
 uint64_t KeystoreClientImpl::getNextVirtualHandle() {
     return next_virtual_handle_++;
 }
 
-bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name) {
+bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags) {
     bool key_exists = doesKeyExist(key_name);
     if (key_exists) {
         bool verified = false;
@@ -386,7 +412,7 @@
         AuthorizationSet hardware_enforced_characteristics;
         AuthorizationSet software_enforced_characteristics;
         auto result =
-            generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
+            generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics,
                         &software_enforced_characteristics);
         if (!result.isOk()) {
             ALOGE("Failed to generate encryption key: %d", int32_t(result));
@@ -399,7 +425,8 @@
     return true;
 }
 
-bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name) {
+bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name,
+                                                         int32_t flags) {
     bool key_exists = doesKeyExist(key_name);
     if (key_exists) {
         bool verified = false;
@@ -424,7 +451,7 @@
         AuthorizationSet hardware_enforced_characteristics;
         AuthorizationSet software_enforced_characteristics;
         auto result =
-            generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
+            generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics,
                         &software_enforced_characteristics);
         if (!result.isOk()) {
             ALOGE("Failed to generate authentication key: %d", int32_t(result));
@@ -442,32 +469,32 @@
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
     auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
-                                           &software_enforced_characteristics);
+                                        &software_enforced_characteristics);
     if (!result.isOk()) {
         ALOGE("Failed to query encryption key: %d", int32_t(result));
         return false;
     }
     *verified = true;
     auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
-            software_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;
     }
     auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
-            software_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;
     }
     auto block_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE),
-            software_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;
     }
     auto padding_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_PADDING),
-            software_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;
@@ -483,32 +510,32 @@
     AuthorizationSet hardware_enforced_characteristics;
     AuthorizationSet software_enforced_characteristics;
     auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
-                                           &software_enforced_characteristics);
+                                        &software_enforced_characteristics);
     if (!result.isOk()) {
         ALOGE("Failed to query authentication key: %d", int32_t(result));
         return false;
     }
     *verified = true;
     auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
-            software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
-    if (!algorithm.isOk() || algorithm.value() != Algorithm::HMAC){
+                              software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
+    if (!algorithm.isOk() || algorithm.value() != Algorithm::HMAC) {
         ALOGW("Found authentication key with invalid algorithm.");
         *verified = false;
     }
     auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
-            software_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;
     }
     auto mac_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH),
-            software_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;
     }
     auto digest = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_DIGEST),
-            software_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 8fb7f80..cf67fa4 100644
--- a/keystore/keystore_get.cpp
+++ b/keystore/keystore_get.cpp
@@ -14,24 +14,26 @@
  * limitations under the License.
  */
 
-#include <keystore/IKeystoreService.h>
+#include <android/security/IKeystoreService.h>
 #include <binder/IServiceManager.h>
 
 #include <keystore/keystore_get.h>
+#include <vector>
 
 using namespace android;
 using namespace keystore;
 
-ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
+ssize_t keystore_get(const char* key, size_t keyLength, uint8_t** value) {
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
-    sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+    sp<android::security::IKeystoreService> service =
+        interface_cast<android::security::IKeystoreService>(binder);
 
     if (service == NULL) {
         return -1;
     }
 
-    hidl_vec<uint8_t> result;
+    ::std::vector<uint8_t> result;
     auto ret = service->get(String16(key, keyLength), -1, &result);
     if (!ret.isOk()) return -1;
 
@@ -41,5 +43,4 @@
         memcpy(*value, &result[0], result.size());
     }
     return result.size();
-
 }
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
index 0389201..e114ea9 100644
--- a/keystore/keystore_keymaster_enforcement.h
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -73,17 +73,30 @@
         return now_date > expiration_date;
     }
 
-    bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const {
+    bool auth_token_timed_out(const HardwareAuthToken&, uint32_t) const {
         // Assume the token has not timed out, because AuthTokenTable would not have returned it if
         // the timeout were past.  Secure hardware will also check timeouts if it supports them.
         return false;
     }
 
-    bool ValidateTokenSignature(const hw_auth_token_t&) const override {
+    bool ValidateTokenSignature(const HardwareAuthToken&) const override {
         // Non-secure world cannot validate token signatures because it doesn't have access to the
         // signing key. Assume the token is good.
         return true;
     }
+
+    bool is_device_locked(int32_t userId) const override {
+        // If we haven't had a set call for this user yet, assume the device is locked.
+        if (mIsDeviceLockedForUser.count(userId) == 0) return true;
+        return mIsDeviceLockedForUser.find(userId)->second;
+    }
+
+    void set_device_locked(bool isLocked, int32_t userId) {
+        mIsDeviceLockedForUser[userId] = isLocked;
+    }
+
+  private:
+    std::map<int32_t, bool> mIsDeviceLockedForUser;
 };
 
 } // namespace keystore
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
index a739c5e..82d4e69 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -14,25 +14,28 @@
  * limitations under the License.
  */
 
-//#define LOG_NDEBUG 0
 #define LOG_TAG "keystore"
 
+#include <android-base/logging.h>
+#include <android/hidl/manager/1.1/IServiceManager.h>
+#include <android/security/IKeystoreService.h>
+#include <android/system/wifi/keystore/1.0/IKeystore.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 <hidl/HidlTransportSupport.h>
+#include <keymasterV4_0/Keymaster3.h>
+#include <keymasterV4_0/Keymaster4.h>
+#include <utils/StrongPointer.h>
 #include <wifikeystorehal/keystore.h>
 
-#include <cutils/log.h>
+#include <keystore/keystore_hidl_support.h>
+#include <keystore/keystore_return_types.h>
 
+#include "KeyStore.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"
+#include "permissions.h"
 
 /* KeyStore is a secured storage for key-value pairs. In this implementation,
  * each file stores one key-value pair. Keys are encoded in file names, and
@@ -40,68 +43,124 @@
  * 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 ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
 using ::android::system::wifi::keystore::V1_0::IKeystore;
 using ::android::system::wifi::keystore::V1_0::implementation::Keystore;
-using ::android::hardware::configureRpcThreadpool;
+using ::android::hidl::manager::V1_1::IServiceManager;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::keymaster::V4_0::SecurityLevel;
+using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
+using ::android::hardware::keymaster::V4_0::ErrorCode;
 
-/**
- * TODO implement keystore daemon using binderized keymaster HAL.
- */
+using ::keystore::keymaster::support::Keymaster;
+using ::keystore::keymaster::support::Keymaster3;
+using ::keystore::keymaster::support::Keymaster4;
+
+using keystore::KeymasterDevices;
+
+template <typename Wrapper>
+KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {
+    KeymasterDevices result;
+    serviceManager->listByInterface(
+        Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
+            auto try_get_device = [&](const auto& name, bool fail_silent) {
+                auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
+                if (fail_silent && !device) return;
+                CHECK(device) << "Failed to get service for \""
+                              << Wrapper::WrappedIKeymasterDevice::descriptor
+                              << "\" with interface name \"" << name << "\"";
+
+                sp<Keymaster> kmDevice(new Wrapper(device, name));
+                auto halVersion = kmDevice->halVersion();
+                SecurityLevel securityLevel = halVersion.securityLevel;
+                LOG(INFO) << "found " << Wrapper::WrappedIKeymasterDevice::descriptor
+                          << " with interface name " << name << " and seclevel "
+                          << toString(securityLevel);
+                CHECK(static_cast<uint32_t>(securityLevel) < result.size())
+                    << "Security level of \"" << Wrapper::WrappedIKeymasterDevice::descriptor
+                    << "\" with interface name \"" << name << "\" out of range";
+                auto& deviceSlot = result[securityLevel];
+                if (deviceSlot) {
+                    if (!fail_silent) {
+                        LOG(WARNING) << "Implementation of \""
+                                     << Wrapper::WrappedIKeymasterDevice::descriptor
+                                     << "\" with interface name \"" << name
+                                     << "\" and security level: " << toString(securityLevel)
+                                     << " Masked by other implementation of Keymaster";
+                    }
+                } else {
+                    deviceSlot = kmDevice;
+                }
+            };
+            bool has_default = false;
+            for (auto& n : names) {
+                try_get_device(n, false);
+                if (n == "default") has_default = true;
+            }
+            // Make sure that we always check the default device. If we enumerate only what is
+            // known to hwservicemanager, we miss a possible passthrough HAL.
+            if (!has_default) {
+                try_get_device("default", true /* fail_silent */);
+            }
+        });
+    return result;
+}
+
+KeymasterDevices initializeKeymasters() {
+    auto serviceManager = android::hidl::manager::V1_1::IServiceManager::getService();
+    CHECK(serviceManager.get()) << "Failed to get ServiceManager";
+    auto result = enumerateKeymasterDevices<Keymaster4>(serviceManager.get());
+    auto softKeymaster = result[SecurityLevel::SOFTWARE];
+    if (!result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
+        result = enumerateKeymasterDevices<Keymaster3>(serviceManager.get());
+    }
+    if (softKeymaster) result[SecurityLevel::SOFTWARE] = softKeymaster;
+    if (result[SecurityLevel::SOFTWARE] && !result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
+        LOG(WARNING) << "No secure Keymaster implementation found, but device offers insecure"
+                        " Keymaster HAL. Using as default.";
+        result[SecurityLevel::TRUSTED_ENVIRONMENT] = result[SecurityLevel::SOFTWARE];
+        result[SecurityLevel::SOFTWARE] = nullptr;
+    }
+    if (!result[SecurityLevel::SOFTWARE]) {
+        auto fbdev = android::keystore::makeSoftwareKeymasterDevice();
+        CHECK(fbdev.get()) << "Unable to create Software Keymaster Device";
+        result[SecurityLevel::SOFTWARE] = new Keymaster3(fbdev, "Software");
+    }
+    return result;
+}
 
 int main(int argc, char* argv[]) {
     using android::hardware::hidl_string;
-    if (argc < 2) {
-        ALOGE("A directory must be specified!");
-        return 1;
-    }
-    if (chdir(argv[1]) == -1) {
-        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
-        return 1;
-    }
+    CHECK(argc >= 2) << "A directory must be specified!";
+    CHECK(chdir(argv[1]) != -1) << "chdir: " << argv[1] << ": " << strerror(errno);
 
     Entropy entropy;
-    if (!entropy.open()) {
-        return 1;
-    }
+    CHECK(entropy.open()) << "Failed to open entropy source.";
 
-    auto dev = android::hardware::keymaster::V3_0::IKeymasterDevice::getService();
-    if (dev.get() == nullptr) {
-        return -1;
-    }
-    auto fallback = android::keystore::makeSoftwareKeymasterDevice();
-    if (dev.get() == nullptr) {
-        return -1;
-    }
+    auto kmDevices = initializeKeymasters();
 
-    if (configure_selinux() == -1) {
-        return -1;
-    }
+    CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device";
+    CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT])
+        << "Error no viable keymaster device found";
 
-    bool allowNewFallbackDevice = false;
+    CHECK(configure_selinux() != -1) << "Failed to configure SELinux.";
 
-    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;
-            }));
+    auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion();
 
-    if (!rc.isOk()) {
-        return -1;
-    }
+    // If the hardware is keymaster 2.0 or higher 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.
+    SecurityLevel minimalAllowedSecurityLevelForNewKeys =
+        halVersion.majorVersion >= 2 ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE;
 
-    KeyStore keyStore(&entropy, dev, fallback, allowNewFallbackDevice);
+    keystore::KeyStore keyStore(&entropy, kmDevices, minimalAllowedSecurityLevelForNewKeys);
     keyStore.initialize();
     android::sp<android::IServiceManager> sm = android::defaultServiceManager();
     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;
-    }
+    CHECK(ret == android::OK) << "Couldn't register binder service!";
 
     /**
      * Register the wifi keystore HAL service to run in passthrough mode.
@@ -111,9 +170,7 @@
     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);
-    }
+    CHECK(ret == android::OK) << "Cannot register wifi keystore HAL service: " << err;
 
     /*
      * This thread is just going to process Binder transactions.
diff --git a/keystore/keystore_tags_utils.cpp b/keystore/keystore_tags_utils.cpp
deleted file mode 100644
index 278348a..0000000
--- a/keystore/keystore_tags_utils.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-**
-** 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 b1777d0..e5ae29a 100644
--- a/keystore/keystore_utils.cpp
+++ b/keystore/keystore_utils.cpp
@@ -24,10 +24,14 @@
 
 #include <cutils/log.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 
-#include <keystore/authorization_set.h>
+#include <log/log_event_list.h>
+
+#include <keystore/keymaster_types.h>
 #include <keystore/keystore_client.h>
-#include <keystore/IKeystoreService.h>
+
+#include "blob.h"
 
 size_t readFully(int fd, uint8_t* data, size_t size) {
     size_t remaining = size;
@@ -80,7 +84,6 @@
     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);
@@ -94,3 +97,43 @@
 uid_t get_user_id(uid_t uid) {
     return uid / AID_USER;
 }
+
+void log_key_integrity_violation(const char* name, uid_t uid) {
+    if (!__android_log_security()) return;
+    android_log_event_list(SEC_TAG_KEY_INTEGRITY_VIOLATION)
+        << name << int32_t(uid) << LOG_ID_SECURITY;
+}
+
+namespace keystore {
+
+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;
+}
+
+SecurityLevel flagsToSecurityLevel(int32_t flags) {
+    switch (flags & (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX)) {
+    case KEYSTORE_FLAG_FALLBACK:
+    // treating Strongbox flag as "don't care" if Fallback is set
+    case (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX):
+        return SecurityLevel::SOFTWARE;
+    case KEYSTORE_FLAG_STRONGBOX:
+        return SecurityLevel::STRONGBOX;
+    default:
+        return SecurityLevel::TRUSTED_ENVIRONMENT;
+    }
+}
+
+uint32_t securityLevelToFlags(SecurityLevel secLevel) {
+    switch (secLevel) {
+    case SecurityLevel::SOFTWARE:
+        return KEYSTORE_FLAG_FALLBACK;
+    case SecurityLevel::STRONGBOX:
+        return KEYSTORE_FLAG_STRONGBOX;
+    default:
+        return 0;
+    }
+}
+
+}  // namespace keystore
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
index f970559..3bc9c01 100644
--- a/keystore/keystore_utils.h
+++ b/keystore/keystore_utils.h
@@ -17,20 +17,15 @@
 #ifndef KEYSTORE_KEYSTORE_UTILS_H_
 #define KEYSTORE_KEYSTORE_UTILS_H_
 
-#include <stdint.h>
-
+#include <cstdint>
 #include <vector>
 
 #include <openssl/evp.h>
 #include <openssl/pem.h>
 
-#include <hardware/keymaster_defs.h>
-
 #include <memory>
 
-#include <keystore/authorization_set.h>
-
-#include "blob.h"
+#include <keystore/keymaster_types.h>
 
 size_t readFully(int fd, uint8_t* data, size_t size);
 size_t writeFully(int fd, uint8_t* data, size_t size);
@@ -59,14 +54,24 @@
 };
 typedef std::unique_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
 
+class Blob;
+
+// Tags for audit logging. Be careful and don't log sensitive data.
+// Should be in sync with frameworks/base/core/java/android/app/admin/SecurityLogTags.logtags
+constexpr int SEC_TAG_KEY_DESTROYED = 210026;
+constexpr int SEC_TAG_KEY_INTEGRITY_VIOLATION = 210032;
+constexpr int SEC_TAG_AUTH_KEY_GENERATED = 210024;
+constexpr int SEC_TAG_KEY_IMPORTED = 210025;
+
+void log_key_integrity_violation(const char* name, uid_t uid);
+
 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;
-}
+hidl_vec<uint8_t> blob2hidlVec(const Blob& blob);
 
-} // namespace keystore
+SecurityLevel flagsToSecurityLevel(int32_t flags);
+uint32_t securityLevelToFlags(SecurityLevel secLevel);
+
+}  // namespace keystore
 
 #endif  // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 8c39716..4069060 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -20,47 +20,29 @@
 #include <algorithm>
 
 namespace keystore {
-using namespace android;
 
 OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
     : mDeathRecipient(deathRecipient) {}
 
 sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
-                                       const OperationMap::km_device_t& dev,
-                                       const sp<IBinder>& appToken,
-                                       KeyCharacteristics&& characteristics, bool pruneable) {
-    sp<IBinder> token = new BBinder();
-    mMap[token] = Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken);
-    if (pruneable) {
-        mLru.push_back(token);
-    }
-    if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) {
-        appToken->linkToDeath(mDeathRecipient);
-    }
+                                       const sp<Keymaster>& dev, const sp<IBinder>& appToken,
+                                       KeyCharacteristics&& characteristics,
+                                       const hidl_vec<KeyParameter>& params, bool pruneable) {
+    sp<IBinder> token = new ::android::BBinder();
+    mMap.emplace(token, Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken,
+                                  params));
+    if (pruneable) mLru.push_back(token);
+    if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient);
     mAppTokenMap[appToken].push_back(token);
     return token;
 }
 
-bool OperationMap::getOperation(const sp<IBinder>& token, uint64_t* outHandle, uint64_t* outKeyid,
-                                KeyPurpose* outPurpose, km_device_t* outDevice,
-                                const KeyCharacteristics** outCharacteristics) {
-    if (!outHandle || !outDevice) {
-        return false;
-    }
+NullOr<const Operation&> OperationMap::getOperation(const sp<IBinder>& token) {
     auto entry = mMap.find(token);
-    if (entry == mMap.end()) {
-        return false;
-    }
-    updateLru(token);
+    if (entry == mMap.end()) return {};
 
-    *outHandle = entry->second.handle;
-    *outKeyid = entry->second.keyid;
-    *outPurpose = entry->second.purpose;
-    *outDevice = entry->second.device;
-    if (outCharacteristics) {
-        *outCharacteristics = &entry->second.characteristics;
-    }
-    return true;
+    updateLru(token);
+    return entry->second;
 }
 
 void OperationMap::updateLru(const sp<IBinder>& token) {
@@ -71,19 +53,18 @@
     }
 }
 
-bool OperationMap::removeOperation(const sp<IBinder>& token) {
+NullOr<Operation> OperationMap::removeOperation(const sp<IBinder>& token, bool wasSuccessful) {
     auto entry = mMap.find(token);
-    if (entry == mMap.end()) {
-        return false;
-    }
-    sp<IBinder> appToken = entry->second.appToken;
+    if (entry == mMap.end()) return {};
+
+    Operation op = std::move(entry->second);
+    uploadOpAsProto(op, wasSuccessful);
     mMap.erase(entry);
+
     auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
-    if (lruEntry != mLru.end()) {
-        mLru.erase(lruEntry);
-    }
-    removeOperationTracking(token, appToken);
-    return true;
+    if (lruEntry != mLru.end()) mLru.erase(lruEntry);
+    removeOperationTracking(token, op.appToken);
+    return op;
 }
 
 void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) {
@@ -102,7 +83,7 @@
 }
 
 bool OperationMap::hasPruneableOperation() const {
-    return mLru.size() != 0;
+    return !mLru.empty();
 }
 
 size_t OperationMap::getPruneableOperationCount() const {
@@ -110,49 +91,29 @@
 }
 
 sp<IBinder> OperationMap::getOldestPruneableOperation() {
-    if (!hasPruneableOperation()) {
-        return sp<IBinder>(NULL);
-    }
-    return mLru[0];
+    if (!hasPruneableOperation()) return sp<IBinder>(nullptr);
+    return mLru.front();
 }
 
-bool OperationMap::getOperationAuthToken(const sp<IBinder>& token,
-                                         const HardwareAuthToken** outToken) {
+void OperationMap::setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken) {
     auto entry = mMap.find(token);
-    if (entry == mMap.end()) {
-        return false;
-    }
-    *outToken = entry->second.authToken.get();
-    return true;
+    if (entry == mMap.end()) return;
+
+    entry->second.authToken = std::move(authToken);
 }
 
-bool OperationMap::setOperationAuthToken(const sp<IBinder>& token,
-                                         const HardwareAuthToken* authToken) {
+void OperationMap::setOperationVerificationToken(const sp<IBinder>& token,
+                                                 VerificationToken verificationToken) {
     auto entry = mMap.find(token);
-    if (entry == mMap.end()) {
-        return false;
-    }
-    entry->second.authToken.reset(new HardwareAuthToken);
-    *entry->second.authToken = *authToken;
-    return true;
+    if (entry == mMap.end()) return;
+
+    entry->second.verificationToken = std::move(verificationToken);
 }
 
 std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) {
     auto appEntry = mAppTokenMap.find(appToken);
-    if (appEntry != mAppTokenMap.end()) {
-        return appEntry->second;
-    } else {
-        return std::vector<sp<IBinder>>();
-    }
+    if (appEntry == mAppTokenMap.end()) return {};
+    return appEntry->second;
 }
 
-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), keyid(0), device(nullptr), characteristics(), appToken(nullptr) {}
-
-}  // namespace android
+}  // namespace keystore
diff --git a/keystore/operation.h b/keystore/operation.h
index e69b43a..4888bfa 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -17,18 +17,25 @@
 #ifndef KEYSTORE_OPERATION_H_
 #define KEYSTORE_OPERATION_H_
 
+#include <map>
+#include <vector>
+
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
-#include <keystore/keymaster_tags.h>
-#include <map>
-#include <utils/LruCache.h>
+#include <keymasterV4_0/Keymaster.h>
 #include <utils/StrongPointer.h>
-#include <vector>
+
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+
+#include "operation_proto_handler.h"
+#include "operation_struct.h"
 
 namespace keystore {
 
 using ::android::IBinder;
 using ::android::sp;
+using keymaster::support::Keymaster;
 
 /**
  * OperationMap handles the translation of uint64_t's and keymaster2_device_t's to opaque binder
@@ -38,51 +45,29 @@
  */
 
 class OperationMap {
-    typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
-
   public:
     explicit OperationMap(IBinder::DeathRecipient* deathRecipient);
-    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);
+    sp<IBinder> addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
+                             const sp<Keymaster>& dev, const sp<IBinder>& appToken,
+                             KeyCharacteristics&& characteristics,
+                             const hidl_vec<KeyParameter>& params, bool pruneable);
+    NullOr<const Operation&> getOperation(const sp<IBinder>& token);
+    NullOr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful);
     bool hasPruneableOperation() const;
     size_t getOperationCount() const { return mMap.size(); }
     size_t getPruneableOperationCount() const;
-    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);
+    void setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken);
+    void setOperationVerificationToken(const sp<IBinder>& token, VerificationToken authToken);
+    sp<IBinder> getOldestPruneableOperation();
+    std::vector<sp<IBinder>> getOperationsForToken(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(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;
-        KeyPurpose purpose;
-        km_device_t device;
-        KeyCharacteristics characteristics;
-        android::sp<android::IBinder> appToken;
-        std::unique_ptr<HardwareAuthToken> authToken;
-    };
-    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;
+    void updateLru(const sp<IBinder>& token);
+    void removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken);
+    std::map<sp<IBinder>, Operation> mMap;
+    std::vector<sp<IBinder>> mLru;
+    std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap;
+    IBinder::DeathRecipient* mDeathRecipient;
 };
 
 }  // namespace keystore
diff --git a/keystore/operation_config.proto b/keystore/operation_config.proto
new file mode 100644
index 0000000..37b4cbb
--- /dev/null
+++ b/keystore/operation_config.proto
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+syntax = "proto2";
+
+package keystore;
+
+option optimize_for = LITE_RUNTIME;
+
+message OperationConfig {
+  // What type of encryption algorithm is the key being used in the op for.
+  optional string algorithm = 1;
+
+  // Size of the key being used in this op
+  optional int32 key_size = 2;
+
+  // Log whether the key in this op was generated, imported,
+  // securely imported, or derived.
+  optional string origin = 3;
+
+  // What auth types does this op require? If none, then no auth required.
+  optional string user_auth_type = 4;
+
+  // If user authentication is required, is the requirement time based? If it
+  // is not time based then this field will not be used and the key is per
+  // operation. Per operation keys must be user authenticated on each usage.
+  optional int32 user_auth_key_timeout = 5;
+
+  // Track which padding mode was used for this operation.
+  optional string padding = 6;
+
+  // Keep track of the digest algorithm being used.
+  optional string digest = 7;
+
+  // Check what block mode is being used depending on the mode of encryption
+  optional string block_mode = 8;
+
+  // Did the operation succeed? If it didn't, this represents bugs or
+  // error cases occurring.
+  optional bool was_op_successful = 9;
+
+  // What purpose is this operation serving? Encrypt, decrypt, sign verify?
+  optional string purpose = 10;
+
+  // Which ec curve was selected if elliptic curve cryptography is in use
+  optional string ec_curve = 11;
+
+  // Standalone or is a file system required
+  optional string key_blob_usage_reqs = 12;
+}
diff --git a/keystore/operation_proto_handler.cpp b/keystore/operation_proto_handler.cpp
new file mode 100644
index 0000000..77e1b73
--- /dev/null
+++ b/keystore/operation_proto_handler.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "KeystoreOperation"
+
+#include "operation_proto_handler.h"
+
+#include <android/os/DropBoxManager.h>
+#include <google/protobuf/message_lite.h>
+#include <keymasterV4_0/Keymaster.h>
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+#include <utils/String16.h>
+
+#include "operation_config.pb.h"
+
+namespace keystore {
+
+void determinePurpose(KeyPurpose purpose, OperationConfig* operationConfig) {
+    switch (purpose) {
+    case KeyPurpose::VERIFY:
+        operationConfig->set_purpose("verify");
+        break;
+    case KeyPurpose::ENCRYPT:
+        operationConfig->set_purpose("encrypt");
+        break;
+    case KeyPurpose::SIGN:
+        operationConfig->set_purpose("sign");
+        break;
+    case KeyPurpose::DECRYPT:
+        operationConfig->set_purpose("decrypt");
+        break;
+    case KeyPurpose::WRAP_KEY:
+        operationConfig->set_purpose("wrap");
+        break;
+    default:
+        break;
+    }
+}
+
+void checkKeyCharacteristics(const hidl_vec<KeyParameter>& characteristics,
+                             OperationConfig* operationConfig) {
+    for (auto& opParam : characteristics) {
+        switch (opParam.tag) {
+        case Tag::ALGORITHM:
+            operationConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, opParam)));
+            break;
+        case Tag::KEY_SIZE:
+            operationConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, opParam));
+            break;
+        case Tag::EC_CURVE:
+            operationConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, opParam)));
+            break;
+        case Tag::AUTH_TIMEOUT:
+            operationConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, opParam));
+            break;
+        case Tag::ORIGIN:
+            operationConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, opParam)));
+            break;
+        case Tag::BLOB_USAGE_REQUIREMENTS:
+            operationConfig->set_key_blob_usage_reqs(
+                toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, opParam)));
+            break;
+        case Tag::USER_AUTH_TYPE:
+            operationConfig->set_user_auth_type(
+                toString(accessTagValue(TAG_USER_AUTH_TYPE, opParam)));
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void checkOpCharacteristics(const hidl_vec<KeyParameter>& characteristics,
+                            OperationConfig* operationConfig) {
+    for (auto& opParam : characteristics) {
+        switch (opParam.tag) {
+        case Tag::BLOCK_MODE:
+            operationConfig->set_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, opParam)));
+            break;
+        case Tag::PADDING:
+            operationConfig->set_padding(toString(accessTagValue(TAG_PADDING, opParam)));
+            break;
+        case Tag::DIGEST:
+            operationConfig->set_digest(toString(accessTagValue(TAG_DIGEST, opParam)));
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void uploadOpAsProto(Operation& op, bool wasOpSuccessful) {
+    OperationConfig operationConfig;
+    determinePurpose(op.purpose, &operationConfig);
+    checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig);
+    checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig);
+    checkOpCharacteristics(op.params, &operationConfig);
+    auto dropbox = std::make_unique<android::os::DropBoxManager>();
+    operationConfig.set_was_op_successful(wasOpSuccessful);
+
+    size_t size = operationConfig.ByteSize();
+    auto data = std::make_unique<uint8_t[]>(size);
+    operationConfig.SerializeWithCachedSizesToArray(data.get());
+    dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
+}
+
+}  // namespace keystore
diff --git a/keystore/operation_proto_handler.h b/keystore/operation_proto_handler.h
new file mode 100644
index 0000000..bf461b4
--- /dev/null
+++ b/keystore/operation_proto_handler.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_OPERATION_PROTO_HANDLER_H_
+#define KEYSTORE_OPERATION_PROTO_HANDLER_H_
+
+#include "operation_struct.h"
+
+namespace keystore {
+
+using ::android::IBinder;
+using keymaster::support::Keymaster;
+
+void uploadOpAsProto(Operation& op, bool wasOpSuccessful);
+
+}  // namespace keystore
+
+#endif  // KEYSTORE_OPERATION_PROTO_HANDLER_H_
diff --git a/keystore/operation_struct.h b/keystore/operation_struct.h
new file mode 100644
index 0000000..00f1fe2
--- /dev/null
+++ b/keystore/operation_struct.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_OPERATION_STRUCT_H_
+#define KEYSTORE_OPERATION_STRUCT_H_
+
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <keymasterV4_0/Keymaster.h>
+#include <utils/StrongPointer.h>
+
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+using ::android::IBinder;
+using ::android::sp;
+using keymaster::support::Keymaster;
+
+struct Operation {
+    Operation() = default;
+    Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_, const sp<Keymaster>& device_,
+              KeyCharacteristics&& characteristics_, sp<IBinder> appToken_,
+              const hidl_vec<KeyParameter> params_)
+        : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
+          characteristics(characteristics_), appToken(appToken_), params(params_) {}
+    Operation(Operation&&) = default;
+    Operation(const Operation&) = delete;
+
+    bool hasAuthToken() const { return authToken.mac.size() != 0; }
+
+    uint64_t handle;
+    uint64_t keyid;
+    KeyPurpose purpose;
+    sp<Keymaster> device;
+    KeyCharacteristics characteristics;
+    sp<IBinder> appToken;
+    HardwareAuthToken authToken;
+    VerificationToken verificationToken;
+    const hidl_vec<KeyParameter> params;
+};
+
+}  // namespace keystore
+
+#endif
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index cc89681..73459c1 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -1,20 +1,30 @@
 // Unit test for AuthTokenTable
-// TODO: enable after fixing b/68149839
-/*
+
 cc_test {
     cflags: [
         "-Wall",
         "-Werror",
         "-Wextra",
+        "-O0",
     ],
-    srcs: ["auth_token_table_test.cpp"],
+    srcs: [
+        "auth_token_table_test.cpp",
+        "auth_token_formatting_test.cpp",
+        "confirmationui_rate_limiting_test.cpp",
+        "gtest_main.cpp",
+    ],
     name: "keystore_unit_tests",
-    tags: ["test"],
     static_libs: [
+        "android.hardware.confirmationui@1.0",
+        "libbase",
         "libgtest_main",
+        "libhidlbase",
+        "libkeymaster4support",
         "libkeystore_test",
         "liblog",
     ],
     shared_libs: ["libkeymaster_messages"],
+   sanitize: {
+     cfi: false,
+   }
 }
-*/
diff --git a/keystore/tests/auth_token_formatting_test.cpp b/keystore/tests/auth_token_formatting_test.cpp
new file mode 100644
index 0000000..0ecc4cc
--- /dev/null
+++ b/keystore/tests/auth_token_formatting_test.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <endian.h>
+#include <hidl/HidlSupport.h>
+#include <keymaster/logger.h>
+#include <keymasterV4_0/keymaster_utils.h>
+
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+
+#include "../auth_token_table.h"
+
+using std::vector;
+
+namespace keystore {
+
+using android::hardware::hidl_array;
+using android::hardware::hidl_vec;
+
+namespace test {
+
+namespace {
+
+class StdoutLogger : public ::keymaster::Logger {
+  public:
+    StdoutLogger() { set_instance(this); }
+
+    int log_msg(LogLevel level, const char* fmt, va_list args) const {
+        int output_len = 0;
+        switch (level) {
+        case DEBUG_LVL:
+            output_len = printf("DEBUG: ");
+            break;
+        case INFO_LVL:
+            output_len = printf("INFO: ");
+            break;
+        case WARNING_LVL:
+            output_len = printf("WARNING: ");
+            break;
+        case ERROR_LVL:
+            output_len = printf("ERROR: ");
+            break;
+        case SEVERE_LVL:
+            output_len = printf("SEVERE: ");
+            break;
+        }
+
+        output_len += vprintf(fmt, args);
+        output_len += printf("\n");
+        return output_len;
+    }
+};
+
+StdoutLogger logger;
+
+}  // namespace
+
+constexpr const uint8_t test_token[69] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+    0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+    0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+    0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44};
+
+constexpr const uint8_t test_hmac_data[] = {
+    0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
+    0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44};
+
+static const Km3HardwareAuthToken km3_hidl_test_token_little_endian = {
+    UINT64_C(0x0807060504030201), UINT64_C(0x100f0e0d0c0b0a09),
+    UINT64_C(0x1817161514131211), UINT32_C(0x1c1b1a19),
+    UINT64_C(0x24232221201f1e1d), hidl_array<uint8_t, 32>(test_hmac_data)};
+
+static const HardwareAuthToken km4_hidl_test_token = {
+    UINT64_C(0x0807060504030201), UINT64_C(0x100f0e0d0c0b0a09),
+    UINT64_C(0x1817161514131211), static_cast<HardwareAuthenticatorType>(UINT32_C(0x191a1b1c)),
+    UINT64_C(0x1d1e1f2021222324), hidl_vec<uint8_t>(test_hmac_data, test_hmac_data + 32)};
+
+TEST(AuthenticationTokenFormattingTest, hidlVec2Km3AuthToken) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    ASSERT_EQ(km3_hidl_test_token_little_endian, hidlVec2Km3AuthToken(hidl_test_token));
+}
+
+TEST(AuthenticationTokenFormattingTest, hidlVec2Km4AuthToken) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    ASSERT_EQ(km4_hidl_test_token, hidlVec2AuthToken(hidl_test_token));
+}
+
+TEST(AuthenticationTokenFormattingTest, km3AuthToken2HidlVec) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    ASSERT_EQ(hidl_test_token, authToken2HidlVec(km3_hidl_test_token_little_endian));
+}
+
+TEST(AuthenticationTokenFormattingTest, km4AuthToken2HidlVec) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    ASSERT_EQ(hidl_test_token, authToken2HidlVec(km4_hidl_test_token));
+}
+
+TEST(AuthenticationTokenFormattingTest, backAndForth) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    ASSERT_EQ(km3_hidl_test_token_little_endian,
+              hidlVec2Km3AuthToken(authToken2HidlVec(km3_hidl_test_token_little_endian)));
+    ASSERT_EQ(km4_hidl_test_token, hidlVec2AuthToken(authToken2HidlVec(km4_hidl_test_token)));
+}
+
+TEST(AuthenticationTokenFormattingTest, forthAndBack) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    ASSERT_EQ(hidl_test_token, authToken2HidlVec(hidlVec2Km3AuthToken(hidl_test_token)));
+    ASSERT_EQ(hidl_test_token, authToken2HidlVec(hidlVec2Km3AuthToken(hidl_test_token)));
+}
+
+TEST(AuthenticationTokenFormattingTest, roundAndRound) {
+    static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+    hidl_vec<uint8_t> hidl_test_token;
+    hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+    HardwareAuthToken km4_from_hidl = hidlVec2AuthToken(hidl_test_token);
+    hidl_vec<uint8_t> hidl_from_km4 = authToken2HidlVec(km4_from_hidl);
+    Km3HardwareAuthToken km3_from_hidl = hidlVec2Km3AuthToken(hidl_from_km4);
+    hidl_vec<uint8_t> hidl_from_km3 = authToken2HidlVec(km3_from_hidl);
+
+    ASSERT_EQ(hidl_from_km4, hidl_test_token);
+    ASSERT_EQ(hidl_from_km3, hidl_test_token);
+    ASSERT_NE(km4_from_hidl.timestamp, km3_from_hidl.timestamp);
+    ASSERT_NE(static_cast<uint32_t>(km4_from_hidl.authenticatorType),
+              km3_from_hidl.authenticatorType);
+}
+
+}  // namespace test
+}  // namespace keystore
diff --git a/keystore/tests/auth_token_table_test.cpp b/keystore/tests/auth_token_table_test.cpp
index 1b31cf5..511a78d 100644
--- a/keystore/tests/auth_token_table_test.cpp
+++ b/keystore/tests/auth_token_table_test.cpp
@@ -16,21 +16,17 @@
 
 #include <gtest/gtest.h>
 
-#include <keymaster/android_keymaster_utils.h>
+#include <endian.h>
 #include <keymaster/logger.h>
 
 #include "../auth_token_table.h"
 
 using std::vector;
 
-inline bool operator==(const hw_auth_token_t& a, const hw_auth_token_t& b) {
-    return (memcmp(&a, &b, sizeof(a)) == 0);
-}
-
-namespace keymaster {
+namespace keystore {
 namespace test {
 
-class StdoutLogger : public Logger {
+class StdoutLogger : public ::keymaster::Logger {
   public:
     StdoutLogger() { set_instance(this); }
 
@@ -66,26 +62,24 @@
     AuthTokenTable table;
 }
 
-static hw_auth_token_t* make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
-                                   uint64_t timestamp = 0) {
-    hw_auth_token_t* token = new hw_auth_token_t;
-    token->user_id = rsid;
-    token->authenticator_id = ssid;
-    token->authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
-    token->challenge = challenge;
-    token->timestamp = hton(timestamp);
+static HardwareAuthToken make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
+                                    uint64_t timestamp = 0) {
+    HardwareAuthToken token;
+    token.userId = rsid;
+    token.authenticatorId = ssid;
+    token.authenticatorType = HardwareAuthenticatorType::PASSWORD;
+    token.challenge = challenge;
+    token.timestamp = timestamp;
     return token;
 }
 
 static AuthorizationSet make_set(uint64_t rsid, uint32_t timeout = 10000) {
     AuthorizationSetBuilder builder;
-    builder.Authorization(TAG_USER_ID, 10)
-        .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
+    builder.Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
         .Authorization(TAG_USER_SECURE_ID, rsid);
     // Use timeout == 0 to indicate tags that require auth per operation.
-    if (timeout != 0)
-        builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
-    return builder.build();
+    if (timeout != 0) builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
+    return builder;
 }
 
 // Tests obviously run so fast that a real-time clock with a one-second granularity rarely changes
@@ -102,26 +96,30 @@
     table.AddAuthenticationToken(make_token(3, 4));
     EXPECT_EQ(2U, table.size());
 
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
-    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(1U, found->user_id);
-    EXPECT_EQ(2U, found->authenticator_id);
+    ASSERT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(1U, found->userId);
+    EXPECT_EQ(2U, found->authenticatorId);
 
-    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(1U, found->user_id);
-    EXPECT_EQ(2U, found->authenticator_id);
+    ASSERT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(1U, found->userId);
+    EXPECT_EQ(2U, found->authenticatorId);
 
-    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(3U, found->user_id);
-    EXPECT_EQ(4U, found->authenticator_id);
+    ASSERT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(3U, found->userId);
+    EXPECT_EQ(4U, found->authenticatorId);
 
-    ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(3U, found->user_id);
-    EXPECT_EQ(4U, found->authenticator_id);
+    ASSERT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(3U, found->userId);
+    EXPECT_EQ(4U, found->authenticatorId);
 
     ASSERT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
 }
 
 TEST(AuthTokenTableTest, FlushTable) {
@@ -131,13 +129,16 @@
     table.AddAuthenticationToken(make_token(2));
     table.AddAuthenticationToken(make_token(3));
 
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     // All three should be in the table.
     EXPECT_EQ(3U, table.size());
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
 
     table.Clear();
     EXPECT_EQ(0U, table.size());
@@ -150,36 +151,45 @@
     table.AddAuthenticationToken(make_token(2));
     table.AddAuthenticationToken(make_token(3));
 
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     // All three should be in the table.
     EXPECT_EQ(3U, table.size());
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
 
     table.AddAuthenticationToken(make_token(4));
 
     // Oldest should be gone.
     EXPECT_EQ(3U, table.size());
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
 
     // Others should be there, including the new one (4).  Search for it first, then the others, so
     // 4 becomes the least recently used.
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
 
     table.AddAuthenticationToken(make_token(5));
 
     // 5 should have replaced 4.
     EXPECT_EQ(3U, table.size());
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
 
     table.AddAuthenticationToken(make_token(6));
     table.AddAuthenticationToken(make_token(7));
@@ -187,12 +197,15 @@
     // 2 and 5 should be gone
     EXPECT_EQ(3U, table.size());
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(6), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(7), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
 
     table.AddAuthenticationToken(make_token(8));
     table.AddAuthenticationToken(make_token(9));
@@ -201,75 +214,76 @@
     // Only the three most recent should be there.
     EXPECT_EQ(3U, table.size());
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(6), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(7), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(8), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(9), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(10), KM_PURPOSE_SIGN, 0, &found));
+              table.FindAuthorization(make_set(8), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(9), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(10), KeyPurpose::SIGN, 0, &found));
 }
 
 TEST(AuthTokenTableTest, AuthenticationNotRequired) {
     AuthTokenTable table;
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     EXPECT_EQ(AuthTokenTable::AUTH_NOT_REQUIRED,
-              table.FindAuthorization(
-                  AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED).build(),
-                  KM_PURPOSE_SIGN, 0 /* no challenge */, &found));
+              table.FindAuthorization(AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED),
+                                      KeyPurpose::SIGN, 0 /* no challenge */, &found));
 }
 
 TEST(AuthTokenTableTest, OperationHandleNotFound) {
     AuthTokenTable table;
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     table.AddAuthenticationToken(make_token(1, 0, 1, 5));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       2 /* non-matching challenge */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       1 /* matching challenge */, &found));
     table.MarkCompleted(1);
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       1 /* used challenge */, &found));
 }
 
 TEST(AuthTokenTableTest, OperationHandleRequired) {
     AuthTokenTable table;
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     table.AddAuthenticationToken(make_token(1));
     EXPECT_EQ(AuthTokenTable::OP_HANDLE_REQUIRED,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       0 /* no op handle */, &found));
 }
 
 TEST(AuthTokenTableTest, AuthSidChanged) {
     AuthTokenTable table;
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     table.AddAuthenticationToken(make_token(1, 3, /* op handle */ 1));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_WRONG_SID,
-              table.FindAuthorization(make_set(2, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(2, 0 /* no timeout */), KeyPurpose::SIGN,
                                       1 /* op handle */, &found));
 }
 
 TEST(AuthTokenTableTest, TokenExpired) {
     AuthTokenTable table(5, monotonic_clock);
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     auto key_info = make_set(1, 5 /* five second timeout */);
 
@@ -281,17 +295,17 @@
     // keymaster when the found token is passed to it.
     table.AddAuthenticationToken(make_token(1, 0));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+              table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+              table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+              table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+              table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+              table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_EXPIRED,
-              table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+              table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
 }
 
 TEST(AuthTokenTableTest, MarkNonexistentEntryCompleted) {
@@ -302,15 +316,16 @@
 
 TEST(AuthTokenTableTest, SupersededEntries) {
     AuthTokenTable table;
-    const hw_auth_token_t* found;
+    const HardwareAuthToken* found;
 
     // Add two identical tokens, without challenges.  The second should supersede the first, based
     // on timestamp (fourth arg to make_token).
     table.AddAuthenticationToken(make_token(1, 0, 0, 0));
     table.AddAuthenticationToken(make_token(1, 0, 0, 1));
     EXPECT_EQ(1U, table.size());
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(1U, ntoh(found->timestamp));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(1U, found->timestamp);
 
     // Add a third token, this with a different RSID.  It should not be superseded.
     table.AddAuthenticationToken(make_token(2, 0, 0, 2));
@@ -320,10 +335,12 @@
     table.AddAuthenticationToken(make_token(1, 0, 0, 3));
     table.AddAuthenticationToken(make_token(2, 0, 0, 4));
     EXPECT_EQ(2U, table.size());
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(3U, ntoh(found->timestamp));
-    EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
-    EXPECT_EQ(4U, ntoh(found->timestamp));
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(3U, found->timestamp);
+    EXPECT_EQ(AuthTokenTable::OK,
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+    EXPECT_EQ(4U, found->timestamp);
 
     // Add another, this one with a challenge value.  It should supersede the old one since it is
     // newer, and matches other than the challenge.
@@ -338,13 +355,13 @@
     // Should be able to find each of them, by specifying their challenge, with a key that is not
     // timed (timed keys don't care about challenges).
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout*/), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout*/), KeyPurpose::SIGN,
                                       1 /* challenge */, &found));
-    EXPECT_EQ(5U, ntoh(found->timestamp));
+    EXPECT_EQ(5U, found->timestamp);
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       2 /* challenge */, &found));
-    EXPECT_EQ(6U, ntoh(found->timestamp));
+    EXPECT_EQ(6U, found->timestamp);
 
     // Add another, without a challenge, and the same timestamp as the last one.  This new one
     // actually could be considered already-superseded, but the table doesn't handle that case,
@@ -352,31 +369,31 @@
     table.AddAuthenticationToken(make_token(1, 0, 0, 6));
     EXPECT_EQ(4U, table.size());
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
-    EXPECT_EQ(6U, ntoh(found->timestamp));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+    EXPECT_EQ(6U, found->timestamp);
 
     // Add another without a challenge but an increased timestamp. This should supersede the
     // previous challenge-free entry.
     table.AddAuthenticationToken(make_token(1, 0, 0, 7));
     EXPECT_EQ(4U, table.size());
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       2 /* challenge */, &found));
-    EXPECT_EQ(6U, ntoh(found->timestamp));
+    EXPECT_EQ(6U, found->timestamp);
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
-    EXPECT_EQ(7U, ntoh(found->timestamp));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+    EXPECT_EQ(7U, found->timestamp);
 
     // Mark the entry with challenge 2 as complete.  Since there's a newer challenge-free entry, the
     // challenge entry will be superseded.
     table.MarkCompleted(2);
     EXPECT_EQ(3U, table.size());
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       2 /* challenge */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
-    EXPECT_EQ(7U, ntoh(found->timestamp));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+    EXPECT_EQ(7U, found->timestamp);
 
     // Add another SID 1 entry with a challenge.  It supersedes the previous SID 1 entry with
     // no challenge (timestamp 7), but not the one with challenge 1 (timestamp 5).
@@ -384,19 +401,19 @@
     EXPECT_EQ(3U, table.size());
 
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       1 /* challenge */, &found));
-    EXPECT_EQ(5U, ntoh(found->timestamp));
+    EXPECT_EQ(5U, found->timestamp);
 
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       3 /* challenge */, &found));
-    EXPECT_EQ(8U, ntoh(found->timestamp));
+    EXPECT_EQ(8U, found->timestamp);
 
     // SID 2 entry is still there.
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
-    EXPECT_EQ(4U, ntoh(found->timestamp));
+              table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0 /* challenge */, &found));
+    EXPECT_EQ(4U, found->timestamp);
 
     // Mark the entry with challenge 3 as complete.  Since the older challenge 1 entry is
     // incomplete, nothing is superseded.
@@ -404,25 +421,25 @@
     EXPECT_EQ(3U, table.size());
 
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       1 /* challenge */, &found));
-    EXPECT_EQ(5U, ntoh(found->timestamp));
+    EXPECT_EQ(5U, found->timestamp);
 
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
-    EXPECT_EQ(8U, ntoh(found->timestamp));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+    EXPECT_EQ(8U, found->timestamp);
 
     // Mark the entry with challenge 1 as complete.  Since there's a newer one (with challenge 3,
     // completed), the challenge 1 entry is superseded and removed.
     table.MarkCompleted(1);
     EXPECT_EQ(2U, table.size());
     EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
-              table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+              table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
                                       1 /* challenge */, &found));
     EXPECT_EQ(AuthTokenTable::OK,
-              table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
-    EXPECT_EQ(8U, ntoh(found->timestamp));
+              table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+    EXPECT_EQ(8U, found->timestamp);
 }
 
-}  // namespace keymaster
 }  // namespace test
+}  // namespace keystore
diff --git a/keystore/tests/confirmationui_rate_limiting_test.cpp b/keystore/tests/confirmationui_rate_limiting_test.cpp
new file mode 100644
index 0000000..f56b509
--- /dev/null
+++ b/keystore/tests/confirmationui_rate_limiting_test.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "../confirmationui_rate_limiting.h"
+#include <keymaster/logger.h>
+
+using std::vector;
+
+namespace keystore {
+
+namespace test {
+
+namespace {
+
+class StdoutLogger : public ::keymaster::Logger {
+  public:
+    StdoutLogger() { set_instance(this); }
+
+    int log_msg(LogLevel level, const char* fmt, va_list args) const {
+        int output_len = 0;
+        switch (level) {
+        case DEBUG_LVL:
+            output_len = printf("DEBUG: ");
+            break;
+        case INFO_LVL:
+            output_len = printf("INFO: ");
+            break;
+        case WARNING_LVL:
+            output_len = printf("WARNING: ");
+            break;
+        case ERROR_LVL:
+            output_len = printf("ERROR: ");
+            break;
+        case SEVERE_LVL:
+            output_len = printf("SEVERE: ");
+            break;
+        }
+
+        output_len += vprintf(fmt, args);
+        output_len += printf("\n");
+        return output_len;
+    }
+};
+
+StdoutLogger logger;
+
+class FakeClock : public std::chrono::steady_clock {
+  private:
+    static time_point sNow;
+
+  public:
+    static void setNow(time_point newNow) { sNow = newNow; }
+    static time_point now() noexcept { return sNow; }
+};
+
+FakeClock::time_point FakeClock::sNow;
+
+}  // namespace
+
+/*
+ * Test that there are no residual slots when various apps receive successful confirmations.
+ */
+TEST(ConfirmationUIRateLimitingTest, noPenaltyTest) {
+    auto now = std::chrono::steady_clock::now();
+    RateLimiting<FakeClock> rateLimiting;
+    FakeClock::setNow(now);
+
+    for (int i = 0; i < 10000; ++i) {
+        ASSERT_TRUE(rateLimiting.tryPrompt(rand()));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    ASSERT_EQ(0U, rateLimiting.usedSlots());
+}
+
+TEST(ConfirmationUIRateLimitingTest, policyTest) {
+    using namespace std::chrono_literals;
+    auto now = std::chrono::steady_clock::now();
+    RateLimiting<FakeClock> rateLimiting;
+    FakeClock::setNow(now);
+
+    // first three tries are free
+    for (int i = 0; i < 3; ++i) {
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    // the next three tries get a 30s penalty
+    for (int i = 3; i < 6; ++i) {
+        FakeClock::setNow(FakeClock::now() + 29s);
+        ASSERT_FALSE(rateLimiting.tryPrompt(20));
+        FakeClock::setNow(FakeClock::now() + 1s);
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    // there after the penalty doubles with each cancellation
+    for (int i = 6; i < 17; ++i) {
+        FakeClock::setNow((FakeClock::now() + 60s * (1ULL << (i - 6))) - 1s);
+        ASSERT_FALSE(rateLimiting.tryPrompt(20));
+        FakeClock::setNow(FakeClock::now() + 1s);
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    ASSERT_EQ(1U, rateLimiting.usedSlots());
+
+    FakeClock::setNow(FakeClock::now() + 24h - 1s);
+    ASSERT_FALSE(rateLimiting.tryPrompt(20));
+
+    // after 24h the counter is forgotten
+    FakeClock::setNow(FakeClock::now() + 1s);
+    ASSERT_TRUE(rateLimiting.tryPrompt(20));
+    rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    for (int i = 1; i < 3; ++i) {
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    for (int i = 3; i < 6; ++i) {
+        FakeClock::setNow(FakeClock::now() + 29s);
+        ASSERT_FALSE(rateLimiting.tryPrompt(20));
+        FakeClock::setNow(FakeClock::now() + 1s);
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    for (int i = 6; i < 17; ++i) {
+        FakeClock::setNow((FakeClock::now() + 60s * (1ULL << (i - 6))) - 1s);
+        ASSERT_FALSE(rateLimiting.tryPrompt(20));
+        FakeClock::setNow(FakeClock::now() + 1s);
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    ASSERT_EQ(1U, rateLimiting.usedSlots());
+}
+
+TEST(ConfirmationUIRateLimitingTest, rewindTest) {
+    using namespace std::chrono_literals;
+    auto now = std::chrono::steady_clock::now();
+    RateLimiting<FakeClock> rateLimiting;
+
+    // first three tries are free
+    for (int i = 0; i < 3; ++i) {
+        FakeClock::setNow(now);
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    for (int i = 3; i < 6; ++i) {
+        FakeClock::setNow(FakeClock::now() + 29s);
+        ASSERT_FALSE(rateLimiting.tryPrompt(20));
+        FakeClock::setNow(FakeClock::now() + 1s);
+        ASSERT_TRUE(rateLimiting.tryPrompt(20));
+        rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+    }
+
+    FakeClock::setNow(FakeClock::now() + 59s);
+    ASSERT_FALSE(rateLimiting.tryPrompt(20));
+    FakeClock::setNow(FakeClock::now() + 1s);
+    ASSERT_TRUE(rateLimiting.tryPrompt(20));
+    rateLimiting.processResult(ConfirmationResponseCode::Aborted);
+
+    FakeClock::setNow(FakeClock::now() - 1s);
+    ASSERT_FALSE(rateLimiting.tryPrompt(20));
+    FakeClock::setNow(FakeClock::now() + 1s);
+    ASSERT_TRUE(rateLimiting.tryPrompt(20));
+    rateLimiting.processResult(ConfirmationResponseCode::SystemError);
+
+    // throw in a couple of successful confirmations by other apps to make sure there
+    // is not cross talk
+    for (int i = 0; i < 10000; ++i) {
+        uid_t id = rand();
+        if (id == 20) continue;
+        ASSERT_TRUE(rateLimiting.tryPrompt(id));
+        rateLimiting.processResult(ConfirmationResponseCode::OK);
+    }
+
+    FakeClock::setNow(FakeClock::now() - 1s);
+    ASSERT_FALSE(rateLimiting.tryPrompt(20));
+    FakeClock::setNow(FakeClock::now() + 1s);
+    ASSERT_TRUE(rateLimiting.tryPrompt(20));
+    rateLimiting.processResult(ConfirmationResponseCode::UIError);
+
+    FakeClock::setNow(FakeClock::now() - 1s);
+    ASSERT_FALSE(rateLimiting.tryPrompt(20));
+    FakeClock::setNow(FakeClock::now() + 1s);
+    ASSERT_TRUE(rateLimiting.tryPrompt(20));
+
+    ASSERT_EQ(1U, rateLimiting.usedSlots());
+}
+
+}  // namespace test
+}  // namespace keystore
diff --git a/softkeymaster/Android.bp b/softkeymaster/Android.bp
deleted file mode 100644
index 3d27ecb..0000000
--- a/softkeymaster/Android.bp
+++ /dev/null
@@ -1,40 +0,0 @@
-cc_defaults {
-    name: "softkeymaster_defaults",
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-fvisibility=hidden",
-    ],
-}
-
-cc_library_shared {
-    name: "keystore.default",
-    defaults: ["softkeymaster_defaults"],
-
-    relative_install_path: "hw",
-    srcs: ["module.cpp"],
-    include_dirs: ["system/security/keystore"],
-    shared_libs: [
-        "libcrypto",
-        "libkeystore_binder",
-        "liblog",
-        "libsoftkeymaster",
-    ],
-}
-
-cc_library_shared {
-    name: "libsoftkeymaster",
-    defaults: ["softkeymaster_defaults"],
-
-    srcs: ["keymaster_openssl.cpp"],
-    include_dirs: ["system/security/keystore"],
-    local_include_dirs: [],
-    shared_libs: [
-        "libcrypto",
-        "libkeystore_binder",
-        "liblog",
-    ],
-
-    export_include_dirs: ["include"],
-}
diff --git a/softkeymaster/include/keymaster/softkeymaster.h b/softkeymaster/include/keymaster/softkeymaster.h
deleted file mode 100644
index e86ba3d..0000000
--- a/softkeymaster/include/keymaster/softkeymaster.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <hardware/keymaster0.h>
-
-#ifndef SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
-#define SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
-
-int openssl_generate_keypair(const keymaster0_device_t* dev, const keymaster_keypair_t key_type,
-                             const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength);
-
-int openssl_import_keypair(const keymaster0_device_t* dev, const uint8_t* key,
-                           const size_t key_length, uint8_t** key_blob, size_t* key_blob_length);
-
-int openssl_get_keypair_public(const struct keymaster0_device* dev, const uint8_t* key_blob,
-                               const size_t key_blob_length, uint8_t** x509_data,
-                               size_t* x509_data_length);
-
-int openssl_sign_data(const keymaster0_device_t* dev, const void* params, const uint8_t* keyBlob,
-                      const size_t keyBlobLength, const uint8_t* data, const size_t dataLength,
-                      uint8_t** signedData, size_t* signedDataLength);
-
-int openssl_verify_data(const keymaster0_device_t* dev, const void* params, const uint8_t* keyBlob,
-                        const size_t keyBlobLength, const uint8_t* signedData,
-                        const size_t signedDataLength, const uint8_t* signature,
-                        const size_t signatureLength);
-
-int openssl_open(const hw_module_t* module, const char* name, hw_device_t** device);
-
-extern struct keystore_module softkeymaster_module;
-
-#endif  // SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
diff --git a/softkeymaster/keymaster_openssl.cpp b/softkeymaster/keymaster_openssl.cpp
deleted file mode 100644
index f4d55bd..0000000
--- a/softkeymaster/keymaster_openssl.cpp
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <errno.h>
-#include <string.h>
-#include <stdint.h>
-
-#include <keystore/keystore.h>
-#include <keymaster/softkeymaster.h>
-
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-#include <openssl/evp.h>
-#include <openssl/bio.h>
-#include <openssl/rsa.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-
-#include <memory>
-
-// For debugging
-// #define LOG_NDEBUG 0
-
-#define LOG_TAG "OpenSSLKeyMaster"
-#include <cutils/log.h>
-
-struct BIGNUM_Delete {
-    void operator()(BIGNUM* p) const { BN_free(p); }
-};
-typedef std::unique_ptr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
-
-struct EVP_PKEY_Delete {
-    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
-};
-typedef std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
-
-struct PKCS8_PRIV_KEY_INFO_Delete {
-    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
-};
-typedef std::unique_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
-
-struct DSA_Delete {
-    void operator()(DSA* p) const { DSA_free(p); }
-};
-typedef std::unique_ptr<DSA, DSA_Delete> Unique_DSA;
-
-struct EC_KEY_Delete {
-    void operator()(EC_KEY* p) const { EC_KEY_free(p); }
-};
-typedef std::unique_ptr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
-
-struct EC_GROUP_Delete {
-    void operator()(EC_GROUP* p) const { EC_GROUP_free(p); }
-};
-typedef std::unique_ptr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
-
-struct RSA_Delete {
-    void operator()(RSA* p) const { RSA_free(p); }
-};
-typedef std::unique_ptr<RSA, RSA_Delete> Unique_RSA;
-
-struct Malloc_Free {
-    void operator()(void* p) const { free(p); }
-};
-
-typedef std::unique_ptr<keymaster0_device_t> Unique_keymaster_device_t;
-
-/**
- * Many OpenSSL APIs take ownership of an argument on success but
- * don't free the argument on failure. This means we need to tell our
- * scoped pointers when we've transferred ownership, without
- * triggering a warning by not using the result of release().
- */
-template <typename T, typename Delete_T>
-inline void release_because_ownership_transferred(std::unique_ptr<T, Delete_T>& p) {
-    T* val __attribute__((unused)) = p.release();
-}
-
-/*
- * Checks this thread's OpenSSL error queue and logs if
- * necessary.
- */
-static void logOpenSSLError(const char* location) {
-    int error = ERR_get_error();
-
-    if (error != 0) {
-        char message[256];
-        ERR_error_string_n(error, message, sizeof(message));
-        ALOGE("OpenSSL error in %s %d: %s", location, error, message);
-    }
-
-    ERR_clear_error();
-    ERR_remove_thread_state(NULL);
-}
-
-static int wrap_key(EVP_PKEY* pkey, int type, uint8_t** keyBlob, size_t* keyBlobLength) {
-    /*
-     * Find the length of each size. Public key is not needed anymore
-     * but must be kept for alignment purposes.
-     */
-    int publicLen = 0;
-    int privateLen = i2d_PrivateKey(pkey, NULL);
-
-    if (privateLen <= 0) {
-        ALOGE("private key size was too big");
-        return -1;
-    }
-
-    /* int type + int size + private key data + int size + public key data */
-    *keyBlobLength = get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + privateLen +
-                     sizeof(privateLen) + publicLen;
-
-    // derData will be returned to the caller, so allocate it with malloc.
-    std::unique_ptr<unsigned char, Malloc_Free> derData(
-        static_cast<unsigned char*>(malloc(*keyBlobLength)));
-    if (derData.get() == NULL) {
-        ALOGE("could not allocate memory for key blob");
-        return -1;
-    }
-    unsigned char* p = derData.get();
-
-    /* Write the magic value for software keys. */
-    p = add_softkey_header(p, *keyBlobLength);
-
-    /* Write key type to allocated buffer */
-    for (int i = sizeof(type) - 1; i >= 0; i--) {
-        *p++ = (type >> (8 * i)) & 0xFF;
-    }
-
-    /* Write public key to allocated buffer */
-    for (int i = sizeof(publicLen) - 1; i >= 0; i--) {
-        *p++ = (publicLen >> (8 * i)) & 0xFF;
-    }
-
-    /* Write private key to allocated buffer */
-    for (int i = sizeof(privateLen) - 1; i >= 0; i--) {
-        *p++ = (privateLen >> (8 * i)) & 0xFF;
-    }
-    if (i2d_PrivateKey(pkey, &p) != privateLen) {
-        logOpenSSLError("wrap_key");
-        return -1;
-    }
-
-    *keyBlob = derData.release();
-
-    return 0;
-}
-
-static EVP_PKEY* unwrap_key(const uint8_t* keyBlob, const size_t keyBlobLength) {
-    long publicLen = 0;
-    long privateLen = 0;
-    const uint8_t* p = keyBlob;
-    const uint8_t* const end = keyBlob + keyBlobLength;
-
-    if (keyBlob == NULL) {
-        ALOGE("supplied key blob was NULL");
-        return NULL;
-    }
-
-    int type = 0;
-    if (keyBlobLength < (get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + 1 +
-                         sizeof(privateLen) + 1)) {
-        ALOGE("key blob appears to be truncated");
-        return NULL;
-    }
-
-    if (!is_softkey(p, keyBlobLength)) {
-        ALOGE("cannot read key; it was not made by this keymaster");
-        return NULL;
-    }
-    p += get_softkey_header_size();
-
-    for (size_t i = 0; i < sizeof(type); i++) {
-        type = (type << 8) | *p++;
-    }
-
-    for (size_t i = 0; i < sizeof(type); i++) {
-        publicLen = (publicLen << 8) | *p++;
-    }
-    if (p + publicLen > end) {
-        ALOGE("public key length encoding error: size=%ld, end=%td", publicLen, end - p);
-        return NULL;
-    }
-
-    p += publicLen;
-    if (end - p < 2) {
-        ALOGE("private key truncated");
-        return NULL;
-    }
-    for (size_t i = 0; i < sizeof(type); i++) {
-        privateLen = (privateLen << 8) | *p++;
-    }
-    if (p + privateLen > end) {
-        ALOGE("private key length encoding error: size=%ld, end=%td", privateLen, end - p);
-        return NULL;
-    }
-
-    Unique_EVP_PKEY pkey(d2i_PrivateKey(type, nullptr, &p, privateLen));
-    if (pkey.get() == NULL) {
-        logOpenSSLError("unwrap_key");
-        return NULL;
-    }
-
-    return pkey.release();
-}
-
-static int generate_dsa_keypair(EVP_PKEY* pkey, const keymaster_dsa_keygen_params_t* dsa_params) {
-    if (dsa_params->key_size < 512) {
-        ALOGI("Requested DSA key size is too small (<512)");
-        return -1;
-    }
-
-    Unique_DSA dsa(DSA_new());
-
-    if (dsa_params->generator_len == 0 || dsa_params->prime_p_len == 0 ||
-        dsa_params->prime_q_len == 0 || dsa_params->generator == NULL ||
-        dsa_params->prime_p == NULL || dsa_params->prime_q == NULL) {
-        if (DSA_generate_parameters_ex(dsa.get(), dsa_params->key_size, NULL, 0, NULL, NULL,
-                                       NULL) != 1) {
-            logOpenSSLError("generate_dsa_keypair");
-            return -1;
-        }
-    } else {
-        dsa->g = BN_bin2bn(dsa_params->generator, dsa_params->generator_len, NULL);
-        if (dsa->g == NULL) {
-            logOpenSSLError("generate_dsa_keypair");
-            return -1;
-        }
-
-        dsa->p = BN_bin2bn(dsa_params->prime_p, dsa_params->prime_p_len, NULL);
-        if (dsa->p == NULL) {
-            logOpenSSLError("generate_dsa_keypair");
-            return -1;
-        }
-
-        dsa->q = BN_bin2bn(dsa_params->prime_q, dsa_params->prime_q_len, NULL);
-        if (dsa->q == NULL) {
-            logOpenSSLError("generate_dsa_keypair");
-            return -1;
-        }
-    }
-
-    if (DSA_generate_key(dsa.get()) != 1) {
-        logOpenSSLError("generate_dsa_keypair");
-        return -1;
-    }
-
-    if (EVP_PKEY_assign_DSA(pkey, dsa.get()) == 0) {
-        logOpenSSLError("generate_dsa_keypair");
-        return -1;
-    }
-    release_because_ownership_transferred(dsa);
-
-    return 0;
-}
-
-static int generate_ec_keypair(EVP_PKEY* pkey, const keymaster_ec_keygen_params_t* ec_params) {
-    Unique_EC_GROUP group;
-    switch (ec_params->field_size) {
-    case 224:
-        group.reset(EC_GROUP_new_by_curve_name(NID_secp224r1));
-        break;
-    case 256:
-        group.reset(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
-        break;
-    case 384:
-        group.reset(EC_GROUP_new_by_curve_name(NID_secp384r1));
-        break;
-    case 521:
-        group.reset(EC_GROUP_new_by_curve_name(NID_secp521r1));
-        break;
-    default:
-        break;
-    }
-
-    if (group.get() == NULL) {
-        logOpenSSLError("generate_ec_keypair");
-        return -1;
-    }
-
-#if !defined(OPENSSL_IS_BORINGSSL)
-    EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
-    EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
-#endif
-
-    /* initialize EC key */
-    Unique_EC_KEY eckey(EC_KEY_new());
-    if (eckey.get() == NULL) {
-        logOpenSSLError("generate_ec_keypair");
-        return -1;
-    }
-
-    if (EC_KEY_set_group(eckey.get(), group.get()) != 1) {
-        logOpenSSLError("generate_ec_keypair");
-        return -1;
-    }
-
-    if (EC_KEY_generate_key(eckey.get()) != 1 || EC_KEY_check_key(eckey.get()) < 0) {
-        logOpenSSLError("generate_ec_keypair");
-        return -1;
-    }
-
-    if (EVP_PKEY_assign_EC_KEY(pkey, eckey.get()) == 0) {
-        logOpenSSLError("generate_ec_keypair");
-        return -1;
-    }
-    release_because_ownership_transferred(eckey);
-
-    return 0;
-}
-
-static int generate_rsa_keypair(EVP_PKEY* pkey, const keymaster_rsa_keygen_params_t* rsa_params) {
-    Unique_BIGNUM bn(BN_new());
-    if (bn.get() == NULL) {
-        logOpenSSLError("generate_rsa_keypair");
-        return -1;
-    }
-
-    if (BN_set_word(bn.get(), rsa_params->public_exponent) == 0) {
-        logOpenSSLError("generate_rsa_keypair");
-        return -1;
-    }
-
-    /* initialize RSA */
-    Unique_RSA rsa(RSA_new());
-    if (rsa.get() == NULL) {
-        logOpenSSLError("generate_rsa_keypair");
-        return -1;
-    }
-
-    if (!RSA_generate_key_ex(rsa.get(), rsa_params->modulus_size, bn.get(), NULL) ||
-        RSA_check_key(rsa.get()) < 0) {
-        logOpenSSLError("generate_rsa_keypair");
-        return -1;
-    }
-
-    if (EVP_PKEY_assign_RSA(pkey, rsa.get()) == 0) {
-        logOpenSSLError("generate_rsa_keypair");
-        return -1;
-    }
-    release_because_ownership_transferred(rsa);
-
-    return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_generate_keypair(
-    const keymaster0_device_t*, const keymaster_keypair_t key_type, const void* key_params,
-    uint8_t** keyBlob, size_t* keyBlobLength) {
-    Unique_EVP_PKEY pkey(EVP_PKEY_new());
-    if (pkey.get() == NULL) {
-        logOpenSSLError("openssl_generate_keypair");
-        return -1;
-    }
-
-    if (key_params == NULL) {
-        ALOGW("key_params == null");
-        return -1;
-    } else if (key_type == TYPE_DSA) {
-        const keymaster_dsa_keygen_params_t* dsa_params =
-            (const keymaster_dsa_keygen_params_t*)key_params;
-        generate_dsa_keypair(pkey.get(), dsa_params);
-    } else if (key_type == TYPE_EC) {
-        const keymaster_ec_keygen_params_t* ec_params =
-            (const keymaster_ec_keygen_params_t*)key_params;
-        generate_ec_keypair(pkey.get(), ec_params);
-    } else if (key_type == TYPE_RSA) {
-        const keymaster_rsa_keygen_params_t* rsa_params =
-            (const keymaster_rsa_keygen_params_t*)key_params;
-        generate_rsa_keypair(pkey.get(), rsa_params);
-    } else {
-        ALOGW("Unsupported key type %d", key_type);
-        return -1;
-    }
-
-    if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), keyBlob, keyBlobLength)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_import_keypair(const keymaster0_device_t*,
-                                                                  const uint8_t* key,
-                                                                  const size_t key_length,
-                                                                  uint8_t** key_blob,
-                                                                  size_t* key_blob_length) {
-    if (key == NULL) {
-        ALOGW("input key == NULL");
-        return -1;
-    } else if (key_blob == NULL || key_blob_length == NULL) {
-        ALOGW("output key blob or length == NULL");
-        return -1;
-    }
-
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
-    if (pkcs8.get() == NULL) {
-        logOpenSSLError("openssl_import_keypair");
-        return -1;
-    }
-
-    /* assign to EVP */
-    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
-    if (pkey.get() == NULL) {
-        logOpenSSLError("openssl_import_keypair");
-        return -1;
-    }
-
-    if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), key_blob, key_blob_length)) {
-        return -1;
-    }
-
-    return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_get_keypair_public(const keymaster0_device_t*,
-                                                                      const uint8_t* key_blob,
-                                                                      const size_t key_blob_length,
-                                                                      uint8_t** x509_data,
-                                                                      size_t* x509_data_length) {
-    if (x509_data == NULL || x509_data_length == NULL) {
-        ALOGW("output public key buffer == NULL");
-        return -1;
-    }
-
-    Unique_EVP_PKEY pkey(unwrap_key(key_blob, key_blob_length));
-    if (pkey.get() == NULL) {
-        return -1;
-    }
-
-    int len = i2d_PUBKEY(pkey.get(), NULL);
-    if (len <= 0) {
-        logOpenSSLError("openssl_get_keypair_public");
-        return -1;
-    }
-
-    std::unique_ptr<uint8_t, Malloc_Free> key(static_cast<uint8_t*>(malloc(len)));
-    if (key.get() == NULL) {
-        ALOGE("Could not allocate memory for public key data");
-        return -1;
-    }
-
-    unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
-    if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
-        logOpenSSLError("openssl_get_keypair_public");
-        return -1;
-    }
-
-    ALOGV("Length of x509 data is %d", len);
-    *x509_data_length = len;
-    *x509_data = key.release();
-
-    return 0;
-}
-
-static int sign_dsa(EVP_PKEY* pkey, keymaster_dsa_sign_params_t* sign_params, const uint8_t* data,
-                    const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
-    if (sign_params->digest_type != DIGEST_NONE) {
-        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
-        return -1;
-    }
-
-    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
-    if (dsa.get() == NULL) {
-        logOpenSSLError("openssl_sign_dsa");
-        return -1;
-    }
-
-    unsigned int dsaSize = DSA_size(dsa.get());
-    std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dsaSize)));
-    if (signedDataPtr.get() == NULL) {
-        logOpenSSLError("openssl_sign_dsa");
-        return -1;
-    }
-
-    unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
-    if (DSA_sign(0, data, dataLength, tmp, &dsaSize, dsa.get()) <= 0) {
-        logOpenSSLError("openssl_sign_dsa");
-        return -1;
-    }
-
-    *signedDataLength = dsaSize;
-    *signedData = signedDataPtr.release();
-
-    return 0;
-}
-
-static int sign_ec(EVP_PKEY* pkey, keymaster_ec_sign_params_t* sign_params, const uint8_t* data,
-                   const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
-    if (sign_params->digest_type != DIGEST_NONE) {
-        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
-        return -1;
-    }
-
-    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
-    if (eckey.get() == NULL) {
-        logOpenSSLError("openssl_sign_ec");
-        return -1;
-    }
-
-    unsigned int ecdsaSize = ECDSA_size(eckey.get());
-    std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(ecdsaSize)));
-    if (signedDataPtr.get() == NULL) {
-        logOpenSSLError("openssl_sign_ec");
-        return -1;
-    }
-
-    unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
-    if (ECDSA_sign(0, data, dataLength, tmp, &ecdsaSize, eckey.get()) <= 0) {
-        logOpenSSLError("openssl_sign_ec");
-        return -1;
-    }
-
-    *signedDataLength = ecdsaSize;
-    *signedData = signedDataPtr.release();
-
-    return 0;
-}
-
-static int sign_rsa(EVP_PKEY* pkey, keymaster_rsa_sign_params_t* sign_params, const uint8_t* data,
-                    const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
-    if (sign_params->digest_type != DIGEST_NONE) {
-        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
-        return -1;
-    } else if (sign_params->padding_type != PADDING_NONE) {
-        ALOGW("Cannot handle padding type %d", sign_params->padding_type);
-        return -1;
-    }
-
-    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
-    if (rsa.get() == NULL) {
-        logOpenSSLError("openssl_sign_rsa");
-        return -1;
-    }
-
-    std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dataLength)));
-    if (signedDataPtr.get() == NULL) {
-        logOpenSSLError("openssl_sign_rsa");
-        return -1;
-    }
-
-    unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
-    if (RSA_private_encrypt(dataLength, data, tmp, rsa.get(), RSA_NO_PADDING) <= 0) {
-        logOpenSSLError("openssl_sign_rsa");
-        return -1;
-    }
-
-    *signedDataLength = dataLength;
-    *signedData = signedDataPtr.release();
-
-    return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_sign_data(
-    const keymaster0_device_t*, const void* params, const uint8_t* keyBlob,
-    const size_t keyBlobLength, const uint8_t* data, const size_t dataLength, uint8_t** signedData,
-    size_t* signedDataLength) {
-    if (data == NULL) {
-        ALOGW("input data to sign == NULL");
-        return -1;
-    } else if (signedData == NULL || signedDataLength == NULL) {
-        ALOGW("output signature buffer == NULL");
-        return -1;
-    }
-
-    Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
-    if (pkey.get() == NULL) {
-        return -1;
-    }
-
-    int type = EVP_PKEY_type(pkey->type);
-    if (type == EVP_PKEY_DSA) {
-        const keymaster_dsa_sign_params_t* sign_params =
-            reinterpret_cast<const keymaster_dsa_sign_params_t*>(params);
-        return sign_dsa(pkey.get(), const_cast<keymaster_dsa_sign_params_t*>(sign_params), data,
-                        dataLength, signedData, signedDataLength);
-    } else if (type == EVP_PKEY_EC) {
-        const keymaster_ec_sign_params_t* sign_params =
-            reinterpret_cast<const keymaster_ec_sign_params_t*>(params);
-        return sign_ec(pkey.get(), const_cast<keymaster_ec_sign_params_t*>(sign_params), data,
-                       dataLength, signedData, signedDataLength);
-    } else if (type == EVP_PKEY_RSA) {
-        const keymaster_rsa_sign_params_t* sign_params =
-            reinterpret_cast<const keymaster_rsa_sign_params_t*>(params);
-        return sign_rsa(pkey.get(), const_cast<keymaster_rsa_sign_params_t*>(sign_params), data,
-                        dataLength, signedData, signedDataLength);
-    } else {
-        ALOGW("Unsupported key type");
-        return -1;
-    }
-}
-
-static int verify_dsa(EVP_PKEY* pkey, keymaster_dsa_sign_params_t* sign_params,
-                      const uint8_t* signedData, const size_t signedDataLength,
-                      const uint8_t* signature, const size_t signatureLength) {
-    if (sign_params->digest_type != DIGEST_NONE) {
-        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
-        return -1;
-    }
-
-    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
-    if (dsa.get() == NULL) {
-        logOpenSSLError("openssl_verify_dsa");
-        return -1;
-    }
-
-    if (DSA_verify(0, signedData, signedDataLength, signature, signatureLength, dsa.get()) <= 0) {
-        logOpenSSLError("openssl_verify_dsa");
-        return -1;
-    }
-
-    return 0;
-}
-
-static int verify_ec(EVP_PKEY* pkey, keymaster_ec_sign_params_t* sign_params,
-                     const uint8_t* signedData, const size_t signedDataLength,
-                     const uint8_t* signature, const size_t signatureLength) {
-    if (sign_params->digest_type != DIGEST_NONE) {
-        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
-        return -1;
-    }
-
-    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
-    if (eckey.get() == NULL) {
-        logOpenSSLError("openssl_verify_ec");
-        return -1;
-    }
-
-    if (ECDSA_verify(0, signedData, signedDataLength, signature, signatureLength, eckey.get()) <=
-        0) {
-        logOpenSSLError("openssl_verify_ec");
-        return -1;
-    }
-
-    return 0;
-}
-
-static int verify_rsa(EVP_PKEY* pkey, keymaster_rsa_sign_params_t* sign_params,
-                      const uint8_t* signedData, const size_t signedDataLength,
-                      const uint8_t* signature, const size_t signatureLength) {
-    if (sign_params->digest_type != DIGEST_NONE) {
-        ALOGW("Cannot handle digest type %d", sign_params->digest_type);
-        return -1;
-    } else if (sign_params->padding_type != PADDING_NONE) {
-        ALOGW("Cannot handle padding type %d", sign_params->padding_type);
-        return -1;
-    } else if (signatureLength != signedDataLength) {
-        ALOGW("signed data length must be signature length");
-        return -1;
-    }
-
-    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
-    if (rsa.get() == NULL) {
-        logOpenSSLError("openssl_verify_data");
-        return -1;
-    }
-
-    std::unique_ptr<uint8_t[]> dataPtr(new uint8_t[signedDataLength]);
-    if (dataPtr.get() == NULL) {
-        logOpenSSLError("openssl_verify_data");
-        return -1;
-    }
-
-    unsigned char* tmp = reinterpret_cast<unsigned char*>(dataPtr.get());
-    if (!RSA_public_decrypt(signatureLength, signature, tmp, rsa.get(), RSA_NO_PADDING)) {
-        logOpenSSLError("openssl_verify_data");
-        return -1;
-    }
-
-    int result = 0;
-    for (size_t i = 0; i < signedDataLength; i++) {
-        result |= tmp[i] ^ signedData[i];
-    }
-
-    return result == 0 ? 0 : -1;
-}
-
-__attribute__((visibility("default"))) int openssl_verify_data(
-    const keymaster0_device_t*, const void* params, const uint8_t* keyBlob,
-    const size_t keyBlobLength, const uint8_t* signedData, const size_t signedDataLength,
-    const uint8_t* signature, const size_t signatureLength) {
-    if (signedData == NULL || signature == NULL) {
-        ALOGW("data or signature buffers == NULL");
-        return -1;
-    }
-
-    Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
-    if (pkey.get() == NULL) {
-        return -1;
-    }
-
-    int type = EVP_PKEY_type(pkey->type);
-    if (type == EVP_PKEY_DSA) {
-        const keymaster_dsa_sign_params_t* sign_params =
-            reinterpret_cast<const keymaster_dsa_sign_params_t*>(params);
-        return verify_dsa(pkey.get(), const_cast<keymaster_dsa_sign_params_t*>(sign_params),
-                          signedData, signedDataLength, signature, signatureLength);
-    } else if (type == EVP_PKEY_RSA) {
-        const keymaster_rsa_sign_params_t* sign_params =
-            reinterpret_cast<const keymaster_rsa_sign_params_t*>(params);
-        return verify_rsa(pkey.get(), const_cast<keymaster_rsa_sign_params_t*>(sign_params),
-                          signedData, signedDataLength, signature, signatureLength);
-    } else if (type == EVP_PKEY_EC) {
-        const keymaster_ec_sign_params_t* sign_params =
-            reinterpret_cast<const keymaster_ec_sign_params_t*>(params);
-        return verify_ec(pkey.get(), const_cast<keymaster_ec_sign_params_t*>(sign_params),
-                         signedData, signedDataLength, signature, signatureLength);
-    } else {
-        ALOGW("Unsupported key type %d", type);
-        return -1;
-    }
-}
-
-/* Close an opened OpenSSL instance */
-static int openssl_close(hw_device_t* dev) {
-    delete dev;
-    return 0;
-}
-
-/*
- * Generic device handling
- */
-__attribute__((visibility("default"))) int openssl_open(const hw_module_t* module, const char* name,
-                                                        hw_device_t** device) {
-    if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
-        return -EINVAL;
-
-    Unique_keymaster_device_t dev(new keymaster0_device_t);
-    if (dev.get() == NULL)
-        return -ENOMEM;
-
-    dev->common.tag = HARDWARE_DEVICE_TAG;
-    dev->common.version = 1;
-    dev->common.module = (struct hw_module_t*)module;
-    dev->common.close = openssl_close;
-
-    dev->flags = KEYMASTER_SOFTWARE_ONLY | KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_DSA |
-                 KEYMASTER_SUPPORTS_EC;
-
-    dev->generate_keypair = openssl_generate_keypair;
-    dev->import_keypair = openssl_import_keypair;
-    dev->get_keypair_public = openssl_get_keypair_public;
-    dev->delete_keypair = NULL;
-    dev->delete_all = NULL;
-    dev->sign_data = openssl_sign_data;
-    dev->verify_data = openssl_verify_data;
-
-    ERR_load_crypto_strings();
-    ERR_load_BIO_strings();
-
-    *device = reinterpret_cast<hw_device_t*>(dev.release());
-
-    return 0;
-}
-
-static struct hw_module_methods_t keystore_module_methods = {
-    .open = openssl_open,
-};
-
-struct keystore_module softkeymaster_module __attribute__((visibility("default"))) = {
-    .common =
-        {
-         .tag = HARDWARE_MODULE_TAG,
-         .module_api_version = KEYMASTER_MODULE_API_VERSION_0_2,
-         .hal_api_version = HARDWARE_HAL_API_VERSION,
-         .id = KEYSTORE_HARDWARE_MODULE_ID,
-         .name = "Keymaster OpenSSL HAL",
-         .author = "The Android Open Source Project",
-         .methods = &keystore_module_methods,
-         .dso = 0,
-         .reserved = {},
-        },
-};