10 Commits

Author SHA1 Message Date
1e2934d9a3 version 0.1.0 2012-09-06 14:08:53 +03:00
c13fce4028 remove unused parameter
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:53 +03:00
aa2f6e9b63 Changed time_t timestamp type to uint32_t
time_t is actually long and is different on 32 and 64 bit architectures.
Format of the signatures should not depend on the architecture and should
be the same. Changed timestamp to uint32_t like in GPG.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:53 +03:00
ff071501d0 Added missing CFLAGS
Added missing CFLAGS

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
f2b486e053 Added signature write to .sig file
To enable module signature verification working on file systems
without extended attributes, or to be able to copy modules by methods,
which does not support extended attribute copying, it is necessary
to store signature in the file. This patch provides command line parameter
for storing signature in .sig file.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
e3f11d343a Change set_xattr to xattr.
set_xattr changed to xattr.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
7e89de565e Changed to conform Linux kernel coding style
Changed to conform Linux kernel coding style, except 80 characters
line length limit.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
e91cb01e9a added password parameter for using encrypted keys
Added password parameter for using encrypted keys.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
b0966fd243 added openssl initialization and error reporting
Added openssl initialization and error reporting.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
0b197c4d30 minor fixes
- error message
- command info

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
2012-09-06 14:08:52 +03:00
4 changed files with 194 additions and 268 deletions

View File

@ -4,20 +4,3 @@ SUBDIRS = src tests
ACLOCAL_AMFLAGS = -I m4
SRCS = $(HOME)/rpmbuild/SOURCES
SPEC = $(PACKAGE_NAME).spec
pkgname = $(PACKAGE_NAME)-$(PACKAGE_VERSION)
tarname = $(pkgname).tar.gz
$(tarname):
git tag -f v$(PACKAGE_VERSION)
git archive --format=tar --prefix=$(pkgname)/ v$(PACKAGE_VERSION) $(FILES) | gzip >$@;
tar: $(tarname)
rpm: $(tarname)
cp $(tarname) $(SRCS)/
rpmbuild -ba --nodeps $(SPEC)
.PHONY: $(tarname)

View File

@ -1,7 +1,7 @@
# autoconf script
AC_PREREQ([2.65])
AC_INIT(ima-evm-utils, 0.1.1, dmitry.kasatkin@intel.com)
AC_INIT(evm-utils, 0.1, dmitry.kasatkin@intel.com)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
@ -47,7 +47,7 @@ fi
AC_CONFIG_FILES([Makefile
src/Makefile
tests/Makefile
ima-evm-utils.spec
evm-utils.spec
])
AC_OUTPUT

View File

@ -1,7 +1,7 @@
Name: @PACKAGE_NAME@
Version: @PACKAGE_VERSION@
Release: 1%{?dist}
Summary: @PACKAGE_NAME@ - IMA/EVM control utility
Summary: evm-utils - IMA/EVM support utilities
Group: System/Libraries
License: LGPLv2
#URL:
@ -12,10 +12,11 @@ BuildRequires: autoconf
BuildRequires: automake
BuildRequires: openssl-devel
BuildRequires: libattr-devel
BuildRequires: readline-devel
BuildRequires: keyutils-libs-devel
%description
This package provide IMA/EVM control utility
This library provides EVM support utilities.
%prep
%setup -q
@ -47,6 +48,6 @@ exit 0
%{_libdir}/*
%changelog
* Thu Apr 05 2012 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
- Initial RPM spec file
* Wed Jul 20 2011 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
- Initial package for MeeGo

View File

@ -2,7 +2,7 @@
* evm-utils - IMA/EVM support utilities
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011, 2012 Intel Corporation
* Copyright (C) 2011 Intel Corporation
*
* Authors:
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
@ -74,7 +74,7 @@
#define log_dump(p, len) do_log_dump(LOG_INFO, p, len)
#define log_info(fmt, args...) do_log(LOG_INFO, fmt, ##args)
#define log_err(fmt, args...) do_log(LOG_ERR, fmt, ##args)
#define log_errno(fmt, args...) do_log(LOG_ERR, fmt ": errno: %s (%d)\n", ##args, strerror(errno), errno)
#define log_errno(fmt, args...) do_log(LOG_ERR, fmt ": %s (%d)\n", ##args, strerror(errno), errno)
#define DATA_SIZE 4096
#define SHA1_HASH_LEN 20
@ -200,7 +200,7 @@ static int bin2file(const char *file, const char *ext, const unsigned char *data
fp = fopen(name, "w");
if (!fp) {
log_err("Unable to open %s for writing\n", name);
log_errno("Unable to open %s for writing", name);
return -1;
}
err = fwrite(data, len, 1, fp);
@ -208,16 +208,16 @@ static int bin2file(const char *file, const char *ext, const unsigned char *data
return err;
}
static unsigned char *file2bin(const char *file, int *size)
static char *file2bin(const char *file, int *size)
{
FILE *fp;
int len;
unsigned char *data;
char *data;
len = get_filesize(file);
fp = fopen(file, "r");
if (!fp) {
log_err("Unable to open %s\n", file);
log_errno("Unable to open %s", file);
return NULL;
}
data = malloc(len);
@ -270,14 +270,14 @@ static int read_key(const char *inkey, unsigned char *pub)
fp = fopen(inkey, "r");
if (!fp) {
log_err("read key failed from file %s\n", inkey);
log_errno("read key failed from file %s", inkey);
return -1;
}
key1 = PEM_read_RSA_PUBKEY(fp, &key, NULL, NULL);
fclose(fp);
if (!key1) {
log_err("PEM_read_RSA_PUBKEY() failed\n");
log_errno("PEM_read_RSA_PUBKEY() failed");
return -1;
}
@ -324,14 +324,14 @@ static int sign_hash(const unsigned char *hash, int size, const char *keyfile, u
fp = fopen(keyfile, "r");
if (!fp) {
log_err("Unable to open keyfile %s\n", keyfile);
log_errno("Unable to open keyfile %s", keyfile);
return -1;
}
key1 = PEM_read_RSAPrivateKey(fp, &key, NULL, keypass);
fclose(fp);
if (!key1) {
log_err("PEM_read_RSAPrivateKey() failed\n");
return 1;
log_errno("RSAPrivateKey() failed");
return -1;
}
/* now create a new hash */
@ -355,8 +355,8 @@ static int sign_hash(const unsigned char *hash, int size, const char *keyfile, u
err = RSA_private_encrypt(sizeof(sighash), sighash, sig + sizeof(*hdr) + 2, key, RSA_PKCS1_PADDING);
RSA_free(key);
if (err < 0) {
log_err("RSA_private_encrypt() failed: %d\n", err);
return 1;
log_errno("RSA_private_encrypt() failed: %d", err);
return -1;
}
len = err;
@ -372,18 +372,6 @@ static int sign_hash(const unsigned char *hash, int size, const char *keyfile, u
return len;
}
static int find_xattr(const char *list, int list_size, const char *xattr)
{
int len;
for (; list_size > 0; len++, list_size -= len, list += len) {
len = strlen(list);
if (!strcmp(list, xattr))
return 1;
}
return 0;
}
static int calc_evm_hash(const char *file, unsigned char *hash)
{
struct stat st;
@ -394,22 +382,20 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
unsigned int mdlen;
char **xattrname;
char xattr_value[1024];
char list[1024];
ssize_t list_size;
fd = open(file, 0);
if (fd < 0) {
log_err("Unable to open %s\n", file);
log_errno("Unable to open %s", file);
return -1;
}
if (fstat(fd, &st)) {
log_err("fstat() failed\n");
log_errno("fstat() failed");
return -1;
}
if (ioctl(fd, EXT34_IOC_GETVERSION, &generation)) {
log_err("ioctl() failed\n");
log_errno("ioctl() failed");
return -1;
}
@ -417,32 +403,22 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
log_info("generation: %u\n", generation);
list_size = llistxattr(file, list, sizeof(list));
if (list_size <= 0) {
log_err("llistxattr() failed\n");
return -1;
}
md = EVP_get_digestbyname("sha1");
if (!md) {
log_err("EVP_get_digestbyname() failed\n");
return 1;
log_errno("EVP_get_digestbyname() failed");
return -1;
}
err = EVP_DigestInit(&ctx, md);
if (!err) {
log_err("EVP_DigestInit() failed\n");
return 1;
log_errno("EVP_DigestInit() failed");
return -1;
}
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
err = getxattr(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);
log_info("no attr: %s\n", *xattrname);
continue;
}
/*log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);*/
@ -450,8 +426,8 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
log_debug_dump(xattr_value, err);
err = EVP_DigestUpdate(&ctx, xattr_value, err);
if (!err) {
log_err("EVP_DigestUpdate() failed\n");
return 1;
log_errno("EVP_DigestUpdate() failed");
return -1;
}
}
@ -464,36 +440,34 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
err = EVP_DigestUpdate(&ctx, (const unsigned char *)&hmac_misc, sizeof(hmac_misc));
if (!err) {
log_err("EVP_DigestUpdate() failed\n");
return 1;
log_errno("EVP_DigestUpdate() failed");
return -1;
}
err = EVP_DigestFinal(&ctx, hash, &mdlen);
if (!err) {
log_err("EVP_DigestFinal() failed\n");
return 1;
log_errno("EVP_DigestFinal() failed");
return -1;
}
return mdlen;
return 0;
}
static int sign_evm(const char *file, const char *key)
{
unsigned char hash[20];
unsigned char sig[1024] = "\x03";
int len, err;
int err;
len = calc_evm_hash(file, hash);
if (len <= 1)
return len;
calc_evm_hash(file, hash);
len = sign_hash(hash, len, key, sig + 1);
if (len <= 1)
return len;
err = sign_hash(hash, sizeof(hash), key, sig + 1);
if (err < 0)
return err;
if (xattr) {
err = setxattr(file, "security.evm", sig, len + 1, 0);
err = setxattr(file, "security.evm", sig, err + 1, 0);
if (err < 0) {
log_err("setxattr failed: %s\n", file);
log_errno("setxattr failed: %s", file);
return err;
}
}
@ -513,26 +487,26 @@ static int calc_file_hash(const char *file, uint8_t *hash)
data = malloc(bs);
if (!data) {
log_err("malloc failed\n");
log_errno("malloc failed");
return -1;
}
fp = fopen(file, "r");
if (!fp) {
log_err("Unable to open %s\n", file);
log_errno("Unable to open %s", file);
return -1;
}
md = EVP_get_digestbyname(hash_algo);
if (!md) {
log_err("EVP_get_digestbyname() failed\n");
return 1;
log_errno("EVP_get_digestbyname() failed");
return -1;
}
err = EVP_DigestInit(&ctx, md);
if (!err) {
log_err("EVP_DigestInit() failed\n");
return 1;
log_errno("EVP_DigestInit() failed");
return -1;
}
for (size = get_fdsize(fileno(fp)); size; size -= len) {
@ -540,22 +514,22 @@ static int calc_file_hash(const char *file, uint8_t *hash)
err = fread(data, len, 1, fp);
if (!err) {
if (ferror(fp)) {
log_err("fread() error\n\n");
log_errno("fread() error\n");
return -1;
}
break;
}
err = EVP_DigestUpdate(&ctx, data, len);
if (!err) {
log_err("EVP_DigestUpdate() failed\n");
return 1;
log_errno("EVP_DigestUpdate() failed");
return -1;
}
}
err = EVP_DigestFinal(&ctx, hash, &mdlen);
if (!err) {
log_err("EVP_DigestFinal() failed\n");
return 1;
log_errno("EVP_DigestFinal() failed");
return -1;
}
fclose(fp);
@ -583,20 +557,20 @@ static int calc_dir_hash(const char *file, uint8_t *hash)
dir = opendir(file);
if (!dir) {
log_err("Unable to open %s\n", file);
log_errno("Unable to open %s", file);
return -1;
}
md = EVP_get_digestbyname(hash_algo);
if (!md) {
log_err("EVP_get_digestbyname() failed\n");
return 1;
log_errno("EVP_get_digestbyname() failed");
return -1;
}
err = EVP_DigestInit(&ctx, md);
if (!err) {
log_err("EVP_DigestInit() failed\n");
return 1;
log_errno("EVP_DigestInit() failed");
return -1;
}
while ((de = readdir(dir))) {
@ -620,21 +594,21 @@ static int calc_dir_hash(const char *file, uint8_t *hash)
log_debug("entry: ino: %llu, %s\n", (unsigned long long)ino, cur->de.d_name);
err = EVP_DigestUpdate(&ctx, cur->de.d_name, strlen(cur->de.d_name));
if (!err) {
log_err("EVP_DigestUpdate() failed\n");
return 1;
log_errno("EVP_DigestUpdate() failed");
return -1;
}
err = EVP_DigestUpdate(&ctx, &ino, sizeof(ino));
if (!err) {
log_err("EVP_DigestUpdate() failed\n");
return 1;
log_errno("EVP_DigestUpdate() failed");
return -1;
}
free(cur);
}
err = EVP_DigestFinal(&ctx, hash, &mdlen);
if (!err) {
log_err("EVP_DigestFinal() failed\n");
return 1;
log_errno("EVP_DigestFinal() failed");
return -1;
}
closedir(dir);
@ -645,33 +619,33 @@ static int calc_dir_hash(const char *file, uint8_t *hash)
static int hash_ima(const char *file)
{
unsigned char hash[65] = "\x01"; /* MAX hash size + 1 */
int len, err;
int err;
struct stat st;
/* Need to know the file length */
err = stat(file, &st);
if (err < 0) {
log_err("stat() failed\n");
log_errno("stat() failed");
return err;
}
if (S_ISDIR(st.st_mode))
len = calc_dir_hash(file, hash + 1);
err = calc_dir_hash(file, hash + 1);
else
len = calc_file_hash(file, hash + 1);
if (len <= 1)
return len;
err = calc_file_hash(file, hash + 1);
if (err < 0)
return err;
if (verbose >= LOG_INFO)
log_info("hash: ");
if (!xattr || verbose >= LOG_INFO)
dump(hash, len + 1);
dump(hash, err + 1);
if (xattr) {
err = setxattr(file, "security.ima", hash, len + 1, 0);
err = setxattr(file, "security.ima", hash, err + 1, 0);
if (err < 0) {
log_err("setxattr failed: %s\n", file);
log_errno("setxattr failed: %s", file);
return err;
}
}
@ -686,7 +660,7 @@ static int cmd_hash_ima(struct command *cmd)
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
return 1;
}
return hash_ima(file);
@ -696,23 +670,23 @@ static int sign_ima(const char *file, const char *key)
{
unsigned char hash[64];
unsigned char sig[1024] = "\x03";
int len, err;
int err;
len = calc_file_hash(file, hash);
if (len <= 1)
return len;
err = calc_file_hash(file, hash);
if (err < 0)
return err;
len = sign_hash(hash, len, key, sig + 1);
if (len <= 1)
return len;
err = sign_hash(hash, err, key, sig + 1);
if (err < 0)
return err;
if (sigfile)
bin2file(file, "sig", sig, len + 1);
bin2file(file, "sig", sig, err + 1);
if (xattr) {
err = setxattr(file, "security.ima", sig, len + 1, 0);
err = setxattr(file, "security.ima", sig, err + 1, 0);
if (err < 0) {
log_err("setxattr failed: %s\n", file);
log_errno("setxattr failed: %s", file);
return err;
}
}
@ -727,7 +701,7 @@ static int cmd_sign_ima(struct command *cmd)
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
return 1;
}
key = g_argv[optind++];
@ -746,13 +720,7 @@ static int cmd_sign_evm(struct command *cmd)
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
}
if (!digsig && !digest) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
return 1;
}
key = g_argv[optind++];
@ -789,14 +757,14 @@ static int verify_hash(const unsigned char *hash, int size, unsigned char *sig,
fp = fopen(keyfile, "r");
if (!fp) {
log_err("Unable to open keyfile %s\n", keyfile);
log_errno("Unable to open keyfile %s", keyfile);
return -1;
}
key1 = PEM_read_RSA_PUBKEY(fp, &key, NULL, NULL);
fclose(fp);
if (!key1) {
log_err("PEM_read_RSA_PUBKEY() failed\n");
return 1;
log_errno("PEM_read_RSA_PUBKEY() failed");
return -1;
}
SHA1_Init(&ctx);
@ -809,14 +777,14 @@ static int verify_hash(const unsigned char *hash, int size, unsigned char *sig,
err = RSA_public_decrypt(siglen - sizeof(*hdr) - 2, sig + sizeof(*hdr) + 2, out, key, RSA_PKCS1_PADDING);
RSA_free(key);
if (err < 0) {
log_err("RSA_public_decrypt() failed: %d\n", err);
return 1;
log_errno("RSA_public_decrypt() failed: %d", err);
return -1;
}
len = err;
if (len != sizeof(sighash) || memcmp(out, sighash, len) != 0) {
log_err("Verification failed: %d\n", err);
log_errno("Verification failed: %d", err);
return -1;
} else {
/*log_info("Verification is OK\n");*/
@ -830,24 +798,22 @@ static int verify_evm(const char *file, const char *key)
{
unsigned char hash[20];
unsigned char sig[1024];
int len;
int err;
len = calc_evm_hash(file, hash);
if (len <= 1)
return len;
calc_evm_hash(file, hash);
len = getxattr(file, "security.evm", sig, sizeof(sig));
if (len < 0) {
log_err("getxattr failed\n");
return len;
err = getxattr(file, "security.evm", sig, sizeof(sig));
if (err < 0) {
log_errno("getxattr failed");
return err;
}
if (sig[0] != 0x03) {
log_err("security.evm has not signature\n");
return -1;
log_errno("security.evm has not signature");
return err;
}
return verify_hash(hash, sizeof(hash), sig + 1, len - 1, key);
return verify_hash(hash, sizeof(hash), sig + 1, err - 1, key);
}
static int cmd_verify_evm(struct command *cmd)
@ -857,7 +823,7 @@ static int cmd_verify_evm(struct command *cmd)
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
return 1;
}
key = g_argv[optind++];
@ -897,21 +863,18 @@ static int cmd_convert(struct command *cmd)
return 0;
}
static int cmd_import(struct command *cmd)
static int cmd_import_bin(struct command *cmd)
{
int len;
char *inkey, *ring = NULL;
unsigned char _key[1024], *key = _key;
int id, len;
char name[20];
char *key, name[20];
key_serial_t id;
uint8_t keyid[8];
inkey = g_argv[optind++];
if (!inkey) {
if (binkey)
if (!inkey)
inkey = "/etc/keys/pubkey_evm.bin";
else
inkey = "/etc/keys/pubkey_evm.pem";
} else
ring = g_argv[optind++];
if (!ring)
@ -919,15 +882,53 @@ static int cmd_import(struct command *cmd)
else
id = atoi(ring);
if (binkey) {
key = file2bin(inkey, &len);
if (!key)
return -1;
} else {
calc_keyid(keyid, name, (unsigned char *)key, len);
log_info("Importing public key %s from file %s into keyring %d\n", name, inkey, id);
id = add_key("user", name, key, len, id);
if (id < 0) {
log_errno("add_key failed");
return -1;
}
log_info("keyid: %d\n", id);
printf("%d\n", id);
free(key);
return 0;
}
static int cmd_import(struct command *cmd)
{
char *inkey, *ring = NULL;
unsigned char key[1024];
int id, len;
char name[20];
uint8_t keyid[8];
if (binkey)
return cmd_import_bin(cmd);
inkey = g_argv[optind++];
if (!inkey)
inkey = "/etc/keys/pubkey_evm.pem";
else
ring = g_argv[optind++];
if (!ring)
id = KEY_SPEC_USER_KEYRING;
else
id = atoi(ring);
len = read_key(inkey, key);
if (len < 0)
return -1;
}
calc_keyid(keyid, name, key, len);
@ -935,16 +936,13 @@ static int cmd_import(struct command *cmd)
id = add_key("user", name, key, len, id);
if (id < 0) {
log_err("add_key failed\n");
log_errno("add_key failed");
return -1;
}
log_info("keyid: %d\n", id);
printf("%d\n", id);
if (binkey)
free(key);
return 0;
}
@ -959,20 +957,18 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
unsigned int mdlen;
char **xattrname;
unsigned char xattr_value[1024];
unsigned char *key;
char *key;
int keylen;
unsigned char evmkey[MAX_KEY_SIZE];
char list[1024];
ssize_t list_size;
key = file2bin(keyfile, &keylen);
if (!key) {
log_err("Unable to read a key: %s\n\n", keyfile);
log_errno("Unable to read a key: %s\n", keyfile);
return -1;
}
if (keylen > sizeof(evmkey)) {
log_err("key is too long\n");
log_errno("key is too long\n");
return -1;
}
@ -982,17 +978,17 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
fd = open(file, 0);
if (fd < 0) {
log_err("Unable to open %s\n", file);
log_errno("Unable to open %s", file);
return -1;
}
if (fstat(fd, &st)) {
log_err("fstat() failed\n");
log_errno("fstat() failed");
return -1;
}
if (ioctl(fd, EXT34_IOC_GETVERSION, &generation)) {
log_err("ioctl() failed\n");
log_errno("ioctl() failed");
return -1;
}
@ -1000,36 +996,18 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
log_info("generation: %u\n", generation);
list_size = llistxattr(file, list, sizeof(list));
if (list_size <= 0) {
log_err("llistxattr() failed\n");
return -1;
}
err = HMAC_Init(&ctx, evmkey, sizeof(evmkey), EVP_sha1());
if (!err) {
log_err("HMAC_Init() failed\n");
return 1;
}
HMAC_Init(&ctx, evmkey, sizeof(evmkey), EVP_sha1());
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
err = getxattr(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);
log_info("no attr: %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);
log_debug_dump(xattr_value, err);
err = HMAC_Update(&ctx, xattr_value, err);
if (!err) {
log_err("HMAC_Update() failed\n");
return 1;
}
HMAC_Update(&ctx, xattr_value, err);
}
memset(&hmac_misc, 0, sizeof(hmac_misc));
@ -1039,41 +1017,32 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
hmac_misc.gid = st.st_gid;
hmac_misc.mode = st.st_mode;
err = HMAC_Update(&ctx, (const unsigned char *)&hmac_misc, sizeof(hmac_misc));
if (!err) {
log_err("HMAC_Update() failed\n");
return 1;
}
err = HMAC_Final(&ctx, hash, &mdlen);
if (!err) {
log_err("HMAC_Final() failed\n");
return 1;
}
HMAC_Update(&ctx, (const unsigned char *)&hmac_misc, sizeof(hmac_misc));
HMAC_Final(&ctx, hash, &mdlen);
HMAC_CTX_cleanup(&ctx);
free(key);
return mdlen;
return 0;
}
static int hmac_evm(const char *file, const char *key)
{
unsigned char hash[20];
unsigned char sig[1024] = "\x02";
int len, err;
int err;
len = calc_evm_hmac(file, key, hash);
if (len <= 1)
return len;
calc_evm_hmac(file, key, hash);
log_info("hmac: ");
log_dump(hash, len);
memcpy(sig + 1, hash, len);
log_dump(hash, sizeof(hash));
memcpy(sig + 1, hash, sizeof(hash));
err = sizeof(hash);
if (xattr) {
err = setxattr(file, "security.evm", sig, len + 1, 0);
err = setxattr(file, "security.evm", sig, err + 1, 0);
if (err < 0) {
log_err("setxattr failed: %s\n", file);
log_errno("setxattr failed: %s", file);
return err;
}
}
@ -1089,13 +1058,7 @@ static int cmd_hmac_evm(struct command *cmd)
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
}
if (!digsig && !digest) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
return 1;
}
key = g_argv[optind++];
@ -1127,7 +1090,8 @@ static void print_full_usage(struct command *cmd)
if (cmd->name)
printf("usage: %s %s\n", cmd->name, cmd->arg ? cmd->arg : "");
if (cmd->msg)
printf("%s", cmd->msg);
printf("description:\n%s", cmd->msg);
}
static int print_command_usage(struct command *cmds, char *command)
@ -1141,20 +1105,18 @@ static int print_command_usage(struct command *cmds, char *command)
}
}
printf("invalid command: %s\n", command);
return -1;
return 1;
}
static void print_all_usage(struct command *cmds)
{
struct command *cmd;
printf("commands:\n");
for (cmd = cmds; cmd->name; cmd++) {
if (cmd->arg)
printf(" %s %s\n", cmd->name, cmd->arg);
printf("%s %s\n", cmd->name, cmd->arg);
else if (cmd->msg)
printf(" %s", cmd->msg);
printf("%s", cmd->msg);
}
}
@ -1181,40 +1143,26 @@ static int cmd_help(struct command *cmd)
static void usage(void)
{
printf("Usage: evmctl [-v] <command> [OPTIONS]\n");
printf("Usage: evmctl <command> [parameters..]\n");
print_all_usage(cmds);
printf(
"\n"
" -a, --hashalgo sha1 (default), sha224, sha256, sha384, sha512\n"
" -s, --imasig also make IMA signature\n"
" -d, --imahash also make IMA hash\n"
" -f, --sigfile store IMA signature in .sig file instead of xattr\n"
" -b, --bin signing key is in binary format\n"
" -p, --pass password for encrypted signing key\n"
" -n print result to stdout instead of setting xattr\n"
" -v increase verbosity level\n"
" -h, --help display this help and exit\n"
"\n");
}
struct command cmds[] = {
{"help", cmd_help, 0, "<command>"},
{"import", cmd_import, 0, "[--bin] pubkey keyring", "Import public key (PEM/bin) into the keyring.\n"},
{"import", cmd_import, 0, "[--bin] inkey keyring", "Import public key (PEM/bin) into the keyring.\n"},
{"convert", cmd_convert, 0, "inkey outkey", "Convert PEM public key into IMA/EVM kernel friendly format.\n"},
{"sign", cmd_sign_evm, 0, "[--imahash | --imasig ] [--pass password] file [key]", "Sign file metadata.\n"},
{"sign", cmd_sign_evm, 0, "[--imahash | --imasig ] file [key]", "Sign file metadata.\n"},
{"verify", cmd_verify_evm, 0, "file", "Verify EVM signature (for debugging).\n"},
{"ima_sign", cmd_sign_ima, 0, "[--sigfile] [--pass password] file [key]", "Make file content signature.\n"},
{"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"},
#ifdef DEBUG
{"hmac", cmd_hmac_evm, 0, "[--imahash | --imasig ] file [key]", "Sign file metadata with HMAC using symmetric key (for testing purpose).\n"},
#endif
{"ima_sign", cmd_sign_ima, 0, "[--sigfile] file [key]", "Sign file content.\n"},
{"ima_hash", cmd_hash_ima, 0, "file", "Hash file content.\n"},
{"hmac", cmd_hmac_evm, 0, "[--imahash | --imasig ] file [key]", "Sign file metadata with HMAC (for debugging).\n"},
{0, 0, 0, NULL}
};
static struct option opts[] = {
{"help", 0, 0, 'h'},
{"inkey", 1, 0, 'k'},
{"imasig", 0, 0, 's'},
{"imahash", 0, 0, 'd'},
{"hashalgo", 1, 0, 'a'},
@ -1233,7 +1181,7 @@ int main(int argc, char *argv[])
g_argc = argc;
while (1) {
c = getopt_long(argc, argv, "hvnsda:bp:f", opts, &lind);
c = getopt_long(argc, argv, "hk:vnsda:bp:f", opts, &lind);
if (c == -1)
break;
@ -1242,6 +1190,9 @@ int main(int argc, char *argv[])
usage();
exit(0);
break;
case 'k':
printf("inkey: %s\n", optarg);
break;
case 'v':
verbose++;
break;
@ -1283,17 +1234,8 @@ int main(int argc, char *argv[])
else
err = call_command(cmds, argv[optind++]);
if (err) {
unsigned long err;
if (errno)
log_err("errno: %s (%d)\n", strerror(errno), errno);
for (;;) {
err = ERR_get_error();
if (!err)
break;
log_err("%s\n", ERR_error_string(err, NULL));
}
}
if (err)
log_err("error: %s\n", ERR_error_string(ERR_get_error(), NULL));
ERR_free_strings();
EVP_cleanup();