From 839a6745806b8a031ec6ecbc87e5b03c4db7a0e9 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Sun, 20 Sep 2015 02:54:46 +0300 Subject: [PATCH] Supply file attributes values on command line Can be used by Android filesystem image creation tool. Signed-off-by: Dmitry Kasatkin --- src/evmctl.c | 133 +++++++++++++++++++++++++++++++++++++++++++----- src/libimaevm.c | 6 +-- 2 files changed, 123 insertions(+), 16 deletions(-) diff --git a/src/evmctl.c b/src/evmctl.c index f95ac1d..c54efbb 100644 --- a/src/evmctl.c +++ b/src/evmctl.c @@ -104,6 +104,14 @@ static int digest; static int digsig; static int sigfile; static char *uuid_str; +static char *ino_str; +static char *uid_str; +static char *gid_str; +static char *mode_str; +static char *generation_str; +static char *caps_str; +static char *ima_str; +static char *selinux_str; static char *search_type; static int recursive; static int msize; @@ -111,6 +119,7 @@ static dev_t fs_dev; static bool evm_immutable; #define HMAC_FLAG_NO_UUID 0x0001 +#define HMAC_FLAG_CAPS_SET 0x0002 static unsigned long hmac_flags; @@ -200,7 +209,7 @@ static int hex_to_bin(char ch) return -1; } -static int hex2bin(uint8_t *dst, const char *src, size_t count) +static int hex2bin(void *dst, const char *src, size_t count) { int hi, lo; @@ -214,7 +223,7 @@ static int hex2bin(uint8_t *dst, const char *src, size_t count) if ((hi < 0) || (lo < 0)) return -1; - *dst++ = (hi << 4) | lo; + *(uint8_t *)dst++ = (hi << 4) | lo; } return 0; } @@ -320,10 +329,21 @@ static int calc_evm_hash(const char *file, unsigned char *hash) return -1; } + if (generation_str) + generation = strtoul(generation_str, NULL, 10); + if (ino_str) + st.st_ino = strtoul(ino_str, NULL, 10); + if (uid_str) + st.st_uid = strtoul(uid_str, NULL, 10); + if (gid_str) + st.st_gid = strtoul(gid_str, NULL, 10); + if (mode_str) + st.st_mode = strtoul(mode_str, NULL, 10); + if (!evm_immutable) { - if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { - /* we cannot at the momement to get generation of special files.. - * kernel API does not support it */ + if ((S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && !generation_str) { + /* we cannot at the momement to get generation of + special files kernel API does not support it */ int fd = open(file, 0); if (fd < 0) { @@ -353,14 +373,27 @@ static int calc_evm_hash(const char *file, unsigned char *hash) } for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { - err = lgetxattr(file, *xattrname, xattr_value, sizeof(xattr_value)); - if (err < 0) { - log_info("no xattr: %s\n", *xattrname); - continue; - } - if (!find_xattr(list, list_size, *xattrname)) { - log_info("skipping xattr: %s\n", *xattrname); - continue; + if (!strcmp(*xattrname, XATTR_NAME_SELINUX) && selinux_str) { + strcpy(xattr_value, selinux_str); + err = strlen(selinux_str) + 1; + } else if (!strcmp(*xattrname, XATTR_NAME_IMA) && ima_str) { + hex2bin(xattr_value, ima_str, strlen(ima_str) / 2); + err = strlen(ima_str) / 2; + } else if (!strcmp(*xattrname, XATTR_NAME_CAPS) && (hmac_flags & HMAC_FLAG_CAPS_SET)) { + if (!caps_str) + continue; + strcpy(xattr_value, caps_str); + err = strlen(caps_str); + } else { + err = lgetxattr(file, *xattrname, xattr_value, sizeof(xattr_value)); + if (err < 0) { + log_info("no xattr: %s\n", *xattrname); + continue; + } + if (!find_xattr(list, list_size, *xattrname)) { + log_info("skipping xattr: %s\n", *xattrname); + continue; + } } /*log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);*/ log_info("name: %s, size: %d\n", *xattrname, err); @@ -764,6 +797,38 @@ static int cmd_verify_ima(struct command *cmd) return verify_ima(file); } +static int cmd_convert(struct command *cmd) +{ + char *inkey; + unsigned char _pub[1024], *pub = _pub; + int len, err = 0; + char name[20]; + uint8_t keyid[8]; + RSA *key; + + params.x509 = 0; + + inkey = g_argv[optind++]; + if (!inkey) { + inkey = params.x509 ? "/etc/keys/x509_evm.der" : + "/etc/keys/pubkey_evm.pem"; + } + + key = read_pub_key(inkey, params.x509); + if (!key) + return 1; + + len = key2bin(key, pub); + calc_keyid_v1(keyid, name, pub, len); + + bin2file(inkey, "bin", pub, len); + bin2file(inkey, "keyid", (const unsigned char *)name, strlen(name)); + + RSA_free(key); + return err; +} + + static int cmd_import(struct command *cmd) { char *inkey, *ring = NULL; @@ -1462,6 +1527,14 @@ static void usage(void) " --smack use extra SMACK xattrs for EVM\n" " --m32 force EVM hmac/signature for 32 bit target system\n" " --m64 force EVM hmac/signature for 64 bit target system\n" + " --ino use custom inode for EVM\n" + " --uid use custom UID for EVM\n" + " --gid use custom GID for EVM\n" + " --mode use custom Mode for EVM\n" + " --generation use custom Generation for EVM(unspecified: from FS, empty: use 0)\n" + " --ima use custom IMA signature for EVM\n" + " --selinux use custom Selinux label for EVM\n" + " --caps use custom Capabilities for EVM(unspecified: from FS, empty: do not use)\n" " -v increase verbosity level\n" " -h, --help display this help and exit\n" "\n"); @@ -1471,6 +1544,7 @@ struct command cmds[] = { {"--version", NULL, 0, ""}, {"help", cmd_help, 0, ""}, {"import", cmd_import, 0, "[--rsa] pubkey keyring", "Import public key into the keyring.\n"}, + {"convert", cmd_convert, 0, "key", "convert public key into the keyring.\n"}, {"sign", cmd_sign_evm, 0, "[-r] [--imahash | --imasig ] [--key key] [--pass [password] file", "Sign file metadata.\n"}, {"verify", cmd_verify_evm, 0, "file", "Verify EVM signature (for debugging).\n"}, {"ima_sign", cmd_sign_ima, 0, "[--sigfile] [--key key] [--pass [password] file", "Make file content signature.\n"}, @@ -1502,6 +1576,14 @@ static struct option opts[] = { {"m64", 0, 0, '6'}, {"smack", 0, 0, 128}, {"version", 0, 0, 129}, + {"inode", 1, 0, 130}, + {"uid", 1, 0, 131}, + {"gid", 1, 0, 132}, + {"mode", 1, 0, 133}, + {"generation", 1, 0, 134}, + {"ima", 1, 0, 135}, + {"selinux", 1, 0, 136}, + {"caps", 2, 0, 137}, {} }; @@ -1616,6 +1698,31 @@ int main(int argc, char *argv[]) printf("evmctl %s\n", VERSION); exit(0); break; + case 130: + ino_str = optarg; + break; + case 131: + uid_str = optarg; + break; + case 132: + gid_str = optarg; + break; + case 133: + mode_str = optarg; + break; + case 134: + generation_str = optarg; + break; + case 135: + ima_str = optarg; + break; + case 136: + selinux_str = optarg; + break; + case 137: + caps_str = optarg; + hmac_flags |= HMAC_FLAG_CAPS_SET; + break; case '?': exit(1); break; diff --git a/src/libimaevm.c b/src/libimaevm.c index 47be27d..eedffb4 100644 --- a/src/libimaevm.c +++ b/src/libimaevm.c @@ -375,7 +375,7 @@ int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, int unsigned char sighash[20]; struct signature_hdr *hdr = (struct signature_hdr *)sig; - log_info("hash: "); + log_info("hash-v1: "); log_dump(hash, size); key = read_pub_key(keyfile, 0); @@ -589,7 +589,7 @@ void calc_keyid_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len id = __be64_to_cpup((__be64 *) keyid); sprintf(str, "%llX", (unsigned long long)id); - log_info("keyid: %s\n", str); + log_info("keyid-v1: %s\n", str); } void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key) @@ -721,7 +721,7 @@ int sign_hash_v1(const char *hashalgo, const unsigned char *hash, int size, cons blen = (uint16_t *) (sig + sizeof(*hdr)); *blen = __cpu_to_be16(len << 3); len += sizeof(*hdr) + 2; - log_info("evm/ima signature: %d bytes\n", len); + log_info("evm/ima signature-v1: %d bytes\n", len); out: RSA_free(key); return len;