diff --git a/keystore/Android.mk b/keystore/Android.mk
index d1f45ca..04ca220 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 \
@@ -63,7 +74,7 @@
 ifeq ($(USE_32_BIT_KEYSTORE), true)
 LOCAL_MULTILIB := 32
 endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter -DKEYMASTER_NAME_TAGS
 LOCAL_SRC_FILES := keystore_cli_v2.cpp
 LOCAL_SHARED_LIBRARIES := \
 	libchrome \
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 8ed09c4..466ac24 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -208,6 +208,69 @@
     }
 }
 
+KeymasterCertificateChain::KeymasterCertificateChain() {
+    memset(&chain, 0, sizeof(chain));
+}
+
+KeymasterCertificateChain::~KeymasterCertificateChain() {
+    keymaster_free_cert_chain(&chain);
+}
+
+static bool readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
+    if (in.readInt32() != 1) {
+        return false;
+    }
+
+    blob->data_length = 0;
+    ssize_t length = in.readInt32();
+    if (length <= 0) {
+        blob->data = nullptr;
+        return false;
+    }
+
+    blob->data = reinterpret_cast<const uint8_t*>(in.readInplace(length));
+    if (blob->data) {
+        blob->data_length = static_cast<size_t>(length);
+    }
+    return true;
+}
+
+void KeymasterCertificateChain::readFromParcel(const Parcel& in) {
+    ssize_t count = in.readInt32();
+    size_t ucount = count;
+    if (count < 0) {
+        ucount = 0;
+    }
+    keymaster_free_cert_chain(&chain);
+    chain.entries = new keymaster_blob_t[ucount];
+    memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount);
+    for (size_t i = 0; i < ucount; ++i) {
+        if (!readKeymasterBlob(in, &chain.entries[i])) {
+            keymaster_free_cert_chain(&chain);
+            return;
+        }
+    }
+}
+
+void KeymasterCertificateChain::writeToParcel(Parcel* out) const {
+    out->writeInt32(chain.entry_count);
+    for (size_t i = 0; i < chain.entry_count; ++i) {
+        if (chain.entries[i].data) {
+            out->writeInt32(1); // Tell Java side that object is not NULL
+            out->writeInt32(chain.entries[i].data_length);
+            void* buf = out->writeInplace(chain.entries[i].data_length);
+            if (buf) {
+                memcpy(buf, chain.entries[i].data, chain.entries[i].data_length);
+            } else {
+                ALOGE("Failed to writeInplace keymaster cert chain entry");
+            }
+        } else {
+            out->writeInt32(0); // Tell Java side this object is NULL.
+            ALOGE("Found NULL certificate chain entry");
+        }
+    }
+}
+
 void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out) {
     switch (keymaster_tag_get_type(param.tag)) {
         case KM_ENUM:
@@ -369,23 +432,9 @@
 }
 
 static std::unique_ptr<keymaster_blob_t> readKeymasterBlob(const Parcel& in) {
-    std::unique_ptr<keymaster_blob_t> blob;
-    if (in.readInt32() != 1) {
-        blob.reset(NULL);
-        return blob;
-    }
-    ssize_t length = in.readInt32();
-    blob.reset(new keymaster_blob_t);
-    if (length > 0) {
-        blob->data = reinterpret_cast<const uint8_t*>(in.readInplace(length));
-        if (blob->data) {
-            blob->data_length = static_cast<size_t>(length);
-        } else {
-            blob->data_length = 0;
-        }
-    } else {
-        blob->data = NULL;
-        blob->data_length = 0;
+    std::unique_ptr<keymaster_blob_t> blob (new keymaster_blob_t);
+    if (!readKeymasterBlob(in, blob.get())) {
+        blob.reset();
     }
     return blob;
 }
@@ -1257,6 +1306,34 @@
         return ret;
     }
 
+    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
+                              KeymasterCertificateChain* outChain) {
+        if (!outChain)
+            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+        Parcel data, reply;
+        data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+        data.writeString16(name);
+        data.writeInt32(1);  // params is not NULL.
+        params.writeToParcel(&data);
+
+        status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply);
+        if (status != NO_ERROR) {
+            ALOGD("attestkey() count not contact remote: %d\n", status);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        int32_t err = reply.readExceptionCode();
+        int32_t ret = reply.readInt32();
+        if (err < 0) {
+            ALOGD("attestKey() caught exception %d\n", err);
+            return KM_ERROR_UNKNOWN_ERROR;
+        }
+        if (reply.readInt32() != 0) {
+            outChain->readFromParcel(reply);
+        }
+        return ret;
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
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/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index c136dfd..1c2f6a5 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -90,6 +90,16 @@
     keymaster_key_characteristics_t characteristics;
 };
 
+// struct for serializing keymaster_cert_chain_t's
+struct KeymasterCertificateChain {
+    KeymasterCertificateChain();
+    ~KeymasterCertificateChain();
+    void readFromParcel(const Parcel& in);
+    void writeToParcel(Parcel* out) const;
+
+    keymaster_cert_chain_t chain;
+};
+
 bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out);
 void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out);
 
@@ -134,6 +144,7 @@
         ADD_AUTH_TOKEN = IBinder::FIRST_CALL_TRANSACTION + 32,
         ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33,
         ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34,
+        ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35,
     };
 
     DECLARE_META_INTERFACE(KeystoreService);
@@ -231,6 +242,9 @@
 
     virtual int32_t onUserRemoved(int32_t userId) = 0;
 
+    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
+                              KeymasterCertificateChain* outChain) = 0;
+
 };
 
 // ----------------------------------------------------------------------------
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
new file mode 100644
index 0000000..759ef06
--- /dev/null
+++ b/keystore/key_store_service.cpp
@@ -0,0 +1,1488 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "key_store_service.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <sstream>
+
+#include <binder/IPCThreadState.h>
+
+#include <private/android_filesystem_config.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include "defaults.h"
+#include "keystore_utils.h"
+
+namespace android {
+
+const size_t MAX_OPERATIONS = 15;
+
+struct BIGNUM_Delete {
+    void operator()(BIGNUM* p) const { BN_free(p); }
+};
+typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
+
+void KeyStoreService::binderDied(const wp<IBinder>& who) {
+    auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
+    for (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 auto* device = mKeyStore->getDevice();
+    const auto* fallback = mKeyStore->getFallbackDevice();
+    int32_t devResult = KM_ERROR_UNIMPLEMENTED;
+    int32_t fallbackResult = KM_ERROR_UNIMPLEMENTED;
+    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+        device->add_rng_entropy != NULL) {
+        devResult = device->add_rng_entropy(device, data, dataLength);
+    }
+    if (fallback->add_rng_entropy) {
+        fallbackResult = fallback->add_rng_entropy(fallback, data, dataLength);
+    }
+    if (devResult) {
+        return devResult;
+    }
+    if (fallbackResult) {
+        return fallbackResult;
+    }
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
+                                     const uint8_t* entropy, size_t entropyLength, int uid,
+                                     int flags, KeyCharacteristics* outCharacteristics) {
+    uid = getEffectiveUid(uid);
+    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    rc = KM_ERROR_UNIMPLEMENTED;
+    bool isFallback = false;
+    keymaster_key_blob_t blob;
+    keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+
+    const auto* device = mKeyStore->getDevice();
+    const auto* fallback = mKeyStore->getFallbackDevice();
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    if (device == NULL) {
+        return ::SYSTEM_ERROR;
+    }
+    // TODO: Seed from Linux RNG before this.
+    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+        device->generate_key != NULL) {
+        if (!entropy) {
+            rc = KM_ERROR_OK;
+        } else if (device->add_rng_entropy) {
+            rc = device->add_rng_entropy(device, entropy, entropyLength);
+        } else {
+            rc = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (rc == KM_ERROR_OK) {
+            rc =
+                device->generate_key(device, &inParams, &blob, outCharacteristics ? &out : nullptr);
+        }
+    }
+    // If the HW device didn't support generate_key or generate_key failed
+    // fall back to the software implementation.
+    if (rc && fallback->generate_key != NULL) {
+        ALOGW("Primary keymaster device failed to generate key, falling back to SW.");
+        isFallback = true;
+        if (!entropy) {
+            rc = KM_ERROR_OK;
+        } else if (fallback->add_rng_entropy) {
+            rc = fallback->add_rng_entropy(fallback, entropy, entropyLength);
+        } else {
+            rc = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (rc == KM_ERROR_OK) {
+            rc = fallback->generate_key(fallback, &inParams, &blob,
+                                        outCharacteristics ? &out : nullptr);
+        }
+    }
+
+    if (outCharacteristics) {
+        outCharacteristics->characteristics = out;
+    }
+
+    if (rc) {
+        return rc;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+    keyBlob.setFallback(isFallback);
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+    free(const_cast<uint8_t*>(blob.key_material));
+
+    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+}
+
+int32_t KeyStoreService::getKeyCharacteristics(const String16& name,
+                                               const keymaster_blob_t* clientId,
+                                               const keymaster_blob_t* appData,
+                                               KeyCharacteristics* outCharacteristics) {
+    if (!outCharacteristics) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    Blob keyBlob;
+    String8 name8(name);
+    int rc;
+
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        return responseCode;
+    }
+    keymaster_key_blob_t key;
+    key.key_material_size = keyBlob.getLength();
+    key.key_material = keyBlob.getValue();
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+    if (!dev->get_key_characteristics) {
+        ALOGE("device does not implement get_key_characteristics");
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+    rc = dev->get_key_characteristics(dev, &key, clientId, appData, &out);
+    if (rc != KM_ERROR_OK) {
+        return rc;
+    }
+
+    outCharacteristics->characteristics = out;
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::importKey(const String16& name, const KeymasterArguments& params,
+                                   keymaster_key_format_t format, const uint8_t* keyData,
+                                   size_t keyLength, int uid, int flags,
+                                   KeyCharacteristics* outCharacteristics) {
+    uid = getEffectiveUid(uid);
+    int rc = checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    rc = KM_ERROR_UNIMPLEMENTED;
+    bool isFallback = false;
+    keymaster_key_blob_t blob;
+    keymaster_key_characteristics_t out = {{nullptr, 0}, {nullptr, 0}};
+
+    const auto* device = mKeyStore->getDevice();
+    const auto* fallback = mKeyStore->getFallbackDevice();
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    const keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    const keymaster_blob_t input = {keyData, keyLength};
+    if (device == NULL) {
+        return ::SYSTEM_ERROR;
+    }
+    if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
+        device->import_key != NULL) {
+        rc = device->import_key(device, &inParams, format, &input, &blob,
+                                outCharacteristics ? &out : nullptr);
+    }
+    if (rc && fallback->import_key != NULL) {
+        ALOGW("Primary keymaster device failed to import key, falling back to SW.");
+        isFallback = true;
+        rc = fallback->import_key(fallback, &inParams, format, &input, &blob,
+                                  outCharacteristics ? &out : nullptr);
+    }
+    if (outCharacteristics) {
+        outCharacteristics->characteristics = out;
+    }
+
+    if (rc) {
+        return rc;
+    }
+
+    String8 name8(name);
+    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid));
+
+    Blob keyBlob(blob.key_material, blob.key_material_size, NULL, 0, ::TYPE_KEYMASTER_10);
+    keyBlob.setFallback(isFallback);
+    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
+
+    free(const_cast<uint8_t*>(blob.key_material));
+
+    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
+}
+
+void KeyStoreService::exportKey(const String16& name, keymaster_key_format_t format,
+                                const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
+                                ExportResult* result) {
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    Blob keyBlob;
+    String8 name8(name);
+    int rc;
+
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        result->resultCode = responseCode;
+        return;
+    }
+    keymaster_key_blob_t key;
+    key.key_material_size = keyBlob.getLength();
+    key.key_material = keyBlob.getValue();
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    if (!dev->export_key) {
+        result->resultCode = KM_ERROR_UNIMPLEMENTED;
+        return;
+    }
+    keymaster_blob_t output = {NULL, 0};
+    rc = dev->export_key(dev, format, &key, clientId, appData, &output);
+    result->exportData.reset(const_cast<uint8_t*>(output.data));
+    result->dataLength = output.data_length;
+    result->resultCode = rc ? rc : ::NO_ERROR;
+}
+
+void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name,
+                            keymaster_purpose_t purpose, bool pruneable,
+                            const KeymasterArguments& params, const uint8_t* entropy,
+                            size_t entropyLength, OperationResult* result) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
+        ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
+        result->resultCode = ::PERMISSION_DENIED;
+        return;
+    }
+    if (!checkAllowedOperationParams(params.params)) {
+        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+        return;
+    }
+    Blob keyBlob;
+    String8 name8(name);
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        result->resultCode = responseCode;
+        return;
+    }
+    keymaster_key_blob_t key;
+    key.key_material_size = keyBlob.getLength();
+    key.key_material = keyBlob.getValue();
+    keymaster_operation_handle_t handle;
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    Unique_keymaster_key_characteristics characteristics;
+    characteristics.reset(new keymaster_key_characteristics_t);
+    err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+    const hw_auth_token_t* authToken = NULL;
+    int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
+                                      /*failOnTokenMissing*/ false);
+    // If per-operation auth is needed we need to begin the operation and
+    // the client will need to authorize that operation before calling
+    // update. Any other auth issues stop here.
+    if (authResult != ::NO_ERROR && authResult != ::OP_AUTH_NEEDED) {
+        result->resultCode = authResult;
+        return;
+    }
+    addAuthToParams(&opParams, authToken);
+    // Add entropy to the device first.
+    if (entropy) {
+        if (dev->add_rng_entropy) {
+            err = dev->add_rng_entropy(dev, entropy, entropyLength);
+        } else {
+            err = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+    }
+    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+
+    // Create a keyid for this key.
+    keymaster::km_id_t keyid;
+    if (!enforcement_policy.CreateKeyId(key, &keyid)) {
+        ALOGE("Failed to create a key ID for authorization checking.");
+        result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+        return;
+    }
+
+    // Check that all key authorization policy requirements are met.
+    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+    key_auths.push_back(characteristics->sw_enforced);
+    keymaster::AuthorizationSet operation_params(inParams);
+    err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+                                                0 /* op_handle */, true /* is_begin_operation */);
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+
+    keymaster_key_param_set_t outParams = {NULL, 0};
+
+    // If there are more than MAX_OPERATIONS, abort the oldest operation that was started as
+    // pruneable.
+    while (mOperationMap.getOperationCount() >= MAX_OPERATIONS) {
+        ALOGD("Reached or exceeded concurrent operations limit");
+        if (!pruneOperation()) {
+            break;
+        }
+    }
+
+    err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+    if (err != KM_ERROR_OK) {
+        ALOGE("Got error %d from begin()", err);
+    }
+
+    // If there are too many operations abort the oldest operation that was
+    // started as pruneable and try again.
+    while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
+        ALOGE("Ran out of operation handles");
+        if (!pruneOperation()) {
+            break;
+        }
+        err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
+    }
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+
+    sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev, appToken,
+                                                            characteristics.release(), pruneable);
+    if (authToken) {
+        mOperationMap.setOperationAuthToken(operationToken, authToken);
+    }
+    // Return the authentication lookup result. If this is a per operation
+    // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
+    // application should get an auth token using the handle before the
+    // first call to update, which will fail if keystore hasn't received the
+    // auth token.
+    result->resultCode = authResult;
+    result->token = operationToken;
+    result->handle = handle;
+    if (outParams.params) {
+        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+        free(outParams.params);
+    }
+}
+
+void KeyStoreService::update(const sp<IBinder>& token, const KeymasterArguments& params,
+                             const uint8_t* data, size_t dataLength, OperationResult* result) {
+    if (!checkAllowedOperationParams(params.params)) {
+        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+        return;
+    }
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    const keymaster_key_characteristics_t* characteristics;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+        return;
+    }
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
+    if (authResult != ::NO_ERROR) {
+        result->resultCode = authResult;
+        return;
+    }
+    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    keymaster_blob_t input = {data, dataLength};
+    size_t consumed = 0;
+    keymaster_blob_t output = {NULL, 0};
+    keymaster_key_param_set_t outParams = {NULL, 0};
+
+    // Check that all key authorization policy requirements are met.
+    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+    key_auths.push_back(characteristics->sw_enforced);
+    keymaster::AuthorizationSet operation_params(inParams);
+    result->resultCode = enforcement_policy.AuthorizeOperation(
+        purpose, keyid, key_auths, operation_params, handle, false /* is_begin_operation */);
+    if (result->resultCode) {
+        return;
+    }
+
+    keymaster_error_t err =
+        dev->update(dev, handle, &inParams, &input, &consumed, &outParams, &output);
+    result->data.reset(const_cast<uint8_t*>(output.data));
+    result->dataLength = output.data_length;
+    result->inputConsumed = consumed;
+    result->resultCode = err ? (int32_t)err : ::NO_ERROR;
+    if (outParams.params) {
+        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+        free(outParams.params);
+    }
+}
+
+void KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                             const uint8_t* signature, size_t signatureLength,
+                             const uint8_t* entropy, size_t entropyLength,
+                             OperationResult* result) {
+    if (!checkAllowedOperationParams(params.params)) {
+        result->resultCode = KM_ERROR_INVALID_ARGUMENT;
+        return;
+    }
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    const keymaster_key_characteristics_t* characteristics;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+        result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
+        return;
+    }
+    std::vector<keymaster_key_param_t> opParams(params.params);
+    int32_t authResult = addOperationAuthTokenIfNeeded(token, &opParams);
+    if (authResult != ::NO_ERROR) {
+        result->resultCode = authResult;
+        return;
+    }
+    keymaster_error_t err;
+    if (entropy) {
+        if (dev->add_rng_entropy) {
+            err = dev->add_rng_entropy(dev, entropy, entropyLength);
+        } else {
+            err = KM_ERROR_UNIMPLEMENTED;
+        }
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+    }
+
+    keymaster_key_param_set_t inParams = {opParams.data(), opParams.size()};
+    keymaster_blob_t input = {nullptr, 0};
+    keymaster_blob_t sig = {signature, signatureLength};
+    keymaster_blob_t output = {nullptr, 0};
+    keymaster_key_param_set_t outParams = {nullptr, 0};
+
+    // Check that all key authorization policy requirements are met.
+    keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+    key_auths.push_back(characteristics->sw_enforced);
+    keymaster::AuthorizationSet operation_params(inParams);
+    err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params, handle,
+                                                false /* is_begin_operation */);
+    if (err) {
+        result->resultCode = err;
+        return;
+    }
+
+    err =
+        dev->finish(dev, handle, &inParams, &input /* TODO(swillden): wire up input to finish() */,
+                    &sig, &outParams, &output);
+    // Remove the operation regardless of the result
+    mOperationMap.removeOperation(token);
+    mAuthTokenTable.MarkCompleted(handle);
+
+    result->data.reset(const_cast<uint8_t*>(output.data));
+    result->dataLength = output.data_length;
+    result->resultCode = err ? (int32_t)err : ::NO_ERROR;
+    if (outParams.params) {
+        result->outParams.params.assign(outParams.params, outParams.params + outParams.length);
+        free(outParams.params);
+    }
+}
+
+int32_t KeyStoreService::abort(const sp<IBinder>& token) {
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
+        return KM_ERROR_INVALID_OPERATION_HANDLE;
+    }
+    mOperationMap.removeOperation(token);
+    int32_t rc;
+    if (!dev->abort) {
+        rc = KM_ERROR_UNIMPLEMENTED;
+    } else {
+        rc = dev->abort(dev, handle);
+    }
+    mAuthTokenTable.MarkCompleted(handle);
+    if (rc) {
+        return rc;
+    }
+    return ::NO_ERROR;
+}
+
+bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
+    const keymaster2_device_t* dev;
+    keymaster_operation_handle_t handle;
+    const keymaster_key_characteristics_t* characteristics;
+    keymaster_purpose_t purpose;
+    keymaster::km_id_t keyid;
+    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+        return false;
+    }
+    const hw_auth_token_t* authToken = NULL;
+    mOperationMap.getOperationAuthToken(token, &authToken);
+    std::vector<keymaster_key_param_t> ignored;
+    int32_t authResult = addOperationAuthTokenIfNeeded(token, &ignored);
+    return authResult == ::NO_ERROR;
+}
+
+int32_t KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+    if (!checkBinderPermission(P_ADD_AUTH)) {
+        ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
+        return ::PERMISSION_DENIED;
+    }
+    if (length != sizeof(hw_auth_token_t)) {
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+    hw_auth_token_t* authToken = new hw_auth_token_t;
+    memcpy(reinterpret_cast<void*>(authToken), token, sizeof(hw_auth_token_t));
+    // The table takes ownership of authToken.
+    mAuthTokenTable.AddAuthenticationToken(authToken);
+    return ::NO_ERROR;
+}
+
+int32_t KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
+                                   KeymasterCertificateChain* outChain) {
+    if (!outChain)
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+
+    if (!checkAllowedOperationParams(params.params)) {
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+    Blob keyBlob;
+    String8 name8(name);
+    ResponseCode responseCode =
+        mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
+    if (responseCode != ::NO_ERROR) {
+        return responseCode;
+    }
+
+    keymaster_key_blob_t key = {keyBlob.getValue(),
+                                static_cast<size_t>(std::max(0, keyBlob.getLength()))};
+    auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
+    if (!dev->attest_key)
+        return KM_ERROR_UNIMPLEMENTED;
+
+    const keymaster_key_param_set_t in_params = {
+        const_cast<keymaster_key_param_t*>(params.params.data()), params.params.size()};
+    outChain->chain = {nullptr, 0};
+    int32_t rc = dev->attest_key(dev, &key, &in_params, &outChain->chain);
+    if (rc)
+        return rc;
+    return ::NO_ERROR;
+}
+
+/**
+ * Prune the oldest pruneable operation.
+ */
+bool KeyStoreService::pruneOperation() {
+    sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation();
+    ALOGD("Trying to prune operation %p", oldest.get());
+    size_t op_count_before_abort = mOperationMap.getOperationCount();
+    // We mostly ignore errors from abort() because all we care about is whether at least
+    // one operation has been removed.
+    int abort_error = abort(oldest);
+    if (mOperationMap.getOperationCount() >= op_count_before_abort) {
+        ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Get the effective target uid for a binder operation that takes an
+ * optional uid as the target.
+ */
+uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
+    if (targetUid == UID_SELF) {
+        return IPCThreadState::self()->getCallingUid();
+    }
+    return static_cast<uid_t>(targetUid);
+}
+
+/**
+ * Check if the caller of the current binder method has the required
+ * permission and if acting on other uids the grants to do so.
+ */
+bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    pid_t spid = IPCThreadState::self()->getCallingPid();
+    if (!has_permission(callingUid, permission, spid)) {
+        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
+        return false;
+    }
+    if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
+        ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Check if the caller of the current binder method has the required
+ * permission and the target uid is the caller or the caller is system.
+ */
+bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    pid_t spid = IPCThreadState::self()->getCallingPid();
+    if (!has_permission(callingUid, permission, spid)) {
+        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
+        return false;
+    }
+    return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
+}
+
+/**
+ * Check if the caller of the current binder method has the required
+ * permission or the target of the operation is the caller's uid. This is
+ * for operation where the permission is only for cross-uid activity and all
+ * uids are allowed to act on their own (ie: clearing all entries for a
+ * given uid).
+ */
+bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    if (getEffectiveUid(targetUid) == callingUid) {
+        return true;
+    } else {
+        return checkBinderPermission(permission, targetUid);
+    }
+}
+
+/**
+ * Helper method to check that the caller has the required permission as
+ * well as the keystore is in the unlocked state if checkUnlocked is true.
+ *
+ * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
+ * otherwise the state of keystore when not unlocked and checkUnlocked is
+ * true.
+ */
+int32_t KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
+                                                               bool checkUnlocked) {
+    if (!checkBinderPermission(permission, targetUid)) {
+        return ::PERMISSION_DENIED;
+    }
+    State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
+    if (checkUnlocked && !isKeystoreUnlocked(state)) {
+        return state;
+    }
+
+    return ::NO_ERROR;
+}
+
+inline bool KeyStoreService::isKeystoreUnlocked(State state) {
+    switch (state) {
+    case ::STATE_NO_ERROR:
+        return true;
+    case ::STATE_UNINITIALIZED:
+    case ::STATE_LOCKED:
+        return false;
+    }
+    return false;
+}
+
+bool KeyStoreService::isKeyTypeSupported(const keymaster2_device_t* device,
+                                         keymaster_keypair_t keyType) {
+    const int32_t device_api = device->common.module->module_api_version;
+    if (device_api == KEYMASTER_MODULE_API_VERSION_0_2) {
+        switch (keyType) {
+        case TYPE_RSA:
+        case TYPE_DSA:
+        case TYPE_EC:
+            return true;
+        default:
+            return false;
+        }
+    } else if (device_api >= KEYMASTER_MODULE_API_VERSION_0_3) {
+        switch (keyType) {
+        case TYPE_RSA:
+            return true;
+        case TYPE_DSA:
+            return device->flags & KEYMASTER_SUPPORTS_DSA;
+        case TYPE_EC:
+            return device->flags & KEYMASTER_SUPPORTS_EC;
+        default:
+            return false;
+        }
+    } else {
+        return keyType == TYPE_RSA;
+    }
+}
+
+/**
+ * Check that all keymaster_key_param_t's provided by the application are
+ * allowed. Any parameter that keystore adds itself should be disallowed here.
+ */
+bool KeyStoreService::checkAllowedOperationParams(
+    const std::vector<keymaster_key_param_t>& params) {
+    for (auto param : params) {
+        switch (param.tag) {
+        case KM_TAG_AUTH_TOKEN:
+            return false;
+        default:
+            break;
+        }
+    }
+    return true;
+}
+
+keymaster_error_t KeyStoreService::getOperationCharacteristics(
+    const keymaster_key_blob_t& key, const keymaster2_device_t* dev,
+    const std::vector<keymaster_key_param_t>& params, keymaster_key_characteristics_t* out) {
+    UniquePtr<keymaster_blob_t> appId;
+    UniquePtr<keymaster_blob_t> appData;
+    for (auto param : params) {
+        if (param.tag == KM_TAG_APPLICATION_ID) {
+            appId.reset(new keymaster_blob_t);
+            appId->data = param.blob.data;
+            appId->data_length = param.blob.data_length;
+        } else if (param.tag == KM_TAG_APPLICATION_DATA) {
+            appData.reset(new keymaster_blob_t);
+            appData->data = param.blob.data;
+            appData->data_length = param.blob.data_length;
+        }
+    }
+    keymaster_key_characteristics_t result = {{nullptr, 0}, {nullptr, 0}};
+    if (!dev->get_key_characteristics) {
+        return KM_ERROR_UNIMPLEMENTED;
+    }
+    keymaster_error_t error =
+        dev->get_key_characteristics(dev, &key, appId.get(), appData.get(), &result);
+    if (error == KM_ERROR_OK) {
+        *out = result;
+    }
+    return error;
+}
+
+/**
+ * Get the auth token for this operation from the auth token table.
+ *
+ * Returns ::NO_ERROR if the auth token was set or none was required.
+ *         ::OP_AUTH_NEEDED if it is a per op authorization, no
+ *         authorization token exists for that operation and
+ *         failOnTokenMissing is false.
+ *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
+ *         token for the operation
+ */
+int32_t KeyStoreService::getAuthToken(const keymaster_key_characteristics_t* characteristics,
+                                      keymaster_operation_handle_t handle,
+                                      keymaster_purpose_t purpose,
+                                      const hw_auth_token_t** authToken, bool failOnTokenMissing) {
+
+    std::vector<keymaster_key_param_t> allCharacteristics;
+    for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
+        allCharacteristics.push_back(characteristics->sw_enforced.params[i]);
+    }
+    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
+        allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
+    }
+    keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
+        allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
+    switch (err) {
+    case keymaster::AuthTokenTable::OK:
+    case keymaster::AuthTokenTable::AUTH_NOT_REQUIRED:
+        return ::NO_ERROR;
+    case keymaster::AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
+    case keymaster::AuthTokenTable::AUTH_TOKEN_EXPIRED:
+    case keymaster::AuthTokenTable::AUTH_TOKEN_WRONG_SID:
+        return KM_ERROR_KEY_USER_NOT_AUTHENTICATED;
+    case keymaster::AuthTokenTable::OP_HANDLE_REQUIRED:
+        return failOnTokenMissing ? (int32_t)KM_ERROR_KEY_USER_NOT_AUTHENTICATED
+                                  : (int32_t)::OP_AUTH_NEEDED;
+    default:
+        ALOGE("Unexpected FindAuthorization return value %d", err);
+        return KM_ERROR_INVALID_ARGUMENT;
+    }
+}
+
+inline void KeyStoreService::addAuthToParams(std::vector<keymaster_key_param_t>* params,
+                                             const hw_auth_token_t* token) {
+    if (token) {
+        params->push_back(keymaster_param_blob(
+            KM_TAG_AUTH_TOKEN, reinterpret_cast<const uint8_t*>(token), sizeof(hw_auth_token_t)));
+    }
+}
+
+/**
+ * Add the auth token for the operation to the param list if the operation
+ * requires authorization. Uses the cached result in the OperationMap if available
+ * otherwise gets the token from the AuthTokenTable and caches the result.
+ *
+ * Returns ::NO_ERROR if the auth token was added or not needed.
+ *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
+ *         authenticated.
+ *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
+ *         operation token.
+ */
+int32_t KeyStoreService::addOperationAuthTokenIfNeeded(sp<IBinder> token,
+                                                       std::vector<keymaster_key_param_t>* params) {
+    const hw_auth_token_t* authToken = NULL;
+    mOperationMap.getOperationAuthToken(token, &authToken);
+    if (!authToken) {
+        const keymaster2_device_t* dev;
+        keymaster_operation_handle_t handle;
+        const keymaster_key_characteristics_t* characteristics = NULL;
+        keymaster_purpose_t purpose;
+        keymaster::km_id_t keyid;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+            return KM_ERROR_INVALID_OPERATION_HANDLE;
+        }
+        int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
+        if (result != ::NO_ERROR) {
+            return result;
+        }
+        if (authToken) {
+            mOperationMap.setOperationAuthToken(token, authToken);
+        }
+    }
+    addAuthToParams(params, authToken);
+    return ::NO_ERROR;
+}
+
+/**
+ * Translate a result value to a legacy return value. All keystore errors are
+ * preserved and keymaster errors become SYSTEM_ERRORs
+ */
+inline int32_t KeyStoreService::translateResultToLegacyResult(int32_t result) {
+    if (result > 0) {
+        return result;
+    }
+    return ::SYSTEM_ERROR;
+}
+
+keymaster_key_param_t*
+KeyStoreService::getKeyAlgorithm(keymaster_key_characteristics_t* characteristics) {
+    for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
+        if (characteristics->hw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
+            return &characteristics->hw_enforced.params[i];
+        }
+    }
+    for (size_t i = 0; i < characteristics->sw_enforced.length; i++) {
+        if (characteristics->sw_enforced.params[i].tag == KM_TAG_ALGORITHM) {
+            return &characteristics->sw_enforced.params[i];
+        }
+    }
+    return NULL;
+}
+
+void KeyStoreService::addLegacyBeginParams(const String16& name,
+                                           std::vector<keymaster_key_param_t>& params) {
+    // All legacy keys are DIGEST_NONE/PAD_NONE.
+    params.push_back(keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE));
+    params.push_back(keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE));
+
+    // Look up the algorithm of the key.
+    KeyCharacteristics characteristics;
+    int32_t rc = getKeyCharacteristics(name, NULL, NULL, &characteristics);
+    if (rc != ::NO_ERROR) {
+        ALOGE("Failed to get key characteristics");
+        return;
+    }
+    keymaster_key_param_t* algorithm = getKeyAlgorithm(&characteristics.characteristics);
+    if (!algorithm) {
+        ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
+        return;
+    }
+    params.push_back(*algorithm);
+}
+
+int32_t KeyStoreService::doLegacySignVerify(const String16& name, const uint8_t* data,
+                                            size_t length, uint8_t** out, size_t* outLength,
+                                            const uint8_t* signature, size_t signatureLength,
+                                            keymaster_purpose_t purpose) {
+
+    std::basic_stringstream<uint8_t> outBuffer;
+    OperationResult result;
+    KeymasterArguments inArgs;
+    addLegacyBeginParams(name, inArgs.params);
+    sp<IBinder> appToken(new BBinder);
+    sp<IBinder> token;
+
+    begin(appToken, name, purpose, true, inArgs, NULL, 0, &result);
+    if (result.resultCode != ResponseCode::NO_ERROR) {
+        if (result.resultCode == ::KEY_NOT_FOUND) {
+            ALOGW("Key not found");
+        } else {
+            ALOGW("Error in begin: %d", result.resultCode);
+        }
+        return translateResultToLegacyResult(result.resultCode);
+    }
+    inArgs.params.clear();
+    token = result.token;
+    size_t consumed = 0;
+    size_t lastConsumed = 0;
+    do {
+        update(token, inArgs, data + consumed, length - consumed, &result);
+        if (result.resultCode != ResponseCode::NO_ERROR) {
+            ALOGW("Error in update: %d", result.resultCode);
+            return translateResultToLegacyResult(result.resultCode);
+        }
+        if (out) {
+            outBuffer.write(result.data.get(), result.dataLength);
+        }
+        lastConsumed = result.inputConsumed;
+        consumed += lastConsumed;
+    } while (consumed < length && lastConsumed > 0);
+
+    if (consumed != length) {
+        ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, length);
+        return ::SYSTEM_ERROR;
+    }
+
+    finish(token, inArgs, signature, signatureLength, NULL, 0, &result);
+    if (result.resultCode != ResponseCode::NO_ERROR) {
+        ALOGW("Error in finish: %d", result.resultCode);
+        return translateResultToLegacyResult(result.resultCode);
+    }
+    if (out) {
+        outBuffer.write(result.data.get(), result.dataLength);
+    }
+
+    if (out) {
+        auto buf = outBuffer.str();
+        *out = new uint8_t[buf.size()];
+        memcpy(*out, buf.c_str(), buf.size());
+        *outLength = buf.size();
+    }
+
+    return ::NO_ERROR;
+}
+
+}  // namespace android
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
new file mode 100644
index 0000000..35b8928
--- /dev/null
+++ b/keystore/key_store_service.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_KEYSTORE_SERVICE_H_
+#define KEYSTORE_KEYSTORE_SERVICE_H_
+
+#include <keystore/IKeystoreService.h>
+
+#include "auth_token_table.h"
+#include "keystore.h"
+#include "keystore_keymaster_enforcement.h"
+#include "operation.h"
+#include "permissions.h"
+
+namespace android {
+
+class KeyStoreService : public BnKeystoreService, public IBinder::DeathRecipient {
+  public:
+    KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
+
+    void binderDied(const wp<IBinder>& who);
+
+    int32_t getState(int32_t userId);
+
+    int32_t get(const String16& name, uint8_t** item, size_t* itemLength);
+    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int targetUid,
+                   int32_t flags);
+    int32_t del(const String16& name, int targetUid);
+    int32_t exist(const String16& name, int targetUid);
+    int32_t list(const String16& prefix, int targetUid, Vector<String16>* matches);
+
+    int32_t reset();
+
+    int32_t onUserPasswordChanged(int32_t userId, const String16& password);
+    int32_t onUserAdded(int32_t userId, int32_t parentId);
+    int32_t onUserRemoved(int32_t userId);
+
+    int32_t lock(int32_t userId);
+    int32_t unlock(int32_t userId, const String16& pw);
+
+    bool isEmpty(int32_t userId);
+
+    int32_t generate(const String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
+                     int32_t flags, Vector<sp<KeystoreArg>>* args);
+    int32_t import(const String16& name, const uint8_t* data, size_t length, int targetUid,
+                   int32_t flags);
+    int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
+                 size_t* outLength);
+    int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
+                   const uint8_t* signature, size_t signatureLength);
+
+    /*
+     * TODO: The abstraction between things stored in hardware and regular blobs
+     * of data stored on the filesystem should be moved down to keystore itself.
+     * Unfortunately the Java code that calls this has naming conventions that it
+     * knows about. Ideally keystore shouldn't be used to store random blobs of
+     * data.
+     *
+     * Until that happens, it's necessary to have a separate "get_pubkey" and
+     * "del_key" since the Java code doesn't really communicate what it's
+     * intentions are.
+     */
+    int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength);
+
+    int32_t grant(const String16& name, int32_t granteeUid);
+    int32_t ungrant(const String16& name, int32_t granteeUid);
+
+    int64_t getmtime(const String16& name);
+
+    int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
+                      int32_t destUid);
+
+    int32_t is_hardware_backed(const String16& keyType);
+
+    int32_t clear_uid(int64_t targetUid64);
+
+    int32_t addRngEntropy(const uint8_t* data, size_t dataLength);
+    int32_t generateKey(const String16& name, const KeymasterArguments& params,
+                        const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+                        KeyCharacteristics* outCharacteristics);
+    int32_t getKeyCharacteristics(const String16& name, const keymaster_blob_t* clientId,
+                                  const keymaster_blob_t* appData,
+                                  KeyCharacteristics* outCharacteristics);
+    int32_t importKey(const String16& name, const KeymasterArguments& params,
+                      keymaster_key_format_t format, const uint8_t* keyData, size_t keyLength,
+                      int uid, int flags, KeyCharacteristics* outCharacteristics);
+    void exportKey(const String16& name, keymaster_key_format_t format,
+                   const keymaster_blob_t* clientId, const keymaster_blob_t* appData,
+                   ExportResult* result);
+    void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
+               bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
+               size_t entropyLength, OperationResult* result);
+    void update(const sp<IBinder>& token, const KeymasterArguments& params, const uint8_t* data,
+                size_t dataLength, OperationResult* result);
+    void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+                const uint8_t* signature, size_t signatureLength, const uint8_t* entropy,
+                size_t entropyLength, OperationResult* result);
+    int32_t abort(const sp<IBinder>& token);
+
+    bool isOperationAuthorized(const sp<IBinder>& token);
+
+    int32_t addAuthToken(const uint8_t* token, size_t length);
+
+    int32_t attestKey(const String16& name, const KeymasterArguments& params,
+                      KeymasterCertificateChain* outChain) override;
+
+  private:
+    static const int32_t UID_SELF = -1;
+
+    /**
+     * Prune the oldest pruneable operation.
+     */
+    bool pruneOperation();
+
+    /**
+     * Get the effective target uid for a binder operation that takes an
+     * optional uid as the target.
+     */
+    uid_t getEffectiveUid(int32_t targetUid);
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission and if acting on other uids the grants to do so.
+     */
+    bool checkBinderPermission(perm_t permission, int32_t targetUid = UID_SELF);
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission and the target uid is the caller or the caller is system.
+     */
+    bool checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid);
+
+    /**
+     * Check if the caller of the current binder method has the required
+     * permission or the target of the operation is the caller's uid. This is
+     * for operation where the permission is only for cross-uid activity and all
+     * uids are allowed to act on their own (ie: clearing all entries for a
+     * given uid).
+     */
+    bool checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid);
+
+    /**
+     * Helper method to check that the caller has the required permission as
+     * well as the keystore is in the unlocked state if checkUnlocked is true.
+     *
+     * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
+     * otherwise the state of keystore when not unlocked and checkUnlocked is
+     * true.
+     */
+    int32_t checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid = -1,
+                                                  bool checkUnlocked = true);
+
+    bool isKeystoreUnlocked(State state);
+
+    bool isKeyTypeSupported(const keymaster2_device_t* device, keymaster_keypair_t keyType);
+
+    /**
+     * Check that all keymaster_key_param_t's provided by the application are
+     * allowed. Any parameter that keystore adds itself should be disallowed here.
+     */
+    bool checkAllowedOperationParams(const std::vector<keymaster_key_param_t>& params);
+
+    keymaster_error_t getOperationCharacteristics(const keymaster_key_blob_t& key,
+                                                  const keymaster2_device_t* dev,
+                                                  const std::vector<keymaster_key_param_t>& params,
+                                                  keymaster_key_characteristics_t* out);
+
+    /**
+     * Get the auth token for this operation from the auth token table.
+     *
+     * Returns ::NO_ERROR if the auth token was set or none was required.
+     *         ::OP_AUTH_NEEDED if it is a per op authorization, no
+     *         authorization token exists for that operation and
+     *         failOnTokenMissing is false.
+     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
+     *         token for the operation
+     */
+    int32_t getAuthToken(const keymaster_key_characteristics_t* characteristics,
+                         keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
+                         const hw_auth_token_t** authToken, bool failOnTokenMissing = true);
+
+    void addAuthToParams(std::vector<keymaster_key_param_t>* params, const hw_auth_token_t* token);
+
+    /**
+     * Add the auth token for the operation to the param list if the operation
+     * requires authorization. Uses the cached result in the OperationMap if available
+     * otherwise gets the token from the AuthTokenTable and caches the result.
+     *
+     * Returns ::NO_ERROR if the auth token was added or not needed.
+     *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
+     *         authenticated.
+     *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
+     *         operation token.
+     */
+    int32_t addOperationAuthTokenIfNeeded(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..457a60a 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, keymaster2_device_t* device, keymaster2_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) {
+        auto* dev = getDeviceForBlob(keyBlob);
+        if (dev->delete_key) {
+            keymaster_key_blob_t blob;
+            blob.key_material = keyBlob.getValue();
+            blob.key_material_size = keyBlob.getLength();
+            dev->delete_key(dev, &blob);
+        }
+    }
+    if (rc != ::NO_ERROR) {
+        return rc;
+    }
+
+    return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+}
+
 /*
  * Converts from the "escaped" format on disk to actual name.
  * This will be smaller than the input string.
@@ -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..62d7294
--- /dev/null
+++ b/keystore/keystore.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_KEYSTORE_H_
+#define KEYSTORE_KEYSTORE_H_
+
+#include "user_state.h"
+
+#include <hardware/keymaster2.h>
+
+#include <utils/Vector.h>
+
+#include "blob.h"
+
+typedef struct {
+    uint32_t uid;
+    const uint8_t* filename;
+} grant_t;
+
+class KeyStore {
+  public:
+    KeyStore(Entropy* entropy, keymaster2_device_t* device, keymaster2_device_t* fallback);
+    ~KeyStore();
+
+    keymaster2_device_t* getDevice() const { return mDevice; }
+
+    keymaster2_device_t* getFallbackDevice() const { return mFallbackDevice; }
+
+    keymaster2_device_t* getDeviceForBlob(const Blob& blob) const {
+        return blob.isFallback() ? mFallbackDevice : mDevice;
+    }
+
+    ResponseCode initialize();
+
+    State getState(uid_t userId) { return getUserState(userId)->getState(); }
+
+    ResponseCode initializeUser(const android::String8& pw, uid_t userId);
+
+    ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser);
+    ResponseCode writeMasterKey(const android::String8& pw, uid_t userId);
+    ResponseCode readMasterKey(const android::String8& pw, uid_t userId);
+
+    android::String8 getKeyName(const android::String8& keyName);
+    android::String8 getKeyNameForUid(const android::String8& keyName, uid_t uid);
+    android::String8 getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid);
+
+    /*
+     * Delete entries owned by userId. If keepUnencryptedEntries is true
+     * then only encrypted entries will be removed, otherwise all entries will
+     * be removed.
+     */
+    void resetUser(uid_t userId, bool keepUnenryptedEntries);
+    bool isEmpty(uid_t userId) const;
+
+    void lock(uid_t userId);
+
+    ResponseCode get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId);
+    ResponseCode put(const char* filename, Blob* keyBlob, uid_t userId);
+    ResponseCode del(const char* filename, const BlobType type, uid_t userId);
+    ResponseCode list(const android::String8& prefix, android::Vector<android::String16>* matches,
+                      uid_t userId);
+
+    void addGrant(const char* filename, uid_t granteeUid);
+    bool removeGrant(const char* filename, uid_t granteeUid);
+    bool hasGrant(const char* filename, const uid_t uid) const {
+        return getGrant(filename, uid) != NULL;
+    }
+
+    ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename, uid_t userId,
+                           int32_t flags);
+
+    bool isHardwareBacked(const android::String16& keyType) const;
+
+    ResponseCode getKeyForName(Blob* keyBlob, const android::String8& keyName, const uid_t uid,
+                               const BlobType type);
+
+    /**
+     * Returns any existing UserState or creates it if it doesn't exist.
+     */
+    UserState* getUserState(uid_t userId);
+
+    /**
+     * Returns any existing UserState or creates it if it doesn't exist.
+     */
+    UserState* getUserStateByUid(uid_t uid);
+
+    /**
+     * Returns NULL if the UserState doesn't already exist.
+     */
+    const UserState* getUserState(uid_t userId) const;
+
+    /**
+     * Returns NULL if the UserState doesn't already exist.
+     */
+    const UserState* getUserStateByUid(uid_t uid) const;
+
+  private:
+    static const char* sOldMasterKey;
+    static const char* sMetaDataFile;
+    static const android::String16 sRSAKeyType;
+    static const android::String16 sECKeyType;
+    Entropy* mEntropy;
+
+    keymaster2_device_t* mDevice;
+    keymaster2_device_t* mFallbackDevice;
+
+    android::Vector<UserState*> mMasterKeys;
+
+    android::Vector<grant_t*> mGrants;
+
+    typedef struct { uint32_t version; } keystore_metadata_t;
+
+    keystore_metadata_t mMetaData;
+
+    const grant_t* getGrant(const char* filename, uid_t uid) const;
+
+    /**
+     * Upgrade the key from the current version to whatever is newest.
+     */
+    bool upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
+                     const BlobType type, uid_t uid);
+
+    /**
+     * Takes a blob that is an PEM-encoded RSA key as a byte array and converts it to a DER-encoded
+     * PKCS#8 for import into a keymaster.  Then it overwrites the original blob with the new blob
+     * format that is returned from the keymaster.
+     */
+    ResponseCode importBlobAsKey(Blob* blob, const char* filename, uid_t uid);
+
+    void readMetaData();
+    void writeMetaData();
+
+    bool upgradeKeystore();
+};
+
+#endif  // KEYSTORE_KEYSTORE_H_
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 526dc57..c4dbf5d 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -20,6 +20,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "keymaster/authorization_set.h"
+#include "keymaster/keymaster_tags.h"
 #include "keystore/keystore_client_impl.h"
 
 using base::CommandLine;
@@ -56,90 +57,14 @@
     return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
 }
 
-const char* StringifyTag(keymaster_tag_t tag) {
-    switch (tag) {
-    case KM_TAG_INVALID:
-        return "KM_TAG_INVALID";
-    case KM_TAG_PURPOSE:
-        return "KM_TAG_PURPOSE";
-    case KM_TAG_ALGORITHM:
-        return "KM_TAG_ALGORITHM";
-    case KM_TAG_KEY_SIZE:
-        return "KM_TAG_KEY_SIZE";
-    case KM_TAG_BLOCK_MODE:
-        return "KM_TAG_BLOCK_MODE";
-    case KM_TAG_DIGEST:
-        return "KM_TAG_DIGEST";
-    case KM_TAG_PADDING:
-        return "KM_TAG_PADDING";
-    case KM_TAG_CALLER_NONCE:
-        return "KM_TAG_CALLER_NONCE";
-    case KM_TAG_MIN_MAC_LENGTH:
-        return "KM_TAG_MIN_MAC_LENGTH";
-    case KM_TAG_RSA_PUBLIC_EXPONENT:
-        return "KM_TAG_RSA_PUBLIC_EXPONENT";
-    case KM_TAG_BLOB_USAGE_REQUIREMENTS:
-        return "KM_TAG_BLOB_USAGE_REQUIREMENTS";
-    case KM_TAG_BOOTLOADER_ONLY:
-        return "KM_TAG_BOOTLOADER_ONLY";
-    case KM_TAG_ACTIVE_DATETIME:
-        return "KM_TAG_ACTIVE_DATETIME";
-    case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
-        return "KM_TAG_ORIGINATION_EXPIRE_DATETIME";
-    case KM_TAG_USAGE_EXPIRE_DATETIME:
-        return "KM_TAG_USAGE_EXPIRE_DATETIME";
-    case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
-        return "KM_TAG_MIN_SECONDS_BETWEEN_OPS";
-    case KM_TAG_MAX_USES_PER_BOOT:
-        return "KM_TAG_MAX_USES_PER_BOOT";
-    case KM_TAG_ALL_USERS:
-        return "KM_TAG_ALL_USERS";
-    case KM_TAG_USER_ID:
-        return "KM_TAG_USER_ID";
-    case KM_TAG_USER_SECURE_ID:
-        return "KM_TAG_USER_SECURE_ID";
-    case KM_TAG_NO_AUTH_REQUIRED:
-        return "KM_TAG_NO_AUTH_REQUIRED";
-    case KM_TAG_USER_AUTH_TYPE:
-        return "KM_TAG_USER_AUTH_TYPE";
-    case KM_TAG_AUTH_TIMEOUT:
-        return "KM_TAG_AUTH_TIMEOUT";
-    case KM_TAG_ALL_APPLICATIONS:
-        return "KM_TAG_ALL_APPLICATIONS";
-    case KM_TAG_APPLICATION_ID:
-        return "KM_TAG_APPLICATION_ID";
-    case KM_TAG_APPLICATION_DATA:
-        return "KM_TAG_APPLICATION_DATA";
-    case KM_TAG_CREATION_DATETIME:
-        return "KM_TAG_CREATION_DATETIME";
-    case KM_TAG_ORIGIN:
-        return "KM_TAG_ORIGIN";
-    case KM_TAG_ROLLBACK_RESISTANT:
-        return "KM_TAG_ROLLBACK_RESISTANT";
-    case KM_TAG_ROOT_OF_TRUST:
-        return "KM_TAG_ROOT_OF_TRUST";
-    case KM_TAG_ASSOCIATED_DATA:
-        return "KM_TAG_ASSOCIATED_DATA";
-    case KM_TAG_NONCE:
-        return "KM_TAG_NONCE";
-    case KM_TAG_AUTH_TOKEN:
-        return "KM_TAG_AUTH_TOKEN";
-    case KM_TAG_MAC_LENGTH:
-        return "KM_TAG_MAC_LENGTH";
-    case KM_TAG_KDF:
-        return "KM_TAG_KDF";
-    case KM_TAG_EC_CURVE:
-        return "KM_TAG_EC_CURVE";
-    case KM_TAG_ECIES_SINGLE_HASH_MODE:
-        return "KM_TAG_ECIES_SINGLE_HASH_MODE";
-    }
-    return "<Unknown>";
-}
+#ifndef KEYMASTER_NAME_TAGS
+#erro KEYMASTER_NAME_TAGS must be defined
+#endif
 
 void PrintTags(const AuthorizationSet& parameters) {
     const keymaster_key_param_t* iter = nullptr;
     for (iter = parameters.begin(); iter != parameters.end(); ++iter) {
-        printf("  %s\n", StringifyTag(iter->tag));
+        printf("  %s\n", keymaster::StringifyTag(iter->tag));
     }
 }
 
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
new file mode 100644
index 0000000..a2b75f6
--- /dev/null
+++ b/keystore/keystore_main.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "keystore"
+
+#include <keymaster/soft_keymaster_device.h>
+#include <keymaster/soft_keymaster_logger.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <cutils/log.h>
+
+#include "entropy.h"
+#include "key_store_service.h"
+#include "keystore.h"
+#include "permissions.h"
+
+/* KeyStore is a secured storage for key-value pairs. In this implementation,
+ * each file stores one key-value pair. Keys are encoded in file names, and
+ * values are encrypted with checksums. The encryption key is protected by a
+ * user-defined password. To keep things simple, buffers are always larger than
+ * the maximum space we needed, so boundary checks on buffers are omitted. */
+
+using keymaster::SoftKeymasterDevice;
+
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster0_device_t* km0_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster0_open(mod, &km0_device);
+    if (rc) {
+        ALOGE("Error opening keystore keymaster0 device.");
+        goto err;
+    }
+
+    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
+        km0_device->common.close(&km0_device->common);
+        km0_device = NULL;
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster2_device();
+        return 0;
+    }
+
+    ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km0_device);
+    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by  keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km0_device)
+        km0_device->common.close(&km0_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster1_device_t* km1_device = nullptr;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster1_open(mod, &km1_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster1 device", rc);
+        goto err;
+    }
+
+    ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km1_device);
+    km1_device = nullptr;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km1_device)
+        km1_device->common.close(&km1_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
+    ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster2_device_t* km2_device = nullptr;
+
+    int rc = keymaster2_open(mod, &km2_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster2 device", rc);
+        goto err;
+    }
+
+    *dev = km2_device;
+    return 0;
+
+err:
+    if (km2_device)
+        km2_device->common.close(&km2_device->common);
+    *dev = nullptr;
+    return rc;
+}
+
+static int keymaster_device_initialize(keymaster2_device_t** dev) {
+    const hw_module_t* mod;
+
+    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    if (rc) {
+        ALOGI("Could not find any keystore module, using software-only implementation.");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = (new SoftKeymasterDevice)->keymaster2_device();
+        return 0;
+    }
+
+    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+        return keymaster0_device_initialize(mod, dev);
+    } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
+        return keymaster1_device_initialize(mod, dev);
+    } else {
+        return keymaster2_device_initialize(mod, dev);
+    }
+}
+
+// softkeymaster_logger appears not to be used in keystore, but it installs itself as the
+// logger used by SoftKeymasterDevice.
+static keymaster::SoftKeymasterLogger softkeymaster_logger;
+
+static int fallback_keymaster_device_initialize(keymaster2_device_t** dev) {
+    *dev = (new SoftKeymasterDevice)->keymaster2_device();
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    return 0;
+}
+
+static void keymaster_device_release(keymaster2_device_t* dev) {
+    dev->common.close(&dev->common);
+}
+
+int main(int argc, char* argv[]) {
+    if (argc < 2) {
+        ALOGE("A directory must be specified!");
+        return 1;
+    }
+    if (chdir(argv[1]) == -1) {
+        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
+        return 1;
+    }
+
+    Entropy entropy;
+    if (!entropy.open()) {
+        return 1;
+    }
+
+    keymaster2_device_t* dev;
+    if (keymaster_device_initialize(&dev)) {
+        ALOGE("keystore keymaster could not be initialized; exiting");
+        return 1;
+    }
+
+    keymaster2_device_t* fallback;
+    if (fallback_keymaster_device_initialize(&fallback)) {
+        ALOGE("software keymaster could not be initialized; exiting");
+        return 1;
+    }
+
+    if (configure_selinux() == -1) {
+        return -1;
+    }
+
+    KeyStore keyStore(&entropy, dev, fallback);
+    keyStore.initialize();
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<android::KeyStoreService> service = new android::KeyStoreService(&keyStore);
+    android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
+    if (ret != android::OK) {
+        ALOGE("Couldn't register binder service!");
+        return -1;
+    }
+
+    /*
+     * We're the only thread in existence, so we're just going to process
+     * Binder transaction as a single-threaded program.
+     */
+    android::IPCThreadState::self()->joinThreadPool();
+
+    keymaster_device_release(dev);
+    return 1;
+}
diff --git a/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/operation.cpp b/keystore/operation.cpp
index 3b381c4..72aa95f 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -21,12 +21,10 @@
 
 namespace android {
 OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
-        : mDeathRecipient(deathRecipient) {
-}
+    : mDeathRecipient(deathRecipient) {}
 
-sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle,
-                                       uint64_t keyid, keymaster_purpose_t purpose,
-                                       const keymaster1_device_t* dev,
+sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
+                                       keymaster_purpose_t purpose, const keymaster2_device_t* dev,
                                        sp<IBinder> appToken,
                                        keymaster_key_characteristics_t* characteristics,
                                        bool pruneable) {
@@ -44,7 +42,7 @@
 
 bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
                                 uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
-                                const keymaster1_device_t** outDevice,
+                                const keymaster2_device_t** outDevice,
                                 const keymaster_key_characteristics_t** outCharacteristics) {
     if (!outHandle || !outDevice) {
         return false;
@@ -146,20 +144,13 @@
     }
 }
 
-OperationMap::Operation::Operation(keymaster_operation_handle_t handle_,
-                                   uint64_t keyid_,
-                                   keymaster_purpose_t purpose_,
-                                   const keymaster1_device_t* device_,
+OperationMap::Operation::Operation(keymaster_operation_handle_t handle_, uint64_t keyid_,
+                                   keymaster_purpose_t purpose_, const keymaster2_device_t* device_,
                                    keymaster_key_characteristics_t* characteristics_,
                                    sp<IBinder> appToken_)
-    : handle(handle_),
-      keyid(keyid_),
-      purpose(purpose_),
-      device(device_),
-      characteristics(characteristics_),
-      appToken(appToken_) {
-}
+    : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
+      characteristics(characteristics_), appToken(appToken_) {}
 
-OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) {
-}
-} // namespace android
+OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) {}
+
+}  // namespace android
diff --git a/keystore/operation.h b/keystore/operation.h
index d8d1b18..eb16257 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -18,7 +18,7 @@
 #define KEYSTORE_OPERATION_H_
 
 #include <hardware/hw_auth_token.h>
-#include <hardware/keymaster1.h>
+#include <hardware/keymaster2.h>
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
 #include <utils/LruCache.h>
@@ -39,7 +39,7 @@
 
 /**
  * OperationMap handles the translation of keymaster_operation_handle_t's and
- * keymaster1_device_t's to opaque binder tokens that can be used to reference
+ * keymaster2_device_t's to opaque binder tokens that can be used to reference
  * that operation at a later time by applications. It also does LRU tracking
  * for operation pruning and keeps a mapping of clients to operations to allow
  * for graceful handling of application death.
@@ -48,12 +48,12 @@
 public:
     OperationMap(IBinder::DeathRecipient* deathRecipient);
     sp<IBinder> addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
-                             keymaster_purpose_t purpose, const keymaster1_device_t* dev,
+                             keymaster_purpose_t purpose, const keymaster2_device_t* dev,
                              sp<IBinder> appToken, keymaster_key_characteristics_t* characteristics,
                              bool pruneable);
     bool getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
                       uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
-                      const keymaster1_device_t** outDev,
+                      const keymaster2_device_t** outDev,
                       const keymaster_key_characteristics_t** outCharacteristics);
     bool removeOperation(sp<IBinder> token);
     bool hasPruneableOperation() const;
@@ -70,12 +70,12 @@
     struct Operation {
         Operation();
         Operation(keymaster_operation_handle_t handle, uint64_t keyid, keymaster_purpose_t purpose,
-                  const keymaster1_device_t* device,
+                  const keymaster2_device_t* device,
                   keymaster_key_characteristics_t* characteristics, sp<IBinder> appToken);
         keymaster_operation_handle_t handle;
         uint64_t keyid;
         keymaster_purpose_t purpose;
-        const keymaster1_device_t* device;
+        const keymaster2_device_t* device;
         Unique_keymaster_key_characteristics characteristics;
         sp<IBinder> appToken;
         std::unique_ptr<hw_auth_token_t> authToken;
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_
