1
0
mirror of https://git.code.sf.net/p/linux-ima/ima-evm-utils synced 2025-07-03 22:23:16 +02:00

9 Commits
v0.9 ... v1.0

Author SHA1 Message Date
4b56112c09 Release version 1.0
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-07-30 21:28:53 +03:00
9c8a67a209 Prompt for the password
Supplying the password on the command line is not safe.  This patch
adds support for prompting the user to enter the password.  At some
point, supplying the pasword on the command line should be deprecated.

Prior to this patch, the password could be specified with a blank in
between the '-p' option and the password.  With this patch, the
password now must be adjacent

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2015-07-28 21:42:35 +03:00
96e55082c2 Must use 'const char*'
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-07-24 22:51:39 +03:00
6a712b3b38 Add support for passing the private key password to sign_hash()
evmctl defines the "--pass | -p" command line option for providing
the private key's password.  The password is then stored in a global
variable accessible by the sign_hash_XXXX() functions.

This patch modifies the arguments to the library sign_hash()
function to include the password, allowing callers to specify the
private key password.

Changelog:
- add library init to call OpenSSL_add_all_algorithms

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2015-07-24 22:51:27 +03:00
17f49a1881 Add "ima_clear" command to remove IMA/EVM xattrs
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2014-10-29 21:38:03 +02:00
4d7d2c71a5 Define common function for recursive scanning
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2014-10-29 21:31:58 +02:00
92033dc404 Produce immutable EVM signature
'evmctl sign -i <file>' generates immutable EVM signature.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2014-10-29 13:00:43 +02:00
f805d4d0fe Fix typo
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2014-10-29 12:33:58 +02:00
8558dc5250 Add recursive hashing
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2014-10-02 19:22:19 +03:00
7 changed files with 176 additions and 121 deletions

View File

@ -1,3 +1,12 @@
2014-07-30 Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
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 <d.kasatkin@samsung.com>
version 0.9

2
README
View File

@ -403,7 +403,7 @@ When using plain RSA public keys in PEM format, use 'evmctl import --rsa' for im
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

View File

@ -1,7 +1,7 @@
# autoconf script
AC_PREREQ([2.65])
AC_INIT(ima-evm-utils, 0.9, d.kasatkin@samsung.com)
AC_INIT(ima-evm-utils, 1.0, dmitry.kasatkin@huawei.com)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

View File

@ -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

View File

@ -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 char *search_type;
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,6 +320,7 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
return -1;
}
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 */
@ -333,8 +336,8 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
}
close(fd);
}
log_info("generation: %u\n", generation);
}
list_size = llistxattr(file, list, sizeof(list));
if (list_size < 0) {
@ -370,7 +373,14 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
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 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
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 @@ static int sign_evm(const char *file, const char *key)
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 @@ static int sign_evm(const char *file, const char *key)
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 @@ static int hash_ima(const char *file)
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 @@ static int sign_ima(const char *file, const char *key)
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,9 +577,39 @@ static int get_file_type(const char *path, const char *search_type)
return dts;
}
static int do_cmd(struct command *cmd, find_cb_t func)
{
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, func);
} else {
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)
{
char *key;
const char *key;
key = params.keyfile ? : "/etc/keys/privkey_evm.pem";
@ -588,32 +618,13 @@ static int sign_ima_file(const char *file)
static int cmd_sign_ima(struct command *cmd)
{
char *file = g_argv[optind++];
int err, dts = REG_MASK; /* only regular files by default */
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
}
if (recursive) {
if (search_type) {
dts = get_file_type(file, search_type);
if (dts < 0)
return dts;
}
err = find(file, dts, sign_ima_file);
} else {
err = sign_ima_file(file);
}
return err;
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 @@ static int cmd_sign_hash(struct command *cmd)
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 cmd_sign_hash(struct command *cmd)
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 sign_evm_path(const char *file)
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 hmac_evm(const char *file, const char *key)
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 find(const char *path, int dts, find_cb_t func)
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;
}
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);
}
return err;
return do_cmd(cmd, ima_fix);
}
static int ima_clear(const char *path)
{
log_info("%s\n", path);
lremovexattr(path, "security.ima");
lremovexattr(path, "security.evm");
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 @@ struct command cmds[] = {
{"--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 @@ static struct option opts[] = {
{"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 struct option opts[] = {
};
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 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
params.hash_algo = optarg;
break;
case 'p':
if (optarg)
params.keypass = optarg;
else
params.keypass = get_password();
break;
case 'f':
sigfile = 1;
@ -1573,6 +1595,9 @@ int main(int argc, char *argv[])
case 'k':
params.keyfile = optarg;
break;
case 'i':
evm_immutable = true;
break;
case 't':
search_type = optarg;
break;
@ -1600,9 +1625,6 @@ int main(int argc, char *argv[])
}
}
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
if (argv[optind] == NULL)
usage();
else
@ -1623,6 +1645,6 @@ int main(int argc, char *argv[])
ERR_free_strings();
EVP_cleanup();
BIO_free(NULL);
return err;
}

View File

@ -108,6 +108,12 @@ struct h_misc_64 {
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 @@ struct libevm_params {
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_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len
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);

View File

@ -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 @@ struct libevm_params params = {
.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 @@ static int get_hash_algo_from_sig(unsigned char *sig)
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 @@ void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key)
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 @@ static RSA *read_priv_key(const char *keyfile, char *keypass)
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 @@ out:
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();
}