diff options
| -rw-r--r-- | cmds/keystore/commands.c | 170 | ||||
| -rw-r--r-- | cmds/keystore/keystore.c | 100 | ||||
| -rw-r--r-- | cmds/keystore/keystore.h | 37 | ||||
| -rw-r--r-- | keystore/java/android/security/Keystore.java | 120 | 
4 files changed, 341 insertions, 86 deletions
| diff --git a/cmds/keystore/commands.c b/cmds/keystore/commands.c index e53cece..17dd060 100644 --- a/cmds/keystore/commands.c +++ b/cmds/keystore/commands.c @@ -1,5 +1,5 @@  /* -** Copyright 2008, The Android Open Source Project +** 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. @@ -30,7 +30,8 @@ static DIR *open_keystore(const char *dir)      return d;  } -static int list_files(const char *dir, char reply[REPLY_MAX]) { +static int list_files(const char *dir, char reply[REPLY_MAX]) +{      struct dirent *de;      DIR *d; @@ -39,7 +40,9 @@ static int list_files(const char *dir, char reply[REPLY_MAX]) {      }      reply[0]=0;      while ((de = readdir(d))) { -        if (de->d_type != DT_REG) continue; +        if (de->d_type != DT_DIR) continue; +        if ((strcmp(DOT, de->d_name) == 0) || +                (strcmp(DOTDOT, de->d_name) == 0)) continue;          if (reply[0] != 0) strlcat(reply, " ", REPLY_MAX);          if (strlcat(reply, de->d_name, REPLY_MAX) >= REPLY_MAX) {              LOGE("reply is too long(too many files under '%s'\n", dir); @@ -50,31 +53,25 @@ static int list_files(const char *dir, char reply[REPLY_MAX]) {      return 0;  } -static int copy_keyfile(const char *keystore, const char *srcfile) { -    int srcfd, dstfd; -    int length; -    char buf[2048]; -    char dstfile[KEYNAME_LENGTH]; -    const char *filename = strrchr(srcfile, '/'); +static int copy_keyfile(const char *src, int src_type, const char *dstfile) { +    int srcfd = -1, dstfd; +    char buf[REPLY_MAX]; -    strlcpy(dstfile, keystore, KEYNAME_LENGTH); -    strlcat(dstfile, "/", KEYNAME_LENGTH); -    if (strlcat(dstfile, filename ? filename + 1 : srcfile, -                KEYNAME_LENGTH) >= KEYNAME_LENGTH) { -        LOGE("keyname is too long '%s'\n", srcfile); -        return -1; -    } - -    if ((srcfd = open(srcfile, O_RDONLY)) == -1) { -        LOGE("Cannot open the original file '%s'\n", srcfile); +    if ((src_type == IS_FILE) && (srcfd = open(src, O_RDONLY)) == -1) { +        LOGE("Cannot open the original file '%s'\n", src);          return -1;      }      if ((dstfd = open(dstfile, O_CREAT|O_RDWR)) == -1) {          LOGE("Cannot open the destination file '%s'\n", dstfile);          return -1;      } -    while((length = read(srcfd, buf, 2048)) > 0) { -        write(dstfd, buf, length); +    if (src_type == IS_FILE) { +        int length; +        while((length = read(srcfd, buf, REPLY_MAX)) > 0) { +            write(dstfd, buf, length); +        } +    } else { +        write(dstfd, src, strlen(src));      }      close(srcfd);      close(dstfd); @@ -82,60 +79,149 @@ static int copy_keyfile(const char *keystore, const char *srcfile) {      return 0;  } -static int install_key(const char *dir, const char *keyfile) +static int install_key(const char *path, const char *certname, const char *src, +        int src_is_file, char *dstfile)  {      struct dirent *de; +    char fullpath[KEYNAME_LENGTH];      DIR *d; -    if ((d = open_keystore(dir)) == NULL) { +    if (snprintf(fullpath, sizeof(fullpath), "%s/%s/", path, certname) +            >= KEYNAME_LENGTH) { +        LOGE("cert name '%s' is too long.\n", certname); +        return -1; +    } + +    if ((d = open_keystore(fullpath)) == NULL) { +        LOGE("Can not open the keystore '%s'\n", fullpath); +        return -1; +    } +    closedir(d); +    if (strlcat(fullpath, dstfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) { +        LOGE("cert name '%s' is too long.\n", certname);          return -1;      } -    return copy_keyfile(dir, keyfile); +    return copy_keyfile(src, src_is_file, fullpath);  } -static int remove_key(const char *dir, const char *keyfile) +static int get_key(const char *path, const char *keyname, const char *file, +        char reply[REPLY_MAX]) +{ +    struct dirent *de; +    char filename[KEYNAME_LENGTH]; +    int fd; + +    if (snprintf(filename, sizeof(filename), "%s/%s/%s", path, keyname, file) +            >= KEYNAME_LENGTH) { +        LOGE("cert name '%s' is too long.\n", keyname); +        return -1; +    } + +    if ((fd = open(filename, O_RDONLY)) == -1) { +        return -1; +    } +    close(fd); +    strlcpy(reply, filename, REPLY_MAX); +    return 0; +} + +static int remove_key(const char *dir, const char *key)  {      char dstfile[KEYNAME_LENGTH]; +    char *keyfile[4] = { USER_KEY, USER_P12_CERT, USER_CERTIFICATE, +            CA_CERTIFICATE }; +    int i, count = 0; + +    for ( i = 0 ; i < 4 ; i++) { +        if (snprintf(dstfile, KEYNAME_LENGTH, "%s/%s/%s", dir, key, keyfile[i]) +                >= KEYNAME_LENGTH) { +            LOGE("keyname is too long '%s'\n", key); +            return -1; +        } +        if (unlink(dstfile) == 0) count++; +    } -    strlcpy(dstfile, dir, KEYNAME_LENGTH); -    strlcat(dstfile, "/", KEYNAME_LENGTH); -    if (strlcat(dstfile, keyfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) { -        LOGE("keyname is too long '%s'\n", keyfile); +    if (count == 0) { +        LOGE("can not clean up '%s' keys or not exist\n", key);          return -1;      } -    if (unlink(dstfile)) { -        LOGE("cannot delete '%s': %s\n", dstfile, strerror(errno)); + +    snprintf(dstfile, KEYNAME_LENGTH, "%s/%s", dir, key); +    if (rmdir(dstfile)) { +        LOGE("can not clean up '%s' directory\n", key);          return -1;      }      return 0;  } -int list_certs(char reply[REPLY_MAX]) +int list_user_certs(char reply[REPLY_MAX])  {      return list_files(CERTS_DIR, reply);  } -int list_userkeys(char reply[REPLY_MAX]) +int list_ca_certs(char reply[REPLY_MAX])  { -    return list_files(USERKEYS_DIR, reply); +    return list_files(CACERTS_DIR, reply);  } -int install_cert(const char *certfile) +int install_user_cert(const char *keyname, const char *cert, const char *key)  { -    return install_key(CERTS_DIR, certfile); +    if (install_key(CERTS_DIR, keyname, cert, IS_FILE, USER_CERTIFICATE) == 0) { +        return install_key(CERTS_DIR, keyname, key, IS_FILE, USER_KEY); +    } +    return -1;  } -int install_userkey(const char *keyfile) +int install_ca_cert(const char *keyname, const char *certfile)  { -    return install_key(USERKEYS_DIR, keyfile); +    return install_key(CACERTS_DIR, keyname, certfile, IS_FILE, CA_CERTIFICATE); +} + +int install_p12_cert(const char *keyname, const char *certfile) +{ +    return install_key(CERTS_DIR, keyname, certfile, IS_FILE, USER_P12_CERT); +} + +int add_ca_cert(const char *keyname, const char *certificate) +{ +    return install_key(CACERTS_DIR, keyname, certificate, IS_CONTENT, +            CA_CERTIFICATE); +} + +int add_user_cert(const char *keyname, const char *certificate) +{ +    return install_key(CERTS_DIR, keyname, certificate, IS_CONTENT, +            USER_CERTIFICATE); +} + +int add_user_key(const char *keyname, const char *key) +{ +    return install_key(CERTS_DIR, keyname, key, IS_CONTENT, USER_KEY); +} + +int get_ca_cert(const char *keyname, char reply[REPLY_MAX]) +{ +    return get_key(CACERTS_DIR, keyname, CA_CERTIFICATE, reply); +} + +int get_user_cert(const char *keyname, char reply[REPLY_MAX]) +{ +    return get_key(CERTS_DIR, keyname, USER_CERTIFICATE, reply); +} + +int get_user_key(const char *keyname, char reply[REPLY_MAX]) +{ +    if(get_key(CERTS_DIR, keyname, USER_KEY, reply)) +        return get_key(CERTS_DIR, keyname, USER_P12_CERT, reply); +    return 0;  } -int remove_cert(const char *certfile) +int remove_user_cert(const char *key)  { -    return remove_key(CERTS_DIR, certfile); +    return remove_key(CERTS_DIR, key);  } -int remove_userkey(const char *keyfile) +int remove_ca_cert(const char *key)  { -    return remove_key(USERKEYS_DIR, keyfile); +    return remove_key(CACERTS_DIR, key);  } diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c index 5193b3d..df8d832 100644 --- a/cmds/keystore/keystore.c +++ b/cmds/keystore/keystore.c @@ -16,37 +16,89 @@  #include "keystore.h" +static inline int has_whitespace(char *name) +{ +    if((strrchr(name, ' ') != NULL)) { +        LOGE("'%s' contains whitespace character\n", name); +        return 1; +    } +    return 0; +} + +static int do_list_user_certs(char **arg, char reply[REPLY_MAX]) +{ +    return list_user_certs(reply); +} + +static int do_list_ca_certs(char **arg, char reply[REPLY_MAX]) +{ +    return list_ca_certs(reply); +} + +static int do_install_user_cert(char **arg, char reply[REPLY_MAX]) +{ +    if (has_whitespace(arg[0])) return -1; +    /* copy the certificate and key to keystore */ +    return install_user_cert(arg[0], arg[1], arg[2]); +} -static int do_list_certs(char **arg, char reply[REPLY_MAX]) +static int do_install_p12_cert(char **arg, char reply[REPLY_MAX])  { -    return list_certs(reply); +    if (has_whitespace(arg[0])) return -1; +    return install_p12_cert(arg[0], arg[1]);  } -static int do_list_userkeys(char **arg, char reply[REPLY_MAX]) +static int do_install_ca_cert(char **arg, char reply[REPLY_MAX])  { -    return list_userkeys(reply); +    if (has_whitespace(arg[0])) return -1; +    /* copy the certificate and key to keystore */ +    return install_ca_cert(arg[0], arg[1]);  } -static int do_install_cert(char **arg, char reply[REPLY_MAX]) +static int do_add_ca_cert(char **arg, char reply[REPLY_MAX])  { -    return install_cert(arg[0]); /* move the certificate to keystore */ +    if (has_whitespace(arg[0])) return -1; +    return add_ca_cert(arg[0], arg[1]);  } -static int do_remove_cert(char **arg, char reply[REPLY_MAX]) +static int do_add_user_cert(char **arg, char reply[REPLY_MAX])  { -    return remove_cert(arg[0]); /* certificate */ +    if (has_whitespace(arg[0])) return -1; +    return add_user_cert(arg[0], arg[1]);  } -static int do_install_userkey(char **arg, char reply[REPLY_MAX]) +static int do_add_user_key(char **arg, char reply[REPLY_MAX])  { -    return install_userkey(arg[0]); /* move the certificate to keystore */ +    if (has_whitespace(arg[0])) return -1; +    return add_user_key(arg[0], arg[1]);  } -static int do_remove_userkey(char **arg, char reply[REPLY_MAX]) +static int do_get_ca_cert(char **arg, char reply[REPLY_MAX])  { -    return remove_userkey(arg[0]); /* userkey */ +    return get_ca_cert(arg[0], reply);  } +static int do_get_user_cert(char **arg, char reply[REPLY_MAX]) +{ +    return get_user_cert(arg[0], reply); +} + +static int do_get_user_key(char **arg, char reply[REPLY_MAX]) +{ +    return get_user_key(arg[0], reply); +} + +static int do_remove_user_cert(char **arg, char reply[REPLY_MAX]) +{ +    return remove_user_cert(arg[0]); +} + +static int do_remove_ca_cert(char **arg, char reply[REPLY_MAX]) +{ +    return remove_ca_cert(arg[0]); +} + +  struct cmdinfo {      const char *name;      unsigned numargs; @@ -55,12 +107,19 @@ struct cmdinfo {  struct cmdinfo cmds[] = { -    { "listcerts",            0, do_list_certs }, -    { "listuserkeys",         0, do_list_userkeys }, -    { "installcert",          1, do_install_cert }, -    { "removecert",           1, do_remove_cert }, -    { "installuserkey",       1, do_install_userkey }, -    { "removeuserkey",        1, do_remove_userkey }, +    { "listcacerts",        0, do_list_ca_certs }, +    { "listusercerts",      0, do_list_user_certs }, +    { "installusercert",    3, do_install_user_cert }, +    { "installcacert",      2, do_install_ca_cert }, +    { "installp12cert",     2, do_install_p12_cert }, +    { "addusercert",        2, do_add_user_cert }, +    { "adduserkey",         2, do_add_user_key }, +    { "addcacert",          2, do_add_ca_cert }, +    { "getusercert",        1, do_get_user_cert }, +    { "getuserkey",         1, do_get_user_key }, +    { "getcacert",          1, do_get_ca_cert }, +    { "removecacert",       1, do_remove_ca_cert }, +    { "removeusercert",     1, do_remove_user_cert },  };  static int readx(int s, void *_buf, int count) @@ -121,7 +180,7 @@ static int execute(int s, char cmd[BUFFER_MAX])      /* n is number of args (not counting arg[0]) */      arg[0] = cmd;      while (*cmd) { -        if (isspace(*cmd)) { +        if (*cmd == CMD_DELIMITER) {              *cmd++ = 0;              n++;              arg[n] = cmd; @@ -167,6 +226,7 @@ int shell_command(const int argc, const char **argv)      int fd, i;      short ret;      unsigned short count; +    char delimiter[2] = { CMD_DELIMITER, 0 };      char buf[BUFFER_MAX]="";      fd = socket_local_client(SOCKET_PATH, @@ -177,7 +237,7 @@ int shell_command(const int argc, const char **argv)          exit(1);      }      for(i = 0; i < argc; i++) { -        if (i > 0) strlcat(buf, " ", BUFFER_MAX); +        if (i > 0) strlcat(buf, delimiter, BUFFER_MAX);          if(strlcat(buf, argv[i], BUFFER_MAX) >= BUFFER_MAX) {              fprintf(stderr, "Arguments are too long\n");              exit(1); diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h index 35acf0b9..b9cb185 100644 --- a/cmds/keystore/keystore.h +++ b/cmds/keystore/keystore.h @@ -40,18 +40,35 @@  /* path of the keystore */  #define KEYSTORE_DIR_PREFIX "/data/misc/keystore" -#define CERTS_DIR           KEYSTORE_DIR_PREFIX "/certs" -#define USERKEYS_DIR         KEYSTORE_DIR_PREFIX "/userkeys" +#define CERTS_DIR           KEYSTORE_DIR_PREFIX "/keys" +#define CACERTS_DIR         KEYSTORE_DIR_PREFIX "/cacerts" +#define CA_CERTIFICATE      "ca.crt" +#define USER_CERTIFICATE    "user.crt" +#define USER_P12_CERT       "user.p12" +#define USER_KEY            "user.key" +#define DOT                 "." +#define DOTDOT              ".." -#define BUFFER_MAX      1024  /* input buffer for commands */ +#define BUFFER_MAX      4096  /* input buffer for commands */  #define TOKEN_MAX       8     /* max number of arguments in buffer */ -#define REPLY_MAX       1024  /* largest reply allowed */ +#define REPLY_MAX       4096  /* largest reply allowed */ +#define CMD_DELIMITER   '\t'  #define KEYNAME_LENGTH  128 +#define IS_CONTENT      0 +#define IS_FILE         1 +  /* commands.c */ -int list_certs(char reply[REPLY_MAX]); -int list_userkeys(char reply[REPLY_MAX]); -int install_cert(const char *certfile); -int install_userkey(const char *keyfile); -int remove_cert(const char *certfile); -int remove_userkey(const char *keyfile); +int list_ca_certs(char reply[REPLY_MAX]); +int list_user_certs(char reply[REPLY_MAX]); +int install_user_cert(const char *certname, const char *cert, const char *key); +int install_ca_cert(const char *certname, const char *cert); +int install_p12_cert(const char *certname, const char *cert); +int add_ca_cert(const char *certname, const char *content); +int add_user_cert(const char *certname, const char *content); +int add_user_key(const char *keyname, const char *content); +int get_ca_cert(const char *keyname, char reply[REPLY_MAX]); +int get_user_cert(const char *keyname, char reply[REPLY_MAX]); +int get_user_key(const char *keyname, char reply[REPLY_MAX]); +int remove_user_cert(const char *certname); +int remove_ca_cert(const char *certname); diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java index 71c1cf4..ce3fa88 100644 --- a/keystore/java/android/security/Keystore.java +++ b/keystore/java/android/security/Keystore.java @@ -30,6 +30,7 @@ public abstract class Keystore {          return new FileKeystore();      } +    // for compatiblity, start from here      /**       */      public abstract String getUserkey(String key); @@ -46,6 +47,34 @@ public abstract class Keystore {       */      public abstract String[] getAllUserkeyKeys(); +    // to here + +    /** +     */ +    public abstract String getCaCertificate(String key); + +    /** +     */ +    public abstract String getUserCertificate(String key); + +    /** +     */ +    public abstract String getUserPrivateKey(String key); + +    /** +     * Returns the array of the certificate keynames in keystore if successful. +     * Or return an empty array if error. +     * +     * @return array of the certificate keynames +     */ +    public abstract String[] getAllUserCertificateKeys(); + +    /** +     */ +    public abstract String[] getAllCaCertificateKeys(); + +    /** +     */      public abstract String[] getSupportedKeyStrenghs();      /** @@ -63,13 +92,25 @@ public abstract class Keystore {      private static class FileKeystore extends Keystore {          private static final String SERVICE_NAME = "keystore"; +        private static final String LIST_CA_CERTIFICATES = "listcacerts"; +        private static final String LIST_USER_CERTIFICATES = "listusercerts"; +        private static final String GET_CA_CERTIFICATE = "getcacert"; +        private static final String GET_USER_CERTIFICATE = "getusercert"; +        private static final String GET_USER_KEY = "getuserkey"; +        private static final String ADD_CA_CERTIFICATE = "addcacert"; +        private static final String ADD_USER_CERTIFICATE = "addusercert"; +        private static final String ADD_USER_KEY = "adduserkey"; +        private static final String COMMAND_DELIMITER = "\t"; +        private static final ServiceCommand mServiceCommand = +                new ServiceCommand(SERVICE_NAME); + +        // for compatiblity, start from here +          private static final String LIST_CERTIFICATES = "listcerts";          private static final String LIST_USERKEYS = "listuserkeys";          private static final String PATH = "/data/misc/keystore/";          private static final String USERKEY_PATH = PATH + "userkeys/";          private static final String CERT_PATH = PATH + "certs/"; -        private static final ServiceCommand mServiceCommand = -                new ServiceCommand(SERVICE_NAME);          @Override          public String getUserkey(String key) { @@ -81,12 +122,6 @@ public abstract class Keystore {              return CERT_PATH + key;          } -        /** -         * Returns the array of the certificate names in keystore if successful. -         * Or return an empty array if error. -         * -         * @return array of the certificates -         */          @Override          public String[] getAllCertificateKeys() {              try { @@ -98,12 +133,6 @@ public abstract class Keystore {              }          } -        /** -         * Returns the array of the names of private keys in keystore if successful. -         * Or return an empty array if errors. -         * -         * @return array of the user keys -         */          @Override          public String[] getAllUserkeyKeys() {              try { @@ -115,6 +144,48 @@ public abstract class Keystore {              }          } +        // to here + +        @Override +        public String getUserPrivateKey(String key) { +            return mServiceCommand.execute( +                    GET_USER_KEY + COMMAND_DELIMITER + key); +        } + +        @Override +        public String getUserCertificate(String key) { +            return mServiceCommand.execute( +                    GET_USER_CERTIFICATE + COMMAND_DELIMITER + key); +        } + +        @Override +        public String getCaCertificate(String key) { +            return mServiceCommand.execute( +                    GET_CA_CERTIFICATE + COMMAND_DELIMITER + key); +        } + +        @Override +        public String[] getAllUserCertificateKeys() { +            try { +                String result = mServiceCommand.execute(LIST_USER_CERTIFICATES); +                if (result != null) return result.split("\\s+"); +                return NOTFOUND; +            } catch (NumberFormatException ex) { +                return NOTFOUND; +            } +        } + +        @Override +        public String[] getAllCaCertificateKeys() { +            try { +                String result = mServiceCommand.execute(LIST_CA_CERTIFICATES); +                if (result != null) return result.split("\\s+"); +                return NOTFOUND; +            } catch (NumberFormatException ex) { +                return NOTFOUND; +            } +        } +          @Override          public String[] getSupportedKeyStrenghs() {              // TODO: real implementation @@ -149,5 +220,26 @@ public abstract class Keystore {          public void addCertificate(String cert) {              // TODO: real implementation          } + +        private boolean addUserCertificate(String key, String certificate, +                String privateKey) { +            if(mServiceCommand.execute(ADD_USER_CERTIFICATE + COMMAND_DELIMITER +                    + key + COMMAND_DELIMITER + certificate) != null) { +                if (mServiceCommand.execute(ADD_USER_KEY + COMMAND_DELIMITER +                        + key + COMMAND_DELIMITER + privateKey) != null) { +                    return true; +                } +            } +            return false; +        } + +        private boolean addCaCertificate(String key, String content) { +            if (mServiceCommand.execute(ADD_CA_CERTIFICATE + COMMAND_DELIMITER +                    + key + COMMAND_DELIMITER + content) != null) { +                return true; +            } +            return false; +        } +      }  } | 
