Switch keystore to binder

Change-Id: I6dacdc43bcc1a56e47655e37e825ee6a205eb56b
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index ea58ad6..23711e7 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "keystore"
+
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
@@ -42,13 +45,15 @@
 
 #include <cutils/list.h>
 
-//#define LOG_NDEBUG 0
-#define LOG_TAG "keystore"
+#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.h"
+#include <keystore/keystore.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
@@ -154,6 +159,72 @@
     keymaster_close(dev);
 }
 
+/***************
+ * PERMISSIONS *
+ ***************/
+
+/* Here are the permissions, actions, users, and the main function. */
+typedef enum {
+    P_TEST     = 1 << 0,
+    P_GET      = 1 << 1,
+    P_INSERT   = 1 << 2,
+    P_DELETE   = 1 << 3,
+    P_EXIST    = 1 << 4,
+    P_SAW      = 1 << 5,
+    P_RESET    = 1 << 6,
+    P_PASSWORD = 1 << 7,
+    P_LOCK     = 1 << 8,
+    P_UNLOCK   = 1 << 9,
+    P_ZERO     = 1 << 10,
+    P_SIGN     = 1 << 11,
+    P_VERIFY   = 1 << 12,
+    P_GRANT    = 1 << 13,
+} 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},
+};
+
+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_TEST | P_GET | P_INSERT | P_DELETE | P_EXIST | P_SAW | P_SIGN
+        | P_VERIFY);
+
+static bool has_permission(uid_t uid, perm_t perm) {
+    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;
+        }
+    }
+
+    return DEFAULT_PERMS & perm;
+}
+
+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;
+}
+
 /* Here is the encoding of keys. This is necessary in order to allow arbitrary
  * characters in keys. Characters in [0-~] are not encoded. Others are encoded
  * into two bytes. The first byte is one of [+-.] which represents the first
@@ -161,9 +232,9 @@
  * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
  * that Base64 cannot be used here due to the need of prefix match on keys. */
 
-static int encode_key(char* out, const Value* key) {
-    const uint8_t* in = key->value;
-    int length = key->length;
+static int encode_key(char* out, const android::String8& keyName) {
+    const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
+    size_t length = keyName.length();
     for (int i = length; i > 0; --i, ++in, ++out) {
         if (*in >= '0' && *in <= '~') {
             *out = *in;
@@ -177,25 +248,48 @@
     return length;
 }
 
-static int encode_key_for_uid(char* out, uid_t uid, const Value* key) {
+static int encode_key_for_uid(char* out, uid_t uid, const android::String8& keyName) {
     int n = snprintf(out, NAME_MAX, "%u_", uid);
     out += n;
 
-    return n + encode_key(out, key);
+    return n + encode_key(out, keyName);
 }
 
-static int decode_key(uint8_t* out, const char* in, int length) {
-    for (int i = 0; i < length; ++i, ++in, ++out) {
-        if (*in >= '0' && *in <= '~') {
-            *out = *in;
+/*
+ * Converts from the "escaped" format on disk to actual name.
+ * This will be smaller than the input string.
+ *
+ * Characters that should combine with the next at the end will be truncated.
+ */
+static size_t decode_key_length(const char* in, size_t length) {
+    size_t outLength = 0;
+
+    for (const char* end = in + length; in < end; in++) {
+        /* This combines with the next character. */
+        if (*in < '0' || *in > '~') {
+            continue;
+        }
+
+        outLength++;
+    }
+    return outLength;
+}
+
+static void decode_key(char* out, const char* in, size_t length) {
+    for (const char* end = in + length; in < end; in++) {
+        if (*in < '0' || *in > '~') {
+            /* Truncate combining characters at the end. */
+            if (in + 1 >= end) {
+                break;
+            }
+
+            *out = (*in++ - '+') << 6;
+            *out++ |= (*in - '0') & 0x3F;
         } else {
-            *out = (*in - '+') << 6;
-            *out |= (*++in - '0') & 0x3F;
-            --length;
+            *out++ = *in;
         }
     }
     *out = '\0';
-    return length;
 }
 
 static size_t readFully(int fd, uint8_t* data, size_t size) {
@@ -293,18 +387,19 @@
     TYPE_KEY_PAIR = 3,
 } BlobType;
 
-static const uint8_t CurrentBlobVersion = 1;
+static const uint8_t CURRENT_BLOB_VERSION = 1;
 
 class Blob {
 public:
-    Blob(uint8_t* value, int32_t valueLength, uint8_t* info, uint8_t infoLength, BlobType type) {
+    Blob(const uint8_t* value, int32_t valueLength, const uint8_t* info, uint8_t infoLength,
+            BlobType type) {
         mBlob.length = valueLength;
         memcpy(mBlob.value, value, valueLength);
 
         mBlob.info = infoLength;
         memcpy(mBlob.value + valueLength, info, infoLength);
 
-        mBlob.version = CurrentBlobVersion;
+        mBlob.version = CURRENT_BLOB_VERSION;
         mBlob.type = uint8_t(type);
     }
 
@@ -388,7 +483,7 @@
             unlink(tmpFileName);
             return SYSTEM_ERROR;
         }
-        return (rename(tmpFileName, filename) == 0) ? NO_ERROR : SYSTEM_ERROR;
+        return (rename(tmpFileName, filename) == 0) ? ::NO_ERROR : ::SYSTEM_ERROR;
     }
 
     ResponseCode decryptBlob(const char* filename, AES_KEY *aes_key) {
@@ -430,7 +525,7 @@
             // move info from after padding to after data
             memmove(&mBlob.value[mBlob.length], &mBlob.value[maxValueLength], mBlob.info);
         }
-        return NO_ERROR;
+        return ::NO_ERROR;
     }
 
 private:
@@ -472,7 +567,7 @@
         return mDevice;
     }
 
-    ResponseCode initialize(Value* pw) {
+    ResponseCode initialize(const android::String8& pw) {
         if (!generateMasterKey()) {
             return SYSTEM_ERROR;
         }
@@ -481,10 +576,10 @@
             return response;
         }
         setupMasterKeys();
-        return NO_ERROR;
+        return ::NO_ERROR;
     }
 
-    ResponseCode writeMasterKey(Value* pw) {
+    ResponseCode writeMasterKey(const android::String8& pw) {
         uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
         generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
         AES_KEY passwordAesKey;
@@ -493,7 +588,7 @@
         return masterKeyBlob.encryptBlob(MASTER_KEY_FILE, &passwordAesKey, mEntropy);
     }
 
-    ResponseCode readMasterKey(Value* pw) {
+    ResponseCode readMasterKey(const android::String8& pw) {
         int in = open(MASTER_KEY_FILE, O_RDONLY);
         if (in == -1) {
             return SYSTEM_ERROR;
@@ -596,7 +691,7 @@
         }
 
         const uint8_t version = keyBlob->getVersion();
-        if (version < CurrentBlobVersion) {
+        if (version < CURRENT_BLOB_VERSION) {
             upgrade(filename, keyBlob, version, type);
         }
 
@@ -612,28 +707,18 @@
         return keyBlob->encryptBlob(filename, &mMasterKeyEncryption, mEntropy);
     }
 
-    void addGrant(const char* filename, const Value* uidValue) {
-        uid_t uid;
-        if (!convertToUid(uidValue, &uid)) {
-            return;
-        }
-
-        grant_t *grant = getGrant(filename, uid);
+    void addGrant(const char* filename, uid_t granteeUid) {
+        grant_t *grant = getGrant(filename, granteeUid);
         if (grant == NULL) {
             grant = new grant_t;
-            grant->uid = uid;
+            grant->uid = granteeUid;
             grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
             list_add_tail(&mGrants, &grant->plist);
         }
     }
 
-    bool removeGrant(const char* filename, const Value* uidValue) {
-        uid_t uid;
-        if (!convertToUid(uidValue, &uid)) {
-            return false;
-        }
-
-        grant_t *grant = getGrant(filename, uid);
+    bool removeGrant(const char* filename, uid_t granteeUid) {
+        grant_t *grant = getGrant(filename, granteeUid);
         if (grant != NULL) {
             list_remove(&grant->plist);
             delete grant;
@@ -647,7 +732,7 @@
         return getGrant(filename, uid) != NULL;
     }
 
-    ResponseCode importKey(const Value* key, const char* filename) {
+    ResponseCode importKey(const uint8_t* key, size_t keyLen, const char* filename) {
         uint8_t* data;
         size_t dataLength;
         int rc;
@@ -657,7 +742,7 @@
             return SYSTEM_ERROR;
         }
 
-        rc = mDevice->import_keypair(mDevice, key->value, key->length, &data, &dataLength);
+        rc = mDevice->import_keypair(mDevice, key, keyLen, &data, &dataLength);
         if (rc) {
             ALOGE("Error while importing keypair: %d", rc);
             return SYSTEM_ERROR;
@@ -726,7 +811,8 @@
         memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
     }
 
-    static void generateKeyFromPassword(uint8_t* key, ssize_t keySize, Value* pw, uint8_t* salt) {
+    static void generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+            uint8_t* salt) {
         size_t saltSize;
         if (salt != NULL) {
             saltSize = SALT_SIZE;
@@ -736,7 +822,9 @@
             // sizeof = 9, not strlen = 8
             saltSize = sizeof("keystore");
         }
-        PKCS5_PBKDF2_HMAC_SHA1((char*) pw->value, pw->length, salt, saltSize, 8192, keySize, key);
+
+        PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt,
+                saltSize, 8192, keySize, key);
     }
 
     static bool isKeyFile(const char* filename) {
@@ -834,7 +922,7 @@
             return SYSTEM_ERROR;
         }
 
-        ResponseCode rc = importKey(&pkcs8key, filename);
+        ResponseCode rc = importKey(pkcs8key.value, pkcs8key.length, filename);
         if (rc != NO_ERROR) {
             return rc;
         }
@@ -845,55 +933,8 @@
 
 const char* KeyStore::MASTER_KEY_FILE = ".masterkey";
 
-/* Here is the protocol used in both requests and responses:
- *     code [length_1 message_1 ... length_n message_n] end-of-file
- * where code is one byte long and lengths are unsigned 16-bit integers in
- * network order. Thus the maximum length of a message is 65535 bytes. */
-
-static int recv_code(int sock, int8_t* code) {
-    return recv(sock, code, 1, 0) == 1;
-}
-
-static int recv_message(int sock, uint8_t* message, int length) {
-    uint8_t bytes[2];
-    if (recv(sock, &bytes[0], 1, 0) != 1 ||
-        recv(sock, &bytes[1], 1, 0) != 1) {
-        return -1;
-    } else {
-        int offset = bytes[0] << 8 | bytes[1];
-        if (length < offset) {
-            return -1;
-        }
-        length = offset;
-        offset = 0;
-        while (offset < length) {
-            int n = recv(sock, &message[offset], length - offset, 0);
-            if (n <= 0) {
-                return -1;
-            }
-            offset += n;
-        }
-    }
-    return length;
-}
-
-static int recv_end_of_file(int sock) {
-    uint8_t byte;
-    return recv(sock, &byte, 1, 0) == 0;
-}
-
-static void send_code(int sock, int8_t code) {
-    send(sock, &code, 1, 0);
-}
-
-static void send_message(int sock, const uint8_t* message, int length) {
-    uint16_t bytes = htons(length);
-    send(sock, &bytes, 2, 0);
-    send(sock, message, length, 0);
-}
-
-static ResponseCode get_key_for_name(KeyStore* keyStore, Blob* keyBlob, const Value* keyName,
-        const uid_t uid, const BlobType type) {
+static ResponseCode get_key_for_name(KeyStore* keyStore, Blob* keyBlob,
+        const android::String8& keyName, const uid_t uid, const BlobType type) {
     char filename[NAME_MAX];
 
     encode_key_for_uid(filename, uid, keyName);
@@ -922,494 +963,627 @@
     return keyStore->get(filename, keyBlob, type);
 }
 
-/* Here are the actions. Each of them is a function without arguments. All
- * information is defined in global variables, which are set properly before
- * performing an action. The number of parameters required by each action is
- * fixed and defined in a table. If the return value of an action is positive,
- * it will be treated as a response code and transmitted to the client. Note
- * that the lengths of parameters are checked when they are received, so
- * boundary checks on parameters are omitted. */
-
-static const ResponseCode NO_ERROR_RESPONSE_CODE_SENT = (ResponseCode) 0;
-
-static ResponseCode test(KeyStore* keyStore, int, uid_t, Value*, Value*, Value*) {
-    return (ResponseCode) keyStore->getState();
-}
-
-static ResponseCode get(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*, Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    Blob keyBlob;
-    ResponseCode responseCode = keyStore->get(filename, &keyBlob, TYPE_GENERIC);
-    if (responseCode != NO_ERROR) {
-        return responseCode;
+namespace android {
+class KeyStoreProxy : public BnKeystoreService, public IBinder::DeathRecipient {
+public:
+    KeyStoreProxy(KeyStore* keyStore)
+        : mKeyStore(keyStore)
+    {
     }
-    send_code(sock, NO_ERROR);
-    send_message(sock, keyBlob.getValue(), keyBlob.getLength());
-    return NO_ERROR_RESPONSE_CODE_SENT;
-}
 
-static ResponseCode insert(KeyStore* keyStore, int, uid_t uid, Value* keyName, Value* val,
-        Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    Blob keyBlob(val->value, val->length, NULL, 0, TYPE_GENERIC);
-    return keyStore->put(filename, &keyBlob);
-}
-
-static ResponseCode del(KeyStore* keyStore, int, uid_t uid, Value* keyName, Value*, Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    Blob keyBlob;
-    ResponseCode responseCode = keyStore->get(filename, &keyBlob, TYPE_GENERIC);
-    if (responseCode != NO_ERROR) {
-        return responseCode;
+    void binderDied(const wp<IBinder>&) {
+        ALOGE("binder death detected");
     }
-    return (unlink(filename) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
-}
 
-static ResponseCode exist(KeyStore*, int, uid_t uid, Value* keyName, Value*, Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    if (access(filename, R_OK) == -1) {
-        return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
-    }
-    return NO_ERROR;
-}
-
-static ResponseCode saw(KeyStore*, int sock, uid_t uid, Value* keyPrefix, Value*, Value*) {
-    DIR* dir = opendir(".");
-    if (!dir) {
-        return SYSTEM_ERROR;
-    }
-    char filename[NAME_MAX];
-    int n = encode_key_for_uid(filename, uid, keyPrefix);
-    send_code(sock, NO_ERROR);
-
-    struct dirent* file;
-    while ((file = readdir(dir)) != NULL) {
-        if (!strncmp(filename, file->d_name, n)) {
-            const char* p = &file->d_name[n];
-            keyPrefix->length = decode_key(keyPrefix->value, p, strlen(p));
-            send_message(sock, keyPrefix->value, keyPrefix->length);
+    int32_t test() {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_TEST)) {
+            ALOGW("permission denied for %d: test", uid);
+            return ::PERMISSION_DENIED;
         }
-    }
-    closedir(dir);
-    return NO_ERROR_RESPONSE_CODE_SENT;
-}
 
-static ResponseCode reset(KeyStore* keyStore, int, uid_t, Value*, Value*, Value*) {
-    ResponseCode rc = keyStore->reset() ? NO_ERROR : SYSTEM_ERROR;
-
-    const keymaster_device_t* device = keyStore->getDevice();
-    if (device == NULL) {
-        ALOGE("No keymaster device!");
-        return SYSTEM_ERROR;
+        return mKeyStore->getState();
     }
 
-    if (device->delete_all == NULL) {
-        ALOGV("keymaster device doesn't implement delete_all");
-        return rc;
-    }
-
-    if (device->delete_all(device)) {
-        ALOGE("Problem calling keymaster's delete_all");
-        return SYSTEM_ERROR;
-    }
-
-    return rc;
-}
-
-/* Here is the history. To improve the security, the parameters to generate the
- * master key has been changed. To make a seamless transition, we update the
- * file using the same password when the user unlock it for the first time. If
- * any thing goes wrong during the transition, the new file will not overwrite
- * the old one. This avoids permanent damages of the existing data. */
-
-static ResponseCode password(KeyStore* keyStore, int, uid_t, Value* pw, Value*, Value*) {
-    switch (keyStore->getState()) {
-        case STATE_UNINITIALIZED: {
-            // generate master key, encrypt with password, write to file, initialize mMasterKey*.
-            return keyStore->initialize(pw);
+    int32_t get(const String16& name, uint8_t** item, size_t* itemLength) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_GET)) {
+            ALOGW("permission denied for %d: get", uid);
+            return ::PERMISSION_DENIED;
         }
-        case STATE_NO_ERROR: {
-            // rewrite master key with new password.
-            return keyStore->writeMasterKey(pw);
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling get in state: %d", state);
+            return state;
         }
-        case STATE_LOCKED: {
-            // read master key, decrypt with password, initialize mMasterKey*.
-            return keyStore->readMasterKey(pw);
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        Blob keyBlob;
+        ResponseCode responseCode = mKeyStore->get(filename, &keyBlob, TYPE_GENERIC);
+        if (responseCode != ::NO_ERROR) {
+            *item = NULL;
+            *itemLength = 0;
+            return responseCode;
         }
-    }
-    return SYSTEM_ERROR;
-}
 
-static ResponseCode lock(KeyStore* keyStore, int, uid_t, Value*, Value*, Value*) {
-    keyStore->lock();
-    return NO_ERROR;
-}
+        *item = (uint8_t*) malloc(keyBlob.getLength());
+        memcpy(*item, keyBlob.getValue(), keyBlob.getLength());
+        *itemLength = keyBlob.getLength();
 
-static ResponseCode unlock(KeyStore* keyStore, int sock, uid_t uid, Value* pw, Value* unused,
-        Value* unused2) {
-    return password(keyStore, sock, uid, pw, unused, unused2);
-}
-
-static ResponseCode zero(KeyStore* keyStore, int, uid_t, Value*, Value*, Value*) {
-    return keyStore->isEmpty() ? KEY_NOT_FOUND : NO_ERROR;
-}
-
-static ResponseCode generate(KeyStore* keyStore, int, uid_t uid, Value* keyName, Value*,
-        Value*) {
-    char filename[NAME_MAX];
-    uint8_t* data;
-    size_t dataLength;
-    int rc;
-
-    const keymaster_device_t* device = keyStore->getDevice();
-    if (device == NULL) {
-        return SYSTEM_ERROR;
+        return ::NO_ERROR;
     }
 
-    if (device->generate_keypair == NULL) {
-        return SYSTEM_ERROR;
+    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_INSERT)) {
+            ALOGW("permission denied for %d: insert", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling insert in state: %d", state);
+            return state;
+        }
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
+        return mKeyStore->put(filename, &keyBlob);
     }
 
-    keymaster_rsa_keygen_params_t rsa_params;
-    rsa_params.modulus_size = 2048;
-    rsa_params.public_exponent = 0x10001;
+    int32_t del(const String16& name) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_DELETE)) {
+            ALOGW("permission denied for %d: del", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
 
-    rc = device->generate_keypair(device, TYPE_RSA, &rsa_params, &data, &dataLength);
-    if (rc) {
-        return SYSTEM_ERROR;
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        Blob keyBlob;
+        ResponseCode responseCode = mKeyStore->get(filename, &keyBlob, TYPE_GENERIC);
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
+        return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
     }
 
-    encode_key_for_uid(filename, uid, keyName);
+    int32_t exist(const String16& name) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_EXIST)) {
+            ALOGW("permission denied for %d: exist", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
 
-    Blob keyBlob(data, dataLength, NULL, 0, TYPE_KEY_PAIR);
-    free(data);
+        String8 name8(name);
+        char filename[NAME_MAX];
 
-    return keyStore->put(filename, &keyBlob);
-}
+        encode_key_for_uid(filename, uid, name8);
 
-static ResponseCode import(KeyStore* keyStore, int, uid_t uid, Value* keyName, Value* key,
-        Value*) {
-    char filename[NAME_MAX];
-
-    encode_key_for_uid(filename, uid, keyName);
-
-    return keyStore->importKey(key, filename);
-}
-
-/*
- * 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.
- */
-static ResponseCode get_pubkey(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value*, Value*) {
-    Blob keyBlob;
-    ALOGV("get_pubkey '%s' from uid %d", ValueString(keyName).c_str(), uid);
-
-    ResponseCode responseCode = get_key_for_name(keyStore, &keyBlob, keyName, uid, TYPE_KEY_PAIR);
-    if (responseCode != NO_ERROR) {
-        return responseCode;
+        if (access(filename, R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+        return ::NO_ERROR;
     }
 
-    const keymaster_device_t* device = keyStore->getDevice();
-    if (device == NULL) {
-        return SYSTEM_ERROR;
-    }
+    int32_t saw(const String16& prefix, Vector<String16>* matches) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_SAW)) {
+            ALOGW("permission denied for %d: saw", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
 
-    if (device->get_keypair_public == NULL) {
-        ALOGE("device has no get_keypair_public implementation!");
-        return SYSTEM_ERROR;
-    }
+        DIR* dir = opendir(".");
+        if (!dir) {
+            return ::SYSTEM_ERROR;
+        }
 
-    uint8_t* data = NULL;
-    size_t dataLength;
+        const String8 prefix8(prefix);
+        char filename[NAME_MAX];
 
-    int rc = device->get_keypair_public(device, keyBlob.getValue(), keyBlob.getLength(), &data,
-            &dataLength);
-    if (rc) {
-        return SYSTEM_ERROR;
-    }
+        int n = encode_key_for_uid(filename, uid, prefix8);
 
-    send_code(sock, NO_ERROR);
-    send_message(sock, data, dataLength);
-    free(data);
+        struct dirent* file;
+        while ((file = readdir(dir)) != NULL) {
+            if (!strncmp(filename, file->d_name, n)) {
+                const char* p = &file->d_name[n];
+                size_t plen = strlen(p);
 
-    return NO_ERROR_RESPONSE_CODE_SENT;
-}
-
-static ResponseCode del_key(KeyStore* keyStore, int, uid_t uid, Value* keyName, Value*,
-        Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    Blob keyBlob;
-    ResponseCode responseCode = keyStore->get(filename, &keyBlob, TYPE_KEY_PAIR);
-    if (responseCode != NO_ERROR) {
-        return responseCode;
-    }
-
-    ResponseCode rc = NO_ERROR;
-
-    const keymaster_device_t* device = keyStore->getDevice();
-    if (device == NULL) {
-        rc = SYSTEM_ERROR;
-    } else {
-        // A device doesn't have to implement delete_keypair.
-        if (device->delete_keypair != NULL) {
-            if (device->delete_keypair(device, keyBlob.getValue(), keyBlob.getLength())) {
-                rc = SYSTEM_ERROR;
+                size_t extra = decode_key_length(p, plen);
+                char *match = (char*) malloc(extra + 1);
+                if (match != NULL) {
+                    decode_key(match, p, plen);
+                    matches->push(String16(match, extra));
+                    free(match);
+                } else {
+                    ALOGW("could not allocate match of size %zd", extra);
+                }
             }
         }
+        closedir(dir);
+
+        return ::NO_ERROR;
     }
 
-    if (rc != NO_ERROR) {
+    int32_t reset() {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_RESET)) {
+            ALOGW("permission denied for %d: reset", uid);
+            return ::PERMISSION_DENIED;
+        }
+
+        ResponseCode rc = mKeyStore->reset() ? ::NO_ERROR : ::SYSTEM_ERROR;
+
+        const keymaster_device_t* device = mKeyStore->getDevice();
+        if (device == NULL) {
+            ALOGE("No keymaster device!");
+            return ::SYSTEM_ERROR;
+        }
+
+        if (device->delete_all == NULL) {
+            ALOGV("keymaster device doesn't implement delete_all");
+            return rc;
+        }
+
+        if (device->delete_all(device)) {
+            ALOGE("Problem calling keymaster's delete_all");
+            return ::SYSTEM_ERROR;
+        }
+
         return rc;
     }
 
-    return (unlink(filename) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
-}
+    /*
+     * Here is the history. To improve the security, the parameters to generate the
+     * master key has been changed. To make a seamless transition, we update the
+     * file using the same password when the user unlock it for the first time. If
+     * any thing goes wrong during the transition, the new file will not overwrite
+     * the old one. This avoids permanent damages of the existing data.
+     */
+    int32_t password(const String16& password) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_PASSWORD)) {
+            ALOGW("permission denied for %d: password", uid);
+            return ::PERMISSION_DENIED;
+        }
 
-static ResponseCode sign(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value* data,
-        Value*) {
-    ALOGV("sign %s from uid %d", ValueString(keyName).c_str(), uid);
-    Blob keyBlob;
-    int rc;
+        const String8 password8(password);
 
-    ResponseCode responseCode = get_key_for_name(keyStore, &keyBlob, keyName, uid, TYPE_KEY_PAIR);
-    if (responseCode != NO_ERROR) {
-        return responseCode;
+        switch (mKeyStore->getState()) {
+            case ::STATE_UNINITIALIZED: {
+                // generate master key, encrypt with password, write to file, initialize mMasterKey*.
+                return mKeyStore->initialize(password8);
+            }
+            case ::STATE_NO_ERROR: {
+                // rewrite master key with new password.
+                return mKeyStore->writeMasterKey(password8);
+            }
+            case ::STATE_LOCKED: {
+                // read master key, decrypt with password, initialize mMasterKey*.
+                return mKeyStore->readMasterKey(password8);
+            }
+        }
+        return ::SYSTEM_ERROR;
     }
 
-    uint8_t* signedData;
-    size_t signedDataLength;
+    int32_t lock() {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_LOCK)) {
+            ALOGW("permission denied for %d: lock", uid);
+            return ::PERMISSION_DENIED;
+        }
 
-    const keymaster_device_t* device = keyStore->getDevice();
-    if (device == NULL) {
-        ALOGE("no keymaster device; cannot sign");
-        return SYSTEM_ERROR;
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling lock in state: %d", state);
+            return state;
+        }
+
+        mKeyStore->lock();
+        return ::NO_ERROR;
     }
 
-    if (device->sign_data == NULL) {
-        ALOGE("device doesn't implement signing");
-        return SYSTEM_ERROR;
+    int32_t unlock(const String16& pw) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_UNLOCK)) {
+            ALOGW("permission denied for %d: unlock", uid);
+            return ::PERMISSION_DENIED;
+        }
+
+        State state = checkState();
+        if (state != STATE_LOCKED) {
+            ALOGD("calling unlock when not locked");
+            return state;
+        }
+
+        const String8 password8(pw);
+        return password(pw);
     }
 
-    keymaster_rsa_sign_params_t params;
-    params.digest_type = DIGEST_NONE;
-    params.padding_type = PADDING_NONE;
+    int32_t zero() {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_ZERO)) {
+            ALOGW("permission denied for %d: zero", uid);
+            return -1;
+        }
 
-    rc = device->sign_data(device, &params, keyBlob.getValue(), keyBlob.getLength(),
-            data->value, data->length, &signedData, &signedDataLength);
-    if (rc) {
-        ALOGW("device couldn't sign data");
-        return SYSTEM_ERROR;
+        return mKeyStore->isEmpty() ? ::KEY_NOT_FOUND : ::NO_ERROR;
     }
 
-    send_code(sock, NO_ERROR);
-    send_message(sock, signedData, signedDataLength);
-    return NO_ERROR_RESPONSE_CODE_SENT;
-}
+    int32_t generate(const String16& name) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_INSERT)) {
+            ALOGW("permission denied for %d: generate", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
 
-static ResponseCode verify(KeyStore* keyStore, int, uid_t uid, Value* keyName, Value* data,
-        Value* signature) {
-    Blob keyBlob;
-    int rc;
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling generate in state: %d", state);
+            return state;
+        }
 
-    ResponseCode responseCode = get_key_for_name(keyStore, &keyBlob, keyName, uid, TYPE_KEY_PAIR);
-    if (responseCode != NO_ERROR) {
-        return responseCode;
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        uint8_t* data;
+        size_t dataLength;
+        int rc;
+
+        const keymaster_device_t* device = mKeyStore->getDevice();
+        if (device == NULL) {
+            return ::SYSTEM_ERROR;
+        }
+
+        if (device->generate_keypair == NULL) {
+            return ::SYSTEM_ERROR;
+        }
+
+        keymaster_rsa_keygen_params_t rsa_params;
+        rsa_params.modulus_size = 2048;
+        rsa_params.public_exponent = 0x10001;
+
+        rc = device->generate_keypair(device, TYPE_RSA, &rsa_params, &data, &dataLength);
+        if (rc) {
+            return ::SYSTEM_ERROR;
+        }
+
+        encode_key_for_uid(filename, uid, name8);
+
+        Blob keyBlob(data, dataLength, NULL, 0, TYPE_KEY_PAIR);
+        free(data);
+
+        return mKeyStore->put(filename, &keyBlob);
     }
 
-    const keymaster_device_t* device = keyStore->getDevice();
-    if (device == NULL) {
-        return SYSTEM_ERROR;
+    int32_t import(const String16& name, const uint8_t* data, size_t length) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_INSERT)) {
+            ALOGW("permission denied for %d: import", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling import in state: %d", state);
+            return state;
+        }
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        return mKeyStore->importKey(data, length, filename);
     }
 
-    if (device->verify_data == NULL) {
-        return SYSTEM_ERROR;
+    int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out,
+            size_t* outLength) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_SIGN)) {
+            ALOGW("permission denied for %d: saw", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling sign in state: %d", state);
+            return state;
+        }
+
+        Blob keyBlob;
+        String8 name8(name);
+
+        ALOGV("sign %s from uid %d", name8.string(), uid);
+        int rc;
+
+        ResponseCode responseCode = get_key_for_name(mKeyStore, &keyBlob, name8, uid, ::TYPE_KEY_PAIR);
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
+
+        const keymaster_device_t* device = mKeyStore->getDevice();
+        if (device == NULL) {
+            ALOGE("no keymaster device; cannot sign");
+            return ::SYSTEM_ERROR;
+        }
+
+        if (device->sign_data == NULL) {
+            ALOGE("device doesn't implement signing");
+            return ::SYSTEM_ERROR;
+        }
+
+        keymaster_rsa_sign_params_t params;
+        params.digest_type = DIGEST_NONE;
+        params.padding_type = PADDING_NONE;
+
+        rc = device->sign_data(device, &params, keyBlob.getValue(), keyBlob.getLength(),
+                data, length, out, outLength);
+        if (rc) {
+            ALOGW("device couldn't sign data");
+            return ::SYSTEM_ERROR;
+        }
+
+        return ::NO_ERROR;
     }
 
-    keymaster_rsa_sign_params_t params;
-    params.digest_type = DIGEST_NONE;
-    params.padding_type = PADDING_NONE;
+    int32_t verify(const String16& name, const uint8_t* data, size_t dataLength,
+            const uint8_t* signature, size_t signatureLength) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_VERIFY)) {
+            ALOGW("permission denied for %d: verify", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
 
-    rc = device->verify_data(device, &params, keyBlob.getValue(), keyBlob.getLength(),
-            data->value, data->length, signature->value, signature->length);
-    if (rc) {
-        return SYSTEM_ERROR;
-    } else {
-        return NO_ERROR;
-    }
-}
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling verify in state: %d", state);
+            return state;
+        }
 
-static ResponseCode grant(KeyStore* keyStore, int, uid_t uid, Value* keyName,
-        Value* granteeData, Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    if (access(filename, R_OK) == -1) {
-        return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
-    }
+        Blob keyBlob;
+        String8 name8(name);
+        int rc;
 
-    keyStore->addGrant(filename, granteeData);
-    return NO_ERROR;
-}
+        ResponseCode responseCode = get_key_for_name(mKeyStore, &keyBlob, name8, uid, TYPE_KEY_PAIR);
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
 
-static ResponseCode ungrant(KeyStore* keyStore, int, uid_t uid, Value* keyName,
-        Value* granteeData, Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    if (access(filename, R_OK) == -1) {
-        return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
-    }
+        const keymaster_device_t* device = mKeyStore->getDevice();
+        if (device == NULL) {
+            return ::SYSTEM_ERROR;
+        }
 
-    return keyStore->removeGrant(filename, granteeData) ? NO_ERROR : KEY_NOT_FOUND;
-}
+        if (device->verify_data == NULL) {
+            return ::SYSTEM_ERROR;
+        }
 
-static ResponseCode getmtime(KeyStore*, int sock, uid_t uid, Value* keyName,
-        Value*, Value*) {
-    char filename[NAME_MAX];
-    encode_key_for_uid(filename, uid, keyName);
-    if (access(filename, R_OK) == -1) {
-        return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
-    }
+        keymaster_rsa_sign_params_t params;
+        params.digest_type = DIGEST_NONE;
+        params.padding_type = PADDING_NONE;
 
-    int fd = open(filename, O_NOFOLLOW, O_RDONLY);
-    if (fd < 0) {
-        return SYSTEM_ERROR;
-    }
-
-    struct stat s;
-    int ret = fstat(fd, &s);
-    close(fd);
-    if (ret == -1) {
-        return SYSTEM_ERROR;
-    }
-
-    uint8_t *data;
-    int dataLength = asprintf(reinterpret_cast<char**>(&data), "%lu", s.st_mtime);
-    if (dataLength < 0) {
-        return SYSTEM_ERROR;
-    }
-
-    send_code(sock, NO_ERROR);
-    send_message(sock, data, dataLength);
-    free(data);
-
-    return NO_ERROR_RESPONSE_CODE_SENT;
-}
-
-/* Here are the permissions, actions, users, and the main function. */
-enum perm {
-    P_TEST     = 1 << TEST,
-    P_GET      = 1 << GET,
-    P_INSERT   = 1 << INSERT,
-    P_DELETE   = 1 << DELETE,
-    P_EXIST    = 1 << EXIST,
-    P_SAW      = 1 << SAW,
-    P_RESET    = 1 << RESET,
-    P_PASSWORD = 1 << PASSWORD,
-    P_LOCK     = 1 << LOCK,
-    P_UNLOCK   = 1 << UNLOCK,
-    P_ZERO     = 1 << ZERO,
-    P_SIGN     = 1 << SIGN,
-    P_VERIFY   = 1 << VERIFY,
-    P_GRANT    = 1 << GRANT,
-};
-
-static const int MAX_PARAM = 3;
-
-static const State STATE_ANY = (State) 0;
-
-static struct action {
-    ResponseCode (*run)(KeyStore* keyStore, int sock, uid_t uid, Value* param1, Value* param2,
-            Value* param3);
-    uint8_t code;
-    State state;
-    uint32_t perm;
-    int lengths[MAX_PARAM];
-} actions[] = {
-    {test,       CommandCodes[TEST],       STATE_ANY,      P_TEST,     {0, 0, 0}},
-    {get,        CommandCodes[GET],        STATE_NO_ERROR, P_GET,      {KEY_SIZE, 0, 0}},
-    {insert,     CommandCodes[INSERT],     STATE_NO_ERROR, P_INSERT,   {KEY_SIZE, VALUE_SIZE, 0}},
-    {del,        CommandCodes[DELETE],     STATE_ANY,      P_DELETE,   {KEY_SIZE, 0, 0}},
-    {exist,      CommandCodes[EXIST],      STATE_ANY,      P_EXIST,    {KEY_SIZE, 0, 0}},
-    {saw,        CommandCodes[SAW],        STATE_ANY,      P_SAW,      {KEY_SIZE, 0, 0}},
-    {reset,      CommandCodes[RESET],      STATE_ANY,      P_RESET,    {0, 0, 0}},
-    {password,   CommandCodes[PASSWORD],   STATE_ANY,      P_PASSWORD, {PASSWORD_SIZE, 0, 0}},
-    {lock,       CommandCodes[LOCK],       STATE_NO_ERROR, P_LOCK,     {0, 0, 0}},
-    {unlock,     CommandCodes[UNLOCK],     STATE_LOCKED,   P_UNLOCK,   {PASSWORD_SIZE, 0, 0}},
-    {zero,       CommandCodes[ZERO],       STATE_ANY,      P_ZERO,     {0, 0, 0}},
-    {generate,   CommandCodes[GENERATE],   STATE_NO_ERROR, P_INSERT,   {KEY_SIZE, 0, 0}},
-    {import,     CommandCodes[IMPORT],     STATE_NO_ERROR, P_INSERT,   {KEY_SIZE, VALUE_SIZE, 0}},
-    {sign,       CommandCodes[SIGN],       STATE_NO_ERROR, P_SIGN,     {KEY_SIZE, VALUE_SIZE, 0}},
-    {verify,     CommandCodes[VERIFY],     STATE_NO_ERROR, P_VERIFY,   {KEY_SIZE, VALUE_SIZE, VALUE_SIZE}},
-    {get_pubkey, CommandCodes[GET_PUBKEY], STATE_NO_ERROR, P_GET,      {KEY_SIZE, 0, 0}},
-    {del_key,    CommandCodes[DEL_KEY],    STATE_ANY,      P_DELETE,   {KEY_SIZE, 0, 0}},
-    {grant,      CommandCodes[GRANT],      STATE_NO_ERROR, P_GRANT,    {KEY_SIZE, KEY_SIZE, 0}},
-    {ungrant,    CommandCodes[UNGRANT],    STATE_NO_ERROR, P_GRANT,    {KEY_SIZE, KEY_SIZE, 0}},
-    {getmtime,   CommandCodes[GETMTIME],   STATE_ANY,      P_SAW,      {KEY_SIZE, 0, 0}},
-    {NULL,       0,                        STATE_ANY,      0,          {0, 0, 0}},
-};
-
-static struct user {
-    uid_t uid;
-    uid_t euid;
-    uint32_t perms;
-} users[] = {
-    {AID_SYSTEM,  (uid_t)(~0), (uint32_t)(~0)},
-    {AID_VPN,     AID_SYSTEM,  P_GET | P_SIGN | P_VERIFY },
-    {AID_WIFI,    AID_SYSTEM,  P_GET | P_SIGN | P_VERIFY },
-    {AID_ROOT,    AID_SYSTEM,  P_GET},
-    {(uid_t)(~0), (uid_t)(~0), P_TEST | P_GET | P_INSERT | P_DELETE | P_EXIST | P_SAW |
-                               P_SIGN | P_VERIFY},
-};
-
-static ResponseCode process(KeyStore* keyStore, int sock, uid_t uid, int8_t code) {
-    struct user* user = users;
-    struct action* action = actions;
-    int i;
-
-    while (~user->uid && user->uid != (uid % AID_USER)) {
-        ++user;
-    }
-    while (action->code && action->code != code) {
-        ++action;
-    }
-    if (!action->code) {
-        return UNDEFINED_ACTION;
-    }
-    if (!(action->perm & user->perms)) {
-        return PERMISSION_DENIED;
-    }
-    if (action->state != STATE_ANY && action->state != keyStore->getState()) {
-        return (ResponseCode) keyStore->getState();
-    }
-    if (~user->euid) {
-        uid = user->euid;
-    }
-    Value params[MAX_PARAM];
-    for (i = 0; i < MAX_PARAM && action->lengths[i] != 0; ++i) {
-        params[i].length = recv_message(sock, params[i].value, action->lengths[i]);
-        if (params[i].length < 0) {
-            return PROTOCOL_ERROR;
+        rc = device->verify_data(device, &params, keyBlob.getValue(), keyBlob.getLength(),
+                data, dataLength, signature, signatureLength);
+        if (rc) {
+            return ::SYSTEM_ERROR;
+        } else {
+            return ::NO_ERROR;
         }
     }
-    if (!recv_end_of_file(sock)) {
-        return PROTOCOL_ERROR;
+
+    /*
+     * 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) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_GET)) {
+            ALOGW("permission denied for %d: get_pubkey", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling get_pubkey in state: %d", state);
+            return state;
+        }
+
+        Blob keyBlob;
+        String8 name8(name);
+
+        ALOGV("get_pubkey '%s' from uid %d", name8.string(), uid);
+
+        ResponseCode responseCode = get_key_for_name(mKeyStore, &keyBlob, name8, uid,
+                TYPE_KEY_PAIR);
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
+
+        const keymaster_device_t* device = mKeyStore->getDevice();
+        if (device == NULL) {
+            return ::SYSTEM_ERROR;
+        }
+
+        if (device->get_keypair_public == NULL) {
+            ALOGE("device has no get_keypair_public implementation!");
+            return ::SYSTEM_ERROR;
+        }
+
+        int rc = device->get_keypair_public(device, keyBlob.getValue(), keyBlob.getLength(), pubkey,
+                pubkeyLength);
+        if (rc) {
+            return ::SYSTEM_ERROR;
+        }
+
+        return ::NO_ERROR;
     }
-    return action->run(keyStore, sock, uid, &params[0], &params[1], &params[2]);
-}
+
+    int32_t del_key(const String16& name) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_DELETE)) {
+            ALOGW("permission denied for %d: del_key", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        Blob keyBlob;
+        ResponseCode responseCode = mKeyStore->get(filename, &keyBlob, ::TYPE_KEY_PAIR);
+        if (responseCode != ::NO_ERROR) {
+            return responseCode;
+        }
+
+        ResponseCode rc = ::NO_ERROR;
+
+        const keymaster_device_t* device = mKeyStore->getDevice();
+        if (device == NULL) {
+            rc = ::SYSTEM_ERROR;
+        } else {
+            // A device doesn't have to implement delete_keypair.
+            if (device->delete_keypair != NULL) {
+                if (device->delete_keypair(device, keyBlob.getValue(), keyBlob.getLength())) {
+                    rc = ::SYSTEM_ERROR;
+                }
+            }
+        }
+
+        if (rc != ::NO_ERROR) {
+            return rc;
+        }
+
+        return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
+    }
+
+    int32_t grant(const String16& name, int32_t granteeUid) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_GRANT)) {
+            ALOGW("permission denied for %d: grant", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling grant in state: %d", state);
+            return state;
+        }
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        if (access(filename, R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+
+        mKeyStore->addGrant(filename, granteeUid);
+        return ::NO_ERROR;
+    }
+
+    int32_t ungrant(const String16& name, int32_t granteeUid) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_GRANT)) {
+            ALOGW("permission denied for %d: ungrant", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        State state = checkState();
+        if (state != STATE_NO_ERROR) {
+            ALOGD("calling ungrant in state: %d", state);
+            return state;
+        }
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        if (access(filename, R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+
+        return mKeyStore->removeGrant(filename, granteeUid) ? ::NO_ERROR : ::KEY_NOT_FOUND;
+    }
+
+    int64_t getmtime(const String16& name) {
+        uid_t uid = IPCThreadState::self()->getCallingUid();
+        if (!has_permission(uid, P_GET)) {
+            ALOGW("permission denied for %d: getmtime", uid);
+            return ::PERMISSION_DENIED;
+        }
+        uid = get_keystore_euid(uid);
+
+        String8 name8(name);
+        char filename[NAME_MAX];
+
+        encode_key_for_uid(filename, uid, name8);
+
+        if (access(filename, R_OK) == -1) {
+            return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
+        }
+
+        int fd = open(filename, O_NOFOLLOW, O_RDONLY);
+        if (fd < 0) {
+            return ::SYSTEM_ERROR;
+        }
+
+        struct stat s;
+        int ret = fstat(fd, &s);
+        close(fd);
+        if (ret == -1) {
+            return ::SYSTEM_ERROR;
+        }
+
+        return s.st_mtime;
+    }
+
+private:
+    inline State checkState() {
+        return mKeyStore->getState();
+    }
+
+    ::KeyStore* mKeyStore;
+};
+
+}; // namespace android
 
 int main(int argc, char* argv[]) {
-    int controlSocket = android_get_control_socket("keystore");
     if (argc < 2) {
         ALOGE("A directory must be specified!");
         return 1;
@@ -1430,48 +1604,21 @@
         return 1;
     }
 
-    if (listen(controlSocket, 3) == -1) {
-        ALOGE("listen: %s", strerror(errno));
-        return 1;
-    }
-
-    signal(SIGPIPE, SIG_IGN);
-
     KeyStore keyStore(&entropy, dev);
-    int sock;
-    while ((sock = accept(controlSocket, NULL, 0)) != -1) {
-        struct timeval tv;
-        tv.tv_sec = 3;
-        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
-
-        struct ucred cred;
-        socklen_t size = sizeof(cred);
-        int credResult = getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cred, &size);
-        if (credResult != 0) {
-            ALOGW("getsockopt: %s", strerror(errno));
-        } else {
-            int8_t request;
-            if (recv_code(sock, &request)) {
-                State old_state = keyStore.getState();
-                ResponseCode response = process(&keyStore, sock, cred.uid, request);
-                if (response == NO_ERROR_RESPONSE_CODE_SENT) {
-                    response = NO_ERROR;
-                } else {
-                    send_code(sock, response);
-                }
-                ALOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
-                     cred.uid,
-                     request, response,
-                     old_state, keyStore.getState(),
-                     keyStore.getRetry());
-            }
-        }
-        close(sock);
+    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;
     }
-    ALOGE("accept: %s", strerror(errno));
+
+    /*
+     * 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;
 }