diff --git a/keystore/Android.mk b/keystore/Android.mk
index f2262c1..e26aebe 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -27,18 +27,7 @@
 LOCAL_MULTILIB := 32
 endif
 LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
-LOCAL_SRC_FILES := \
-	auth_token_table.cpp \
-	blob.cpp \
-	entropy.cpp \
-	key_store_service.cpp \
-	keyblob_utils.cpp \
-	keystore.cpp \
-	keystore_main.cpp \
-	keystore_utils.cpp \
-	operation.cpp \
-	permissions.cpp \
-	user_state.cpp
+LOCAL_SRC_FILES := keystore.cpp keyblob_utils.cpp operation.cpp auth_token_table.cpp
 LOCAL_SHARED_LIBRARIES := \
 	libbinder \
 	libcutils \
@@ -55,6 +44,9 @@
 LOCAL_MODULE := keystore
 LOCAL_MODULE_TAGS := optional
 LOCAL_INIT_RC := keystore.rc
+LOCAL_C_INCLUES := system/keymaster/
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_EXECUTABLE)
 
@@ -110,6 +102,8 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(call keystore_proto_include)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 8ed09c4..6e20f9d 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -418,11 +418,12 @@
         return ret;
     }
 
-    virtual int32_t get(const String16& name, uint8_t** item, size_t* itemLength)
+    virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength)
     {
         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);
@@ -833,11 +834,12 @@
         return ret;
     }
 
-    int64_t getmtime(const String16& name)
+    int64_t getmtime(const String16& name, int32_t uid)
     {
         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);
@@ -963,7 +965,7 @@
     virtual int32_t getKeyCharacteristics(const String16& name,
                                           const keymaster_blob_t* clientId,
                                           const keymaster_blob_t* appData,
-                                          KeyCharacteristics* outCharacteristics)
+                                          int32_t uid, KeyCharacteristics* outCharacteristics)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
@@ -978,6 +980,7 @@
         } else {
             data.writeInt32(-1);
         }
+        data.writeInt32(uid);
         status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
                                              data, &reply);
         if (status != NO_ERROR) {
@@ -1028,7 +1031,7 @@
 
     virtual void exportKey(const String16& name, keymaster_key_format_t format,
                            const keymaster_blob_t* clientId,
-                           const keymaster_blob_t* appData, ExportResult* result)
+                           const keymaster_blob_t* appData, int32_t uid, ExportResult* result)
     {
         if (!result) {
             return;
@@ -1048,6 +1051,7 @@
         } else {
             data.writeInt32(-1);
         }
+        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);
@@ -1068,7 +1072,7 @@
     virtual void begin(const sp<IBinder>& appToken, const String16& name,
                        keymaster_purpose_t purpose, bool pruneable,
                        const KeymasterArguments& params, const uint8_t* entropy,
-                       size_t entropyLength, OperationResult* result)
+                       size_t entropyLength, int32_t uid, OperationResult* result)
     {
         if (!result) {
             return;
@@ -1082,6 +1086,7 @@
         data.writeInt32(1);
         params.writeToParcel(&data);
         data.writeByteArray(entropyLength, entropy);
+        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);
@@ -1278,9 +1283,10 @@
         case GET: {
             CHECK_INTERFACE(IKeystoreService, data, reply);
             String16 name = data.readString16();
+            int32_t uid = data.readInt32();
             void* out = NULL;
             size_t outSize = 0;
-            int32_t ret = get(name, (uint8_t**) &out, &outSize);
+            int32_t ret = get(name, uid, (uint8_t**) &out, &outSize);
             reply->writeNoException();
             if (ret == 1) {
                 reply->writeInt32(outSize);
@@ -1524,7 +1530,8 @@
         case GETMTIME: {
             CHECK_INTERFACE(IKeystoreService, data, reply);
             String16 name = data.readString16();
-            int64_t ret = getmtime(name);
+            int32_t uid = data.readInt32();
+            int64_t ret = getmtime(name, uid);
             reply->writeNoException();
             reply->writeInt64(ret);
             return NO_ERROR;
@@ -1592,8 +1599,9 @@
             String16 name = data.readString16();
             std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
             std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
+            int32_t uid = data.readInt32();
             KeyCharacteristics outCharacteristics;
-            int ret = getKeyCharacteristics(name, clientId.get(), appData.get(),
+            int ret = getKeyCharacteristics(name, clientId.get(), appData.get(), uid,
                                             &outCharacteristics);
             reply->writeNoException();
             reply->writeInt32(ret);
@@ -1630,8 +1638,9 @@
             keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
             std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data);
             std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data);
+            int32_t uid = data.readInt32();
             ExportResult result;
-            exportKey(name, format, clientId.get(), appData.get(), &result);
+            exportKey(name, format, clientId.get(), appData.get(), uid, &result);
             reply->writeNoException();
             reply->writeInt32(1);
             result.writeToParcel(reply);
@@ -1651,8 +1660,9 @@
             const uint8_t* entropy = NULL;
             size_t entropyLength = 0;
             readByteArray(data, &entropy, &entropyLength);
+            int32_t uid = data.readInt32();
             OperationResult result;
-            begin(token, name, purpose, pruneable, args, entropy, entropyLength, &result);
+            begin(token, name, purpose, pruneable, args, entropy, entropyLength, uid, &result);
             reply->writeNoException();
             reply->writeInt32(1);
             result.writeToParcel(reply);
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index a2f1446..24aa774 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -20,8 +20,8 @@
 #include <hardware/hw_auth_token.h>
 #include <keymaster/authorization_set.h>
 
-#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
-#define KEYSTORE_AUTH_TOKEN_TABLE_H_
+#ifndef SYSTEM_KEYMASTER_AUTH_TOKEN_TABLE_H
+#define SYSTEM_KEYMASTER_AUTH_TOKEN_TABLE_H
 
 namespace keymaster {
 
@@ -160,4 +160,4 @@
 
 }  // namespace keymaster
 
-#endif  // KEYSTORE_AUTH_TOKEN_TABLE_H_
+#endif  // SYSTEM_KEYMASTER_AUTH_TOKEN_TABLE_H
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
deleted file mode 100644
index 8b08f07..0000000
--- a/keystore/blob.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "keystore"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <cutils/log.h>
-
-#include "blob.h"
-#include "entropy.h"
-
-#include "keystore_utils.h"
-
-Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
-           BlobType type) {
-    memset(&mBlob, 0, sizeof(mBlob));
-    if (valueLength > VALUE_SIZE) {
-        valueLength = VALUE_SIZE;
-        ALOGW("Provided blob length too large");
-    }
-    if (infoLength + valueLength > VALUE_SIZE) {
-        infoLength = VALUE_SIZE - valueLength;
-        ALOGW("Provided info length too large");
-    }
-    mBlob.length = valueLength;
-    memcpy(mBlob.value, value, valueLength);
-
-    mBlob.info = infoLength;
-    memcpy(mBlob.value + valueLength, info, infoLength);
-
-    mBlob.version = CURRENT_BLOB_VERSION;
-    mBlob.type = uint8_t(type);
-
-    if (type == TYPE_MASTER_KEY) {
-        mBlob.flags = KEYSTORE_FLAG_ENCRYPTED;
-    } else {
-        mBlob.flags = KEYSTORE_FLAG_NONE;
-    }
-}
-
-Blob::Blob(blob b) {
-    mBlob = b;
-}
-
-Blob::Blob() {
-    memset(&mBlob, 0, sizeof(mBlob));
-}
-
-bool Blob::isEncrypted() const {
-    if (mBlob.version < 2) {
-        return true;
-    }
-
-    return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
-}
-
-void Blob::setEncrypted(bool encrypted) {
-    if (encrypted) {
-        mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
-    } else {
-        mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
-    }
-}
-
-void Blob::setFallback(bool fallback) {
-    if (fallback) {
-        mBlob.flags |= KEYSTORE_FLAG_FALLBACK;
-    } else {
-        mBlob.flags &= ~KEYSTORE_FLAG_FALLBACK;
-    }
-}
-
-ResponseCode Blob::writeBlob(const char* filename, AES_KEY* aes_key, State state,
-                             Entropy* entropy) {
-    ALOGV("writing blob %s", filename);
-    if (isEncrypted()) {
-        if (state != STATE_NO_ERROR) {
-            ALOGD("couldn't insert encrypted blob while not unlocked");
-            return LOCKED;
-        }
-
-        if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
-            ALOGW("Could not read random data for: %s", filename);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    // data includes the value and the value's length
-    size_t dataLength = mBlob.length + sizeof(mBlob.length);
-    // pad data to the AES_BLOCK_SIZE
-    size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
-    // encrypted data includes the digest value
-    size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
-    // move info after space for padding
-    memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
-    // zero padding area
-    memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);
-
-    mBlob.length = htonl(mBlob.length);
-
-    if (isEncrypted()) {
-        MD5(mBlob.digested, digestedLength, mBlob.digest);
-
-        uint8_t vector[AES_BLOCK_SIZE];
-        memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
-        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, vector,
-                        AES_ENCRYPT);
-    }
-
-    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
-    size_t fileLength = encryptedLength + headerLength + mBlob.info;
-
-    const char* tmpFileName = ".tmp";
-    int out =
-        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
-    if (out < 0) {
-        ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
-        return SYSTEM_ERROR;
-    }
-    size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
-    if (close(out) != 0) {
-        return SYSTEM_ERROR;
-    }
-    if (writtenBytes != fileLength) {
-        ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
-        unlink(tmpFileName);
-        return SYSTEM_ERROR;
-    }
-    if (rename(tmpFileName, filename) == -1) {
-        ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
-        return SYSTEM_ERROR;
-    }
-    return NO_ERROR;
-}
-
-ResponseCode Blob::readBlob(const char* filename, AES_KEY* aes_key, State state) {
-    ALOGV("reading blob %s", filename);
-    int in = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
-    if (in < 0) {
-        return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
-    }
-    // fileLength may be less than sizeof(mBlob) since the in
-    // memory version has extra padding to tolerate rounding up to
-    // the AES_BLOCK_SIZE
-    size_t fileLength = readFully(in, (uint8_t*)&mBlob, sizeof(mBlob));
-    if (close(in) != 0) {
-        return SYSTEM_ERROR;
-    }
-
-    if (fileLength == 0) {
-        return VALUE_CORRUPTED;
-    }
-
-    if (isEncrypted() && (state != STATE_NO_ERROR)) {
-        return LOCKED;
-    }
-
-    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
-    if (fileLength < headerLength) {
-        return VALUE_CORRUPTED;
-    }
-
-    ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
-    if (encryptedLength < 0) {
-        return VALUE_CORRUPTED;
-    }
-
-    ssize_t digestedLength;
-    if (isEncrypted()) {
-        if (encryptedLength % AES_BLOCK_SIZE != 0) {
-            return VALUE_CORRUPTED;
-        }
-
-        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, mBlob.vector,
-                        AES_DECRYPT);
-        digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
-        uint8_t computedDigest[MD5_DIGEST_LENGTH];
-        MD5(mBlob.digested, digestedLength, computedDigest);
-        if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
-            return VALUE_CORRUPTED;
-        }
-    } else {
-        digestedLength = encryptedLength;
-    }
-
-    ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
-    mBlob.length = ntohl(mBlob.length);
-    if (mBlob.length < 0 || mBlob.length > maxValueLength) {
-        return VALUE_CORRUPTED;
-    }
-    if (mBlob.info != 0) {
-        // move info from after padding to after data
-        memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
-    }
-    return ::NO_ERROR;
-}
diff --git a/keystore/blob.h b/keystore/blob.h
deleted file mode 100644
index 8c26b28..0000000
--- a/keystore/blob.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_BLOB_H_
-#define KEYSTORE_BLOB_H_
-
-#include <stdint.h>
-
-#include <openssl/aes.h>
-#include <openssl/md5.h>
-
-#include <keystore/keystore.h>
-
-#define VALUE_SIZE      32768
-
-/* Here is the file format. There are two parts in blob.value, the secret and
- * the description. The secret is stored in ciphertext, and its original size
- * can be found in blob.length. The description is stored after the secret in
- * plaintext, and its size is specified in blob.info. The total size of the two
- * parts must be no more than VALUE_SIZE bytes. The first field is the version,
- * the second is the blob's type, and the third byte is flags. Fields other
- * than blob.info, blob.length, and blob.value are modified by encryptBlob()
- * and decryptBlob(). Thus they should not be accessed from outside. */
-
-/* ** Note to future implementors of encryption: **
- * Currently this is the construction:
- *   metadata || Enc(MD5(data) || data)
- *
- * This should be the construction used for encrypting if re-implementing:
- *
- *   Derive independent keys for encryption and MAC:
- *     Kenc = AES_encrypt(masterKey, "Encrypt")
- *     Kmac = AES_encrypt(masterKey, "MAC")
- *
- *   Store this:
- *     metadata || AES_CTR_encrypt(Kenc, rand_IV, data) ||
- *             HMAC(Kmac, metadata || Enc(data))
- */
-struct __attribute__((packed)) blob {
-    uint8_t version;
-    uint8_t type;
-    uint8_t flags;
-    uint8_t info;
-    uint8_t vector[AES_BLOCK_SIZE];
-    uint8_t encrypted[0]; // Marks offset to encrypted data.
-    uint8_t digest[MD5_DIGEST_LENGTH];
-    uint8_t digested[0]; // Marks offset to digested data.
-    int32_t length; // in network byte order when encrypted
-    uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
-};
-
-static const uint8_t CURRENT_BLOB_VERSION = 2;
-
-typedef enum {
-    TYPE_ANY = 0, // meta type that matches anything
-    TYPE_GENERIC = 1,
-    TYPE_MASTER_KEY = 2,
-    TYPE_KEY_PAIR = 3,
-    TYPE_KEYMASTER_10 = 4,
-} BlobType;
-
-class Entropy;
-
-class Blob {
-  public:
-    Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
-         BlobType type);
-    Blob(blob b);
-
-    Blob();
-
-    const uint8_t* getValue() const { return mBlob.value; }
-
-    int32_t getLength() const { return mBlob.length; }
-
-    const uint8_t* getInfo() const { return mBlob.value + mBlob.length; }
-    uint8_t getInfoLength() const { return mBlob.info; }
-
-    uint8_t getVersion() const { return mBlob.version; }
-
-    bool isEncrypted() const;
-    void setEncrypted(bool encrypted);
-
-    bool isFallback() const { return mBlob.flags & KEYSTORE_FLAG_FALLBACK; }
-    void setFallback(bool fallback);
-
-    void setVersion(uint8_t version) { mBlob.version = version; }
-    BlobType getType() const { return BlobType(mBlob.type); }
-    void setType(BlobType type) { mBlob.type = uint8_t(type); }
-
-    ResponseCode writeBlob(const char* filename, AES_KEY* aes_key, State state, Entropy* entropy);
-    ResponseCode readBlob(const char* filename, AES_KEY* aes_key, State state);
-
-  private:
-    struct blob mBlob;
-};
-
-#endif  // KEYSTORE_BLOB_H_
diff --git a/keystore/entropy.cpp b/keystore/entropy.cpp
deleted file mode 100644
index 1bfe9a1..0000000
--- a/keystore/entropy.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "keystore"
-
-#include "entropy.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cutils/log.h>
-
-#include "keystore_utils.h"
-
-Entropy::~Entropy() {
-    if (mRandom >= 0) {
-        close(mRandom);
-    }
-}
-
-bool Entropy::open() {
-    const char* randomDevice = "/dev/urandom";
-    mRandom = TEMP_FAILURE_RETRY(::open(randomDevice, O_RDONLY));
-    if (mRandom < 0) {
-        ALOGE("open: %s: %s", randomDevice, strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-bool Entropy::generate_random_data(uint8_t* data, size_t size) const {
-    return (readFully(mRandom, data, size) == size);
-}
diff --git a/keystore/entropy.h b/keystore/entropy.h
deleted file mode 100644
index 0e4d1b2..0000000
--- a/keystore/entropy.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_ENTROPY_H_
-#define KEYSTORE_ENTROPY_H_
-
-#include <stdint.h>
-
-class Entropy {
-  public:
-    Entropy() : mRandom(-1) {}
-    ~Entropy();
-
-    bool open();
-    bool generate_random_data(uint8_t* data, size_t size) const;
-
-  private:
-    int mRandom;
-};
-
-#endif  // KEYSTORE_ENTROPY_H_
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index c136dfd..7160b5a 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -140,7 +140,7 @@
 
     virtual int32_t getState(int32_t userId) = 0;
 
-    virtual int32_t get(const String16& name, uint8_t** item, size_t* itemLength) = 0;
+    virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength) = 0;
 
     virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
             int32_t flags) = 0;
@@ -179,7 +179,7 @@
 
     virtual int32_t ungrant(const String16& name, int32_t granteeUid) = 0;
 
-    virtual int64_t getmtime(const String16& name) = 0;
+    virtual int64_t getmtime(const String16& name, int32_t uid) = 0;
 
     virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
             int32_t destUid) = 0;
@@ -197,6 +197,7 @@
     virtual int32_t getKeyCharacteristics(const String16& name,
                                           const keymaster_blob_t* clientId,
                                           const keymaster_blob_t* appData,
+                                          int32_t uid,
                                           KeyCharacteristics* outCharacteristics) = 0;
 
     virtual int32_t importKey(const String16& name, const KeymasterArguments&  params,
@@ -206,12 +207,12 @@
 
     virtual void exportKey(const String16& name, keymaster_key_format_t format,
                            const keymaster_blob_t* clientId,
-                           const keymaster_blob_t* appData, ExportResult* result) = 0;
+                           const keymaster_blob_t* appData, int32_t uid, ExportResult* result) = 0;
 
     virtual void begin(const sp<IBinder>& apptoken, const String16& name,
                        keymaster_purpose_t purpose, bool pruneable,
                        const KeymasterArguments& params, const uint8_t* entropy,
-                       size_t entropyLength, OperationResult* result) = 0;
+                       size_t entropyLength, int32_t uid, OperationResult* result) = 0;
 
     virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
                         const uint8_t* data, size_t dataLength, OperationResult* result) = 0;
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
deleted file mode 100644
index 9db333b..0000000
--- a/keystore/key_store_service.cpp
+++ /dev/null
@@ -1,1456 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "key_store_service.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#include <sstream>
-
-#include <binder/IPCThreadState.h>
-
-#include <private/android_filesystem_config.h>
-
-#include <hardware/keymaster_defs.h>
-
-#include "defaults.h"
-#include "keystore_utils.h"
-
-namespace android {
-
-const size_t MAX_OPERATIONS = 15;
-
-struct BIGNUM_Delete {
-    void operator()(BIGNUM* p) const { BN_free(p); }
-};
-typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
-
-void KeyStoreService::binderDied(const wp<IBinder>& who) {
-    auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
-    for (auto token : operations) {
-        abort(token);
-    }
-}
-
-int32_t KeyStoreService::getState(int32_t userId) {
-    if (!checkBinderPermission(P_GET_STATE)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    return mKeyStore->getState(userId);
-}
-
-int32_t KeyStoreService::get(const String16& name, uint8_t** item, size_t* itemLength) {
-    if (!checkBinderPermission(P_GET)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    String8 name8(name);
-    Blob keyBlob;
-
-    ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_GENERIC);
-    if (responseCode != ::NO_ERROR) {
-        *item = NULL;
-        *itemLength = 0;
-        return responseCode;
-    }
-
-    *item = (uint8_t*)malloc(keyBlob.getLength());
-    memcpy(*item, keyBlob.getValue(), keyBlob.getLength());
-    *itemLength = keyBlob.getLength();
-
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::insert(const String16& name, const uint8_t* item, size_t itemLength,
-                                int targetUid, int32_t flags) {
-    targetUid = getEffectiveUid(targetUid);
-    int32_t result =
-        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (result != ::NO_ERROR) {
-        return result;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-
-    Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
-    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-
-    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
-}
-
-int32_t KeyStoreService::del(const String16& name, int targetUid) {
-    targetUid = getEffectiveUid(targetUid);
-    if (!checkBinderPermission(P_DELETE, targetUid)) {
-        return ::PERMISSION_DENIED;
-    }
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-    return mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
-}
-
-int32_t KeyStoreService::exist(const String16& name, int targetUid) {
-    targetUid = getEffectiveUid(targetUid);
-    if (!checkBinderPermission(P_EXIST, targetUid)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-
-    if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
-    }
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::list(const String16& prefix, int targetUid, Vector<String16>* matches) {
-    targetUid = getEffectiveUid(targetUid);
-    if (!checkBinderPermission(P_LIST, targetUid)) {
-        return ::PERMISSION_DENIED;
-    }
-    const String8 prefix8(prefix);
-    String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid));
-
-    if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ::NO_ERROR) {
-        return ::SYSTEM_ERROR;
-    }
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::reset() {
-    if (!checkBinderPermission(P_RESET)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    mKeyStore->resetUser(get_user_id(callingUid), false);
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password) {
-    if (!checkBinderPermission(P_PASSWORD)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    const String8 password8(password);
-    // Flush the auth token table to prevent stale tokens from sticking
-    // around.
-    mAuthTokenTable.Clear();
-
-    if (password.size() == 0) {
-        ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
-        mKeyStore->resetUser(userId, true);
-        return ::NO_ERROR;
-    } else {
-        switch (mKeyStore->getState(userId)) {
-        case ::STATE_UNINITIALIZED: {
-            // generate master key, encrypt with password, write to file,
-            // initialize mMasterKey*.
-            return mKeyStore->initializeUser(password8, userId);
-        }
-        case ::STATE_NO_ERROR: {
-            // rewrite master key with new password.
-            return mKeyStore->writeMasterKey(password8, userId);
-        }
-        case ::STATE_LOCKED: {
-            ALOGE("Changing user %d's password while locked, clearing old encryption", userId);
-            mKeyStore->resetUser(userId, true);
-            return mKeyStore->initializeUser(password8, userId);
-        }
-        }
-        return ::SYSTEM_ERROR;
-    }
-}
-
-int32_t KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
-    if (!checkBinderPermission(P_USER_CHANGED)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    // Sanity check that the new user has an empty keystore.
-    if (!mKeyStore->isEmpty(userId)) {
-        ALOGW("New user %d's keystore not empty. Clearing old entries.", userId);
-    }
-    // Unconditionally clear the keystore, just to be safe.
-    mKeyStore->resetUser(userId, false);
-    if (parentId != -1) {
-        // This profile must share the same master key password as the parent profile. Because the
-        // password of the parent profile is not known here, the best we can do is copy the parent's
-        // master key and master key file. This makes this profile use the same master key as the
-        // parent profile, forever.
-        return mKeyStore->copyMasterKey(parentId, userId);
-    } else {
-        return ::NO_ERROR;
-    }
-}
-
-int32_t KeyStoreService::onUserRemoved(int32_t userId) {
-    if (!checkBinderPermission(P_USER_CHANGED)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    mKeyStore->resetUser(userId, false);
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::lock(int32_t userId) {
-    if (!checkBinderPermission(P_LOCK)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    State state = mKeyStore->getState(userId);
-    if (state != ::STATE_NO_ERROR) {
-        ALOGD("calling lock in state: %d", state);
-        return state;
-    }
-
-    mKeyStore->lock(userId);
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::unlock(int32_t userId, const String16& pw) {
-    if (!checkBinderPermission(P_UNLOCK)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    State state = mKeyStore->getState(userId);
-    if (state != ::STATE_LOCKED) {
-        switch (state) {
-        case ::STATE_NO_ERROR:
-            ALOGI("calling unlock when already unlocked, ignoring.");
-            break;
-        case ::STATE_UNINITIALIZED:
-            ALOGE("unlock called on uninitialized keystore.");
-            break;
-        default:
-            ALOGE("unlock called on keystore in unknown state: %d", state);
-            break;
-        }
-        return state;
-    }
-
-    const String8 password8(pw);
-    // read master key, decrypt with password, initialize mMasterKey*.
-    return mKeyStore->readMasterKey(password8, userId);
-}
-
-bool KeyStoreService::isEmpty(int32_t userId) {
-    if (!checkBinderPermission(P_IS_EMPTY)) {
-        return false;
-    }
-
-    return mKeyStore->isEmpty(userId);
-}
-
-int32_t KeyStoreService::generate(const String16& name, int32_t targetUid, int32_t keyType,
-                                  int32_t keySize, int32_t flags, Vector<sp<KeystoreArg>>* args) {
-    targetUid = getEffectiveUid(targetUid);
-    int32_t result =
-        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (result != ::NO_ERROR) {
-        return result;
-    }
-
-    KeymasterArguments params;
-    add_legacy_key_authorizations(keyType, &params.params);
-
-    switch (keyType) {
-    case EVP_PKEY_EC: {
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
-        if (keySize == -1) {
-            keySize = EC_DEFAULT_KEY_SIZE;
-        } else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
-            ALOGI("invalid key size %d", keySize);
-            return ::SYSTEM_ERROR;
-        }
-        params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
-        break;
-    }
-    case EVP_PKEY_RSA: {
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
-        if (keySize == -1) {
-            keySize = RSA_DEFAULT_KEY_SIZE;
-        } else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
-            ALOGI("invalid key size %d", keySize);
-            return ::SYSTEM_ERROR;
-        }
-        params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
-        unsigned long exponent = RSA_DEFAULT_EXPONENT;
-        if (args->size() > 1) {
-            ALOGI("invalid number of arguments: %zu", args->size());
-            return ::SYSTEM_ERROR;
-        } else if (args->size() == 1) {
-            sp<KeystoreArg> expArg = args->itemAt(0);
-            if (expArg != NULL) {
-                Unique_BIGNUM pubExpBn(BN_bin2bn(
-                    reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
-                if (pubExpBn.get() == NULL) {
-                    ALOGI("Could not convert public exponent to BN");
-                    return ::SYSTEM_ERROR;
-                }
-                exponent = BN_get_word(pubExpBn.get());
-                if (exponent == 0xFFFFFFFFL) {
-                    ALOGW("cannot represent public exponent as a long value");
-                    return ::SYSTEM_ERROR;
-                }
-            } else {
-                ALOGW("public exponent not read");
-                return ::SYSTEM_ERROR;
-            }
-        }
-        params.params.push_back(keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, exponent));
-        break;
-    }
-    default: {
-        ALOGW("Unsupported key type %d", keyType);
-        return ::SYSTEM_ERROR;
-    }
-    }
-
-    int32_t rc = generateKey(name, params, NULL, 0, targetUid, flags,
-                             /*outCharacteristics*/ NULL);
-    if (rc != ::NO_ERROR) {
-        ALOGW("generate failed: %d", rc);
-    }
-    return translateResultToLegacyResult(rc);
-}
-
-int32_t KeyStoreService::import(const String16& name, const uint8_t* data, size_t length,
-                                int targetUid, int32_t flags) {
-    const uint8_t* ptr = data;
-
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, length));
-    if (!pkcs8.get()) {
-        return ::SYSTEM_ERROR;
-    }
-    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
-    if (!pkey.get()) {
-        return ::SYSTEM_ERROR;
-    }
-    int type = EVP_PKEY_type(pkey->type);
-    KeymasterArguments params;
-    add_legacy_key_authorizations(type, &params.params);
-    switch (type) {
-    case EVP_PKEY_RSA:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
-        break;
-    case EVP_PKEY_EC:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
-        break;
-    default:
-        ALOGW("Unsupported key type %d", type);
-        return ::SYSTEM_ERROR;
-    }
-    int32_t rc = importKey(name, params, KM_KEY_FORMAT_PKCS8, data, length, targetUid, flags,
-                           /*outCharacteristics*/ NULL);
-    if (rc != ::NO_ERROR) {
-        ALOGW("importKey failed: %d", rc);
-    }
-    return translateResultToLegacyResult(rc);
-}
-
-int32_t KeyStoreService::sign(const String16& name, const uint8_t* data, size_t length,
-                              uint8_t** out, size_t* outLength) {
-    if (!checkBinderPermission(P_SIGN)) {
-        return ::PERMISSION_DENIED;
-    }
-    return doLegacySignVerify(name, data, length, out, outLength, NULL, 0, KM_PURPOSE_SIGN);
-}
-
-int32_t KeyStoreService::verify(const String16& name, const uint8_t* data, size_t dataLength,
-                                const uint8_t* signature, size_t signatureLength) {
-    if (!checkBinderPermission(P_VERIFY)) {
-        return ::PERMISSION_DENIED;
-    }
-    return doLegacySignVerify(name, data, dataLength, NULL, NULL, signature, signatureLength,
-                              KM_PURPOSE_VERIFY);
-}
-
-/*
- * TODO: The abstraction between things stored in hardware and regular blobs
- * of data stored on the filesystem should be moved down to keystore itself.
- * Unfortunately the Java code that calls this has naming conventions that it
- * knows about. Ideally keystore shouldn't be used to store random blobs of
- * data.
- *
- * Until that happens, it's necessary to have a separate "get_pubkey" and
- * "del_key" since the Java code doesn't really communicate what it's
- * intentions are.
- */
-int32_t KeyStoreService::get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {
-    ExportResult result;
-    exportKey(name, KM_KEY_FORMAT_X509, NULL, NULL, &result);
-    if (result.resultCode != ::NO_ERROR) {
-        ALOGW("export failed: %d", result.resultCode);
-        return translateResultToLegacyResult(result.resultCode);
-    }
-
-    *pubkey = result.exportData.release();
-    *pubkeyLength = result.dataLength;
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::grant(const String16& name, int32_t granteeUid) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
-    if (result != ::NO_ERROR) {
-        return result;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
-
-    if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
-    }
-
-    mKeyStore->addGrant(filename.string(), granteeUid);
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
-    if (result != ::NO_ERROR) {
-        return result;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
-
-    if (access(filename.string(), R_OK) == -1) {
-        return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
-    }
-
-    return mKeyStore->removeGrant(filename.string(), granteeUid) ? ::NO_ERROR : ::KEY_NOT_FOUND;
-}
-
-int64_t KeyStoreService::getmtime(const String16& name) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    if (!checkBinderPermission(P_GET)) {
-        ALOGW("permission denied for %d: getmtime", callingUid);
-        return -1L;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
-
-    if (access(filename.string(), R_OK) == -1) {
-        ALOGW("could not access %s for getmtime", filename.string());
-        return -1L;
-    }
-
-    int fd = TEMP_FAILURE_RETRY(open(filename.string(), O_NOFOLLOW, O_RDONLY));
-    if (fd < 0) {
-        ALOGW("could not open %s for getmtime", filename.string());
-        return -1L;
-    }
-
-    struct stat s;
-    int ret = fstat(fd, &s);
-    close(fd);
-    if (ret == -1) {
-        ALOGW("could not stat %s for getmtime", filename.string());
-        return -1L;
-    }
-
-    return static_cast<int64_t>(s.st_mtime);
-}
-
-int32_t KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-                                   int32_t destUid) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    pid_t spid = IPCThreadState::self()->getCallingPid();
-    if (!has_permission(callingUid, P_DUPLICATE, spid)) {
-        ALOGW("permission denied for %d: duplicate", callingUid);
-        return -1L;
-    }
-
-    State state = mKeyStore->getState(get_user_id(callingUid));
-    if (!isKeystoreUnlocked(state)) {
-        ALOGD("calling duplicate in state: %d", state);
-        return state;
-    }
-
-    if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
-        srcUid = callingUid;
-    } else if (!is_granted_to(callingUid, srcUid)) {
-        ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
-        return ::PERMISSION_DENIED;
-    }
-
-    if (destUid == -1) {
-        destUid = callingUid;
-    }
-
-    if (srcUid != destUid) {
-        if (static_cast<uid_t>(srcUid) != callingUid) {
-            ALOGD("can only duplicate from caller to other or to same uid: "
-                  "calling=%d, srcUid=%d, destUid=%d",
-                  callingUid, srcUid, destUid);
-            return ::PERMISSION_DENIED;
-        }
-
-        if (!is_granted_to(callingUid, destUid)) {
-            ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
-            return ::PERMISSION_DENIED;
-        }
-    }
-
-    String8 source8(srcKey);
-    String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid));
-
-    String8 target8(destKey);
-    String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid));
-
-    if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
-        ALOGD("destination already exists: %s", targetFile.string());
-        return ::SYSTEM_ERROR;
-    }
-
-    Blob keyBlob;
-    ResponseCode responseCode =
-        mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
-    if (responseCode != ::NO_ERROR) {
-        return responseCode;
-    }
-
-    return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
-}
-
-int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
-    return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
-}
-
-int32_t KeyStoreService::clear_uid(int64_t targetUid64) {
-    uid_t targetUid = getEffectiveUid(targetUid64);
-    if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
-        return ::PERMISSION_DENIED;
-    }
-
-    String8 prefix = String8::format("%u_", targetUid);
-    Vector<String16> aliases;
-    if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ::NO_ERROR) {
-        return ::SYSTEM_ERROR;
-    }
-
-    for (uint32_t i = 0; i < aliases.size(); i++) {
-        String8 name8(aliases[i]);
-        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
-        mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
-    }
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::addRngEntropy(const uint8_t* data, size_t dataLength) {
-    const keymaster1_device_t* device = mKeyStore->getDevice();
-    const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
-    int32_t devResult = KM_ERROR_UNIMPLEMENTED;
-    int32_t fallbackResult = KM_ERROR_UNIMPLEMENTED;
-    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
-        device->add_rng_entropy != NULL) {
-        devResult = device->add_rng_entropy(device, data, dataLength);
-    }
-    if (fallback->add_rng_entropy) {
-        fallbackResult = fallback->add_rng_entropy(fallback, data, dataLength);
-    }
-    if (devResult) {
-        return devResult;
-    }
-    if (fallbackResult) {
-        return fallbackResult;
-    }
-    return ::NO_ERROR;
-}
-
-int32_t KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
-                                     const uint8_t* entropy, size_t entropyLength, int uid,
-                                     int flags, KeyCharacteristics* outCharacteristics) {
-    uid = getEffectiveUid(uid);
-    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (rc != ::NO_ERROR) {
-        return rc;
-    }
-
-    rc = KM_ERROR_UNIMPLEMENTED;
-    bool isFallback = false;
-    keymaster_key_blob_t blob;
-    keymaster_key_characteristics_t* out = NULL;
-
-    const keymaster1_device_t* device = mKeyStore->getDevice();
-    const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
-    std::vector<keymaster_key_param_t> opParams(params.params);
-    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
-    if (device == NULL) {
-        return ::SYSTEM_ERROR;
-    }
-    // TODO: Seed from Linux RNG before this.
-    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
-        device->generate_key != NULL) {
-        if (!entropy) {
-            rc = KM_ERROR_OK;
-        } else if (device->add_rng_entropy) {
-            rc = device->add_rng_entropy(device, entropy, entropyLength);
-        } else {
-            rc = KM_ERROR_UNIMPLEMENTED;
-        }
-        if (rc == KM_ERROR_OK) {
-            rc = device->generate_key(device, &inParams, &blob, &out);
-        }
-    }
-    // If the HW device didn't support generate_key or generate_key failed
-    // fall back to the software implementation.
-    if (rc && fallback->generate_key != NULL) {
-        ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
-        isFallback = true;
-        if (!entropy) {
-            rc = KM_ERROR_OK;
-        } else if (fallback->add_rng_entropy) {
-            rc = fallback->add_rng_entropy(fallback, entropy, entropyLength);
-        } else {
-            rc = KM_ERROR_UNIMPLEMENTED;
-        }
-        if (rc == KM_ERROR_OK) {
-            rc = fallback->generate_key(fallback, &inParams, &blob, &out);
-        }
-    }
-
-    if (out) {
-        if (outCharacteristics) {
-            outCharacteristics->characteristics = *out;
-        } else {
-            keymaster_free_characteristics(out);
-        }
-        free(out);
-    }
-
-    if (rc) {
-        return rc;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
-
-    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
-    keyBlob.setFallback(isFallback);
-    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-
-    free(const_cast<uint8_t*>(blob.key_material));
-
-    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
-}
-
-int32_t KeyStoreService::getKeyCharacteristics(const String16& name,
-                                               const keymaster_blob_t* clientId,
-                                               const keymaster_blob_t* appData,
-                                               KeyCharacteristics* outCharacteristics) {
-    if (!outCharacteristics) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-
-    Blob keyBlob;
-    String8 name8(name);
-    int rc;
-
-    ResponseCode responseCode =
-        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        return responseCode;
-    }
-    keymaster_key_blob_t key;
-    key.key_material_size = keyBlob.getLength();
-    key.key_material = keyBlob.getValue();
-    keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
-    keymaster_key_characteristics_t* out = NULL;
-    if (!dev->get_key_characteristics) {
-        ALOGW("device does not implement get_key_characteristics");
-        return KM_ERROR_UNIMPLEMENTED;
-    }
-    rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
-    if (out) {
-        outCharacteristics->characteristics = *out;
-        free(out);
-    }
-    return rc ? rc : ::NO_ERROR;
-}
-
-int32_t KeyStoreService::importKey(const String16& name, const KeymasterArguments& params,
-                                   keymaster_key_format_t format, const uint8_t* keyData,
-                                   size_t keyLength, int uid, int flags,
-                                   KeyCharacteristics* outCharacteristics) {
-    uid = getEffectiveUid(uid);
-    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
-    if (rc != ::NO_ERROR) {
-        return rc;
-    }
-
-    rc = KM_ERROR_UNIMPLEMENTED;
-    bool isFallback = false;
-    keymaster_key_blob_t blob;
-    keymaster_key_characteristics_t* out = NULL;
-
-    const keymaster1_device_t* device = mKeyStore->getDevice();
-    const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
-    std::vector<keymaster_key_param_t> opParams(params.params);
-    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
-    const keymaster_blob_t input = {keyData, keyLength};
-    if (device == NULL) {
-        return ::SYSTEM_ERROR;
-    }
-    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
-        device->import_key != NULL) {
-        rc = device->import_key(device, &inParams, format, &input, &blob, &out);
-    }
-    if (rc && fallback->import_key != NULL) {
-        ALOGW("Primary keymaster device failed to import key, falling back to SW.");
-        isFallback = true;
-        rc = fallback->import_key(fallback, &inParams, format, &input, &blob, &out);
-    }
-    if (out) {
-        if (outCharacteristics) {
-            outCharacteristics->characteristics = *out;
-        } else {
-            keymaster_free_characteristics(out);
-        }
-        free(out);
-    }
-    if (rc) {
-        return rc;
-    }
-
-    String8 name8(name);
-    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
-
-    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
-    keyBlob.setFallback(isFallback);
-    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-
-    free((void*)blob.key_material);
-
-    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
-}
-
-void KeyStoreService::exportKey(const String16& name, keymaster_key_format_t format,
-                                const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
-                                ExportResult* result) {
-
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-
-    Blob keyBlob;
-    String8 name8(name);
-    int rc;
-
-    ResponseCode responseCode =
-        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        result->resultCode = responseCode;
-        return;
-    }
-    keymaster_key_blob_t key;
-    key.key_material_size = keyBlob.getLength();
-    key.key_material = keyBlob.getValue();
-    keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
-    if (!dev->export_key) {
-        result->resultCode = KM_ERROR_UNIMPLEMENTED;
-        return;
-    }
-    keymaster_blob_t output = {NULL, 0};
-    rc = dev->export_key(dev, format, &key, clientId, appData, &output);
-    result->exportData.reset(const_cast<uint8_t*>(output.data));
-    result->dataLength = output.data_length;
-    result->resultCode = rc ? rc : ::NO_ERROR;
-}
-
-void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name,
-                            keymaster_purpose_t purpose, bool pruneable,
-                            const KeymasterArguments& params, const uint8_t* entropy,
-                            size_t entropyLength, OperationResult* result) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
-        ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
-        result->resultCode = ::PERMISSION_DENIED;
-        return;
-    }
-    if (!checkAllowedOperationParams(params.params)) {
-        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
-        return;
-    }
-    Blob keyBlob;
-    String8 name8(name);
-    ResponseCode responseCode =
-        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
-    if (responseCode != ::NO_ERROR) {
-        result->resultCode = responseCode;
-        return;
-    }
-    keymaster_key_blob_t key;
-    key.key_material_size = keyBlob.getLength();
-    key.key_material = keyBlob.getValue();
-    keymaster_operation_handle_t handle;
-    keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
-    keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
-    std::vector<keymaster_key_param_t> opParams(params.params);
-    Unique_keymaster_key_characteristics characteristics;
-    characteristics.reset(new keymaster_key_characteristics_t);
-    err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
-    if (err) {
-        result->resultCode = err;
-        return;
-    }
-    const hw_auth_token_t* authToken = NULL;
-    int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
-                                      /*failOnTokenMissing*/ false);
-    // If per-operation auth is needed we need to begin the operation and
-    // the client will need to authorize that operation before calling
-    // update. Any other auth issues stop here.
-    if (authResult != ::NO_ERROR && authResult != ::OP_AUTH_NEEDED) {
-        result->resultCode = authResult;
-        return;
-    }
-    addAuthToParams(&opParams, authToken);
-    // Add entropy to the device first.
-    if (entropy) {
-        if (dev->add_rng_entropy) {
-            err = dev->add_rng_entropy(dev, entropy, entropyLength);
-        } else {
-            err = KM_ERROR_UNIMPLEMENTED;
-        }
-        if (err) {
-            result->resultCode = err;
-            return;
-        }
-    }
-    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
-
-    // Create a keyid for this key.
-    keymaster::km_id_t keyid;
-    if (!enforcement_policy.CreateKeyId(key, &keyid)) {
-        ALOGE("Failed to create a key ID for authorization checking.");
-        result->resultCode = KM_ERROR_UNKNOWN_ERROR;
-        return;
-    }
-
-    // Check that all key authorization policy requirements are met.
-    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
-    key_auths.push_back(characteristics->sw_enforced);
-    keymaster::AuthorizationSet operation_params(inParams);
-    err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
-                                                0 /* op_handle */, true /* is_begin_operation */);
-    if (err) {
-        result->resultCode = err;
-        return;
-    }
-
-    keymaster_key_param_set_t outParams = {NULL, 0};
-
-    // If there are more than MAX_OPERATIONS, abort the oldest operation that was started as
-    // pruneable.
-    while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) {
-        ALOGD("Reached or exceeded concurrent operations limit");
-        if (!pruneOperation()) {
-            break;
-        }
-    }
-
-    err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
-    if (err != KM_ERROR_OK) {
-        ALOGE("Got error %d from begin()", err);
-    }
-
-    // If there are too many operations abort the oldest operation that was
-    // started as pruneable and try again.
-    while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
-        ALOGE("Ran out of operation handles");
-        if (!pruneOperation()) {
-            break;
-        }
-        err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
-    }
-    if (err) {
-        result->resultCode = err;
-        return;
-    }
-
-    sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev, appToken,
-                                                            characteristics.release(), pruneable);
-    if (authToken) {
-        mOperationMap.setOperationAuthToken(operationToken, authToken);
-    }
-    // Return the authentication lookup result. If this is a per operation
-    // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
-    // application should get an auth token using the handle before the
-    // first call to update, which will fail if keystore hasn't received the
-    // auth token.
-    result->resultCode = authResult;
-    result->token = operationToken;
-    result->handle = handle;
-    if (outParams.params) {
-        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
-        free(outParams.params);
-    }
-}
-
-void KeyStoreService::update(const sp<IBinder>& token, const KeymasterArguments& params,
-                             const uint8_t* data, size_t dataLength, OperationResult* result) {
-    if (!checkAllowedOperationParams(params.params)) {
-        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
-        return;
-    }
-    const keymaster1_device_t* dev;
-    keymaster_operation_handle_t handle;
-    keymaster_purpose_t purpose;
-    keymaster::km_id_t keyid;
-    const keymaster_key_characteristics_t* characteristics;
-    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
-        return;
-    }
-    std::vector<keymaster_key_param_t> opParams(params.params);
-    int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
-    if (authResult != ::NO_ERROR) {
-        result->resultCode = authResult;
-        return;
-    }
-    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
-    keymaster_blob_t input = {data, dataLength};
-    size_t consumed = 0;
-    keymaster_blob_t output = {NULL, 0};
-    keymaster_key_param_set_t outParams = {NULL, 0};
-
-    // Check that all key authorization policy requirements are met.
-    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
-    key_auths.push_back(characteristics->sw_enforced);
-    keymaster::AuthorizationSet operation_params(inParams);
-    result->resultCode = enforcement_policy.AuthorizeOperation(
-        purpose, keyid, key_auths, operation_params, handle, false /* is_begin_operation */);
-    if (result->resultCode) {
-        return;
-    }
-
-    keymaster_error_t err =
-        dev->update(dev, handle, &inParams, &input, &consumed, &outParams, &output);
-    result->data.reset(const_cast<uint8_t*>(output.data));
-    result->dataLength = output.data_length;
-    result->inputConsumed = consumed;
-    result->resultCode = err ? (int32_t)err : ::NO_ERROR;
-    if (outParams.params) {
-        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
-        free(outParams.params);
-    }
-}
-
-void KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
-                             const uint8_t* signature, size_t signatureLength,
-                             const uint8_t* entropy, size_t entropyLength,
-                             OperationResult* result) {
-    if (!checkAllowedOperationParams(params.params)) {
-        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
-        return;
-    }
-    const keymaster1_device_t* dev;
-    keymaster_operation_handle_t handle;
-    keymaster_purpose_t purpose;
-    keymaster::km_id_t keyid;
-    const keymaster_key_characteristics_t* characteristics;
-    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
-        return;
-    }
-    std::vector<keymaster_key_param_t> opParams(params.params);
-    int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
-    if (authResult != ::NO_ERROR) {
-        result->resultCode = authResult;
-        return;
-    }
-    keymaster_error_t err;
-    if (entropy) {
-        if (dev->add_rng_entropy) {
-            err = dev->add_rng_entropy(dev, entropy, entropyLength);
-        } else {
-            err = KM_ERROR_UNIMPLEMENTED;
-        }
-        if (err) {
-            result->resultCode = err;
-            return;
-        }
-    }
-
-    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
-    keymaster_blob_t input = {signature, signatureLength};
-    keymaster_blob_t output = {NULL, 0};
-    keymaster_key_param_set_t outParams = {NULL, 0};
-
-    // Check that all key authorization policy requirements are met.
-    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
-    key_auths.push_back(characteristics->sw_enforced);
-    keymaster::AuthorizationSet operation_params(inParams);
-    err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params, handle,
-                                                false /* is_begin_operation */);
-    if (err) {
-        result->resultCode = err;
-        return;
-    }
-
-    err = dev->finish(dev, handle, &inParams, &input, &outParams, &output);
-    // Remove the operation regardless of the result
-    mOperationMap.removeOperation(token);
-    mAuthTokenTable.MarkCompleted(handle);
-
-    result->data.reset(const_cast<uint8_t*>(output.data));
-    result->dataLength = output.data_length;
-    result->resultCode = err ? (int32_t)err : ::NO_ERROR;
-    if (outParams.params) {
-        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
-        free(outParams.params);
-    }
-}
-
-int32_t KeyStoreService::abort(const sp<IBinder>& token) {
-    const keymaster1_device_t* dev;
-    keymaster_operation_handle_t handle;
-    keymaster_purpose_t purpose;
-    keymaster::km_id_t keyid;
-    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
-        return KM_ERROR_INVALID_OPERATION_HANDLE;
-    }
-    mOperationMap.removeOperation(token);
-    int32_t rc;
-    if (!dev->abort) {
-        rc = KM_ERROR_UNIMPLEMENTED;
-    } else {
-        rc = dev->abort(dev, handle);
-    }
-    mAuthTokenTable.MarkCompleted(handle);
-    if (rc) {
-        return rc;
-    }
-    return ::NO_ERROR;
-}
-
-bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
-    const keymaster1_device_t* dev;
-    keymaster_operation_handle_t handle;
-    const keymaster_key_characteristics_t* characteristics;
-    keymaster_purpose_t purpose;
-    keymaster::km_id_t keyid;
-    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-        return false;
-    }
-    const hw_auth_token_t* authToken = NULL;
-    mOperationMap.getOperationAuthToken(token, &authToken);
-    std::vector<keymaster_key_param_t> ignored;
-    int32_t authResult = addOperationAuthTokenIfNeeded(token, &ignored);
-    return authResult == ::NO_ERROR;
-}
-
-int32_t KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
-    if (!checkBinderPermission(P_ADD_AUTH)) {
-        ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
-        return ::PERMISSION_DENIED;
-    }
-    if (length != sizeof(hw_auth_token_t)) {
-        return KM_ERROR_INVALID_ARGUMENT;
-    }
-    hw_auth_token_t* authToken = new hw_auth_token_t;
-    memcpy(reinterpret_cast<void*>(authToken), token, sizeof(hw_auth_token_t));
-    // The table takes ownership of authToken.
-    mAuthTokenTable.AddAuthenticationToken(authToken);
-    return ::NO_ERROR;
-}
-
-/**
- * Prune the oldest pruneable operation.
- */
-bool KeyStoreService::pruneOperation() {
-    sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation();
-    ALOGD("Trying to prune operation %p", oldest.get());
-    size_t op_count_before_abort = mOperationMap.getOperationCount();
-    // We mostly ignore errors from abort() because all we care about is whether at least
-    // one operation has been removed.
-    int abort_error = abort(oldest);
-    if (mOperationMap.getOperationCount() >= op_count_before_abort) {
-        ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
-        return false;
-    }
-    return true;
-}
-
-/**
- * Get the effective target uid for a binder operation that takes an
- * optional uid as the target.
- */
-uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
-    if (targetUid == UID_SELF) {
-        return IPCThreadState::self()->getCallingUid();
-    }
-    return static_cast<uid_t>(targetUid);
-}
-
-/**
- * Check if the caller of the current binder method has the required
- * permission and if acting on other uids the grants to do so.
- */
-bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    pid_t spid = IPCThreadState::self()->getCallingPid();
-    if (!has_permission(callingUid, permission, spid)) {
-        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
-        return false;
-    }
-    if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
-        ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
-        return false;
-    }
-    return true;
-}
-
-/**
- * Check if the caller of the current binder method has the required
- * permission and the target uid is the caller or the caller is system.
- */
-bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    pid_t spid = IPCThreadState::self()->getCallingPid();
-    if (!has_permission(callingUid, permission, spid)) {
-        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
-        return false;
-    }
-    return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
-}
-
-/**
- * Check if the caller of the current binder method has the required
- * permission or the target of the operation is the caller's uid. This is
- * for operation where the permission is only for cross-uid activity and all
- * uids are allowed to act on their own (ie: clearing all entries for a
- * given uid).
- */
-bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
-    uid_t callingUid = IPCThreadState::self()->getCallingUid();
-    if (getEffectiveUid(targetUid) == callingUid) {
-        return true;
-    } else {
-        return checkBinderPermission(permission, targetUid);
-    }
-}
-
-/**
- * Helper method to check that the caller has the required permission as
- * well as the keystore is in the unlocked state if checkUnlocked is true.
- *
- * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
- * otherwise the state of keystore when not unlocked and checkUnlocked is
- * true.
- */
-int32_t KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
-                                                               bool checkUnlocked) {
-    if (!checkBinderPermission(permission, targetUid)) {
-        return ::PERMISSION_DENIED;
-    }
-    State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
-    if (checkUnlocked && !isKeystoreUnlocked(state)) {
-        return state;
-    }
-
-    return ::NO_ERROR;
-}
-
-inline bool KeyStoreService::isKeystoreUnlocked(State state) {
-    switch (state) {
-    case ::STATE_NO_ERROR:
-        return true;
-    case ::STATE_UNINITIALIZED:
-    case ::STATE_LOCKED:
-        return false;
-    }
-    return false;
-}
-
-bool KeyStoreService::isKeyTypeSupported(const keymaster1_device_t* device,
-                                         keymaster_keypair_t keyType) {
-    const int32_t device_api = device->common.module->module_api_version;
-    if (device_api == KEYMASTER_MODULE_API_VERSION_0_2) {
-        switch (keyType) {
-        case TYPE_RSA:
-        case TYPE_DSA:
-        case TYPE_EC:
-            return true;
-        default:
-            return false;
-        }
-    } else if (device_api >= KEYMASTER_MODULE_API_VERSION_0_3) {
-        switch (keyType) {
-        case TYPE_RSA:
-            return true;
-        case TYPE_DSA:
-            return device->flags & KEYMASTER_SUPPORTS_DSA;
-        case TYPE_EC:
-            return device->flags & KEYMASTER_SUPPORTS_EC;
-        default:
-            return false;
-        }
-    } else {
-        return keyType == TYPE_RSA;
-    }
-}
-
-/**
- * Check that all keymaster_key_param_t's provided by the application are
- * allowed. Any parameter that keystore adds itself should be disallowed here.
- */
-bool KeyStoreService::checkAllowedOperationParams(
-    const std::vector<keymaster_key_param_t>& params) {
-    for (auto param : params) {
-        switch (param.tag) {
-        case KM_TAG_AUTH_TOKEN:
-            return false;
-        default:
-            break;
-        }
-    }
-    return true;
-}
-
-keymaster_error_t KeyStoreService::getOperationCharacteristics(
-    const keymaster_key_blob_t& key, const keymaster1_device_t* dev,
-    const std::vector<keymaster_key_param_t>& params, keymaster_key_characteristics_t* out) {
-    UniquePtr<keymaster_blob_t> appId;
-    UniquePtr<keymaster_blob_t> appData;
-    for (auto param : params) {
-        if (param.tag == KM_TAG_APPLICATION_ID) {
-            appId.reset(new keymaster_blob_t);
-            appId->data = param.blob.data;
-            appId->data_length = param.blob.data_length;
-        } else if (param.tag == KM_TAG_APPLICATION_DATA) {
-            appData.reset(new keymaster_blob_t);
-            appData->data = param.blob.data;
-            appData->data_length = param.blob.data_length;
-        }
-    }
-    keymaster_key_characteristics_t* result = NULL;
-    if (!dev->get_key_characteristics) {
-        return KM_ERROR_UNIMPLEMENTED;
-    }
-    keymaster_error_t error =
-        dev->get_key_characteristics(dev, &key, appId.get(), appData.get(), &result);
-    if (result) {
-        *out = *result;
-        free(result);
-    }
-    return error;
-}
-
-/**
- * Get the auth token for this operation from the auth token table.
- *
- * Returns ::NO_ERROR if the auth token was set or none was required.
- *         ::OP_AUTH_NEEDED if it is a per op authorization, no
- *         authorization token exists for that operation and
- *         failOnTokenMissing is false.
- *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
- *         token for the operation
- */
-int32_t KeyStoreService::getAuthToken(const keymaster_key_characteristics_t* characteristics,
-                                      keymaster_operation_handle_t handle,
-                                      keymaster_purpose_t purpose,
-                                      const hw_auth_token_t** authToken, bool failOnTokenMissing) {
-
-    std::vector<keymaster_key_param_t> allCharacteristics;
-    for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
-        allCharacteristics.push_back(characteristics->sw_enforced.params[i]);
-    }
-    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
-        allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
-    }
-    keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
-        allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
-    switch (err) {
-    case keymaster::AuthTokenTable::OK:
-    case keymaster::AuthTokenTable::AUTH_NOT_REQUIRED:
-        return ::NO_ERROR;
-    case keymaster::AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
-    case keymaster::AuthTokenTable::AUTH_TOKEN_EXPIRED:
-    case keymaster::AuthTokenTable::AUTH_TOKEN_WRONG_SID:
-        return KM_ERROR_KEY_USER_NOT_AUTHENTICATED;
-    case keymaster::AuthTokenTable::OP_HANDLE_REQUIRED:
-        return failOnTokenMissing ? (int32_t)KM_ERROR_KEY_USER_NOT_AUTHENTICATED
-                                  : (int32_t)::OP_AUTH_NEEDED;
-    default:
-        ALOGE("Unexpected FindAuthorization return value %d", err);
-        return KM_ERROR_INVALID_ARGUMENT;
-    }
-}
-
-inline void KeyStoreService::addAuthToParams(std::vector<keymaster_key_param_t>* params,
-                                             const hw_auth_token_t* token) {
-    if (token) {
-        params->push_back(keymaster_param_blob(
-            KM_TAG_AUTH_TOKEN, reinterpret_cast<const uint8_t*>(token), sizeof(hw_auth_token_t)));
-    }
-}
-
-/**
- * Add the auth token for the operation to the param list if the operation
- * requires authorization. Uses the cached result in the OperationMap if available
- * otherwise gets the token from the AuthTokenTable and caches the result.
- *
- * Returns ::NO_ERROR if the auth token was added or not needed.
- *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
- *         authenticated.
- *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
- *         operation token.
- */
-int32_t KeyStoreService::addOperationAuthTokenIfNeeded(sp<IBinder> token,
-                                                       std::vector<keymaster_key_param_t>* params) {
-    const hw_auth_token_t* authToken = NULL;
-    mOperationMap.getOperationAuthToken(token, &authToken);
-    if (!authToken) {
-        const keymaster1_device_t* dev;
-        keymaster_operation_handle_t handle;
-        const keymaster_key_characteristics_t* characteristics = NULL;
-        keymaster_purpose_t purpose;
-        keymaster::km_id_t keyid;
-        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
-            return KM_ERROR_INVALID_OPERATION_HANDLE;
-        }
-        int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
-        if (result != ::NO_ERROR) {
-            return result;
-        }
-        if (authToken) {
-            mOperationMap.setOperationAuthToken(token, authToken);
-        }
-    }
-    addAuthToParams(params, authToken);
-    return ::NO_ERROR;
-}
-
-/**
- * Translate a result value to a legacy return value. All keystore errors are
- * preserved and keymaster errors become SYSTEM_ERRORs
- */
-inline int32_t KeyStoreService::translateResultToLegacyResult(int32_t result) {
-    if (result > 0) {
-        return result;
-    }
-    return ::SYSTEM_ERROR;
-}
-
-keymaster_key_param_t*
-KeyStoreService::getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
-    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
-        if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
-            return &characteristics->hw_enforced.params[i];
-        }
-    }
-    for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
-        if (characteristics->sw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
-            return &characteristics->sw_enforced.params[i];
-        }
-    }
-    return NULL;
-}
-
-void KeyStoreService::addLegacyBeginParams(const String16& name,
-                                           std::vector<keymaster_key_param_t>& params) {
-    // All legacy keys are DIGEST_NONE/PAD_NONE.
-    params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
-    params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
-
-    // Look up the algorithm of the key.
-    KeyCharacteristics characteristics;
-    int32_t rc = getKeyCharacteristics(name, NULL, NULL, &characteristics);
-    if (rc != ::NO_ERROR) {
-        ALOGE("Failed to get key characteristics");
-        return;
-    }
-    keymaster_key_param_t* algorithm = getKeyAlgorithm(&characteristics.characteristics);
-    if (!algorithm) {
-        ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
-        return;
-    }
-    params.push_back(*algorithm);
-}
-
-int32_t KeyStoreService::doLegacySignVerify(const String16& name, const uint8_t* data,
-                                            size_t length, uint8_t** out, size_t* outLength,
-                                            const uint8_t* signature, size_t signatureLength,
-                                            keymaster_purpose_t purpose) {
-
-    std::basic_stringstream<uint8_t> outBuffer;
-    OperationResult result;
-    KeymasterArguments inArgs;
-    addLegacyBeginParams(name, inArgs.params);
-    sp<IBinder> appToken(new BBinder);
-    sp<IBinder> token;
-
-    begin(appToken, name, purpose, true, inArgs, NULL, 0, &result);
-    if (result.resultCode != ResponseCode::NO_ERROR) {
-        if (result.resultCode == ::KEY_NOT_FOUND) {
-            ALOGW("Key not found");
-        } else {
-            ALOGW("Error in begin: %d", result.resultCode);
-        }
-        return translateResultToLegacyResult(result.resultCode);
-    }
-    inArgs.params.clear();
-    token = result.token;
-    size_t consumed = 0;
-    size_t lastConsumed = 0;
-    do {
-        update(token, inArgs, data + consumed, length - consumed, &result);
-        if (result.resultCode != ResponseCode::NO_ERROR) {
-            ALOGW("Error in update: %d", result.resultCode);
-            return translateResultToLegacyResult(result.resultCode);
-        }
-        if (out) {
-            outBuffer.write(result.data.get(), result.dataLength);
-        }
-        lastConsumed = result.inputConsumed;
-        consumed += lastConsumed;
-    } while (consumed < length && lastConsumed > 0);
-
-    if (consumed != length) {
-        ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
-        return ::SYSTEM_ERROR;
-    }
-
-    finish(token, inArgs, signature, signatureLength, NULL, 0, &result);
-    if (result.resultCode != ResponseCode::NO_ERROR) {
-        ALOGW("Error in finish: %d", result.resultCode);
-        return translateResultToLegacyResult(result.resultCode);
-    }
-    if (out) {
-        outBuffer.write(result.data.get(), result.dataLength);
-    }
-
-    if (out) {
-        auto buf = outBuffer.str();
-        *out = new uint8_t[buf.size()];
-        memcpy(*out, buf.c_str(), buf.size());
-        *outLength = buf.size();
-    }
-
-    return ::NO_ERROR;
-}
-
-}  // namespace android
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
deleted file mode 100644
index 1f0f2cc..0000000
--- a/keystore/key_store_service.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_KEYSTORE_SERVICE_H_
-#define KEYSTORE_KEYSTORE_SERVICE_H_
-
-#include <keystore/IKeystoreService.h>
-
-#include "auth_token_table.h"
-#include "keystore.h"
-#include "keystore_keymaster_enforcement.h"
-#include "operation.h"
-#include "permissions.h"
-
-namespace android {
-
-class KeyStoreService : public BnKeystoreService, public IBinder::DeathRecipient {
-  public:
-    KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
-
-    void binderDied(const wp<IBinder>& who);
-
-    int32_t getState(int32_t userId);
-
-    int32_t get(const String16& name, uint8_t** item, size_t* itemLength);
-    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int targetUid,
-                   int32_t flags);
-    int32_t del(const String16& name, int targetUid);
-    int32_t exist(const String16& name, int targetUid);
-    int32_t list(const String16& prefix, int targetUid, Vector<String16>* matches);
-
-    int32_t reset();
-
-    int32_t onUserPasswordChanged(int32_t userId, const String16& password);
-    int32_t onUserAdded(int32_t userId, int32_t parentId);
-    int32_t onUserRemoved(int32_t userId);
-
-    int32_t lock(int32_t userId);
-    int32_t unlock(int32_t userId, const String16& pw);
-
-    bool isEmpty(int32_t userId);
-
-    int32_t generate(const String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
-                     int32_t flags, Vector<sp<KeystoreArg>>* args);
-    int32_t import(const String16& name, const uint8_t* data, size_t length, int targetUid,
-                   int32_t flags);
-    int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
-                 size_t* outLength);
-    int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
-                   const uint8_t* signature, size_t signatureLength);
-
-    /*
-     * TODO: The abstraction between things stored in hardware and regular blobs
-     * of data stored on the filesystem should be moved down to keystore itself.
-     * Unfortunately the Java code that calls this has naming conventions that it
-     * knows about. Ideally keystore shouldn't be used to store random blobs of
-     * data.
-     *
-     * Until that happens, it's necessary to have a separate "get_pubkey" and
-     * "del_key" since the Java code doesn't really communicate what it's
-     * intentions are.
-     */
-    int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength);
-
-    int32_t grant(const String16& name, int32_t granteeUid);
-    int32_t ungrant(const String16& name, int32_t granteeUid);
-
-    int64_t getmtime(const String16& name);
-
-    int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-                      int32_t destUid);
-
-    int32_t is_hardware_backed(const String16& keyType);
-
-    int32_t clear_uid(int64_t targetUid64);
-
-    int32_t addRngEntropy(const uint8_t* data, size_t dataLength);
-    int32_t generateKey(const String16& name, const KeymasterArguments& params,
-                        const uint8_t* entropy, size_t entropyLength, int uid, int flags,
-                        KeyCharacteristics* outCharacteristics);
-    int32_t getKeyCharacteristics(const String16& name, const keymaster_blob_t* clientId,
-                                  const keymaster_blob_t* appData,
-                                  KeyCharacteristics* outCharacteristics);
-    int32_t importKey(const String16& name, const KeymasterArguments& params,
-                      keymaster_key_format_t format, const uint8_t* keyData, size_t keyLength,
-                      int uid, int flags, KeyCharacteristics* outCharacteristics);
-    void exportKey(const String16& name, keymaster_key_format_t format,
-                   const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
-                   ExportResult* result);
-    void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
-               bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
-               size_t entropyLength, OperationResult* result);
-    void update(const sp<IBinder>& token, const KeymasterArguments& params, const uint8_t* data,
-                size_t dataLength, OperationResult* result);
-    void finish(const sp<IBinder>& token, const KeymasterArguments& params,
-                const uint8_t* signature, size_t signatureLength, const uint8_t* entropy,
-                size_t entropyLength, OperationResult* result);
-    int32_t abort(const sp<IBinder>& token);
-
-    bool isOperationAuthorized(const sp<IBinder>& token);
-
-    int32_t addAuthToken(const uint8_t* token, size_t length);
-
-  private:
-    static const int32_t UID_SELF = -1;
-
-    /**
-     * Prune the oldest pruneable operation.
-     */
-    bool pruneOperation();
-
-    /**
-     * Get the effective target uid for a binder operation that takes an
-     * optional uid as the target.
-     */
-    uid_t getEffectiveUid(int32_t targetUid);
-
-    /**
-     * Check if the caller of the current binder method has the required
-     * permission and if acting on other uids the grants to do so.
-     */
-    bool checkBinderPermission(perm_t permission, int32_t targetUid = UID_SELF);
-
-    /**
-     * Check if the caller of the current binder method has the required
-     * permission and the target uid is the caller or the caller is system.
-     */
-    bool checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid);
-
-    /**
-     * Check if the caller of the current binder method has the required
-     * permission or the target of the operation is the caller's uid. This is
-     * for operation where the permission is only for cross-uid activity and all
-     * uids are allowed to act on their own (ie: clearing all entries for a
-     * given uid).
-     */
-    bool checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid);
-
-    /**
-     * Helper method to check that the caller has the required permission as
-     * well as the keystore is in the unlocked state if checkUnlocked is true.
-     *
-     * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
-     * otherwise the state of keystore when not unlocked and checkUnlocked is
-     * true.
-     */
-    int32_t checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid = -1,
-                                                  bool checkUnlocked = true);
-
-    bool isKeystoreUnlocked(State state);
-
-    bool isKeyTypeSupported(const keymaster1_device_t* device, keymaster_keypair_t keyType);
-
-    /**
-     * Check that all keymaster_key_param_t's provided by the application are
-     * allowed. Any parameter that keystore adds itself should be disallowed here.
-     */
-    bool checkAllowedOperationParams(const std::vector<keymaster_key_param_t>& params);
-
-    keymaster_error_t getOperationCharacteristics(const keymaster_key_blob_t& key,
-                                                  const keymaster1_device_t* dev,
-                                                  const std::vector<keymaster_key_param_t>& params,
-                                                  keymaster_key_characteristics_t* out);
-
-    /**
-     * Get the auth token for this operation from the auth token table.
-     *
-     * Returns ::NO_ERROR if the auth token was set or none was required.
-     *         ::OP_AUTH_NEEDED if it is a per op authorization, no
-     *         authorization token exists for that operation and
-     *         failOnTokenMissing is false.
-     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
-     *         token for the operation
-     */
-    int32_t getAuthToken(const keymaster_key_characteristics_t* characteristics,
-                         keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
-                         const hw_auth_token_t** authToken, bool failOnTokenMissing = true);
-
-    void addAuthToParams(std::vector<keymaster_key_param_t>* params, const hw_auth_token_t* token);
-
-    /**
-     * Add the auth token for the operation to the param list if the operation
-     * requires authorization. Uses the cached result in the OperationMap if available
-     * otherwise gets the token from the AuthTokenTable and caches the result.
-     *
-     * Returns ::NO_ERROR if the auth token was added or not needed.
-     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
-     *         authenticated.
-     *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
-     *         operation token.
-     */
-    int32_t addOperationAuthTokenIfNeeded(sp<IBinder> token,
-                                          std::vector<keymaster_key_param_t>* params);
-
-    /**
-     * Translate a result value to a legacy return value. All keystore errors are
-     * preserved and keymaster errors become SYSTEM_ERRORs
-     */
-    int32_t translateResultToLegacyResult(int32_t result);
-
-    keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics);
-
-    void addLegacyBeginParams(const String16& name, std::vector<keymaster_key_param_t>& params);
-
-    int32_t doLegacySignVerify(const String16& name, const uint8_t* data, size_t length,
-                               uint8_t** out, size_t* outLength, const uint8_t* signature,
-                               size_t signatureLength, keymaster_purpose_t purpose);
-
-    ::KeyStore* mKeyStore;
-    OperationMap mOperationMap;
-    keymaster::AuthTokenTable mAuthTokenTable;
-    KeystoreKeymasterEnforcement enforcement_policy;
-};
-
-};  // namespace android
-
-#endif  // KEYSTORE_KEYSTORE_SERVICE_H_
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 0d8dc21..9eb6c7b 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,72 +14,445 @@
  * limitations under the License.
  */
 
-#include "keystore.h"
+//#define LOG_NDEBUG 0
+#define LOG_TAG "keystore"
 
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
 #include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
 
+#include <openssl/aes.h>
 #include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/pem.h>
 
-#include <utils/String16.h>
+#include <hardware/keymaster0.h>
+
+#include <keymaster/soft_keymaster_device.h>
+#include <keymaster/soft_keymaster_logger.h>
+#include <keymaster/softkeymaster.h>
+
+#include <UniquePtr.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
 
 #include <keystore/IKeystoreService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
-#include "keystore_utils.h"
-#include "permissions.h"
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
 
-const char* KeyStore::sOldMasterKey = ".masterkey";
-const char* KeyStore::sMetaDataFile = ".metadata";
+#include <keystore/keystore.h>
 
-const android::String16 KeyStore::sRSAKeyType("RSA");
-const android::String16 KeyStore::sECKeyType("EC");
+#include <selinux/android.h>
 
-KeyStore::KeyStore(Entropy* entropy, keymaster1_device_t* device, keymaster1_device_t* fallback)
-    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback) {
-    memset(&mMetaData, '\0', sizeof(mMetaData));
-}
+#include <sstream>
 
-KeyStore::~KeyStore() {
-    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
-        delete *it;
+#include "auth_token_table.h"
+#include "defaults.h"
+#include "keystore_keymaster_enforcement.h"
+#include "operation.h"
+
+/* KeyStore is a secured storage for key-value pairs. In this implementation,
+ * each file stores one key-value pair. Keys are encoded in file names, and
+ * values are encrypted with checksums. The encryption key is protected by a
+ * user-defined password. To keep things simple, buffers are always larger than
+ * the maximum space we needed, so boundary checks on buffers are omitted. */
+
+#define KEY_SIZE        ((NAME_MAX - 15) / 2)
+#define VALUE_SIZE      32768
+#define PASSWORD_SIZE   VALUE_SIZE
+const size_t MAX_OPERATIONS = 15;
+
+using keymaster::SoftKeymasterDevice;
+
+struct BIGNUM_Delete {
+    void operator()(BIGNUM* p) const {
+        BN_free(p);
     }
-    mGrants.clear();
+};
+typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
 
-    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
-         it++) {
-        delete *it;
+struct BIO_Delete {
+    void operator()(BIO* p) const {
+        BIO_free(p);
     }
-    mMasterKeys.clear();
-}
+};
+typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
 
-ResponseCode KeyStore::initialize() {
-    readMetaData();
-    if (upgradeKeystore()) {
-        writeMetaData();
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) const {
+        EVP_PKEY_free(p);
+    }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const {
+        PKCS8_PRIV_KEY_INFO_free(p);
+    }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
+    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster0_device_t* km0_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster0_open(mod, &km0_device);
+    if (rc) {
+        ALOGE("Error opening keystore keymaster0 device.");
+        goto err;
     }
 
-    return ::NO_ERROR;
+    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
+        km0_device->common.close(&km0_device->common);
+        km0_device = NULL;
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster_device();
+        return 0;
+    }
+
+    ALOGE("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km0_device);
+    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster_device();
+    return 0;
+
+err:
+    if (km0_device)
+        km0_device->common.close(&km0_device->common);
+    *dev = NULL;
+    return rc;
 }
 
-ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
-    UserState* userState = getUserState(userId);
-    return userState->initialize(pw, mEntropy);
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster1_device_t* km1_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster1_open(mod, &km1_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster1 device", rc);
+        goto err;
+    }
+
+    error = soft_keymaster->SetHardwareDevice(km1_device);
+    km1_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    if (!soft_keymaster->Keymaster1DeviceIsGood()) {
+        ALOGI("Keymaster1 module is incomplete, using SoftKeymasterDevice wrapper");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster_device();
+        return 0;
+    } else {
+        ALOGI("Keymaster1 module is good, destroying wrapper and re-opening");
+        soft_keymaster.reset(NULL);
+        rc = keymaster1_open(mod, &km1_device);
+        if (rc) {
+            ALOGE("Error %d re-opening keystore keymaster1 device.", rc);
+            goto err;
+        }
+        *dev = km1_device;
+        return 0;
+    }
+
+err:
+    if (km1_device)
+        km1_device->common.close(&km1_device->common);
+    *dev = NULL;
+    return rc;
+
 }
 
-ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
-    UserState* userState = getUserState(dstUser);
-    UserState* initState = getUserState(srcUser);
-    return userState->copyMasterKey(initState);
+static int keymaster_device_initialize(keymaster1_device_t** dev) {
+    const hw_module_t* mod;
+
+    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    if (rc) {
+        ALOGI("Could not find any keystore module, using software-only implementation.");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = (new SoftKeymasterDevice)->keymaster_device();
+        return 0;
+    }
+
+    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+        return keymaster0_device_initialize(mod, dev);
+    } else {
+        return keymaster1_device_initialize(mod, dev);
+    }
 }
 
-ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
-    UserState* userState = getUserState(userId);
-    return userState->writeMasterKey(pw, mEntropy);
+// softkeymaster_logger appears not to be used in keystore, but it installs itself as the
+// logger used by SoftKeymasterDevice.
+static keymaster::SoftKeymasterLogger softkeymaster_logger;
+
+static int fallback_keymaster_device_initialize(keymaster1_device_t** dev) {
+    *dev = (new SoftKeymasterDevice)->keymaster_device();
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    return 0;
 }
 
-ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
-    UserState* userState = getUserState(userId);
-    return userState->readMasterKey(pw, mEntropy);
+static void keymaster_device_release(keymaster1_device_t* dev) {
+    dev->common.close(&dev->common);
+}
+
+static void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+    if (keyType == EVP_PKEY_RSA) {
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
+    }
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
+    params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
+    params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
+    params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
+}
+
+/***************
+ * PERMISSIONS *
+ ***************/
+
+/* Here are the permissions, actions, users, and the main function. */
+typedef enum {
+    P_GET_STATE     = 1 << 0,
+    P_GET           = 1 << 1,
+    P_INSERT        = 1 << 2,
+    P_DELETE        = 1 << 3,
+    P_EXIST         = 1 << 4,
+    P_LIST          = 1 << 5,
+    P_RESET         = 1 << 6,
+    P_PASSWORD      = 1 << 7,
+    P_LOCK          = 1 << 8,
+    P_UNLOCK        = 1 << 9,
+    P_IS_EMPTY      = 1 << 10,
+    P_SIGN          = 1 << 11,
+    P_VERIFY        = 1 << 12,
+    P_GRANT         = 1 << 13,
+    P_DUPLICATE     = 1 << 14,
+    P_CLEAR_UID     = 1 << 15,
+    P_ADD_AUTH      = 1 << 16,
+    P_USER_CHANGED  = 1 << 17,
+} perm_t;
+
+static struct user_euid {
+    uid_t uid;
+    uid_t euid;
+} user_euids[] = {
+    {AID_VPN, AID_SYSTEM},
+    {AID_WIFI, AID_SYSTEM},
+    {AID_ROOT, AID_SYSTEM},
+};
+
+/* perm_labels associcated with keystore_key SELinux class verbs. */
+const char *perm_labels[] = {
+    "get_state",
+    "get",
+    "insert",
+    "delete",
+    "exist",
+    "list",
+    "reset",
+    "password",
+    "lock",
+    "unlock",
+    "is_empty",
+    "sign",
+    "verify",
+    "grant",
+    "duplicate",
+    "clear_uid",
+    "add_auth",
+    "user_changed",
+};
+
+static struct user_perm {
+    uid_t uid;
+    perm_t perms;
+} user_perms[] = {
+    {AID_SYSTEM, static_cast<perm_t>((uint32_t)(~0)) },
+    {AID_VPN,    static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY) },
+    {AID_WIFI,   static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY) },
+    {AID_ROOT,   static_cast<perm_t>(P_GET) },
+};
+
+static const perm_t DEFAULT_PERMS = static_cast<perm_t>(P_GET_STATE | P_GET | P_INSERT | P_DELETE
+                                                        | P_EXIST | P_LIST | P_SIGN | P_VERIFY);
+
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+};
+
+static char *tctx;
+static int ks_is_selinux_enabled;
+
+static const char *get_perm_label(perm_t perm) {
+    unsigned int index = ffs(perm);
+    if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) {
+        return perm_labels[index - 1];
+    } else {
+        ALOGE("Keystore: Failed to retrieve permission label.\n");
+        abort();
+    }
+}
+
+/**
+ * Returns the app ID (in the Android multi-user sense) for the current
+ * UNIX UID.
+ */
+static uid_t get_app_id(uid_t uid) {
+    return uid % AID_USER;
+}
+
+/**
+ * Returns the user ID (in the Android multi-user sense) for the current
+ * UNIX UID.
+ */
+static uid_t get_user_id(uid_t uid) {
+    return uid / AID_USER;
+}
+
+static int audit_callback(void *data, security_class_t /* cls */, char *buf, size_t len)
+{
+    struct audit_data *ad = reinterpret_cast<struct audit_data *>(data);
+    if (!ad) {
+        ALOGE("No keystore audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
+    return 0;
+}
+
+static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
+    if (!ks_is_selinux_enabled) {
+        return true;
+    }
+
+    audit_data ad;
+    char *sctx = NULL;
+    const char *selinux_class = "keystore_key";
+    const char *str_perm = get_perm_label(perm);
+
+    if (!str_perm) {
+        return false;
+    }
+
+    if (getpidcon(spid, &sctx) != 0) {
+        ALOGE("SELinux: Failed to get source pid context.\n");
+        return false;
+    }
+
+    ad.pid = spid;
+    ad.uid = uid;
+
+    bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
+            reinterpret_cast<void *>(&ad)) == 0;
+    freecon(sctx);
+    return allowed;
+}
+
+static bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
+    // All system users are equivalent for multi-user support.
+    if (get_app_id(uid) == AID_SYSTEM) {
+        uid = AID_SYSTEM;
+    }
+
+    for (size_t i = 0; i < sizeof(user_perms)/sizeof(user_perms[0]); i++) {
+        struct user_perm user = user_perms[i];
+        if (user.uid == uid) {
+            return (user.perms & perm) &&
+                keystore_selinux_check_access(uid, perm, spid);
+        }
+    }
+
+    return (DEFAULT_PERMS & perm) &&
+        keystore_selinux_check_access(uid, perm, spid);
+}
+
+/**
+ * Returns the UID that the callingUid should act as. This is here for
+ * legacy support of the WiFi and VPN systems and should be removed
+ * when WiFi can operate in its own namespace.
+ */
+static uid_t get_keystore_euid(uid_t uid) {
+    for (size_t i = 0; i < sizeof(user_euids)/sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.uid == uid) {
+            return user.euid;
+        }
+    }
+
+    return uid;
+}
+
+/**
+ * Returns true if the callingUid is allowed to interact in the targetUid's
+ * namespace.
+ */
+static bool is_granted_to(uid_t callingUid, uid_t targetUid) {
+    if (callingUid == targetUid) {
+        return true;
+    }
+    for (size_t i = 0; i < sizeof(user_euids)/sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.euid == callingUid && user.uid == targetUid) {
+            return true;
+        }
+    }
+
+    return false;
 }
 
 /* Here is the encoding of keys. This is necessary in order to allow arbitrary
@@ -116,198 +489,6 @@
     return length;
 }
 
-android::String8 KeyStore::getKeyName(const android::String8& keyName) {
-    char encoded[encode_key_length(keyName) + 1];  // add 1 for null char
-    encode_key(encoded, keyName);
-    return android::String8(encoded);
-}
-
-android::String8 KeyStore::getKeyNameForUid(const android::String8& keyName, uid_t uid) {
-    char encoded[encode_key_length(keyName) + 1];  // add 1 for null char
-    encode_key(encoded, keyName);
-    return android::String8::format("%u_%s", uid, encoded);
-}
-
-android::String8 KeyStore::getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid) {
-    char encoded[encode_key_length(keyName) + 1];  // add 1 for null char
-    encode_key(encoded, keyName);
-    return android::String8::format("%s/%u_%s", getUserStateByUid(uid)->getUserDirName(), uid,
-                                    encoded);
-}
-
-void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
-    android::String8 prefix("");
-    android::Vector<android::String16> aliases;
-    UserState* userState = getUserState(userId);
-    if (list(prefix, &aliases, userId) != ::NO_ERROR) {
-        return;
-    }
-    for (uint32_t i = 0; i < aliases.size(); i++) {
-        android::String8 filename(aliases[i]);
-        filename = android::String8::format("%s/%s", userState->getUserDirName(),
-                                            getKeyName(filename).string());
-        bool shouldDelete = true;
-        if (keepUnenryptedEntries) {
-            Blob blob;
-            ResponseCode rc = get(filename, &blob, ::TYPE_ANY, userId);
-
-            /* get can fail if the blob is encrypted and the state is
-             * not unlocked, only skip deleting blobs that were loaded and
-             * who are not encrypted. If there are blobs we fail to read for
-             * other reasons err on the safe side and delete them since we
-             * can't tell if they're encrypted.
-             */
-            shouldDelete = !(rc == ::NO_ERROR && !blob.isEncrypted());
-        }
-        if (shouldDelete) {
-            del(filename, ::TYPE_ANY, userId);
-        }
-    }
-    if (!userState->deleteMasterKey()) {
-        ALOGE("Failed to delete user %d's master key", userId);
-    }
-    if (!keepUnenryptedEntries) {
-        if (!userState->reset()) {
-            ALOGE("Failed to remove user %d's directory", userId);
-        }
-    }
-}
-
-bool KeyStore::isEmpty(uid_t userId) const {
-    const UserState* userState = getUserState(userId);
-    if (userState == NULL) {
-        return true;
-    }
-
-    DIR* dir = opendir(userState->getUserDirName());
-    if (!dir) {
-        return true;
-    }
-
-    bool result = true;
-    struct dirent* file;
-    while ((file = readdir(dir)) != NULL) {
-        // We only care about files.
-        if (file->d_type != DT_REG) {
-            continue;
-        }
-
-        // Skip anything that starts with a "."
-        if (file->d_name[0] == '.') {
-            continue;
-        }
-
-        result = false;
-        break;
-    }
-    closedir(dir);
-    return result;
-}
-
-void KeyStore::lock(uid_t userId) {
-    UserState* userState = getUserState(userId);
-    userState->zeroizeMasterKeysInMemory();
-    userState->setState(STATE_LOCKED);
-}
-
-ResponseCode KeyStore::get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
-    UserState* userState = getUserState(userId);
-    ResponseCode rc =
-        keyBlob->readBlob(filename, userState->getDecryptionKey(), userState->getState());
-    if (rc != NO_ERROR) {
-        return rc;
-    }
-
-    const uint8_t version = keyBlob->getVersion();
-    if (version < CURRENT_BLOB_VERSION) {
-        /* If we upgrade the key, we need to write it to disk again. Then
-         * it must be read it again since the blob is encrypted each time
-         * it's written.
-         */
-        if (upgradeBlob(filename, keyBlob, version, type, userId)) {
-            if ((rc = this->put(filename, keyBlob, userId)) != NO_ERROR ||
-                (rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
-                                        userState->getState())) != NO_ERROR) {
-                return rc;
-            }
-        }
-    }
-
-    /*
-     * This will upgrade software-backed keys to hardware-backed keys when
-     * the HAL for the device supports the newer key types.
-     */
-    if (rc == NO_ERROR && type == TYPE_KEY_PAIR &&
-        mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2 &&
-        keyBlob->isFallback()) {
-        ResponseCode imported =
-            importKey(keyBlob->getValue(), keyBlob->getLength(), filename, userId,
-                      keyBlob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
-
-        // The HAL allowed the import, reget the key to have the "fresh"
-        // version.
-        if (imported == NO_ERROR) {
-            rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
-        }
-    }
-
-    // Keymaster 0.3 keys are valid keymaster 1.0 keys, so silently upgrade.
-    if (keyBlob->getType() == TYPE_KEY_PAIR) {
-        keyBlob->setType(TYPE_KEYMASTER_10);
-        rc = this->put(filename, keyBlob, userId);
-    }
-
-    if (type != TYPE_ANY && keyBlob->getType() != type) {
-        ALOGW("key found but type doesn't match: %d vs %d", keyBlob->getType(), type);
-        return KEY_NOT_FOUND;
-    }
-
-    return rc;
-}
-
-ResponseCode KeyStore::put(const char* filename, Blob* keyBlob, uid_t userId) {
-    UserState* userState = getUserState(userId);
-    return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState(),
-                              mEntropy);
-}
-
-ResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t userId) {
-    Blob keyBlob;
-    ResponseCode rc = get(filename, &keyBlob, type, userId);
-    if (rc == ::VALUE_CORRUPTED) {
-        // The file is corrupt, the best we can do is rm it.
-        return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
-    }
-    if (rc != ::NO_ERROR) {
-        return rc;
-    }
-
-    if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
-        // A device doesn't have to implement delete_key.
-        if (mDevice->delete_key != NULL && !keyBlob.isFallback()) {
-            keymaster_key_blob_t blob = {keyBlob.getValue(),
-                                         static_cast<size_t>(keyBlob.getLength())};
-            if (mDevice->delete_key(mDevice, &blob)) {
-                rc = ::SYSTEM_ERROR;
-            }
-        }
-    }
-    if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
-        keymaster1_device_t* dev = getDeviceForBlob(keyBlob);
-        if (dev->delete_key) {
-            keymaster_key_blob_t blob;
-            blob.key_material = keyBlob.getValue();
-            blob.key_material_size = keyBlob.getLength();
-            dev->delete_key(dev, &blob);
-        }
-    }
-    if (rc != ::NO_ERROR) {
-        return rc;
-    }
-
-    return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
-}
-
 /*
  * Converts from the "escaped" format on disk to actual name.
  * This will be smaller than the input string.
@@ -345,371 +526,899 @@
     *out = '\0';
 }
 
-ResponseCode KeyStore::list(const android::String8& prefix,
-                            android::Vector<android::String16>* matches, uid_t userId) {
-
-    UserState* userState = getUserState(userId);
-    size_t n = prefix.length();
-
-    DIR* dir = opendir(userState->getUserDirName());
-    if (!dir) {
-        ALOGW("can't open directory for user: %s", strerror(errno));
-        return ::SYSTEM_ERROR;
+static size_t readFully(int fd, uint8_t* data, size_t size) {
+    size_t remaining = size;
+    while (remaining > 0) {
+        ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, remaining));
+        if (n <= 0) {
+            return size - remaining;
+        }
+        data += n;
+        remaining -= n;
     }
-
-    struct dirent* file;
-    while ((file = readdir(dir)) != NULL) {
-        // We only care about files.
-        if (file->d_type != DT_REG) {
-            continue;
-        }
-
-        // Skip anything that starts with a "."
-        if (file->d_name[0] == '.') {
-            continue;
-        }
-
-        if (!strncmp(prefix.string(), file->d_name, n)) {
-            const char* p = &file->d_name[n];
-            size_t plen = strlen(p);
-
-            size_t extra = decode_key_length(p, plen);
-            char* match = (char*)malloc(extra + 1);
-            if (match != NULL) {
-                decode_key(match, p, plen);
-                matches->push(android::String16(match, extra));
-                free(match);
-            } else {
-                ALOGW("could not allocate match of size %zd", extra);
-            }
-        }
-    }
-    closedir(dir);
-    return ::NO_ERROR;
+    return size;
 }
 
-void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
-    const grant_t* existing = getGrant(filename, granteeUid);
-    if (existing == NULL) {
-        grant_t* grant = new grant_t;
-        grant->uid = granteeUid;
-        grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
-        mGrants.add(grant);
+static size_t writeFully(int fd, uint8_t* data, size_t size) {
+    size_t remaining = size;
+    while (remaining > 0) {
+        ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, remaining));
+        if (n < 0) {
+            ALOGW("write failed: %s", strerror(errno));
+            return size - remaining;
+        }
+        data += n;
+        remaining -= n;
     }
+    return size;
 }
 
-bool KeyStore::removeGrant(const char* filename, uid_t granteeUid) {
-    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
-        grant_t* grant = *it;
-        if (grant->uid == granteeUid &&
-            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
-            mGrants.erase(it);
+class Entropy {
+public:
+    Entropy() : mRandom(-1) {}
+    ~Entropy() {
+        if (mRandom >= 0) {
+            close(mRandom);
+        }
+    }
+
+    bool open() {
+        const char* randomDevice = "/dev/urandom";
+        mRandom = TEMP_FAILURE_RETRY(::open(randomDevice, O_RDONLY));
+        if (mRandom < 0) {
+            ALOGE("open: %s: %s", randomDevice, strerror(errno));
+            return false;
+        }
+        return true;
+    }
+
+    bool generate_random_data(uint8_t* data, size_t size) const {
+        return (readFully(mRandom, data, size) == size);
+    }
+
+private:
+    int mRandom;
+};
+
+/* Here is the file format. There are two parts in blob.value, the secret and
+ * the description. The secret is stored in ciphertext, and its original size
+ * can be found in blob.length. The description is stored after the secret in
+ * plaintext, and its size is specified in blob.info. The total size of the two
+ * parts must be no more than VALUE_SIZE bytes. The first field is the version,
+ * the second is the blob's type, and the third byte is flags. Fields other
+ * than blob.info, blob.length, and blob.value are modified by encryptBlob()
+ * and decryptBlob(). Thus they should not be accessed from outside. */
+
+/* ** Note to future implementors of encryption: **
+ * Currently this is the construction:
+ *   metadata || Enc(MD5(data) || data)
+ *
+ * This should be the construction used for encrypting if re-implementing:
+ *
+ *   Derive independent keys for encryption and MAC:
+ *     Kenc = AES_encrypt(masterKey, "Encrypt")
+ *     Kmac = AES_encrypt(masterKey, "MAC")
+ *
+ *   Store this:
+ *     metadata || AES_CTR_encrypt(Kenc, rand_IV, data) ||
+ *             HMAC(Kmac, metadata || Enc(data))
+ */
+struct __attribute__((packed)) blob {
+    uint8_t version;
+    uint8_t type;
+    uint8_t flags;
+    uint8_t info;
+    uint8_t vector[AES_BLOCK_SIZE];
+    uint8_t encrypted[0]; // Marks offset to encrypted data.
+    uint8_t digest[MD5_DIGEST_LENGTH];
+    uint8_t digested[0]; // Marks offset to digested data.
+    int32_t length; // in network byte order when encrypted
+    uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+};
+
+typedef enum {
+    TYPE_ANY = 0, // meta type that matches anything
+    TYPE_GENERIC = 1,
+    TYPE_MASTER_KEY = 2,
+    TYPE_KEY_PAIR = 3,
+    TYPE_KEYMASTER_10 = 4,
+} BlobType;
+
+static const uint8_t CURRENT_BLOB_VERSION = 2;
+
+class Blob {
+public:
+    Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
+            BlobType type) {
+        memset(&mBlob, 0, sizeof(mBlob));
+        if (valueLength > VALUE_SIZE) {
+            valueLength = VALUE_SIZE;
+            ALOGW("Provided blob length too large");
+        }
+        if (infoLength + valueLength > VALUE_SIZE) {
+            infoLength = VALUE_SIZE - valueLength;
+            ALOGW("Provided info length too large");
+        }
+        mBlob.length = valueLength;
+        memcpy(mBlob.value, value, valueLength);
+
+        mBlob.info = infoLength;
+        memcpy(mBlob.value + valueLength, info, infoLength);
+
+        mBlob.version = CURRENT_BLOB_VERSION;
+        mBlob.type = uint8_t(type);
+
+        if (type == TYPE_MASTER_KEY) {
+            mBlob.flags = KEYSTORE_FLAG_ENCRYPTED;
+        } else {
+            mBlob.flags = KEYSTORE_FLAG_NONE;
+        }
+    }
+
+    Blob(blob b) {
+        mBlob = b;
+    }
+
+    Blob() {
+        memset(&mBlob, 0, sizeof(mBlob));
+    }
+
+    const uint8_t* getValue() const {
+        return mBlob.value;
+    }
+
+    int32_t getLength() const {
+        return mBlob.length;
+    }
+
+    const uint8_t* getInfo() const {
+        return mBlob.value + mBlob.length;
+    }
+
+    uint8_t getInfoLength() const {
+        return mBlob.info;
+    }
+
+    uint8_t getVersion() const {
+        return mBlob.version;
+    }
+
+    bool isEncrypted() const {
+        if (mBlob.version < 2) {
             return true;
         }
-    }
-    return false;
-}
 
-ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* filename,
-                                 uid_t userId, int32_t flags) {
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
-    if (!pkcs8.get()) {
-        return ::SYSTEM_ERROR;
-    }
-    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
-    if (!pkey.get()) {
-        return ::SYSTEM_ERROR;
-    }
-    int type = EVP_PKEY_type(pkey->type);
-    android::KeymasterArguments params;
-    add_legacy_key_authorizations(type, &params.params);
-    switch (type) {
-    case EVP_PKEY_RSA:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
-        break;
-    case EVP_PKEY_EC:
-        params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
-        break;
-    default:
-        ALOGW("Unsupported key type %d", type);
-        return ::SYSTEM_ERROR;
+        return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
     }
 
-    std::vector<keymaster_key_param_t> opParams(params.params);
-    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
-    keymaster_blob_t input = {key, keyLen};
-    keymaster_key_blob_t blob = {nullptr, 0};
-    bool isFallback = false;
-    keymaster_error_t error = mDevice->import_key(mDevice, &inParams, KM_KEY_FORMAT_PKCS8, &input,
-                                                  &blob, NULL /* characteristics */);
-    if (error != KM_ERROR_OK) {
-        ALOGE("Keymaster error %d importing key pair, falling back", error);
+    void setEncrypted(bool encrypted) {
+        if (encrypted) {
+            mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
+        } else {
+            mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
+        }
+    }
 
-        /*
-         * There should be no way to get here.  Fallback shouldn't ever really happen
-         * because the main device may be many (SW, KM0/SW hybrid, KM1/SW hybrid), but it must
-         * provide full support of the API.  In any case, we'll do the fallback just for
-         * consistency... and I suppose to cover for broken HW implementations.
-         */
-        error = mFallbackDevice->import_key(mFallbackDevice, &inParams, KM_KEY_FORMAT_PKCS8, &input,
-                                            &blob, NULL /* characteristics */);
-        isFallback = true;
+    bool isFallback() const {
+        return mBlob.flags & KEYSTORE_FLAG_FALLBACK;
+    }
 
-        if (error) {
-            ALOGE("Keymaster error while importing key pair with fallback: %d", error);
+    void setFallback(bool fallback) {
+        if (fallback) {
+            mBlob.flags |= KEYSTORE_FLAG_FALLBACK;
+        } else {
+            mBlob.flags &= ~KEYSTORE_FLAG_FALLBACK;
+        }
+    }
+
+    void setVersion(uint8_t version) {
+        mBlob.version = version;
+    }
+
+    BlobType getType() const {
+        return BlobType(mBlob.type);
+    }
+
+    void setType(BlobType type) {
+        mBlob.type = uint8_t(type);
+    }
+
+    ResponseCode writeBlob(const char* filename, AES_KEY *aes_key, State state, Entropy* entropy) {
+        ALOGV("writing blob %s", filename);
+        if (isEncrypted()) {
+            if (state != STATE_NO_ERROR) {
+                ALOGD("couldn't insert encrypted blob while not unlocked");
+                return LOCKED;
+            }
+
+            if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
+                ALOGW("Could not read random data for: %s", filename);
+                return SYSTEM_ERROR;
+            }
+        }
+
+        // data includes the value and the value's length
+        size_t dataLength = mBlob.length + sizeof(mBlob.length);
+        // pad data to the AES_BLOCK_SIZE
+        size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1)
+                                 / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
+        // encrypted data includes the digest value
+        size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
+        // move info after space for padding
+        memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
+        // zero padding area
+        memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);
+
+        mBlob.length = htonl(mBlob.length);
+
+        if (isEncrypted()) {
+            MD5(mBlob.digested, digestedLength, mBlob.digest);
+
+            uint8_t vector[AES_BLOCK_SIZE];
+            memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
+            AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength,
+                            aes_key, vector, AES_ENCRYPT);
+        }
+
+        size_t headerLength = (mBlob.encrypted - (uint8_t*) &mBlob);
+        size_t fileLength = encryptedLength + headerLength + mBlob.info;
+
+        const char* tmpFileName = ".tmp";
+        int out = TEMP_FAILURE_RETRY(open(tmpFileName,
+                O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+        if (out < 0) {
+            ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
             return SYSTEM_ERROR;
         }
+        size_t writtenBytes = writeFully(out, (uint8_t*) &mBlob, fileLength);
+        if (close(out) != 0) {
+            return SYSTEM_ERROR;
+        }
+        if (writtenBytes != fileLength) {
+            ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
+            unlink(tmpFileName);
+            return SYSTEM_ERROR;
+        }
+        if (rename(tmpFileName, filename) == -1) {
+            ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
+            return SYSTEM_ERROR;
+        }
+        return NO_ERROR;
     }
 
-    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
-    free(const_cast<uint8_t*>(blob.key_material));
+    ResponseCode readBlob(const char* filename, AES_KEY *aes_key, State state) {
+        ALOGV("reading blob %s", filename);
+        int in = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
+        if (in < 0) {
+            return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+        }
+        // fileLength may be less than sizeof(mBlob) since the in
+        // memory version has extra padding to tolerate rounding up to
+        // the AES_BLOCK_SIZE
+        size_t fileLength = readFully(in, (uint8_t*) &mBlob, sizeof(mBlob));
+        if (close(in) != 0) {
+            return SYSTEM_ERROR;
+        }
 
-    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-    keyBlob.setFallback(isFallback);
+        if (fileLength == 0) {
+            return VALUE_CORRUPTED;
+        }
 
-    return put(filename, &keyBlob, userId);
-}
+        if (isEncrypted() && (state != STATE_NO_ERROR)) {
+            return LOCKED;
+        }
 
-bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
-    if (mDevice == NULL) {
-        ALOGW("can't get keymaster device");
-        return false;
+        size_t headerLength = (mBlob.encrypted - (uint8_t*) &mBlob);
+        if (fileLength < headerLength) {
+            return VALUE_CORRUPTED;
+        }
+
+        ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
+        if (encryptedLength < 0) {
+            return VALUE_CORRUPTED;
+        }
+
+        ssize_t digestedLength;
+        if (isEncrypted()) {
+            if (encryptedLength % AES_BLOCK_SIZE != 0) {
+                return VALUE_CORRUPTED;
+            }
+
+            AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key,
+                            mBlob.vector, AES_DECRYPT);
+            digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
+            uint8_t computedDigest[MD5_DIGEST_LENGTH];
+            MD5(mBlob.digested, digestedLength, computedDigest);
+            if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
+                return VALUE_CORRUPTED;
+            }
+        } else {
+            digestedLength = encryptedLength;
+        }
+
+        ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
+        mBlob.length = ntohl(mBlob.length);
+        if (mBlob.length < 0 || mBlob.length > maxValueLength) {
+            return VALUE_CORRUPTED;
+        }
+        if (mBlob.info != 0) {
+            // move info from after padding to after data
+            memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
+        }
+        return ::NO_ERROR;
     }
 
-    if (sRSAKeyType == keyType) {
-        return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0;
-    } else {
-        return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0 &&
-               (mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2);
-    }
-}
+private:
+    struct blob mBlob;
+};
 
-ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
-                                     const uid_t uid, const BlobType type) {
-    android::String8 filepath8(getKeyNameForUidWithDir(keyName, uid));
-    uid_t userId = get_user_id(uid);
-
-    ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
-    if (responseCode == NO_ERROR) {
-        return responseCode;
+class UserState {
+public:
+    UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
+        asprintf(&mUserDir, "user_%u", mUserId);
+        asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
     }
 
-    // If this is one of the legacy UID->UID mappings, use it.
-    uid_t euid = get_keystore_euid(uid);
-    if (euid != uid) {
-        filepath8 = getKeyNameForUidWithDir(keyName, euid);
-        responseCode = get(filepath8.string(), keyBlob, type, userId);
-        if (responseCode == NO_ERROR) {
-            return responseCode;
+    ~UserState() {
+        free(mUserDir);
+        free(mMasterKeyFile);
+    }
+
+    bool initialize() {
+        if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
+            ALOGE("Could not create directory '%s'", mUserDir);
+            return false;
+        }
+
+        if (access(mMasterKeyFile, R_OK) == 0) {
+            setState(STATE_LOCKED);
+        } else {
+            setState(STATE_UNINITIALIZED);
+        }
+
+        return true;
+    }
+
+    uid_t getUserId() const {
+        return mUserId;
+    }
+
+    const char* getUserDirName() const {
+        return mUserDir;
+    }
+
+    const char* getMasterKeyFileName() const {
+        return mMasterKeyFile;
+    }
+
+    void setState(State state) {
+        mState = state;
+        if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
+            mRetry = MAX_RETRY;
         }
     }
 
-    // They might be using a granted key.
-    android::String8 filename8 = getKeyName(keyName);
-    char* end;
-    strtoul(filename8.string(), &end, 10);
-    if (end[0] != '_' || end[1] == 0) {
-        return KEY_NOT_FOUND;
-    }
-    filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
-                                         filename8.string());
-    if (!hasGrant(filepath8.string(), uid)) {
-        return responseCode;
+    State getState() const {
+        return mState;
     }
 
-    // It is a granted key. Try to load it.
-    return get(filepath8.string(), keyBlob, type, userId);
-}
+    int8_t getRetry() const {
+        return mRetry;
+    }
 
-UserState* KeyStore::getUserState(uid_t userId) {
-    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
-         it++) {
-        UserState* state = *it;
-        if (state->getUserId() == userId) {
-            return state;
+    void zeroizeMasterKeysInMemory() {
+        memset(mMasterKey, 0, sizeof(mMasterKey));
+        memset(mSalt, 0, sizeof(mSalt));
+        memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
+        memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
+    }
+
+    bool deleteMasterKey() {
+        setState(STATE_UNINITIALIZED);
+        zeroizeMasterKeysInMemory();
+        return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
+    }
+
+    ResponseCode initialize(const android::String8& pw, Entropy* entropy) {
+        if (!generateMasterKey(entropy)) {
+            return SYSTEM_ERROR;
         }
+        ResponseCode response = writeMasterKey(pw, entropy);
+        if (response != NO_ERROR) {
+            return response;
+        }
+        setupMasterKeys();
+        return ::NO_ERROR;
     }
 
-    UserState* userState = new UserState(userId);
-    if (!userState->initialize()) {
-        /* There's not much we can do if initialization fails. Trying to
-         * unlock the keystore for that user will fail as well, so any
-         * subsequent request for this user will just return SYSTEM_ERROR.
+    ResponseCode copyMasterKey(UserState* src) {
+        if (mState != STATE_UNINITIALIZED) {
+            return ::SYSTEM_ERROR;
+        }
+        if (src->getState() != STATE_NO_ERROR) {
+            return ::SYSTEM_ERROR;
+        }
+        memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
+        setupMasterKeys();
+        return copyMasterKeyFile(src);
+    }
+
+    ResponseCode copyMasterKeyFile(UserState* src) {
+        /* Copy the master key file to the new user.
+         * Unfortunately we don't have the src user's password so we cannot
+         * generate a new file with a new salt.
          */
-        ALOGE("User initialization failed for %u; subsuquent operations will fail", userId);
+        int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
+        if (in < 0) {
+            return ::SYSTEM_ERROR;
+        }
+        blob rawBlob;
+        size_t length = readFully(in, (uint8_t*) &rawBlob, sizeof(rawBlob));
+        if (close(in) != 0) {
+            return ::SYSTEM_ERROR;
+        }
+        int out = TEMP_FAILURE_RETRY(open(mMasterKeyFile,
+                O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+        if (out < 0) {
+            return ::SYSTEM_ERROR;
+        }
+        size_t outLength = writeFully(out, (uint8_t*) &rawBlob, length);
+        if (close(out) != 0) {
+            return ::SYSTEM_ERROR;
+        }
+        if (outLength != length) {
+            ALOGW("blob not fully written %zu != %zu", outLength, length);
+            unlink(mMasterKeyFile);
+            return ::SYSTEM_ERROR;
+        }
+
+        return ::NO_ERROR;
     }
-    mMasterKeys.add(userState);
-    return userState;
-}
 
-UserState* KeyStore::getUserStateByUid(uid_t uid) {
-    uid_t userId = get_user_id(uid);
-    return getUserState(userId);
-}
+    ResponseCode writeMasterKey(const android::String8& pw, Entropy* entropy) {
+        uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
+        generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
+        AES_KEY passwordAesKey;
+        AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
+        Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
+        return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
+    }
 
-const UserState* KeyStore::getUserState(uid_t userId) const {
-    for (android::Vector<UserState*>::const_iterator it(mMasterKeys.begin());
-         it != mMasterKeys.end(); it++) {
-        UserState* state = *it;
-        if (state->getUserId() == userId) {
-            return state;
+    ResponseCode readMasterKey(const android::String8& pw, Entropy* entropy) {
+        int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
+        if (in < 0) {
+            return SYSTEM_ERROR;
+        }
+
+        // we read the raw blob to just to get the salt to generate
+        // the AES key, then we create the Blob to use with decryptBlob
+        blob rawBlob;
+        size_t length = readFully(in, (uint8_t*) &rawBlob, sizeof(rawBlob));
+        if (close(in) != 0) {
+            return SYSTEM_ERROR;
+        }
+        // find salt at EOF if present, otherwise we have an old file
+        uint8_t* salt;
+        if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
+            salt = (uint8_t*) &rawBlob + length - SALT_SIZE;
+        } else {
+            salt = NULL;
+        }
+        uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
+        generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
+        AES_KEY passwordAesKey;
+        AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
+        Blob masterKeyBlob(rawBlob);
+        ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey,
+                STATE_NO_ERROR);
+        if (response == SYSTEM_ERROR) {
+            return response;
+        }
+        if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
+            // if salt was missing, generate one and write a new master key file with the salt.
+            if (salt == NULL) {
+                if (!generateSalt(entropy)) {
+                    return SYSTEM_ERROR;
+                }
+                response = writeMasterKey(pw, entropy);
+            }
+            if (response == NO_ERROR) {
+                memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
+                setupMasterKeys();
+            }
+            return response;
+        }
+        if (mRetry <= 0) {
+            reset();
+            return UNINITIALIZED;
+        }
+        --mRetry;
+        switch (mRetry) {
+            case 0: return WRONG_PASSWORD_0;
+            case 1: return WRONG_PASSWORD_1;
+            case 2: return WRONG_PASSWORD_2;
+            case 3: return WRONG_PASSWORD_3;
+            default: return WRONG_PASSWORD_3;
         }
     }
 
-    return NULL;
-}
-
-const UserState* KeyStore::getUserStateByUid(uid_t uid) const {
-    uid_t userId = get_user_id(uid);
-    return getUserState(userId);
-}
-
-const grant_t* KeyStore::getGrant(const char* filename, uid_t uid) const {
-    for (android::Vector<grant_t*>::const_iterator it(mGrants.begin()); it != mGrants.end(); it++) {
-        grant_t* grant = *it;
-        if (grant->uid == uid &&
-            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
-            return grant;
-        }
-    }
-    return NULL;
-}
-
-bool KeyStore::upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
-                           const BlobType type, uid_t uid) {
-    bool updated = false;
-    uint8_t version = oldVersion;
-
-    /* From V0 -> V1: All old types were unknown */
-    if (version == 0) {
-        ALOGV("upgrading to version 1 and setting type %d", type);
-
-        blob->setType(type);
-        if (type == TYPE_KEY_PAIR) {
-            importBlobAsKey(blob, filename, uid);
-        }
-        version = 1;
-        updated = true;
+    AES_KEY* getEncryptionKey() {
+        return &mMasterKeyEncryption;
     }
 
-    /* From V1 -> V2: All old keys were encrypted */
-    if (version == 1) {
-        ALOGV("upgrading to version 2");
+    AES_KEY* getDecryptionKey() {
+        return &mMasterKeyDecryption;
+    }
 
-        blob->setEncrypted(true);
-        version = 2;
-        updated = true;
+    bool reset() {
+        DIR* dir = opendir(getUserDirName());
+        if (!dir) {
+            // If the directory doesn't exist then nothing to do.
+            if (errno == ENOENT) {
+                return true;
+            }
+            ALOGW("couldn't open user directory: %s", strerror(errno));
+            return false;
+        }
+
+        struct dirent* file;
+        while ((file = readdir(dir)) != NULL) {
+            // skip . and ..
+            if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
+                continue;
+            }
+
+            unlinkat(dirfd(dir), file->d_name, 0);
+        }
+        closedir(dir);
+        return true;
+    }
+
+private:
+    static const int MASTER_KEY_SIZE_BYTES = 16;
+    static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
+
+    static const int MAX_RETRY = 4;
+    static const size_t SALT_SIZE = 16;
+
+    void generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+            uint8_t* salt) {
+        size_t saltSize;
+        if (salt != NULL) {
+            saltSize = SALT_SIZE;
+        } else {
+            // pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
+            salt = (uint8_t*) "keystore";
+            // sizeof = 9, not strlen = 8
+            saltSize = sizeof("keystore");
+        }
+
+        PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt,
+                saltSize, 8192, keySize, key);
+    }
+
+    bool generateSalt(Entropy* entropy) {
+        return entropy->generate_random_data(mSalt, sizeof(mSalt));
+    }
+
+    bool generateMasterKey(Entropy* entropy) {
+        if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
+            return false;
+        }
+        if (!generateSalt(entropy)) {
+            return false;
+        }
+        return true;
+    }
+
+    void setupMasterKeys() {
+        AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
+        AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
+        setState(STATE_NO_ERROR);
+    }
+
+    uid_t mUserId;
+
+    char* mUserDir;
+    char* mMasterKeyFile;
+
+    State mState;
+    int8_t mRetry;
+
+    uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
+    uint8_t mSalt[SALT_SIZE];
+
+    AES_KEY mMasterKeyEncryption;
+    AES_KEY mMasterKeyDecryption;
+};
+
+typedef struct {
+    uint32_t uid;
+    const uint8_t* filename;
+} grant_t;
+
+class KeyStore {
+public:
+    KeyStore(Entropy* entropy, keymaster1_device_t* device, keymaster1_device_t* fallback)
+        : mEntropy(entropy)
+        , mDevice(device)
+        , mFallbackDevice(fallback)
+    {
+        memset(&mMetaData, '\0', sizeof(mMetaData));
+    }
+
+    ~KeyStore() {
+        for (android::Vector<grant_t*>::iterator it(mGrants.begin());
+                it != mGrants.end(); it++) {
+            delete *it;
+        }
+        mGrants.clear();
+
+        for (android::Vector<UserState*>::iterator it(mMasterKeys.begin());
+                it != mMasterKeys.end(); it++) {
+            delete *it;
+        }
+        mMasterKeys.clear();
+    }
+
+    /**
+     * Depending on the hardware keymaster version is this may return a
+     * keymaster0_device_t* cast to a keymaster1_device_t*. All methods from
+     * keymaster0 are safe to call, calls to keymaster1_device_t methods should
+     * be guarded by a check on the device's version.
+     */
+    keymaster1_device_t *getDevice() const {
+        return mDevice;
+    }
+
+    keymaster1_device_t *getFallbackDevice() const {
+        return mFallbackDevice;
+    }
+
+    keymaster1_device_t *getDeviceForBlob(const Blob& blob) const {
+        return blob.isFallback() ? mFallbackDevice: mDevice;
+    }
+
+    ResponseCode initialize() {
+        readMetaData();
+        if (upgradeKeystore()) {
+            writeMetaData();
+        }
+
+        return ::NO_ERROR;
+    }
+
+    State getState(uid_t userId) {
+        return getUserState(userId)->getState();
+    }
+
+    ResponseCode initializeUser(const android::String8& pw, uid_t userId) {
+        UserState* userState = getUserState(userId);
+        return userState->initialize(pw, mEntropy);
+    }
+
+    ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser) {
+        UserState *userState = getUserState(dstUser);
+        UserState *initState = getUserState(srcUser);
+        return userState->copyMasterKey(initState);
+    }
+
+    ResponseCode writeMasterKey(const android::String8& pw, uid_t userId) {
+        UserState* userState = getUserState(userId);
+        return userState->writeMasterKey(pw, mEntropy);
+    }
+
+    ResponseCode readMasterKey(const android::String8& pw, uid_t userId) {
+        UserState* userState = getUserState(userId);
+        return userState->readMasterKey(pw, mEntropy);
+    }
+
+    android::String8 getKeyName(const android::String8& keyName) {
+        char encoded[encode_key_length(keyName) + 1];	// add 1 for null char
+        encode_key(encoded, keyName);
+        return android::String8(encoded);
+    }
+
+    android::String8 getKeyNameForUid(const android::String8& keyName, uid_t uid) {
+        char encoded[encode_key_length(keyName) + 1];	// add 1 for null char
+        encode_key(encoded, keyName);
+        return android::String8::format("%u_%s", uid, encoded);
+    }
+
+    android::String8 getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid) {
+        char encoded[encode_key_length(keyName) + 1];	// add 1 for null char
+        encode_key(encoded, keyName);
+        return android::String8::format("%s/%u_%s", getUserStateByUid(uid)->getUserDirName(), uid,
+                encoded);
     }
 
     /*
-     * If we've updated, set the key blob to the right version
-     * and write it.
+     * Delete entries owned by userId. If keepUnencryptedEntries is true
+     * then only encrypted entries will be removed, otherwise all entries will
+     * be removed.
      */
-    if (updated) {
-        ALOGV("updated and writing file %s", filename);
-        blob->setVersion(version);
+    void resetUser(uid_t userId, bool keepUnenryptedEntries) {
+        android::String8 prefix("");
+        android::Vector<android::String16> aliases;
+        UserState* userState = getUserState(userId);
+        if (list(prefix, &aliases, userId) != ::NO_ERROR) {
+            return;
+        }
+        for (uint32_t i = 0; i < aliases.size(); i++) {
+            android::String8 filename(aliases[i]);
+            filename = android::String8::format("%s/%s", userState->getUserDirName(),
+                                                getKeyName(filename).string());
+            bool shouldDelete = true;
+            if (keepUnenryptedEntries) {
+                Blob blob;
+                ResponseCode rc = get(filename, &blob, ::TYPE_ANY, userId);
+
+                /* get can fail if the blob is encrypted and the state is
+                 * not unlocked, only skip deleting blobs that were loaded and
+                 * who are not encrypted. If there are blobs we fail to read for
+                 * other reasons err on the safe side and delete them since we
+                 * can't tell if they're encrypted.
+                 */
+                shouldDelete = !(rc == ::NO_ERROR && !blob.isEncrypted());
+            }
+            if (shouldDelete) {
+                del(filename, ::TYPE_ANY, userId);
+            }
+        }
+        if (!userState->deleteMasterKey()) {
+            ALOGE("Failed to delete user %d's master key", userId);
+        }
+        if (!keepUnenryptedEntries) {
+            if(!userState->reset()) {
+                ALOGE("Failed to remove user %d's directory", userId);
+            }
+        }
     }
 
-    return updated;
-}
+    bool isEmpty(uid_t userId) const {
+        const UserState* userState = getUserState(userId);
+        if (userState == NULL) {
+            return true;
+        }
 
-struct BIO_Delete {
-    void operator()(BIO* p) const { BIO_free(p); }
-};
-typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
+        DIR* dir = opendir(userState->getUserDirName());
+        if (!dir) {
+            return true;
+        }
 
-ResponseCode KeyStore::importBlobAsKey(Blob* blob, const char* filename, uid_t uid) {
-    // We won't even write to the blob directly with this BIO, so const_cast is okay.
-    Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
-    if (b.get() == NULL) {
-        ALOGE("Problem instantiating BIO");
-        return SYSTEM_ERROR;
+        bool result = true;
+        struct dirent* file;
+        while ((file = readdir(dir)) != NULL) {
+            // We only care about files.
+            if (file->d_type != DT_REG) {
+                continue;
+            }
+
+            // Skip anything that starts with a "."
+            if (file->d_name[0] == '.') {
+                continue;
+            }
+
+            result = false;
+            break;
+        }
+        closedir(dir);
+        return result;
     }
 
-    Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
-    if (pkey.get() == NULL) {
-        ALOGE("Couldn't read old PEM file");
-        return SYSTEM_ERROR;
+    void lock(uid_t userId) {
+        UserState* userState = getUserState(userId);
+        userState->zeroizeMasterKeysInMemory();
+        userState->setState(STATE_LOCKED);
     }
 
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
-    int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
-    if (len < 0) {
-        ALOGE("Couldn't measure PKCS#8 length");
-        return SYSTEM_ERROR;
-    }
+    ResponseCode get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
+        UserState* userState = getUserState(userId);
+        ResponseCode rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
+                userState->getState());
+        if (rc != NO_ERROR) {
+            return rc;
+        }
 
-    UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
-    uint8_t* tmp = pkcs8key.get();
-    if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
-        ALOGE("Couldn't convert to PKCS#8");
-        return SYSTEM_ERROR;
-    }
-
-    ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
-                                blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
-    if (rc != NO_ERROR) {
-        return rc;
-    }
-
-    return get(filename, blob, TYPE_KEY_PAIR, uid);
-}
-
-void KeyStore::readMetaData() {
-    int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
-    if (in < 0) {
-        return;
-    }
-    size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData));
-    if (fileLength != sizeof(mMetaData)) {
-        ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData));
-    }
-    close(in);
-}
-
-void KeyStore::writeMetaData() {
-    const char* tmpFileName = ".metadata.tmp";
-    int out =
-        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
-    if (out < 0) {
-        ALOGE("couldn't write metadata file: %s", strerror(errno));
-        return;
-    }
-    size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData));
-    if (fileLength != sizeof(mMetaData)) {
-        ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
-              sizeof(mMetaData));
-    }
-    close(out);
-    rename(tmpFileName, sMetaDataFile);
-}
-
-bool KeyStore::upgradeKeystore() {
-    bool upgraded = false;
-
-    if (mMetaData.version == 0) {
-        UserState* userState = getUserStateByUid(0);
-
-        // Initialize first so the directory is made.
-        userState->initialize();
-
-        // Migrate the old .masterkey file to user 0.
-        if (access(sOldMasterKey, R_OK) == 0) {
-            if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
-                ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
-                return false;
+        const uint8_t version = keyBlob->getVersion();
+        if (version < CURRENT_BLOB_VERSION) {
+            /* If we upgrade the key, we need to write it to disk again. Then
+             * it must be read it again since the blob is encrypted each time
+             * it's written.
+             */
+            if (upgradeBlob(filename, keyBlob, version, type, userId)) {
+                if ((rc = this->put(filename, keyBlob, userId)) != NO_ERROR
+                        || (rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
+                                userState->getState())) != NO_ERROR) {
+                    return rc;
+                }
             }
         }
 
-        // Initialize again in case we had a key.
-        userState->initialize();
+        /*
+         * This will upgrade software-backed keys to hardware-backed keys when
+         * the HAL for the device supports the newer key types.
+         */
+        if (rc == NO_ERROR && type == TYPE_KEY_PAIR
+                && mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2
+                && keyBlob->isFallback()) {
+            ResponseCode imported = importKey(keyBlob->getValue(), keyBlob->getLength(), filename,
+                    userId, keyBlob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
 
-        // Try to migrate existing keys.
-        DIR* dir = opendir(".");
+            // The HAL allowed the import, reget the key to have the "fresh"
+            // version.
+            if (imported == NO_ERROR) {
+                rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
+            }
+        }
+
+        // Keymaster 0.3 keys are valid keymaster 1.0 keys, so silently upgrade.
+        if (keyBlob->getType() == TYPE_KEY_PAIR) {
+            keyBlob->setType(TYPE_KEYMASTER_10);
+            rc = this->put(filename, keyBlob, userId);
+        }
+
+        if (type != TYPE_ANY && keyBlob->getType() != type) {
+            ALOGW("key found but type doesn't match: %d vs %d", keyBlob->getType(), type);
+            return KEY_NOT_FOUND;
+        }
+
+        return rc;
+    }
+
+    ResponseCode put(const char* filename, Blob* keyBlob, uid_t userId) {
+        UserState* userState = getUserState(userId);
+        return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState(),
+                mEntropy);
+    }
+
+    ResponseCode del(const char *filename, const BlobType type, uid_t userId) {
+        Blob keyBlob;
+        ResponseCode rc = get(filename, &keyBlob, type, userId);
+        if (rc == ::VALUE_CORRUPTED) {
+            // The file is corrupt, the best we can do is rm it.
+            return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+        }
+        if (rc != ::NO_ERROR) {
+            return rc;
+        }
+
+        if (keyBlob.getType() == ::TYPE_KEY_PAIR) {
+            // A device doesn't have to implement delete_key.
+            if (mDevice->delete_key != NULL && !keyBlob.isFallback()) {
+                keymaster_key_blob_t blob = {keyBlob.getValue(),
+                                             static_cast<size_t>(keyBlob.getLength())};
+                if (mDevice->delete_key(mDevice, &blob)) {
+                    rc = ::SYSTEM_ERROR;
+                }
+            }
+        }
+        if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
+            keymaster1_device_t* dev = getDeviceForBlob(keyBlob);
+            if (dev->delete_key) {
+                keymaster_key_blob_t blob;
+                blob.key_material = keyBlob.getValue();
+                blob.key_material_size = keyBlob.getLength();
+                dev->delete_key(dev, &blob);
+            }
+        }
+        if (rc != ::NO_ERROR) {
+            return rc;
+        }
+
+        return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+    }
+
+    ResponseCode list(const android::String8& prefix, android::Vector<android::String16> *matches,
+            uid_t userId) {
+
+        UserState* userState = getUserState(userId);
+        size_t n = prefix.length();
+
+        DIR* dir = opendir(userState->getUserDirName());
         if (!dir) {
-            // Give up now; maybe we can upgrade later.
-            ALOGE("couldn't open keystore's directory; something is wrong");
-            return false;
+            ALOGW("can't open directory for user: %s", strerror(errno));
+            return ::SYSTEM_ERROR;
         }
 
         struct dirent* file;
@@ -724,33 +1433,1968 @@
                 continue;
             }
 
-            // Find the current file's user.
-            char* end;
-            unsigned long thisUid = strtoul(file->d_name, &end, 10);
-            if (end[0] != '_' || end[1] == 0) {
-                continue;
-            }
-            UserState* otherUser = getUserStateByUid(thisUid);
-            if (otherUser->getUserId() != 0) {
-                unlinkat(dirfd(dir), file->d_name, 0);
-            }
+            if (!strncmp(prefix.string(), file->d_name, n)) {
+                const char* p = &file->d_name[n];
+                size_t plen = strlen(p);
 
-            // Rename the file into user directory.
-            DIR* otherdir = opendir(otherUser->getUserDirName());
-            if (otherdir == NULL) {
-                ALOGW("couldn't open user directory for rename");
-                continue;
+                size_t extra = decode_key_length(p, plen);
+                char *match = (char*) malloc(extra + 1);
+                if (match != NULL) {
+                    decode_key(match, p, plen);
+                    matches->push(android::String16(match, extra));
+                    free(match);
+                } else {
+                    ALOGW("could not allocate match of size %zd", extra);
+                }
             }
-            if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
-                ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
-            }
-            closedir(otherdir);
         }
         closedir(dir);
-
-        mMetaData.version = 1;
-        upgraded = true;
+        return ::NO_ERROR;
     }
 
-    return upgraded;
+    void addGrant(const char* filename, uid_t granteeUid) {
+        const grant_t* existing = getGrant(filename, granteeUid);
+        if (existing == NULL) {
+            grant_t* grant = new grant_t;
+            grant->uid = granteeUid;
+            grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
+            mGrants.add(grant);
+        }
+    }
+
+    bool removeGrant(const char* filename, uid_t granteeUid) {
+        for (android::Vector<grant_t*>::iterator it(mGrants.begin());
+                it != mGrants.end(); it++) {
+            grant_t* grant = *it;
+            if (grant->uid == granteeUid
+                    && !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
+                mGrants.erase(it);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    bool hasGrant(const char* filename, const uid_t uid) const {
+        return getGrant(filename, uid) != NULL;
+    }
+
+    ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename, uid_t userId,
+            int32_t flags) {
+        Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
+        if (!pkcs8.get()) {
+            return ::SYSTEM_ERROR;
+        }
+        Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+        if (!pkey.get()) {
+            return ::SYSTEM_ERROR;
+        }
+        int type = EVP_PKEY_type(pkey->type);
+        android::KeymasterArguments params;
+        add_legacy_key_authorizations(type, &params.params);
+        switch (type) {
+            case EVP_PKEY_RSA:
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+                break;
+            case EVP_PKEY_EC:
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM,
+                                                             KM_ALGORITHM_EC));
+                break;
+            default:
+                ALOGW("Unsupported key type %d", type);
+                return ::SYSTEM_ERROR;
+        }
+
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+        keymaster_blob_t input = {key, keyLen};
+        keymaster_key_blob_t blob = {nullptr, 0};
+        bool isFallback = false;
+        keymaster_error_t error = mDevice->import_key(mDevice, &inParams, KM_KEY_FORMAT_PKCS8,
+                                                      &input, &blob, NULL /* characteristics */);
+        if (error != KM_ERROR_OK){
+            ALOGE("Keymaster error %d importing key pair, falling back", error);
+
+            /*
+             * There should be no way to get here.  Fallback shouldn't ever really happen
+             * because the main device may be many (SW, KM0/SW hybrid, KM1/SW hybrid), but it must
+             * provide full support of the API.  In any case, we'll do the fallback just for
+             * consistency... and I suppose to cover for broken HW implementations.
+             */
+            error = mFallbackDevice->import_key(mFallbackDevice, &inParams, KM_KEY_FORMAT_PKCS8,
+                                                &input, &blob, NULL /* characteristics */);
+            isFallback = true;
+
+            if (error) {
+                ALOGE("Keymaster error while importing key pair with fallback: %d", error);
+                return SYSTEM_ERROR;
+            }
+        }
+
+        Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
+        free(const_cast<uint8_t*>(blob.key_material));
+
+        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+        keyBlob.setFallback(isFallback);
+
+        return put(filename, &keyBlob, userId);
+    }
+
+    bool isHardwareBacked(const android::String16& keyType) const {
+        if (mDevice == NULL) {
+            ALOGW("can't get keymaster device");
+            return false;
+        }
+
+        if (sRSAKeyType == keyType) {
+            return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0;
+        } else {
+            return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0
+                    && (mDevice->common.module->module_api_version
+                            >= KEYMASTER_MODULE_API_VERSION_0_2);
+        }
+    }
+
+    ResponseCode getKeyForName(Blob* keyBlob, const android::String8& keyName, const uid_t uid,
+            const BlobType type) {
+        android::String8 filepath8(getKeyNameForUidWithDir(keyName, uid));
+        uid_t userId = get_user_id(uid);
+
+        ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
+        if (responseCode == NO_ERROR) {
+            return responseCode;
+        }
+
+        // If this is one of the legacy UID->UID mappings, use it.
+        uid_t euid = get_keystore_euid(uid);
+        if (euid != uid) {
+            filepath8 = getKeyNameForUidWithDir(keyName, euid);
+            responseCode = get(filepath8.string(), keyBlob, type, userId);
+            if (responseCode == NO_ERROR) {
+                return responseCode;
+            }
+        }
+
+        // They might be using a granted key.
+        android::String8 filename8 = getKeyName(keyName);
+        char* end;
+        strtoul(filename8.string(), &end, 10);
+        if (end[0] != '_' || end[1] == 0) {
+            return KEY_NOT_FOUND;
+        }
+        filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
+                filename8.string());
+        if (!hasGrant(filepath8.string(), uid)) {
+            return responseCode;
+        }
+
+        // It is a granted key. Try to load it.
+        return get(filepath8.string(), keyBlob, type, userId);
+    }
+
+    /**
+     * Returns any existing UserState or creates it if it doesn't exist.
+     */
+    UserState* getUserState(uid_t userId) {
+        for (android::Vector<UserState*>::iterator it(mMasterKeys.begin());
+                it != mMasterKeys.end(); it++) {
+            UserState* state = *it;
+            if (state->getUserId() == userId) {
+                return state;
+            }
+        }
+
+        UserState* userState = new UserState(userId);
+        if (!userState->initialize()) {
+            /* There's not much we can do if initialization fails. Trying to
+             * unlock the keystore for that user will fail as well, so any
+             * subsequent request for this user will just return SYSTEM_ERROR.
+             */
+            ALOGE("User initialization failed for %u; subsuquent operations will fail", userId);
+        }
+        mMasterKeys.add(userState);
+        return userState;
+    }
+
+    /**
+     * Returns any existing UserState or creates it if it doesn't exist.
+     */
+    UserState* getUserStateByUid(uid_t uid) {
+        uid_t userId = get_user_id(uid);
+        return getUserState(userId);
+    }
+
+    /**
+     * Returns NULL if the UserState doesn't already exist.
+     */
+    const UserState* getUserState(uid_t userId) const {
+        for (android::Vector<UserState*>::const_iterator it(mMasterKeys.begin());
+                it != mMasterKeys.end(); it++) {
+            UserState* state = *it;
+            if (state->getUserId() == userId) {
+                return state;
+            }
+        }
+
+        return NULL;
+    }
+
+    /**
+     * Returns NULL if the UserState doesn't already exist.
+     */
+    const UserState* getUserStateByUid(uid_t uid) const {
+        uid_t userId = get_user_id(uid);
+        return getUserState(userId);
+    }
+
+private:
+    static const char* sOldMasterKey;
+    static const char* sMetaDataFile;
+    static const android::String16 sRSAKeyType;
+    Entropy* mEntropy;
+
+    keymaster1_device_t* mDevice;
+    keymaster1_device_t* mFallbackDevice;
+
+    android::Vector<UserState*> mMasterKeys;
+
+    android::Vector<grant_t*> mGrants;
+
+    typedef struct {
+        uint32_t version;
+    } keystore_metadata_t;
+
+    keystore_metadata_t mMetaData;
+
+    const grant_t* getGrant(const char* filename, uid_t uid) const {
+        for (android::Vector<grant_t*>::const_iterator it(mGrants.begin());
+                it != mGrants.end(); it++) {
+            grant_t* grant = *it;
+            if (grant->uid == uid
+                    && !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
+                return grant;
+            }
+        }
+        return NULL;
+    }
+
+    /**
+     * Upgrade code. This will upgrade the key from the current version
+     * to whatever is newest.
+     */
+    bool upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
+            const BlobType type, uid_t uid) {
+        bool updated = false;
+        uint8_t version = oldVersion;
+
+        /* From V0 -> V1: All old types were unknown */
+        if (version == 0) {
+            ALOGV("upgrading to version 1 and setting type %d", type);
+
+            blob->setType(type);
+            if (type == TYPE_KEY_PAIR) {
+                importBlobAsKey(blob, filename, uid);
+            }
+            version = 1;
+            updated = true;
+        }
+
+        /* From V1 -> V2: All old keys were encrypted */
+        if (version == 1) {
+            ALOGV("upgrading to version 2");
+
+            blob->setEncrypted(true);
+            version = 2;
+            updated = true;
+        }
+
+        /*
+         * If we've updated, set the key blob to the right version
+         * and write it.
+         */
+        if (updated) {
+            ALOGV("updated and writing file %s", filename);
+            blob->setVersion(version);
+        }
+
+        return updated;
+    }
+
+    /**
+     * Takes a blob that is an PEM-encoded RSA key as a byte array and
+     * converts it to a DER-encoded PKCS#8 for import into a keymaster.
+     * Then it overwrites the original blob with the new blob
+     * format that is returned from the keymaster.
+     */
+    ResponseCode importBlobAsKey(Blob* blob, const char* filename, uid_t uid) {
+        // We won't even write to the blob directly with this BIO, so const_cast is okay.
+        Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
+        if (b.get() == NULL) {
+            ALOGE("Problem instantiating BIO");
+            return SYSTEM_ERROR;
+        }
+
+        Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
+        if (pkey.get() == NULL) {
+            ALOGE("Couldn't read old PEM file");
+            return SYSTEM_ERROR;
+        }
+
+        Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
+        int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
+        if (len < 0) {
+            ALOGE("Couldn't measure PKCS#8 length");
+            return SYSTEM_ERROR;
+        }
+
+        UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
+        uint8_t* tmp = pkcs8key.get();
+        if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
+            ALOGE("Couldn't convert to PKCS#8");
+            return SYSTEM_ERROR;
+        }
+
+        ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
+                blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
+        if (rc != NO_ERROR) {
+            return rc;
+        }
+
+        return get(filename, blob, TYPE_KEY_PAIR, uid);
+    }
+
+    void readMetaData() {
+        int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
+        if (in < 0) {
+            return;
+        }
+        size_t fileLength = readFully(in, (uint8_t*) &mMetaData, sizeof(mMetaData));
+        if (fileLength != sizeof(mMetaData)) {
+            ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength,
+                    sizeof(mMetaData));
+        }
+        close(in);
+    }
+
+    void writeMetaData() {
+        const char* tmpFileName = ".metadata.tmp";
+        int out = TEMP_FAILURE_RETRY(open(tmpFileName,
+                O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+        if (out < 0) {
+            ALOGE("couldn't write metadata file: %s", strerror(errno));
+            return;
+        }
+        size_t fileLength = writeFully(out, (uint8_t*) &mMetaData, sizeof(mMetaData));
+        if (fileLength != sizeof(mMetaData)) {
+            ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
+                    sizeof(mMetaData));
+        }
+        close(out);
+        rename(tmpFileName, sMetaDataFile);
+    }
+
+    bool upgradeKeystore() {
+        bool upgraded = false;
+
+        if (mMetaData.version == 0) {
+            UserState* userState = getUserStateByUid(0);
+
+            // Initialize first so the directory is made.
+            userState->initialize();
+
+            // Migrate the old .masterkey file to user 0.
+            if (access(sOldMasterKey, R_OK) == 0) {
+                if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
+                    ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
+                    return false;
+                }
+            }
+
+            // Initialize again in case we had a key.
+            userState->initialize();
+
+            // Try to migrate existing keys.
+            DIR* dir = opendir(".");
+            if (!dir) {
+                // Give up now; maybe we can upgrade later.
+                ALOGE("couldn't open keystore's directory; something is wrong");
+                return false;
+            }
+
+            struct dirent* file;
+            while ((file = readdir(dir)) != NULL) {
+                // We only care about files.
+                if (file->d_type != DT_REG) {
+                    continue;
+                }
+
+                // Skip anything that starts with a "."
+                if (file->d_name[0] == '.') {
+                    continue;
+                }
+
+                // Find the current file's user.
+                char* end;
+                unsigned long thisUid = strtoul(file->d_name, &end, 10);
+                if (end[0] != '_' || end[1] == 0) {
+                    continue;
+                }
+                UserState* otherUser = getUserStateByUid(thisUid);
+                if (otherUser->getUserId() != 0) {
+                    unlinkat(dirfd(dir), file->d_name, 0);
+                }
+
+                // Rename the file into user directory.
+                DIR* otherdir = opendir(otherUser->getUserDirName());
+                if (otherdir == NULL) {
+                    ALOGW("couldn't open user directory for rename");
+                    continue;
+                }
+                if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
+                    ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
+                }
+                closedir(otherdir);
+            }
+            closedir(dir);
+
+            mMetaData.version = 1;
+            upgraded = true;
+        }
+
+        return upgraded;
+    }
+};
+
+const char* KeyStore::sOldMasterKey = ".masterkey";
+const char* KeyStore::sMetaDataFile = ".metadata";
+
+const android::String16 KeyStore::sRSAKeyType("RSA");
+
+namespace android {
+class KeyStoreProxy : public BnKeystoreService, public IBinder::DeathRecipient {
+public:
+    KeyStoreProxy(KeyStore* keyStore)
+        : mKeyStore(keyStore),
+          mOperationMap(this)
+    {
+    }
+
+    void binderDied(const wp<IBinder>& who) {
+        auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
+        for (auto token: operations) {
+            abort(token);
+        }
+    }
+
+    int32_t getState(int32_t userId) {
+        if (!checkBinderPermission(P_GET_STATE)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        return mKeyStore->getState(userId);
+    }
+
+    int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength) {
+        uid_t targetUid = getEffectiveUid(uid);
+        if (!checkBinderPermission(P_GET, targetUid)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        String8 name8(name);
+        Blob keyBlob;
+
+        ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid,
+                TYPE_GENERIC);
+        if (responseCode != ::NO_ERROR) {
+            *item = NULL;
+            *itemLength = 0;
+            return responseCode;
+        }
+
+        *item = (uint8_t*) malloc(keyBlob.getLength());
+        memcpy(*item, keyBlob.getValue(), keyBlob.getLength());
+        *itemLength = keyBlob.getLength();
+
+        return ::NO_ERROR;
+    }
+
+    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int targetUid,
+            int32_t flags) {
+        targetUid = getEffectiveUid(targetUid);
+        int32_t result = checkBinderPermissionAndKeystoreState(P_INSERT, targetUid,
+                                                    flags & KEYSTORE_FLAG_ENCRYPTED);
+        if (result != ::NO_ERROR) {
+            return result;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+
+        Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
+        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+        return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
+    }
+
+    int32_t del(const String16& name, int targetUid) {
+        targetUid = getEffectiveUid(targetUid);
+        if (!checkBinderPermission(P_DELETE, targetUid)) {
+            return ::PERMISSION_DENIED;
+        }
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+        return mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
+    }
+
+    int32_t exist(const String16& name, int targetUid) {
+        targetUid = getEffectiveUid(targetUid);
+        if (!checkBinderPermission(P_EXIST, targetUid)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+
+        if (access(filename.string(), R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+        return ::NO_ERROR;
+    }
+
+    int32_t list(const String16& prefix, int targetUid, Vector<String16>* matches) {
+        targetUid = getEffectiveUid(targetUid);
+        if (!checkBinderPermission(P_LIST, targetUid)) {
+            return ::PERMISSION_DENIED;
+        }
+        const String8 prefix8(prefix);
+        String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid));
+
+        if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ::NO_ERROR) {
+            return ::SYSTEM_ERROR;
+        }
+        return ::NO_ERROR;
+    }
+
+    int32_t reset() {
+        if (!checkBinderPermission(P_RESET)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        mKeyStore->resetUser(get_user_id(callingUid), false);
+        return ::NO_ERROR;
+    }
+
+    int32_t onUserPasswordChanged(int32_t userId, const String16& password) {
+        if (!checkBinderPermission(P_PASSWORD)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        const String8 password8(password);
+        // Flush the auth token table to prevent stale tokens from sticking
+        // around.
+        mAuthTokenTable.Clear();
+
+        if (password.size() == 0) {
+            ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
+            mKeyStore->resetUser(userId, true);
+            return ::NO_ERROR;
+        } else {
+            switch (mKeyStore->getState(userId)) {
+                case ::STATE_UNINITIALIZED: {
+                    // generate master key, encrypt with password, write to file,
+                    // initialize mMasterKey*.
+                    return mKeyStore->initializeUser(password8, userId);
+                }
+                case ::STATE_NO_ERROR: {
+                    // rewrite master key with new password.
+                    return mKeyStore->writeMasterKey(password8, userId);
+                }
+                case ::STATE_LOCKED: {
+                    ALOGE("Changing user %d's password while locked, clearing old encryption",
+                          userId);
+                    mKeyStore->resetUser(userId, true);
+                    return mKeyStore->initializeUser(password8, userId);
+                }
+            }
+            return ::SYSTEM_ERROR;
+        }
+    }
+
+    int32_t onUserAdded(int32_t userId, int32_t parentId) {
+        if (!checkBinderPermission(P_USER_CHANGED)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        // Sanity check that the new user has an empty keystore.
+        if (!mKeyStore->isEmpty(userId)) {
+            ALOGW("New user %d's keystore not empty. Clearing old entries.", userId);
+        }
+        // Unconditionally clear the keystore, just to be safe.
+        mKeyStore->resetUser(userId, false);
+        if (parentId != -1) {
+            // This profile must share the same master key password as the parent
+            // profile. Because the password of the parent profile is not known
+            // here, the best we can do is copy the parent's master key and master
+            // key file. This makes this profile use the same master key as the
+            // parent profile, forever.
+            return mKeyStore->copyMasterKey(parentId, userId);
+        } else {
+            return ::NO_ERROR;
+        }
+    }
+
+    int32_t onUserRemoved(int32_t userId) {
+        if (!checkBinderPermission(P_USER_CHANGED)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        mKeyStore->resetUser(userId, false);
+        return ::NO_ERROR;
+    }
+
+    int32_t lock(int32_t userId) {
+        if (!checkBinderPermission(P_LOCK)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        State state = mKeyStore->getState(userId);
+        if (state != ::STATE_NO_ERROR) {
+            ALOGD("calling lock in state: %d", state);
+            return state;
+        }
+
+        mKeyStore->lock(userId);
+        return ::NO_ERROR;
+    }
+
+    int32_t unlock(int32_t userId, const String16& pw) {
+        if (!checkBinderPermission(P_UNLOCK)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        State state = mKeyStore->getState(userId);
+        if (state != ::STATE_LOCKED) {
+            switch (state) {
+                case ::STATE_NO_ERROR:
+                    ALOGI("calling unlock when already unlocked, ignoring.");
+                    break;
+                case ::STATE_UNINITIALIZED:
+                    ALOGE("unlock called on uninitialized keystore.");
+                    break;
+                default:
+                    ALOGE("unlock called on keystore in unknown state: %d", state);
+                    break;
+            }
+            return state;
+        }
+
+        const String8 password8(pw);
+        // read master key, decrypt with password, initialize mMasterKey*.
+        return mKeyStore->readMasterKey(password8, userId);
+    }
+
+    bool isEmpty(int32_t userId) {
+        if (!checkBinderPermission(P_IS_EMPTY)) {
+            return false;
+        }
+
+        return mKeyStore->isEmpty(userId);
+    }
+
+    int32_t generate(const String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
+            int32_t flags, Vector<sp<KeystoreArg> >* args) {
+        targetUid = getEffectiveUid(targetUid);
+        int32_t result = checkBinderPermissionAndKeystoreState(P_INSERT, targetUid,
+                                                       flags & KEYSTORE_FLAG_ENCRYPTED);
+        if (result != ::NO_ERROR) {
+            return result;
+        }
+
+        KeymasterArguments params;
+        add_legacy_key_authorizations(keyType, &params.params);
+
+        switch (keyType) {
+            case EVP_PKEY_EC: {
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC));
+                if (keySize == -1) {
+                    keySize = EC_DEFAULT_KEY_SIZE;
+                } else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
+                    ALOGI("invalid key size %d", keySize);
+                    return ::SYSTEM_ERROR;
+                }
+                params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+                break;
+            }
+            case EVP_PKEY_RSA: {
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+                if (keySize == -1) {
+                    keySize = RSA_DEFAULT_KEY_SIZE;
+                } else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
+                    ALOGI("invalid key size %d", keySize);
+                    return ::SYSTEM_ERROR;
+                }
+                params.params.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, keySize));
+                unsigned long exponent = RSA_DEFAULT_EXPONENT;
+                if (args->size() > 1) {
+                    ALOGI("invalid number of arguments: %zu", args->size());
+                    return ::SYSTEM_ERROR;
+                } else if (args->size() == 1) {
+                    sp<KeystoreArg> expArg = args->itemAt(0);
+                    if (expArg != NULL) {
+                        Unique_BIGNUM pubExpBn(
+                                BN_bin2bn(reinterpret_cast<const unsigned char*>(expArg->data()),
+                                          expArg->size(), NULL));
+                        if (pubExpBn.get() == NULL) {
+                            ALOGI("Could not convert public exponent to BN");
+                            return ::SYSTEM_ERROR;
+                        }
+                        exponent = BN_get_word(pubExpBn.get());
+                        if (exponent == 0xFFFFFFFFL) {
+                            ALOGW("cannot represent public exponent as a long value");
+                            return ::SYSTEM_ERROR;
+                        }
+                    } else {
+                        ALOGW("public exponent not read");
+                        return ::SYSTEM_ERROR;
+                    }
+                }
+                params.params.push_back(keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT,
+                                                             exponent));
+                break;
+            }
+            default: {
+                ALOGW("Unsupported key type %d", keyType);
+                return ::SYSTEM_ERROR;
+            }
+        }
+
+        int32_t rc = generateKey(name, params, NULL, 0, targetUid, flags,
+                                 /*outCharacteristics*/ NULL);
+        if (rc != ::NO_ERROR) {
+            ALOGW("generate failed: %d", rc);
+        }
+        return translateResultToLegacyResult(rc);
+    }
+
+    int32_t import(const String16& name, const uint8_t* data, size_t length, int targetUid,
+            int32_t flags) {
+        const uint8_t* ptr = data;
+
+        Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, length));
+        if (!pkcs8.get()) {
+            return ::SYSTEM_ERROR;
+        }
+        Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+        if (!pkey.get()) {
+            return ::SYSTEM_ERROR;
+        }
+        int type = EVP_PKEY_type(pkey->type);
+        KeymasterArguments params;
+        add_legacy_key_authorizations(type, &params.params);
+        switch (type) {
+            case EVP_PKEY_RSA:
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA));
+                break;
+            case EVP_PKEY_EC:
+                params.params.push_back(keymaster_param_enum(KM_TAG_ALGORITHM,
+                                                             KM_ALGORITHM_EC));
+                break;
+            default:
+                ALOGW("Unsupported key type %d", type);
+                return ::SYSTEM_ERROR;
+        }
+        int32_t rc = importKey(name, params, KM_KEY_FORMAT_PKCS8, data, length, targetUid, flags,
+                               /*outCharacteristics*/ NULL);
+        if (rc != ::NO_ERROR) {
+            ALOGW("importKey failed: %d", rc);
+        }
+        return translateResultToLegacyResult(rc);
+    }
+
+    int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
+                 size_t* outLength) {
+        if (!checkBinderPermission(P_SIGN)) {
+            return ::PERMISSION_DENIED;
+        }
+        return doLegacySignVerify(name, data, length, out, outLength, NULL, 0, KM_PURPOSE_SIGN);
+    }
+
+    int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
+            const uint8_t* signature, size_t signatureLength) {
+        if (!checkBinderPermission(P_VERIFY)) {
+            return ::PERMISSION_DENIED;
+        }
+        return doLegacySignVerify(name, data, dataLength, NULL, NULL, signature, signatureLength,
+                                 KM_PURPOSE_VERIFY);
+    }
+
+    /*
+     * TODO: The abstraction between things stored in hardware and regular blobs
+     * of data stored on the filesystem should be moved down to keystore itself.
+     * Unfortunately the Java code that calls this has naming conventions that it
+     * knows about. Ideally keystore shouldn't be used to store random blobs of
+     * data.
+     *
+     * Until that happens, it's necessary to have a separate "get_pubkey" and
+     * "del_key" since the Java code doesn't really communicate what it's
+     * intentions are.
+     */
+    int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {
+        ExportResult result;
+        exportKey(name, KM_KEY_FORMAT_X509, NULL, NULL, UID_SELF, &result);
+        if (result.resultCode != ::NO_ERROR) {
+            ALOGW("export failed: %d", result.resultCode);
+            return translateResultToLegacyResult(result.resultCode);
+        }
+
+        *pubkey = result.exportData.release();
+        *pubkeyLength = result.dataLength;
+        return ::NO_ERROR;
+    }
+
+    int32_t grant(const String16& name, int32_t granteeUid) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
+        if (result != ::NO_ERROR) {
+            return result;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
+
+        if (access(filename.string(), R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+
+        mKeyStore->addGrant(filename.string(), granteeUid);
+        return ::NO_ERROR;
+    }
+
+    int32_t ungrant(const String16& name, int32_t granteeUid) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        int32_t result = checkBinderPermissionAndKeystoreState(P_GRANT);
+        if (result != ::NO_ERROR) {
+            return result;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid));
+
+        if (access(filename.string(), R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+
+        return mKeyStore->removeGrant(filename.string(), granteeUid) ? ::NO_ERROR : ::KEY_NOT_FOUND;
+    }
+
+    int64_t getmtime(const String16& name, int32_t uid) {
+        uid_t targetUid = getEffectiveUid(uid);
+        if (!checkBinderPermission(P_GET, targetUid)) {
+            ALOGW("permission denied for %d: getmtime", targetUid);
+            return -1L;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+
+        if (access(filename.string(), R_OK) == -1) {
+            ALOGW("could not access %s for getmtime", filename.string());
+            return -1L;
+        }
+
+        int fd = TEMP_FAILURE_RETRY(open(filename.string(), O_NOFOLLOW, O_RDONLY));
+        if (fd < 0) {
+            ALOGW("could not open %s for getmtime", filename.string());
+            return -1L;
+        }
+
+        struct stat s;
+        int ret = fstat(fd, &s);
+        close(fd);
+        if (ret == -1) {
+            ALOGW("could not stat %s for getmtime", filename.string());
+            return -1L;
+        }
+
+        return static_cast<int64_t>(s.st_mtime);
+    }
+
+    int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
+            int32_t destUid) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        pid_t spid = IPCThreadState::self()->getCallingPid();
+        if (!has_permission(callingUid, P_DUPLICATE, spid)) {
+            ALOGW("permission denied for %d: duplicate", callingUid);
+            return -1L;
+        }
+
+        State state = mKeyStore->getState(get_user_id(callingUid));
+        if (!isKeystoreUnlocked(state)) {
+            ALOGD("calling duplicate in state: %d", state);
+            return state;
+        }
+
+        if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
+            srcUid = callingUid;
+        } else if (!is_granted_to(callingUid, srcUid)) {
+            ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
+            return ::PERMISSION_DENIED;
+        }
+
+        if (destUid == -1) {
+            destUid = callingUid;
+        }
+
+        if (srcUid != destUid) {
+            if (static_cast<uid_t>(srcUid) != callingUid) {
+                ALOGD("can only duplicate from caller to other or to same uid: "
+                      "calling=%d, srcUid=%d, destUid=%d", callingUid, srcUid, destUid);
+                return ::PERMISSION_DENIED;
+            }
+
+            if (!is_granted_to(callingUid, destUid)) {
+                ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
+                return ::PERMISSION_DENIED;
+            }
+        }
+
+        String8 source8(srcKey);
+        String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid));
+
+        String8 target8(destKey);
+        String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid));
+
+        if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
+            ALOGD("destination already exists: %s", targetFile.string());
+            return ::SYSTEM_ERROR;
+        }
+
+        Blob keyBlob;
+        ResponseCode responseCode = mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY,
+                get_user_id(srcUid));
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
+
+        return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
+    }
+
+    int32_t is_hardware_backed(const String16& keyType) {
+        return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
+    }
+
+    int32_t clear_uid(int64_t targetUid64) {
+        uid_t targetUid = getEffectiveUid(targetUid64);
+        if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
+            return ::PERMISSION_DENIED;
+        }
+
+        String8 prefix = String8::format("%u_", targetUid);
+        Vector<String16> aliases;
+        if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ::NO_ERROR) {
+            return ::SYSTEM_ERROR;
+        }
+
+        for (uint32_t i = 0; i < aliases.size(); i++) {
+            String8 name8(aliases[i]);
+            String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid));
+            mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
+        }
+        return ::NO_ERROR;
+    }
+
+    int32_t addRngEntropy(const uint8_t* data, size_t dataLength) {
+        const keymaster1_device_t* device = mKeyStore->getDevice();
+        const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
+        int32_t devResult = KM_ERROR_UNIMPLEMENTED;
+        int32_t fallbackResult = KM_ERROR_UNIMPLEMENTED;
+        if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+                device->add_rng_entropy != NULL) {
+            devResult = device->add_rng_entropy(device, data, dataLength);
+        }
+        if (fallback->add_rng_entropy) {
+            fallbackResult = fallback->add_rng_entropy(fallback, data, dataLength);
+        }
+        if (devResult) {
+            return devResult;
+        }
+        if (fallbackResult) {
+            return fallbackResult;
+        }
+        return ::NO_ERROR;
+    }
+
+    int32_t generateKey(const String16& name, const KeymasterArguments& params,
+                        const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+                        KeyCharacteristics* outCharacteristics) {
+        uid = getEffectiveUid(uid);
+        int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid,
+                                                       flags & KEYSTORE_FLAG_ENCRYPTED);
+        if (rc != ::NO_ERROR) {
+            return rc;
+        }
+
+        rc = KM_ERROR_UNIMPLEMENTED;
+        bool isFallback = false;
+        keymaster_key_blob_t blob;
+        keymaster_key_characteristics_t *out = NULL;
+
+        const keymaster1_device_t* device = mKeyStore->getDevice();
+        const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+        if (device == NULL) {
+            return ::SYSTEM_ERROR;
+        }
+        // TODO: Seed from Linux RNG before this.
+        if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+                device->generate_key != NULL) {
+            if (!entropy) {
+                rc = KM_ERROR_OK;
+            } else if (device->add_rng_entropy) {
+                rc = device->add_rng_entropy(device, entropy, entropyLength);
+            } else {
+                rc = KM_ERROR_UNIMPLEMENTED;
+            }
+            if (rc == KM_ERROR_OK) {
+                rc = device->generate_key(device, &inParams, &blob, &out);
+            }
+        }
+        // If the HW device didn't support generate_key or generate_key failed
+        // fall back to the software implementation.
+        if (rc && fallback->generate_key != NULL) {
+            ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
+            isFallback = true;
+            if (!entropy) {
+                rc = KM_ERROR_OK;
+            } else if (fallback->add_rng_entropy) {
+                rc = fallback->add_rng_entropy(fallback, entropy, entropyLength);
+            } else {
+                rc = KM_ERROR_UNIMPLEMENTED;
+            }
+            if (rc == KM_ERROR_OK) {
+                rc = fallback->generate_key(fallback, &inParams, &blob, &out);
+            }
+        }
+
+        if (out) {
+            if (outCharacteristics) {
+                outCharacteristics->characteristics = *out;
+            } else {
+                keymaster_free_characteristics(out);
+            }
+            free(out);
+        }
+
+        if (rc) {
+            return rc;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+        Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+        keyBlob.setFallback(isFallback);
+        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+        free(const_cast<uint8_t*>(blob.key_material));
+
+        return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+    }
+
+    int32_t getKeyCharacteristics(const String16& name,
+                                  const keymaster_blob_t* clientId,
+                                  const keymaster_blob_t* appData,
+                                  int32_t uid,
+                                  KeyCharacteristics* outCharacteristics) {
+        if (!outCharacteristics) {
+            return KM_ERROR_UNEXPECTED_NULL_POINTER;
+        }
+
+        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 getKeyCharacteristics", callingUid,
+                  targetUid);
+            return ::PERMISSION_DENIED;
+        }
+
+        Blob keyBlob;
+        String8 name8(name);
+        int rc;
+
+        ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid,
+                TYPE_KEYMASTER_10);
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
+        keymaster_key_blob_t key;
+        key.key_material_size = keyBlob.getLength();
+        key.key_material = keyBlob.getValue();
+        keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
+        keymaster_key_characteristics_t *out = NULL;
+        if (!dev->get_key_characteristics) {
+            ALOGW("device does not implement get_key_characteristics");
+            return KM_ERROR_UNIMPLEMENTED;
+        }
+        rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
+        if (out) {
+            outCharacteristics->characteristics = *out;
+            free(out);
+        }
+        return rc ? rc : ::NO_ERROR;
+    }
+
+    int32_t importKey(const String16& name, const KeymasterArguments& params,
+                                keymaster_key_format_t format, const uint8_t *keyData,
+                                size_t keyLength, int uid, int flags,
+                                KeyCharacteristics* outCharacteristics) {
+        uid = getEffectiveUid(uid);
+        int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid,
+                                                       flags & KEYSTORE_FLAG_ENCRYPTED);
+        if (rc != ::NO_ERROR) {
+            return rc;
+        }
+
+        rc = KM_ERROR_UNIMPLEMENTED;
+        bool isFallback = false;
+        keymaster_key_blob_t blob;
+        keymaster_key_characteristics_t *out = NULL;
+
+        const keymaster1_device_t* device = mKeyStore->getDevice();
+        const keymaster1_device_t* fallback = mKeyStore->getFallbackDevice();
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+        const keymaster_blob_t input = {keyData, keyLength};
+        if (device == NULL) {
+            return ::SYSTEM_ERROR;
+        }
+        if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+                device->import_key != NULL) {
+            rc = device->import_key(device, &inParams, format,&input, &blob, &out);
+        }
+        if (rc && fallback->import_key != NULL) {
+            ALOGW("Primary keymaster device failed to import key, falling back to SW.");
+            isFallback = true;
+            rc = fallback->import_key(fallback, &inParams, format, &input, &blob, &out);
+        }
+        if (out) {
+            if (outCharacteristics) {
+                outCharacteristics->characteristics = *out;
+            } else {
+                keymaster_free_characteristics(out);
+            }
+            free(out);
+        }
+        if (rc) {
+            return rc;
+        }
+
+        String8 name8(name);
+        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+        Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+        keyBlob.setFallback(isFallback);
+        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+        free((void*) blob.key_material);
+
+        return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+    }
+
+    void exportKey(const String16& name, keymaster_key_format_t format,
+                           const keymaster_blob_t* clientId,
+                           const keymaster_blob_t* appData, int32_t uid, ExportResult* result) {
+
+        uid_t targetUid = getEffectiveUid(uid);
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        if (!is_granted_to(callingUid, targetUid)) {
+            ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid,
+                  targetUid);
+            result->resultCode = ::PERMISSION_DENIED;
+            return;
+        }
+
+        Blob keyBlob;
+        String8 name8(name);
+        int rc;
+
+        ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid,
+                TYPE_KEYMASTER_10);
+        if (responseCode != ::NO_ERROR) {
+            result->resultCode = responseCode;
+            return;
+        }
+        keymaster_key_blob_t key;
+        key.key_material_size = keyBlob.getLength();
+        key.key_material = keyBlob.getValue();
+        keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
+        if (!dev->export_key) {
+            result->resultCode = KM_ERROR_UNIMPLEMENTED;
+            return;
+        }
+        keymaster_blob_t output = {NULL, 0};
+        rc = dev->export_key(dev, format, &key, clientId, appData, &output);
+        result->exportData.reset(const_cast<uint8_t*>(output.data));
+        result->dataLength = output.data_length;
+        result->resultCode = rc ? rc : ::NO_ERROR;
+    }
+
+
+    void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
+               bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
+               size_t entropyLength, int32_t uid, OperationResult* result) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        uid_t targetUid = getEffectiveUid(uid);
+        if (!is_granted_to(callingUid, targetUid)) {
+            ALOGW("uid %d not permitted to act for uid %d in begin", callingUid,
+                  targetUid);
+            result->resultCode = ::PERMISSION_DENIED;
+            return;
+        }
+        if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
+            ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
+            result->resultCode = ::PERMISSION_DENIED;
+            return;
+        }
+        if (!checkAllowedOperationParams(params.params)) {
+            result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+            return;
+        }
+        Blob keyBlob;
+        String8 name8(name);
+        ResponseCode responseCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid,
+                TYPE_KEYMASTER_10);
+        if (responseCode != ::NO_ERROR) {
+            result->resultCode = responseCode;
+            return;
+        }
+        keymaster_key_blob_t key;
+        key.key_material_size = keyBlob.getLength();
+        key.key_material = keyBlob.getValue();
+        keymaster_operation_handle_t handle;
+        keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
+        keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        Unique_keymaster_key_characteristics characteristics;
+        characteristics.reset(new keymaster_key_characteristics_t);
+        err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+        const hw_auth_token_t* authToken = NULL;
+        int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
+                                                /*failOnTokenMissing*/ false);
+        // If per-operation auth is needed we need to begin the operation and
+        // the client will need to authorize that operation before calling
+        // update. Any other auth issues stop here.
+        if (authResult != ::NO_ERROR && authResult != ::OP_AUTH_NEEDED) {
+            result->resultCode = authResult;
+            return;
+        }
+        addAuthToParams(&opParams, authToken);
+        // Add entropy to the device first.
+        if (entropy) {
+            if (dev->add_rng_entropy) {
+                err = dev->add_rng_entropy(dev, entropy, entropyLength);
+            } else {
+                err = KM_ERROR_UNIMPLEMENTED;
+            }
+            if (err) {
+                result->resultCode = err;
+                return;
+            }
+        }
+        keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+
+        // Create a keyid for this key.
+        keymaster::km_id_t keyid;
+        if (!enforcement_policy.CreateKeyId(key, &keyid)) {
+            ALOGE("Failed to create a key ID for authorization checking.");
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+
+        // Check that all key authorization policy requirements are met.
+        keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+        key_auths.push_back(characteristics->sw_enforced);
+        keymaster::AuthorizationSet operation_params(inParams);
+        err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+                                                    0 /* op_handle */,
+                                                    true /* is_begin_operation */);
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+
+        keymaster_key_param_set_t outParams = {NULL, 0};
+
+        // If there are more than MAX_OPERATIONS, abort the oldest operation that was started as
+        // pruneable.
+        while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) {
+            ALOGD("Reached or exceeded concurrent operations limit");
+            if (!pruneOperation()) {
+                break;
+            }
+        }
+
+        err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+        if (err != KM_ERROR_OK) {
+            ALOGE("Got error %d from begin()", err);
+        }
+
+        // If there are too many operations abort the oldest operation that was
+        // started as pruneable and try again.
+        while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
+            ALOGE("Ran out of operation handles");
+            if (!pruneOperation()) {
+                break;
+            }
+            err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+        }
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+
+        sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev,
+                                                                appToken, characteristics.release(),
+                                                                pruneable);
+        if (authToken) {
+            mOperationMap.setOperationAuthToken(operationToken, authToken);
+        }
+        // Return the authentication lookup result. If this is a per operation
+        // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
+        // application should get an auth token using the handle before the
+        // first call to update, which will fail if keystore hasn't received the
+        // auth token.
+        result->resultCode = authResult;
+        result->token = operationToken;
+        result->handle = handle;
+        if (outParams.params) {
+            result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+            free(outParams.params);
+        }
+    }
+
+    void update(const sp<IBinder>& token, const KeymasterArguments& params, const uint8_t* data,
+                size_t dataLength, OperationResult* result) {
+        if (!checkAllowedOperationParams(params.params)) {
+            result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+            return;
+        }
+        const keymaster1_device_t* dev;
+        keymaster_operation_handle_t handle;
+        keymaster_purpose_t purpose;
+        keymaster::km_id_t keyid;
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+            result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+            return;
+        }
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
+        if (authResult != ::NO_ERROR) {
+            result->resultCode = authResult;
+            return;
+        }
+        keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+        keymaster_blob_t input = {data, dataLength};
+        size_t consumed = 0;
+        keymaster_blob_t output = {NULL, 0};
+        keymaster_key_param_set_t outParams = {NULL, 0};
+
+        // Check that all key authorization policy requirements are met.
+        keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+        key_auths.push_back(characteristics->sw_enforced);
+        keymaster::AuthorizationSet operation_params(inParams);
+        result->resultCode =
+                enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths,
+                                                      operation_params, handle,
+                                                      false /* is_begin_operation */);
+        if (result->resultCode) {
+            return;
+        }
+
+        keymaster_error_t err = dev->update(dev, handle, &inParams, &input, &consumed, &outParams,
+                                            &output);
+        result->data.reset(const_cast<uint8_t*>(output.data));
+        result->dataLength = output.data_length;
+        result->inputConsumed = consumed;
+        result->resultCode = err ? (int32_t) err : ::NO_ERROR;
+        if (outParams.params) {
+            result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+            free(outParams.params);
+        }
+    }
+
+    void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                const uint8_t* signature, size_t signatureLength,
+                const uint8_t* entropy, size_t entropyLength, OperationResult* result) {
+        if (!checkAllowedOperationParams(params.params)) {
+            result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+            return;
+        }
+        const keymaster1_device_t* dev;
+        keymaster_operation_handle_t handle;
+        keymaster_purpose_t purpose;
+        keymaster::km_id_t keyid;
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+            result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+            return;
+        }
+        std::vector<keymaster_key_param_t> opParams(params.params);
+        int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
+        if (authResult != ::NO_ERROR) {
+            result->resultCode = authResult;
+            return;
+        }
+        keymaster_error_t err;
+        if (entropy) {
+            if (dev->add_rng_entropy) {
+                err = dev->add_rng_entropy(dev, entropy, entropyLength);
+            } else {
+                err = KM_ERROR_UNIMPLEMENTED;
+            }
+            if (err) {
+                result->resultCode = err;
+                return;
+            }
+        }
+
+        keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+        keymaster_blob_t input = {signature, signatureLength};
+        keymaster_blob_t output = {NULL, 0};
+        keymaster_key_param_set_t outParams = {NULL, 0};
+
+        // Check that all key authorization policy requirements are met.
+        keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+        key_auths.push_back(characteristics->sw_enforced);
+        keymaster::AuthorizationSet operation_params(inParams);
+        err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+                                                    handle, false /* is_begin_operation */);
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+
+        err = dev->finish(dev, handle, &inParams, &input, &outParams, &output);
+        // Remove the operation regardless of the result
+        mOperationMap.removeOperation(token);
+        mAuthTokenTable.MarkCompleted(handle);
+
+        result->data.reset(const_cast<uint8_t*>(output.data));
+        result->dataLength = output.data_length;
+        result->resultCode = err ? (int32_t) err : ::NO_ERROR;
+        if (outParams.params) {
+            result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+            free(outParams.params);
+        }
+    }
+
+    int32_t abort(const sp<IBinder>& token) {
+        const keymaster1_device_t* dev;
+        keymaster_operation_handle_t handle;
+        keymaster_purpose_t purpose;
+        keymaster::km_id_t keyid;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
+            return KM_ERROR_INVALID_OPERATION_HANDLE;
+        }
+        mOperationMap.removeOperation(token);
+        int32_t rc;
+        if (!dev->abort) {
+            rc = KM_ERROR_UNIMPLEMENTED;
+        } else {
+            rc = dev->abort(dev, handle);
+        }
+        mAuthTokenTable.MarkCompleted(handle);
+        if (rc) {
+            return rc;
+        }
+        return ::NO_ERROR;
+    }
+
+    bool isOperationAuthorized(const sp<IBinder>& token) {
+        const keymaster1_device_t* dev;
+        keymaster_operation_handle_t handle;
+        const keymaster_key_characteristics_t* characteristics;
+        keymaster_purpose_t purpose;
+        keymaster::km_id_t keyid;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+            return false;
+        }
+        const hw_auth_token_t* authToken = NULL;
+        mOperationMap.getOperationAuthToken(token, &authToken);
+        std::vector<keymaster_key_param_t> ignored;
+        int32_t authResult = addOperationAuthTokenIfNeeded(token, &ignored);
+        return authResult == ::NO_ERROR;
+    }
+
+    int32_t addAuthToken(const uint8_t* token, size_t length) {
+        if (!checkBinderPermission(P_ADD_AUTH)) {
+            ALOGW("addAuthToken: permission denied for %d",
+                  IPCThreadState::self()->getCallingUid());
+            return ::PERMISSION_DENIED;
+        }
+        if (length != sizeof(hw_auth_token_t)) {
+            return KM_ERROR_INVALID_ARGUMENT;
+        }
+        hw_auth_token_t* authToken = new hw_auth_token_t;
+        memcpy(reinterpret_cast<void*>(authToken), token, sizeof(hw_auth_token_t));
+        // The table takes ownership of authToken.
+        mAuthTokenTable.AddAuthenticationToken(authToken);
+        return ::NO_ERROR;
+    }
+
+private:
+    static const int32_t UID_SELF = -1;
+
+    /**
+     * Prune the oldest pruneable operation.
+     */
+    inline bool pruneOperation() {
+        sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation();
+        ALOGD("Trying to prune operation %p", oldest.get());
+        size_t op_count_before_abort = mOperationMap.getOperationCount();
+        // We mostly ignore errors from abort() because all we care about is whether at least
+        // one operation has been removed.
+        int abort_error = abort(oldest);
+        if (mOperationMap.getOperationCount() >= op_count_before_abort) {
+            ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(),
+                  abort_error);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get the effective target uid for a binder operation that takes an
+     * optional uid as the target.
+     */
+    inline uid_t getEffectiveUid(int32_t targetUid) {
+        if (targetUid == UID_SELF) {
+            return IPCThreadState::self()->getCallingUid();
+        }
+        return static_cast<uid_t>(targetUid);
+    }
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission and if acting on other uids the grants to do so.
+     */
+    inline bool checkBinderPermission(perm_t permission, int32_t targetUid = UID_SELF) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        pid_t spid = IPCThreadState::self()->getCallingPid();
+        if (!has_permission(callingUid, permission, spid)) {
+            ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
+            return false;
+        }
+        if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
+            ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission and the target uid is the caller or the caller is system.
+     */
+    inline bool checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        pid_t spid = IPCThreadState::self()->getCallingPid();
+        if (!has_permission(callingUid, permission, spid)) {
+            ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
+            return false;
+        }
+        return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
+    }
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission or the target of the operation is the caller's uid. This is
+     * for operation where the permission is only for cross-uid activity and all
+     * uids are allowed to act on their own (ie: clearing all entries for a
+     * given uid).
+     */
+    inline bool checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
+        uid_t callingUid = IPCThreadState::self()->getCallingUid();
+        if (getEffectiveUid(targetUid) == callingUid) {
+            return true;
+        } else {
+            return checkBinderPermission(permission, targetUid);
+        }
+    }
+
+    /**
+     * Helper method to check that the caller has the required permission as
+     * well as the keystore is in the unlocked state if checkUnlocked is true.
+     *
+     * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
+     * otherwise the state of keystore when not unlocked and checkUnlocked is
+     * true.
+     */
+    inline int32_t checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid = -1,
+                                                 bool checkUnlocked = true) {
+        if (!checkBinderPermission(permission, targetUid)) {
+            return ::PERMISSION_DENIED;
+        }
+        State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
+        if (checkUnlocked && !isKeystoreUnlocked(state)) {
+            return state;
+        }
+
+        return ::NO_ERROR;
+
+    }
+
+    inline bool isKeystoreUnlocked(State state) {
+        switch (state) {
+        case ::STATE_NO_ERROR:
+            return true;
+        case ::STATE_UNINITIALIZED:
+        case ::STATE_LOCKED:
+            return false;
+        }
+        return false;
+    }
+
+    bool isKeyTypeSupported(const keymaster1_device_t* device, keymaster_keypair_t keyType) {
+        const int32_t device_api = device->common.module->module_api_version;
+        if (device_api == KEYMASTER_MODULE_API_VERSION_0_2) {
+            switch (keyType) {
+                case TYPE_RSA:
+                case TYPE_DSA:
+                case TYPE_EC:
+                    return true;
+                default:
+                    return false;
+            }
+        } else if (device_api >= KEYMASTER_MODULE_API_VERSION_0_3) {
+            switch (keyType) {
+                case TYPE_RSA:
+                    return true;
+                case TYPE_DSA:
+                    return device->flags & KEYMASTER_SUPPORTS_DSA;
+                case TYPE_EC:
+                    return device->flags & KEYMASTER_SUPPORTS_EC;
+                default:
+                    return false;
+            }
+        } else {
+            return keyType == TYPE_RSA;
+        }
+    }
+
+    /**
+     * Check that all keymaster_key_param_t's provided by the application are
+     * allowed. Any parameter that keystore adds itself should be disallowed here.
+     */
+    bool checkAllowedOperationParams(const std::vector<keymaster_key_param_t>& params) {
+        for (auto param: params) {
+            switch (param.tag) {
+                case KM_TAG_AUTH_TOKEN:
+                    return false;
+                default:
+                    break;
+            }
+        }
+        return true;
+    }
+
+    keymaster_error_t getOperationCharacteristics(const keymaster_key_blob_t& key,
+                                    const keymaster1_device_t* dev,
+                                    const std::vector<keymaster_key_param_t>& params,
+                                    keymaster_key_characteristics_t* out) {
+        UniquePtr<keymaster_blob_t> appId;
+        UniquePtr<keymaster_blob_t> appData;
+        for (auto param : params) {
+            if (param.tag == KM_TAG_APPLICATION_ID) {
+                appId.reset(new keymaster_blob_t);
+                appId->data = param.blob.data;
+                appId->data_length = param.blob.data_length;
+            } else if (param.tag == KM_TAG_APPLICATION_DATA) {
+                appData.reset(new keymaster_blob_t);
+                appData->data = param.blob.data;
+                appData->data_length = param.blob.data_length;
+            }
+        }
+        keymaster_key_characteristics_t* result = NULL;
+        if (!dev->get_key_characteristics) {
+            return KM_ERROR_UNIMPLEMENTED;
+        }
+        keymaster_error_t error = dev->get_key_characteristics(dev, &key, appId.get(),
+                                                               appData.get(), &result);
+        if (result) {
+            *out = *result;
+            free(result);
+        }
+        return error;
+    }
+
+    /**
+     * Get the auth token for this operation from the auth token table.
+     *
+     * Returns ::NO_ERROR if the auth token was set or none was required.
+     *         ::OP_AUTH_NEEDED if it is a per op authorization, no
+     *         authorization token exists for that operation and
+     *         failOnTokenMissing is false.
+     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
+     *         token for the operation
+     */
+    int32_t getAuthToken(const keymaster_key_characteristics_t* characteristics,
+                         keymaster_operation_handle_t handle,
+                         keymaster_purpose_t purpose,
+                         const hw_auth_token_t** authToken,
+                         bool failOnTokenMissing = true) {
+
+        std::vector<keymaster_key_param_t> allCharacteristics;
+        for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
+            allCharacteristics.push_back(characteristics->sw_enforced.params[i]);
+        }
+        for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
+            allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
+        }
+        keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
+                allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
+        switch (err) {
+            case keymaster::AuthTokenTable::OK:
+            case keymaster::AuthTokenTable::AUTH_NOT_REQUIRED:
+                return ::NO_ERROR;
+            case keymaster::AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
+            case keymaster::AuthTokenTable::AUTH_TOKEN_EXPIRED:
+            case keymaster::AuthTokenTable::AUTH_TOKEN_WRONG_SID:
+                return KM_ERROR_KEY_USER_NOT_AUTHENTICATED;
+            case keymaster::AuthTokenTable::OP_HANDLE_REQUIRED:
+                return failOnTokenMissing ? (int32_t) KM_ERROR_KEY_USER_NOT_AUTHENTICATED :
+                        (int32_t) ::OP_AUTH_NEEDED;
+            default:
+                ALOGE("Unexpected FindAuthorization return value %d", err);
+                return KM_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    inline void addAuthToParams(std::vector<keymaster_key_param_t>* params,
+                                const hw_auth_token_t* token) {
+        if (token) {
+            params->push_back(keymaster_param_blob(KM_TAG_AUTH_TOKEN,
+                                                   reinterpret_cast<const uint8_t*>(token),
+                                                   sizeof(hw_auth_token_t)));
+        }
+    }
+
+    /**
+     * Add the auth token for the operation to the param list if the operation
+     * requires authorization. Uses the cached result in the OperationMap if available
+     * otherwise gets the token from the AuthTokenTable and caches the result.
+     *
+     * Returns ::NO_ERROR if the auth token was added or not needed.
+     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
+     *         authenticated.
+     *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
+     *         operation token.
+     */
+    int32_t addOperationAuthTokenIfNeeded(sp<IBinder> token,
+                                          std::vector<keymaster_key_param_t>* params) {
+        const hw_auth_token_t* authToken = NULL;
+        mOperationMap.getOperationAuthToken(token, &authToken);
+        if (!authToken) {
+            const keymaster1_device_t* dev;
+            keymaster_operation_handle_t handle;
+            const keymaster_key_characteristics_t* characteristics = NULL;
+            keymaster_purpose_t purpose;
+            keymaster::km_id_t keyid;
+            if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev,
+                                            &characteristics)) {
+                return KM_ERROR_INVALID_OPERATION_HANDLE;
+            }
+            int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
+            if (result != ::NO_ERROR) {
+                return result;
+            }
+            if (authToken) {
+                mOperationMap.setOperationAuthToken(token, authToken);
+            }
+        }
+        addAuthToParams(params, authToken);
+        return ::NO_ERROR;
+    }
+
+    /**
+     * Translate a result value to a legacy return value. All keystore errors are
+     * preserved and keymaster errors become SYSTEM_ERRORs
+     */
+    inline int32_t translateResultToLegacyResult(int32_t result) {
+        if (result > 0) {
+            return result;
+        }
+        return ::SYSTEM_ERROR;
+    }
+
+    keymaster_key_param_t* getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
+        for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
+            if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
+                return &characteristics->hw_enforced.params[i];
+            }
+        }
+        for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
+            if (characteristics->sw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
+                return &characteristics->sw_enforced.params[i];
+            }
+        }
+        return NULL;
+    }
+
+    void addLegacyBeginParams(const String16& name, std::vector<keymaster_key_param_t>& params) {
+        // All legacy keys are DIGEST_NONE/PAD_NONE.
+        params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+        params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+
+        // Look up the algorithm of the key.
+        KeyCharacteristics characteristics;
+        int32_t rc = getKeyCharacteristics(name, NULL, NULL, UID_SELF, &characteristics);
+        if (rc != ::NO_ERROR) {
+            ALOGE("Failed to get key characteristics");
+            return;
+        }
+        keymaster_key_param_t* algorithm = getKeyAlgorithm(&characteristics.characteristics);
+        if (!algorithm) {
+            ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
+            return;
+        }
+        params.push_back(*algorithm);
+    }
+
+    int32_t doLegacySignVerify(const String16& name, const uint8_t* data, size_t length,
+                              uint8_t** out, size_t* outLength, const uint8_t* signature,
+                              size_t signatureLength, keymaster_purpose_t purpose) {
+
+        std::basic_stringstream<uint8_t> outBuffer;
+        OperationResult result;
+        KeymasterArguments inArgs;
+        addLegacyBeginParams(name, inArgs.params);
+        sp<IBinder> appToken(new BBinder);
+        sp<IBinder> token;
+
+        begin(appToken, name, purpose, true, inArgs, NULL, 0, UID_SELF, &result);
+        if (result.resultCode != ResponseCode::NO_ERROR) {
+            if (result.resultCode == ::KEY_NOT_FOUND) {
+                ALOGW("Key not found");
+            } else {
+                ALOGW("Error in begin: %d", result.resultCode);
+            }
+            return translateResultToLegacyResult(result.resultCode);
+        }
+        inArgs.params.clear();
+        token = result.token;
+        size_t consumed = 0;
+        size_t lastConsumed = 0;
+        do {
+            update(token, inArgs, data + consumed, length - consumed, &result);
+            if (result.resultCode != ResponseCode::NO_ERROR) {
+                ALOGW("Error in update: %d", result.resultCode);
+                return translateResultToLegacyResult(result.resultCode);
+            }
+            if (out) {
+                outBuffer.write(result.data.get(), result.dataLength);
+            }
+            lastConsumed = result.inputConsumed;
+            consumed += lastConsumed;
+        } while (consumed < length && lastConsumed > 0);
+
+        if (consumed != length) {
+            ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
+            return ::SYSTEM_ERROR;
+        }
+
+        finish(token, inArgs, signature, signatureLength, NULL, 0, &result);
+        if (result.resultCode != ResponseCode::NO_ERROR) {
+            ALOGW("Error in finish: %d", result.resultCode);
+            return translateResultToLegacyResult(result.resultCode);
+        }
+        if (out) {
+            outBuffer.write(result.data.get(), result.dataLength);
+        }
+
+        if (out) {
+            auto buf = outBuffer.str();
+            *out = new uint8_t[buf.size()];
+            memcpy(*out, buf.c_str(), buf.size());
+            *outLength = buf.size();
+        }
+
+        return ::NO_ERROR;
+    }
+
+    ::KeyStore* mKeyStore;
+    OperationMap mOperationMap;
+    keymaster::AuthTokenTable mAuthTokenTable;
+    KeystoreKeymasterEnforcement enforcement_policy;
+};
+
+}; // namespace android
+
+int main(int argc, char* argv[]) {
+    if (argc < 2) {
+        ALOGE("A directory must be specified!");
+        return 1;
+    }
+    if (chdir(argv[1]) == -1) {
+        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
+        return 1;
+    }
+
+    Entropy entropy;
+    if (!entropy.open()) {
+        return 1;
+    }
+
+    keymaster1_device_t* dev;
+    if (keymaster_device_initialize(&dev)) {
+        ALOGE("keystore keymaster could not be initialized; exiting");
+        return 1;
+    }
+
+    keymaster1_device_t* fallback;
+    if (fallback_keymaster_device_initialize(&fallback)) {
+        ALOGE("software keymaster could not be initialized; exiting");
+        return 1;
+    }
+
+    ks_is_selinux_enabled = is_selinux_enabled();
+    if (ks_is_selinux_enabled) {
+        union selinux_callback cb;
+        cb.func_audit = audit_callback;
+        selinux_set_callback(SELINUX_CB_AUDIT, cb);
+        cb.func_log = selinux_log_callback;
+        selinux_set_callback(SELINUX_CB_LOG, cb);
+        if (getcon(&tctx) != 0) {
+            ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n");
+            return -1;
+        }
+    } else {
+        ALOGI("SELinux: Keystore SELinux is disabled.\n");
+    }
+
+    KeyStore keyStore(&entropy, dev, fallback);
+    keyStore.initialize();
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<android::KeyStoreProxy> proxy = new android::KeyStoreProxy(&keyStore);
+    android::status_t ret = sm->addService(android::String16("android.security.keystore"), proxy);
+    if (ret != android::OK) {
+        ALOGE("Couldn't register binder service!");
+        return -1;
+    }
+
+    /*
+     * We're the only thread in existence, so we're just going to process
+     * Binder transaction as a single-threaded program.
+     */
+    android::IPCThreadState::self()->joinThreadPool();
+
+    keymaster_device_release(dev);
+    return 1;
 }
diff --git a/keystore/keystore.h b/keystore/keystore.h
deleted file mode 100644
index 5ef8842..0000000
--- a/keystore/keystore.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_KEYSTORE_H_
-#define KEYSTORE_KEYSTORE_H_
-
-#include "user_state.h"
-
-#include <hardware/keymaster1.h>
-
-#include <utils/Vector.h>
-
-#include "blob.h"
-
-typedef struct {
-    uint32_t uid;
-    const uint8_t* filename;
-} grant_t;
-
-class KeyStore {
-  public:
-    KeyStore(Entropy* entropy, keymaster1_device_t* device, keymaster1_device_t* fallback);
-    ~KeyStore();
-
-    /**
-     * Depending on the hardware keymaster version is this may return a
-     * keymaster0_device_t* cast to a keymaster1_device_t*. All methods from
-     * keymaster0 are safe to call, calls to keymaster1_device_t methods should
-     * be guarded by a check on the device's version.
-     */
-    keymaster1_device_t* getDevice() const { return mDevice; }
-
-    keymaster1_device_t* getFallbackDevice() const { return mFallbackDevice; }
-
-    keymaster1_device_t* getDeviceForBlob(const Blob& blob) const {
-        return blob.isFallback() ? mFallbackDevice : mDevice;
-    }
-
-    ResponseCode initialize();
-
-    State getState(uid_t userId) { return getUserState(userId)->getState(); }
-
-    ResponseCode initializeUser(const android::String8& pw, uid_t userId);
-
-    ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser);
-    ResponseCode writeMasterKey(const android::String8& pw, uid_t userId);
-    ResponseCode readMasterKey(const android::String8& pw, uid_t userId);
-
-    android::String8 getKeyName(const android::String8& keyName);
-    android::String8 getKeyNameForUid(const android::String8& keyName, uid_t uid);
-    android::String8 getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid);
-
-    /*
-     * Delete entries owned by userId. If keepUnencryptedEntries is true
-     * then only encrypted entries will be removed, otherwise all entries will
-     * be removed.
-     */
-    void resetUser(uid_t userId, bool keepUnenryptedEntries);
-    bool isEmpty(uid_t userId) const;
-
-    void lock(uid_t userId);
-
-    ResponseCode get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId);
-    ResponseCode put(const char* filename, Blob* keyBlob, uid_t userId);
-    ResponseCode del(const char* filename, const BlobType type, uid_t userId);
-    ResponseCode list(const android::String8& prefix, android::Vector<android::String16>* matches,
-                      uid_t userId);
-
-    void addGrant(const char* filename, uid_t granteeUid);
-    bool removeGrant(const char* filename, uid_t granteeUid);
-    bool hasGrant(const char* filename, const uid_t uid) const {
-        return getGrant(filename, uid) != NULL;
-    }
-
-    ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename, uid_t userId,
-                           int32_t flags);
-
-    bool isHardwareBacked(const android::String16& keyType) const;
-
-    ResponseCode getKeyForName(Blob* keyBlob, const android::String8& keyName, const uid_t uid,
-                               const BlobType type);
-
-    /**
-     * Returns any existing UserState or creates it if it doesn't exist.
-     */
-    UserState* getUserState(uid_t userId);
-
-    /**
-     * Returns any existing UserState or creates it if it doesn't exist.
-     */
-    UserState* getUserStateByUid(uid_t uid);
-
-    /**
-     * Returns NULL if the UserState doesn't already exist.
-     */
-    const UserState* getUserState(uid_t userId) const;
-
-    /**
-     * Returns NULL if the UserState doesn't already exist.
-     */
-    const UserState* getUserStateByUid(uid_t uid) const;
-
-  private:
-    static const char* sOldMasterKey;
-    static const char* sMetaDataFile;
-    static const android::String16 sRSAKeyType;
-    static const android::String16 sECKeyType;
-    Entropy* mEntropy;
-
-    keymaster1_device_t* mDevice;
-    keymaster1_device_t* mFallbackDevice;
-
-    android::Vector<UserState*> mMasterKeys;
-
-    android::Vector<grant_t*> mGrants;
-
-    typedef struct { uint32_t version; } keystore_metadata_t;
-
-    keystore_metadata_t mMetaData;
-
-    const grant_t* getGrant(const char* filename, uid_t uid) const;
-
-    /**
-     * Upgrade the key from the current version to whatever is newest.
-     */
-    bool upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
-                     const BlobType type, uid_t uid);
-
-    /**
-     * Takes a blob that is an PEM-encoded RSA key as a byte array and converts it to a DER-encoded
-     * PKCS#8 for import into a keymaster.  Then it overwrites the original blob with the new blob
-     * format that is returned from the keymaster.
-     */
-    ResponseCode importBlobAsKey(Blob* blob, const char* filename, uid_t uid);
-
-    void readMetaData();
-    void writeMetaData();
-
-    bool upgradeKeystore();
-};
-
-#endif  // KEYSTORE_KEYSTORE_H_
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index 34f1d9c..7f6996b 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -104,7 +104,7 @@
             int uid = -1; \
             if (argc > 3) { \
                 uid = atoi(argv[3]); \
-                fprintf(stderr, "Working with uid %d\n", uid); \
+                fprintf(stderr, "Running as uid %d\n", uid); \
             } \
             int32_t ret = service->cmd(String16(argv[2]), uid); \
             if (ret < 0) { \
@@ -117,28 +117,47 @@
         } \
     } while (0)
 
-#define STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(cmd) \
+#define SINGLE_ARG_PLUS_UID_DATA_RETURN(cmd) \
     do { \
         if (strcmp(argv[1], #cmd) == 0) { \
             if (argc < 3) { \
-                fprintf(stderr, "Usage: %s " #cmd " <name> [<uid>, <flags>]\n", argv[0]); \
+                fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
+                return 1; \
+            } \
+            uint8_t* data; \
+            size_t dataSize; \
+            int uid = -1; \
+            if (argc > 3) { \
+                uid = atoi(argv[3]); \
+                fprintf(stderr, "Running as uid %d\n", uid); \
+            } \
+            int32_t ret = service->cmd(String16(argv[2]), uid, &data, &dataSize); \
+            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); \
+                return 1; \
+            } else { \
+                fwrite(data, dataSize, 1, stdout); \
+                fflush(stdout); \
+                free(data); \
+                return 0; \
+            } \
+        } \
+    } while (0)
+
+#define STING_ARG_DATA_STDIN_INT_RETURN(cmd) \
+    do { \
+        if (strcmp(argv[1], #cmd) == 0) { \
+            if (argc < 3) { \
+                fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
                 return 1; \
             } \
             uint8_t* data; \
             size_t dataSize; \
             read_input(&data, &dataSize); \
-            int uid = -1; \
-            if (argc > 3) { \
-                uid = atoi(argv[3]); \
-                fprintf(stderr, "Working with uid %d\n", uid); \
-            } \
-            int32_t flags = 0; \
-            if (argc > 4) { \
-                flags = int32_t(atoi(argv[4])); \
-                fprintf(stderr, "Using flags %04x\n", flags); \
-            } \
-            int32_t ret = service->cmd(String16(argv[2]), data, dataSize, uid, flags); \
-            free(data); \
+            int32_t ret = service->cmd(String16(argv[2]), data, dataSize); \
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
@@ -162,16 +181,14 @@
             if (ret < 0) { \
                 fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
                 return 1; \
-            } else if (ret) { \
+            } else if (ret != ::NO_ERROR) { \
                 fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
                 return 1; \
-            } else if (dataSize) { \
+            } else { \
                 fwrite(data, dataSize, 1, stdout); \
                 fflush(stdout); \
                 free(data); \
                 return 0; \
-            } else { \
-                return 1; \
             } \
         } \
     } while (0)
@@ -194,39 +211,6 @@
     }
 }
 
-#define BUF_SIZE 1024
-static void read_input(uint8_t** data, size_t* dataSize) {
-    char buffer[BUF_SIZE];
-    size_t contentSize = 0;
-    char *content = (char *) malloc(sizeof(char) * BUF_SIZE);
-
-    if (content == NULL) {
-        fprintf(stderr, "read_input: failed to allocate content");
-        exit(1);
-    }
-    content[0] = '\0';
-    while (fgets(buffer, BUF_SIZE, stdin)) {
-        char *old = content;
-        contentSize += strlen(buffer);
-        content = (char *) realloc(content, contentSize);
-        if (content == NULL) {
-            fprintf(stderr, "read_input: failed to reallocate content.");
-            free(old);
-            exit(1);
-        }
-        strcat(content, buffer);
-    }
-
-    if (ferror(stdin)) {
-        free(content);
-        fprintf(stderr, "read_input: error reading from stdin.");
-        exit(1);
-    }
-
-    *data = (uint8_t*) content;
-    *dataSize = contentSize;
-}
-
 int main(int argc, char* argv[])
 {
     if (argc < 2) {
@@ -249,9 +233,9 @@
 
     SINGLE_INT_ARG_INT_RETURN(getState);
 
-    SINGLE_ARG_DATA_RETURN(get);
+    SINGLE_ARG_PLUS_UID_DATA_RETURN(get);
 
-    STING_ARG_DATA_STDIN_PLUS_UID_PLUS_FLAGS_INT_RETURN(insert);
+    // TODO: insert
 
     SINGLE_ARG_PLUS_UID_INT_RETURN(del);
 
@@ -276,7 +260,7 @@
 
     SINGLE_ARG_DATA_RETURN(get_pubkey);
 
-    SINGLE_ARG_PLUS_UID_INT_RETURN(grant);
+    // TODO: grant
 
     // TODO: ungrant
 
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index a46dfc7..c3d8f35 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -222,7 +222,7 @@
     keymaster_blob_t app_data_blob = {nullptr, 0};
     KeyCharacteristics characteristics;
     int32_t result = keystore_->getKeyCharacteristics(key_name16, &client_id_blob, &app_data_blob,
-                                                      &characteristics);
+                                                      kDefaultUID, &characteristics);
     hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
     software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
     return mapKeystoreError(result);
@@ -253,7 +253,7 @@
     keymaster_blob_t app_data_blob = {nullptr, 0};
     ExportResult export_result;
     keystore_->exportKey(key_name16, export_format, &client_id_blob, &app_data_blob,
-                         &export_result);
+                         kDefaultUID, &export_result);
     *export_data = ByteArrayAsString(export_result.exportData.get(), export_result.dataLength);
     return mapKeystoreError(export_result.resultCode);
 }
@@ -277,7 +277,7 @@
     CopyParameters(input_parameters, &input_arguments.params);
     OperationResult result;
     keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_arguments,
-                     NULL /*entropy*/, 0 /*entropyLength*/, &result);
+                     NULL /*entropy*/, 0 /*entropyLength*/, kDefaultUID, &result);
     int32_t error_code = mapKeystoreError(result.resultCode);
     if (error_code == KM_ERROR_OK) {
         *handle = getNextVirtualHandle();
diff --git a/keystore/keystore_get.cpp b/keystore/keystore_get.cpp
index 45ad415..2783816 100644
--- a/keystore/keystore_get.cpp
+++ b/keystore/keystore_get.cpp
@@ -31,7 +31,7 @@
     }
 
     size_t valueLength;
-    int32_t ret = service->get(String16(key, keyLength), value, &valueLength);
+    int32_t ret = service->get(String16(key, keyLength), -1, value, &valueLength);
     if (ret < 0) {
         return -1;
     } else if (ret != ::NO_ERROR) {
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
deleted file mode 100644
index 57b94b2..0000000
--- a/keystore/keystore_main.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "keystore"
-
-#include <keymaster/soft_keymaster_device.h>
-#include <keymaster/soft_keymaster_logger.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <cutils/log.h>
-
-#include "entropy.h"
-#include "key_store_service.h"
-#include "keystore.h"
-#include "permissions.h"
-
-/* KeyStore is a secured storage for key-value pairs. In this implementation,
- * each file stores one key-value pair. Keys are encoded in file names, and
- * values are encrypted with checksums. The encryption key is protected by a
- * user-defined password. To keep things simple, buffers are always larger than
- * the maximum space we needed, so boundary checks on buffers are omitted. */
-
-using keymaster::SoftKeymasterDevice;
-
-static int keymaster0_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
-    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
-    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
-
-    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
-    keymaster0_device_t* km0_device = NULL;
-    keymaster_error_t error = KM_ERROR_OK;
-
-    int rc = keymaster0_open(mod, &km0_device);
-    if (rc) {
-        ALOGE("Error opening keystore keymaster0 device.");
-        goto err;
-    }
-
-    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
-        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
-        km0_device->common.close(&km0_device->common);
-        km0_device = NULL;
-        // SoftKeymasterDevice will be deleted by keymaster_device_release()
-        *dev = soft_keymaster.release()->keymaster_device();
-        return 0;
-    }
-
-    ALOGE("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
-    error = soft_keymaster->SetHardwareDevice(km0_device);
-    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
-    if (error != KM_ERROR_OK) {
-        ALOGE("Got error %d from SetHardwareDevice", error);
-        rc = error;
-        goto err;
-    }
-
-    // SoftKeymasterDevice will be deleted by keymaster_device_release()
-    *dev = soft_keymaster.release()->keymaster_device();
-    return 0;
-
-err:
-    if (km0_device)
-        km0_device->common.close(&km0_device->common);
-    *dev = NULL;
-    return rc;
-}
-
-static int keymaster1_device_initialize(const hw_module_t* mod, keymaster1_device_t** dev) {
-    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
-    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
-
-    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
-    keymaster1_device_t* km1_device = NULL;
-    keymaster_error_t error = KM_ERROR_OK;
-
-    int rc = keymaster1_open(mod, &km1_device);
-    if (rc) {
-        ALOGE("Error %d opening keystore keymaster1 device", rc);
-        goto err;
-    }
-
-    error = soft_keymaster->SetHardwareDevice(km1_device);
-    km1_device = NULL;  // SoftKeymasterDevice has taken ownership.
-    if (error != KM_ERROR_OK) {
-        ALOGE("Got error %d from SetHardwareDevice", error);
-        rc = error;
-        goto err;
-    }
-
-    if (!soft_keymaster->Keymaster1DeviceIsGood()) {
-        ALOGI("Keymaster1 module is incomplete, using SoftKeymasterDevice wrapper");
-        // SoftKeymasterDevice will be deleted by keymaster_device_release()
-        *dev = soft_keymaster.release()->keymaster_device();
-        return 0;
-    } else {
-        ALOGI("Keymaster1 module is good, destroying wrapper and re-opening");
-        soft_keymaster.reset(NULL);
-        rc = keymaster1_open(mod, &km1_device);
-        if (rc) {
-            ALOGE("Error %d re-opening keystore keymaster1 device.", rc);
-            goto err;
-        }
-        *dev = km1_device;
-        return 0;
-    }
-
-err:
-    if (km1_device)
-        km1_device->common.close(&km1_device->common);
-    *dev = NULL;
-    return rc;
-}
-
-static int keymaster_device_initialize(keymaster1_device_t** dev) {
-    const hw_module_t* mod;
-
-    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
-    if (rc) {
-        ALOGI("Could not find any keystore module, using software-only implementation.");
-        // SoftKeymasterDevice will be deleted by keymaster_device_release()
-        *dev = (new SoftKeymasterDevice)->keymaster_device();
-        return 0;
-    }
-
-    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
-        return keymaster0_device_initialize(mod, dev);
-    } else {
-        return keymaster1_device_initialize(mod, dev);
-    }
-}
-
-// softkeymaster_logger appears not to be used in keystore, but it installs itself as the
-// logger used by SoftKeymasterDevice.
-static keymaster::SoftKeymasterLogger softkeymaster_logger;
-
-static int fallback_keymaster_device_initialize(keymaster1_device_t** dev) {
-    *dev = (new SoftKeymasterDevice)->keymaster_device();
-    // SoftKeymasterDevice will be deleted by keymaster_device_release()
-    return 0;
-}
-
-static void keymaster_device_release(keymaster1_device_t* dev) {
-    dev->common.close(&dev->common);
-}
-
-int main(int argc, char* argv[]) {
-    if (argc < 2) {
-        ALOGE("A directory must be specified!");
-        return 1;
-    }
-    if (chdir(argv[1]) == -1) {
-        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
-        return 1;
-    }
-
-    Entropy entropy;
-    if (!entropy.open()) {
-        return 1;
-    }
-
-    keymaster1_device_t* dev;
-    if (keymaster_device_initialize(&dev)) {
-        ALOGE("keystore keymaster could not be initialized; exiting");
-        return 1;
-    }
-
-    keymaster1_device_t* fallback;
-    if (fallback_keymaster_device_initialize(&fallback)) {
-        ALOGE("software keymaster could not be initialized; exiting");
-        return 1;
-    }
-
-    if (configure_selinux() == -1) {
-        return -1;
-    }
-
-    KeyStore keyStore(&entropy, dev, fallback);
-    keyStore.initialize();
-    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
-    android::sp<android::KeyStoreService> service = new android::KeyStoreService(&keyStore);
-    android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
-    if (ret != android::OK) {
-        ALOGE("Couldn't register binder service!");
-        return -1;
-    }
-
-    /*
-     * We're the only thread in existence, so we're just going to process
-     * Binder transaction as a single-threaded program.
-     */
-    android::IPCThreadState::self()->joinThreadPool();
-
-    keymaster_device_release(dev);
-    return 1;
-}
diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp
deleted file mode 100644
index bfcb43a..0000000
--- a/keystore/keystore_utils.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "keystore"
-
-#include "keystore_utils.h"
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cutils/log.h>
-#include <private/android_filesystem_config.h>
-
-#include <keymaster/android_keymaster_utils.h>
-
-size_t readFully(int fd, uint8_t* data, size_t size) {
-    size_t remaining = size;
-    while (remaining > 0) {
-        ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, remaining));
-        if (n <= 0) {
-            return size - remaining;
-        }
-        data += n;
-        remaining -= n;
-    }
-    return size;
-}
-
-size_t writeFully(int fd, uint8_t* data, size_t size) {
-    size_t remaining = size;
-    while (remaining > 0) {
-        ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, remaining));
-        if (n < 0) {
-            ALOGW("write failed: %s", strerror(errno));
-            return size - remaining;
-        }
-        data += n;
-        remaining -= n;
-    }
-    return size;
-}
-
-void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
-    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
-    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
-    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
-    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
-    params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
-    if (keyType == EVP_PKEY_RSA) {
-        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
-        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
-        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
-        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
-    }
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
-    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
-    params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
-    params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
-    params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
-    params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
-    params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
-    uint64_t now = keymaster::java_time(time(NULL));
-    params->push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
-}
-
-uid_t get_app_id(uid_t uid) {
-    return uid % AID_USER;
-}
-
-uid_t get_user_id(uid_t uid) {
-    return uid / AID_USER;
-}
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
deleted file mode 100644
index eaa5eb3..0000000
--- a/keystore/keystore_utils.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_KEYSTORE_UTILS_H_
-#define KEYSTORE_KEYSTORE_UTILS_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include <openssl/evp.h>
-#include <openssl/pem.h>
-
-#include <hardware/keymaster_defs.h>
-
-#include <UniquePtr.h>
-
-size_t readFully(int fd, uint8_t* data, size_t size);
-size_t writeFully(int fd, uint8_t* data, size_t size);
-
-void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params);
-
-/**
- * Returns the app ID (in the Android multi-user sense) for the current
- * UNIX UID.
- */
-uid_t get_app_id(uid_t uid);
-
-/**
- * Returns the user ID (in the Android multi-user sense) for the current
- * UNIX UID.
- */
-uid_t get_user_id(uid_t uid);
-
-struct EVP_PKEY_Delete {
-    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
-};
-typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
-
-struct PKCS8_PRIV_KEY_INFO_Delete {
-    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
-};
-typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
-
-#endif  // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp
deleted file mode 100644
index feacd8f..0000000
--- a/keystore/permissions.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "keystore"
-
-#include "permissions.h"
-
-#include <cutils/log.h>
-#include <cutils/sockets.h>
-#include <private/android_filesystem_config.h>
-
-#include <selinux/android.h>
-
-#include "keystore_utils.h"
-
-/* perm_labels associcated with keystore_key SELinux class verbs. */
-const char* perm_labels[] = {
-    "get_state", "get",      "insert",    "delete",    "exist",    "list",
-    "reset",     "password", "lock",      "unlock",    "is_empty", "sign",
-    "verify",    "grant",    "duplicate", "clear_uid", "add_auth", "user_changed",
-};
-
-struct user_euid {
-    uid_t uid;
-    uid_t euid;
-};
-
-user_euid user_euids[] = {
-    {AID_VPN, AID_SYSTEM}, {AID_WIFI, AID_SYSTEM}, {AID_ROOT, AID_SYSTEM},
-};
-
-struct user_perm {
-    uid_t uid;
-    perm_t perms;
-};
-
-static user_perm user_perms[] = {
-    {AID_SYSTEM, static_cast<perm_t>((uint32_t)(~0))},
-    {AID_VPN, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
-    {AID_WIFI, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
-    {AID_ROOT, static_cast<perm_t>(P_GET)},
-};
-
-static const perm_t DEFAULT_PERMS = static_cast<perm_t>(P_GET_STATE | P_GET | P_INSERT | P_DELETE |
-                                                        P_EXIST | P_LIST | P_SIGN | P_VERIFY);
-
-struct audit_data {
-    pid_t pid;
-    uid_t uid;
-};
-
-const char* get_perm_label(perm_t perm) {
-    unsigned int index = ffs(perm);
-    if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) {
-        return perm_labels[index - 1];
-    } else {
-        ALOGE("Keystore: Failed to retrieve permission label.\n");
-        abort();
-    }
-}
-
-static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) {
-    struct audit_data* ad = reinterpret_cast<struct audit_data*>(data);
-    if (!ad) {
-        ALOGE("No keystore audit data");
-        return 0;
-    }
-
-    snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
-    return 0;
-}
-
-static char* tctx;
-static int ks_is_selinux_enabled;
-
-int configure_selinux() {
-    ks_is_selinux_enabled = is_selinux_enabled();
-    if (ks_is_selinux_enabled) {
-        union selinux_callback cb;
-        cb.func_audit = audit_callback;
-        selinux_set_callback(SELINUX_CB_AUDIT, cb);
-        cb.func_log = selinux_log_callback;
-        selinux_set_callback(SELINUX_CB_LOG, cb);
-        if (getcon(&tctx) != 0) {
-            ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n");
-            return -1;
-        }
-    } else {
-        ALOGI("SELinux: Keystore SELinux is disabled.\n");
-    }
-
-    return 0;
-}
-
-static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
-    if (!ks_is_selinux_enabled) {
-        return true;
-    }
-
-    audit_data ad;
-    char* sctx = NULL;
-    const char* selinux_class = "keystore_key";
-    const char* str_perm = get_perm_label(perm);
-
-    if (!str_perm) {
-        return false;
-    }
-
-    if (getpidcon(spid, &sctx) != 0) {
-        ALOGE("SELinux: Failed to get source pid context.\n");
-        return false;
-    }
-
-    ad.pid = spid;
-    ad.uid = uid;
-
-    bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
-                                        reinterpret_cast<void*>(&ad)) == 0;
-    freecon(sctx);
-    return allowed;
-}
-
-/**
- * Returns the UID that the callingUid should act as. This is here for
- * legacy support of the WiFi and VPN systems and should be removed
- * when WiFi can operate in its own namespace.
- */
-uid_t get_keystore_euid(uid_t uid) {
-    for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
-        struct user_euid user = user_euids[i];
-        if (user.uid == uid) {
-            return user.euid;
-        }
-    }
-
-    return uid;
-}
-
-bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
-    // All system users are equivalent for multi-user support.
-    if (get_app_id(uid) == AID_SYSTEM) {
-        uid = AID_SYSTEM;
-    }
-
-    for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) {
-        struct user_perm user = user_perms[i];
-        if (user.uid == uid) {
-            return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid);
-        }
-    }
-
-    return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid);
-}
-
-/**
- * Returns true if the callingUid is allowed to interact in the targetUid's
- * namespace.
- */
-bool is_granted_to(uid_t callingUid, uid_t targetUid) {
-    if (callingUid == targetUid) {
-        return true;
-    }
-    for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
-        struct user_euid user = user_euids[i];
-        if (user.euid == callingUid && user.uid == targetUid) {
-            return true;
-        }
-    }
-
-    return false;
-}
diff --git a/keystore/permissions.h b/keystore/permissions.h
deleted file mode 100644
index f5f1831..0000000
--- a/keystore/permissions.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_PERMISSIONS_H_
-#define KEYSTORE_PERMISSIONS_H_
-
-#include <unistd.h>
-
-/* Here are the permissions, actions, users, and the main function. */
-enum perm_t {
-    P_GET_STATE = 1 << 0,
-    P_GET = 1 << 1,
-    P_INSERT = 1 << 2,
-    P_DELETE = 1 << 3,
-    P_EXIST = 1 << 4,
-    P_LIST = 1 << 5,
-    P_RESET = 1 << 6,
-    P_PASSWORD = 1 << 7,
-    P_LOCK = 1 << 8,
-    P_UNLOCK = 1 << 9,
-    P_IS_EMPTY = 1 << 10,
-    P_SIGN = 1 << 11,
-    P_VERIFY = 1 << 12,
-    P_GRANT = 1 << 13,
-    P_DUPLICATE = 1 << 14,
-    P_CLEAR_UID = 1 << 15,
-    P_ADD_AUTH = 1 << 16,
-    P_USER_CHANGED = 1 << 17,
-};
-
-const char* get_perm_label(perm_t perm);
-
-/**
- * Returns the UID that the callingUid should act as. This is here for
- * legacy support of the WiFi and VPN systems and should be removed
- * when WiFi can operate in its own namespace.
- */
-uid_t get_keystore_euid(uid_t uid);
-
-bool has_permission(uid_t uid, perm_t perm, pid_t spid);
-
-/**
- * Returns true if the callingUid is allowed to interact in the targetUid's
- * namespace.
- */
-bool is_granted_to(uid_t callingUid, uid_t targetUid);
-
-int configure_selinux();
-
-#endif  // KEYSTORE_PERMISSIONS_H_
diff --git a/keystore/test-keystore b/keystore/test-keystore
index 071cfcd..3be51b3 100755
--- a/keystore/test-keystore
+++ b/keystore/test-keystore
@@ -44,7 +44,7 @@
 function run() {
     # strip out carriage returns from adb
     # strip out date/time from ls -l
-    "$@" | tr -d '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
+    "$@" | tr --delete '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
 }
 
 function keystore() {
@@ -53,15 +53,8 @@
     run adb shell su $user keystore_cli "$@"
 }
 
-function keystore_in() {
-    declare -r user=$1
-    declare -r input=$2
-    shift; shift
-    run adb shell "echo '$input' | su $user keystore_cli $@"
-}
-
 function list_keystore_directory() {
-    run adb shell ls -al /data/misc/keystore$@
+    run adb shell ls -al /data/misc/keystore
 }
 
 function compare() {
@@ -75,211 +68,195 @@
     # reset
     #
     log "reset keystore as system user"
-    keystore system reset
-    expect "reset: No error (1)"
+    keystore system r
+    expect "1 No error"
     list_keystore_directory
-    expect "-rw------- keystore keystore        4 .metadata"
-    expect "drwx------ keystore keystore          user_0"
 
     #
     # basic tests as system/root
     #
     log "root does not have permission to run test"
-    keystore root test
-    expect "test: Permission denied (6)"
-
+    keystore root t
+    expect "6 Permission denied"
+    
     log "but system user does"
-    keystore system test
-    expect "test: Uninitialized (3)"
+    keystore system t
+    expect "3 Uninitialized"
     list_keystore_directory
-    expect "-rw------- keystore keystore        4 .metadata"
-    expect "drwx------ keystore keystore          user_0"
 
     log "password is now bar"
-    keystore system password bar
-    expect "password: No error (1)"
-    list_keystore_directory /user_0
+    keystore system p bar
+    expect "1 No error"
+    list_keystore_directory
     expect "-rw------- keystore keystore       84 .masterkey"
-
+    
     log "no error implies initialized and unlocked"
-    keystore system test
-    expect "test: No error (1)"
-
+    keystore system t
+    expect "1 No error"
+    
     log "saw with no argument"
-    keystore system saw
+    keystore system s
+    expect "5 Protocol error"
 
     log "saw nothing"
-    keystore system saw ""
+    keystore system s ""
+    expect "1 No error"
 
     log "add key baz"
-    keystore_in system quux insert baz
-    expect "insert: No error (1)"
+    keystore system i baz quux
+    expect "1 No error"
 
     log "1000 is uid of system"
-    list_keystore_directory /user_0
+    list_keystore_directory
     expect "-rw------- keystore keystore       84 .masterkey"
     expect "-rw------- keystore keystore       52 1000_baz"
 
     log "saw baz"
-    keystore system saw
+    keystore system s ""
+    expect "1 No error"
     expect "baz"
 
     log "get baz"
-    keystore system get baz
+    keystore system g baz
+    expect "1 No error"
     expect "quux"
 
     log "root can read system user keys (as can wifi or vpn users)"
-    keystore root get baz
+    keystore root g baz
+    expect "1 No error"
     expect "quux"
 
     #
     # app user tests
     #
 
-    # u0_a0 has uid 10000, as seen below
+    # app_0 has uid 10000, as seen below
     log "other uses cannot see the system keys"
-    keystore u0_a0 get baz
-
+    keystore app_0 g baz
+    expect "7 Key not found"
+    
     log "app user cannot use reset, password, lock, unlock"
-    keystore u0_a0 reset
-    expect "reset: Permission denied (6)"
-    keystore u0_a0 password some_pass
-    expect "password: Permission denied (6)"
-    keystore u0_a0 lock
-    expect "lock: Permission denied (6)"
-    keystore u0_a0 unlock some_pass
-    expect "unlock: Permission denied (6)"
+    keystore app_0 r
+    expect "6 Permission denied"
+    keystore app_0 p
+    expect "6 Permission denied"
+    keystore app_0 l
+    expect "6 Permission denied"
+    keystore app_0 u
+    expect "6 Permission denied"
 
-    log "install u0_a0 key"
-    keystore_in u0_a0 deadbeef insert 0x
-    expect "insert: No error (1)"
-    list_keystore_directory /user_0
+    log "install app_0 key"
+    keystore app_0 i 0x deadbeef
+    expect 1 No error
+    list_keystore_directory
     expect "-rw------- keystore keystore       84 .masterkey"
     expect "-rw------- keystore keystore       52 10000_0x"
     expect "-rw------- keystore keystore       52 1000_baz"
 
     log "get with no argument"
-    keystore u0_a0 get
-    expect "Usage: keystore_cli get <name>"
-
-    log "few get tests for an app"
-    keystore u0_a0 get 0x
+    keystore app_0 g
+    expect "5 Protocol error"
+    
+    keystore app_0 g 0x
+    expect "1 No error"
     expect "deadbeef"
-
-    keystore_in u0_a0 barney insert fred
-    expect "insert: No error (1)"
-
-    keystore u0_a0 saw
+    
+    keystore app_0 i fred barney
+    expect "1 No error"
+    
+    keystore app_0 s ""
+    expect "1 No error"
     expect "0x"
     expect "fred"
 
     log "note that saw returns the suffix of prefix matches"
-    keystore u0_a0 saw fr # fred
+    keystore app_0 s fr # fred
+    expect "1 No error"
     expect "ed" # fred
 
     #
     # lock tests
     #
     log "lock the store as system"
-    keystore system lock
-    expect "lock: No error (1)"
-    keystore system test
-    expect "test: Locked (2)"
-
+    keystore system l
+    expect "1 No error"
+    keystore system t
+    expect "2 Locked"
+    
     log "saw works while locked"
-    keystore u0_a0 saw
+    keystore app_0 s ""
+    expect "1 No error"
     expect "0x"
     expect "fred"
 
-    log "...and app can read keys..."
-    keystore u0_a0 get 0x
-    expect "deadbeef"
-
-    log "...but they cannot be deleted."
-    keystore u0_a0 exist 0x
-    expect "exist: No error (1)"
-    keystore u0_a0 del_key 0x
-    expect "del_key: Key not found (7)"
+    log "...but cannot read keys..."
+    keystore app_0 g 0x
+    expect "2 Locked"
+    
+    log "...but they can be deleted."
+    keystore app_0 e 0x
+    expect "1 No error"
+    keystore app_0 d 0x
+    expect "1 No error"
+    keystore app_0 e 0x
+    expect "7 Key not found"
 
     #
     # password
     #
     log "wrong password"
-    keystore system unlock foo
-    expect "unlock: Wrong password (4 tries left) (13)"
+    keystore system u foo
+    expect "13 Wrong password (4 tries left)"
     log "right password"
-    keystore system unlock bar
-    expect "unlock: No error (1)"
-
+    keystore system u bar
+    expect "1 No error"
+    
     log "make the password foo"
-    keystore system password foo
-    expect "password: No error (1)"
-
+    keystore system p foo
+    expect "1 No error"
+    
     #
     # final reset
     #
     log "reset wipes everything for all users"
-    keystore system reset
-    expect "reset: No error (1)"
+    keystore system r
+    expect "1 No error"
     list_keystore_directory
-    expect "-rw------- keystore keystore        4 .metadata"
-    expect "drwx------ keystore keystore          user_0"
-    list_keystore_directory /user_0
-
-    keystore system test
-    expect "test: Uninitialized (3)"
-}
-
-function test_grant() {
-    log "test granting"
-    keystore system reset
-    expect "reset: No error (1)"
-    keystore system password test_pass
-    expect "password: No error (1)"
-
-    keystore_in system granted_key_value insert granted_key
-    expect "insert: No error (1)"
-  
-    # Cannot read before grant.
-    keystore u10_a0 get granted_key
     
-    # Grant and read.
-    log "System grants to u0_a1"
-    keystore system grant granted_key 10001 
-    expect "Working with uid 10001"
-    expect "grant: No error (1)"
-    keystore u0_a1 get 1000_granted_key
-    expect "granted_key_value"
+    keystore system t
+    expect "3 Uninitialized"
+
 }
 
 function test_4599735() {
     # http://b/4599735
     log "start regression test for b/4599735"
-    keystore system reset
-    expect "reset: No error (1)"
-    list_keystore_directory /user_0
+    keystore system r
+    expect "1 No error"
 
-    keystore system password foo
-    expect "password: No error (1)"
+    keystore system p foo
+    expect "1 No error"
 
-    keystore_in system quux insert baz
-    expect "insert: No error (1)"
-
-    keystore root get baz
+    keystore system i baz quux
+    expect "1 No error"
+    
+    keystore root g baz
+    expect "1 No error"
     expect "quux"
 
-    keystore system lock
-    expect "lock: No error (1)"
+    keystore system l
+    expect "1 No error"
 
-    keystore system password foo
-    expect "password: No error (1)"
+    keystore system p foo
+    expect "1 No error"
 
     log "after unlock, regression led to result of '8 Value corrupted'"
-    keystore root get baz
+    keystore root g baz
+    expect "1 No error"
     expect "quux"
 
-    keystore system reset
-    expect "reset: No error (1)"
+    keystore system r
+    expect "1 No error"
     log "end regression test for b/4599735"
 }
 
@@ -288,7 +265,6 @@
     log $tag START
     test_basic
     test_4599735
-    test_grant
     compare
     log $tag PASSED
     cleanup_output
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
deleted file mode 100644
index 3da88c2..0000000
--- a/keystore/user_state.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "keystore"
-
-#include "user_state.h"
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-
-#include <openssl/evp.h>
-
-#include <cutils/log.h>
-
-#include "blob.h"
-#include "keystore_utils.h"
-
-UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
-    asprintf(&mUserDir, "user_%u", mUserId);
-    asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
-}
-
-UserState::~UserState() {
-    free(mUserDir);
-    free(mMasterKeyFile);
-}
-
-bool UserState::initialize() {
-    if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
-        ALOGE("Could not create directory '%s'", mUserDir);
-        return false;
-    }
-
-    if (access(mMasterKeyFile, R_OK) == 0) {
-        setState(STATE_LOCKED);
-    } else {
-        setState(STATE_UNINITIALIZED);
-    }
-
-    return true;
-}
-
-void UserState::setState(State state) {
-    mState = state;
-    if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
-        mRetry = MAX_RETRY;
-    }
-}
-
-void UserState::zeroizeMasterKeysInMemory() {
-    memset(mMasterKey, 0, sizeof(mMasterKey));
-    memset(mSalt, 0, sizeof(mSalt));
-    memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
-    memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
-}
-
-bool UserState::deleteMasterKey() {
-    setState(STATE_UNINITIALIZED);
-    zeroizeMasterKeysInMemory();
-    return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
-}
-
-ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
-    if (!generateMasterKey(entropy)) {
-        return SYSTEM_ERROR;
-    }
-    ResponseCode response = writeMasterKey(pw, entropy);
-    if (response != NO_ERROR) {
-        return response;
-    }
-    setupMasterKeys();
-    return ::NO_ERROR;
-}
-
-ResponseCode UserState::copyMasterKey(UserState* src) {
-    if (mState != STATE_UNINITIALIZED) {
-        return ::SYSTEM_ERROR;
-    }
-    if (src->getState() != STATE_NO_ERROR) {
-        return ::SYSTEM_ERROR;
-    }
-    memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
-    setupMasterKeys();
-    return copyMasterKeyFile(src);
-}
-
-ResponseCode UserState::copyMasterKeyFile(UserState* src) {
-    /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
-     * password so we cannot generate a new file with a new salt.
-     */
-    int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
-    if (in < 0) {
-        return ::SYSTEM_ERROR;
-    }
-    blob rawBlob;
-    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
-    if (close(in) != 0) {
-        return ::SYSTEM_ERROR;
-    }
-    int out =
-        TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
-    if (out < 0) {
-        return ::SYSTEM_ERROR;
-    }
-    size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
-    if (close(out) != 0) {
-        return ::SYSTEM_ERROR;
-    }
-    if (outLength != length) {
-        ALOGW("blob not fully written %zu != %zu", outLength, length);
-        unlink(mMasterKeyFile);
-        return ::SYSTEM_ERROR;
-    }
-    return ::NO_ERROR;
-}
-
-ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
-    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
-    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
-    AES_KEY passwordAesKey;
-    AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
-    Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
-    return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
-}
-
-ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
-    int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
-    if (in < 0) {
-        return SYSTEM_ERROR;
-    }
-
-    // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
-    // to use with decryptBlob
-    blob rawBlob;
-    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
-    if (close(in) != 0) {
-        return SYSTEM_ERROR;
-    }
-    // find salt at EOF if present, otherwise we have an old file
-    uint8_t* salt;
-    if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
-        salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
-    } else {
-        salt = NULL;
-    }
-    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
-    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
-    AES_KEY passwordAesKey;
-    AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
-    Blob masterKeyBlob(rawBlob);
-    ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
-    if (response == SYSTEM_ERROR) {
-        return response;
-    }
-    if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
-        // If salt was missing, generate one and write a new master key file with the salt.
-        if (salt == NULL) {
-            if (!generateSalt(entropy)) {
-                return SYSTEM_ERROR;
-            }
-            response = writeMasterKey(pw, entropy);
-        }
-        if (response == NO_ERROR) {
-            memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
-            setupMasterKeys();
-        }
-        return response;
-    }
-    if (mRetry <= 0) {
-        reset();
-        return UNINITIALIZED;
-    }
-    --mRetry;
-    switch (mRetry) {
-    case 0:
-        return WRONG_PASSWORD_0;
-    case 1:
-        return WRONG_PASSWORD_1;
-    case 2:
-        return WRONG_PASSWORD_2;
-    case 3:
-        return WRONG_PASSWORD_3;
-    default:
-        return WRONG_PASSWORD_3;
-    }
-}
-
-bool UserState::reset() {
-    DIR* dir = opendir(getUserDirName());
-    if (!dir) {
-        // If the directory doesn't exist then nothing to do.
-        if (errno == ENOENT) {
-            return true;
-        }
-        ALOGW("couldn't open user directory: %s", strerror(errno));
-        return false;
-    }
-
-    struct dirent* file;
-    while ((file = readdir(dir)) != NULL) {
-        // skip . and ..
-        if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
-            continue;
-        }
-
-        unlinkat(dirfd(dir), file->d_name, 0);
-    }
-    closedir(dir);
-    return true;
-}
-
-void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
-                                        uint8_t* salt) {
-    size_t saltSize;
-    if (salt != NULL) {
-        saltSize = SALT_SIZE;
-    } else {
-        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
-        salt = (uint8_t*)"keystore";
-        // sizeof = 9, not strlen = 8
-        saltSize = sizeof("keystore");
-    }
-
-    PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
-                           8192, keySize, key);
-}
-
-bool UserState::generateSalt(Entropy* entropy) {
-    return entropy->generate_random_data(mSalt, sizeof(mSalt));
-}
-
-bool UserState::generateMasterKey(Entropy* entropy) {
-    if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
-        return false;
-    }
-    if (!generateSalt(entropy)) {
-        return false;
-    }
-    return true;
-}
-
-void UserState::setupMasterKeys() {
-    AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
-    AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
-    setState(STATE_NO_ERROR);
-}
diff --git a/keystore/user_state.h b/keystore/user_state.h
deleted file mode 100644
index 2a52f81..0000000
--- a/keystore/user_state.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_USER_STATE_H_
-#define KEYSTORE_USER_STATE_H_
-
-#include <sys/types.h>
-
-#include <openssl/aes.h>
-
-#include <utils/String8.h>
-
-#include <keystore/keystore.h>
-
-#include "entropy.h"
-
-class UserState {
-  public:
-    UserState(uid_t userId);
-    ~UserState();
-
-    bool initialize();
-
-    uid_t getUserId() const { return mUserId; }
-    const char* getUserDirName() const { return mUserDir; }
-
-    const char* getMasterKeyFileName() const { return mMasterKeyFile; }
-
-    void setState(State state);
-    State getState() const { return mState; }
-
-    int8_t getRetry() const { return mRetry; }
-
-    void zeroizeMasterKeysInMemory();
-    bool deleteMasterKey();
-
-    ResponseCode initialize(const android::String8& pw, Entropy* entropy);
-
-    ResponseCode copyMasterKey(UserState* src);
-    ResponseCode copyMasterKeyFile(UserState* src);
-    ResponseCode writeMasterKey(const android::String8& pw, Entropy* entropy);
-    ResponseCode readMasterKey(const android::String8& pw, Entropy* entropy);
-
-    AES_KEY* getEncryptionKey() { return &mMasterKeyEncryption; }
-    AES_KEY* getDecryptionKey() { return &mMasterKeyDecryption; }
-
-    bool reset();
-
-  private:
-    static const int MASTER_KEY_SIZE_BYTES = 16;
-    static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
-
-    static const int MAX_RETRY = 4;
-    static const size_t SALT_SIZE = 16;
-
-    void generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
-                                 uint8_t* salt);
-    bool generateSalt(Entropy* entropy);
-    bool generateMasterKey(Entropy* entropy);
-    void setupMasterKeys();
-
-    uid_t mUserId;
-
-    char* mUserDir;
-    char* mMasterKeyFile;
-
-    State mState;
-    int8_t mRetry;
-
-    uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
-    uint8_t mSalt[SALT_SIZE];
-
-    AES_KEY mMasterKeyEncryption;
-    AES_KEY mMasterKeyDecryption;
-};
-
-#endif  // KEYSTORE_USER_STATE_H_
