diff --git a/keystore/Android.mk b/keystore/Android.mk
index d1f45ca..f2262c1 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -27,7 +27,18 @@
 LOCAL_MULTILIB := 32
 endif
 LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
-LOCAL_SRC_FILES := keystore.cpp keyblob_utils.cpp operation.cpp auth_token_table.cpp
+LOCAL_SRC_FILES := \
+	auth_token_table.cpp \
+	blob.cpp \
+	entropy.cpp \
+	key_store_service.cpp \
+	keyblob_utils.cpp \
+	keystore.cpp \
+	keystore_main.cpp \
+	keystore_utils.cpp \
+	operation.cpp \
+	permissions.cpp \
+	user_state.cpp
 LOCAL_SHARED_LIBRARIES := \
 	libbinder \
 	libcutils \
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index 24aa774..a2f1446 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 SYSTEM_KEYMASTER_AUTH_TOKEN_TABLE_H
-#define SYSTEM_KEYMASTER_AUTH_TOKEN_TABLE_H
+#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
+#define KEYSTORE_AUTH_TOKEN_TABLE_H_
 
 namespace keymaster {
 
@@ -160,4 +160,4 @@
 
 }  // namespace keymaster
 
-#endif  // SYSTEM_KEYMASTER_AUTH_TOKEN_TABLE_H
+#endif  // KEYSTORE_AUTH_TOKEN_TABLE_H_
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
new file mode 100644
index 0000000..8b08f07
--- /dev/null
+++ b/keystore/blob.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <cutils/log.h>
+
+#include "blob.h"
+#include "entropy.h"
+
+#include "keystore_utils.h"
+
+Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
+           BlobType type) {
+    memset(&mBlob, 0, sizeof(mBlob));
+    if (valueLength > VALUE_SIZE) {
+        valueLength = VALUE_SIZE;
+        ALOGW("Provided blob length too large");
+    }
+    if (infoLength + valueLength > VALUE_SIZE) {
+        infoLength = VALUE_SIZE - valueLength;
+        ALOGW("Provided info length too large");
+    }
+    mBlob.length = valueLength;
+    memcpy(mBlob.value, value, valueLength);
+
+    mBlob.info = infoLength;
+    memcpy(mBlob.value + valueLength, info, infoLength);
+
+    mBlob.version = CURRENT_BLOB_VERSION;
+    mBlob.type = uint8_t(type);
+
+    if (type == TYPE_MASTER_KEY) {
+        mBlob.flags = KEYSTORE_FLAG_ENCRYPTED;
+    } else {
+        mBlob.flags = KEYSTORE_FLAG_NONE;
+    }
+}
+
+Blob::Blob(blob b) {
+    mBlob = b;
+}
+
+Blob::Blob() {
+    memset(&mBlob, 0, sizeof(mBlob));
+}
+
+bool Blob::isEncrypted() const {
+    if (mBlob.version < 2) {
+        return true;
+    }
+
+    return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
+}
+
+void Blob::setEncrypted(bool encrypted) {
+    if (encrypted) {
+        mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
+    } else {
+        mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
+    }
+}
+
+void Blob::setFallback(bool fallback) {
+    if (fallback) {
+        mBlob.flags |= KEYSTORE_FLAG_FALLBACK;
+    } else {
+        mBlob.flags &= ~KEYSTORE_FLAG_FALLBACK;
+    }
+}
+
+ResponseCode Blob::writeBlob(const char* filename, AES_KEY* aes_key, State state,
+                             Entropy* entropy) {
+    ALOGV("writing blob %s", filename);
+    if (isEncrypted()) {
+        if (state != STATE_NO_ERROR) {
+            ALOGD("couldn't insert encrypted blob while not unlocked");
+            return LOCKED;
+        }
+
+        if (!entropy->generate_random_data(mBlob.vector, AES_BLOCK_SIZE)) {
+            ALOGW("Could not read random data for: %s", filename);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    // data includes the value and the value's length
+    size_t dataLength = mBlob.length + sizeof(mBlob.length);
+    // pad data to the AES_BLOCK_SIZE
+    size_t digestedLength = ((dataLength + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE);
+    // encrypted data includes the digest value
+    size_t encryptedLength = digestedLength + MD5_DIGEST_LENGTH;
+    // move info after space for padding
+    memmove(&mBlob.encrypted[encryptedLength], &mBlob.value[mBlob.length], mBlob.info);
+    // zero padding area
+    memset(mBlob.value + mBlob.length, 0, digestedLength - dataLength);
+
+    mBlob.length = htonl(mBlob.length);
+
+    if (isEncrypted()) {
+        MD5(mBlob.digested, digestedLength, mBlob.digest);
+
+        uint8_t vector[AES_BLOCK_SIZE];
+        memcpy(vector, mBlob.vector, AES_BLOCK_SIZE);
+        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, vector,
+                        AES_ENCRYPT);
+    }
+
+    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
+    size_t fileLength = encryptedLength + headerLength + mBlob.info;
+
+    const char* tmpFileName = ".tmp";
+    int out =
+        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+    if (out < 0) {
+        ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
+    if (close(out) != 0) {
+        return SYSTEM_ERROR;
+    }
+    if (writtenBytes != fileLength) {
+        ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
+        unlink(tmpFileName);
+        return SYSTEM_ERROR;
+    }
+    if (rename(tmpFileName, filename) == -1) {
+        ALOGW("could not rename blob to %s: %s", filename, strerror(errno));
+        return SYSTEM_ERROR;
+    }
+    return NO_ERROR;
+}
+
+ResponseCode Blob::readBlob(const char* filename, AES_KEY* aes_key, State state) {
+    ALOGV("reading blob %s", filename);
+    int in = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
+    if (in < 0) {
+        return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+    }
+    // fileLength may be less than sizeof(mBlob) since the in
+    // memory version has extra padding to tolerate rounding up to
+    // the AES_BLOCK_SIZE
+    size_t fileLength = readFully(in, (uint8_t*)&mBlob, sizeof(mBlob));
+    if (close(in) != 0) {
+        return SYSTEM_ERROR;
+    }
+
+    if (fileLength == 0) {
+        return VALUE_CORRUPTED;
+    }
+
+    if (isEncrypted() && (state != STATE_NO_ERROR)) {
+        return LOCKED;
+    }
+
+    size_t headerLength = (mBlob.encrypted - (uint8_t*)&mBlob);
+    if (fileLength < headerLength) {
+        return VALUE_CORRUPTED;
+    }
+
+    ssize_t encryptedLength = fileLength - (headerLength + mBlob.info);
+    if (encryptedLength < 0) {
+        return VALUE_CORRUPTED;
+    }
+
+    ssize_t digestedLength;
+    if (isEncrypted()) {
+        if (encryptedLength % AES_BLOCK_SIZE != 0) {
+            return VALUE_CORRUPTED;
+        }
+
+        AES_cbc_encrypt(mBlob.encrypted, mBlob.encrypted, encryptedLength, aes_key, mBlob.vector,
+                        AES_DECRYPT);
+        digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
+        uint8_t computedDigest[MD5_DIGEST_LENGTH];
+        MD5(mBlob.digested, digestedLength, computedDigest);
+        if (memcmp(mBlob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
+            return VALUE_CORRUPTED;
+        }
+    } else {
+        digestedLength = encryptedLength;
+    }
+
+    ssize_t maxValueLength = digestedLength - sizeof(mBlob.length);
+    mBlob.length = ntohl(mBlob.length);
+    if (mBlob.length < 0 || mBlob.length > maxValueLength) {
+        return VALUE_CORRUPTED;
+    }
+    if (mBlob.info != 0) {
+        // move info from after padding to after data
+        memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
+    }
+    return ::NO_ERROR;
+}
diff --git a/keystore/blob.h b/keystore/blob.h
new file mode 100644
index 0000000..8c26b28
--- /dev/null
+++ b/keystore/blob.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_BLOB_H_
+#define KEYSTORE_BLOB_H_
+
+#include <stdint.h>
+
+#include <openssl/aes.h>
+#include <openssl/md5.h>
+
+#include <keystore/keystore.h>
+
+#define VALUE_SIZE      32768
+
+/* Here is the file format. There are two parts in blob.value, the secret and
+ * the description. The secret is stored in ciphertext, and its original size
+ * can be found in blob.length. The description is stored after the secret in
+ * plaintext, and its size is specified in blob.info. The total size of the two
+ * parts must be no more than VALUE_SIZE bytes. The first field is the version,
+ * the second is the blob's type, and the third byte is flags. Fields other
+ * than blob.info, blob.length, and blob.value are modified by encryptBlob()
+ * and decryptBlob(). Thus they should not be accessed from outside. */
+
+/* ** Note to future implementors of encryption: **
+ * Currently this is the construction:
+ *   metadata || Enc(MD5(data) || data)
+ *
+ * This should be the construction used for encrypting if re-implementing:
+ *
+ *   Derive independent keys for encryption and MAC:
+ *     Kenc = AES_encrypt(masterKey, "Encrypt")
+ *     Kmac = AES_encrypt(masterKey, "MAC")
+ *
+ *   Store this:
+ *     metadata || AES_CTR_encrypt(Kenc, rand_IV, data) ||
+ *             HMAC(Kmac, metadata || Enc(data))
+ */
+struct __attribute__((packed)) blob {
+    uint8_t version;
+    uint8_t type;
+    uint8_t flags;
+    uint8_t info;
+    uint8_t vector[AES_BLOCK_SIZE];
+    uint8_t encrypted[0]; // Marks offset to encrypted data.
+    uint8_t digest[MD5_DIGEST_LENGTH];
+    uint8_t digested[0]; // Marks offset to digested data.
+    int32_t length; // in network byte order when encrypted
+    uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+};
+
+static const uint8_t CURRENT_BLOB_VERSION = 2;
+
+typedef enum {
+    TYPE_ANY = 0, // meta type that matches anything
+    TYPE_GENERIC = 1,
+    TYPE_MASTER_KEY = 2,
+    TYPE_KEY_PAIR = 3,
+    TYPE_KEYMASTER_10 = 4,
+} BlobType;
+
+class Entropy;
+
+class Blob {
+  public:
+    Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
+         BlobType type);
+    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
new file mode 100644
index 0000000..1bfe9a1
--- /dev/null
+++ b/keystore/entropy.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore"
+
+#include "entropy.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+
+#include "keystore_utils.h"
+
+Entropy::~Entropy() {
+    if (mRandom >= 0) {
+        close(mRandom);
+    }
+}
+
+bool Entropy::open() {
+    const char* randomDevice = "/dev/urandom";
+    mRandom = TEMP_FAILURE_RETRY(::open(randomDevice, O_RDONLY));
+    if (mRandom < 0) {
+        ALOGE("open: %s: %s", randomDevice, strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+bool Entropy::generate_random_data(uint8_t* data, size_t size) const {
+    return (readFully(mRandom, data, size) == size);
+}
diff --git a/keystore/entropy.h b/keystore/entropy.h
new file mode 100644
index 0000000..0e4d1b2
--- /dev/null
+++ b/keystore/entropy.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_ENTROPY_H_
+#define KEYSTORE_ENTROPY_H_
+
+#include <stdint.h>
+
+class Entropy {
+  public:
+    Entropy() : mRandom(-1) {}
+    ~Entropy();
+
+    bool open();
+    bool generate_random_data(uint8_t* data, size_t size) const;
+
+  private:
+    int mRandom;
+};
+
+#endif  // KEYSTORE_ENTROPY_H_
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
new file mode 100644
index 0000000..9db333b
--- /dev/null
+++ b/keystore/key_store_service.cpp
@@ -0,0 +1,1456 @@
+/*
+ * 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
new file mode 100644
index 0000000..1f0f2cc
--- /dev/null
+++ b/keystore/key_store_service.h
@@ -0,0 +1,230 @@
+/*
+ * 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 77b3039..0d8dc21 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,447 +14,72 @@
  * limitations under the License.
  */
 
-//#define LOG_NDEBUG 0
-#define LOG_TAG "keystore"
+#include "keystore.h"
 
-#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 <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 <utils/String16.h>
 
 #include <keystore/IKeystoreService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
 
-#include <cutils/log.h>
-#include <cutils/sockets.h>
-#include <private/android_filesystem_config.h>
+#include "keystore_utils.h"
+#include "permissions.h"
 
-#include <keystore/keystore.h>
+const char* KeyStore::sOldMasterKey = ".masterkey";
+const char* KeyStore::sMetaDataFile = ".metadata";
 
-#include <selinux/android.h>
+const android::String16 KeyStore::sRSAKeyType("RSA");
+const android::String16 KeyStore::sECKeyType("EC");
 
-#include <sstream>
-
-#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);
-    }
-};
-typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
-
-struct BIO_Delete {
-    void operator()(BIO* p) const {
-        BIO_free(p);
-    }
-};
-typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
-
-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;
-    }
-
-    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;
+KeyStore::KeyStore(Entropy* entropy, keymaster1_device_t* device, keymaster1_device_t* fallback)
+    : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback) {
+    memset(&mMetaData, '\0', sizeof(mMetaData));
 }
 
-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;
+KeyStore::~KeyStore() {
+    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
+        delete *it;
     }
+    mGrants.clear();
 
-    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;
+    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
+         it++) {
+        delete *it;
     }
-
-    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;
-
+    mMasterKeys.clear();
 }
 
-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;
+ResponseCode KeyStore::initialize() {
+    readMetaData();
+    if (upgradeKeystore()) {
+        writeMetaData();
     }
 
-    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
-        return keymaster0_device_initialize(mod, dev);
-    } else {
-        return keymaster1_device_initialize(mod, dev);
-    }
+    return ::NO_ERROR;
 }
 
-// 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::initializeUser(const android::String8& pw, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return userState->initialize(pw, mEntropy);
 }
 
-static void keymaster_device_release(keymaster1_device_t* dev) {
-    dev->common.close(&dev->common);
+ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
+    UserState* userState = getUserState(dstUser);
+    UserState* initState = getUserState(srcUser);
+    return userState->copyMasterKey(initState);
 }
 
-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));
-    uint64_t now = keymaster::java_time(time(NULL));
-    params->push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
+ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return userState->writeMasterKey(pw, mEntropy);
 }
 
-/***************
- * 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;
+ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
+    UserState* userState = getUserState(userId);
+    return userState->readMasterKey(pw, mEntropy);
 }
 
 /* Here is the encoding of keys. This is necessary in order to allow arbitrary
@@ -491,6 +116,198 @@
     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.
@@ -528,2854 +345,412 @@
     *out = '\0';
 }
 
-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;
-    }
-    return size;
-}
+ResponseCode KeyStore::list(const android::String8& prefix,
+                            android::Vector<android::String16>* matches, uid_t userId) {
 
-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;
-}
+    UserState* userState = getUserState(userId);
+    size_t n = prefix.length();
 
-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 mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
-    }
-
-    void setEncrypted(bool encrypted) {
-        if (encrypted) {
-            mBlob.flags |= KEYSTORE_FLAG_ENCRYPTED;
-        } else {
-            mBlob.flags &= ~KEYSTORE_FLAG_ENCRYPTED;
-        }
-    }
-
-    bool isFallback() const {
-        return mBlob.flags & KEYSTORE_FLAG_FALLBACK;
-    }
-
-    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;
-    }
-
-    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;
-        }
-
-        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;
-    }
-
-private:
-    struct blob mBlob;
-};
-
-class UserState {
-public:
-    UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
-        asprintf(&mUserDir, "user_%u", mUserId);
-        asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
-    }
-
-    ~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;
-        }
-    }
-
-    State getState() const {
-        return mState;
-    }
-
-    int8_t getRetry() const {
-        return mRetry;
-    }
-
-    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;
-    }
-
-    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.
-         */
-        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 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 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;
-        }
-    }
-
-    AES_KEY* getEncryptionKey() {
-        return &mMasterKeyEncryption;
-    }
-
-    AES_KEY* getDecryptionKey() {
-        return &mMasterKeyDecryption;
-    }
-
-    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);
-    }
-
-    /*
-     * 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) {
-        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 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 lock(uid_t userId) {
-        UserState* userState = getUserState(userId);
-        userState->zeroizeMasterKeysInMemory();
-        userState->setState(STATE_LOCKED);
-    }
-
-    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;
-        }
-
-        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 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) {
-            ALOGW("can't open directory for user: %s", strerror(errno));
-            return ::SYSTEM_ERROR;
-        }
-
-        struct dirent* file;
-        while ((file = readdir(dir)) != NULL) {
-            // We only care about files.
-            if (file->d_type != DT_REG) {
-                continue;
-            }
-
-            // Skip anything that starts with a "."
-            if (file->d_name[0] == '.') {
-                continue;
-            }
-
-            if (!strncmp(prefix.string(), file->d_name, n)) {
-                const char* p = &file->d_name[n];
-                size_t plen = strlen(p);
-
-                size_t extra = decode_key_length(p, plen);
-                char *match = (char*) malloc(extra + 1);
-                if (match != NULL) {
-                    decode_key(match, p, plen);
-                    matches->push(android::String16(match, extra));
-                    free(match);
-                } else {
-                    ALOGW("could not allocate match of size %zd", extra);
-                }
-            }
-        }
-        closedir(dir);
-        return ::NO_ERROR;
-    }
-
-    void 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, 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 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, &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) {
-        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 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,
-                                  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 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, 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 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 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;
-        }
+    DIR* dir = opendir(userState->getUserDirName());
+    if (!dir) {
+        ALOGW("can't open directory for user: %s", strerror(errno));
         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];
-            }
+    struct dirent* file;
+    while ((file = readdir(dir)) != NULL) {
+        // We only care about files.
+        if (file->d_type != DT_REG) {
+            continue;
         }
-        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];
-            }
+
+        // Skip anything that starts with a "."
+        if (file->d_name[0] == '.') {
+            continue;
         }
-        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));
+        if (!strncmp(prefix.string(), file->d_name, n)) {
+            const char* p = &file->d_name[n];
+            size_t plen = strlen(p);
 
-        // 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 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");
+            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("Error in begin: %d", result.resultCode);
+                ALOGW("could not allocate match of size %zd", extra);
             }
-            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);
+    }
+    closedir(dir);
+    return ::NO_ERROR;
+}
 
-        if (consumed != length) {
-            ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
-            return ::SYSTEM_ERROR;
-        }
+void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
+    const grant_t* existing = getGrant(filename, granteeUid);
+    if (existing == NULL) {
+        grant_t* grant = new grant_t;
+        grant->uid = granteeUid;
+        grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
+        mGrants.add(grant);
+    }
+}
 
-        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);
+bool KeyStore::removeGrant(const char* filename, uid_t granteeUid) {
+    for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
+        grant_t* grant = *it;
+        if (grant->uid == granteeUid &&
+            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
+            mGrants.erase(it);
+            return true;
         }
-        if (out) {
-            outBuffer.write(result.data.get(), result.dataLength);
-        }
+    }
+    return false;
+}
 
-        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;
+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;
     }
 
-    ::KeyStore* mKeyStore;
-    OperationMap mOperationMap;
-    keymaster::AuthTokenTable mAuthTokenTable;
-    KeystoreKeymasterEnforcement enforcement_policy;
-};
+    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);
 
-}; // namespace android
+        /*
+         * 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;
 
-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;
+        if (error) {
+            ALOGE("Keymaster error while importing key pair with fallback: %d", error);
+            return SYSTEM_ERROR;
         }
+    }
+
+    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, TYPE_KEYMASTER_10);
+    free(const_cast<uint8_t*>(blob.key_material));
+
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+    keyBlob.setFallback(isFallback);
+
+    return put(filename, &keyBlob, userId);
+}
+
+bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
+    if (mDevice == NULL) {
+        ALOGW("can't get keymaster device");
+        return false;
+    }
+
+    if (sRSAKeyType == keyType) {
+        return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0;
     } else {
-        ALOGI("SELinux: Keystore SELinux is disabled.\n");
+        return (mDevice->flags & KEYMASTER_SOFTWARE_ONLY) == 0 &&
+               (mDevice->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_0_2);
+    }
+}
+
+ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
+                                     const uid_t uid, const BlobType type) {
+    android::String8 filepath8(getKeyNameForUidWithDir(keyName, uid));
+    uid_t userId = get_user_id(uid);
+
+    ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
+    if (responseCode == NO_ERROR) {
+        return responseCode;
     }
 
-    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;
+    // If this is one of the legacy UID->UID mappings, use it.
+    uid_t euid = get_keystore_euid(uid);
+    if (euid != uid) {
+        filepath8 = getKeyNameForUidWithDir(keyName, euid);
+        responseCode = get(filepath8.string(), keyBlob, type, userId);
+        if (responseCode == NO_ERROR) {
+            return responseCode;
+        }
+    }
+
+    // They might be using a granted key.
+    android::String8 filename8 = getKeyName(keyName);
+    char* end;
+    strtoul(filename8.string(), &end, 10);
+    if (end[0] != '_' || end[1] == 0) {
+        return KEY_NOT_FOUND;
+    }
+    filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
+                                         filename8.string());
+    if (!hasGrant(filepath8.string(), uid)) {
+        return responseCode;
+    }
+
+    // It is a granted key. Try to load it.
+    return get(filepath8.string(), keyBlob, type, userId);
+}
+
+UserState* KeyStore::getUserState(uid_t userId) {
+    for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
+         it++) {
+        UserState* state = *it;
+        if (state->getUserId() == userId) {
+            return state;
+        }
+    }
+
+    UserState* userState = new UserState(userId);
+    if (!userState->initialize()) {
+        /* There's not much we can do if initialization fails. Trying to
+         * unlock the keystore for that user will fail as well, so any
+         * subsequent request for this user will just return SYSTEM_ERROR.
+         */
+        ALOGE("User initialization failed for %u; subsuquent operations will fail", userId);
+    }
+    mMasterKeys.add(userState);
+    return userState;
+}
+
+UserState* KeyStore::getUserStateByUid(uid_t uid) {
+    uid_t userId = get_user_id(uid);
+    return getUserState(userId);
+}
+
+const UserState* KeyStore::getUserState(uid_t userId) const {
+    for (android::Vector<UserState*>::const_iterator it(mMasterKeys.begin());
+         it != mMasterKeys.end(); it++) {
+        UserState* state = *it;
+        if (state->getUserId() == userId) {
+            return state;
+        }
+    }
+
+    return NULL;
+}
+
+const UserState* KeyStore::getUserStateByUid(uid_t uid) const {
+    uid_t userId = get_user_id(uid);
+    return getUserState(userId);
+}
+
+const grant_t* KeyStore::getGrant(const char* filename, uid_t uid) const {
+    for (android::Vector<grant_t*>::const_iterator it(mGrants.begin()); it != mGrants.end(); it++) {
+        grant_t* grant = *it;
+        if (grant->uid == uid &&
+            !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
+            return grant;
+        }
+    }
+    return NULL;
+}
+
+bool KeyStore::upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
+                           const BlobType type, uid_t uid) {
+    bool updated = false;
+    uint8_t version = oldVersion;
+
+    /* From V0 -> V1: All old types were unknown */
+    if (version == 0) {
+        ALOGV("upgrading to version 1 and setting type %d", type);
+
+        blob->setType(type);
+        if (type == TYPE_KEY_PAIR) {
+            importBlobAsKey(blob, filename, uid);
+        }
+        version = 1;
+        updated = true;
+    }
+
+    /* From V1 -> V2: All old keys were encrypted */
+    if (version == 1) {
+        ALOGV("upgrading to version 2");
+
+        blob->setEncrypted(true);
+        version = 2;
+        updated = true;
     }
 
     /*
-     * We're the only thread in existence, so we're just going to process
-     * Binder transaction as a single-threaded program.
+     * If we've updated, set the key blob to the right version
+     * and write it.
      */
-    android::IPCThreadState::self()->joinThreadPool();
+    if (updated) {
+        ALOGV("updated and writing file %s", filename);
+        blob->setVersion(version);
+    }
 
-    keymaster_device_release(dev);
-    return 1;
+    return updated;
+}
+
+struct BIO_Delete {
+    void operator()(BIO* p) const { BIO_free(p); }
+};
+typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
+
+ResponseCode KeyStore::importBlobAsKey(Blob* blob, const char* filename, uid_t uid) {
+    // We won't even write to the blob directly with this BIO, so const_cast is okay.
+    Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
+    if (b.get() == NULL) {
+        ALOGE("Problem instantiating BIO");
+        return SYSTEM_ERROR;
+    }
+
+    Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
+    if (pkey.get() == NULL) {
+        ALOGE("Couldn't read old PEM file");
+        return SYSTEM_ERROR;
+    }
+
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
+    int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
+    if (len < 0) {
+        ALOGE("Couldn't measure PKCS#8 length");
+        return SYSTEM_ERROR;
+    }
+
+    UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
+    uint8_t* tmp = pkcs8key.get();
+    if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
+        ALOGE("Couldn't convert to PKCS#8");
+        return SYSTEM_ERROR;
+    }
+
+    ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
+                                blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
+    if (rc != NO_ERROR) {
+        return rc;
+    }
+
+    return get(filename, blob, TYPE_KEY_PAIR, uid);
+}
+
+void KeyStore::readMetaData() {
+    int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
+    if (in < 0) {
+        return;
+    }
+    size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData));
+    if (fileLength != sizeof(mMetaData)) {
+        ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData));
+    }
+    close(in);
+}
+
+void KeyStore::writeMetaData() {
+    const char* tmpFileName = ".metadata.tmp";
+    int out =
+        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+    if (out < 0) {
+        ALOGE("couldn't write metadata file: %s", strerror(errno));
+        return;
+    }
+    size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData));
+    if (fileLength != sizeof(mMetaData)) {
+        ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
+              sizeof(mMetaData));
+    }
+    close(out);
+    rename(tmpFileName, sMetaDataFile);
+}
+
+bool KeyStore::upgradeKeystore() {
+    bool upgraded = false;
+
+    if (mMetaData.version == 0) {
+        UserState* userState = getUserStateByUid(0);
+
+        // Initialize first so the directory is made.
+        userState->initialize();
+
+        // Migrate the old .masterkey file to user 0.
+        if (access(sOldMasterKey, R_OK) == 0) {
+            if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
+                ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
+                return false;
+            }
+        }
+
+        // Initialize again in case we had a key.
+        userState->initialize();
+
+        // Try to migrate existing keys.
+        DIR* dir = opendir(".");
+        if (!dir) {
+            // Give up now; maybe we can upgrade later.
+            ALOGE("couldn't open keystore's directory; something is wrong");
+            return false;
+        }
+
+        struct dirent* file;
+        while ((file = readdir(dir)) != NULL) {
+            // We only care about files.
+            if (file->d_type != DT_REG) {
+                continue;
+            }
+
+            // Skip anything that starts with a "."
+            if (file->d_name[0] == '.') {
+                continue;
+            }
+
+            // Find the current file's user.
+            char* end;
+            unsigned long thisUid = strtoul(file->d_name, &end, 10);
+            if (end[0] != '_' || end[1] == 0) {
+                continue;
+            }
+            UserState* otherUser = getUserStateByUid(thisUid);
+            if (otherUser->getUserId() != 0) {
+                unlinkat(dirfd(dir), file->d_name, 0);
+            }
+
+            // Rename the file into user directory.
+            DIR* otherdir = opendir(otherUser->getUserDirName());
+            if (otherdir == NULL) {
+                ALOGW("couldn't open user directory for rename");
+                continue;
+            }
+            if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
+                ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
+            }
+            closedir(otherdir);
+        }
+        closedir(dir);
+
+        mMetaData.version = 1;
+        upgraded = true;
+    }
+
+    return upgraded;
 }
diff --git a/keystore/keystore.h b/keystore/keystore.h
new file mode 100644
index 0000000..5ef8842
--- /dev/null
+++ b/keystore/keystore.h
@@ -0,0 +1,155 @@
+/*
+ * 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_main.cpp b/keystore/keystore_main.cpp
new file mode 100644
index 0000000..57b94b2
--- /dev/null
+++ b/keystore/keystore_main.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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
new file mode 100644
index 0000000..bfcb43a
--- /dev/null
+++ b/keystore/keystore_utils.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore"
+
+#include "keystore_utils.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <keymaster/android_keymaster_utils.h>
+
+size_t readFully(int fd, uint8_t* data, size_t size) {
+    size_t remaining = size;
+    while (remaining > 0) {
+        ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, remaining));
+        if (n <= 0) {
+            return size - remaining;
+        }
+        data += n;
+        remaining -= n;
+    }
+    return size;
+}
+
+size_t writeFully(int fd, uint8_t* data, size_t size) {
+    size_t remaining = size;
+    while (remaining > 0) {
+        ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, remaining));
+        if (n < 0) {
+            ALOGW("write failed: %s", strerror(errno));
+            return size - remaining;
+        }
+        data += n;
+        remaining -= n;
+    }
+    return size;
+}
+
+void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params) {
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_ENCRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_DECRYPT));
+    params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+    if (keyType == EVP_PKEY_RSA) {
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PSS));
+        params->push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_OAEP));
+    }
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_MD5));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA1));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_224));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_384));
+    params->push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_512));
+    params->push_back(keymaster_param_bool(KM_TAG_ALL_USERS));
+    params->push_back(keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED));
+    params->push_back(keymaster_param_date(KM_TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX));
+    params->push_back(keymaster_param_date(KM_TAG_ACTIVE_DATETIME, 0));
+    uint64_t now = keymaster::java_time(time(NULL));
+    params->push_back(keymaster_param_date(KM_TAG_CREATION_DATETIME, now));
+}
+
+uid_t get_app_id(uid_t uid) {
+    return uid % AID_USER;
+}
+
+uid_t get_user_id(uid_t uid) {
+    return uid / AID_USER;
+}
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
new file mode 100644
index 0000000..eaa5eb3
--- /dev/null
+++ b/keystore/keystore_utils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_KEYSTORE_UTILS_H_
+#define KEYSTORE_KEYSTORE_UTILS_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include <UniquePtr.h>
+
+size_t readFully(int fd, uint8_t* data, size_t size);
+size_t writeFully(int fd, uint8_t* data, size_t size);
+
+void add_legacy_key_authorizations(int keyType, std::vector<keymaster_key_param_t>* params);
+
+/**
+ * Returns the app ID (in the Android multi-user sense) for the current
+ * UNIX UID.
+ */
+uid_t get_app_id(uid_t uid);
+
+/**
+ * Returns the user ID (in the Android multi-user sense) for the current
+ * UNIX UID.
+ */
+uid_t get_user_id(uid_t uid);
+
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
+#endif  // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp
new file mode 100644
index 0000000..feacd8f
--- /dev/null
+++ b/keystore/permissions.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore"
+
+#include "permissions.h"
+
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include <selinux/android.h>
+
+#include "keystore_utils.h"
+
+/* perm_labels associcated with keystore_key SELinux class verbs. */
+const char* perm_labels[] = {
+    "get_state", "get",      "insert",    "delete",    "exist",    "list",
+    "reset",     "password", "lock",      "unlock",    "is_empty", "sign",
+    "verify",    "grant",    "duplicate", "clear_uid", "add_auth", "user_changed",
+};
+
+struct user_euid {
+    uid_t uid;
+    uid_t euid;
+};
+
+user_euid user_euids[] = {
+    {AID_VPN, AID_SYSTEM}, {AID_WIFI, AID_SYSTEM}, {AID_ROOT, AID_SYSTEM},
+};
+
+struct user_perm {
+    uid_t uid;
+    perm_t perms;
+};
+
+static user_perm user_perms[] = {
+    {AID_SYSTEM, static_cast<perm_t>((uint32_t)(~0))},
+    {AID_VPN, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
+    {AID_WIFI, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
+    {AID_ROOT, static_cast<perm_t>(P_GET)},
+};
+
+static const perm_t DEFAULT_PERMS = static_cast<perm_t>(P_GET_STATE | P_GET | P_INSERT | P_DELETE |
+                                                        P_EXIST | P_LIST | P_SIGN | P_VERIFY);
+
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+};
+
+const char* get_perm_label(perm_t perm) {
+    unsigned int index = ffs(perm);
+    if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) {
+        return perm_labels[index - 1];
+    } else {
+        ALOGE("Keystore: Failed to retrieve permission label.\n");
+        abort();
+    }
+}
+
+static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) {
+    struct audit_data* ad = reinterpret_cast<struct audit_data*>(data);
+    if (!ad) {
+        ALOGE("No keystore audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
+    return 0;
+}
+
+static char* tctx;
+static int ks_is_selinux_enabled;
+
+int configure_selinux() {
+    ks_is_selinux_enabled = is_selinux_enabled();
+    if (ks_is_selinux_enabled) {
+        union selinux_callback cb;
+        cb.func_audit = audit_callback;
+        selinux_set_callback(SELINUX_CB_AUDIT, cb);
+        cb.func_log = selinux_log_callback;
+        selinux_set_callback(SELINUX_CB_LOG, cb);
+        if (getcon(&tctx) != 0) {
+            ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n");
+            return -1;
+        }
+    } else {
+        ALOGI("SELinux: Keystore SELinux is disabled.\n");
+    }
+
+    return 0;
+}
+
+static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
+    if (!ks_is_selinux_enabled) {
+        return true;
+    }
+
+    audit_data ad;
+    char* sctx = NULL;
+    const char* selinux_class = "keystore_key";
+    const char* str_perm = get_perm_label(perm);
+
+    if (!str_perm) {
+        return false;
+    }
+
+    if (getpidcon(spid, &sctx) != 0) {
+        ALOGE("SELinux: Failed to get source pid context.\n");
+        return false;
+    }
+
+    ad.pid = spid;
+    ad.uid = uid;
+
+    bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
+                                        reinterpret_cast<void*>(&ad)) == 0;
+    freecon(sctx);
+    return allowed;
+}
+
+/**
+ * Returns the UID that the callingUid should act as. This is here for
+ * legacy support of the WiFi and VPN systems and should be removed
+ * when WiFi can operate in its own namespace.
+ */
+uid_t get_keystore_euid(uid_t uid) {
+    for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.uid == uid) {
+            return user.euid;
+        }
+    }
+
+    return uid;
+}
+
+bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
+    // All system users are equivalent for multi-user support.
+    if (get_app_id(uid) == AID_SYSTEM) {
+        uid = AID_SYSTEM;
+    }
+
+    for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) {
+        struct user_perm user = user_perms[i];
+        if (user.uid == uid) {
+            return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid);
+        }
+    }
+
+    return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid);
+}
+
+/**
+ * Returns true if the callingUid is allowed to interact in the targetUid's
+ * namespace.
+ */
+bool is_granted_to(uid_t callingUid, uid_t targetUid) {
+    if (callingUid == targetUid) {
+        return true;
+    }
+    for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.euid == callingUid && user.uid == targetUid) {
+            return true;
+        }
+    }
+
+    return false;
+}
diff --git a/keystore/permissions.h b/keystore/permissions.h
new file mode 100644
index 0000000..f5f1831
--- /dev/null
+++ b/keystore/permissions.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_PERMISSIONS_H_
+#define KEYSTORE_PERMISSIONS_H_
+
+#include <unistd.h>
+
+/* Here are the permissions, actions, users, and the main function. */
+enum perm_t {
+    P_GET_STATE = 1 << 0,
+    P_GET = 1 << 1,
+    P_INSERT = 1 << 2,
+    P_DELETE = 1 << 3,
+    P_EXIST = 1 << 4,
+    P_LIST = 1 << 5,
+    P_RESET = 1 << 6,
+    P_PASSWORD = 1 << 7,
+    P_LOCK = 1 << 8,
+    P_UNLOCK = 1 << 9,
+    P_IS_EMPTY = 1 << 10,
+    P_SIGN = 1 << 11,
+    P_VERIFY = 1 << 12,
+    P_GRANT = 1 << 13,
+    P_DUPLICATE = 1 << 14,
+    P_CLEAR_UID = 1 << 15,
+    P_ADD_AUTH = 1 << 16,
+    P_USER_CHANGED = 1 << 17,
+};
+
+const char* get_perm_label(perm_t perm);
+
+/**
+ * Returns the UID that the callingUid should act as. This is here for
+ * legacy support of the WiFi and VPN systems and should be removed
+ * when WiFi can operate in its own namespace.
+ */
+uid_t get_keystore_euid(uid_t uid);
+
+bool has_permission(uid_t uid, perm_t perm, pid_t spid);
+
+/**
+ * Returns true if the callingUid is allowed to interact in the targetUid's
+ * namespace.
+ */
+bool is_granted_to(uid_t callingUid, uid_t targetUid);
+
+int configure_selinux();
+
+#endif  // KEYSTORE_PERMISSIONS_H_
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
new file mode 100644
index 0000000..3da88c2
--- /dev/null
+++ b/keystore/user_state.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore"
+
+#include "user_state.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <openssl/evp.h>
+
+#include <cutils/log.h>
+
+#include "blob.h"
+#include "keystore_utils.h"
+
+UserState::UserState(uid_t userId) : mUserId(userId), mRetry(MAX_RETRY) {
+    asprintf(&mUserDir, "user_%u", mUserId);
+    asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
+}
+
+UserState::~UserState() {
+    free(mUserDir);
+    free(mMasterKeyFile);
+}
+
+bool UserState::initialize() {
+    if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
+        ALOGE("Could not create directory '%s'", mUserDir);
+        return false;
+    }
+
+    if (access(mMasterKeyFile, R_OK) == 0) {
+        setState(STATE_LOCKED);
+    } else {
+        setState(STATE_UNINITIALIZED);
+    }
+
+    return true;
+}
+
+void UserState::setState(State state) {
+    mState = state;
+    if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
+        mRetry = MAX_RETRY;
+    }
+}
+
+void UserState::zeroizeMasterKeysInMemory() {
+    memset(mMasterKey, 0, sizeof(mMasterKey));
+    memset(mSalt, 0, sizeof(mSalt));
+    memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
+    memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
+}
+
+bool UserState::deleteMasterKey() {
+    setState(STATE_UNINITIALIZED);
+    zeroizeMasterKeysInMemory();
+    return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
+}
+
+ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
+    if (!generateMasterKey(entropy)) {
+        return SYSTEM_ERROR;
+    }
+    ResponseCode response = writeMasterKey(pw, entropy);
+    if (response != NO_ERROR) {
+        return response;
+    }
+    setupMasterKeys();
+    return ::NO_ERROR;
+}
+
+ResponseCode UserState::copyMasterKey(UserState* src) {
+    if (mState != STATE_UNINITIALIZED) {
+        return ::SYSTEM_ERROR;
+    }
+    if (src->getState() != STATE_NO_ERROR) {
+        return ::SYSTEM_ERROR;
+    }
+    memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
+    setupMasterKeys();
+    return copyMasterKeyFile(src);
+}
+
+ResponseCode UserState::copyMasterKeyFile(UserState* src) {
+    /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
+     * password so we cannot generate a new file with a new salt.
+     */
+    int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
+    if (in < 0) {
+        return ::SYSTEM_ERROR;
+    }
+    blob rawBlob;
+    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
+    if (close(in) != 0) {
+        return ::SYSTEM_ERROR;
+    }
+    int out =
+        TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
+    if (out < 0) {
+        return ::SYSTEM_ERROR;
+    }
+    size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
+    if (close(out) != 0) {
+        return ::SYSTEM_ERROR;
+    }
+    if (outLength != length) {
+        ALOGW("blob not fully written %zu != %zu", outLength, length);
+        unlink(mMasterKeyFile);
+        return ::SYSTEM_ERROR;
+    }
+    return ::NO_ERROR;
+}
+
+ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
+    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
+    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
+    AES_KEY passwordAesKey;
+    AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
+    Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
+    return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
+}
+
+ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
+    int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
+    if (in < 0) {
+        return SYSTEM_ERROR;
+    }
+
+    // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
+    // to use with decryptBlob
+    blob rawBlob;
+    size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
+    if (close(in) != 0) {
+        return SYSTEM_ERROR;
+    }
+    // find salt at EOF if present, otherwise we have an old file
+    uint8_t* salt;
+    if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
+        salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
+    } else {
+        salt = NULL;
+    }
+    uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
+    generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
+    AES_KEY passwordAesKey;
+    AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
+    Blob masterKeyBlob(rawBlob);
+    ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
+    if (response == SYSTEM_ERROR) {
+        return response;
+    }
+    if (response == NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
+        // If salt was missing, generate one and write a new master key file with the salt.
+        if (salt == NULL) {
+            if (!generateSalt(entropy)) {
+                return SYSTEM_ERROR;
+            }
+            response = writeMasterKey(pw, entropy);
+        }
+        if (response == NO_ERROR) {
+            memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
+            setupMasterKeys();
+        }
+        return response;
+    }
+    if (mRetry <= 0) {
+        reset();
+        return UNINITIALIZED;
+    }
+    --mRetry;
+    switch (mRetry) {
+    case 0:
+        return WRONG_PASSWORD_0;
+    case 1:
+        return WRONG_PASSWORD_1;
+    case 2:
+        return WRONG_PASSWORD_2;
+    case 3:
+        return WRONG_PASSWORD_3;
+    default:
+        return WRONG_PASSWORD_3;
+    }
+}
+
+bool UserState::reset() {
+    DIR* dir = opendir(getUserDirName());
+    if (!dir) {
+        // If the directory doesn't exist then nothing to do.
+        if (errno == ENOENT) {
+            return true;
+        }
+        ALOGW("couldn't open user directory: %s", strerror(errno));
+        return false;
+    }
+
+    struct dirent* file;
+    while ((file = readdir(dir)) != NULL) {
+        // skip . and ..
+        if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
+            continue;
+        }
+
+        unlinkat(dirfd(dir), file->d_name, 0);
+    }
+    closedir(dir);
+    return true;
+}
+
+void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+                                        uint8_t* salt) {
+    size_t saltSize;
+    if (salt != NULL) {
+        saltSize = SALT_SIZE;
+    } else {
+        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
+        salt = (uint8_t*)"keystore";
+        // sizeof = 9, not strlen = 8
+        saltSize = sizeof("keystore");
+    }
+
+    PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
+                           8192, keySize, key);
+}
+
+bool UserState::generateSalt(Entropy* entropy) {
+    return entropy->generate_random_data(mSalt, sizeof(mSalt));
+}
+
+bool UserState::generateMasterKey(Entropy* entropy) {
+    if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
+        return false;
+    }
+    if (!generateSalt(entropy)) {
+        return false;
+    }
+    return true;
+}
+
+void UserState::setupMasterKeys() {
+    AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
+    AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
+    setState(STATE_NO_ERROR);
+}
diff --git a/keystore/user_state.h b/keystore/user_state.h
new file mode 100644
index 0000000..2a52f81
--- /dev/null
+++ b/keystore/user_state.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_USER_STATE_H_
+#define KEYSTORE_USER_STATE_H_
+
+#include <sys/types.h>
+
+#include <openssl/aes.h>
+
+#include <utils/String8.h>
+
+#include <keystore/keystore.h>
+
+#include "entropy.h"
+
+class UserState {
+  public:
+    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_
