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

17 Commits
v0.5 ... v0.6

Author SHA1 Message Date
78ccd56afe License changed from LGPL to GPL as in COPYING
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-09-04 16:51:44 +03:00
f1ba3e7b45 Version 0.6 release
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-08-28 16:37:52 +03:00
d7d74e5648 Fix cleanup in the case of errors
Proper memory cleanup is not really necessary for command line
utility because all memory is cleaned up when it quits. But as
code does it most of the cases, fix other places.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-08-28 15:20:16 +03:00
15dab873b5 fix the crash when key file is not found
Error in error handling caused crash when key file is not found.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-08-27 15:44:18 +03:00
971b286169 make --imahash or --imasig optional for EVM signing
One might not want to change/set IMA xattr value when performing
EVM signing.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-08-13 16:55:14 +03:00
2406322914 perform uuid format checking and error handling
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-08-13 16:55:14 +03:00
b3a5fcbca2 make argument for '-u' option as optional
-u required to provide uuid or '-', which was confusing.
Now -u does not require '-' argument to read uuid automatically.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-08-13 16:55:10 +03:00
59ef0a0b99 Save full security.ima attribute to a file
Right now if -f option is passed in, we only save the actual signature to
a file and not the full security.ima attribute.

I think it makes more sense to save full security.ima attribute so that
it can act as detached signatures and one can install signature later.
That is signing can take place on build server and detached signatures
can be generated and these signatures can be installed later on target.

One can use following steps.

evmctl ima_sign -f -x -a sha256 /tmp/data.txt

hexdump -v -e '1/1 "%02x"' /tmp/data.txt.sig > /tmp/data.txt.sig.hex
printf "# file: /tmp/data.txt\nsecurity.ima=0x" | cat - /tmp/data.txt.sig.hex | setfattr --restore -

evmctl ima_verify /tmp/data.txt

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-08-09 15:57:26 +03:00
ab18c60ec1 Get signature version from the header
Currently we assume signature version is v1 until and unless -x is
specified on kernel command line. Given the fact that signature version
information is available in signature itself, it is much better to get
it from there and not require user to pass -x during verification phase.

If user passed -x on command line, then honor it.

Now one can do following.

	evmctl ima_sign -x /tmp/data.txt
	evmctl ima_verify /tmp/data.txt

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-08-09 15:57:26 +03:00
d9678295b9 Move key file selection to later phase
Following patch reads signature version from header and based
on that key file needs to be selected.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-08-09 15:57:18 +03:00
0df73005a3 Use enums for signature versions
Using enums for fixed values looks cleaner. Also I am planning to use
version field in more places in next patch. So use enums intead of
numbers like 1 and 2.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-08-09 15:55:53 +03:00
b49e2251a0 Let user specified hash algo take precedence
After applying previous patch, we will always get hash algo info from
signature and if user specified one on command line, that will be overridden.

This is like breaking old behavior. So keep track whether user specified
hash algo on command line or not. If user did not specify one then get
hash algo info from signature otherwise use the one user provided.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-08-09 15:55:49 +03:00
fa3c365cce Get hash algorithm info from the signature
If one signs a file using hash algo -sha256 then one needs to specify
signature during verification also. Otherwise evmctl using default sha1
for calculating hash and signature verification fails. One needs to
specify -a sha256 on command line even during signature verification
phase to make sure file is signed right.

I think that's completely unnecessary. A user is not always supposed
to know what algorithm was used to generate signature. User is only
concered with whether this signature is valid or not.

So retrieve hash algorithm info from signature and use that.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-07-15 18:02:02 +03:00
00caa1d5ba Put right hash algo info in digital signature version 1 header
hdr->hash for signature version 1 contains the info about what hash
algorithm has been used for signing the file. Currently we always set
hdr->hash to DIGEST_ALGO_SHA1. But one can sign file using SHA256 using
option "-a sha256". In that case we should put right hash algo info
in signature header. Fix it.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-07-15 18:01:05 +03:00
b48f4f9c7e Fix hash array size in verify_ima()
Now evmctl supports different hash algorithms and sha512 will produce
64 byte digest. verify_ima() still allocates only 20bytes to store hash.
This does not work with larger hashes.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-07-15 18:00:32 +03:00
16d40dbdf6 evmctl: Fix signature verification code for V2 digital signature
For V2 of digital signature we store signature at hdr->sig and not at
hdr->sig + 2. That's the property of V1 of signature.

Fix the verification code otherwise it fails with following message.

RSA_public_decrypt() failed: -1
error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01
error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
2013-07-10 16:45:38 +01:00
3f0c0a3c84 Fix verification using signature file
Signature file does not contain xattr prefix.
Add signature xattr prefix manually.

Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
2013-07-10 16:00:53 +01:00
7 changed files with 202 additions and 117 deletions

View File

@ -1,2 +1,5 @@
Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Dmitry Kasatkin <d.kasatkin@samsung.com>
CONTRIBUTORS:
Vivek Goyal <vgoyal@redhat.com>

View File

@ -1,3 +1,13 @@
2013-08-28 Dmitry Kasatkin <d.kasatkin@samsung.com>
version 0.6
* support for asymmetric crypto keys and new signature format (v2)
* fixes to set correct hash algo for digital signature v1
* uuid support for EVM
* signature verification support
* test scripts removed
* README updates
2012-05-18 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
version 0.3

View File

@ -1,6 +1,6 @@
SUBDIRS = src
#EXTRA_DIST = LEGAL acinclude.m4 include
EXTRA_DIST = autogen.sh
ACLOCAL_AMFLAGS = -I m4

11
README
View File

@ -15,7 +15,8 @@ Key and signature formats
EVM support (v2) in latest version of the kernel adds the file system UUID to
the HMAC calculation. It is controlled by the CONFIG_EVM_HMAC_VERSION and
version 2 is enabled by default. To include the UUID to the signature calculation,
it is necessary to provide '--uuid -' or '-u -' parameter to the 'sign' command.
it is necessary to provide '--uuid' or '-u' parameter to the 'sign' command.
UUID can be provided on command line in form of '-uUUID' or '--uuid=UUID'.
Latest kernel got IMA/EVM support for using X509 certificates and asymmetric key
support for verifying digital signatures. The new command line parameter
@ -121,15 +122,15 @@ Default private key: /etc/keys/privkey_evm.pem
Default X509 certificate: /etc/keys/x509_evm.der
Signing for using X509 certificates is done using '-x' or '--x509' parameter.
Signing for using new the EVM HMAC format is done using '-u -' or '--uuid -' parameter.
Signing for using new the EVM HMAC format is done using '-u' or '--uuid' parameter.
Sign file with EVM signature and use hash value for IMA - common case
$ evmctl sign [-u -] [-x] --imahash test.txt
$ evmctl sign [-u] [-x] --imahash test.txt
Sign file with both IMA and EVM signatures - for immutable files
$ evmctl sign [-u -] [-x] --imasig test.txt
$ evmctl sign [-u] [-x] --imasig test.txt
Sign file with IMA signature - for immutable files
@ -137,7 +138,7 @@ Sign file with IMA signature - for immutable files
Label whole filesystem with EVM signatures
$ find / \( -fstype rootfs -o -fstype ext4 \) -exec evmctl sign [-u -] [-x] --imahash '{}' \;
$ find / \( -fstype rootfs -o -fstype ext4 \) -exec evmctl sign [-u] [-x] --imahash '{}' \;
Label filesystem in fix mode - kernel sets correct values to IMA and EVM xattrs

View File

@ -1,7 +1,7 @@
# autoconf script
AC_PREREQ([2.65])
AC_INIT(ima-evm-utils, 0.3, dmitry.kasatkin@intel.com)
AC_INIT(ima-evm-utils, 0.6, d.kasatkin@samsung.com)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
@ -30,6 +30,9 @@ AC_SUBST(OPENSSL_LIBS)
AC_CHECK_HEADER(unistd.h)
AC_CHECK_HEADERS(openssl/conf.h)
AC_CHECK_HEADERS(attr/xattr.h, , [AC_MSG_ERROR([attr/xattr.h header not found. You need the libattr development package.])])
AC_CHECK_HEADERS(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])])
#debug support - yes for a while
PKG_ARG_ENABLE(debug, "yes", DEBUG, [Enable Debug support])
if test $pkg_cv_enable_debug = yes; then

View File

@ -3,7 +3,7 @@ Version: @PACKAGE_VERSION@
Release: 1%{?dist}
Summary: @PACKAGE_NAME@ - IMA/EVM control utility
Group: System/Libraries
License: LGPLv2
License: GPLv2
#URL:
Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root

View File

@ -1,26 +1,26 @@
/*
* evm-utils - IMA/EVM support utilities
* ima-evm-utils - IMA/EVM support utilities
*
* Copyright (C) 2011 Nokia Corporation
* Copyright (C) 2011,2012,2013 Intel Corporation
* Copyright (C) 2013 Samsung Electronics
*
* Authors:
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
* <dmitry.kasatkin@intel.com>
* <d.kasatkin@samsung.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* File: evmctl.c
* IMA/EVM control program
@ -108,6 +108,11 @@ enum digest_algo {
DIGEST_ALGO_MAX
};
enum digsig_version {
DIGSIG_VERSION_1 = 1,
DIGSIG_VERSION_2
};
struct pubkey_hdr {
uint8_t version; /* key format version */
uint32_t timestamp; /* key made, always 0 for now */
@ -244,12 +249,14 @@ static int xattr = 1;
static int sigdump;
static int digest;
static int digsig;
static char *hash_algo = "sha1";
static const char *hash_algo = "sha1";
static int user_hash_algo;
static char *keypass;
static int sigfile;
static int modsig;
static char *uuid_str;
static int x509;
static int user_sig_type;
static char *keyfile;
typedef int (*sign_hash_fn_t)(const char *algo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig);
@ -476,9 +483,20 @@ static RSA *read_priv_key(const char *keyfile)
return key;
}
static int sign_hash_v1(const char *algo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig)
int get_hash_algo_v1(const char *algo)
{
int err, len;
if (!strcmp(algo, "sha1"))
return DIGEST_ALGO_SHA1;
else if (!strcmp(algo, "sha256"))
return DIGEST_ALGO_SHA256;
return -1;
}
static int sign_hash_v1(const char *hashalgo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig)
{
int len = -1, hashalgo_idx;
SHA_CTX ctx;
unsigned char pub[1024];
RSA *key;
@ -495,10 +513,16 @@ static int sign_hash_v1(const char *algo, const unsigned char *hash, int size, c
return -1;
/* now create a new hash */
hdr->version = 1;
hdr->version = (uint8_t) DIGSIG_VERSION_1;
hdr->timestamp = time(NULL);
hdr->algo = PUBKEY_ALGO_RSA;
hdr->hash = DIGEST_ALGO_SHA1;
hashalgo_idx = get_hash_algo_v1(hashalgo);
if (hashalgo_idx < 0) {
log_err("Signature version 1 does not support hash algo %s\n",
hashalgo);
goto out;
}
hdr->hash = (uint8_t) hashalgo_idx;
len = key2bin(key, pub);
calc_keyid_v1(hdr->keyid, name, pub, len);
@ -512,15 +536,12 @@ static int sign_hash_v1(const char *algo, const unsigned char *hash, int size, c
log_info("sighash: ");
log_dump(sighash, sizeof(sighash));
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;
len = RSA_private_encrypt(sizeof(sighash), sighash, sig + sizeof(*hdr) + 2, key, RSA_PKCS1_PADDING);
if (len < 0) {
log_err("RSA_private_encrypt() failed: %d\n", len);
goto out;
}
len = err;
/* we add bit length of the signature to make it gnupg compatible */
blen = (uint16_t *) (sig + sizeof(*hdr));
*blen = __cpu_to_be16(len << 3);
@ -528,7 +549,8 @@ static int sign_hash_v1(const char *algo, const unsigned char *hash, int size, c
log_info("evm/ima signature: %d bytes\n", len);
if (sigdump || verbose >= LOG_INFO)
dump(sig, len);
out:
RSA_free(key);
return len;
}
@ -546,7 +568,7 @@ uint8_t get_hash_algo(const char *algo)
static int sign_hash_v2(const char *algo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig)
{
struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
int len;
int len = -1;
RSA *key;
char name[20];
unsigned char *buf;
@ -559,7 +581,7 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash, int size, c
if (!key)
return -1;
hdr->version = 2;
hdr->version = (uint8_t) DIGSIG_VERSION_2;
hdr->hash_algo = get_hash_algo(algo);
calc_keyid_v2(&hdr->keyid, name, key);
@ -568,16 +590,15 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash, int size, c
buf = malloc(size + asn1->size);
if (!buf)
return -1;
goto out;
memcpy(buf, asn1->data, asn1->size);
memcpy(buf + asn1->size, hash, size);
len = RSA_private_encrypt(size + asn1->size, buf, hdr->sig,
key, RSA_PKCS1_PADDING);
RSA_free(key);
if (len < 0) {
log_err("RSA_private_encrypt() failed: %d\n", len);
return -1;
goto out;
}
/* we add bit length of the signature to make it gnupg compatible */
@ -586,7 +607,10 @@ static int sign_hash_v2(const char *algo, const unsigned char *hash, int size, c
log_info("evm/ima signature: %d bytes\n", len);
if (sigdump || verbose >= LOG_INFO)
dump(sig, len);
out:
if (buf)
free(buf);
RSA_free(key);
return len;
}
@ -612,10 +636,16 @@ static int hex_to_bin(char ch)
return -1;
}
static void pack_uuid(const char *uuid_str, char *to)
static int pack_uuid(const char *uuid_str, char *uuid)
{
int i;
char *to = uuid;
for (i = 0; i < 16; ++i) {
if (!uuid_str[0] || !uuid_str[1]) {
log_err("wrong UUID format\n");
return -1;
}
*to++ = (hex_to_bin(*uuid_str) << 4) |
(hex_to_bin(*(uuid_str + 1)));
uuid_str += 2;
@ -624,10 +654,17 @@ static void pack_uuid(const char *uuid_str, char *to)
case 5:
case 7:
case 9:
if (*uuid_str != '-') {
log_err("wrong UUID format\n");
return -1;
}
uuid_str++;
continue;
}
}
log_info("uuid: ");
log_dump(uuid, 16);
return 0;
}
static int get_uuid(struct stat *st, char *uuid)
@ -638,10 +675,8 @@ static int get_uuid(struct stat *st, char *uuid)
FILE *fp;
size_t len;
if (uuid_str[0] != '-') {
pack_uuid(uuid_str, uuid);
return 0;
}
if (uuid_str[0] != '-')
return pack_uuid(uuid_str, uuid);
dev = st->st_dev;
major = (dev & 0xfff00) >> 8;
@ -663,12 +698,7 @@ static int get_uuid(struct stat *st, char *uuid)
return -1;
}
pack_uuid(_uuid, uuid);
log_info("uuid: ");
log_dump(uuid, 16);
return 0;
return pack_uuid(_uuid, uuid);
}
static int calc_evm_hash(const char *file, unsigned char *hash)
@ -1020,7 +1050,7 @@ static int sign_ima(const char *file, const char *key)
}
if (sigfile)
bin2file(file, "sig", sig + 1, len - 1);
bin2file(file, "sig", sig, len);
if (xattr) {
err = setxattr(file, "security.ima", sig, len, 0);
@ -1060,12 +1090,6 @@ static int cmd_sign_evm(struct command *cmd)
return -1;
}
if (!digsig && !digest) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
}
key = keyfile ? : "/etc/keys/privkey_evm.pem";
if (digsig) {
@ -1141,7 +1165,7 @@ static int verify_hash_v2(const unsigned char *hash, int size, unsigned char *si
if (!key)
return 1;
err = RSA_public_decrypt(siglen - sizeof(*hdr) - 2, sig + sizeof(*hdr) + 2, out, key, RSA_PKCS1_PADDING);
err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr), out, key, RSA_PKCS1_PADDING);
RSA_free(key);
if (err < 0) {
log_err("RSA_public_decrypt() failed: %d\n", err);
@ -1211,15 +1235,40 @@ static int cmd_verify_evm(struct command *cmd)
return verify_evm(file, key);
}
static int verify_ima(const char *file, const char *key)
static int get_hash_algo_from_sig(unsigned char *sig)
{
unsigned char hash[20];
unsigned char sig[1024];
int len;
uint8_t hashalgo;
len = calc_hash(file, hash);
if (len <= 1)
return len;
if (sig[0] == 1) {
hashalgo = ((struct signature_hdr *)sig)->hash;
if (hashalgo >= DIGEST_ALGO_MAX)
return -1;
switch (hashalgo) {
case DIGEST_ALGO_SHA1:
return PKEY_HASH_SHA1;
case DIGEST_ALGO_SHA256:
return PKEY_HASH_SHA256;
default:
return -1;
}
} else if (sig[0] == 2) {
hashalgo = ((struct signature_v2_hdr *)sig)->hash_algo;
if (hashalgo >= PKEY_HASH__LAST)
return -1;
return hashalgo;
} else
return -1;
}
static int verify_ima(const char *file)
{
unsigned char hash[64];
unsigned char sig[1024];
int len, hashlen;
int sig_hash_algo;
char *key;
if (xattr) {
len = getxattr(file, "security.ima", sig, sizeof(sig));
@ -1241,12 +1290,44 @@ static int verify_ima(const char *file, const char *key)
return -1;
}
return verify_hash(hash, sizeof(hash), sig + 1, len - 1, key);
/* If user specified an hash algo on command line, let it override */
if (!user_hash_algo) {
sig_hash_algo = get_hash_algo_from_sig(sig + 1);
if (sig_hash_algo < 0) {
log_err("Invalid signature\n");
return -1;
}
/* Use hash algorithm as retrieved from signature */
hash_algo = pkey_hash_algo[sig_hash_algo];
}
hashlen = calc_hash(file, hash);
if (hashlen <= 1)
return hashlen;
/* Get signature type from sig header if user did not enforce it */
if (!user_sig_type) {
if (sig[1] == DIGSIG_VERSION_1)
verify_hash = verify_hash_v1;
else if (sig[1] == DIGSIG_VERSION_2) {
verify_hash = verify_hash_v2;
/* Read pubkey from x509 cert */
x509 = 1;
}
}
/* Determine what key to use for verification*/
key = keyfile ? : x509 ?
"/etc/keys/x509_evm.der" :
"/etc/keys/pubkey_evm.pem";
return verify_hash(hash, hashlen, sig + 1, len - 1, key);
}
static int cmd_verify_ima(struct command *cmd)
{
char *key, *file = g_argv[optind++];
char *file = g_argv[optind++];
if (!file) {
log_err("Parameters missing\n");
@ -1254,21 +1335,17 @@ static int cmd_verify_ima(struct command *cmd)
return -1;
}
key = keyfile ? : x509 ?
"/etc/keys/x509_evm.der" :
"/etc/keys/pubkey_evm.pem";
return verify_ima(file, key);
return verify_ima(file);
}
static int cmd_import(struct command *cmd)
{
char *inkey, *ring = NULL;
unsigned char _pub[1024], *pub = _pub;
int id, len, err = -1;
int id, len, err = 0;
char name[20];
uint8_t keyid[8];
RSA *key = NULL;
RSA *key;
inkey = g_argv[optind++];
if (!inkey) {
@ -1284,7 +1361,7 @@ static int cmd_import(struct command *cmd)
key = read_pub_key(inkey);
if (!key)
goto out;
return 1;
if (x509) {
pub = file2bin(inkey, NULL, &len);
@ -1301,19 +1378,15 @@ static int cmd_import(struct command *cmd)
id = add_key(x509 ? "asymmetric" : "user", x509 ? NULL : name, pub, len, id);
if (id < 0) {
log_err("add_key failed\n");
goto out;
err = id;
} else {
log_info("keyid: %d\n", id);
printf("%d\n", id);
}
log_info("keyid: %d\n", id);
printf("%d\n", id);
err = 0;
out:
if (key)
RSA_free(key);
if (x509)
free(pub);
out:
RSA_free(key);
return err;
}
@ -1322,7 +1395,7 @@ out:
static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *hash)
{
struct stat st;
int fd, err;
int fd, err = -1;
uint32_t generation;
HMAC_CTX ctx;
unsigned int mdlen;
@ -1342,7 +1415,7 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
if (keylen > sizeof(evmkey)) {
log_err("key is too long\n");
return -1;
goto out;
}
/* EVM key is 128 bytes */
@ -1352,17 +1425,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);
return -1;
goto out;
}
if (fstat(fd, &st)) {
log_err("fstat() failed\n");
return -1;
goto out;
}
if (ioctl(fd, EXT34_IOC_GETVERSION, &generation)) {
log_err("ioctl() failed\n");
return -1;
goto out;
}
close(fd);
@ -1372,13 +1445,13 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
list_size = llistxattr(file, list, sizeof(list));
if (list_size <= 0) {
log_err("llistxattr() failed\n");
return -1;
goto out;
}
err = HMAC_Init(&ctx, evmkey, sizeof(evmkey), EVP_sha1());
if (!err) {
err = !HMAC_Init(&ctx, evmkey, sizeof(evmkey), EVP_sha1());
if (err) {
log_err("HMAC_Init() failed\n");
return 1;
goto out;
}
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
@ -1394,10 +1467,10 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
/*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) {
err = !HMAC_Update(&ctx, xattr_value, err);
if (err) {
log_err("HMAC_Update() failed\n");
return 1;
goto out_ctx_cleanup;
}
}
@ -1408,21 +1481,19 @@ 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) {
err = !HMAC_Update(&ctx, (const unsigned char *)&hmac_misc, sizeof(hmac_misc));
if (err) {
log_err("HMAC_Update() failed\n");
return 1;
goto out_ctx_cleanup;
}
err = HMAC_Final(&ctx, hash, &mdlen);
if (!err) {
err = !HMAC_Final(&ctx, hash, &mdlen);
if (err)
log_err("HMAC_Final() failed\n");
return 1;
}
out_ctx_cleanup:
HMAC_CTX_cleanup(&ctx);
out:
free(key);
return mdlen;
return err ?: mdlen;
}
static int hmac_evm(const char *file, const char *key)
@ -1461,12 +1532,6 @@ static int cmd_hmac_evm(struct command *cmd)
return -1;
}
if (!digsig && !digest) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
}
key = keyfile ? : "/etc/keys/privkey_evm.pem";
if (digsig) {
@ -1562,6 +1627,7 @@ static void usage(void)
" -x, --x509 signing key is in x509 DER format (signing v2 for using asymmetric keys)\n"
" -k, --key path to signing key (default keys are /etc/keys/{privkey,pubkey}_evm.pem)\n"
" -p, --pass password for encrypted signing key\n"
" -u, --uuid use file system UUID in HMAC calculation (EVM v2)\n"
" -n print result to stdout instead of setting xattr\n"
" -v increase verbosity level\n"
" -h, --help display this help and exit\n"
@ -1590,7 +1656,7 @@ static struct option opts[] = {
{"pass", 1, 0, 'p'},
{"sigfile", 0, 0, 'f'},
{"modsig", 0, 0, 'm'},
{"uuid", 1, 0, 'u'},
{"uuid", 2, 0, 'u'},
{"x509", 0, 0, 'x'},
{"key", 1, 0, 'k'},
{}
@ -1608,7 +1674,7 @@ int main(int argc, char *argv[])
verify_hash = verify_hash_v1;
while (1) {
c = getopt_long(argc, argv, "hvnsda:p:fu:xk:", opts, &lind);
c = getopt_long(argc, argv, "hvnsda:p:fu::xk:", opts, &lind);
if (c == -1)
break;
@ -1633,6 +1699,7 @@ int main(int argc, char *argv[])
break;
case 'a':
hash_algo = optarg;
user_hash_algo = 1;
break;
case 'p':
keypass = optarg;
@ -1646,12 +1713,13 @@ int main(int argc, char *argv[])
xattr = 0;
break;
case 'u':
uuid_str = optarg;
uuid_str = optarg ?: "-";
break;
case 'x':
x509 = 1;
sign_hash = sign_hash_v2;
verify_hash = verify_hash_v2;
user_sig_type = 1;
break;
case 'k':
keyfile = optarg;