Blame src/evmctl.c

Packit Service 087331
/*
Packit Service 087331
 * ima-evm-utils - IMA/EVM support utilities
Packit Service 087331
 *
Packit Service 087331
 * Copyright (C) 2011 Nokia Corporation
Packit Service 087331
 * Copyright (C) 2011,2012,2013 Intel Corporation
Packit Service 087331
 * Copyright (C) 2013,2014 Samsung Electronics
Packit Service 087331
 *
Packit Service 087331
 * Authors:
Packit Service 087331
 * Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
Packit Service 087331
 *                 <dmitry.kasatkin@intel.com>
Packit Service 087331
 *                 <d.kasatkin@samsung.com>
Packit Service 087331
 *
Packit Service 087331
 * This program is free software; you can redistribute it and/or
Packit Service 087331
 * modify it under the terms of the GNU General Public License
Packit Service 087331
 * version 2 as published by the Free Software Foundation.
Packit Service 087331
 *
Packit Service 087331
 * This program is distributed in the hope that it will be useful,
Packit Service 087331
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 087331
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 087331
 * GNU General Public License for more details.
Packit Service 087331
 *
Packit Service 087331
 * You should have received a copy of the GNU General Public License
Packit Service 087331
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 087331
 *
Packit Service 087331
 * As a special exception, the copyright holders give permission to link the
Packit Service 087331
 * code of portions of this program with the OpenSSL library under certain
Packit Service 087331
 * conditions as described in each individual source file and distribute
Packit Service 087331
 * linked combinations including the program with the OpenSSL library. You
Packit Service 087331
 * must comply with the GNU General Public License in all respects
Packit Service 087331
 * for all of the code used other than as permitted herein. If you modify
Packit Service 087331
 * file(s) with this exception, you may extend this exception to your
Packit Service 087331
 * version of the file(s), but you are not obligated to do so. If you do not
Packit Service 087331
 * wish to do so, delete this exception statement from your version. If you
Packit Service 087331
 * delete this exception statement from all source files in the program,
Packit Service 087331
 * then also delete it in the license file.
Packit Service 087331
 *
Packit Service 087331
 * File: evmctl.c
Packit Service 087331
 *	 IMA/EVM control program
Packit Service 087331
 */
Packit Service 087331
Packit Service 087331
#include <sys/types.h>
Packit Service 087331
#include <sys/param.h>
Packit Service 087331
#include <sys/stat.h>
Packit Service 087331
#include <sys/ioctl.h>
Packit Service 087331
#include <fcntl.h>
Packit Service 087331
#include <unistd.h>
Packit Service 087331
#include <stdlib.h>
Packit Service 087331
#include <stdio.h>
Packit Service 087331
#include <stdint.h>
Packit Service 087331
#include <string.h>
Packit Service 087331
#include <dirent.h>
Packit Service 087331
#include <sys/xattr.h>
Packit Service 087331
#include <linux/xattr.h>
Packit Service 087331
#include <getopt.h>
Packit Service 087331
#include <keyutils.h>
Packit Service 087331
#include <ctype.h>
Packit Service 087331
#include <termios.h>
Packit Service 087331
#include <assert.h>
Packit Service 087331
Packit Service 087331
#include <openssl/sha.h>
Packit Service 087331
#include <openssl/pem.h>
Packit Service 087331
#include <openssl/hmac.h>
Packit Service 087331
#include <openssl/err.h>
Packit Service 087331
#include <openssl/rsa.h>
Packit Service 087331
#include <openssl/engine.h>
Packit Service 087331
#include "hash_info.h"
Packit Service 087331
#include "pcr.h"
Packit Service 087331
#include "utils.h"
Packit Service 087331
Packit Service 087331
#ifndef XATTR_APPAARMOR_SUFFIX
Packit Service 087331
#define XATTR_APPARMOR_SUFFIX "apparmor"
Packit Service 087331
#define XATTR_NAME_APPARMOR XATTR_SECURITY_PREFIX XATTR_APPARMOR_SUFFIX
Packit Service 087331
#endif
Packit Service 087331
Packit Service 087331
#define USE_FPRINTF
Packit Service 087331
Packit Service 087331
#include "imaevm.h"
Packit Service 087331
Packit Service 087331
static char *evm_default_xattrs[] = {
Packit Service 087331
	XATTR_NAME_SELINUX,
Packit Service 087331
	XATTR_NAME_SMACK,
Packit Service 087331
	XATTR_NAME_APPARMOR,
Packit Service 087331
	XATTR_NAME_IMA,
Packit Service 087331
	XATTR_NAME_CAPS,
Packit Service 087331
	NULL
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
static char *evm_extra_smack_xattrs[] = {
Packit Service 087331
	XATTR_NAME_SELINUX,
Packit Service 087331
	XATTR_NAME_SMACK,
Packit Service 087331
	XATTR_NAME_SMACKEXEC,
Packit Service 087331
	XATTR_NAME_SMACKTRANSMUTE,
Packit Service 087331
	XATTR_NAME_SMACKMMAP,
Packit Service 087331
	XATTR_NAME_APPARMOR,
Packit Service 087331
	XATTR_NAME_IMA,
Packit Service 087331
	XATTR_NAME_CAPS,
Packit Service 087331
	NULL
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
static char **evm_config_xattrnames = evm_default_xattrs;
Packit Service 087331
Packit Service 087331
struct command {
Packit Service 087331
	char *name;
Packit Service 087331
	int (*func)(struct command *cmd);
Packit Service 087331
	int cmd;
Packit Service 087331
	char *arg;
Packit Service 087331
	char *msg;		/* extra info message */
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
static int g_argc;
Packit Service 087331
static char **g_argv;
Packit Service 087331
static int xattr = 1;
Packit Service 087331
static bool check_xattr;
Packit Service 087331
static int sigdump;
Packit Service 087331
static int digest;
Packit Service 087331
static int digsig;
Packit Service 087331
static int sigfile;
Packit Service 087331
static char *uuid_str;
Packit Service 087331
static char *ino_str;
Packit Service 087331
static char *uid_str;
Packit Service 087331
static char *gid_str;
Packit Service 087331
static char *mode_str;
Packit Service 087331
static char *generation_str;
Packit Service 087331
static char *caps_str;
Packit Service 087331
static char *ima_str;
Packit Service 087331
static char *selinux_str;
Packit Service 087331
static char *search_type;
Packit Service 087331
static int verify_list_sig;
Packit Service 087331
static int recursive;
Packit Service 087331
static int msize;
Packit Service 087331
static dev_t fs_dev;
Packit Service 087331
static bool evm_immutable;
Packit Service 087331
static bool evm_portable;
Packit Service 087331
Packit Service 087331
#define HMAC_FLAG_NO_UUID	0x0001
Packit Service 087331
#define HMAC_FLAG_CAPS_SET	0x0002
Packit Service 087331
Packit Service 087331
static unsigned long hmac_flags;
Packit Service 087331
Packit Service 087331
typedef int (*find_cb_t)(const char *path);
Packit Service 087331
static int find(const char *path, int dts, find_cb_t func);
Packit Service 087331
Packit Service 087331
#define REG_MASK	(1 << DT_REG)
Packit Service 087331
#define DIR_MASK	(1 << DT_DIR)
Packit Service 087331
#define LNK_MASK	(1 << DT_LNK)
Packit Service 087331
#define CHR_MASK	(1 << DT_CHR)
Packit Service 087331
#define BLK_MASK	(1 << DT_BLK)
Packit Service 087331
Packit Service 087331
struct command cmds[];
Packit Service 087331
static void print_usage(struct command *cmd);
Packit Service 087331
Packit Service 087331
static const char *xattr_ima = "security.ima";
Packit Service 087331
static const char *xattr_evm = "security.evm";
Packit Service 087331
Packit Service 087331
struct tpm_bank_info {
Packit Service 087331
	int digest_size;
Packit Service 087331
	int supported;
Packit Service 087331
	const char *algo_name;
Packit Service 087331
	uint8_t digest[MAX_DIGEST_SIZE];
Packit Service 087331
	uint8_t pcr[NUM_PCRS][MAX_DIGEST_SIZE];
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
/* One --pcrs file per hash-algorithm/bank */
Packit Service 087331
#define MAX_PCRFILE 2
Packit Service 087331
static char *pcrfile[MAX_PCRFILE];
Packit Service 087331
static unsigned npcrfile;
Packit Service 087331
Packit Service 087331
static int bin2file(const char *file, const char *ext, const unsigned char *data, int len)
Packit Service 087331
{
Packit Service 087331
	FILE *fp;
Packit Service 087331
	char name[strlen(file) + (ext ? strlen(ext) : 0) + 2];
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	if (ext)
Packit Service 087331
		sprintf(name, "%s.%s", file, ext);
Packit Service 087331
	else
Packit Service 087331
		sprintf(name, "%s", file);
Packit Service 087331
Packit Service 087331
	log_info("Writing to %s\n", name);
Packit Service 087331
Packit Service 087331
	fp = fopen(name, "w");
Packit Service 087331
	if (!fp) {
Packit Service 087331
		log_err("Failed to open: %s\n", name);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
	err = fwrite(data, len, 1, fp);
Packit Service 087331
	fclose(fp);
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static unsigned char *file2bin(const char *file, const char *ext, int *size)
Packit Service 087331
{
Packit Service 087331
	FILE *fp;
Packit Service 087331
	size_t len;
Packit Service 087331
	unsigned char *data;
Packit Service 087331
	char name[strlen(file) + (ext ? strlen(ext) : 0) + 2];
Packit Service 087331
	struct stat stats;
Packit Service 087331
Packit Service 087331
	if (ext)
Packit Service 087331
		sprintf(name, "%s.%s", file, ext);
Packit Service 087331
	else
Packit Service 087331
		sprintf(name, "%s", file);
Packit Service 087331
Packit Service 087331
	log_info("Reading to %s\n", name);
Packit Service 087331
Packit Service 087331
	fp = fopen(name, "r");
Packit Service 087331
	if (!fp) {
Packit Service 087331
		log_err("Failed to open: %s\n", name);
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
	if (fstat(fileno(fp), &stats) == -1) {
Packit Service 087331
		log_err("Failed to fstat: %s (%s)\n", name, strerror(errno));
Packit Service 087331
		fclose(fp);
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
	len = stats.st_size;
Packit Service 087331
Packit Service 087331
	data = malloc(len);
Packit Service 087331
	if (!data) {
Packit Service 087331
		log_err("Failed to malloc %zu bytes: %s\n", len, name);
Packit Service 087331
		fclose(fp);
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
	if (fread(data, len, 1, fp) != 1) {
Packit Service 087331
		log_err("Failed to fread %zu bytes: %s\n", len, name);
Packit Service 087331
		fclose(fp);
Packit Service 087331
		free(data);
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
	fclose(fp);
Packit Service 087331
Packit Service 087331
	*size = (int)len;
Packit Service 087331
	return data;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int find_xattr(const char *list, int list_size, const char *xattr)
Packit Service 087331
{
Packit Service 087331
	int len;
Packit Service 087331
Packit Service 087331
	for (; list_size > 0; len++, list_size -= len, list += len) {
Packit Service 087331
		len = strlen(list);
Packit Service 087331
		if (!strcmp(list, xattr))
Packit Service 087331
			return 1;
Packit Service 087331
	}
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
Packit Service 087331
#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
Packit Service 087331
Packit Service 087331
const char hex_asc[] = "0123456789abcdef";
Packit Service 087331
Packit Service 087331
/* this is faster than fprintf - makes sense? */
Packit Service 087331
static void bin2hex(uint8_t *buf, size_t buflen, FILE *stream)
Packit Service 087331
{
Packit Service 087331
	char asciihex[2];
Packit Service 087331
Packit Service 087331
	for (; buflen--; buf++) {
Packit Service 087331
		asciihex[0] = hex_asc_hi(*buf);
Packit Service 087331
		asciihex[1] = hex_asc_lo(*buf);
Packit Service 087331
		fwrite(asciihex, 2, 1, stream);
Packit Service 087331
	}
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int pack_uuid(const char *uuid_str, char *uuid)
Packit Service 087331
{
Packit Service 087331
	int i;
Packit Service 087331
	char *to = uuid;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < 16; ++i) {
Packit Service 087331
		if (!uuid_str[0] || !uuid_str[1]) {
Packit Service 087331
			log_err("wrong UUID format\n");
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
		*to++ = (hex_to_bin(*uuid_str) << 4) |
Packit Service 087331
			(hex_to_bin(*(uuid_str + 1)));
Packit Service 087331
		uuid_str += 2;
Packit Service 087331
		switch (i) {
Packit Service 087331
		case 3:
Packit Service 087331
		case 5:
Packit Service 087331
		case 7:
Packit Service 087331
		case 9:
Packit Service 087331
			if (*uuid_str != '-') {
Packit Service 087331
				log_err("wrong UUID format\n");
Packit Service 087331
				return -1;
Packit Service 087331
			}
Packit Service 087331
			uuid_str++;
Packit Service 087331
			continue;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
	log_info("uuid: ");
Packit Service 087331
	log_dump(uuid, 16);
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int get_uuid(struct stat *st, char *uuid)
Packit Service 087331
{
Packit Service 087331
	uint32_t dev;
Packit Service 087331
	unsigned minor, major;
Packit Service 087331
	char path[PATH_MAX], _uuid[37];
Packit Service 087331
	FILE *fp;
Packit Service 087331
	size_t len;
Packit Service 087331
Packit Service 087331
	if (uuid_str)
Packit Service 087331
		return pack_uuid(uuid_str, uuid);
Packit Service 087331
Packit Service 087331
	dev = st->st_dev;
Packit Service 087331
	major = (dev & 0xfff00) >> 8;
Packit Service 087331
	minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
Packit Service 087331
Packit Service 087331
	log_debug("dev: %u:%u\n", major, minor);
Packit Service 087331
	sprintf(path, "blkid -s UUID -o value /dev/block/%u:%u", major, minor);
Packit Service 087331
Packit Service 087331
	fp = popen(path, "r");
Packit Service 087331
	if (!fp)
Packit Service 087331
		goto err;
Packit Service 087331
Packit Service 087331
	len = fread(_uuid, 1, sizeof(_uuid), fp);
Packit Service 087331
	pclose(fp);
Packit Service 087331
	if (len != sizeof(_uuid))
Packit Service 087331
		goto err;
Packit Service 087331
Packit Service 087331
	return pack_uuid(_uuid, uuid);
Packit Service 087331
err:
Packit Service 087331
	log_err("Failed to read UUID. Root access might require.\n");
Packit Service 087331
	return -1;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int calc_evm_hash(const char *file, unsigned char *hash)
Packit Service 087331
{
Packit Service 087331
        const EVP_MD *md;
Packit Service 087331
	struct stat st;
Packit Service 087331
	int err;
Packit Service 087331
	uint32_t generation = 0;
Packit Service 087331
	EVP_MD_CTX *pctx;
Packit Service 087331
	unsigned int mdlen;
Packit Service 087331
	char **xattrname;
Packit Service 087331
	char xattr_value[1024];
Packit Service 087331
	char list[1024];
Packit Service 087331
	ssize_t list_size;
Packit Service 087331
	char uuid[16];
Packit Service 087331
	struct h_misc_64 hmac_misc;
Packit Service 087331
	int hmac_size;
Packit Service 087331
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 087331
	EVP_MD_CTX ctx;
Packit Service 087331
	pctx = &ctx;
Packit Service 087331
#else
Packit Service 087331
	pctx = EVP_MD_CTX_new();
Packit Service 087331
#endif
Packit Service 087331
Packit Service 087331
	if (lstat(file, &st)) {
Packit Service 087331
		log_err("Failed to stat: %s\n", file);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (generation_str)
Packit Service 087331
		generation = strtoul(generation_str, NULL, 10);
Packit Service 087331
	if (ino_str)
Packit Service 087331
		st.st_ino = strtoul(ino_str, NULL, 10);
Packit Service 087331
	if (uid_str)
Packit Service 087331
		st.st_uid = strtoul(uid_str, NULL, 10);
Packit Service 087331
	if (gid_str)
Packit Service 087331
		st.st_gid = strtoul(gid_str, NULL, 10);
Packit Service 087331
	if (mode_str)
Packit Service 087331
		st.st_mode = strtoul(mode_str, NULL, 10);
Packit Service 087331
Packit Service 087331
	if (!evm_immutable) {
Packit Service 087331
		if ((S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) && !generation_str) {
Packit Service 087331
			/* we cannot at the momement to get generation of
Packit Service 087331
			   special files kernel API does not support it */
Packit Service 087331
			int fd = open(file, 0);
Packit Service 087331
Packit Service 087331
			if (fd < 0) {
Packit Service 087331
				log_err("Failed to open: %s\n", file);
Packit Service 087331
				return -1;
Packit Service 087331
			}
Packit Service 087331
			if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
Packit Service 087331
				log_err("ioctl() failed\n");
Packit Service 087331
				close(fd);
Packit Service 087331
				return -1;
Packit Service 087331
			}
Packit Service 087331
			close(fd);
Packit Service 087331
		}
Packit Service 087331
		log_info("generation: %u\n", generation);
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	list_size = llistxattr(file, list, sizeof(list));
Packit Service 087331
	if (list_size < 0) {
Packit Service 087331
		log_err("llistxattr() failed\n");
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	md = EVP_get_digestbyname(imaevm_params.hash_algo);
Packit Service 087331
	if (!md) {
Packit Service 087331
		log_err("EVP_get_digestbyname(%s) failed\n",
Packit Service 087331
			imaevm_params.hash_algo);
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestInit(pctx, md);
Packit Service 087331
	if (!err) {
Packit Service 087331
		log_err("EVP_DigestInit() failed\n");
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
Packit Service 087331
		if (!strcmp(*xattrname, XATTR_NAME_SELINUX) && selinux_str) {
Packit Service 087331
			err = strlen(selinux_str) + 1;
Packit Service 087331
			if (err > sizeof(xattr_value)) {
Packit Service 087331
				log_err("selinux[%u] value is too long to fit into xattr[%zu]\n",
Packit Service 087331
					err, sizeof(xattr_value));
Packit Service 087331
				return -1;
Packit Service 087331
			}
Packit Service 087331
			strcpy(xattr_value, selinux_str);
Packit Service 087331
		} else if (!strcmp(*xattrname, XATTR_NAME_IMA) && ima_str) {
Packit Service 087331
			err = strlen(ima_str) / 2;
Packit Service 087331
			if (err > sizeof(xattr_value)) {
Packit Service 087331
				log_err("ima[%u] value is too long to fit into xattr[%zu]\n",
Packit Service 087331
					err, sizeof(xattr_value));
Packit Service 087331
				return -1;
Packit Service 087331
			}
Packit Service 087331
			hex2bin(xattr_value, ima_str, err);
Packit Service 087331
		} else if (!strcmp(*xattrname, XATTR_NAME_CAPS) && (hmac_flags & HMAC_FLAG_CAPS_SET)) {
Packit Service 087331
			if (!caps_str)
Packit Service 087331
				continue;
Packit Service 087331
			err = strlen(caps_str);
Packit Service 087331
			if (err >= sizeof(xattr_value)) {
Packit Service 087331
				log_err("caps[%u] value is too long to fit into xattr[%zu]\n",
Packit Service 087331
					err + 1, sizeof(xattr_value));
Packit Service 087331
				return -1;
Packit Service 087331
			}
Packit Service 087331
			strcpy(xattr_value, caps_str);
Packit Service 087331
		} else {
Packit Service 087331
			err = lgetxattr(file, *xattrname, xattr_value, sizeof(xattr_value));
Packit Service 087331
			if (err < 0) {
Packit Service 087331
				log_info("no xattr: %s\n", *xattrname);
Packit Service 087331
				continue;
Packit Service 087331
			}
Packit Service 087331
			if (!find_xattr(list, list_size, *xattrname)) {
Packit Service 087331
				log_info("skipping xattr: %s\n", *xattrname);
Packit Service 087331
				continue;
Packit Service 087331
			}
Packit Service 087331
		}
Packit Service 087331
		/*log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);*/
Packit Service 087331
		log_info("name: %s, size: %d\n", *xattrname, err);
Packit Service 087331
		log_debug_dump(xattr_value, err);
Packit Service 087331
		err = EVP_DigestUpdate(pctx, xattr_value, err);
Packit Service 087331
		if (!err) {
Packit Service 087331
			log_err("EVP_DigestUpdate() failed\n");
Packit Service 087331
			return 1;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	memset(&hmac_misc, 0, sizeof(hmac_misc));
Packit Service 087331
Packit Service 087331
	if (evm_immutable) {
Packit Service 087331
		struct h_misc_digsig *hmac = (struct h_misc_digsig *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	} else if (msize == 0) {
Packit Service 087331
		struct h_misc *hmac = (struct h_misc *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		if (!evm_portable) {
Packit Service 087331
			hmac->ino = st.st_ino;
Packit Service 087331
			hmac->generation = generation;
Packit Service 087331
		}
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	} else if (msize == 64) {
Packit Service 087331
		struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		if (!evm_portable) {
Packit Service 087331
			hmac->ino = st.st_ino;
Packit Service 087331
			hmac->generation = generation;
Packit Service 087331
		}
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	} else {
Packit Service 087331
		struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		if (!evm_portable) {
Packit Service 087331
			hmac->ino = st.st_ino;
Packit Service 087331
			hmac->generation = generation;
Packit Service 087331
		}
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	log_debug("hmac_misc (%d): ", hmac_size);
Packit Service 087331
	log_debug_dump(&hmac_misc, hmac_size);
Packit Service 087331
Packit Service 087331
	err = EVP_DigestUpdate(pctx, &hmac_misc, hmac_size);
Packit Service 087331
	if (!err) {
Packit Service 087331
		log_err("EVP_DigestUpdate() failed\n");
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (!evm_immutable && !evm_portable &&
Packit Service 087331
	    !(hmac_flags & HMAC_FLAG_NO_UUID)) {
Packit Service 087331
		err = get_uuid(&st, uuid);
Packit Service 087331
		if (err)
Packit Service 087331
			return -1;
Packit Service 087331
Packit Service 087331
		err = EVP_DigestUpdate(pctx, (const unsigned char *)uuid, sizeof(uuid));
Packit Service 087331
		if (!err) {
Packit Service 087331
			log_err("EVP_DigestUpdate() failed\n");
Packit Service 087331
			return 1;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestFinal(pctx, hash, &mdlen);
Packit Service 087331
	if (!err) {
Packit Service 087331
		log_err("EVP_DigestFinal() failed\n");
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return mdlen;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int sign_evm(const char *file, const char *key)
Packit Service 087331
{
Packit Service 087331
	unsigned char hash[MAX_DIGEST_SIZE];
Packit Service 087331
	unsigned char sig[MAX_SIGNATURE_SIZE];
Packit Service 087331
	int len, err;
Packit Service 087331
Packit Service 087331
	len = calc_evm_hash(file, hash);
Packit Service 087331
	if (len <= 1)
Packit Service 087331
		return len;
Packit Service 087331
	assert(len <= sizeof(hash));
Packit Service 087331
Packit Service 087331
	len = sign_hash(imaevm_params.hash_algo, hash, len, key, NULL, sig + 1);
Packit Service 087331
	if (len <= 1)
Packit Service 087331
		return len;
Packit Service 087331
	assert(len < sizeof(sig));
Packit Service 087331
Packit Service 087331
	/* add header */
Packit Service 087331
	len++;
Packit Service 087331
	if (evm_portable)
Packit Service 087331
		sig[0] = EVM_XATTR_PORTABLE_DIGSIG;
Packit Service 087331
	else
Packit Service 087331
		sig[0] = EVM_IMA_XATTR_DIGSIG;
Packit Service 087331
Packit Service 087331
	if (evm_immutable)
Packit Service 087331
		sig[1] = 3; /* immutable signature version */
Packit Service 087331
Packit Service 087331
	if (sigdump || imaevm_params.verbose >= LOG_INFO)
Packit Service 087331
		imaevm_hexdump(sig, len);
Packit Service 087331
Packit Service 087331
	if (xattr) {
Packit Service 087331
		err = lsetxattr(file, xattr_evm, sig, len, 0);
Packit Service 087331
		if (err < 0) {
Packit Service 087331
			log_err("setxattr failed: %s\n", file);
Packit Service 087331
			return err;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int hash_ima(const char *file)
Packit Service 087331
{
Packit Service 087331
	unsigned char hash[MAX_DIGEST_SIZE + 2]; /* +2 byte xattr header */
Packit Service 087331
	int len, err, offset;
Packit Service 087331
	int algo = imaevm_get_hash_algo(imaevm_params.hash_algo);
Packit Service 087331
Packit Service 087331
	if (algo < 0) {
Packit Service 087331
		log_err("Unknown hash algo: %s\n", imaevm_params.hash_algo);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
	if (algo > PKEY_HASH_SHA1) {
Packit Service 087331
		hash[0] = IMA_XATTR_DIGEST_NG;
Packit Service 087331
		hash[1] = algo;
Packit Service 087331
		offset = 2;
Packit Service 087331
	} else {
Packit Service 087331
		hash[0] = IMA_XATTR_DIGEST;
Packit Service 087331
		offset = 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	len = ima_calc_hash(file, hash + offset);
Packit Service 087331
	if (len <= 1)
Packit Service 087331
		return len;
Packit Service 087331
	assert(len + offset <= sizeof(hash));
Packit Service 087331
Packit Service 087331
	len += offset;
Packit Service 087331
Packit Service 087331
	if (imaevm_params.verbose >= LOG_INFO)
Packit Service 087331
		log_info("hash(%s): ", imaevm_params.hash_algo);
Packit Service 087331
Packit Service 087331
	if (sigdump || imaevm_params.verbose >= LOG_INFO)
Packit Service 087331
		imaevm_hexdump(hash, len);
Packit Service 087331
Packit Service 087331
	if (xattr) {
Packit Service 087331
		err = lsetxattr(file, xattr_ima, hash, len, 0);
Packit Service 087331
		if (err < 0) {
Packit Service 087331
			log_err("setxattr failed: %s\n", file);
Packit Service 087331
			return err;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int sign_ima(const char *file, const char *key)
Packit Service 087331
{
Packit Service 087331
	unsigned char hash[MAX_DIGEST_SIZE];
Packit Service 087331
	unsigned char sig[MAX_SIGNATURE_SIZE];
Packit Service 087331
	int len, err;
Packit Service 087331
Packit Service 087331
	len = ima_calc_hash(file, hash);
Packit Service 087331
	if (len <= 1)
Packit Service 087331
		return len;
Packit Service 087331
	assert(len <= sizeof(hash));
Packit Service 087331
Packit Service 087331
	len = sign_hash(imaevm_params.hash_algo, hash, len, key, NULL, sig + 1);
Packit Service 087331
	if (len <= 1)
Packit Service 087331
		return len;
Packit Service 087331
	assert(len < sizeof(sig));
Packit Service 087331
Packit Service 087331
	/* add header */
Packit Service 087331
	len++;
Packit Service 087331
	sig[0] = EVM_IMA_XATTR_DIGSIG;
Packit Service 087331
Packit Service 087331
	if (sigdump || imaevm_params.verbose >= LOG_INFO)
Packit Service 087331
		imaevm_hexdump(sig, len);
Packit Service 087331
Packit Service 087331
	if (sigfile)
Packit Service 087331
		bin2file(file, "sig", sig, len);
Packit Service 087331
Packit Service 087331
	if (xattr) {
Packit Service 087331
		err = lsetxattr(file, xattr_ima, sig, len, 0);
Packit Service 087331
		if (err < 0) {
Packit Service 087331
			log_err("setxattr failed: %s\n", file);
Packit Service 087331
			return err;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int get_file_type(const char *path, const char *search_type)
Packit Service 087331
{
Packit Service 087331
	int err, dts = 0, i;
Packit Service 087331
	struct stat st;
Packit Service 087331
Packit Service 087331
	for (i = 0; search_type[i]; i++) {
Packit Service 087331
		switch (search_type[i]) {
Packit Service 087331
		case 'f':
Packit Service 087331
			dts |= REG_MASK; break;
Packit Service 087331
		case 'd':
Packit Service 087331
			dts |= DIR_MASK; break;
Packit Service 087331
		case 's':
Packit Service 087331
			dts |= BLK_MASK | CHR_MASK | LNK_MASK; break;
Packit Service 087331
		case 'x':
Packit Service 087331
			check_xattr = true; break;
Packit Service 087331
		case 'm':
Packit Service 087331
			/* stay within the same filesystem*/
Packit Service 087331
			err = lstat(path, &st);
Packit Service 087331
			if (err < 0) {
Packit Service 087331
				log_err("Failed to stat: %s\n", path);
Packit Service 087331
				return err;
Packit Service 087331
			}
Packit Service 087331
			fs_dev = st.st_dev; /* filesystem to start from */
Packit Service 087331
			break;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return dts;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int do_cmd(struct command *cmd, find_cb_t func)
Packit Service 087331
{
Packit Service 087331
	char *path = g_argv[optind++];
Packit Service 087331
	int err, dts = REG_MASK; /* only regular files by default */
Packit Service 087331
Packit Service 087331
	if (!path) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (recursive) {
Packit Service 087331
		if (search_type) {
Packit Service 087331
			dts = get_file_type(path, search_type);
Packit Service 087331
			if (dts < 0)
Packit Service 087331
				return dts;
Packit Service 087331
		}
Packit Service 087331
		err = find(path, dts, func);
Packit Service 087331
	} else {
Packit Service 087331
		err = func(path);
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_hash_ima(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	return do_cmd(cmd, hash_ima);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int sign_ima_file(const char *file)
Packit Service 087331
{
Packit Service 087331
	const char *key;
Packit Service 087331
Packit Service 087331
	key = imaevm_params.keyfile ? : "/etc/keys/privkey_evm.pem";
Packit Service 087331
Packit Service 087331
	return sign_ima(file, key);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_sign_ima(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	return do_cmd(cmd, sign_ima_file);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_sign_hash(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	const char *key;
Packit Service 087331
	char *token, *line = NULL;
Packit Service 087331
	int hashlen = 0;
Packit Service 087331
	size_t line_len;
Packit Service 087331
	ssize_t len;
Packit Service 087331
	unsigned char hash[MAX_DIGEST_SIZE];
Packit Service 087331
	unsigned char sig[MAX_SIGNATURE_SIZE] = "\x03";
Packit Service 087331
	int siglen;
Packit Service 087331
Packit Service 087331
	key = imaevm_params.keyfile ? : "/etc/keys/privkey_evm.pem";
Packit Service 087331
Packit Service 087331
	/* support reading hash (eg. output of shasum) */
Packit Service 087331
	while ((len = getline(&line, &line_len, stdin)) > 0) {
Packit Service 087331
		/* remove end of line */
Packit Service 087331
		if (line[len - 1] == '\n')
Packit Service 087331
			line[--len] = '\0';
Packit Service 087331
Packit Service 087331
		/* find the end of the hash */
Packit Service 087331
		token = strpbrk(line, ", \t");
Packit Service 087331
		hashlen = token ? token - line : strlen(line);
Packit Service 087331
Packit Service 087331
		assert(hashlen / 2 <= sizeof(hash));
Packit Service 087331
		hex2bin(hash, line, hashlen / 2);
Packit Service 087331
		siglen = sign_hash(imaevm_params.hash_algo, hash, hashlen / 2,
Packit Service 087331
				 key, NULL, sig + 1);
Packit Service 087331
		if (siglen <= 1)
Packit Service 087331
			return siglen;
Packit Service 087331
		assert(siglen < sizeof(sig));
Packit Service 087331
Packit Service 087331
		fwrite(line, len, 1, stdout);
Packit Service 087331
		fprintf(stdout, " ");
Packit Service 087331
		bin2hex(sig, siglen + 1, stdout);
Packit Service 087331
		fprintf(stdout, "\n");
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (!hashlen) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int sign_evm_path(const char *file)
Packit Service 087331
{
Packit Service 087331
	const char *key;
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	key = imaevm_params.keyfile ? : "/etc/keys/privkey_evm.pem";
Packit Service 087331
Packit Service 087331
	if (digsig) {
Packit Service 087331
		err = sign_ima(file, key);
Packit Service 087331
		if (err)
Packit Service 087331
			return err;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (digest) {
Packit Service 087331
		err = hash_ima(file);
Packit Service 087331
		if (err)
Packit Service 087331
			return err;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return sign_evm(file, key);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_sign_evm(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	return do_cmd(cmd, sign_evm_path);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int verify_evm(const char *file)
Packit Service 087331
{
Packit Service 087331
	unsigned char hash[MAX_DIGEST_SIZE];
Packit Service 087331
	unsigned char sig[MAX_SIGNATURE_SIZE];
Packit Service 087331
	int sig_hash_algo;
Packit Service 087331
	int mdlen;
Packit Service 087331
	int len;
Packit Service 087331
Packit Service 087331
	len = lgetxattr(file, xattr_evm, sig, sizeof(sig));
Packit Service 087331
	if (len < 0) {
Packit Service 087331
		log_err("getxattr failed: %s\n", file);
Packit Service 087331
		return len;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (sig[0] != 0x03) {
Packit Service 087331
		log_err("%s has no signature\n", xattr_evm);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	sig_hash_algo = imaevm_hash_algo_from_sig(sig + 1);
Packit Service 087331
	if (sig_hash_algo < 0) {
Packit Service 087331
		log_err("unknown hash algo: %s\n", file);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
	imaevm_params.hash_algo = imaevm_hash_algo_by_id(sig_hash_algo);
Packit Service 087331
Packit Service 087331
	mdlen = calc_evm_hash(file, hash);
Packit Service 087331
	if (mdlen <= 1)
Packit Service 087331
		return mdlen;
Packit Service 087331
	assert(mdlen <= sizeof(hash));
Packit Service 087331
Packit Service 087331
	return verify_hash(file, hash, mdlen, sig + 1, len - 1);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_verify_evm(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	char *file = g_argv[optind++];
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	if (!file) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (imaevm_params.x509) {
Packit Service 087331
		if (imaevm_params.keyfile) /* Support multiple public keys */
Packit Service 087331
			init_public_keys(imaevm_params.keyfile);
Packit Service 087331
		else			   /* assume read pubkey from x509 cert */
Packit Service 087331
			init_public_keys("/etc/keys/x509_evm.der");
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = verify_evm(file);
Packit Service 087331
	if (!err && imaevm_params.verbose >= LOG_INFO)
Packit Service 087331
		log_info("%s: verification is OK\n", file);
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int verify_ima(const char *file)
Packit Service 087331
{
Packit Service 087331
	unsigned char sig[MAX_SIGNATURE_SIZE];
Packit Service 087331
	int len;
Packit Service 087331
Packit Service 087331
	if (sigfile) {
Packit Service 087331
		void *tmp = file2bin(file, "sig", &len;;
Packit Service 087331
Packit Service 087331
		if (!tmp) {
Packit Service 087331
			log_err("Failed reading: %s\n", file);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
		if (len > sizeof(sig)) {
Packit Service 087331
			log_err("Signature file is too big: %s\n", file);
Packit Service 087331
			free(tmp);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
		memcpy(sig, tmp, len);
Packit Service 087331
		free(tmp);
Packit Service 087331
	} else {
Packit Service 087331
		len = lgetxattr(file, xattr_ima, sig, sizeof(sig));
Packit Service 087331
		if (len < 0) {
Packit Service 087331
			log_err("getxattr failed: %s\n", file);
Packit Service 087331
			return len;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return ima_verify_signature(file, sig, len, NULL, 0);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_verify_ima(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	char *file = g_argv[optind++];
Packit Service 087331
	int err, fails = 0;
Packit Service 087331
Packit Service 087331
	if (imaevm_params.x509) {
Packit Service 087331
		if (imaevm_params.keyfile) /* Support multiple public keys */
Packit Service 087331
			init_public_keys(imaevm_params.keyfile);
Packit Service 087331
		else			   /* assume read pubkey from x509 cert */
Packit Service 087331
			init_public_keys("/etc/keys/x509_evm.der");
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	errno = 0;
Packit Service 087331
	if (!file) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	do {
Packit Service 087331
		err = verify_ima(file);
Packit Service 087331
		if (err)
Packit Service 087331
			fails++;
Packit Service 087331
		if (!err && imaevm_params.verbose >= LOG_INFO)
Packit Service 087331
			log_info("%s: verification is OK\n", file);
Packit Service 087331
	} while ((file = g_argv[optind++]));
Packit Service 087331
	return fails > 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_convert(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	char *inkey;
Packit Service 087331
	unsigned char _pub[1024], *pub = _pub;
Packit Service 087331
	int len, err = 0;
Packit Service 087331
	char name[20];
Packit Service 087331
	uint8_t keyid[8];
Packit Service 087331
	RSA *key;
Packit Service 087331
Packit Service 087331
	imaevm_params.x509 = 0;
Packit Service 087331
Packit Service 087331
	inkey = g_argv[optind++];
Packit Service 087331
	if (!inkey) {
Packit Service 087331
		inkey = imaevm_params.x509 ? "/etc/keys/x509_evm.der" :
Packit Service 087331
					     "/etc/keys/pubkey_evm.pem";
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	key = read_pub_key(inkey, imaevm_params.x509);
Packit Service 087331
	if (!key)
Packit Service 087331
		return 1;
Packit Service 087331
Packit Service 087331
	len = key2bin(key, pub);
Packit Service 087331
	calc_keyid_v1(keyid, name, pub, len);
Packit Service 087331
Packit Service 087331
	bin2file(inkey, "bin", pub, len);
Packit Service 087331
	bin2file(inkey, "keyid", (const unsigned char *)name, strlen(name));
Packit Service 087331
Packit Service 087331
	RSA_free(key);
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_import(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	char *inkey, *ring = NULL;
Packit Service 087331
	unsigned char _pub[1024], *pub = _pub;
Packit Service 087331
	int id, len, err = 0;
Packit Service 087331
	char name[20];
Packit Service 087331
	uint8_t keyid[8];
Packit Service 087331
Packit Service 087331
	inkey = g_argv[optind++];
Packit Service 087331
	if (!inkey) {
Packit Service 087331
		inkey = imaevm_params.x509 ? "/etc/keys/x509_evm.der" :
Packit Service 087331
					     "/etc/keys/pubkey_evm.pem";
Packit Service 087331
	} else
Packit Service 087331
		ring = g_argv[optind++];
Packit Service 087331
Packit Service 087331
	id = KEY_SPEC_USER_KEYRING; /* default keyring */
Packit Service 087331
Packit Service 087331
	if (ring) {
Packit Service 087331
		if (ring[0] != '@') {
Packit Service 087331
			int base = 10;
Packit Service 087331
Packit Service 087331
			if (ring[0] == '0' && ring[1] == 'x')
Packit Service 087331
				base = 16;
Packit Service 087331
			id = strtoul(ring, NULL, base);
Packit Service 087331
		} else {
Packit Service 087331
			if (strcmp(ring, "@t") == 0)
Packit Service 087331
				id = -1;
Packit Service 087331
			else if (strcmp(ring, "@p") == 0)
Packit Service 087331
				id = -2;
Packit Service 087331
			else if (strcmp(ring, "@s") == 0)
Packit Service 087331
				id = -3;
Packit Service 087331
			else if (strcmp(ring, "@u") == 0)
Packit Service 087331
				id = -4;
Packit Service 087331
			else if (strcmp(ring, "@us") == 0)
Packit Service 087331
				id = -5;
Packit Service 087331
			else if (strcmp(ring, "@g") == 0)
Packit Service 087331
				id = -6;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (imaevm_params.x509) {
Packit Service 087331
		EVP_PKEY *pkey = read_pub_pkey(inkey, imaevm_params.x509);
Packit Service 087331
Packit Service 087331
		if (!pkey)
Packit Service 087331
			return 1;
Packit Service 087331
		pub = file2bin(inkey, NULL, &len;;
Packit Service 087331
		if (!pub) {
Packit Service 087331
			EVP_PKEY_free(pkey);
Packit Service 087331
			return 1;
Packit Service 087331
		}
Packit Service 087331
		calc_keyid_v2((uint32_t *)keyid, name, pkey);
Packit Service 087331
		EVP_PKEY_free(pkey);
Packit Service 087331
	} else {
Packit Service 087331
		RSA *key = read_pub_key(inkey, imaevm_params.x509);
Packit Service 087331
Packit Service 087331
		if (!key)
Packit Service 087331
			return 1;
Packit Service 087331
		len = key2bin(key, pub);
Packit Service 087331
		calc_keyid_v1(keyid, name, pub, len);
Packit Service 087331
		RSA_free(key);
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	log_info("Importing public key %s from file %s into keyring %d\n", name, inkey, id);
Packit Service 087331
Packit Service 087331
	id = add_key(imaevm_params.x509 ? "asymmetric" : "user",
Packit Service 087331
		     imaevm_params.x509 ? NULL : name, pub, len, id);
Packit Service 087331
	if (id < 0) {
Packit Service 087331
		log_err("add_key failed\n");
Packit Service 087331
		err = id;
Packit Service 087331
	} else {
Packit Service 087331
		log_info("keyid: %d\n", id);
Packit Service 087331
		printf("%d\n", id);
Packit Service 087331
	}
Packit Service 087331
	if (imaevm_params.x509)
Packit Service 087331
		free(pub);
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int setxattr_ima(const char *file, char *sig_file)
Packit Service 087331
{
Packit Service 087331
	unsigned char *sig;
Packit Service 087331
	int len, err;
Packit Service 087331
Packit Service 087331
	if (sig_file)
Packit Service 087331
		sig = file2bin(sig_file, NULL, &len;;
Packit Service 087331
	else
Packit Service 087331
		sig = file2bin(file, "sig", &len;;
Packit Service 087331
	if (!sig)
Packit Service 087331
		return 0;
Packit Service 087331
Packit Service 087331
	err = lsetxattr(file, xattr_ima, sig, len, 0);
Packit Service 087331
	if (err < 0)
Packit Service 087331
		log_err("setxattr failed: %s\n", file);
Packit Service 087331
	free(sig);
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_setxattr_ima(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	char *file, *sig = NULL;
Packit Service 087331
Packit Service 087331
	if (sigfile)
Packit Service 087331
		sig = g_argv[optind++];
Packit Service 087331
	file =  g_argv[optind++];
Packit Service 087331
Packit Service 087331
	if (!file) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return setxattr_ima(file, sig);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
#define MAX_KEY_SIZE 128
Packit Service 087331
Packit Service 087331
static int calc_evm_hmac(const char *file, const char *keyfile, unsigned char *hash)
Packit Service 087331
{
Packit Service 087331
        const EVP_MD *md;
Packit Service 087331
	struct stat st;
Packit Service 087331
	int err = -1;
Packit Service 087331
	uint32_t generation = 0;
Packit Service 087331
	HMAC_CTX *pctx;
Packit Service 087331
	unsigned int mdlen;
Packit Service 087331
	char **xattrname;
Packit Service 087331
	unsigned char xattr_value[1024];
Packit Service 087331
	unsigned char *key;
Packit Service 087331
	int keylen;
Packit Service 087331
	unsigned char evmkey[MAX_KEY_SIZE];
Packit Service 087331
	char list[1024];
Packit Service 087331
	ssize_t list_size;
Packit Service 087331
	struct h_misc_64 hmac_misc;
Packit Service 087331
	int hmac_size;
Packit Service 087331
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 087331
	HMAC_CTX ctx;
Packit Service 087331
	pctx = &ctx;
Packit Service 087331
#else
Packit Service 087331
	pctx = HMAC_CTX_new();
Packit Service 087331
#endif
Packit Service 087331
Packit Service 087331
	key = file2bin(keyfile, NULL, &keylen);
Packit Service 087331
	if (!key) {
Packit Service 087331
		log_err("Failed to read a key: %s\n", keyfile);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (keylen > sizeof(evmkey)) {
Packit Service 087331
		log_err("key is too long: %d\n", keylen);
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	/* EVM key is 128 bytes */
Packit Service 087331
	memcpy(evmkey, key, keylen);
Packit Service 087331
	memset(evmkey + keylen, 0, sizeof(evmkey) - keylen);
Packit Service 087331
Packit Service 087331
	if (lstat(file, &st)) {
Packit Service 087331
		log_err("Failed to stat: %s\n", file);
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) {
Packit Service 087331
		/* we cannot at the momement to get generation of special files..
Packit Service 087331
		 * kernel API does not support it */
Packit Service 087331
		int fd = open(file, 0);
Packit Service 087331
Packit Service 087331
		if (fd < 0) {
Packit Service 087331
			log_err("Failed to open %s\n", file);
Packit Service 087331
			goto out;
Packit Service 087331
		}
Packit Service 087331
		if (ioctl(fd, FS_IOC_GETVERSION, &generation)) {
Packit Service 087331
			log_err("ioctl() failed\n");
Packit Service 087331
			close(fd);
Packit Service 087331
			goto out;
Packit Service 087331
		}
Packit Service 087331
		close(fd);
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	log_info("generation: %u\n", generation);
Packit Service 087331
Packit Service 087331
	list_size = llistxattr(file, list, sizeof(list));
Packit Service 087331
	if (list_size <= 0) {
Packit Service 087331
		log_err("llistxattr() failed: %s\n", file);
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	md = EVP_get_digestbyname(imaevm_params.hash_algo);
Packit Service 087331
	if (!md) {
Packit Service 087331
		log_err("EVP_get_digestbyname(%s) failed\n",
Packit Service 087331
			imaevm_params.hash_algo);
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = !HMAC_Init_ex(pctx, evmkey, sizeof(evmkey), md, NULL);
Packit Service 087331
	if (err) {
Packit Service 087331
		log_err("HMAC_Init() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
Packit Service 087331
		err = lgetxattr(file, *xattrname, xattr_value, sizeof(xattr_value));
Packit Service 087331
		if (err < 0) {
Packit Service 087331
			log_info("no xattr: %s\n", *xattrname);
Packit Service 087331
			continue;
Packit Service 087331
		}
Packit Service 087331
		if (!find_xattr(list, list_size, *xattrname)) {
Packit Service 087331
			log_info("skipping xattr: %s\n", *xattrname);
Packit Service 087331
			continue;
Packit Service 087331
		}
Packit Service 087331
		/*log_debug("name: %s, value: %s, size: %d\n", *xattrname, xattr_value, err);*/
Packit Service 087331
		log_info("name: %s, size: %d\n", *xattrname, err);
Packit Service 087331
		log_debug_dump(xattr_value, err);
Packit Service 087331
		err = !HMAC_Update(pctx, xattr_value, err);
Packit Service 087331
		if (err) {
Packit Service 087331
			log_err("HMAC_Update() failed\n");
Packit Service 087331
			goto out_ctx_cleanup;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	memset(&hmac_misc, 0, sizeof(hmac_misc));
Packit Service 087331
Packit Service 087331
	if (msize == 0) {
Packit Service 087331
		struct h_misc *hmac = (struct h_misc *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		hmac->ino = st.st_ino;
Packit Service 087331
		hmac->generation = generation;
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	} else if (msize == 64) {
Packit Service 087331
		struct h_misc_64 *hmac = (struct h_misc_64 *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		hmac->ino = st.st_ino;
Packit Service 087331
		hmac->generation = generation;
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	} else {
Packit Service 087331
		struct h_misc_32 *hmac = (struct h_misc_32 *)&hmac_misc;
Packit Service 087331
Packit Service 087331
		hmac_size = sizeof(*hmac);
Packit Service 087331
		hmac->ino = st.st_ino;
Packit Service 087331
		hmac->generation = generation;
Packit Service 087331
		hmac->uid = st.st_uid;
Packit Service 087331
		hmac->gid = st.st_gid;
Packit Service 087331
		hmac->mode = st.st_mode;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	log_debug("hmac_misc (%d): ", hmac_size);
Packit Service 087331
	log_debug_dump(&hmac_misc, hmac_size);
Packit Service 087331
Packit Service 087331
	err = !HMAC_Update(pctx, (const unsigned char *)&hmac_misc, hmac_size);
Packit Service 087331
	if (err) {
Packit Service 087331
		log_err("HMAC_Update() failed\n");
Packit Service 087331
		goto out_ctx_cleanup;
Packit Service 087331
	}
Packit Service 087331
	err = !HMAC_Final(pctx, hash, &mdlen);
Packit Service 087331
	if (err)
Packit Service 087331
		log_err("HMAC_Final() failed\n");
Packit Service 087331
out_ctx_cleanup:
Packit Service 087331
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 087331
	HMAC_CTX_cleanup(pctx);
Packit Service 087331
#else
Packit Service 087331
	HMAC_CTX_free(pctx);
Packit Service 087331
#endif
Packit Service 087331
out:
Packit Service 087331
	free(key);
Packit Service 087331
	return err ?: mdlen;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int hmac_evm(const char *file, const char *key)
Packit Service 087331
{
Packit Service 087331
	unsigned char hash[MAX_DIGEST_SIZE];
Packit Service 087331
	unsigned char sig[MAX_SIGNATURE_SIZE];
Packit Service 087331
	int len, err;
Packit Service 087331
Packit Service 087331
	len = calc_evm_hmac(file, key, hash);
Packit Service 087331
	if (len <= 1)
Packit Service 087331
		return len;
Packit Service 087331
	assert(len <= sizeof(hash));
Packit Service 087331
Packit Service 087331
	log_info("hmac: ");
Packit Service 087331
	log_dump(hash, len);
Packit Service 087331
	assert(len < sizeof(sig));
Packit Service 087331
	memcpy(sig + 1, hash, len);
Packit Service 087331
Packit Service 087331
	if (xattr) {
Packit Service 087331
		sig[0] = EVM_XATTR_HMAC;
Packit Service 087331
		err = lsetxattr(file, xattr_evm, sig, len + 1, 0);
Packit Service 087331
		if (err < 0) {
Packit Service 087331
			log_err("setxattr failed: %s\n", file);
Packit Service 087331
			return err;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_hmac_evm(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	const char *key, *file = g_argv[optind++];
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	if (!file) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	key = imaevm_params.keyfile ? : "/etc/keys/privkey_evm.pem";
Packit Service 087331
Packit Service 087331
	if (digsig) {
Packit Service 087331
		err = sign_ima(file, key);
Packit Service 087331
		if (err)
Packit Service 087331
			return err;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (digest) {
Packit Service 087331
		err = hash_ima(file);
Packit Service 087331
		if (err)
Packit Service 087331
			return err;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return hmac_evm(file, "/etc/keys/evm-key-plain");
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int ima_fix(const char *path)
Packit Service 087331
{
Packit Service 087331
	int fd, size, len, ima = 0, evm = 0;
Packit Service 087331
	char buf[1024], *list = buf;
Packit Service 087331
Packit Service 087331
	log_info("%s\n", path);
Packit Service 087331
Packit Service 087331
	if (check_xattr) {
Packit Service 087331
		/* re-measuring takes a time
Packit Service 087331
		 * in some cases we can skip labeling if xattrs exists
Packit Service 087331
		 */
Packit Service 087331
		size = llistxattr(path, list, sizeof(buf));
Packit Service 087331
		if (size < 0) {
Packit Service 087331
			log_errno("Failed to read xattrs (llistxattr): %s\n", path);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
		for (; size > 0; len++, size -= len, list += len) {
Packit Service 087331
			len = strlen(list);
Packit Service 087331
			if (!strcmp(list, xattr_ima))
Packit Service 087331
				ima = 1;
Packit Service 087331
			else if (!strcmp(list, xattr_evm))
Packit Service 087331
				evm = 1;
Packit Service 087331
		}
Packit Service 087331
		if (ima && evm)
Packit Service 087331
			return 0;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	fd = open(path, O_RDONLY);
Packit Service 087331
	if (fd < 0) {
Packit Service 087331
		log_errno("Failed to open file: %s", path);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	close(fd);
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int find(const char *path, int dts, find_cb_t func)
Packit Service 087331
{
Packit Service 087331
	struct dirent *de;
Packit Service 087331
	DIR *dir;
Packit Service 087331
Packit Service 087331
	if (fs_dev) {
Packit Service 087331
		struct stat st;
Packit Service 087331
		int err = lstat(path, &st);
Packit Service 087331
Packit Service 087331
		if (err < 0) {
Packit Service 087331
			log_err("Failed to stat: %s\n", path);
Packit Service 087331
			return err;
Packit Service 087331
		}
Packit Service 087331
		if (st.st_dev != fs_dev)
Packit Service 087331
			return 0;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	dir = opendir(path);
Packit Service 087331
	if (!dir) {
Packit Service 087331
		log_err("Failed to open directory %s\n", path);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (fchdir(dirfd(dir))) {
Packit Service 087331
		log_err("Failed to chdir %s\n", path);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	while ((de = readdir(dir))) {
Packit Service 087331
		if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, "."))
Packit Service 087331
			continue;
Packit Service 087331
		log_debug("path: %s, type: %u\n", de->d_name, de->d_type);
Packit Service 087331
		if (de->d_type == DT_DIR)
Packit Service 087331
			find(de->d_name, dts, func);
Packit Service 087331
		else if (dts & (1 << de->d_type))
Packit Service 087331
			func(de->d_name);
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (chdir("..")) {
Packit Service 087331
		log_err("Failed to chdir: %s\n", path);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (dts & DIR_MASK)
Packit Service 087331
		func(path);
Packit Service 087331
Packit Service 087331
	closedir(dir);
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_ima_fix(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	return do_cmd(cmd, ima_fix);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int ima_clear(const char *path)
Packit Service 087331
{
Packit Service 087331
	log_info("%s\n", path);
Packit Service 087331
	lremovexattr(path, xattr_ima);
Packit Service 087331
	lremovexattr(path, xattr_evm);
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_ima_clear(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	return do_cmd(cmd, ima_clear);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
#define TCG_EVENT_NAME_LEN_MAX	255
Packit Service 087331
Packit Service 087331
struct template_entry {
Packit Service 087331
	struct {
Packit Service 087331
		uint32_t pcr;
Packit Service 087331
		uint8_t digest[SHA_DIGEST_LENGTH];
Packit Service 087331
		uint32_t name_len;
Packit Service 087331
	} header  __packed;
Packit Service 087331
	char name[TCG_EVENT_NAME_LEN_MAX + 1];
Packit Service 087331
	uint32_t template_buf_len;
Packit Service 087331
	uint32_t template_len;
Packit Service 087331
	uint8_t *template;
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
static uint8_t zero[MAX_DIGEST_SIZE];
Packit Service 087331
Packit Service 087331
static int ignore_violations = 0;
Packit Service 087331
Packit Service 087331
static int ima_verify_template_hash(struct template_entry *entry)
Packit Service 087331
{
Packit Service 087331
	uint8_t digest[SHA_DIGEST_LENGTH];
Packit Service 087331
	static int line = 0;
Packit Service 087331
Packit Service 087331
	line++;
Packit Service 087331
Packit Service 087331
	if (!memcmp(zero, entry->header.digest, sizeof(digest)))
Packit Service 087331
		return 0;
Packit Service 087331
Packit Service 087331
	SHA1(entry->template, entry->template_len, digest);
Packit Service 087331
Packit Service 087331
	if (memcmp(digest, entry->header.digest, sizeof(digest))) {
Packit Service 087331
		if (imaevm_params.verbose > LOG_INFO)
Packit Service 087331
			log_info("Failed to verify template data digest(line %d).\n",
Packit Service 087331
				  line);
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
void ima_show(struct template_entry *entry)
Packit Service 087331
{
Packit Service 087331
	if (imaevm_params.verbose <= LOG_INFO)
Packit Service 087331
		return;
Packit Service 087331
Packit Service 087331
	log_info("%d ", entry->header.pcr);
Packit Service 087331
	log_dump_n(entry->header.digest, sizeof(entry->header.digest));
Packit Service 087331
	log_info(" %s ", entry->name);
Packit Service 087331
	log_dump_n(entry->template, SHA_DIGEST_LENGTH);
Packit Service 087331
	log_info(" %s\n", entry->template + SHA_DIGEST_LENGTH);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/*
Packit Service 087331
 * Keep track of unknown or malformed template names.
Packit Service 087331
 *
Packit Service 087331
 * Return 1 for found, return 0 for not found.
Packit Service 087331
 */
Packit Service 087331
static int lookup_template_name_entry(char *template_name)
Packit Service 087331
{
Packit Service 087331
	struct template_name_entry {
Packit Service 087331
		struct template_name_entry *next;
Packit Service 087331
		char name[];
Packit Service 087331
	} *entry;
Packit Service 087331
	static struct template_name_entry *template_names = NULL;
Packit Service 087331
Packit Service 087331
	for (entry = template_names; entry != NULL; entry = entry->next) {
Packit Service 087331
		if (strcmp(entry->name, template_name) == 0)
Packit Service 087331
			return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	entry = malloc(sizeof(struct template_name_entry) +
Packit Service 087331
			strlen(template_name) + 1);
Packit Service 087331
	if (entry) {
Packit Service 087331
		strcpy(entry->name, template_name);
Packit Service 087331
		entry->next = template_names;
Packit Service 087331
		template_names = entry;
Packit Service 087331
	}
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
void ima_ng_show(struct template_entry *entry)
Packit Service 087331
{
Packit Service 087331
	uint8_t *fieldp = entry->template;
Packit Service 087331
	uint32_t field_len;
Packit Service 087331
	int total_len = entry->template_len, digest_len, len, sig_len, fbuf_len;
Packit Service 087331
	uint8_t *digest, *sig = NULL, *fbuf = NULL;
Packit Service 087331
	char *algo, *path;
Packit Service 087331
	int found;
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	/* get binary digest */
Packit Service 087331
	field_len = *(uint32_t *)fieldp;
Packit Service 087331
	fieldp += sizeof(field_len);
Packit Service 087331
	total_len -= sizeof(field_len);
Packit Service 087331
Packit Service 087331
	algo = (char *)fieldp;
Packit Service 087331
	len = strlen(algo) + 1;
Packit Service 087331
	digest_len = field_len - len;
Packit Service 087331
	digest = fieldp + len;
Packit Service 087331
Packit Service 087331
	/* move to next field */
Packit Service 087331
	fieldp += field_len;
Packit Service 087331
	total_len -= field_len;
Packit Service 087331
Packit Service 087331
	/* get path */
Packit Service 087331
	field_len = *(uint32_t *)fieldp;
Packit Service 087331
	fieldp += sizeof(field_len);
Packit Service 087331
	total_len -= sizeof(field_len);
Packit Service 087331
Packit Service 087331
	path = (char *)fieldp;
Packit Service 087331
Packit Service 087331
	/* move to next field */
Packit Service 087331
	fieldp += field_len;
Packit Service 087331
	total_len -= field_len;
Packit Service 087331
Packit Service 087331
	if (!strcmp(entry->name, "ima-sig")) {
Packit Service 087331
		/* get signature */
Packit Service 087331
		field_len = *(uint32_t *)fieldp;
Packit Service 087331
		fieldp += sizeof(field_len);
Packit Service 087331
		total_len -= sizeof(field_len);
Packit Service 087331
Packit Service 087331
		if (field_len) {
Packit Service 087331
			sig = fieldp;
Packit Service 087331
			sig_len = field_len;
Packit Service 087331
Packit Service 087331
			/* move to next field */
Packit Service 087331
			fieldp += field_len;
Packit Service 087331
			total_len -= field_len;
Packit Service 087331
		}
Packit Service 087331
	} else if (!strcmp(entry->name, "ima-buf")) {
Packit Service 087331
		field_len = *(uint32_t *)fieldp;
Packit Service 087331
		fieldp += sizeof(field_len);
Packit Service 087331
		total_len -= sizeof(field_len);
Packit Service 087331
		if (field_len) {
Packit Service 087331
			fbuf = fieldp;
Packit Service 087331
			fbuf_len = field_len;
Packit Service 087331
Packit Service 087331
			/* move to next field */
Packit Service 087331
			fieldp += field_len;
Packit Service 087331
			total_len -= field_len;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	/* ascii_runtime_measurements */
Packit Service 087331
	if (imaevm_params.verbose > LOG_INFO) {
Packit Service 087331
		log_info("%d ", entry->header.pcr);
Packit Service 087331
		log_dump_n(entry->header.digest, sizeof(entry->header.digest));
Packit Service 087331
		log_info(" %s %s", entry->name, algo);
Packit Service 087331
		log_dump_n(digest, digest_len);
Packit Service 087331
		log_info(" %s", path);
Packit Service 087331
		if (fbuf) {
Packit Service 087331
			log_info(" ");
Packit Service 087331
			log_dump_n(fbuf, fbuf_len);
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (sig) {
Packit Service 087331
		if (imaevm_params.verbose > LOG_INFO) {
Packit Service 087331
			log_info(" ");
Packit Service 087331
			log_dump(sig, sig_len);
Packit Service 087331
		}
Packit Service 087331
		if (verify_list_sig)
Packit Service 087331
			err = ima_verify_signature(path, sig, sig_len,
Packit Service 087331
						   digest, digest_len);
Packit Service 087331
		else
Packit Service 087331
			err = ima_verify_signature(path, sig, sig_len, NULL, 0);
Packit Service 087331
		if (!err && imaevm_params.verbose > LOG_INFO)
Packit Service 087331
			log_info("%s: verification is OK\n", path);
Packit Service 087331
	} else {
Packit Service 087331
		if (imaevm_params.verbose > LOG_INFO)
Packit Service 087331
			log_info("\n");
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (total_len) {
Packit Service 087331
		found = lookup_template_name_entry(entry->name);
Packit Service 087331
		if (!found)
Packit Service 087331
			log_err("Template \"%s\" contains unprocessed data: "
Packit Service 087331
				 "%d bytes\n", entry->name, total_len);
Packit Service 087331
	}
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static void set_bank_info(struct tpm_bank_info *bank, const char *algo_name)
Packit Service 087331
{
Packit Service 087331
	const EVP_MD *md;
Packit Service 087331
Packit Service 087331
	bank->algo_name = algo_name;
Packit Service 087331
	md = EVP_get_digestbyname(bank->algo_name);
Packit Service 087331
	if (!md)
Packit Service 087331
		return;
Packit Service 087331
Packit Service 087331
	bank->supported = 1;
Packit Service 087331
	bank->digest_size = EVP_MD_size(md);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static struct tpm_bank_info *init_tpm_banks(int *num_banks)
Packit Service 087331
{
Packit Service 087331
	struct tpm_bank_info *banks = NULL;
Packit Service 087331
	const char *default_algos[] = {"sha1", "sha256"};
Packit Service 087331
	int num_algos = sizeof(default_algos) / sizeof(default_algos[0]);
Packit Service 087331
	int i, j;
Packit Service 087331
Packit Service 087331
	banks = calloc(num_algos, sizeof(struct tpm_bank_info));
Packit Service 087331
	if (!banks)
Packit Service 087331
		return banks;
Packit Service 087331
Packit Service 087331
	/* re-calculate the PCRs digests for only known algorithms */
Packit Service 087331
	*num_banks = num_algos;
Packit Service 087331
	for (i = 0; i < num_algos; i++) {
Packit Service 087331
		for (j = 0; j < HASH_ALGO__LAST; j++) {
Packit Service 087331
			if (!strcmp(default_algos[i], hash_algo_name[j]))
Packit Service 087331
				set_bank_info(&banks[i], hash_algo_name[j]);
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
	return banks;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/*
Packit Service 087331
 * Compare the calculated TPM PCR banks against the PCR values read.
Packit Service 087331
 * On failure to match any TPM bank, fail comparison.
Packit Service 087331
 */
Packit Service 087331
static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
Packit Service 087331
			     struct tpm_bank_info *tpm_bank)
Packit Service 087331
{
Packit Service 087331
	int i, j;
Packit Service 087331
	int ret = 0;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < num_banks; i++) {
Packit Service 087331
		if (!bank[i].supported || !tpm_bank[i].supported)
Packit Service 087331
			continue;
Packit Service 087331
		for (j = 0; j < NUM_PCRS; j++) {
Packit Service 087331
			if (memcmp(bank[i].pcr[j], zero, bank[i].digest_size)
Packit Service 087331
			    == 0)
Packit Service 087331
				continue;
Packit Service 087331
Packit Service 087331
			if (memcmp(bank[i].pcr[j], tpm_bank[i].pcr[j],
Packit Service 087331
				     bank[i].digest_size) != 0)
Packit Service 087331
				ret = 1;
Packit Service 087331
Packit Service 087331
			if ((!ret && imaevm_params.verbose <= LOG_INFO) ||
Packit Service 087331
			    (ret && imaevm_params.verbose <= LOG_DEBUG))
Packit Service 087331
				continue;
Packit Service 087331
Packit Service 087331
			log_info("%s: PCRAgg  %d: ", bank[i].algo_name, j);
Packit Service 087331
			log_dump(bank[i].pcr[j], bank[i].digest_size);
Packit Service 087331
Packit Service 087331
			log_info("%s: TPM PCR-%d: ", tpm_bank[i].algo_name, j);
Packit Service 087331
			log_dump(tpm_bank[i].pcr[j], tpm_bank[i].digest_size);
Packit Service 087331
Packit Service 087331
			if (!ret)
Packit Service 087331
				log_info("%s PCR-%d: succeed\n",
Packit Service 087331
					 bank[i].algo_name, j);
Packit Service 087331
			else
Packit Service 087331
				log_info("%s: PCRAgg %d does not match TPM PCR-%d\n",
Packit Service 087331
					 bank[i].algo_name, j, j);
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
	return ret;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/* Calculate the template hash for a particular hash algorithm */
Packit Service 087331
static int calculate_template_digest(EVP_MD_CTX *pctx, const EVP_MD *md,
Packit Service 087331
				     struct template_entry *entry,
Packit Service 087331
				     struct tpm_bank_info *bank)
Packit Service 087331
{
Packit Service 087331
	unsigned int mdlen;
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	err = EVP_DigestInit(pctx, md);
Packit Service 087331
	if (!err) {
Packit Service 087331
		printf("EVP_DigestInit() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestUpdate(pctx, entry->template, entry->template_len);
Packit Service 087331
	if (!err) {
Packit Service 087331
		printf("EVP_DigestUpdate() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestFinal(pctx, bank->digest, &mdlen);
Packit Service 087331
	if (!err)
Packit Service 087331
		printf("EVP_DigestUpdate() failed\n");
Packit Service 087331
out:
Packit Service 087331
	if (!err)
Packit Service 087331
		err = 1;
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/* Extend a specific TPM bank with the template hash */
Packit Service 087331
static int extend_tpm_bank(EVP_MD_CTX *pctx, const EVP_MD *md,
Packit Service 087331
			   struct template_entry *entry,
Packit Service 087331
			   struct tpm_bank_info *bank)
Packit Service 087331
{
Packit Service 087331
	unsigned int mdlen;
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	err = EVP_DigestInit(pctx, md);
Packit Service 087331
	if (!err) {
Packit Service 087331
		printf("EVP_DigestInit() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestUpdate(pctx, bank->pcr[entry->header.pcr],
Packit Service 087331
			       bank->digest_size);
Packit Service 087331
	if (!err) {
Packit Service 087331
		printf("EVP_DigestUpdate() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestUpdate(pctx, bank->digest, bank->digest_size);
Packit Service 087331
	if (!err) {
Packit Service 087331
		printf("EVP_DigestUpdate() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestFinal(pctx, bank->pcr[entry->header.pcr], &mdlen);
Packit Service 087331
	if (!err)
Packit Service 087331
		printf("EVP_DigestFinal() failed\n");
Packit Service 087331
Packit Service 087331
out:
Packit Service 087331
	if (!err)
Packit Service 087331
		err = 1;
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/* Calculate and extend the template hash for multiple hash algorithms */
Packit Service 087331
static void extend_tpm_banks(struct template_entry *entry, int num_banks,
Packit Service 087331
			     struct tpm_bank_info *bank,
Packit Service 087331
			     struct tpm_bank_info *padded_bank)
Packit Service 087331
{
Packit Service 087331
	EVP_MD_CTX *pctx;
Packit Service 087331
	const EVP_MD *md;
Packit Service 087331
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 087331
	EVP_MD_CTX ctx;
Packit Service 087331
	pctx = &ctx;
Packit Service 087331
#else
Packit Service 087331
	pctx = EVP_MD_CTX_new();
Packit Service 087331
#endif
Packit Service 087331
	int err;
Packit Service 087331
	int i;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < num_banks; i++) {
Packit Service 087331
		if (!bank[i].supported)
Packit Service 087331
			continue;
Packit Service 087331
		md = EVP_get_digestbyname(bank[i].algo_name);
Packit Service 087331
		if (!md) {
Packit Service 087331
			printf("EVP_get_digestbyname(%s) failed\n",
Packit Service 087331
				bank[i].algo_name);
Packit Service 087331
			bank[i].supported = 0;
Packit Service 087331
			continue;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		/*
Packit Service 087331
		 * Measurement violations are 0x00 digests, which are extended
Packit Service 087331
		 * into the TPM as 0xff.  Verifying the IMA measurement list
Packit Service 087331
		 * will fail, unless the 0x00 digests are converted to 0xff's.
Packit Service 087331
		 *
Packit Service 087331
		 * Initially the sha1 digest, including violations, was padded
Packit Service 087331
		 * with zeroes before being extended into the TPM.  With the
Packit Service 087331
		 * per TPM bank digest, violations are the full per bank digest
Packit Service 087331
		 * size.
Packit Service 087331
		 */
Packit Service 087331
		if (memcmp(entry->header.digest, zero, SHA_DIGEST_LENGTH) == 0) {
Packit Service 087331
			if (!ignore_violations) {
Packit Service 087331
				memset(bank[i].digest, 0x00, bank[i].digest_size);
Packit Service 087331
				memset(padded_bank[i].digest, 0x00, padded_bank[i].digest_size);
Packit Service 087331
			} else {
Packit Service 087331
				memset(bank[i].digest, 0xff,
Packit Service 087331
				       bank[i].digest_size);
Packit Service 087331
Packit Service 087331
				memset(padded_bank[i].digest, 0x00,
Packit Service 087331
				       padded_bank[i].digest_size);
Packit Service 087331
				memset(padded_bank[i].digest, 0xff,
Packit Service 087331
				       SHA_DIGEST_LENGTH);
Packit Service 087331
			}
Packit Service 087331
		} else {
Packit Service 087331
			err = calculate_template_digest(pctx, md, entry,
Packit Service 087331
							&bank[i]);
Packit Service 087331
			if (!err) {
Packit Service 087331
				bank[i].supported = 0;
Packit Service 087331
				continue;
Packit Service 087331
			}
Packit Service 087331
Packit Service 087331
			/*
Packit Service 087331
			 * calloc set the memory to zero, so just copy the
Packit Service 087331
			 * sha1 digest.
Packit Service 087331
			 */
Packit Service 087331
			memcpy(padded_bank[i].digest, entry->header.digest,
Packit Service 087331
			       SHA_DIGEST_LENGTH);
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		/* extend TPM BANK with template digest */
Packit Service 087331
		err = extend_tpm_bank(pctx, md, entry, &bank[i]);
Packit Service 087331
		if (!err)
Packit Service 087331
			bank[i].supported = 0;
Packit Service 087331
Packit Service 087331
		/* extend TPM BANK with zero padded sha1 template digest */
Packit Service 087331
		err = extend_tpm_bank(pctx, md, entry, &padded_bank[i]);
Packit Service 087331
		if (!err)
Packit Service 087331
			padded_bank[i].supported = 0;
Packit Service 087331
	}
Packit Service 087331
#if OPENSSL_VERSION_NUMBER >= 0x10100000
Packit Service 087331
	EVP_MD_CTX_free(pctx);
Packit Service 087331
#endif
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int read_one_bank(struct tpm_bank_info *tpm_bank, FILE *fp)
Packit Service 087331
{
Packit Service 087331
	char *p, pcr_str[8], buf[MAX_DIGEST_SIZE * 2 + 8];
Packit Service 087331
	int i = 0;
Packit Service 087331
	int result = -1;
Packit Service 087331
	for (;;) {
Packit Service 087331
		p = fgets(buf, sizeof(buf), fp);
Packit Service 087331
		if (!p || i >= NUM_PCRS)
Packit Service 087331
			break;
Packit Service 087331
		sprintf(pcr_str, "PCR-%2.2d", i);
Packit Service 087331
		if (!strncmp(p, pcr_str, 6))
Packit Service 087331
			hex2bin(tpm_bank->pcr[i++], p + 7, tpm_bank->digest_size);
Packit Service 087331
		result = 0;
Packit Service 087331
	}
Packit Service 087331
	return result;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static char *pcrs = "/sys/class/tpm/tpm0/device/pcrs";  /* Kernels >= 4.0 */
Packit Service 087331
static char *misc_pcrs = "/sys/class/misc/tpm0/device/pcrs";
Packit Service 087331
Packit Service 087331
/* Read one of the TPM 1.2 sysfs files if present */
Packit Service 087331
static int read_sysfs_pcrs(int num_banks, struct tpm_bank_info *tpm_banks)
Packit Service 087331
{
Packit Service 087331
	FILE *fp;
Packit Service 087331
	int i, result;
Packit Service 087331
Packit Service 087331
	fp = fopen(pcrs, "r");
Packit Service 087331
	if (!fp)
Packit Service 087331
		fp = fopen(misc_pcrs, "r");
Packit Service 087331
	if (!fp)
Packit Service 087331
		return -1;
Packit Service 087331
Packit Service 087331
	result = read_one_bank(&tpm_banks[0], fp);
Packit Service 087331
	fclose(fp);
Packit Service 087331
	if (result < 0)
Packit Service 087331
		return result;
Packit Service 087331
	tpm_banks[0].supported = 1;
Packit Service 087331
	for (i = 1; i < num_banks; i++)
Packit Service 087331
		tpm_banks[i].supported = 0;
Packit Service 087331
	return 0;
Packit Service 087331
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/* Read PCRs from per-bank file(s) specified via --pcrs */
Packit Service 087331
static int read_file_pcrs(int num_banks, struct tpm_bank_info *tpm_banks)
Packit Service 087331
{
Packit Service 087331
	struct stat s;
Packit Service 087331
	FILE *fp;
Packit Service 087331
	char *p;
Packit Service 087331
	const char *alg, *path;
Packit Service 087331
	int i, j, bank, result;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < num_banks; i++)
Packit Service 087331
		tpm_banks[i].supported = 0;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < npcrfile; i++) {
Packit Service 087331
		p = strchr(pcrfile[i], ',');
Packit Service 087331
		if (p) {
Packit Service 087331
			*p = 0;
Packit Service 087331
			alg = pcrfile[i];
Packit Service 087331
			path = ++p;
Packit Service 087331
		} else {
Packit Service 087331
			alg = "sha1";
Packit Service 087331
			path = pcrfile[i];
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		bank = -1;
Packit Service 087331
		for (j = 0; j < num_banks; j++) {
Packit Service 087331
			if (!strcmp(tpm_banks[j].algo_name, alg)) {
Packit Service 087331
				bank = j;
Packit Service 087331
				break;
Packit Service 087331
			}
Packit Service 087331
		}
Packit Service 087331
		if (bank < 0) {
Packit Service 087331
			log_err("Unknown algorithm '%s'\n", alg);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		if (stat(path, &s) == -1) {
Packit Service 087331
			log_err("Could not stat '%s'\n", path);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		if (!S_ISREG(s.st_mode)) {
Packit Service 087331
			log_err("PCR file: not a regular file or link to regular file\n");
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		fp = fopen(path, "r");
Packit Service 087331
		if (!fp) {
Packit Service 087331
			log_err("Could not open '%s'\n", path);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		result = read_one_bank(&tpm_banks[bank], fp);
Packit Service 087331
		fclose(fp);
Packit Service 087331
		if (result < 0)
Packit Service 087331
			return result;
Packit Service 087331
		tpm_banks[bank].supported = 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/*
Packit Service 087331
 * Attempt to read TPM PCRs from either TPM 1.2 or multiple TPM 2.0 banks.
Packit Service 087331
 *
Packit Service 087331
 * On success reading from any TPM bank, return 0.
Packit Service 087331
 */
Packit Service 087331
static int read_tpm_banks(int num_banks, struct tpm_bank_info *bank)
Packit Service 087331
{
Packit Service 087331
	int tpm_enabled = 0;
Packit Service 087331
	char *errmsg = NULL;
Packit Service 087331
	int i, j;
Packit Service 087331
	int err;
Packit Service 087331
Packit Service 087331
	/* If --pcrs was specified, read only from the specified file(s) */
Packit Service 087331
	if (npcrfile)
Packit Service 087331
		return read_file_pcrs(num_banks, bank);
Packit Service 087331
Packit Service 087331
	/* Else try reading PCRs from the sysfs file if present */
Packit Service 087331
	if (read_sysfs_pcrs(num_banks, bank) == 0)
Packit Service 087331
		return 0;
Packit Service 087331
Packit Service 087331
	/* Any userspace applications available for reading TPM 2.0 PCRs? */
Packit Service 087331
	if (!tpm2_pcr_supported()) {
Packit Service 087331
		log_debug("Failed to read TPM 2.0 PCRs\n");
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	/* Read PCRs from multiple TPM 2.0 banks */
Packit Service 087331
	for (i = 0; i < num_banks; i++) {
Packit Service 087331
		err = 0;
Packit Service 087331
		for (j = 0; j < NUM_PCRS && !err; j++) {
Packit Service 087331
			err = tpm2_pcr_read(bank[i].algo_name, j,
Packit Service 087331
					    bank[i].pcr[j], bank[i].digest_size,
Packit Service 087331
					    &errmsg);
Packit Service 087331
			if (err) {
Packit Service 087331
				log_debug("Failed to read %s PCRs: (%s)\n",
Packit Service 087331
					  bank[i].algo_name, errmsg);
Packit Service 087331
				free(errmsg);
Packit Service 087331
				bank[i].supported = 0;
Packit Service 087331
			}
Packit Service 087331
		}
Packit Service 087331
		if (bank[i].supported)
Packit Service 087331
			tpm_enabled = 1;
Packit Service 087331
	}
Packit Service 087331
	return tpm_enabled ? 0 : 1;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int ima_measurement(const char *file)
Packit Service 087331
{
Packit Service 087331
	struct tpm_bank_info *pseudo_padded_banks;
Packit Service 087331
	struct tpm_bank_info *pseudo_banks;
Packit Service 087331
	struct tpm_bank_info *tpm_banks;
Packit Service 087331
	int is_ima_template, cur_template_fmt;
Packit Service 087331
	int num_banks = 0;
Packit Service 087331
	int tpmbanks = 1;
Packit Service 087331
	int first_record = 1;
Packit Service 087331
Packit Service 087331
	struct template_entry entry = { .template = 0 };
Packit Service 087331
	FILE *fp;
Packit Service 087331
	int invalid_template_digest = 0;
Packit Service 087331
	int err_padded = -1;
Packit Service 087331
	int err = -1;
Packit Service 087331
Packit Service 087331
	errno = 0;
Packit Service 087331
	memset(zero, 0, MAX_DIGEST_SIZE);
Packit Service 087331
Packit Service 087331
	pseudo_padded_banks = init_tpm_banks(&num_banks);
Packit Service 087331
	pseudo_banks = init_tpm_banks(&num_banks);
Packit Service 087331
	tpm_banks = init_tpm_banks(&num_banks);
Packit Service 087331
Packit Service 087331
	fp = fopen(file, "rb");
Packit Service 087331
	if (!fp) {
Packit Service 087331
		log_err("Failed to open measurement file: %s\n", file);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (imaevm_params.keyfile)	/* Support multiple public keys */
Packit Service 087331
		init_public_keys(imaevm_params.keyfile);
Packit Service 087331
	else				/* assume read pubkey from x509 cert */
Packit Service 087331
		init_public_keys("/etc/keys/x509_evm.der");
Packit Service 087331
Packit Service 087331
	/*
Packit Service 087331
	 * Reading the PCRs before walking the IMA measurement list
Packit Service 087331
	 * guarantees that all of the measurements are included in
Packit Service 087331
	 * the PCRs.
Packit Service 087331
	 */
Packit Service 087331
	if (read_tpm_banks(num_banks, tpm_banks) != 0)
Packit Service 087331
		tpmbanks = 0;
Packit Service 087331
Packit Service 087331
	while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
Packit Service 087331
		if (entry.header.name_len > TCG_EVENT_NAME_LEN_MAX) {
Packit Service 087331
			log_err("%d ERROR: event name too long!\n",
Packit Service 087331
				entry.header.name_len);
Packit Service 087331
		       fclose(fp);
Packit Service 087331
		       exit(1);
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		memset(entry.name, 0x00, sizeof(entry.name));
Packit Service 087331
		if (!fread(entry.name, entry.header.name_len, 1, fp)) {
Packit Service 087331
			log_err("Unable to read template name\n");
Packit Service 087331
			goto out;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
	       /*
Packit Service 087331
		* The "ima" template format can not be mixed with other
Packit Service 087331
		* template formats records.
Packit Service 087331
		*/
Packit Service 087331
		if (!first_record) {
Packit Service 087331
			cur_template_fmt = strcmp(entry.name, "ima") == 0 ? 1 : 0;
Packit Service 087331
			if ((is_ima_template && !cur_template_fmt) ||
Packit Service 087331
			    (!is_ima_template && cur_template_fmt)) {
Packit Service 087331
				log_err("Mixed measurement list containing \"ima\" and other template formats not supported.\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
		} else {
Packit Service 087331
			first_record = 0;
Packit Service 087331
			is_ima_template = strcmp(entry.name, "ima") == 0 ? 1 : 0;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		/* The "ima" template data is not length prefixed.  Skip it. */
Packit Service 087331
		if (!is_ima_template) {
Packit Service 087331
			if (!fread(&entry.template_len,
Packit Service 087331
				   sizeof(entry.template_len), 1, fp)) {
Packit Service 087331
				log_err("Unable to read template length\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
		} else {
Packit Service 087331
			entry.template_len = SHA_DIGEST_LENGTH +
Packit Service 087331
					     TCG_EVENT_NAME_LEN_MAX + 1;
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		if (entry.template_buf_len < entry.template_len) {
Packit Service 087331
			free(entry.template);
Packit Service 087331
			entry.template_buf_len = entry.template_len;
Packit Service 087331
			entry.template = malloc(entry.template_len);
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		if (!is_ima_template) {
Packit Service 087331
			if (!fread(entry.template, entry.template_len, 1, fp)) {
Packit Service 087331
				log_errno("Unable to read template\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
		} else {
Packit Service 087331
			uint32_t field_len;
Packit Service 087331
			uint32_t len;
Packit Service 087331
Packit Service 087331
			/*
Packit Service 087331
			 * The "ima" template data format is digest,
Packit Service 087331
			 * filename length, filename.
Packit Service 087331
			 */
Packit Service 087331
			if (!fread(entry.template, SHA_DIGEST_LENGTH, 1, fp)) {
Packit Service 087331
				log_errno("Unable to read file data hash\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
Packit Service 087331
			/*
Packit Service 087331
			 * Read the filename length, but it isn't included
Packit Service 087331
			 * in the template data hash calculation.
Packit Service 087331
			 */
Packit Service 087331
			len = fread(&field_len, sizeof(field_len), 1, fp);
Packit Service 087331
			if (len <= 0) {
Packit Service 087331
				log_errno("Failed reading file name length\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
			if (field_len > TCG_EVENT_NAME_LEN_MAX) {
Packit Service 087331
				log_err("file pathname is too long\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
Packit Service 087331
			len = fread(entry.template + SHA_DIGEST_LENGTH,
Packit Service 087331
				    field_len, 1, fp);
Packit Service 087331
			if (len != 1) {
Packit Service 087331
				log_errno("Failed reading file name\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
Packit Service 087331
			/*
Packit Service 087331
			 * The template data is fixed sized, zero out
Packit Service 087331
			 * the remaining memory.
Packit Service 087331
			 */
Packit Service 087331
			len = SHA_DIGEST_LENGTH + field_len;
Packit Service 087331
			memset(entry.template + len, 0x00,
Packit Service 087331
			       entry.template_buf_len - len);
Packit Service 087331
		}
Packit Service 087331
Packit Service 087331
		extend_tpm_banks(&entry, num_banks, pseudo_banks,
Packit Service 087331
				 pseudo_padded_banks);
Packit Service 087331
Packit Service 087331
		/* Recalculate and verify template data digest */
Packit Service 087331
		err = ima_verify_template_hash(&entry);
Packit Service 087331
		if (err)
Packit Service 087331
			invalid_template_digest = 1;
Packit Service 087331
Packit Service 087331
		if (is_ima_template)
Packit Service 087331
			ima_show(&entry);
Packit Service 087331
		else
Packit Service 087331
			ima_ng_show(&entry);
Packit Service 087331
Packit Service 087331
		if (!tpmbanks)
Packit Service 087331
			continue;
Packit Service 087331
Packit Service 087331
		/* The measurement list might contain too many entries,
Packit Service 087331
		 * compare the re-calculated TPM PCR values after each
Packit Service 087331
		 * extend.
Packit Service 087331
		 */
Packit Service 087331
		err = compare_tpm_banks(num_banks, pseudo_banks, tpm_banks);
Packit Service 087331
		if (!err)
Packit Service 087331
			break;
Packit Service 087331
Packit Service 087331
		/* Compare against original SHA1 zero padded TPM PCR values */
Packit Service 087331
		err_padded = compare_tpm_banks(num_banks, pseudo_padded_banks,
Packit Service 087331
					       tpm_banks);
Packit Service 087331
		if (!err_padded)
Packit Service 087331
			break;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (tpmbanks == 0)
Packit Service 087331
		log_info("Failed to read any TPM PCRs\n");
Packit Service 087331
	else {
Packit Service 087331
		if (!err)
Packit Service 087331
			log_info("Matched per TPM bank calculated digest(s).\n");
Packit Service 087331
		else if (!err_padded) {
Packit Service 087331
			log_info("Matched SHA1 padded TPM digest(s).\n");
Packit Service 087331
			err = 0;
Packit Service 087331
		} else
Packit Service 087331
			log_info("Failed to match per TPM bank or SHA1 padded TPM digest(s).\n");
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (invalid_template_digest) {
Packit Service 087331
		log_info("Failed to verify template data digest.\n");
Packit Service 087331
		err = 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
out:
Packit Service 087331
	fclose(fp);
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_ima_measurement(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	char *file = g_argv[optind++];
Packit Service 087331
Packit Service 087331
	if (!file) {
Packit Service 087331
		log_err("Parameters missing\n");
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return ima_measurement(file);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
#define MAX_EVENT_DATA_SIZE 200000
Packit Service 087331
static int read_binary_bios_measurements(char *file, struct tpm_bank_info *bank)
Packit Service 087331
{
Packit Service 087331
	struct {
Packit Service 087331
		struct {
Packit Service 087331
			uint32_t pcr;
Packit Service 087331
			int type;
Packit Service 087331
			unsigned char digest[SHA_DIGEST_LENGTH];
Packit Service 087331
			uint32_t len;
Packit Service 087331
		} header;
Packit Service 087331
		unsigned char data[MAX_EVENT_DATA_SIZE];
Packit Service 087331
	} event;
Packit Service 087331
	struct stat s;
Packit Service 087331
	FILE *fp;
Packit Service 087331
	SHA_CTX c;
Packit Service 087331
	int err = 0;
Packit Service 087331
	int len;
Packit Service 087331
	int i;
Packit Service 087331
Packit Service 087331
	if (stat(file, &s) == -1) {
Packit Service 087331
		errno = 0;
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (!S_ISREG(s.st_mode)) {
Packit Service 087331
		log_info("Bios event log: not a regular file or link to regular file\n");
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	fp = fopen(file, "r");
Packit Service 087331
	if (!fp) {
Packit Service 087331
		log_errno("Failed to open TPM 1.2 event log.\n");
Packit Service 087331
		return 1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (imaevm_params.verbose > LOG_INFO)
Packit Service 087331
		log_info("Reading the TPM 1.2 event log %s.\n", file);
Packit Service 087331
Packit Service 087331
	/* Extend the pseudo TPM PCRs with the event digest */
Packit Service 087331
	while (fread(&event, sizeof(event.header), 1, fp)) {
Packit Service 087331
		if (imaevm_params.verbose > LOG_INFO) {
Packit Service 087331
			log_info("%02u ", event.header.pcr);
Packit Service 087331
			log_dump(event.header.digest, SHA_DIGEST_LENGTH);
Packit Service 087331
		}
Packit Service 087331
		if (event.header.pcr > NUM_PCRS) {
Packit Service 087331
			log_err("Invalid PCR %d.\n", event.header.pcr);
Packit Service 087331
			err = 1;
Packit Service 087331
			break;
Packit Service 087331
		}
Packit Service 087331
		SHA1_Init(&c);
Packit Service 087331
		SHA1_Update(&c, bank->pcr[event.header.pcr], 20);
Packit Service 087331
		SHA1_Update(&c, event.header.digest, 20);
Packit Service 087331
		SHA1_Final(bank->pcr[event.header.pcr], &c);
Packit Service 087331
		if (event.header.len > MAX_EVENT_DATA_SIZE) {
Packit Service 087331
			log_err("Event data event too long.\n");
Packit Service 087331
			err = 1;
Packit Service 087331
			break;
Packit Service 087331
		}
Packit Service 087331
		len = fread(event.data, event.header.len, 1, fp);
Packit Service 087331
		if (len != 1) {
Packit Service 087331
			log_errno("Failed reading event data (short read)\n");
Packit Service 087331
			break;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
	fclose(fp);
Packit Service 087331
Packit Service 087331
	if (imaevm_params.verbose <= LOG_INFO)
Packit Service 087331
		return err;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < NUM_PCRS; i++) {
Packit Service 087331
		log_info("PCR-%2.2x ", i);
Packit Service 087331
		log_dump(bank->pcr[i], SHA_DIGEST_LENGTH);
Packit Service 087331
Packit Service 087331
	}
Packit Service 087331
	return err;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static void calc_bootaggr(struct tpm_bank_info *bank)
Packit Service 087331
{
Packit Service 087331
	EVP_MD_CTX *pctx;
Packit Service 087331
	unsigned int mdlen;
Packit Service 087331
	const EVP_MD *md;
Packit Service 087331
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 087331
	EVP_MD_CTX ctx;
Packit Service 087331
	pctx = &ctx;
Packit Service 087331
#else
Packit Service 087331
	pctx = EVP_MD_CTX_new();
Packit Service 087331
#endif
Packit Service 087331
	int err = 0;
Packit Service 087331
	int i;
Packit Service 087331
Packit Service 087331
	md = EVP_get_digestbyname(bank->algo_name);
Packit Service 087331
Packit Service 087331
	err = EVP_DigestInit(pctx, md);
Packit Service 087331
	if (!err) {
Packit Service 087331
		printf("EVP_DigestInit() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	for (i = 0; i < 8;  i++) {
Packit Service 087331
		err = EVP_DigestUpdate(pctx, bank->pcr[i], bank->digest_size);
Packit Service 087331
		if (!err) {
Packit Service 087331
			log_err("EVP_DigestUpdate() failed\n");
Packit Service 087331
			goto out;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (strcmp(bank->algo_name, "sha1") != 0) {
Packit Service 087331
		for (i = 8; i < 10; i++) {
Packit Service 087331
			err = EVP_DigestUpdate(pctx, bank->pcr[i], bank->digest_size);
Packit Service 087331
			if (!err) {
Packit Service 087331
				log_err("EVP_DigestUpdate() failed\n");
Packit Service 087331
				goto out;
Packit Service 087331
			}
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	err = EVP_DigestFinal(pctx, bank->digest, &mdlen);
Packit Service 087331
	if (!err) {
Packit Service 087331
		log_err("EVP_DigestFinal() failed\n");
Packit Service 087331
		goto out;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
out:
Packit Service 087331
#if OPENSSL_VERSION_NUMBER >= 0x10100000
Packit Service 087331
	EVP_MD_CTX_free(pctx);
Packit Service 087331
#endif
Packit Service 087331
	return;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/*
Packit Service 087331
 * The "boot_aggregate" format is the TPM PCR bank algorithm, a colon
Packit Service 087331
 * separator, followed by a per bank TPM PCR bank specific digest.
Packit Service 087331
 * Store the TPM PCR bank specific "boot_aggregate" value as a newline
Packit Service 087331
 * terminated string in the provided buffer.
Packit Service 087331
 */
Packit Service 087331
static int append_bootaggr(char *bootaggr, struct tpm_bank_info *tpm_banks)
Packit Service 087331
{
Packit Service 087331
	uint8_t *buf;
Packit Service 087331
	int j;
Packit Service 087331
Packit Service 087331
	strcpy(bootaggr, tpm_banks->algo_name);
Packit Service 087331
	j = strlen(tpm_banks->algo_name);
Packit Service 087331
	bootaggr[j++] = ':';
Packit Service 087331
Packit Service 087331
	for (buf = tpm_banks->digest;
Packit Service 087331
	     buf < (tpm_banks->digest + tpm_banks->digest_size);
Packit Service 087331
	     buf++) {
Packit Service 087331
		bootaggr[j++] = hex_asc_hi(*buf);
Packit Service 087331
		bootaggr[j++] = hex_asc_lo(*buf);
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	bootaggr[j++] = '\n';
Packit Service 087331
	return j;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
/*
Packit Service 087331
 * The IMA measurement list boot_aggregate is the link between the preboot
Packit Service 087331
 * event log and the IMA measurement list.  Read and calculate all the
Packit Service 087331
 * possible per TPM bank boot_aggregate digests based on the existing PCRs
Packit Service 087331
 * 0 - 9 to validate against the IMA boot_aggregate record. If the digest
Packit Service 087331
 * algorithm is SHA1, only PCRs 0 - 7 are considered to avoid ambiguity.
Packit Service 087331
 */
Packit Service 087331
static int cmd_ima_bootaggr(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	struct tpm_bank_info *tpm_banks;
Packit Service 087331
	int bootaggr_len = 0;
Packit Service 087331
	char *bootaggr;
Packit Service 087331
	int num_banks = 0;
Packit Service 087331
	int offset = 0;
Packit Service 087331
	int err = 0;
Packit Service 087331
	int i;
Packit Service 087331
Packit Service 087331
	char *file = g_argv[optind++];
Packit Service 087331
Packit Service 087331
	/*
Packit Service 087331
	 * Instead of just reading the TPM 1.2 PCRs, walk the exported
Packit Service 087331
	 * TPM 1.2 SHA1 event log, calculating the PCRs.
Packit Service 087331
	 */
Packit Service 087331
	if (file) {
Packit Service 087331
		tpm_banks = init_tpm_banks(&num_banks);
Packit Service 087331
Packit Service 087331
		/* TPM 1.2 only supports SHA1.*/
Packit Service 087331
		for (i = 1; i < num_banks; i++)
Packit Service 087331
			tpm_banks[i].supported = 0;
Packit Service 087331
Packit Service 087331
		err = read_binary_bios_measurements(file, tpm_banks);
Packit Service 087331
		if (err) {
Packit Service 087331
			log_info("Failed reading the TPM 1.2 event log %s.\n",
Packit Service 087331
				 file);
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
	} else {
Packit Service 087331
		tpm_banks = init_tpm_banks(&num_banks);
Packit Service 087331
		if (read_tpm_banks(num_banks, tpm_banks) != 0) {
Packit Service 087331
			log_info("Failed to read any TPM PCRs\n");
Packit Service 087331
			return -1;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	/*
Packit Service 087331
	 * Allocate enough memory for the per TPM 2.0 PCR bank algorithm,
Packit Service 087331
	 * the colon separator, the boot_aggregate digest and newline.
Packit Service 087331
	 *
Packit Service 087331
	 * Format: <hash algorithm name>:<boot_aggregate digest>\n ...
Packit Service 087331
	 */
Packit Service 087331
	for (i = 0; i < num_banks; i++) {
Packit Service 087331
		if (!tpm_banks[i].supported)
Packit Service 087331
			continue;
Packit Service 087331
		bootaggr_len += strlen(tpm_banks[i].algo_name) + 1;
Packit Service 087331
		bootaggr_len += (tpm_banks[i].digest_size * 2) + 1;
Packit Service 087331
	}
Packit Service 087331
	/* Make room for the trailing null */
Packit Service 087331
	bootaggr = malloc(bootaggr_len + 1);
Packit Service 087331
Packit Service 087331
	/*
Packit Service 087331
	 * Calculate and convert the per TPM 2.0 PCR bank algorithm
Packit Service 087331
	 * "boot_aggregate" digest from binary to asciihex.  Store the
Packit Service 087331
	 * "boot_aggregate" values as a list of newline terminated
Packit Service 087331
	 * strings.
Packit Service 087331
	 */
Packit Service 087331
	for (i = 0; i < num_banks; i++) {
Packit Service 087331
		if (!tpm_banks[i].supported)
Packit Service 087331
			continue;
Packit Service 087331
		calc_bootaggr(&tpm_banks[i]);
Packit Service 087331
		offset += append_bootaggr(bootaggr + offset, tpm_banks + i);
Packit Service 087331
	}
Packit Service 087331
	bootaggr[bootaggr_len] = '\0';
Packit Service 087331
	printf("%s", bootaggr);
Packit Service 087331
	free(bootaggr);
Packit Service 087331
	return 0;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static void print_usage(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	printf("usage: %s %s\n", cmd->name, cmd->arg ? cmd->arg : "");
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static void print_full_usage(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	if (cmd->name)
Packit Service 087331
		printf("usage: %s %s\n", cmd->name, cmd->arg ? cmd->arg : "");
Packit Service 087331
	if (cmd->msg)
Packit Service 087331
		printf("%s", cmd->msg);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int print_command_usage(struct command *cmds, char *command)
Packit Service 087331
{
Packit Service 087331
	struct command *cmd;
Packit Service 087331
Packit Service 087331
	for (cmd = cmds; cmd->name; cmd++) {
Packit Service 087331
		if (strcmp(cmd->name, command) == 0) {
Packit Service 087331
			print_full_usage(cmd);
Packit Service 087331
			return 0;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
	printf("invalid command: %s\n", command);
Packit Service 087331
	return -1;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static void print_all_usage(struct command *cmds)
Packit Service 087331
{
Packit Service 087331
	struct command *cmd;
Packit Service 087331
Packit Service 087331
	printf("commands:\n");
Packit Service 087331
Packit Service 087331
	for (cmd = cmds; cmd->name; cmd++) {
Packit Service 087331
		if (cmd->arg)
Packit Service 087331
			printf(" %s %s\n", cmd->name, cmd->arg);
Packit Service 087331
		else if (cmd->msg)
Packit Service 087331
			printf(" %s", cmd->msg);
Packit Service 087331
	}
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int call_command(struct command *cmds, char *command)
Packit Service 087331
{
Packit Service 087331
	struct command *cmd;
Packit Service 087331
Packit Service 087331
	for (cmd = cmds; cmd->name; cmd++) {
Packit Service 087331
		if (strcasecmp(cmd->name, command) == 0)
Packit Service 087331
			return cmd->func(cmd);
Packit Service 087331
	}
Packit Service 087331
	printf("Invalid command: %s\n", command);
Packit Service 087331
	return -1;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int cmd_help(struct command *cmd)
Packit Service 087331
{
Packit Service 087331
	if (!g_argv[optind]) {
Packit Service 087331
		print_usage(cmd);
Packit Service 087331
		return 0;
Packit Service 087331
	} else
Packit Service 087331
		return print_command_usage(cmds, g_argv[optind]);
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static void usage(void)
Packit Service 087331
{
Packit Service 087331
	printf("Usage: evmctl [-v] <command> [OPTIONS]\n");
Packit Service 087331
Packit Service 087331
	print_all_usage(cmds);
Packit Service 087331
Packit Service 087331
	printf(
Packit Service 087331
		"\n"
Packit Service 087331
		"  -a, --hashalgo     sha1 (default), sha224, sha256, sha384, sha512, streebog256, streebog512\n"
Packit Service 087331
		"  -s, --imasig       make IMA signature\n"
Packit Service 087331
		"  -d, --imahash      make IMA hash\n"
Packit Service 087331
		"  -f, --sigfile      store IMA signature in .sig file instead of xattr\n"
Packit Service 087331
		"      --xattr-user   store xattrs in user namespace (for testing purposes)\n"
Packit Service 087331
		"      --rsa          use RSA key type and signing scheme v1\n"
Packit Service 087331
		"  -k, --key          path to signing key (default: /etc/keys/{privkey,pubkey}_evm.pem)\n"
Packit Service 087331
		"  -o, --portable     generate portable EVM signatures\n"
Packit Service 087331
		"  -p, --pass         password for encrypted signing key\n"
Packit Service 087331
		"  -r, --recursive    recurse into directories (sign)\n"
Packit Service 087331
		"  -t, --type         file types to fix 'fdsxm' (f: file, d: directory, s: block/char/symlink)\n"
Packit Service 087331
		"                     x - skip fixing if both ima and evm xattrs exist (use with caution)\n"
Packit Service 087331
		"                     m - stay on the same filesystem (like 'find -xdev')\n"
Packit Service 087331
		"  -n                 print result to stdout instead of setting xattr\n"
Packit Service 087331
		"  -u, --uuid         use custom FS UUID for EVM (unspecified: from FS, empty: do not use)\n"
Packit Service 087331
		"      --smack        use extra SMACK xattrs for EVM\n"
Packit Service 087331
		"      --m32          force EVM hmac/signature for 32 bit target system\n"
Packit Service 087331
		"      --m64          force EVM hmac/signature for 64 bit target system\n"
Packit Service 087331
		"      --ino          use custom inode for EVM\n"
Packit Service 087331
		"      --uid          use custom UID for EVM\n"
Packit Service 087331
		"      --gid          use custom GID for EVM\n"
Packit Service 087331
		"      --mode         use custom Mode for EVM\n"
Packit Service 087331
		"      --generation   use custom Generation for EVM(unspecified: from FS, empty: use 0)\n"
Packit Service 087331
		"      --ima          use custom IMA signature for EVM\n"
Packit Service 087331
		"      --selinux      use custom Selinux label for EVM\n"
Packit Service 087331
		"      --caps         use custom Capabilities for EVM(unspecified: from FS, empty: do not use)\n"
Packit Service 087331
		"      --verify-sig   verify measurement list signatures\n"
Packit Service 087331
		"      --engine e     preload OpenSSL engine e (such as: gost)\n"
Packit Service 087331
		"      --ignore-violations ignore ToMToU measurement violations\n"
Packit Service 087331
		"  -v                 increase verbosity level\n"
Packit Service 087331
		"  -h, --help         display this help and exit\n"
Packit Service 087331
		"\n");
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
struct command cmds[] = {
Packit Service 087331
	{"--version", NULL, 0, ""},
Packit Service 087331
	{"help", cmd_help, 0, "<command>"},
Packit Service 087331
	{"import", cmd_import, 0, "[--rsa] pubkey keyring", "Import public key into the keyring.\n"},
Packit Service 087331
	{"convert", cmd_convert, 0, "key", "convert public key into the keyring.\n"},
Packit Service 087331
	{"sign", cmd_sign_evm, 0, "[-r] [--imahash | --imasig ] [--key key] [--pass [password] file", "Sign file metadata.\n"},
Packit Service 087331
	{"verify", cmd_verify_evm, 0, "file", "Verify EVM signature (for debugging).\n"},
Packit Service 087331
	{"ima_sign", cmd_sign_ima, 0, "[--sigfile] [--key key] [--pass [password] file", "Make file content signature.\n"},
Packit Service 087331
	{"ima_verify", cmd_verify_ima, 0, "file", "Verify IMA signature (for debugging).\n"},
Packit Service 087331
	{"ima_setxattr", cmd_setxattr_ima, 0, "[--sigfile file]", "Set IMA signature from sigfile\n"},
Packit Service 087331
	{"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"},
Packit Service 087331
	{"ima_measurement", cmd_ima_measurement, 0, "[--ignore-violations] [--verify-sig [--key key1, key2, ...]] [--pcrs [hash-algorithm,]file [--pcrs hash-algorithm,file] ...] file", "Verify measurement list (experimental).\n"},
Packit Service 087331
	{"ima_boot_aggregate", cmd_ima_bootaggr, 0, "[--pcrs hash-algorithm,file] [TPM 1.2 BIOS event log]", "Calculate per TPM bank boot_aggregate digests\n"},
Packit Service 087331
	{"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM xattrs in fix mode.\n"},
Packit Service 087331
	{"ima_clear", cmd_ima_clear, 0, "[-t fdsxm] path", "Recursively remove IMA/EVM xattrs.\n"},
Packit Service 087331
	{"sign_hash", cmd_sign_hash, 0, "[--key key] [--pass [password]", "Sign hashes from shaXsum output.\n"},
Packit Service 087331
#ifdef DEBUG
Packit Service 087331
	{"hmac", cmd_hmac_evm, 0, "[--imahash | --imasig ] file", "Sign file metadata with HMAC using symmetric key (for testing purpose).\n"},
Packit Service 087331
#endif
Packit Service 087331
	{0, 0, 0, NULL}
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
static struct option opts[] = {
Packit Service 087331
	{"help", 0, 0, 'h'},
Packit Service 087331
	{"imasig", 0, 0, 's'},
Packit Service 087331
	{"imahash", 0, 0, 'd'},
Packit Service 087331
	{"hashalgo", 1, 0, 'a'},
Packit Service 087331
	{"pass", 2, 0, 'p'},
Packit Service 087331
	{"sigfile", 0, 0, 'f'},
Packit Service 087331
	{"uuid", 2, 0, 'u'},
Packit Service 087331
	{"rsa", 0, 0, '1'},
Packit Service 087331
	{"key", 1, 0, 'k'},
Packit Service 087331
	{"type", 1, 0, 't'},
Packit Service 087331
	{"recursive", 0, 0, 'r'},
Packit Service 087331
	{"m32", 0, 0, '3'},
Packit Service 087331
	{"m64", 0, 0, '6'},
Packit Service 087331
	{"portable", 0, 0, 'o'},
Packit Service 087331
	{"smack", 0, 0, 128},
Packit Service 087331
	{"version", 0, 0, 129},
Packit Service 087331
	{"inode", 1, 0, 130},
Packit Service 087331
	{"uid", 1, 0, 131},
Packit Service 087331
	{"gid", 1, 0, 132},
Packit Service 087331
	{"mode", 1, 0, 133},
Packit Service 087331
	{"generation", 1, 0, 134},
Packit Service 087331
	{"ima", 1, 0, 135},
Packit Service 087331
	{"selinux", 1, 0, 136},
Packit Service 087331
	{"caps", 2, 0, 137},
Packit Service 087331
	{"verify-sig", 0, 0, 138},
Packit Service 087331
	{"engine", 1, 0, 139},
Packit Service 087331
	{"xattr-user", 0, 0, 140},
Packit Service 087331
	{"ignore-violations", 0, 0, 141},
Packit Service 087331
	{"pcrs", 1, 0, 142},
Packit Service 087331
	{}
Packit Service 087331
Packit Service 087331
};
Packit Service 087331
Packit Service 087331
static char *get_password(void)
Packit Service 087331
{
Packit Service 087331
	struct termios flags, tmp_flags;
Packit Service 087331
	char *password, *pwd;
Packit Service 087331
	int passlen = 64;
Packit Service 087331
Packit Service 087331
	password = malloc(passlen);
Packit Service 087331
	if (!password) {
Packit Service 087331
		perror("malloc");
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	tcgetattr(fileno(stdin), &flags);
Packit Service 087331
	tmp_flags = flags;
Packit Service 087331
	tmp_flags.c_lflag &= ~ECHO;
Packit Service 087331
	tmp_flags.c_lflag |= ECHONL;
Packit Service 087331
Packit Service 087331
	if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) {
Packit Service 087331
		perror("tcsetattr");
Packit Service 087331
		free(password);
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	printf("PEM password: ");
Packit Service 087331
	pwd = fgets(password, passlen, stdin);
Packit Service 087331
Packit Service 087331
	/* restore terminal */
Packit Service 087331
	if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) {
Packit Service 087331
		perror("tcsetattr");
Packit Service 087331
		free(password);
Packit Service 087331
		return NULL;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return pwd;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
int main(int argc, char *argv[])
Packit Service 087331
{
Packit Service 087331
	int err = 0, c, lind;
Packit Service 087331
	ENGINE *eng = NULL;
Packit Service 087331
Packit Service 087331
#if !(OPENSSL_VERSION_NUMBER < 0x10100000)
Packit Service 087331
	OPENSSL_init_crypto(
Packit Service 087331
#ifndef DISABLE_OPENSSL_CONF
Packit Service 087331
			    OPENSSL_INIT_LOAD_CONFIG |
Packit Service 087331
#endif
Packit Service 087331
			    OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
Packit Service 087331
#endif
Packit Service 087331
	g_argv = argv;
Packit Service 087331
	g_argc = argc;
Packit Service 087331
Packit Service 087331
	while (1) {
Packit Service 087331
		c = getopt_long(argc, argv, "hvnsda:op::fu::k:t:ri", opts, &lind);
Packit Service 087331
		if (c == -1)
Packit Service 087331
			break;
Packit Service 087331
Packit Service 087331
		switch (c) {
Packit Service 087331
		case 'h':
Packit Service 087331
			usage();
Packit Service 087331
			exit(0);
Packit Service 087331
			break;
Packit Service 087331
		case 'v':
Packit Service 087331
			imaevm_params.verbose++;
Packit Service 087331
			break;
Packit Service 087331
		case 'd':
Packit Service 087331
			digest = 1;
Packit Service 087331
			break;
Packit Service 087331
		case 's':
Packit Service 087331
			digsig = 1;
Packit Service 087331
			break;
Packit Service 087331
		case 'n':
Packit Service 087331
			/* do not set Extended Attributes... just print signature */
Packit Service 087331
			xattr = 0;
Packit Service 087331
			sigdump = 1;
Packit Service 087331
			break;
Packit Service 087331
		case 'a':
Packit Service 087331
			imaevm_params.hash_algo = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 'p':
Packit Service 087331
			if (optarg)
Packit Service 087331
				imaevm_params.keypass = optarg;
Packit Service 087331
			else
Packit Service 087331
				imaevm_params.keypass = get_password();
Packit Service 087331
			break;
Packit Service 087331
		case 'f':
Packit Service 087331
			sigfile = 1;
Packit Service 087331
			break;
Packit Service 087331
		case 'u':
Packit Service 087331
			uuid_str = optarg;
Packit Service 087331
			if (!uuid_str)
Packit Service 087331
				hmac_flags |= HMAC_FLAG_NO_UUID;
Packit Service 087331
			break;
Packit Service 087331
		case '1':
Packit Service 087331
			imaevm_params.x509 = 0;
Packit Service 087331
			break;
Packit Service 087331
		case 'k':
Packit Service 087331
			imaevm_params.keyfile = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 'i':
Packit Service 087331
			if (evm_portable)
Packit Service 087331
				log_err("Portable and immutable options are exclusive, ignoring immutable option.");
Packit Service 087331
			else
Packit Service 087331
				evm_immutable = true;
Packit Service 087331
			break;
Packit Service 087331
		case 'o':
Packit Service 087331
			if (evm_immutable)
Packit Service 087331
				log_err("Portable and immutable options are exclusive, ignoring portable option.");
Packit Service 087331
			else
Packit Service 087331
				evm_portable = true;
Packit Service 087331
			break;
Packit Service 087331
		case 't':
Packit Service 087331
			search_type = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 'r':
Packit Service 087331
			recursive = 1;
Packit Service 087331
			break;
Packit Service 087331
		case '3':
Packit Service 087331
			msize = 32;
Packit Service 087331
			break;
Packit Service 087331
		case '6':
Packit Service 087331
			msize = 64;
Packit Service 087331
			break;
Packit Service 087331
		case 128:
Packit Service 087331
			evm_config_xattrnames = evm_extra_smack_xattrs;
Packit Service 087331
			break;
Packit Service 087331
		case 129:
Packit Service 087331
			printf("evmctl %s\n", VERSION);
Packit Service 087331
			exit(0);
Packit Service 087331
			break;
Packit Service 087331
		case 130:
Packit Service 087331
			ino_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 131:
Packit Service 087331
			uid_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 132:
Packit Service 087331
			gid_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 133:
Packit Service 087331
			mode_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 134:
Packit Service 087331
			generation_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 135:
Packit Service 087331
			ima_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 136:
Packit Service 087331
			selinux_str = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case 137:
Packit Service 087331
			caps_str = optarg;
Packit Service 087331
			hmac_flags |= HMAC_FLAG_CAPS_SET;
Packit Service 087331
			break;
Packit Service 087331
		case 138:
Packit Service 087331
			verify_list_sig = 1;
Packit Service 087331
			break;
Packit Service 087331
		case 139: /* --engine e */
Packit Service 087331
			eng = ENGINE_by_id(optarg);
Packit Service 087331
			if (!eng) {
Packit Service 087331
				log_err("engine %s isn't available\n", optarg);
Packit Service 087331
				ERR_print_errors_fp(stderr);
Packit Service 087331
			} else if (!ENGINE_init(eng)) {
Packit Service 087331
				log_err("engine %s init failed\n", optarg);
Packit Service 087331
				ERR_print_errors_fp(stderr);
Packit Service 087331
				ENGINE_free(eng);
Packit Service 087331
				eng = NULL;
Packit Service 087331
			}
Packit Service 087331
			ENGINE_set_default(eng, ENGINE_METHOD_ALL);
Packit Service 087331
			break;
Packit Service 087331
		case 140: /* --xattr-user */
Packit Service 087331
			xattr_ima = "user.ima";
Packit Service 087331
			xattr_evm = "user.evm";
Packit Service 087331
			break;
Packit Service 087331
		case 141: /* --ignore-violations */
Packit Service 087331
			ignore_violations = 1;
Packit Service 087331
			break;
Packit Service 087331
		case 142:
Packit Service 087331
			if (npcrfile >= MAX_PCRFILE) {
Packit Service 087331
				log_err("too many --pcrfile options\n");
Packit Service 087331
				exit(1);
Packit Service 087331
			}
Packit Service 087331
			pcrfile[npcrfile++] = optarg;
Packit Service 087331
			break;
Packit Service 087331
		case '?':
Packit Service 087331
			exit(1);
Packit Service 087331
			break;
Packit Service 087331
		default:
Packit Service 087331
			log_err("getopt() returned: %d (%c)\n", c, c);
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (argv[optind] == NULL)
Packit Service 087331
		usage();
Packit Service 087331
	else
Packit Service 087331
		err = call_command(cmds, argv[optind++]);
Packit Service 087331
Packit Service 087331
	if (err) {
Packit Service 087331
		unsigned long error;
Packit Service 087331
Packit Service 087331
		if (errno)
Packit Service 087331
			log_err("errno: %s (%d)\n", strerror(errno), errno);
Packit Service 087331
		for (;;) {
Packit Service 087331
			error = ERR_get_error();
Packit Service 087331
			if (!error)
Packit Service 087331
				break;
Packit Service 087331
			log_err("%s\n", ERR_error_string(error, NULL));
Packit Service 087331
		}
Packit Service 087331
		if (err < 0)
Packit Service 087331
			err = 125;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (eng) {
Packit Service 087331
		ENGINE_finish(eng);
Packit Service 087331
		ENGINE_free(eng);
Packit Service 087331
#if OPENSSL_API_COMPAT < 0x10100000L
Packit Service 087331
		ENGINE_cleanup();
Packit Service 087331
#endif
Packit Service 087331
	}
Packit Service 087331
	ERR_free_strings();
Packit Service 087331
	EVP_cleanup();
Packit Service 087331
	BIO_free(NULL);
Packit Service 087331
	return err;
Packit Service 087331
}