Compare commits

...

2 Commits
master ... next

Author SHA1 Message Date
Matthew Garrett
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
Mimi Zohar
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
3 changed files with 74 additions and 13 deletions

6
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:

View File

@ -117,6 +117,7 @@ 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_NO_UUID 0x0001 #define HMAC_FLAG_NO_UUID 0x0001
#define HMAC_FLAG_CAPS_SET 0x0002 #define HMAC_FLAG_CAPS_SET 0x0002
@ -418,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;
@ -427,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;
@ -436,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;
@ -452,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_NO_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;
@ -489,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 */
@ -828,7 +839,6 @@ static int cmd_convert(struct command *cmd)
return err; return err;
} }
static int cmd_import(struct command *cmd) static int cmd_import(struct command *cmd)
{ {
char *inkey, *ring = NULL; char *inkey, *ring = NULL;
@ -901,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)
@ -1517,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"
@ -1549,6 +1596,7 @@ struct command cmds[] = {
{"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"},
@ -1574,6 +1622,7 @@ 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'},
{"portable", 0, 0, 'o'},
{"smack", 0, 0, 128}, {"smack", 0, 0, 128},
{"version", 0, 0, 129}, {"version", 0, 0, 129},
{"inode", 1, 0, 130}, {"inode", 1, 0, 130},
@ -1630,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;
@ -1677,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;

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 {