Hello community, here is the log from the commit of package ima-evm-utils for openSUSE:Factory checked in at 2015-12-03 13:32:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ima-evm-utils (Old) and /work/SRC/openSUSE:Factory/.ima-evm-utils.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ima-evm-utils" Changes: -------- --- /work/SRC/openSUSE:Factory/ima-evm-utils/ima-evm-utils.changes 2015-01-24 22:20:42.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.ima-evm-utils.new/ima-evm-utils.changes 2015-12-03 13:32:51.000000000 +0100 @@ -1,0 +2,10 @@ +Wed Dec 2 13:44:58 UTC 2015 - [email protected] + +- Update to version 1.0 + * Recursive hashing + * Immutable EVM signatures (experimental) + * Command 'ima_clear' to remove xattrs + * Support for passing password to the library + * Support for asking password safely from the user + +------------------------------------------------------------------- Old: ---- ima-evm-utils-0.9.tar.gz New: ---- ima-evm-utils-1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ima-evm-utils.spec ++++++ --- /var/tmp/diff_new_pack.Zwvqf7/_old 2015-12-03 13:32:51.000000000 +0100 +++ /var/tmp/diff_new_pack.Zwvqf7/_new 2015-12-03 13:32:51.000000000 +0100 @@ -19,12 +19,12 @@ %define libname libimaevm%{sover} Name: ima-evm-utils -Version: 0.9 +Version: 1.0 Release: 0 Summary: IMA/EVM control utility License: LGPL-2.1+ Group: System/Libraries -URL: http://sourceforge.net/projects/linux-ima/ +Url: http://sourceforge.net/projects/linux-ima/ Source0: http://downloads.sourceforge.net/project/linux-ima/ima-evm-utils/%{name}-%{version}.tar.gz Patch2: ima-evm-utils-fix-docbook-xsl-directory.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build ++++++ ima-evm-utils-0.9.tar.gz -> ima-evm-utils-1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/ChangeLog new/ima-evm-utils-1.0/ChangeLog --- old/ima-evm-utils-0.9/ChangeLog 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/ChangeLog 2015-07-30 20:28:53.000000000 +0200 @@ -1,3 +1,12 @@ +2014-07-30 Dmitry Kasatkin <[email protected]> + + version 1.0 + * Recursive hashing + * Immutable EVM signatures (experimental) + * Command 'ima_clear' to remove xattrs + * Support for passing password to the library + * Support for asking password safely from the user + 2014-09-23 Dmitry Kasatkin <[email protected]> version 0.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/README new/ima-evm-utils-1.0/README --- old/ima-evm-utils-0.9/README 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/README 2015-07-30 20:28:53.000000000 +0200 @@ -403,7 +403,7 @@ Latest version of keyctl allows to import X509 public key certificates: - cat /etc/keys/x509_ima.der | keyctl padd asymmetric '' @ima_id + cat /etc/keys/x509_ima.der | keyctl padd asymmetric '' $ima_id FILES diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/configure.ac new/ima-evm-utils-1.0/configure.ac --- old/ima-evm-utils-0.9/configure.ac 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/configure.ac 2015-07-30 20:28:53.000000000 +0200 @@ -1,7 +1,7 @@ # autoconf script AC_PREREQ([2.65]) -AC_INIT(ima-evm-utils, 0.9, [email protected]) +AC_INIT(ima-evm-utils, 1.0, [email protected]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/packaging/ima-evm-utils.spec new/ima-evm-utils-1.0/packaging/ima-evm-utils.spec --- old/ima-evm-utils-0.9/packaging/ima-evm-utils.spec 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/packaging/ima-evm-utils.spec 2015-07-30 20:28:53.000000000 +0200 @@ -1,5 +1,5 @@ Name: ima-evm-utils -Version: 0.9 +Version: 1.0 Release: 1%{?dist} Summary: ima-evm-utils - IMA/EVM control utility Group: System/Libraries diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/src/evmctl.c new/ima-evm-utils-1.0/src/evmctl.c --- old/ima-evm-utils-0.9/src/evmctl.c 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/src/evmctl.c 2015-07-30 20:28:53.000000000 +0200 @@ -54,6 +54,7 @@ #include <getopt.h> #include <keyutils.h> #include <ctype.h> +#include <termios.h> #include <openssl/sha.h> #include <openssl/pem.h> @@ -107,6 +108,7 @@ static int recursive; static int msize; static dev_t fs_dev; +static bool evm_immutable; #define HMAC_FLAG_UUID 0x0001 #define HMAC_FLAG_UUID_SET 0x0002 @@ -318,24 +320,25 @@ return -1; } - 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 */ - int fd = open(file, 0); + 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 */ + int fd = open(file, 0); - if (fd < 0) { - log_err("Failed to open: %s\n", file); - return -1; - } - if (ioctl(fd, FS_IOC_GETVERSION, &generation)) { - log_err("ioctl() failed\n"); - return -1; + if (fd < 0) { + log_err("Failed to open: %s\n", file); + return -1; + } + if (ioctl(fd, FS_IOC_GETVERSION, &generation)) { + log_err("ioctl() failed\n"); + return -1; + } + close(fd); } - close(fd); + log_info("generation: %u\n", generation); } - log_info("generation: %u\n", generation); - list_size = llistxattr(file, list, sizeof(list)); if (list_size < 0) { log_err("llistxattr() failed\n"); @@ -370,7 +373,14 @@ memset(&hmac_misc, 0, sizeof(hmac_misc)); - if (msize == 0) { + if (evm_immutable) { + struct h_misc_digsig *hmac = (struct h_misc_digsig *)&hmac_misc; + + hmac_size = sizeof(*hmac); + hmac->uid = st.st_uid; + hmac->gid = st.st_gid; + hmac->mode = st.st_mode; + } else if (msize == 0) { struct h_misc *hmac = (struct h_misc *)&hmac_misc; hmac_size = sizeof(*hmac); @@ -408,7 +418,7 @@ return 1; } - if (hmac_flags & HMAC_FLAG_UUID) { + if (!evm_immutable && (hmac_flags & HMAC_FLAG_UUID)) { err = get_uuid(&st, uuid); if (err) return -1; @@ -439,7 +449,7 @@ if (len <= 1) return len; - len = sign_hash("sha1", hash, len, key, sig + 1); + len = sign_hash("sha1", hash, len, key, NULL, sig + 1); if (len <= 1) return len; @@ -447,6 +457,9 @@ len++; sig[0] = EVM_IMA_XATTR_DIGSIG; + if (evm_immutable) + sig[1] = 3; /* immutable signature version */ + if (sigdump || params.verbose >= LOG_INFO) dump(sig, len); @@ -499,19 +512,6 @@ return 0; } -static int cmd_hash_ima(struct command *cmd) -{ - char *file = g_argv[optind++]; - - if (!file) { - log_err("Parameters missing\n"); - print_usage(cmd); - return -1; - } - - return hash_ima(file); -} - static int sign_ima(const char *file, const char *key) { unsigned char hash[64]; @@ -522,7 +522,7 @@ if (len <= 1) return len; - len = sign_hash(params.hash_algo, hash, len, key, sig + 1); + len = sign_hash(params.hash_algo, hash, len, key, NULL, sig + 1); if (len <= 1) return len; @@ -577,21 +577,12 @@ return dts; } -static int sign_ima_file(const char *file) -{ - char *key; - - key = params.keyfile ? : "/etc/keys/privkey_evm.pem"; - - return sign_ima(file, key); -} - -static int cmd_sign_ima(struct command *cmd) +static int do_cmd(struct command *cmd, find_cb_t func) { - char *file = g_argv[optind++]; + char *path = g_argv[optind++]; int err, dts = REG_MASK; /* only regular files by default */ - if (!file) { + if (!path) { log_err("Parameters missing\n"); print_usage(cmd); return -1; @@ -599,21 +590,41 @@ if (recursive) { if (search_type) { - dts = get_file_type(file, search_type); + dts = get_file_type(path, search_type); if (dts < 0) return dts; } - err = find(file, dts, sign_ima_file); + err = find(path, dts, func); } else { - err = sign_ima_file(file); + err = func(path); } return err; } +static int cmd_hash_ima(struct command *cmd) +{ + return do_cmd(cmd, hash_ima); +} + +static int sign_ima_file(const char *file) +{ + const char *key; + + key = params.keyfile ? : "/etc/keys/privkey_evm.pem"; + + return sign_ima(file, key); +} + +static int cmd_sign_ima(struct command *cmd) +{ + return do_cmd(cmd, sign_ima_file); +} + static int cmd_sign_hash(struct command *cmd) { - char *key, *token, *line = NULL; + const char *key; + char *token, *line = NULL; int hashlen = 0; size_t line_len; ssize_t len; @@ -635,7 +646,7 @@ hex2bin(hash, line, hashlen); siglen = sign_hash(params.hash_algo, hash, hashlen/2, - key, sig + 1); + key, NULL, sig + 1); if (siglen <= 1) return siglen; @@ -656,7 +667,7 @@ static int sign_evm_path(const char *file) { - char *key; + const char *key; int err; key = params.keyfile ? : "/etc/keys/privkey_evm.pem"; @@ -678,27 +689,7 @@ static int cmd_sign_evm(struct command *cmd) { - char *path = g_argv[optind++]; - int err, dts = REG_MASK; /* only regular files by default */ - - if (!path) { - log_err("Parameters missing\n"); - print_usage(cmd); - return -1; - } - - if (recursive) { - if (search_type) { - dts = get_file_type(path, search_type); - if (dts < 0) - return dts; - } - err = find(path, dts, sign_evm_path); - } else { - err = sign_evm_path(path); - } - - return err; + return do_cmd(cmd, sign_evm_path); } static int verify_evm(const char *file) @@ -1012,7 +1003,7 @@ static int cmd_hmac_evm(struct command *cmd) { - char *key, *file = g_argv[optind++]; + const char *key, *file = g_argv[optind++]; int err; if (!file) { @@ -1129,29 +1120,22 @@ static int cmd_ima_fix(struct command *cmd) { - char *path = g_argv[optind++]; - int err, dts = REG_MASK; /* only regular files by default */ - - if (!path) { - log_err("Parameters missing\n"); - print_usage(cmd); - return -1; - } + return do_cmd(cmd, ima_fix); +} - if (recursive) { - if (search_type) { - dts = get_file_type(path, search_type); - if (dts < 0) - return dts; - } - err = find(path, dts, ima_fix); - } else { - err = ima_fix(path); - } +static int ima_clear(const char *path) +{ + log_info("%s\n", path); + lremovexattr(path, "security.ima"); + lremovexattr(path, "security.evm"); - return err; + return 0; } +static int cmd_ima_clear(struct command *cmd) +{ + return do_cmd(cmd, ima_clear); +} static char *pcrs = "/sys/class/misc/tpm0/device/pcrs"; @@ -1485,14 +1469,15 @@ {"--version", NULL, 0, ""}, {"help", cmd_help, 0, "<command>"}, {"import", cmd_import, 0, "[--rsa] pubkey keyring", "Import public key into the keyring.\n"}, - {"sign", cmd_sign_evm, 0, "[-r] [--imahash | --imasig ] [--key key] [--pass password] file", "Sign file metadata.\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"}, + {"ima_sign", cmd_sign_ima, 0, "[--sigfile] [--key key] [--pass [password] file", "Make file content signature.\n"}, {"ima_verify", cmd_verify_ima, 0, "file", "Verify IMA signature (for debugging).\n"}, {"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"}, {"ima_measurement", cmd_ima_measurement, 0, "file", "Verify measurement list (experimental).\n"}, {"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM xattrs in fix mode.\n"}, - {"sign_hash", cmd_sign_hash, 0, "[--key key] [--pass password]", "Sign hashes from shaXsum output.\n"}, + {"ima_clear", cmd_ima_clear, 0, "[-t fdsxm] path", "Recursively remove IMA/EVM xattrs.\n"}, + {"sign_hash", cmd_sign_hash, 0, "[--key key] [--pass [password]", "Sign hashes from shaXsum output.\n"}, #ifdef DEBUG {"hmac", cmd_hmac_evm, 0, "[--imahash | --imasig ] file", "Sign file metadata with HMAC using symmetric key (for testing purpose).\n"}, #endif @@ -1504,7 +1489,7 @@ {"imasig", 0, 0, 's'}, {"imahash", 0, 0, 'd'}, {"hashalgo", 1, 0, 'a'}, - {"pass", 1, 0, 'p'}, + {"pass", 2, 0, 'p'}, {"sigfile", 0, 0, 'f'}, {"uuid", 2, 0, 'u'}, {"rsa", 0, 0, '1'}, @@ -1519,6 +1504,40 @@ }; +static char *get_password(void) +{ + struct termios flags, tmp_flags; + char *password, *pwd; + int passlen = 64; + + password = malloc(passlen); + if (!password) { + perror("malloc"); + return NULL; + } + + tcgetattr(fileno(stdin), &flags); + tmp_flags = flags; + tmp_flags.c_lflag &= ~ECHO; + tmp_flags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) { + perror("tcsetattr"); + return NULL; + } + + printf("PEM password: "); + pwd = fgets(password, passlen, stdin); + + /* restore terminal */ + if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) { + perror("tcsetattr"); + return NULL; + } + + return pwd; +} + int main(int argc, char *argv[]) { int err = 0, c, lind; @@ -1527,7 +1546,7 @@ g_argc = argc; while (1) { - c = getopt_long(argc, argv, "hvnsda:p:fu::k:t:r", opts, &lind); + c = getopt_long(argc, argv, "hvnsda:p::fu::k:t:ri", opts, &lind); if (c == -1) break; @@ -1554,7 +1573,10 @@ params.hash_algo = optarg; break; case 'p': - params.keypass = optarg; + if (optarg) + params.keypass = optarg; + else + params.keypass = get_password(); break; case 'f': sigfile = 1; @@ -1573,6 +1595,9 @@ case 'k': params.keyfile = optarg; break; + case 'i': + evm_immutable = true; + break; case 't': search_type = optarg; break; @@ -1600,9 +1625,6 @@ } } - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - if (argv[optind] == NULL) usage(); else @@ -1623,6 +1645,6 @@ ERR_free_strings(); EVP_cleanup(); - + BIO_free(NULL); return err; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/src/imaevm.h new/ima-evm-utils-1.0/src/imaevm.h --- old/ima-evm-utils-0.9/src/imaevm.h 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/src/imaevm.h 2015-07-30 20:28:53.000000000 +0200 @@ -108,6 +108,12 @@ unsigned short mode; }; +struct h_misc_digsig { + uid_t uid; + gid_t gid; + unsigned short mode; +}; + enum pubkey_algo { PUBKEY_ALGO_RSA, PUBKEY_ALGO_MAX, @@ -172,8 +178,8 @@ int verbose; int x509; const char *hash_algo; - char *keyfile; - char *keypass; + const char *keyfile; + const char *keypass; }; struct RSA_ASN1_template { @@ -195,7 +201,7 @@ void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key); int key2bin(RSA *key, unsigned char *pub); -int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig); +int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig); int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen); int ima_verify_signature(const char *file, unsigned char *sig, int siglen); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ima-evm-utils-0.9/src/libimaevm.c new/ima-evm-utils-1.0/src/libimaevm.c --- old/ima-evm-utils-0.9/src/libimaevm.c 2014-09-23 14:09:05.000000000 +0200 +++ new/ima-evm-utils-1.0/src/libimaevm.c 2015-07-30 20:28:53.000000000 +0200 @@ -53,6 +53,7 @@ #include <openssl/pem.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include <openssl/err.h> #include "imaevm.h" @@ -130,6 +131,8 @@ .hash_algo = "sha1", }; +static void __attribute__ ((constructor)) libinit(void); + void do_dump(FILE *fp, const void *ptr, int len, bool cr) { int i; @@ -488,7 +491,7 @@ int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen) { - char *key; + const char *key; int x509; verify_hash_fn_t verify_hash; @@ -608,7 +611,7 @@ free(pkey); } -static RSA *read_priv_key(const char *keyfile, char *keypass) +static RSA *read_priv_key(const char *keyfile, const char *keypass) { FILE *fp; RSA *key; @@ -618,9 +621,14 @@ log_err("Failed to open keyfile: %s\n", keyfile); return NULL; } - key = PEM_read_RSAPrivateKey(fp, NULL, NULL, keypass); - if (!key) - log_err("PEM_read_RSAPrivateKey() failed\n"); + ERR_load_crypto_strings(); + key = PEM_read_RSAPrivateKey(fp, NULL, NULL, (void *)keypass); + if (!key) { + char str[256]; + + ERR_error_string(ERR_get_error(), str); + log_err("PEM_read_RSAPrivateKey() failed: %s\n", str); + } fclose(fp); return key; @@ -786,8 +794,18 @@ return len; } -int sign_hash(const char *hashalgo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig) + +int sign_hash(const char *hashalgo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig) { + if (keypass) + params.keypass = keypass; + return params.x509 ? sign_hash_v2(hashalgo, hash, size, keyfile, sig) : sign_hash_v1(hashalgo, hash, size, keyfile, sig); } + +static void libinit() +{ + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); +}
