Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c40420c authored by Chung-yih Wang's avatar Chung-yih Wang
Browse files

Change the keystore APIs.

1. simplify the keypair selection in UI.
2. add the user certificate and key into the keystore for keygen feature.
parent b6d1e5b8
Loading
Loading
Loading
Loading
+128 −42
Original line number Diff line number Diff line
/*
** 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,92 +53,175 @@ 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) {
    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);
    chmod(dstfile, 0440);
    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;
    }
    return copy_keyfile(dir, keyfile);

    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(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(CACERTS_DIR, reply);
}

int install_user_cert(const char *keyname, const char *cert, const char *key)
{
    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_ca_cert(const char *keyname, const char *certfile)
{
    return install_key(CACERTS_DIR, keyname, certfile, IS_FILE, CA_CERTIFICATE);
}

int install_p12_cert(const char *keyname, const char *certfile)
{
    return list_files(USERKEYS_DIR, reply);
    return install_key(CERTS_DIR, keyname, certfile, IS_FILE, USER_P12_CERT);
}

int install_cert(const char *certfile)
int add_ca_cert(const char *keyname, const char *certificate)
{
    return install_key(CERTS_DIR, certfile);
    return install_key(CACERTS_DIR, keyname, certificate, IS_CONTENT,
            CA_CERTIFICATE);
}

int install_userkey(const char *keyfile)
int add_user_cert(const char *keyname, const char *certificate)
{
    return install_key(USERKEYS_DIR, keyfile);
    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);
}
+80 −20
Original line number Diff line number Diff line
@@ -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);
+27 −10
Original line number Diff line number Diff line
@@ -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);