11 Commits
v1.0 ... next

Author SHA1 Message Date
4928548d9d Add support for portable EVM format
Add a --portable argument that generates EVM signatures without using
the inode number and generation or fs UUID.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>

Changelog:
- immutable and portable flags are exclusive, prevent enabling both.
2017-11-16 15:02:40 -05:00
233dedffe9 Write out .sig file as security.ima xattr
To write the .sig file as security.ima xattr using setfattr first
requires converting the .sig file from binary to ascii-hex.  Although
this conversion can be done using hexdump, it is unnecessary when
calling setxattr.  This patch defines a new command called
"ima_setxattr", which calls lsetxattr() to write the .sig file as
the security.ima xattr.

Changelog:
- remove unnecessary copy
- fixed --sigfile option

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
2016-03-06 07:55:04 -05:00
3e2a67bdb0 script to build static evmctl version
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-10-01 22:42:45 +03:00
839a674580 Supply file attributes values on command line
Can be used by Android filesystem image creation tool.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-09-20 23:28:20 +03:00
e55d286ad6 Use single flag to indicate 'no'flag
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-09-20 23:15:32 +03:00
28d99354de Use byte range values
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-09-20 22:22:06 +03:00
ea5ccdf38f Newer kernels requires at least 64 byte keys
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
2015-09-20 22:22:00 +03:00
b0d13ba557 calc_evm_hmac/hash: avoid fd leak when ioctl fails
When opening the file succeeds but ioctl() then fails, the file must
be closed before returning.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
2015-09-09 23:02:01 +03:00
199311e6a5 ima_verify: ignore -n flag
"evmutil ima_verify -n <some file>" disabled using xattrs without enabling
using a signature file, resulting in the use of uninitialized memory in
ima_verify_signature() and thus unpredictable results.

Such a mode of operation makes no sense, so interpret -n as
documented ("print result to stdout instead of setting xattr") and ignore it
during ima_verify. Instead, switch between the two verification modes only
via the global sigfile variable.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
2015-09-09 22:50:45 +03:00
453d3db8a5 tpm_pcr_read: close file when returning early
When return from inside the for() loop, the open file was not
closed.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
2015-09-09 22:50:35 +03:00
fa0b30b15e add_dir_hash: fix DIR leak in case of failure
When bailing out of the function due to EVP_DigestUpdate()
failing, the DIR resources allocated with opendir() were
not freed.

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
2015-09-09 22:50:18 +03:00
5 changed files with 227 additions and 54 deletions

8
README
View File

@ -26,7 +26,7 @@ COMMANDS
--version --version
help <command> help <command>
import [--rsa] pubkey keyring import [--rsa] pubkey keyring
sign [-r] [--imahash | --imasig ] [--key key] [--pass password] file sign [-r] [--imahash | --imasig ] [--portable] [--key key] [--pass password] file
verify file verify file
ima_sign [--sigfile] [--key key] [--pass password] file ima_sign [--sigfile] [--key key] [--pass password] file
ima_verify file ima_verify file
@ -46,6 +46,7 @@ OPTIONS
-f, --sigfile store IMA signature in .sig file instead of xattr -f, --sigfile store IMA signature in .sig file instead of xattr
--rsa use RSA key type and signing scheme v1 --rsa use RSA key type and signing scheme v1
-k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem) -k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)
-o, --portable generate portable EVM signatures
-p, --pass password for encrypted signing key -p, --pass password for encrypted signing key
-r, --recursive recurse into directories (sign) -r, --recursive recurse into directories (sign)
-t, --type file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink) -t, --type file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink)
@ -95,7 +96,8 @@ Kernel configuration option CONFIG_EVM_ATTR_FSUUID controls whether to include
filesystem UUID into HMAC and enabled by default. Therefore evmctl also includes filesystem UUID into HMAC and enabled by default. Therefore evmctl also includes
fsuuid by default. Providing '--uuid' option without parameter allows to disable fsuuid by default. Providing '--uuid' option without parameter allows to disable
usage of fs uuid. Providing '--uuid=UUID' option with parameter allows to use usage of fs uuid. Providing '--uuid=UUID' option with parameter allows to use
custom UUID. custom UUID. Providing the '--portable' option will disable usage of the fs uuid
and also the inode number and generation.
Kernel configuration option CONFIG_EVM_EXTRA_SMACK_XATTRS controls whether to Kernel configuration option CONFIG_EVM_EXTRA_SMACK_XATTRS controls whether to
include additional SMACK extended attributes into HMAC. They are following: include additional SMACK extended attributes into HMAC. They are following:
@ -142,7 +144,7 @@ EVM encrypted key is used for EVM HMAC calculation:
keyctl pipe `keyctl search @u user kmk` > /etc/keys/kmk keyctl pipe `keyctl search @u user kmk` > /etc/keys/kmk
# create the EVM encrypted key # create the EVM encrypted key
keyctl add encrypted evm-key "new user:kmk 32" @u keyctl add encrypted evm-key "new user:kmk 64" @u
keyctl pipe `keyctl search @u encrypted evm-key` >/etc/keys/evm-key keyctl pipe `keyctl search @u encrypted evm-key` >/etc/keys/evm-key

4
build-static.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
gcc -static -o evmctl.static -include config.h src/evmctl.c src/libimaevm.c -lcrypto -lkeyutils -ldl

View File

@ -104,15 +104,25 @@ static int digest;
static int digsig; static int digsig;
static int sigfile; static int sigfile;
static char *uuid_str; 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 char *search_type;
static int recursive; static int recursive;
static int msize; static int msize;
static dev_t fs_dev; static dev_t fs_dev;
static bool evm_immutable; static bool evm_immutable;
static bool evm_portable;
#define HMAC_FLAG_UUID 0x0001 #define HMAC_FLAG_NO_UUID 0x0001
#define HMAC_FLAG_UUID_SET 0x0002 #define HMAC_FLAG_CAPS_SET 0x0002
static unsigned long hmac_flags = HMAC_FLAG_UUID;
static unsigned long hmac_flags;
typedef int (*find_cb_t)(const char *path); typedef int (*find_cb_t)(const char *path);
static int find(const char *path, int dts, find_cb_t func); static int find(const char *path, int dts, find_cb_t func);
@ -200,7 +210,7 @@ static int hex_to_bin(char ch)
return -1; 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; int hi, lo;
@ -214,7 +224,7 @@ static int hex2bin(uint8_t *dst, const char *src, size_t count)
if ((hi < 0) || (lo < 0)) if ((hi < 0) || (lo < 0))
return -1; return -1;
*dst++ = (hi << 4) | lo; *(uint8_t *)dst++ = (hi << 4) | lo;
} }
return 0; return 0;
} }
@ -275,7 +285,7 @@ static int get_uuid(struct stat *st, char *uuid)
FILE *fp; FILE *fp;
size_t len; size_t len;
if (hmac_flags & HMAC_FLAG_UUID_SET) if (uuid_str)
return pack_uuid(uuid_str, uuid); return pack_uuid(uuid_str, uuid);
dev = st->st_dev; dev = st->st_dev;
@ -320,10 +330,21 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
return -1; 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 (!evm_immutable) {
if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { if ((S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && !generation_str) {
/* we cannot at the momement to get generation of special files.. /* we cannot at the momement to get generation of
* kernel API does not support it */ special files kernel API does not support it */
int fd = open(file, 0); int fd = open(file, 0);
if (fd < 0) { if (fd < 0) {
@ -332,6 +353,7 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
} }
if (ioctl(fd, FS_IOC_GETVERSION, &generation)) { if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
log_err("ioctl() failed\n"); log_err("ioctl() failed\n");
close(fd);
return -1; return -1;
} }
close(fd); close(fd);
@ -352,14 +374,27 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
} }
for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
err = lgetxattr(file, *xattrname, xattr_value, sizeof(xattr_value)); if (!strcmp(*xattrname, XATTR_NAME_SELINUX) && selinux_str) {
if (err < 0) { strcpy(xattr_value, selinux_str);
log_info("no xattr: %s\n", *xattrname); err = strlen(selinux_str) + 1;
continue; } else if (!strcmp(*xattrname, XATTR_NAME_IMA) && ima_str) {
} hex2bin(xattr_value, ima_str, strlen(ima_str) / 2);
if (!find_xattr(list, list_size, *xattrname)) { err = strlen(ima_str) / 2;
log_info("skipping xattr: %s\n", *xattrname); } else if (!strcmp(*xattrname, XATTR_NAME_CAPS) && (hmac_flags & HMAC_FLAG_CAPS_SET)) {
continue; 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_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);*/
log_info("name: %s, size: %d\n", *xattrname, err); log_info("name: %s, size: %d\n", *xattrname, err);
@ -384,8 +419,10 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
struct h_misc *hmac = (struct h_misc *)&hmac_misc; struct h_misc *hmac = (struct h_misc *)&hmac_misc;
hmac_size = sizeof(*hmac); hmac_size = sizeof(*hmac);
hmac->ino = st.st_ino; if (!evm_portable) {
hmac->generation = generation; hmac->ino = st.st_ino;
hmac->generation = generation;
}
hmac->uid = st.st_uid; hmac->uid = st.st_uid;
hmac->gid = st.st_gid; hmac->gid = st.st_gid;
hmac->mode = st.st_mode; hmac->mode = st.st_mode;
@ -393,8 +430,10 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc; struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc;
hmac_size = sizeof(*hmac); hmac_size = sizeof(*hmac);
hmac->ino = st.st_ino; if (!evm_portable) {
hmac->generation = generation; hmac->ino = st.st_ino;
hmac->generation = generation;
}
hmac->uid = st.st_uid; hmac->uid = st.st_uid;
hmac->gid = st.st_gid; hmac->gid = st.st_gid;
hmac->mode = st.st_mode; hmac->mode = st.st_mode;
@ -402,8 +441,10 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc; struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc;
hmac_size = sizeof(*hmac); hmac_size = sizeof(*hmac);
hmac->ino = st.st_ino; if (!evm_portable) {
hmac->generation = generation; hmac->ino = st.st_ino;
hmac->generation = generation;
}
hmac->uid = st.st_uid; hmac->uid = st.st_uid;
hmac->gid = st.st_gid; hmac->gid = st.st_gid;
hmac->mode = st.st_mode; hmac->mode = st.st_mode;
@ -418,7 +459,8 @@ static int calc_evm_hash(const char *file, unsigned char *hash)
return 1; return 1;
} }
if (!evm_immutable && (hmac_flags & HMAC_FLAG_UUID)) { if (!evm_immutable && !evm_portable &&
!(hmac_flags & HMAC_FLAG_NO_UUID)) {
err = get_uuid(&st, uuid); err = get_uuid(&st, uuid);
if (err) if (err)
return -1; return -1;
@ -455,7 +497,10 @@ static int sign_evm(const char *file, const char *key)
/* add header */ /* add header */
len++; len++;
sig[0] = EVM_IMA_XATTR_DIGSIG; if (evm_portable)
sig[0] = EVM_XATTR_PORTABLE_DIGSIG;
else
sig[0] = EVM_IMA_XATTR_DIGSIG;
if (evm_immutable) if (evm_immutable)
sig[1] = 3; /* immutable signature version */ sig[1] = 3; /* immutable signature version */
@ -734,19 +779,17 @@ static int verify_ima(const char *file)
unsigned char sig[1024]; unsigned char sig[1024];
int len; int len;
if (xattr) {
len = lgetxattr(file, "security.ima", sig, sizeof(sig));
if (len < 0) {
log_err("getxattr failed: %s\n", file);
return len;
}
}
if (sigfile) { if (sigfile) {
void *tmp = file2bin(file, "sig", &len); void *tmp = file2bin(file, "sig", &len);
memcpy(sig, tmp, len); memcpy(sig, tmp, len);
free(tmp); free(tmp);
} else {
len = lgetxattr(file, "security.ima", sig, sizeof(sig));
if (len < 0) {
log_err("getxattr failed: %s\n", file);
return len;
}
} }
return ima_verify_signature(file, sig, len); return ima_verify_signature(file, sig, len);
@ -765,6 +808,37 @@ static int cmd_verify_ima(struct command *cmd)
return verify_ima(file); 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) static int cmd_import(struct command *cmd)
{ {
char *inkey, *ring = NULL; char *inkey, *ring = NULL;
@ -837,6 +911,42 @@ out:
return err; return err;
} }
static int setxattr_ima(const char *file, char *sig_file)
{
unsigned char *sig;
int len, err;
if (sig_file)
sig = file2bin(sig_file, NULL, &len);
else
sig = file2bin(file, "sig", &len);
if (!sig)
return 0;
err = lsetxattr(file, "security.ima", sig, len, 0);
if (err < 0)
log_err("setxattr failed: %s\n", file);
free(sig);
return err;
}
static int cmd_setxattr_ima(struct command *cmd)
{
char *file, *sig = NULL;
if (sigfile)
sig = g_argv[optind++];
file = g_argv[optind++];
if (!file) {
log_err("Parameters missing\n");
print_usage(cmd);
return -1;
}
return setxattr_ima(file, sig);
}
#define MAX_KEY_SIZE 128 #define MAX_KEY_SIZE 128
static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *hash) static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *hash)
@ -887,6 +997,7 @@ static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *h
} }
if (ioctl(fd, FS_IOC_GETVERSION, &generation)) { if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
log_err("ioctl() failed\n"); log_err("ioctl() failed\n");
close(fd);
goto out; goto out;
} }
close(fd); close(fd);
@ -1143,6 +1254,7 @@ static int tpm_pcr_read(int idx, uint8_t *pcr, int len)
{ {
FILE *fp; FILE *fp;
char *p, pcr_str[7], buf[70]; /* length of the TPM string */ char *p, pcr_str[7], buf[70]; /* length of the TPM string */
int result = -1;
sprintf(pcr_str, "PCR-%d", idx); sprintf(pcr_str, "PCR-%d", idx);
@ -1158,11 +1270,12 @@ static int tpm_pcr_read(int idx, uint8_t *pcr, int len)
break; break;
if (!strncmp(p, pcr_str, 6)) { if (!strncmp(p, pcr_str, 6)) {
hex2bin(pcr, p + 7, len); hex2bin(pcr, p + 7, len);
return 0; result = 0;
break;
} }
} }
fclose(fp); fclose(fp);
return -1; return result;
} }
#define TCG_EVENT_NAME_LEN_MAX 255 #define TCG_EVENT_NAME_LEN_MAX 255
@ -1450,6 +1563,7 @@ static void usage(void)
" -f, --sigfile store IMA signature in .sig file instead of xattr\n" " -f, --sigfile store IMA signature in .sig file instead of xattr\n"
" --rsa use RSA key type and signing scheme v1\n" " --rsa use RSA key type and signing scheme v1\n"
" -k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n" " -k, --key path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n"
" -o, --portable generate portable EVM signatures\n"
" -p, --pass password for encrypted signing key\n" " -p, --pass password for encrypted signing key\n"
" -r, --recursive recurse into directories (sign)\n" " -r, --recursive recurse into directories (sign)\n"
" -t, --type file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink)\n" " -t, --type file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink)\n"
@ -1460,6 +1574,14 @@ static void usage(void)
" --smack use extra SMACK xattrs for EVM\n" " --smack use extra SMACK xattrs for EVM\n"
" --m32 force EVM hmac/signature for 32 bit target system\n" " --m32 force EVM hmac/signature for 32 bit target system\n"
" --m64 force EVM hmac/signature for 64 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" " -v increase verbosity level\n"
" -h, --help display this help and exit\n" " -h, --help display this help and exit\n"
"\n"); "\n");
@ -1469,10 +1591,12 @@ struct command cmds[] = {
{"--version", NULL, 0, ""}, {"--version", NULL, 0, ""},
{"help", cmd_help, 0, "<command>"}, {"help", cmd_help, 0, "<command>"},
{"import", cmd_import, 0, "[--rsa] pubkey keyring", "Import public key into the keyring.\n"}, {"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"}, {"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"}, {"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_verify", cmd_verify_ima, 0, "file", "Verify IMA signature (for debugging).\n"},
{"ima_setxattr", cmd_setxattr_ima, 0, "[--sigfile file]", "Set IMA signature from sigfile\n"},
{"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\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_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"}, {"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM xattrs in fix mode.\n"},
@ -1498,8 +1622,17 @@ static struct option opts[] = {
{"recursive", 0, 0, 'r'}, {"recursive", 0, 0, 'r'},
{"m32", 0, 0, '3'}, {"m32", 0, 0, '3'},
{"m64", 0, 0, '6'}, {"m64", 0, 0, '6'},
{"smack", 0, 0, 256}, {"portable", 0, 0, 'o'},
{"version", 0, 0, 257}, {"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},
{} {}
}; };
@ -1546,7 +1679,7 @@ int main(int argc, char *argv[])
g_argc = argc; g_argc = argc;
while (1) { while (1) {
c = getopt_long(argc, argv, "hvnsda:p::fu::k:t:ri", opts, &lind); c = getopt_long(argc, argv, "hvnsda:op::fu::k:t:ri", opts, &lind);
if (c == -1) if (c == -1)
break; break;
@ -1580,14 +1713,11 @@ int main(int argc, char *argv[])
break; break;
case 'f': case 'f':
sigfile = 1; sigfile = 1;
xattr = 0;
break; break;
case 'u': case 'u':
uuid_str = optarg; uuid_str = optarg;
if (uuid_str) if (!uuid_str)
hmac_flags |= HMAC_FLAG_UUID_SET; hmac_flags |= HMAC_FLAG_NO_UUID;
else
hmac_flags &= ~HMAC_FLAG_UUID;
break; break;
case '1': case '1':
params.x509 = 0; params.x509 = 0;
@ -1596,7 +1726,16 @@ int main(int argc, char *argv[])
params.keyfile = optarg; params.keyfile = optarg;
break; break;
case 'i': case 'i':
evm_immutable = true; if (evm_portable)
log_err("Portable and immutable options are exclusive, ignoring immutable option.");
else
evm_immutable = true;
break;
case 'o':
if (evm_immutable)
log_err("Portable and immutable options are exclusive, ignoring portable option.");
else
evm_portable = true;
break; break;
case 't': case 't':
search_type = optarg; search_type = optarg;
@ -1610,13 +1749,38 @@ int main(int argc, char *argv[])
case '6': case '6':
msize = 64; msize = 64;
break; break;
case 256: case 128:
evm_config_xattrnames = evm_extra_smack_xattrs; evm_config_xattrnames = evm_extra_smack_xattrs;
break; break;
case 257: case 129:
printf("evmctl %s\n", VERSION); printf("evmctl %s\n", VERSION);
exit(0); exit(0);
break; 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 '?': case '?':
exit(1); exit(1);
break; break;

View File

@ -82,6 +82,7 @@ enum evm_ima_xattr_type {
EVM_XATTR_HMAC, EVM_XATTR_HMAC,
EVM_IMA_XATTR_DIGSIG, EVM_IMA_XATTR_DIGSIG,
IMA_XATTR_DIGEST_NG, IMA_XATTR_DIGEST_NG,
EVM_XATTR_PORTABLE_DIGSIG,
}; };
struct h_misc { struct h_misc {

View File

@ -214,6 +214,7 @@ static int add_dir_hash(const char *file, EVP_MD_CTX *ctx)
DIR *dir; DIR *dir;
unsigned long long ino, off; unsigned long long ino, off;
unsigned int type; unsigned int type;
int result = 0;
dir = opendir(file); dir = opendir(file);
if (!dir) { if (!dir) {
@ -233,13 +234,14 @@ static int add_dir_hash(const char *file, EVP_MD_CTX *ctx)
err |= EVP_DigestUpdate(ctx, &type, sizeof(type)); err |= EVP_DigestUpdate(ctx, &type, sizeof(type));
if (!err) { if (!err) {
log_err("EVP_DigestUpdate() failed\n"); log_err("EVP_DigestUpdate() failed\n");
return 1; result = 1;
break;
} }
} }
closedir(dir); closedir(dir);
return 0; return result;
} }
static int add_link_hash(const char *path, EVP_MD_CTX *ctx) static int add_link_hash(const char *path, EVP_MD_CTX *ctx)
@ -373,7 +375,7 @@ int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, int
unsigned char sighash[20]; unsigned char sighash[20];
struct signature_hdr *hdr = (struct signature_hdr *)sig; struct signature_hdr *hdr = (struct signature_hdr *)sig;
log_info("hash: "); log_info("hash-v1: ");
log_dump(hash, size); log_dump(hash, size);
key = read_pub_key(keyfile, 0); key = read_pub_key(keyfile, 0);
@ -587,7 +589,7 @@ void calc_keyid_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len
id = __be64_to_cpup((__be64 *) keyid); id = __be64_to_cpup((__be64 *) keyid);
sprintf(str, "%llX", (unsigned long long)id); 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) void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key)
@ -719,7 +721,7 @@ int sign_hash_v1(const char *hashalgo, const unsigned char *hash, int size, cons
blen = (uint16_t *) (sig + sizeof(*hdr)); blen = (uint16_t *) (sig + sizeof(*hdr));
*blen = __cpu_to_be16(len << 3); *blen = __cpu_to_be16(len << 3);
len += sizeof(*hdr) + 2; len += sizeof(*hdr) + 2;
log_info("evm/ima signature: %d bytes\n", len); log_info("evm/ima signature-v1: %d bytes\n", len);
out: out:
RSA_free(key); RSA_free(key);
return len; return len;