Blame compat/src/libimaevm.c

Packit Service 42482e
/*
Packit Service 42482e
 * ima-evm-utils - IMA/EVM support utilities
Packit Service 42482e
 *
Packit Service 42482e
 * Copyright (C) 2011 Nokia Corporation
Packit Service 42482e
 * Copyright (C) 2011,2012,2013 Intel Corporation
Packit Service 42482e
 * Copyright (C) 2013,2014 Samsung Electronics
Packit Service 42482e
 *
Packit Service 42482e
 * Authors:
Packit Service 42482e
 * Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
Packit Service 42482e
 *                 <dmitry.kasatkin@intel.com>
Packit Service 42482e
 *                 <d.kasatkin@samsung.com>
Packit Service 42482e
 *
Packit Service 42482e
 * This program is free software; you can redistribute it and/or
Packit Service 42482e
 * modify it under the terms of the GNU General Public License
Packit Service 42482e
 * version 2 as published by the Free Software Foundation.
Packit Service 42482e
 *
Packit Service 42482e
 * This program is distributed in the hope that it will be useful,
Packit Service 42482e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 42482e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 42482e
 * GNU General Public License for more details.
Packit Service 42482e
 *
Packit Service 42482e
 * You should have received a copy of the GNU General Public License
Packit Service 42482e
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 42482e
 *
Packit Service 42482e
 * As a special exception, the copyright holders give permission to link the
Packit Service 42482e
 * code of portions of this program with the OpenSSL library under certain
Packit Service 42482e
 * conditions as described in each individual source file and distribute
Packit Service 42482e
 * linked combinations including the program with the OpenSSL library. You
Packit Service 42482e
 * must comply with the GNU General Public License in all respects
Packit Service 42482e
 * for all of the code used other than as permitted herein. If you modify
Packit Service 42482e
 * file(s) with this exception, you may extend this exception to your
Packit Service 42482e
 * version of the file(s), but you are not obligated to do so. If you do not
Packit Service 42482e
 * wish to do so, delete this exception statement from your version. If you
Packit Service 42482e
 * delete this exception statement from all source files in the program,
Packit Service 42482e
 * then also delete it in the license file.
Packit Service 42482e
 *
Packit Service 42482e
 * File: libimaevm.c
Packit Service 42482e
 *	 IMA/EVM library
Packit Service 42482e
 */
Packit Service 42482e
Packit Service 42482e
/* should we use logger instead for library? */
Packit Service 42482e
#define USE_FPRINTF
Packit Service 42482e
Packit Service 42482e
#include <sys/types.h>
Packit Service 42482e
#include <sys/param.h>
Packit Service 42482e
#include <sys/stat.h>
Packit Service 42482e
#include <asm/byteorder.h>
Packit Service 42482e
#include <unistd.h>
Packit Service 42482e
#include <dirent.h>
Packit Service 42482e
#include <string.h>
Packit Service 42482e
#include <stdio.h>
Packit Service 42482e
Packit Service 42482e
#include <openssl/pem.h>
Packit Service 42482e
#include <openssl/evp.h>
Packit Service 42482e
#include <openssl/x509.h>
Packit Service 42482e
#include <openssl/err.h>
Packit Service 42482e
Packit Service 42482e
#include "imaevm.h"
Packit Service 42482e
Packit Service 42482e
const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
Packit Service 42482e
	[PKEY_HASH_MD4]		= "md4",
Packit Service 42482e
	[PKEY_HASH_MD5]		= "md5",
Packit Service 42482e
	[PKEY_HASH_SHA1]	= "sha1",
Packit Service 42482e
	[PKEY_HASH_RIPE_MD_160]	= "rmd160",
Packit Service 42482e
	[PKEY_HASH_SHA256]	= "sha256",
Packit Service 42482e
	[PKEY_HASH_SHA384]	= "sha384",
Packit Service 42482e
	[PKEY_HASH_SHA512]	= "sha512",
Packit Service 42482e
	[PKEY_HASH_SHA224]	= "sha224",
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
/*
Packit Service 42482e
 * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
Packit Service 42482e
 */
Packit Service 42482e
static const uint8_t RSA_digest_info_MD5[] = {
Packit Service 42482e
	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
Packit Service 42482e
	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
Packit Service 42482e
	0x05, 0x00, 0x04, 0x10
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static const uint8_t RSA_digest_info_SHA1[] = {
Packit Service 42482e
	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
Packit Service 42482e
	0x2B, 0x0E, 0x03, 0x02, 0x1A,
Packit Service 42482e
	0x05, 0x00, 0x04, 0x14
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static const uint8_t RSA_digest_info_RIPE_MD_160[] = {
Packit Service 42482e
	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
Packit Service 42482e
	0x2B, 0x24, 0x03, 0x02, 0x01,
Packit Service 42482e
	0x05, 0x00, 0x04, 0x14
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static const uint8_t RSA_digest_info_SHA224[] = {
Packit Service 42482e
	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
Packit Service 42482e
	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
Packit Service 42482e
	0x05, 0x00, 0x04, 0x1C
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static const uint8_t RSA_digest_info_SHA256[] = {
Packit Service 42482e
	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
Packit Service 42482e
	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
Packit Service 42482e
	0x05, 0x00, 0x04, 0x20
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static const uint8_t RSA_digest_info_SHA384[] = {
Packit Service 42482e
	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
Packit Service 42482e
	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
Packit Service 42482e
	0x05, 0x00, 0x04, 0x30
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static const uint8_t RSA_digest_info_SHA512[] = {
Packit Service 42482e
	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
Packit Service 42482e
	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
Packit Service 42482e
	0x05, 0x00, 0x04, 0x40
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
const struct RSA_ASN1_template RSA_ASN1_templates[PKEY_HASH__LAST] = {
Packit Service 42482e
#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
Packit Service 42482e
	[PKEY_HASH_MD5]		= _(MD5),
Packit Service 42482e
	[PKEY_HASH_SHA1]	= _(SHA1),
Packit Service 42482e
	[PKEY_HASH_RIPE_MD_160]	= _(RIPE_MD_160),
Packit Service 42482e
	[PKEY_HASH_SHA256]	= _(SHA256),
Packit Service 42482e
	[PKEY_HASH_SHA384]	= _(SHA384),
Packit Service 42482e
	[PKEY_HASH_SHA512]	= _(SHA512),
Packit Service 42482e
	[PKEY_HASH_SHA224]	= _(SHA224),
Packit Service 42482e
#undef _
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
struct libevm_params params = {
Packit Service 42482e
	.verbose = LOG_INFO - 1,
Packit Service 42482e
	.x509 = 1,
Packit Service 42482e
	.hash_algo = "sha1",
Packit Service 42482e
};
Packit Service 42482e
Packit Service 42482e
static void __attribute__ ((constructor)) libinit(void);
Packit Service 42482e
Packit Service 42482e
void do_dump(FILE *fp, const void *ptr, int len, bool cr)
Packit Service 42482e
{
Packit Service 42482e
	int i;
Packit Service 42482e
	uint8_t *data = (uint8_t *) ptr;
Packit Service 42482e
Packit Service 42482e
	for (i = 0; i < len; i++)
Packit Service 42482e
		fprintf(fp, "%02x", data[i]);
Packit Service 42482e
	if (cr)
Packit Service 42482e
		fprintf(fp, "\n");
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
void dump(const void *ptr, int len)
Packit Service 42482e
{
Packit Service 42482e
	do_dump(stdout, ptr, len, true);
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int get_filesize(const char *filename)
Packit Service 42482e
{
Packit Service 42482e
	struct stat stats;
Packit Service 42482e
	/*  Need to know the file length */
Packit Service 42482e
	stat(filename, &stats);
Packit Service 42482e
	return (int)stats.st_size;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static inline off_t get_fdsize(int fd)
Packit Service 42482e
{
Packit Service 42482e
	struct stat stats;
Packit Service 42482e
	/*  Need to know the file length */
Packit Service 42482e
	fstat(fd, &stats);
Packit Service 42482e
	return stats.st_size;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static int add_file_hash(const char *file, EVP_MD_CTX *ctx)
Packit Service 42482e
{
Packit Service 42482e
	uint8_t *data;
Packit Service 42482e
	int err = -1, bs = DATA_SIZE;
Packit Service 42482e
	off_t size, len;
Packit Service 42482e
	FILE *fp;
Packit Service 42482e
Packit Service 42482e
	fp = fopen(file, "r");
Packit Service 42482e
	if (!fp) {
Packit Service 42482e
		log_err("Failed to open: %s\n", file);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	data = malloc(bs);
Packit Service 42482e
	if (!data) {
Packit Service 42482e
		log_err("malloc failed\n");
Packit Service 42482e
		goto out;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	for (size = get_fdsize(fileno(fp)); size; size -= len) {
Packit Service 42482e
		len = MIN(size, bs);
Packit Service 42482e
		if (!fread(data, len, 1, fp)) {
Packit Service 42482e
			if (ferror(fp)) {
Packit Service 42482e
				log_err("fread() failed\n\n");
Packit Service 42482e
				goto out;
Packit Service 42482e
			}
Packit Service 42482e
			break;
Packit Service 42482e
		}
Packit Service 42482e
		if (!EVP_DigestUpdate(ctx, data, len)) {
Packit Service 42482e
			log_err("EVP_DigestUpdate() failed\n");
Packit Service 42482e
			err = 1;
Packit Service 42482e
			goto out;
Packit Service 42482e
		}
Packit Service 42482e
	}
Packit Service 42482e
	err = 0;
Packit Service 42482e
out:
Packit Service 42482e
	fclose(fp);
Packit Service 42482e
	free(data);
Packit Service 42482e
Packit Service 42482e
	return err;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static int add_dir_hash(const char *file, EVP_MD_CTX *ctx)
Packit Service 42482e
{
Packit Service 42482e
	int err;
Packit Service 42482e
	struct dirent *de;
Packit Service 42482e
	DIR *dir;
Packit Service 42482e
	unsigned long long ino, off;
Packit Service 42482e
	unsigned int type;
Packit Service 42482e
	int result = 0;
Packit Service 42482e
Packit Service 42482e
	dir = opendir(file);
Packit Service 42482e
	if (!dir) {
Packit Service 42482e
		log_err("Failed to open: %s\n", file);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	while ((de = readdir(dir))) {
Packit Service 42482e
		ino = de->d_ino;
Packit Service 42482e
		off = de->d_off;
Packit Service 42482e
		type = de->d_type;
Packit Service 42482e
		log_debug("entry: %s, ino: %llu, type: %u, off: %llu, reclen: %hu\n",
Packit Service 42482e
			  de->d_name, ino, type, off, de->d_reclen);
Packit Service 42482e
		err = EVP_DigestUpdate(ctx, de->d_name, strlen(de->d_name));
Packit Service 42482e
		/*err |= EVP_DigestUpdate(ctx, &off, sizeof(off));*/
Packit Service 42482e
		err |= EVP_DigestUpdate(ctx, &ino, sizeof(ino));
Packit Service 42482e
		err |= EVP_DigestUpdate(ctx, &type, sizeof(type));
Packit Service 42482e
		if (!err) {
Packit Service 42482e
			log_err("EVP_DigestUpdate() failed\n");
Packit Service 42482e
			result = 1;
Packit Service 42482e
			break;
Packit Service 42482e
		}
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	closedir(dir);
Packit Service 42482e
Packit Service 42482e
	return result;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static int add_link_hash(const char *path, EVP_MD_CTX *ctx)
Packit Service 42482e
{
Packit Service 42482e
	int err;
Packit Service 42482e
	char buf[1024];
Packit Service 42482e
Packit Service 42482e
	err = readlink(path, buf, sizeof(buf));
Packit Service 42482e
	if (err <= 0)
Packit Service 42482e
		return -1;
Packit Service 42482e
Packit Service 42482e
	log_info("link: %s -> %.*s\n", path, err, buf);
Packit Service 42482e
	return !EVP_DigestUpdate(ctx, buf, err);
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static int add_dev_hash(struct stat *st, EVP_MD_CTX *ctx)
Packit Service 42482e
{
Packit Service 42482e
	uint32_t dev = st->st_rdev;
Packit Service 42482e
	unsigned major = (dev & 0xfff00) >> 8;
Packit Service 42482e
	unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
Packit Service 42482e
Packit Service 42482e
	log_info("device: %u:%u\n", major, minor);
Packit Service 42482e
	return !EVP_DigestUpdate(ctx, &dev, sizeof(dev));
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int ima_calc_hash(const char *file, uint8_t *hash)
Packit Service 42482e
{
Packit Service 42482e
	const EVP_MD *md;
Packit Service 42482e
	struct stat st;
Packit Service 42482e
	EVP_MD_CTX *pctx;
Packit Service 42482e
	unsigned int mdlen;
Packit Service 42482e
	int err;
Packit Service 42482e
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 42482e
	EVP_MD_CTX ctx;
Packit Service 42482e
	pctx = &ctx;
Packit Service 42482e
#else
Packit Service 42482e
	pctx = EVP_MD_CTX_new();
Packit Service 42482e
#endif
Packit Service 42482e
Packit Service 42482e
	/*  Need to know the file length */
Packit Service 42482e
	err = lstat(file, &st);
Packit Service 42482e
	if (err < 0) {
Packit Service 42482e
		log_err("Failed to stat: %s\n", file);
Packit Service 42482e
		return err;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	md = EVP_get_digestbyname(params.hash_algo);
Packit Service 42482e
	if (!md) {
Packit Service 42482e
		log_err("EVP_get_digestbyname() failed\n");
Packit Service 42482e
		return 1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	err = EVP_DigestInit(pctx, md);
Packit Service 42482e
	if (!err) {
Packit Service 42482e
		log_err("EVP_DigestInit() failed\n");
Packit Service 42482e
		return 1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	switch (st.st_mode & S_IFMT) {
Packit Service 42482e
	case S_IFREG:
Packit Service 42482e
		err = add_file_hash(file, pctx);
Packit Service 42482e
		break;
Packit Service 42482e
	case S_IFDIR:
Packit Service 42482e
		err = add_dir_hash(file, pctx);
Packit Service 42482e
		break;
Packit Service 42482e
	case S_IFLNK:
Packit Service 42482e
		err = add_link_hash(file, pctx);
Packit Service 42482e
		break;
Packit Service 42482e
	case S_IFIFO: case S_IFSOCK:
Packit Service 42482e
	case S_IFCHR: case S_IFBLK:
Packit Service 42482e
		err = add_dev_hash(&st, pctx);
Packit Service 42482e
		break;
Packit Service 42482e
	default:
Packit Service 42482e
		log_errno("Unsupported file type");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (err)
Packit Service 42482e
		return err;
Packit Service 42482e
Packit Service 42482e
	err = EVP_DigestFinal(pctx, hash, &mdlen);
Packit Service 42482e
	if (!err) {
Packit Service 42482e
		log_err("EVP_DigestFinal() failed\n");
Packit Service 42482e
		return 1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	return mdlen;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
RSA *read_pub_key(const char *keyfile, int x509)
Packit Service 42482e
{
Packit Service 42482e
	FILE *fp;
Packit Service 42482e
	RSA *key = NULL;
Packit Service 42482e
	X509 *crt = NULL;
Packit Service 42482e
	EVP_PKEY *pkey = NULL;
Packit Service 42482e
Packit Service 42482e
	fp = fopen(keyfile, "r");
Packit Service 42482e
	if (!fp) {
Packit Service 42482e
		log_err("Failed to open keyfile: %s\n", keyfile);
Packit Service 42482e
		return NULL;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (x509) {
Packit Service 42482e
		crt = d2i_X509_fp(fp, NULL);
Packit Service 42482e
		if (!crt) {
Packit Service 42482e
			log_err("d2i_X509_fp() failed\n");
Packit Service 42482e
			goto out;
Packit Service 42482e
		}
Packit Service 42482e
		pkey = X509_extract_key(crt);
Packit Service 42482e
		if (!pkey) {
Packit Service 42482e
			log_err("X509_extract_key() failed\n");
Packit Service 42482e
			goto out;
Packit Service 42482e
		}
Packit Service 42482e
		key = EVP_PKEY_get1_RSA(pkey);
Packit Service 42482e
	} else {
Packit Service 42482e
		key = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (!key)
Packit Service 42482e
		log_err("PEM_read_RSA_PUBKEY() failed\n");
Packit Service 42482e
Packit Service 42482e
out:
Packit Service 42482e
	if (pkey)
Packit Service 42482e
		EVP_PKEY_free(pkey);
Packit Service 42482e
	if (crt)
Packit Service 42482e
		X509_free(crt);
Packit Service 42482e
	fclose(fp);
Packit Service 42482e
	return key;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int verify_hash_v1(const char *file, const unsigned char *hash, int size,
Packit Service 42482e
		   unsigned char *sig, int siglen, const char *keyfile)
Packit Service 42482e
{
Packit Service 42482e
	int err, len;
Packit Service 42482e
	SHA_CTX ctx;
Packit Service 42482e
	unsigned char out[1024];
Packit Service 42482e
	RSA *key;
Packit Service 42482e
	unsigned char sighash[20];
Packit Service 42482e
	struct signature_hdr *hdr = (struct signature_hdr *)sig;
Packit Service 42482e
Packit Service 42482e
	log_info("hash-v1: ");
Packit Service 42482e
	log_dump(hash, size);
Packit Service 42482e
Packit Service 42482e
	key = read_pub_key(keyfile, 0);
Packit Service 42482e
	if (!key)
Packit Service 42482e
		return 1;
Packit Service 42482e
Packit Service 42482e
	SHA1_Init(&ctx;;
Packit Service 42482e
	SHA1_Update(&ctx, hash, size);
Packit Service 42482e
	SHA1_Update(&ctx, hdr, sizeof(*hdr));
Packit Service 42482e
	SHA1_Final(sighash, &ctx;;
Packit Service 42482e
	log_info("sighash: ");
Packit Service 42482e
	log_dump(sighash, sizeof(sighash));
Packit Service 42482e
Packit Service 42482e
	err = RSA_public_decrypt(siglen - sizeof(*hdr) - 2, sig + sizeof(*hdr) + 2, out, key, RSA_PKCS1_PADDING);
Packit Service 42482e
	RSA_free(key);
Packit Service 42482e
	if (err < 0) {
Packit Service 42482e
		log_err("%s: RSA_public_decrypt() failed: %d\n", file, err);
Packit Service 42482e
		return 1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	len = err;
Packit Service 42482e
Packit Service 42482e
	if (len != sizeof(sighash) || memcmp(out, sighash, len) != 0) {
Packit Service 42482e
		log_err("%s: verification failed: %d\n", file, err);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	return 0;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
struct public_key_entry {
Packit Service 42482e
	struct public_key_entry *next;
Packit Service 42482e
	uint32_t keyid;
Packit Service 42482e
	char name[9];
Packit Service 42482e
	RSA *key;
Packit Service 42482e
};
Packit Service 42482e
static struct public_key_entry *public_keys = NULL;
Packit Service 42482e
Packit Service 42482e
static RSA *find_keyid(uint32_t keyid)
Packit Service 42482e
{
Packit Service 42482e
	struct public_key_entry *entry;
Packit Service 42482e
Packit Service 42482e
	for (entry = public_keys; entry != NULL; entry = entry->next) {
Packit Service 42482e
		if (entry->keyid == keyid)
Packit Service 42482e
			return entry->key;
Packit Service 42482e
	}
Packit Service 42482e
	return NULL;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
void init_public_keys(const char *keyfiles)
Packit Service 42482e
{
Packit Service 42482e
	struct public_key_entry *entry;
Packit Service 42482e
	char *tmp_keyfiles;
Packit Service 42482e
	char *keyfile;
Packit Service 42482e
	int i = 1;
Packit Service 42482e
Packit Service 42482e
	tmp_keyfiles = strdup(keyfiles);
Packit Service 42482e
Packit Service 42482e
	while ((keyfile = strsep(&tmp_keyfiles, ", \t")) != NULL) {
Packit Service 42482e
		if (!keyfile)
Packit Service 42482e
			break;
Packit Service 42482e
		if ((*keyfile == '\0') || (*keyfile == ' ') ||
Packit Service 42482e
		    (*keyfile == '\t'))
Packit Service 42482e
			continue;
Packit Service 42482e
Packit Service 42482e
		entry = malloc(sizeof(struct public_key_entry));
Packit Service 42482e
		if (!entry) {
Packit Service 42482e
			perror("malloc");
Packit Service 42482e
			break;
Packit Service 42482e
		}
Packit Service 42482e
Packit Service 42482e
		entry->key = read_pub_key(keyfile, 1);
Packit Service 42482e
		if (!entry->key) {
Packit Service 42482e
			free(entry);
Packit Service 42482e
			continue;
Packit Service 42482e
		}
Packit Service 42482e
Packit Service 42482e
		calc_keyid_v2(&entry->keyid, entry->name, entry->key);
Packit Service 42482e
		sprintf(entry->name, "%x", __be32_to_cpup(&entry->keyid));
Packit Service 42482e
		log_info("key %d: %s %s\n", i++, entry->name, keyfile);
Packit Service 42482e
		entry->next = public_keys;
Packit Service 42482e
		public_keys = entry;
Packit Service 42482e
	}
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int verify_hash_v2(const char *file, const unsigned char *hash, int size,
Packit Service 42482e
		   unsigned char *sig, int siglen, const char *keyfile)
Packit Service 42482e
{
Packit Service 42482e
	int err, len;
Packit Service 42482e
	unsigned char out[1024];
Packit Service 42482e
	RSA *key;
Packit Service 42482e
	struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
Packit Service 42482e
	const struct RSA_ASN1_template *asn1;
Packit Service 42482e
Packit Service 42482e
	if (params.verbose > LOG_INFO) {
Packit Service 42482e
		log_info("hash: ");
Packit Service 42482e
		log_dump(hash, size);
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (public_keys) {
Packit Service 42482e
		key = find_keyid(hdr->keyid);
Packit Service 42482e
		if (!key) {
Packit Service 42482e
			log_err("%s: unknown keyid: %x\n", file,
Packit Service 42482e
				__be32_to_cpup(&hdr->keyid));
Packit Service 42482e
			return -1;
Packit Service 42482e
		}
Packit Service 42482e
	} else {
Packit Service 42482e
		key = read_pub_key(keyfile, 1);
Packit Service 42482e
		if (!key)
Packit Service 42482e
			return 1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
Packit Service 42482e
	err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr),
Packit Service 42482e
				 out, key, RSA_PKCS1_PADDING);
Packit Service 42482e
	if (err < 0) {
Packit Service 42482e
		log_err("%s: RSA_public_decrypt() failed: %d\n", file, err);
Packit Service 42482e
		return 1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	len = err;
Packit Service 42482e
Packit Service 42482e
	asn1 = &RSA_ASN1_templates[hdr->hash_algo];
Packit Service 42482e
Packit Service 42482e
	if (len < asn1->size || memcmp(out, asn1->data, asn1->size)) {
Packit Service 42482e
		log_err("%s: verification failed: %d\n", file, err);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	len -= asn1->size;
Packit Service 42482e
Packit Service 42482e
	if (len != size || memcmp(out + asn1->size, hash, len)) {
Packit Service 42482e
		log_err("%s: verification failed: %d\n", file, err);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	return 0;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int get_hash_algo(const char *algo)
Packit Service 42482e
{
Packit Service 42482e
	int i;
Packit Service 42482e
Packit Service 42482e
	for (i = 0; i < PKEY_HASH__LAST; i++)
Packit Service 42482e
		if (!strcmp(algo, pkey_hash_algo[i]))
Packit Service 42482e
			return i;
Packit Service 42482e
Packit Service 42482e
	return PKEY_HASH_SHA1;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static int get_hash_algo_from_sig(unsigned char *sig)
Packit Service 42482e
{
Packit Service 42482e
	uint8_t hashalgo;
Packit Service 42482e
Packit Service 42482e
	if (sig[0] == 1) {
Packit Service 42482e
		hashalgo = ((struct signature_hdr *)sig)->hash;
Packit Service 42482e
Packit Service 42482e
		if (hashalgo >= DIGEST_ALGO_MAX)
Packit Service 42482e
			return -1;
Packit Service 42482e
Packit Service 42482e
		switch (hashalgo) {
Packit Service 42482e
		case DIGEST_ALGO_SHA1:
Packit Service 42482e
			return PKEY_HASH_SHA1;
Packit Service 42482e
		case DIGEST_ALGO_SHA256:
Packit Service 42482e
			return PKEY_HASH_SHA256;
Packit Service 42482e
		default:
Packit Service 42482e
			return -1;
Packit Service 42482e
		}
Packit Service 42482e
	} else if (sig[0] == 2) {
Packit Service 42482e
		hashalgo = ((struct signature_v2_hdr *)sig)->hash_algo;
Packit Service 42482e
		if (hashalgo >= PKEY_HASH__LAST)
Packit Service 42482e
			return -1;
Packit Service 42482e
		return hashalgo;
Packit Service 42482e
	} else
Packit Service 42482e
		return -1;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int verify_hash(const char *file, const unsigned char *hash, int size, unsigned char *sig,
Packit Service 42482e
		int siglen)
Packit Service 42482e
{
Packit Service 42482e
	const char *key;
Packit Service 42482e
	int x509;
Packit Service 42482e
	verify_hash_fn_t verify_hash;
Packit Service 42482e
Packit Service 42482e
	/* Get signature type from sig header */
Packit Service 42482e
	if (sig[0] == DIGSIG_VERSION_1) {
Packit Service 42482e
		verify_hash = verify_hash_v1;
Packit Service 42482e
		/* Read pubkey from RSA key */
Packit Service 42482e
		x509 = 0;
Packit Service 42482e
	} else if (sig[0] == DIGSIG_VERSION_2) {
Packit Service 42482e
		verify_hash = verify_hash_v2;
Packit Service 42482e
		/* Read pubkey from x509 cert */
Packit Service 42482e
		x509 = 1;
Packit Service 42482e
	} else
Packit Service 42482e
		return -1;
Packit Service 42482e
Packit Service 42482e
	/* Determine what key to use for verification*/
Packit Service 42482e
	key = params.keyfile ? : x509 ?
Packit Service 42482e
			"/etc/keys/x509_evm.der" :
Packit Service 42482e
			"/etc/keys/pubkey_evm.pem";
Packit Service 42482e
Packit Service 42482e
	return verify_hash(file, hash, size, sig, siglen, key);
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int ima_verify_signature(const char *file, unsigned char *sig, int siglen,
Packit Service 42482e
			 unsigned char *digest, int digestlen)
Packit Service 42482e
{
Packit Service 42482e
	unsigned char hash[64];
Packit Service 42482e
	int hashlen, sig_hash_algo;
Packit Service 42482e
Packit Service 42482e
	if (sig[0] != 0x03) {
Packit Service 42482e
		log_err("security.ima has no signature\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	sig_hash_algo = get_hash_algo_from_sig(sig + 1);
Packit Service 42482e
	if (sig_hash_algo < 0) {
Packit Service 42482e
		log_err("Invalid signature\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
	/* Use hash algorithm as retrieved from signature */
Packit Service 42482e
	params.hash_algo = pkey_hash_algo[sig_hash_algo];
Packit Service 42482e
Packit Service 42482e
	/*
Packit Service 42482e
	 * Validate the signature based on the digest included in the
Packit Service 42482e
	 * measurement list, not by calculating the local file digest.
Packit Service 42482e
	 */
Packit Service 42482e
	if (digestlen > 0)
Packit Service 42482e
	    return verify_hash(file, digest, digestlen, sig + 1, siglen - 1);
Packit Service 42482e
Packit Service 42482e
	hashlen = ima_calc_hash(file, hash);
Packit Service 42482e
	if (hashlen <= 1)
Packit Service 42482e
		return hashlen;
Packit Service 42482e
Packit Service 42482e
	return verify_hash(file, hash, hashlen, sig + 1, siglen - 1);
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
/*
Packit Service 42482e
 * Create binary key representation suitable for kernel
Packit Service 42482e
 */
Packit Service 42482e
int key2bin(RSA *key, unsigned char *pub)
Packit Service 42482e
{
Packit Service 42482e
	int len, b, offset = 0;
Packit Service 42482e
	struct pubkey_hdr *pkh = (struct pubkey_hdr *)pub;
Packit Service 42482e
	const BIGNUM *n, *e;
Packit Service 42482e
Packit Service 42482e
#if OPENSSL_VERSION_NUMBER < 0x10100000
Packit Service 42482e
	n = key->n;
Packit Service 42482e
	e = key->e;
Packit Service 42482e
#else
Packit Service 42482e
	RSA_get0_key(key, &n, &e, NULL);
Packit Service 42482e
#endif
Packit Service 42482e
Packit Service 42482e
	/* add key header */
Packit Service 42482e
	pkh->version = 1;
Packit Service 42482e
	pkh->timestamp = 0;	/* PEM has no timestamp?? */
Packit Service 42482e
	pkh->algo = PUBKEY_ALGO_RSA;
Packit Service 42482e
	pkh->nmpi = 2;
Packit Service 42482e
Packit Service 42482e
	offset += sizeof(*pkh);
Packit Service 42482e
Packit Service 42482e
	len = BN_num_bytes(n);
Packit Service 42482e
	b = BN_num_bits(n);
Packit Service 42482e
	pub[offset++] = b >> 8;
Packit Service 42482e
	pub[offset++] = b & 0xff;
Packit Service 42482e
	BN_bn2bin(n, &pub[offset]);
Packit Service 42482e
	offset += len;
Packit Service 42482e
Packit Service 42482e
	len = BN_num_bytes(e);
Packit Service 42482e
	b = BN_num_bits(e);
Packit Service 42482e
	pub[offset++] = b >> 8;
Packit Service 42482e
	pub[offset++] = b & 0xff;
Packit Service 42482e
	BN_bn2bin(e, &pub[offset]);
Packit Service 42482e
	offset += len;
Packit Service 42482e
Packit Service 42482e
	return offset;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
void calc_keyid_v1(uint8_t *keyid, char *str, const unsigned char *pkey, int len)
Packit Service 42482e
{
Packit Service 42482e
	uint8_t sha1[SHA_DIGEST_LENGTH];
Packit Service 42482e
	uint64_t id;
Packit Service 42482e
Packit Service 42482e
	SHA1(pkey, len, sha1);
Packit Service 42482e
Packit Service 42482e
	/* sha1[12 - 19] is exactly keyid from gpg file */
Packit Service 42482e
	memcpy(keyid, sha1 + 12, 8);
Packit Service 42482e
	log_debug("keyid: ");
Packit Service 42482e
	log_debug_dump(keyid, 8);
Packit Service 42482e
Packit Service 42482e
	if (params.verbose > LOG_INFO) {
Packit Service 42482e
		id = __be64_to_cpup((__be64 *) keyid);
Packit Service 42482e
		sprintf(str, "%llX", (unsigned long long)id);
Packit Service 42482e
		log_info("keyid-v1: %s\n", str);
Packit Service 42482e
	}
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key)
Packit Service 42482e
{
Packit Service 42482e
	uint8_t sha1[SHA_DIGEST_LENGTH];
Packit Service 42482e
	unsigned char *pkey = NULL;
Packit Service 42482e
	int len;
Packit Service 42482e
Packit Service 42482e
	len = i2d_RSAPublicKey(key, &pkey);
Packit Service 42482e
Packit Service 42482e
	SHA1(pkey, len, sha1);
Packit Service 42482e
Packit Service 42482e
	/* sha1[12 - 19] is exactly keyid from gpg file */
Packit Service 42482e
	memcpy(keyid, sha1 + 16, 4);
Packit Service 42482e
	log_debug("keyid: ");
Packit Service 42482e
	log_debug_dump(keyid, 4);
Packit Service 42482e
Packit Service 42482e
	if (params.verbose > LOG_INFO) {
Packit Service 42482e
		sprintf(str, "%x", __be32_to_cpup(keyid));
Packit Service 42482e
		log_info("keyid: %s\n", str);
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	free(pkey);
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static RSA *read_priv_key(const char *keyfile, const char *keypass)
Packit Service 42482e
{
Packit Service 42482e
	FILE *fp;
Packit Service 42482e
	RSA *key;
Packit Service 42482e
Packit Service 42482e
	fp = fopen(keyfile, "r");
Packit Service 42482e
	if (!fp) {
Packit Service 42482e
		log_err("Failed to open keyfile: %s\n", keyfile);
Packit Service 42482e
		return NULL;
Packit Service 42482e
	}
Packit Service 42482e
	ERR_load_crypto_strings();
Packit Service 42482e
	key = PEM_read_RSAPrivateKey(fp, NULL, NULL, (void *)keypass);
Packit Service 42482e
	if (!key) {
Packit Service 42482e
		char str[256];
Packit Service 42482e
Packit Service 42482e
		ERR_error_string(ERR_get_error(), str);
Packit Service 42482e
		log_err("PEM_read_RSAPrivateKey() failed: %s\n", str);
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	fclose(fp);
Packit Service 42482e
	return key;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static int get_hash_algo_v1(const char *algo)
Packit Service 42482e
{
Packit Service 42482e
Packit Service 42482e
	if (!strcmp(algo, "sha1"))
Packit Service 42482e
		return DIGEST_ALGO_SHA1;
Packit Service 42482e
	else if (!strcmp(algo, "sha256"))
Packit Service 42482e
		return DIGEST_ALGO_SHA256;
Packit Service 42482e
Packit Service 42482e
	return -1;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int sign_hash_v1(const char *hashalgo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig)
Packit Service 42482e
{
Packit Service 42482e
	int len = -1, hashalgo_idx;
Packit Service 42482e
	SHA_CTX ctx;
Packit Service 42482e
	unsigned char pub[1024];
Packit Service 42482e
	RSA *key;
Packit Service 42482e
	char name[20];
Packit Service 42482e
	unsigned char sighash[20];
Packit Service 42482e
	struct signature_hdr *hdr;
Packit Service 42482e
	uint16_t *blen;
Packit Service 42482e
Packit Service 42482e
	if (!hash) {
Packit Service 42482e
		log_err("sign_hash_v1: hash is null\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (size < 0) {
Packit Service 42482e
		log_err("sign_hash_v1: size is negative: %d\n", size);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (!hashalgo) {
Packit Service 42482e
		log_err("sign_hash_v1: hashalgo is null\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (!sig) {
Packit Service 42482e
		log_err("sign_hash_v1: sig is null\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	log_info("hash: ");
Packit Service 42482e
	log_dump(hash, size);
Packit Service 42482e
Packit Service 42482e
	key = read_priv_key(keyfile, params.keypass);
Packit Service 42482e
	if (!key)
Packit Service 42482e
		return -1;
Packit Service 42482e
Packit Service 42482e
	hdr = (struct signature_hdr *)sig;
Packit Service 42482e
Packit Service 42482e
	/* now create a new hash */
Packit Service 42482e
	hdr->version = (uint8_t) DIGSIG_VERSION_1;
Packit Service 42482e
	hdr->timestamp = time(NULL);
Packit Service 42482e
	hdr->algo = PUBKEY_ALGO_RSA;
Packit Service 42482e
	hashalgo_idx = get_hash_algo_v1(hashalgo);
Packit Service 42482e
	if (hashalgo_idx < 0) {
Packit Service 42482e
		log_err("Signature version 1 does not support hash algo %s\n",
Packit Service 42482e
			hashalgo);
Packit Service 42482e
		goto out;
Packit Service 42482e
	}
Packit Service 42482e
	hdr->hash = (uint8_t) hashalgo_idx;
Packit Service 42482e
Packit Service 42482e
	len = key2bin(key, pub);
Packit Service 42482e
	calc_keyid_v1(hdr->keyid, name, pub, len);
Packit Service 42482e
Packit Service 42482e
	hdr->nmpi = 1;
Packit Service 42482e
Packit Service 42482e
	SHA1_Init(&ctx;;
Packit Service 42482e
	SHA1_Update(&ctx, hash, size);
Packit Service 42482e
	SHA1_Update(&ctx, hdr, sizeof(*hdr));
Packit Service 42482e
	SHA1_Final(sighash, &ctx;;
Packit Service 42482e
	log_info("sighash: ");
Packit Service 42482e
	log_dump(sighash, sizeof(sighash));
Packit Service 42482e
Packit Service 42482e
	len = RSA_private_encrypt(sizeof(sighash), sighash, sig + sizeof(*hdr) + 2, key, RSA_PKCS1_PADDING);
Packit Service 42482e
	if (len < 0) {
Packit Service 42482e
		log_err("RSA_private_encrypt() failed: %d\n", len);
Packit Service 42482e
		goto out;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	/* we add bit length of the signature to make it gnupg compatible */
Packit Service 42482e
	blen = (uint16_t *) (sig + sizeof(*hdr));
Packit Service 42482e
	*blen = __cpu_to_be16(len << 3);
Packit Service 42482e
	len += sizeof(*hdr) + 2;
Packit Service 42482e
	log_info("evm/ima signature-v1: %d bytes\n", len);
Packit Service 42482e
out:
Packit Service 42482e
	RSA_free(key);
Packit Service 42482e
	return len;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
int sign_hash_v2(const char *algo, const unsigned char *hash, int size, const char *keyfile, unsigned char *sig)
Packit Service 42482e
{
Packit Service 42482e
	struct signature_v2_hdr *hdr;
Packit Service 42482e
	int len = -1;
Packit Service 42482e
	RSA *key;
Packit Service 42482e
	char name[20];
Packit Service 42482e
	unsigned char *buf;
Packit Service 42482e
	const struct RSA_ASN1_template *asn1;
Packit Service 42482e
Packit Service 42482e
	if (!hash) {
Packit Service 42482e
		log_err("sign_hash_v2: hash is null\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (size < 0) {
Packit Service 42482e
		log_err("sign_hash_v2: size is negative: %d\n", size);
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (!sig) {
Packit Service 42482e
		log_err("sign_hash_v2: sig is null\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	if (!algo) {
Packit Service 42482e
		log_err("sign_hash_v2: algo is null\n");
Packit Service 42482e
		return -1;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	log_info("hash: ");
Packit Service 42482e
	log_dump(hash, size);
Packit Service 42482e
Packit Service 42482e
	key = read_priv_key(keyfile, params.keypass);
Packit Service 42482e
	if (!key)
Packit Service 42482e
		return -1;
Packit Service 42482e
Packit Service 42482e
	hdr = (struct signature_v2_hdr *)sig;
Packit Service 42482e
	hdr->version = (uint8_t) DIGSIG_VERSION_2;
Packit Service 42482e
Packit Service 42482e
	hdr->hash_algo = get_hash_algo(algo);
Packit Service 42482e
Packit Service 42482e
	calc_keyid_v2(&hdr->keyid, name, key);
Packit Service 42482e
Packit Service 42482e
	asn1 = &RSA_ASN1_templates[hdr->hash_algo];
Packit Service 42482e
Packit Service 42482e
	buf = malloc(size + asn1->size);
Packit Service 42482e
	if (!buf)
Packit Service 42482e
		goto out;
Packit Service 42482e
Packit Service 42482e
	memcpy(buf, asn1->data, asn1->size);
Packit Service 42482e
	memcpy(buf + asn1->size, hash, size);
Packit Service 42482e
	len = RSA_private_encrypt(size + asn1->size, buf, hdr->sig,
Packit Service 42482e
				  key, RSA_PKCS1_PADDING);
Packit Service 42482e
	if (len < 0) {
Packit Service 42482e
		log_err("RSA_private_encrypt() failed: %d\n", len);
Packit Service 42482e
		goto out;
Packit Service 42482e
	}
Packit Service 42482e
Packit Service 42482e
	/* we add bit length of the signature to make it gnupg compatible */
Packit Service 42482e
	hdr->sig_size = __cpu_to_be16(len);
Packit Service 42482e
	len += sizeof(*hdr);
Packit Service 42482e
	log_info("evm/ima signature: %d bytes\n", len);
Packit Service 42482e
out:
Packit Service 42482e
	if (buf)
Packit Service 42482e
		free(buf);
Packit Service 42482e
	RSA_free(key);
Packit Service 42482e
	return len;
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
Packit Service 42482e
int sign_hash(const char *hashalgo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig)
Packit Service 42482e
{
Packit Service 42482e
	if (keypass)
Packit Service 42482e
		params.keypass = keypass;
Packit Service 42482e
Packit Service 42482e
	return params.x509 ? sign_hash_v2(hashalgo, hash, size, keyfile, sig) :
Packit Service 42482e
			     sign_hash_v1(hashalgo, hash, size, keyfile, sig);
Packit Service 42482e
}
Packit Service 42482e
Packit Service 42482e
static void libinit()
Packit Service 42482e
{
Packit Service 42482e
	OpenSSL_add_all_algorithms();
Packit Service 42482e
	ERR_load_crypto_strings();
Packit Service 42482e
}