eclair snapshot
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 3daf44e..15a199f 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -1,22 +1,36 @@
+#
+# 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.
+#
+
ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
+
include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- netkeystore.c keymgmt.c
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, system-core)/cutils \
- external/openssl/include
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils libssl
-
-LOCAL_STATIC_LIBRARIES :=
-
+LOCAL_SRC_FILES := keystore.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
LOCAL_MODULE:= keystore
-
include $(BUILD_EXECUTABLE)
-endif # !simulator))
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := keystore_cli.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
+LOCAL_MODULE:= keystore_cli
+LOCAL_MODULE_TAGS := debug
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/cmds/keystore/certtool.h b/cmds/keystore/certtool.h
deleted file mode 100644
index aefad66..0000000
--- a/cmds/keystore/certtool.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-**
-** Copyright 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.
-*/
-
-#ifndef __CERTTOOL_H__
-#define __CERTTOOL_H__
-
-#include <stdio.h>
-#include <string.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-
-#include "common.h"
-#include "netkeystore.h"
-
-#define CERT_NAME_LEN (2 * MAX_KEY_NAME_LENGTH + 2)
-
-/*
- * The specific function 'get_cert' is used in daemons to get the key value
- * from keystore. Caller should allocate the buffer and the length of the buffer
- * should be MAX_KEY_VALUE_LENGTH.
- */
-static inline int get_cert(const char *certname, unsigned char *value, int *size)
-{
- int count, fd, ret = -1;
- LPC_MARSHAL cmd;
- char delimiter[] = "_";
- char *namespace, *keyname;
- char *context = NULL;
- char cname[CERT_NAME_LEN];
-
- if ((certname == NULL) || (value == NULL)) {
- LOGE("get_cert: certname or value is null\n");
- return -1;
- }
-
- if (strlcpy(cname, certname, CERT_NAME_LEN) >= CERT_NAME_LEN) {
- LOGE("get_cert: keyname is too long\n");
- return -1;
- }
-
- fd = socket_local_client(SOCKET_PATH,
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
- if (fd == -1) {
- LOGE("Keystore service is not up and running.\n");
- return -1;
- }
-
- cmd.opcode = GET;
- if (((namespace = strtok_r(cname, delimiter, &context)) == NULL) ||
- ((keyname = strtok_r(NULL, delimiter, &context)) == NULL)) {
- goto err;
- }
- if ((cmd.len = snprintf((char*)cmd.data, BUFFER_MAX, "%s %s", namespace, keyname))
- > (2 * MAX_KEY_NAME_LENGTH + 1)) goto err;
-
- if (write_marshal(fd, &cmd)) {
- LOGE("Incorrect command or command line is too long.\n");
- goto err;
- }
- if (read_marshal(fd, &cmd)) {
- LOGE("Failed to read the result.\n");
- goto err;
- }
-
- // copy the result if succeeded.
- if (!cmd.retcode && cmd.len <= BUFFER_MAX) {
- memcpy(value, cmd.data, cmd.len);
- ret = 0;
- *size = cmd.len;
- }
-err:
- close(fd);
- return ret;
-}
-
-#endif
diff --git a/cmds/keystore/common.h b/cmds/keystore/common.h
deleted file mode 100644
index a18114e..0000000
--- a/cmds/keystore/common.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-**
-** Copyright 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.
-*/
-
-#ifndef __COMMON_H__
-#define __COMMON_H__
-
-#define SOCKET_PATH "keystore"
-#define KEYSTORE_DIR "/data/misc/keystore/"
-
-#define READ_TIMEOUT 3
-#define MAX_KEY_NAME_LENGTH 64
-#define MAX_NAMESPACE_LENGTH MAX_KEY_NAME_LENGTH
-#define MAX_KEY_VALUE_LENGTH 4096
-
-#define BUFFER_MAX MAX_KEY_VALUE_LENGTH
-
-typedef enum {
- BOOTUP,
- UNINITIALIZED,
- LOCKED,
- UNLOCKED,
-} KEYSTORE_STATE;
-
-typedef enum {
- LOCK,
- UNLOCK,
- PASSWD,
- GETSTATE,
- LISTKEYS,
- GET,
- PUT,
- REMOVE,
- RESET,
- MAX_OPCODE
-} KEYSTORE_OPCODE;
-
-typedef struct {
- uint32_t len;
- union {
- uint32_t opcode;
- uint32_t retcode;
- };
- unsigned char data[BUFFER_MAX + 1];
-} LPC_MARSHAL;
-
-#endif
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
deleted file mode 100644
index 9a1f845..0000000
--- a/cmds/keystore/keymgmt.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <cutils/log.h>
-
-#include "common.h"
-#include "keymgmt.h"
-
-static int retry_count = 0;
-static unsigned char iv[IV_LEN];
-static KEYSTORE_STATE state = BOOTUP;
-static AES_KEY encryptKey, decryptKey;
-
-inline void unlock_keystore(unsigned char *master_key)
-{
- AES_set_encrypt_key(master_key, AES_KEY_LEN, &encryptKey);
- AES_set_decrypt_key(master_key, AES_KEY_LEN, &decryptKey);
- memset(master_key, 0, sizeof(master_key));
- state = UNLOCKED;
-}
-
-inline void lock_keystore()
-{
- memset(&encryptKey, 0 , sizeof(AES_KEY));
- memset(&decryptKey, 0 , sizeof(AES_KEY));
- state = LOCKED;
-}
-
-inline void get_encrypt_key(char *passwd, AES_KEY *key)
-{
- unsigned char user_key[USER_KEY_LEN];
- gen_key(passwd, user_key, USER_KEY_LEN);
- AES_set_encrypt_key(user_key, AES_KEY_LEN, key);
-}
-
-inline void get_decrypt_key(char *passwd, AES_KEY *key)
-{
- unsigned char user_key[USER_KEY_LEN];
- gen_key(passwd, user_key, USER_KEY_LEN);
- AES_set_decrypt_key(user_key, AES_KEY_LEN, key);
-}
-
-static int gen_random_blob(unsigned char *key, int size)
-{
- int ret = 0;
- int fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1) return -1;
- if (read(fd, key, size) != size) ret = -1;
- close(fd);
- return ret;
-}
-
-static int encrypt_n_save(AES_KEY *enc_key, DATA_BLOB *blob,
- const char *keyfile)
-{
- int size, fd, ret = -1;
- unsigned char enc_blob[MAX_BLOB_LEN];
- char tmpfile[KEYFILE_LEN];
-
- if ((keyfile == NULL) || (strlen(keyfile) >= (KEYFILE_LEN - 4))) {
- LOGE("keyfile name is too long or null");
- return -1;
- }
- strcpy(tmpfile, keyfile);
- strcat(tmpfile, ".tmp");
-
- // prepare the blob
- if (IV_LEN > USER_KEY_LEN) {
- LOGE("iv length is too long.");
- return -1;
- }
- memcpy(blob->iv, iv, IV_LEN);
- blob->blob_size = get_blob_size(blob);
- if (blob->blob_size > MAX_BLOB_LEN) {
- LOGE("blob data size is too large.");
- return -1;
- }
- memcpy(enc_blob, blob->blob, blob->blob_size);
- AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char *)blob->blob,
- blob->blob_size, enc_key, iv, AES_ENCRYPT);
- // write to keyfile
- size = data_blob_size(blob);
- if ((fd = open(tmpfile, O_CREAT|O_RDWR)) == -1) return -1;
- if (write(fd, blob, size) == size) ret = 0;
- close(fd);
- if (!ret) {
- unlink(keyfile);
- rename(tmpfile, keyfile);
- chmod(keyfile, 0440);
- }
- return ret;
-}
-
-static int load_n_decrypt(const char *keyname, const char *keyfile,
- AES_KEY *key, DATA_BLOB *blob)
-{
- int fd, ret = -1;
- if ((fd = open(keyfile, O_RDONLY)) == -1) return -1;
- // get the encrypted blob and iv
- if ((read(fd, blob->iv, sizeof(blob->iv)) != sizeof(blob->iv)) ||
- (read(fd, &blob->blob_size, sizeof(uint32_t)) != sizeof(uint32_t)) ||
- (blob->blob_size > MAX_BLOB_LEN)) {
- goto err;
- } else {
- unsigned char enc_blob[MAX_BLOB_LEN];
- if (read(fd, enc_blob, blob->blob_size) !=
- (int) blob->blob_size) goto err;
- // decrypt the blob
- AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char*)blob->blob,
- blob->blob_size, key, blob->iv, AES_DECRYPT);
- if (strcmp(keyname, (char*)blob->keyname) == 0) ret = 0;
- }
-err:
- close(fd);
- return ret;
-}
-
-static int store_master_key(char *upasswd, unsigned char *master_key)
-{
- AES_KEY key;
- DATA_BLOB blob;
-
- // prepare the blob
- if (strlen(MASTER_KEY_TAG) >= USER_KEY_LEN) return -1;
- strlcpy(blob.keyname, MASTER_KEY_TAG, USER_KEY_LEN);
- blob.value_size = USER_KEY_LEN;
- if (USER_KEY_LEN > MAX_KEY_VALUE_LENGTH) {
- LOGE("master_key length is too long.");
- return -1;
- }
- memcpy((void*)blob.value, (const void*)master_key, USER_KEY_LEN);
-
- // generate the encryption key
- get_encrypt_key(upasswd, &key);
- return encrypt_n_save(&key, &blob, MASTER_KEY);
-}
-
-static int get_master_key(char *upasswd, unsigned char *master_key)
-{
- AES_KEY key;
- int size, ret = 0;
- DATA_BLOB blob;
-
- get_decrypt_key(upasswd, &key);
- ret = load_n_decrypt(MASTER_KEY_TAG, MASTER_KEY, &key, &blob);
- if (blob.value_size > USER_KEY_LEN) {
- LOGE("the blob's value size is too large");
- return -1;
- }
- if (!ret) memcpy(master_key, blob.value, blob.value_size);
- return ret;
-}
-
-static int create_master_key(char *upasswd)
-{
- int ret;
- unsigned char mpasswd[AES_KEY_LEN];
- unsigned char master_key[USER_KEY_LEN];
-
- gen_random_blob(mpasswd, AES_KEY_LEN);
- gen_key((char*)mpasswd, master_key, USER_KEY_LEN);
- if ((ret = store_master_key(upasswd, master_key)) == 0) {
- unlock_keystore(master_key);
- }
- memset(master_key, 0, USER_KEY_LEN);
- memset(mpasswd, 0, AES_KEY_LEN);
-
- return ret;
-}
-
-static int change_passwd(char *data)
-{
- unsigned char master_key[USER_KEY_LEN];
- char *old_pass, *new_pass = NULL, *p, *delimiter=" ";
- int ret, count = 0;
- char *context = NULL;
-
- old_pass = p = strtok_r(data, delimiter, &context);
- while (p != NULL) {
- count++;
- new_pass = p;
- p = strtok_r(NULL, delimiter, &context);
- }
- if (count != 2) return -1;
- if (strlen(new_pass) < MIN_PASSWD_LENGTH) return -1;
- if ((ret = get_master_key(old_pass, master_key)) == 0) {
- ret = store_master_key(new_pass, master_key);
- retry_count = 0;
- } else {
- ret = MAX_RETRY_COUNT - ++retry_count;
- if (ret == 0) {
- retry_count = 0;
- LOGE("passwd:reach max retry count, reset the keystore now.");
- reset_keystore();
- return -1;
- }
-
- }
- return ret;
-}
-
-int remove_key(const char *namespace, const char *keyname)
-{
- char keyfile[KEYFILE_LEN];
-
- if (state != UNLOCKED) return -state;
- if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
- (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
- LOGE("keyname is too long.");
- return -1;
- }
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- return unlink(keyfile);
-}
-
-int put_key(const char *namespace, const char *keyname,
- unsigned char *data, int size)
-{
- DATA_BLOB blob;
- uint32_t real_size;
- char keyfile[KEYFILE_LEN];
-
- if (state != UNLOCKED) {
- LOGE("Can not store key with current state %d\n", state);
- return -state;
- }
- if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
- (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
- LOGE("keyname is too long.");
- return -1;
- }
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- strcpy(blob.keyname, keyname);
- blob.value_size = size;
- if (size > MAX_KEY_VALUE_LENGTH) {
- LOGE("the data size is too large.");
- return -1;
- }
- memcpy(blob.value, data, size);
- return encrypt_n_save(&encryptKey, &blob, keyfile);
-}
-
-int get_key(const char *namespace, const char *keyname,
- unsigned char *data, int *size)
-{
- int ret;
- DATA_BLOB blob;
- uint32_t blob_size;
- char keyfile[KEYFILE_LEN];
-
- if (state != UNLOCKED) {
- LOGE("Can not retrieve key value with current state %d\n", state);
- return -state;
- }
- if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
- (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
- LOGE("keyname is too long.");
- return -1;
- }
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
- if (!ret) {
- if ((blob.value_size > MAX_KEY_VALUE_LENGTH)) {
- LOGE("blob value size is too large.");
- ret = -1;
- } else {
- *size = blob.value_size;
- memcpy(data, blob.value, *size);
- }
- }
- return ret;
-}
-
-int list_keys(const char *namespace, char reply[BUFFER_MAX])
-{
- DIR *d;
- struct dirent *de;
-
- if (state != UNLOCKED) {
- LOGE("Can not list key with current state %d\n", state);
- return -1;
- }
-
- if (!namespace || ((d = opendir("."))) == NULL) {
- LOGE("cannot open keystore dir or namespace is null\n");
- return -1;
- }
-
- if (strlen(namespace) >= MAX_KEY_NAME_LENGTH) {
- LOGE("namespace is too long.");
- return -1;
- }
-
- reply[0] = 0;
- while ((de = readdir(d))) {
- char *prefix, *name, *keyfile = de->d_name;
- char *context = NULL;
-
- if (de->d_type != DT_REG) continue;
- if ((prefix = strtok_r(keyfile, NAME_DELIMITER, &context))
- == NULL) continue;
- if (strcmp(prefix, namespace)) continue;
- if ((name = strtok_r(NULL, NAME_DELIMITER, &context)) == NULL) continue;
- // append the key name into reply
- if (reply[0] != 0) strlcat(reply, " ", BUFFER_MAX);
- if (strlcat(reply, name, BUFFER_MAX) >= BUFFER_MAX) {
- LOGE("too many files under keystore directory\n");
- return -1;
- }
- }
- closedir(d);
- return 0;
-}
-
-int passwd(char *data)
-{
- if (state == UNINITIALIZED) {
- if (strchr(data, ' ')) return -1;
- if (strlen(data) < MIN_PASSWD_LENGTH) return -1;
- return create_master_key(data);
- }
- return change_passwd(data);
-}
-
-int lock()
-{
- switch(state) {
- case UNLOCKED:
- lock_keystore();
- case LOCKED:
- return 0;
- default:
- return -1;
- }
-}
-
-int unlock(char *passwd)
-{
- unsigned char master_key[USER_KEY_LEN];
- int ret = get_master_key(passwd, master_key);
- if (!ret) {
- unlock_keystore(master_key);
- retry_count = 0;
- } else {
- ret = MAX_RETRY_COUNT - ++retry_count;
- if (ret == 0) {
- retry_count = 0;
- LOGE("unlock:reach max retry count, reset the keystore now.");
- reset_keystore();
- return -1;
- }
- }
- return ret;
-}
-
-KEYSTORE_STATE get_state()
-{
- return state;
-}
-
-int reset_keystore()
-{
- int ret = 0;
- DIR *d;
- struct dirent *de;
-
- if ((d = opendir(".")) == NULL) {
- LOGE("cannot open keystore dir\n");
- return -1;
- }
- while ((de = readdir(d))) {
- if (unlink(de->d_name) != 0) ret = -1;
- }
- closedir(d);
- state = UNINITIALIZED;
- if (ret == 0) {
- LOGI("keystore is reset.");
- } else {
- LOGI("keystore can not be cleaned up entirely.");
- }
- return ret;
-}
-
-int init_keystore(const char *dir)
-{
- int fd;
-
- if (dir) mkdir(dir, 0770);
- if (!dir || chdir(dir)) {
- LOGE("Can not open/create the keystore directory %s\n",
- dir ? dir : "(null)");
- return -1;
- }
- gen_random_blob(iv, IV_LEN);
- if ((fd = open(MASTER_KEY, O_RDONLY)) == -1) {
- state = UNINITIALIZED;
- return 0;
- }
- close(fd);
- state = LOCKED;
- return 0;
-}
diff --git a/cmds/keystore/keymgmt.h b/cmds/keystore/keymgmt.h
deleted file mode 100644
index 0e928db..0000000
--- a/cmds/keystore/keymgmt.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-#ifndef __KEYMGMT_H__
-#define __KEYMGMT_H__
-
-#define MASTER_KEY_TAG "master_key"
-#define MASTER_KEY ".keymaster"
-#define MAX_PATH_LEN 128
-#define SALT "Android Keystore 0.1"
-#define NAME_DELIMITER "_"
-#define KEYFILE_NAME "%s"NAME_DELIMITER"%s"
-#define KEYGEN_ITER 1024
-#define AES_KEY_LEN 128
-#define USER_KEY_LEN (AES_KEY_LEN/8)
-#define IV_LEN USER_KEY_LEN
-#define MAX_RETRY_COUNT 6
-#define MIN_PASSWD_LENGTH 8
-
-#define gen_key(passwd, key, len) \
- PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), \
- (unsigned char*)SALT, \
- strlen(SALT), KEYGEN_ITER, \
- len, key)
-
-#define KEYFILE_LEN MAX_NAMESPACE_LENGTH + MAX_KEY_NAME_LENGTH + 6
-
-#define get_blob_size(blob) \
- (((blob->value_size + sizeof(uint32_t) + MAX_KEY_NAME_LENGTH \
- + USER_KEY_LEN - 1) / USER_KEY_LEN) * USER_KEY_LEN)
-
-#define MAX_BLOB_LEN ((MAX_KEY_VALUE_LENGTH + MAX_KEY_NAME_LENGTH + \
- sizeof(uint32_t) + USER_KEY_LEN - 1) / USER_KEY_LEN)\
- * USER_KEY_LEN
-
-#define data_blob_size(blob) USER_KEY_LEN + sizeof(uint32_t) + blob->blob_size
-
-typedef struct {
- unsigned char iv[USER_KEY_LEN];
- uint32_t blob_size;
- union {
- unsigned char blob[1];
- struct {
- uint32_t value_size;
- char keyname[MAX_KEY_NAME_LENGTH];
- unsigned char value[MAX_KEY_VALUE_LENGTH];
- } __attribute__((packed));
- };
-} DATA_BLOB;
-
-typedef struct {
- char tag[USER_KEY_LEN];
- unsigned char master_key[USER_KEY_LEN];
-} MASTER_BLOB;
-
-int put_key(const char *namespace, const char *keyname,
- unsigned char *data, int size);
-int get_key(const char *namespace, const char *keyname,
- unsigned char *data, int *size);
-int remove_key(const char *namespace, const char *keyname);
-int list_keys(const char *namespace, char reply[BUFFER_MAX]);
-int passwd(char *data);
-int lock();
-int unlock(char *passwd);
-KEYSTORE_STATE get_state();
-int reset_keystore();
-int init_keystore(const char *dir);
-
-#endif
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
new file mode 100644
index 0000000..ba74c78
--- /dev/null
+++ b/cmds/keystore/keystore.c
@@ -0,0 +1,542 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.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/evp.h>
+#include <openssl/md5.h>
+
+#define LOG_TAG "keystore"
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include "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
+ * 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 120
+#define VALUE_SIZE 32768
+#define PASSWORD_SIZE VALUE_SIZE
+
+/* 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
+ * two bits of the character. The second byte encodes the rest of the bits into
+ * [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, uint8_t *in, int length)
+{
+ int i;
+ for (i = length; i > 0; --i, ++in, ++out) {
+ if (*in >= '0' && *in <= '~') {
+ *out = *in;
+ } else {
+ *out = '+' + (*in >> 6);
+ *++out = '0' + (*in & 0x3F);
+ ++length;
+ }
+ }
+ *out = 0;
+ return length;
+}
+
+static int decode_key(uint8_t *out, char *in, int length)
+{
+ int i;
+ for (i = 0; i < length; ++i, ++in, ++out) {
+ if (*in >= '0' && *in <= '~') {
+ *out = *in;
+ } else {
+ *out = (*in - '+') << 6;
+ *out |= (*++in - '0') & 0x3F;
+ --length;
+ }
+ }
+ *out = 0;
+ return length;
+}
+
+/* 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 the_socket = -1;
+
+static int recv_code(int8_t *code)
+{
+ return recv(the_socket, code, 1, 0) == 1;
+}
+
+static int recv_message(uint8_t *message, int length)
+{
+ uint8_t bytes[2];
+ if (recv(the_socket, &bytes[0], 1, 0) != 1 ||
+ recv(the_socket, &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(the_socket, &message[offset], length - offset, 0);
+ if (n <= 0) {
+ return -1;
+ }
+ offset += n;
+ }
+ }
+ return length;
+}
+
+static int recv_end_of_file()
+{
+ uint8_t byte;
+ return recv(the_socket, &byte, 1, 0) == 0;
+}
+
+static void send_code(int8_t code)
+{
+ send(the_socket, &code, 1, 0);
+}
+
+static void send_message(uint8_t *message, int length)
+{
+ uint16_t bytes = htons(length);
+ send(the_socket, &bytes, 2, 0);
+ send(the_socket, message, length, 0);
+}
+
+/* Here is the file format. Values are encrypted by AES CBC, and MD5 is used to
+ * compute their checksums. To make the files portable, the length is stored in
+ * network order. Note that the first four bytes are reserved for future use and
+ * are always set to zero in this implementation. */
+
+static int the_entropy = -1;
+
+static struct __attribute__((packed)) {
+ uint32_t reserved;
+ uint8_t vector[AES_BLOCK_SIZE];
+ uint8_t encrypted[0];
+ uint8_t digest[MD5_DIGEST_LENGTH];
+ uint8_t digested[0];
+ int32_t length;
+ uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
+} blob;
+
+static int8_t encrypt_blob(char *name, AES_KEY *aes_key)
+{
+ uint8_t vector[AES_BLOCK_SIZE];
+ int length = blob.length;
+ int fd;
+
+ if (read(the_entropy, vector, AES_BLOCK_SIZE) != AES_BLOCK_SIZE) {
+ return SYSTEM_ERROR;
+ }
+
+ length += blob.value - blob.digested;
+ blob.length = htonl(blob.length);
+ MD5(blob.digested, length, blob.digest);
+
+ length += blob.digested - blob.encrypted;
+ length = (length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
+ memcpy(vector, blob.vector, AES_BLOCK_SIZE);
+ AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key, vector,
+ AES_ENCRYPT);
+
+ blob.reserved = 0;
+ length += blob.encrypted - (uint8_t *)&blob;
+
+ fd = open(".tmp", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1 || write(fd, &blob, length) != length) {
+ return SYSTEM_ERROR;
+ }
+ close(fd);
+ return rename(".tmp", name) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t decrypt_blob(char *name, AES_KEY *aes_key)
+{
+ int fd = open(name, O_RDONLY);
+ int length;
+
+ if (fd == -1) {
+ return (errno == ENOENT) ? KEY_NOT_FOUND : SYSTEM_ERROR;
+ }
+ length = read(fd, &blob, sizeof(blob));
+ close(fd);
+
+ length -= blob.encrypted - (uint8_t *)&blob;
+ if (length < blob.value - blob.encrypted || length % AES_BLOCK_SIZE != 0) {
+ return VALUE_CORRUPTED;
+ }
+
+ AES_cbc_encrypt(blob.encrypted, blob.encrypted, length, aes_key,
+ blob.vector, AES_DECRYPT);
+ length -= blob.digested - blob.encrypted;
+ if (!memcmp(blob.digest, MD5(blob.digested, length, NULL),
+ MD5_DIGEST_LENGTH)) {
+ return VALUE_CORRUPTED;
+ }
+
+ length -= blob.value - blob.digested;
+ blob.length = ntohl(blob.length);
+ return (length < blob.length) ? VALUE_CORRUPTED : NO_ERROR;
+}
+
+/* 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. */
+
+#define MAX_PARAM 2
+#define MAX_RETRY 4
+
+static uid_t uid = -1;
+static int8_t state = UNINITIALIZED;
+static int8_t retry = MAX_RETRY;
+
+static struct {
+ int length;
+ uint8_t value[VALUE_SIZE];
+} params[MAX_PARAM];
+
+static AES_KEY encryption_key;
+static AES_KEY decryption_key;
+
+static int8_t test()
+{
+ return state;
+}
+
+static int8_t get()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ n = decrypt_blob(name, &decryption_key);
+ if (n != NO_ERROR) {
+ return n;
+ }
+ send_code(NO_ERROR);
+ send_message(blob.value, blob.length);
+ return -NO_ERROR;
+}
+
+static int8_t insert()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ blob.length = params[1].length;
+ memcpy(blob.value, params[1].value, params[1].length);
+ return encrypt_blob(name, &encryption_key);
+}
+
+static int8_t delete()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ return (unlink(name) && errno != ENOENT) ? SYSTEM_ERROR : NO_ERROR;
+}
+
+static int8_t exist()
+{
+ char name[NAME_MAX];
+ int n = sprintf(name, "%u_", uid);
+ encode_key(&name[n], params[0].value, params[0].length);
+ if (access(name, R_OK) == -1) {
+ return (errno != ENOENT) ? SYSTEM_ERROR : KEY_NOT_FOUND;
+ }
+ return NO_ERROR;
+}
+
+static int8_t saw()
+{
+ DIR *dir = opendir(".");
+ struct dirent *file;
+ char name[NAME_MAX];
+ int n;
+
+ if (!dir) {
+ return SYSTEM_ERROR;
+ }
+ n = sprintf(name, "%u_", uid);
+ n += encode_key(&name[n], params[0].value, params[0].length);
+ send_code(NO_ERROR);
+ while ((file = readdir(dir)) != NULL) {
+ if (!strncmp(name, file->d_name, n)) {
+ char *p = &file->d_name[n];
+ params[0].length = decode_key(params[0].value, p, strlen(p));
+ send_message(params[0].value, params[0].length);
+ }
+ }
+ closedir(dir);
+ return -NO_ERROR;
+}
+
+static int8_t reset()
+{
+ DIR *dir = opendir(".");
+ struct dirent *file;
+
+ memset(&encryption_key, 0, sizeof(encryption_key));
+ memset(&decryption_key, 0, sizeof(decryption_key));
+ state = UNINITIALIZED;
+ retry = MAX_RETRY;
+
+ if (!dir) {
+ return SYSTEM_ERROR;
+ }
+ while ((file = readdir(dir)) != NULL) {
+ unlink(file->d_name);
+ }
+ closedir(dir);
+ return NO_ERROR;
+}
+
+#define MASTER_KEY_FILE ".masterkey"
+#define MASTER_KEY_SIZE 16
+
+static void generate_key(uint8_t *key, uint8_t *password, int length)
+{
+ PKCS5_PBKDF2_HMAC_SHA1((char *)password, length, (uint8_t *)"keystore",
+ sizeof("keystore"), 1024, MASTER_KEY_SIZE, key);
+}
+
+static int8_t password()
+{
+ uint8_t key[MASTER_KEY_SIZE];
+ AES_KEY aes_key;
+ int n;
+
+ if (state == UNINITIALIZED) {
+ blob.length = MASTER_KEY_SIZE;
+ if (read(the_entropy, blob.value, MASTER_KEY_SIZE) != MASTER_KEY_SIZE) {
+ return SYSTEM_ERROR;
+ }
+ } else {
+ generate_key(key, params[0].value, params[0].length);
+ AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+ n = decrypt_blob(MASTER_KEY_FILE, &aes_key);
+ if (n == SYSTEM_ERROR) {
+ return SYSTEM_ERROR;
+ }
+ if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) {
+ if (retry <= 0) {
+ reset();
+ return UNINITIALIZED;
+ }
+ return WRONG_PASSWORD + --retry;
+ }
+ }
+
+ if (params[1].length == -1) {
+ memcpy(key, blob.value, MASTER_KEY_SIZE);
+ } else {
+ generate_key(key, params[1].value, params[1].length);
+ AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &aes_key);
+ memcpy(key, blob.value, MASTER_KEY_SIZE);
+ n = encrypt_blob(MASTER_KEY_FILE, &aes_key);
+ }
+
+ if (n == NO_ERROR) {
+ AES_set_encrypt_key(key, MASTER_KEY_SIZE * 8, &encryption_key);
+ AES_set_decrypt_key(key, MASTER_KEY_SIZE * 8, &decryption_key);
+ state = NO_ERROR;
+ retry = MAX_RETRY;
+ }
+ return n;
+}
+
+static int8_t lock()
+{
+ memset(&encryption_key, 0, sizeof(encryption_key));
+ memset(&decryption_key, 0, sizeof(decryption_key));
+ state = LOCKED;
+ return NO_ERROR;
+}
+
+static int8_t unlock()
+{
+ params[1].length = -1;
+ return password();
+}
+
+/* Here are the permissions, actions, users, and the main function. */
+
+enum perm {
+ TEST = 1,
+ GET = 2,
+ INSERT = 4,
+ DELETE = 8,
+ EXIST = 16,
+ SAW = 32,
+ RESET = 64,
+ PASSWORD = 128,
+ LOCK = 256,
+ UNLOCK = 512,
+};
+
+static struct action {
+ int8_t (*run)();
+ int8_t code;
+ int8_t state;
+ uint32_t perm;
+ int lengths[MAX_PARAM];
+} actions[] = {
+ {test, 't', 0, TEST, {0}},
+ {get, 'g', NO_ERROR, GET, {KEY_SIZE}},
+ {insert, 'i', NO_ERROR, INSERT, {KEY_SIZE, VALUE_SIZE}},
+ {delete, 'd', 0, DELETE, {KEY_SIZE}},
+ {exist, 'e', 0, EXIST, {KEY_SIZE}},
+ {saw, 's', 0, SAW, {KEY_SIZE}},
+ {reset, 'r', 0, RESET, {0}},
+ {password, 'p', 0, PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}},
+ {lock, 'l', NO_ERROR, LOCK, {0}},
+ {unlock, 'u', LOCKED, UNLOCK, {PASSWORD_SIZE}},
+ {NULL, 0 , 0, 0, {0}},
+};
+
+static struct user {
+ uid_t uid;
+ uid_t euid;
+ uint32_t perms;
+} users[] = {
+ {AID_SYSTEM, 0, ~GET},
+ {AID_VPN, AID_SYSTEM, GET},
+ {AID_WIFI, AID_SYSTEM, GET},
+ {0, 0, TEST | GET | INSERT | DELETE | EXIST | SAW},
+};
+
+static int8_t process(int8_t code) {
+ struct user *user = users;
+ struct action *action = actions;
+ int i;
+
+ while (user->uid && user->uid != uid) {
+ ++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 && action->state != state) {
+ return state;
+ }
+ if (user->euid) {
+ uid = user->euid;
+ }
+ for (i = 0; i < MAX_PARAM && action->lengths[i]; ++i) {
+ params[i].length = recv_message(params[i].value, action->lengths[i]);
+ if (params[i].length == -1) {
+ return PROTOCOL_ERROR;
+ }
+ }
+ if (!recv_end_of_file()) {
+ return PROTOCOL_ERROR;
+ }
+ return action->run();
+}
+
+#define RANDOM_DEVICE "/dev/urandom"
+
+int main(int argc, char **argv)
+{
+ int control_socket = android_get_control_socket("keystore");
+ if (argc < 2) {
+ LOGE("A directory must be specified!");
+ return 1;
+ }
+ if (chdir(argv[1]) == -1) {
+ LOGE("chdir: %s: %s", argv[1], strerror(errno));
+ return 1;
+ }
+ if ((the_entropy = open(RANDOM_DEVICE, O_RDONLY)) == -1) {
+ LOGE("open: %s: %s", RANDOM_DEVICE, strerror(errno));
+ return 1;
+ }
+ if (listen(control_socket, 3) == -1) {
+ LOGE("listen: %s", strerror(errno));
+ return 1;
+ }
+
+ signal(SIGPIPE, SIG_IGN);
+ if (access(MASTER_KEY_FILE, R_OK) == 0) {
+ state = LOCKED;
+ }
+
+ while ((the_socket = accept(control_socket, NULL, 0)) != -1) {
+ struct timeval tv = {.tv_sec = 3};
+ struct ucred cred;
+ socklen_t size = sizeof(cred);
+ int8_t request;
+
+ setsockopt(the_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ setsockopt(the_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+
+ if (getsockopt(the_socket, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
+ LOGW("getsockopt: %s", strerror(errno));
+ } else if (recv_code(&request)) {
+ int8_t old_state = state;
+ int8_t response;
+ uid = cred.uid;
+
+ if ((response = process(request)) > 0) {
+ send_code(response);
+ response = -response;
+ }
+
+ LOGI("uid: %d action: %c -> %d state: %d -> %d retry: %d",
+ cred.uid, request, -response, old_state, state, retry);
+ }
+ close(the_socket);
+ }
+ LOGE("accept: %s", strerror(errno));
+ return 1;
+}
diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h
new file mode 100644
index 0000000..5ef51e9
--- /dev/null
+++ b/cmds/keystore/keystore.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef __KEYSTORE_H__
+#define __KEYSTORE_H__
+
+enum response_code {
+ NO_ERROR = 1,
+ LOCKED = 2,
+ UNINITIALIZED = 3,
+ SYSTEM_ERROR = 4,
+ PROTOCOL_ERROR = 5,
+ PERMISSION_DENIED = 6,
+ KEY_NOT_FOUND = 7,
+ VALUE_CORRUPTED = 8,
+ UNDEFINED_ACTION = 9,
+ WRONG_PASSWORD = 10,
+};
+
+#endif
diff --git a/cmds/keystore/keystore_cli.c b/cmds/keystore/keystore_cli.c
new file mode 100644
index 0000000..e8afb5a
--- /dev/null
+++ b/cmds/keystore/keystore_cli.c
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <cutils/sockets.h>
+
+#include "keystore.h"
+
+char *responses[256] = {
+ [NO_ERROR] = "No error",
+ [LOCKED] = "Locked",
+ [UNINITIALIZED] = "Uninitialized",
+ [SYSTEM_ERROR] = "System error",
+ [PROTOCOL_ERROR] = "Protocol error",
+ [PERMISSION_DENIED] = "Permission denied",
+ [KEY_NOT_FOUND] = "Key not found",
+ [VALUE_CORRUPTED] = "Value corrupted",
+ [UNDEFINED_ACTION] = "Undefined action",
+ [WRONG_PASSWORD] = "Wrong password (last chance)",
+ [WRONG_PASSWORD + 1] = "Wrong password (2 tries left)",
+ [WRONG_PASSWORD + 2] = "Wrong password (3 tries left)",
+ [WRONG_PASSWORD + 3] = "Wrong password (4 tries left)",
+};
+
+#define MAX_RESPONSE (WRONG_PASSWORD + 3)
+
+int main(int argc, char **argv)
+{
+ uint8_t bytes[65536];
+ uint8_t code;
+ int sock, i;
+
+ if (argc < 2) {
+ printf("Usage: %s action [parameter ...]\n", argv[0]);
+ return 0;
+ }
+
+ sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (sock == -1) {
+ puts("Failed to connect");
+ return 1;
+ }
+
+ send(sock, argv[1], 1, 0);
+ for (i = 2; i < argc; ++i) {
+ uint16_t length = strlen(argv[i]);
+ bytes[0] = length >> 8;
+ bytes[1] = length;
+ send(sock, &bytes, 2, 0);
+ send(sock, argv[i], length, 0);
+ }
+ shutdown(sock, SHUT_WR);
+
+ if (recv(sock, &code, 1, 0) != 1) {
+ puts("Failed to receive");
+ return 1;
+ }
+ printf("%d %s\n", code , responses[code] ? responses[code] : "Unknown");
+ while ((i = recv(sock, &bytes[0], 1, 0)) == 1) {
+ int length;
+ int offset;
+ if ((i = recv(sock, &bytes[1], 1, 0)) != 1) {
+ puts("Failed to receive");
+ return 1;
+ }
+ length = bytes[0] << 8 | bytes[1];
+ for (offset = 0; offset < length; offset += i) {
+ i = recv(sock, &bytes[offset], length - offset, 0);
+ if (i <= 0) {
+ puts("Failed to receive");
+ return 1;
+ }
+ }
+ fwrite(bytes, 1, length, stdout);
+ puts("");
+ }
+ return 0;
+}
diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h
index 7665e81..0e7e1ae 100644
--- a/cmds/keystore/keystore_get.h
+++ b/cmds/keystore/keystore_get.h
@@ -1,53 +1,69 @@
/*
-**
-** Copyright 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.
-*/
+ * 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.
+ */
#ifndef __KEYSTORE_GET_H__
#define __KEYSTORE_GET_H__
#include <stdio.h>
-#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
-#include "certtool.h"
+#include <cutils/sockets.h>
-/* This function is provided to native components to get values from keystore.
- * Users are required to link against libcutils. If something goes wrong, NULL
- * is returned. Otherwise it returns the value in dynamically allocated memory
- * and sets the size if the pointer is not NULL. One can release the memory by
- * calling free(). */
-static char *keystore_get(const char *key, int *size)
+#define KEYSTORE_MESSAGE_SIZE 65535
+
+/* This function is provided for native components to get values from keystore.
+ * Users are required to link against libcutils. The lengths of keys and values
+ * are limited to KEYSTORE_MESSAGE_SIZE. This function returns the length of
+ * the requested value or -1 if something goes wrong. */
+static int keystore_get(const char *key, char *value)
{
- char buffer[MAX_KEY_VALUE_LENGTH];
- char *value;
- int length;
+ int length = strlen(key);
+ uint8_t bytes[2] = {length >> 8, length};
+ uint8_t code = 'g';
+ int sock;
- if (get_cert(key, (unsigned char *)buffer, &length) != 0) {
- return NULL;
+ if (length > KEYSTORE_MESSAGE_SIZE) {
+ return -1;
}
- value = malloc(length + 1);
- if (!value) {
- return NULL;
+ sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (sock == -1) {
+ return -1;
}
- memcpy(value, buffer, length);
- value[length] = 0;
- if (size) {
- *size = length;
+ if (send(sock, &code, 1, 0) == 1 && send(sock, bytes, 2, 0) == 2 &&
+ send(sock, key, length, 0) == length && shutdown(sock, SHUT_WR) == 0 &&
+ recv(sock, &code, 1, 0) == 1 && code == /* NO_ERROR */ 1 &&
+ recv(sock, &bytes[0], 1, 0) == 1 && recv(sock, &bytes[1], 1, 0) == 1) {
+ int offset = 0;
+ length = bytes[0] << 8 | bytes[1];
+ while (offset < length) {
+ int n = recv(sock, &value[offset], length - offset, 0);
+ if (n <= 0) {
+ length = -1;
+ break;
+ }
+ offset += n;
+ }
}
- return value;
+ close(sock);
+ return length;
}
#endif
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
deleted file mode 100644
index 637e0d8..0000000
--- a/cmds/keystore/netkeystore.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-** Copyright 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_TAG "keystore"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <utime.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <private/android_filesystem_config.h>
-
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include "netkeystore.h"
-#include "keymgmt.h"
-
-#define DBG 1
-#define CMD_PUT_WITH_FILE "putfile"
-
-typedef void CMD_FUNC(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
-
-struct cmdinfo {
- const char *name;
- CMD_FUNC *func;
-};
-
-static CMD_FUNC do_lock;
-static CMD_FUNC do_unlock;
-static CMD_FUNC do_passwd;
-static CMD_FUNC do_get_state;;
-static CMD_FUNC do_listkeys;
-static CMD_FUNC do_get_key;
-static CMD_FUNC do_put_key;
-static CMD_FUNC do_remove_key;
-static CMD_FUNC do_reset_keystore;
-
-#define str(x) #x
-
-struct cmdinfo cmds[] = {
- { str(LOCK), do_lock },
- { str(UNLOCK), do_unlock },
- { str(PASSWD), do_passwd },
- { str(GETSTATE), do_get_state },
- { str(LISTKEYS), do_listkeys },
- { str(GET), do_get_key },
- { str(PUT), do_put_key },
- { str(REMOVE), do_remove_key },
- { str(RESET), do_reset_keystore },
-};
-
-static struct ucred cr;
-
-static int check_get_perm(int uid)
-{
- if (uid == AID_WIFI || uid == AID_VPN) return 0;
- return -1;
-}
-
-static int check_reset_perm(int uid)
-{
- if (uid == AID_SYSTEM) return 0;
- return -1;
-}
-
-static int parse_keyname(char *name, uint32_t len,
- char *namespace, char *keyname)
-{
- int count = 0;
- char *c = namespace, *p = namespace, *t = name;
-
- if (!name || !namespace || !keyname) return -1;
- while (t < name + len && (*t != 0)) {
- if (*t == ' ') {
- if (c == keyname) return -1;
- *p = count = 0;
- c = p = keyname;
- t++;
- } else {
- if (!isalnum(*t)) return -1;
- *p++ = *t++;
- // also check if the keyname/namespace is too long.
- if (count++ == MAX_KEY_NAME_LENGTH) return -1;
- }
- }
- *p = 0;
- return 0;
-}
-
-// args of passwd():
-// firstPassword - for the first time
-// oldPassword newPassword - for changing the password
-static void do_passwd(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = passwd((char*)cmd->data);
-}
-
-// args of lock():
-// no argument
-static void do_lock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = lock();
-}
-
-// args of unlock():
-// password
-static void do_unlock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = unlock((char*)cmd->data);
-}
-
-// args of get_state():
-// no argument
-static void do_get_state(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = get_state();
-}
-
-// args of listkeys():
-// namespace
-static void do_listkeys(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- reply->retcode = list_keys((const char*)cmd->data, (char*)reply->data);
- if (!reply->retcode) reply->len = strlen((char*)reply->data);
-}
-
-// args of get():
-// namespace keyname
-static void do_get_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- char namespace[MAX_KEY_NAME_LENGTH];
- char keyname[MAX_KEY_NAME_LENGTH];
-
- if (check_get_perm(cr.uid)) {
- LOGE("uid %d doesn't have the permission to get key value\n", cr.uid);
- reply->retcode = -1;
- return;
- }
-
- if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
- reply->retcode = -1;
- } else {
- reply->retcode = get_key(namespace, keyname, reply->data,
- (int*)&reply->len);
- }
-}
-
-static int get_value_index(LPC_MARSHAL *cmd)
-{
- uint32_t count = 0, i;
- for (i = 0 ; i < cmd->len ; ++i) {
- if (cmd->data[i] == ' ') {
- if (++count == 2) return ++i;
- }
- }
- return -1;
-}
-
-// args of put():
-// namespace keyname keyvalue
-static void do_put_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- char namespace[MAX_KEY_NAME_LENGTH];
- char keyname[MAX_KEY_NAME_LENGTH];
-
- int p = get_value_index(cmd);
- if (p == -1) {
- reply->retcode = -1;
- } else {
- unsigned char *value;
- if (parse_keyname((char*)cmd->data, p - 1, namespace, keyname)) {
- reply->retcode = -1;
- return;
- }
- value = &cmd->data[p];
- int len = cmd->len - p;
- reply->retcode = put_key(namespace, keyname, value, len);
- }
-}
-
-// args of remove_key():
-// namespace keyname
-static void do_remove_key(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- char namespace[MAX_KEY_NAME_LENGTH];
- char keyname[MAX_KEY_NAME_LENGTH];
- if (parse_keyname((char*)cmd->data, cmd->len, namespace, keyname)) {
- reply->retcode = -1;
- return;
- }
- reply->retcode = remove_key(namespace, keyname);
-}
-
-// args of reset_keystore():
-// no argument
-static void do_reset_keystore(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- if (check_reset_perm(cr.uid)) {
- LOGE("uid %d doesn't have the permission to reset the keystore\n",
- cr.uid);
- reply->retcode = -1;
- return;
- }
- reply->retcode = reset_keystore();
-}
-
-static void execute(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
-{
- uint32_t cmd_max = sizeof(cmds)/sizeof(struct cmdinfo);
-
- if (cmd->opcode >= cmd_max) {
- LOGE("the opcode (%d) is not valid", cmd->opcode);
- reply->retcode = -1;
- return;
- }
- cmds[cmd->opcode].func(cmd, reply);
-}
-
-static int set_read_timeout(int socket)
-{
- struct timeval tv;
- tv.tv_sec = READ_TIMEOUT;
- if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
- {
- LOGE("setsockopt failed");
- return -1;
- }
- return 0;
-}
-
-static int append_input_from_file(const char *filename, LPC_MARSHAL *cmd)
-{
- int fd, len, ret = 0;
-
- // get opcode of the function put()
- if ((fd = open(filename, O_RDONLY)) == -1) {
- fprintf(stderr, "Can not open file %s\n", filename);
- return -1;
- }
- cmd->data[cmd->len] = ' ';
- cmd->len++;
- len = read(fd, cmd->data + cmd->len, BUFFER_MAX - cmd->len);
- if (len < 0 || (len == (int)(BUFFER_MAX - cmd->len))) {
- ret = -1;
- } else {
- cmd->len += len;
- }
- close(fd);
- return ret;
-}
-
-static int flatten_str_args(int argc, const char **argv, LPC_MARSHAL *cmd)
-{
- int i, len = 0;
- char *buf = (char*)cmd->data;
- buf[0] = 0;
- for (i = 0 ; i < argc ; ++i) {
- if (i == 0) {
- len = strlcpy(buf, argv[i], BUFFER_MAX);
- } else {
- len += snprintf(buf + len, BUFFER_MAX - len, " %s", argv[i]);
- }
- if (len >= BUFFER_MAX) return -1;
- }
- if (len) cmd->len = len;
- return 0;
-}
-
-static int parse_cmd(int argc, const char **argv, LPC_MARSHAL *cmd)
-{
- uint32_t i, len = 0;
- uint32_t cmd_max = sizeof(cmds)/sizeof(cmds[0]);
-
- for (i = 0 ; i < cmd_max ; ++i) {
- if (!strcasecmp(argv[0], cmds[i].name)) break;
- }
-
- if (i == cmd_max) {
- // check if this is a command to put the key value with a file.
- if (strcmp(argv[0], CMD_PUT_WITH_FILE) != 0) return -1;
- cmd->opcode = PUT;
- if (argc != 4) {
- fprintf(stderr, "%s args\n\tnamespace keyname filename\n",
- argv[0]);
- return -1;
- }
- if (flatten_str_args(argc - 2, argv + 1, cmd)) return -1;
- return append_input_from_file(argv[3], cmd);
- } else {
- cmd->opcode = i;
- return flatten_str_args(argc - 1, argv + 1, cmd);
- }
-}
-
-static int shell_command(const int argc, const char **argv)
-{
- int fd, i;
- LPC_MARSHAL cmd;
-
- if (parse_cmd(argc, argv , &cmd)) {
- fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
- }
- fd = socket_local_client(SOCKET_PATH,
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
- if (fd == -1) {
- fprintf(stderr, "Keystore service is not up and running.\n");
- exit(1);
- }
-
- if (write_marshal(fd, &cmd)) {
- fprintf(stderr, "Incorrect command or command line is too long.\n");
- exit(1);
- }
- if (read_marshal(fd, &cmd)) {
- fprintf(stderr, "Failed to read the result.\n");
- exit(1);
- }
- cmd.data[cmd.len] = 0;
- fprintf(stdout, "%s\n", (cmd.retcode == 0) ? "Succeeded!" : "Failed!");
- if (cmd.len) fprintf(stdout, "\t%s\n", (char*)cmd.data);
- close(fd);
- return 0;
-}
-
-int main(const int argc, const char *argv[])
-{
- struct sockaddr addr;
- socklen_t alen;
- int lsocket, s;
- LPC_MARSHAL cmd, reply;
-
- if (argc > 1) {
- return shell_command(argc - 1, argv + 1);
- }
-
- if (init_keystore(KEYSTORE_DIR)) {
- LOGE("Can not initialize the keystore, the directory exist?\n");
- exit(1);
- }
-
- lsocket = android_get_control_socket(SOCKET_PATH);
- if (lsocket < 0) {
- LOGE("Failed to get socket from environment: %s\n", strerror(errno));
- exit(1);
- }
- if (listen(lsocket, 5)) {
- LOGE("Listen on socket failed: %s\n", strerror(errno));
- exit(1);
- }
- fcntl(lsocket, F_SETFD, FD_CLOEXEC);
- memset(&reply, 0, sizeof(LPC_MARSHAL));
-
- for (;;) {
- socklen_t cr_size = sizeof(cr);
- alen = sizeof(addr);
- s = accept(lsocket, &addr, &alen);
-
- /* retrieve the caller info here */
- if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
- close(s);
- LOGE("Unable to recieve socket options\n");
- continue;
- }
-
- if (s < 0) {
- LOGE("Accept failed: %s\n", strerror(errno));
- continue;
- }
- fcntl(s, F_SETFD, FD_CLOEXEC);
- if (set_read_timeout(s)) {
- close(s);
- continue;
- }
-
- // read the command, execute and send the result back.
- if(read_marshal(s, &cmd)) goto err;
- if (DBG) LOGD("new connection\n");
- execute(&cmd, &reply);
- write_marshal(s, &reply);
-err:
- memset(&reply, 0, sizeof(LPC_MARSHAL));
- if (DBG) LOGD("closing connection\n");
- close(s);
- }
-
- return 0;
-}
diff --git a/cmds/keystore/netkeystore.h b/cmds/keystore/netkeystore.h
deleted file mode 100644
index a87a667..0000000
--- a/cmds/keystore/netkeystore.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-**
-** Copyright 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.
-*/
-
-#ifndef __NETKEYSTORE_H__
-#define __NETKEYSTORE_H__
-
-#include <stdio.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-
-#include "common.h"
-
-static inline int readx(int s, void *_buf, int count)
-{
- char *buf = _buf;
- int n = 0, r;
- if (count < 0) return -1;
- while (n < count) {
- r = read(s, buf + n, count - n);
- if (r < 0) {
- if (errno == EINTR) continue;
- LOGE("read error: %s\n", strerror(errno));
- return -1;
- }
- if (r == 0) {
- LOGE("eof\n");
- return -1; /* EOF */
- }
- n += r;
- }
- return 0;
-}
-
-static inline int writex(int s, const void *_buf, int count)
-{
- const char *buf = _buf;
- int n = 0, r;
- if (count < 0) return -1;
- while (n < count) {
- r = write(s, buf + n, count - n);
- if (r < 0) {
- if (errno == EINTR) continue;
- LOGE("write error: %s\n", strerror(errno));
- return -1;
- }
- n += r;
- }
- return 0;
-}
-
-static inline int read_marshal(int s, LPC_MARSHAL *cmd)
-{
- if (readx(s, cmd, 2 * sizeof(uint32_t))) {
- LOGE("failed to read header\n");
- return -1;
- }
- if (cmd->len > BUFFER_MAX) {
- LOGE("invalid size %d\n", cmd->len);
- return -1;
- }
- if (readx(s, cmd->data, cmd->len)) {
- LOGE("failed to read data\n");
- return -1;
- }
- cmd->data[cmd->len] = 0;
- return 0;
-}
-
-static inline int write_marshal(int s, LPC_MARSHAL *cmd)
-{
- if (writex(s, cmd, 2 * sizeof(uint32_t))) {
- LOGE("failed to write marshal header\n");
- return -1;
- }
- if (writex(s, cmd->data, cmd->len)) {
- LOGE("failed to write marshal data\n");
- return -1;
- }
- return 0;
-}
-
-#endif
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
deleted file mode 100644
index 33541cc..0000000
--- a/cmds/keystore/tests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# define the KEYSTORE_TESTS environment variable to build the test programs
-ifdef KEYSTORE_TESTS
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
-LOCAL_SHARED_LIBRARIES := libcutils libssl
-LOCAL_MODULE:= netkeystore_test
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := external/openssl/include \
- frameworks/base/cmds/keystore
-EXTRA_CFLAGS := -g -O0 -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING
-include $(BUILD_EXECUTABLE)
-
-endif #KEYSTORE_TESTS
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
deleted file mode 100644
index e7e686b..0000000
--- a/cmds/keystore/tests/netkeystore_test.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "keymgmt.h"
-
-typedef int FUNC_PTR();
-typedef struct {
- const char *name;
- FUNC_PTR *func;
-} TESTFUNC;
-
-#define FUNC_NAME(x) { #x, test_##x }
-#define FUNC_BODY(x) int test_##x()
-
-#define TEST_PASSWD "12345678"
-#define TEST_NPASSWD "11111111"
-#define TEST_DIR "/data/local/tmp/keystore"
-#define READONLY_DIR "/proc/keystore"
-#define TEST_NAMESPACE "test"
-#define TEST_KEYNAME "key"
-#define TEST_KEYNAME2 "key2"
-#define TEST_KEYVALUE "ANDROID"
-
-void setup()
-{
- if (init_keystore(TEST_DIR) != 0) {
- fprintf(stderr, "Can not create the test directory %s\n", TEST_DIR);
- exit(-1);
- }
-}
-
-void teardown()
-{
- reset_keystore();
- rmdir(TEST_DIR);
-}
-
-FUNC_BODY(init_keystore)
-{
- if (init_keystore(READONLY_DIR) == 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(reset_keystore)
-{
- chdir("/procx");
- if (reset_keystore() == 0) return -1;
- chdir(TEST_DIR);
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(get_state)
-{
- if (get_state() != UNINITIALIZED) return -1;
- passwd(TEST_PASSWD);
- if (get_state() != UNLOCKED) return -1;
- lock();
- if (get_state() != LOCKED) return -1;
- reset_keystore();
- if (get_state() != UNINITIALIZED) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(passwd)
-{
- char buf[512];
-
- if (passwd(" 23432dsfsdf") == 0) return -1;
- if (passwd("dsfsdf") == 0) return -1;
- passwd(TEST_PASSWD);
- lock();
- if (unlock("55555555") == 0) return -1;
- if (unlock(TEST_PASSWD) != 0) return -1;
-
- // change the password
- sprintf(buf, "%s %s", "klfdjdsklfjg", "abcdefghi");
- if (passwd(buf) == 0) return -1;
-
- sprintf(buf, "%s %s", TEST_PASSWD, TEST_NPASSWD);
- if (passwd(buf) != 0) return -1;
- lock();
-
- if (unlock(TEST_PASSWD) == 0) return -1;
- if (unlock(TEST_NPASSWD) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(lock)
-{
- if (lock() == 0) return -1;
- passwd(TEST_PASSWD);
- if (lock() != 0) return -1;
- if (lock() != 0) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(unlock)
-{
- int i = MAX_RETRY_COUNT;
- passwd(TEST_PASSWD);
- lock();
- while (i > 1) {
- if (unlock(TEST_NPASSWD) != --i) return -1;
- }
- if (unlock(TEST_NPASSWD) != -1) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(put_key)
-{
- int i = 0;
- char keyname[512];
-
- if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE)) == 0) return -1;
- passwd(TEST_PASSWD);
- if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE)) != 0) return -1;
-
- for(i = 0; i < 500; i++) keyname[i] = 'K';
- keyname[i] = 0;
- if (put_key(TEST_NAMESPACE, keyname, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE)) == 0) return -1;
- if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- MAX_KEY_VALUE_LENGTH + 1) == 0) return -1;
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(get_key)
-{
- int size;
- unsigned char data[MAX_KEY_VALUE_LENGTH];
-
- if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) == 0) return -1;
-
- passwd(TEST_PASSWD);
- put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
- if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) != 0) return -1;
- if (memcmp(data, TEST_KEYVALUE, size) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(remove_key)
-{
- if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
-
- passwd(TEST_PASSWD);
- if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
-
- put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
- if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-FUNC_BODY(list_keys)
-{
- int i;
- char buf[128];
- char reply[BUFFER_MAX];
-
- for(i = 0; i < 100; i++) buf[i] = 'K';
- buf[i] = 0;
-
- if (list_keys(TEST_NAMESPACE, reply) == 0) return -1;
-
- passwd(TEST_PASSWD);
- if (list_keys(buf, reply) == 0) return -1;
-
- if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
- if (strcmp(reply, "") != 0) return -1;
-
- put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
- if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
- if (strcmp(reply, TEST_KEYNAME) != 0) return -1;
-
- put_key(TEST_NAMESPACE, TEST_KEYNAME2, (unsigned char *)TEST_KEYVALUE,
- strlen(TEST_KEYVALUE));
-
- if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
- sprintf(buf, "%s %s", TEST_KEYNAME2, TEST_KEYNAME);
- if (strcmp(reply, buf) != 0) return -1;
-
- return EXIT_SUCCESS;
-}
-
-TESTFUNC all_tests[] = {
- FUNC_NAME(init_keystore),
- FUNC_NAME(reset_keystore),
- FUNC_NAME(get_state),
- FUNC_NAME(passwd),
- FUNC_NAME(lock),
- FUNC_NAME(unlock),
- FUNC_NAME(put_key),
- FUNC_NAME(get_key),
- FUNC_NAME(remove_key),
- FUNC_NAME(list_keys),
-};
-
-int main(int argc, char **argv) {
- int i, ret;
- for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
- setup();
- if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
- fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
- return ret;
- } else {
- fprintf(stderr, "function %s PASSED!\n", all_tests[i].name);
- }
- teardown();
- }
- return EXIT_SUCCESS;
-}
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
index 521eb2b..6a72d10 100644
--- a/cmds/runtime/Android.mk
+++ b/cmds/runtime/Android.mk
@@ -10,6 +10,7 @@
LOCAL_SHARED_LIBRARIES := \
libutils \
+ libbinder \
libandroid_runtime \
libcutils \
libui \
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
index 758a95c..b2bef07 100644
--- a/cmds/runtime/ServiceManager.cpp
+++ b/cmds/runtime/ServiceManager.cpp
@@ -9,9 +9,9 @@
#include <utils/Debug.h>
#include <utils/Log.h>
-#include <utils/Parcel.h>
+#include <binder/Parcel.h>
#include <utils/String8.h>
-#include <utils/ProcessState.h>
+#include <binder/ProcessState.h>
#include <private/utils/Static.h>
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
index d09cec8..090ca6d 100644
--- a/cmds/runtime/ServiceManager.h
+++ b/cmds/runtime/ServiceManager.h
@@ -4,7 +4,7 @@
#ifndef ANDROID_SERVICE_MANAGER_H
#define ANDROID_SERVICE_MANAGER_H
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 476f38a..21e0e4d 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -7,9 +7,11 @@
#include "ServiceManager.h"
#include "SignalHandler.h"
-#include <utils.h>
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
+#include <utils/threads.h>
+#include <utils/Errors.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
#include <utils/Log.h>
#include <cutils/zygote.h>
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
index 37c3d94..bfa58a1 100644
--- a/cmds/surfaceflinger/Android.mk
+++ b/cmds/surfaceflinger/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SHARED_LIBRARIES := \
libsurfaceflinger \
+ libbinder \
libutils
LOCAL_C_INCLUDES := \
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index 7c89578..d650721 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -1,6 +1,6 @@
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <SurfaceFlinger.h>