Blame src/pcr_tss.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: pcr_tss.c
Packit Service 087331
 *	 PCR reading implementation based on Intel TSS2
Packit Service 087331
 */
Packit Service 087331
Packit Service 087331
#include <stdio.h>
Packit Service 087331
#include <string.h>
Packit Service 087331
Packit Service 087331
#include <openssl/sha.h>
Packit Service 087331
Packit Service 087331
#ifdef HAVE_LIBTSS2_ESYS
Packit Service 087331
# include <tss2/tss2_esys.h>
Packit Service 087331
Packit Service 087331
# ifdef HAVE_LIBTSS2_RC
Packit Service 087331
#  include <tss2/tss2_rc.h>
Packit Service 087331
#  define LIB "tss2-rc-decode"
Packit Service 087331
# else
Packit Service 087331
#  define LIB "tss2-esys"
Packit Service 087331
# endif
Packit Service 087331
Packit Service 087331
#endif /* HAVE_LIBTSS2_ESYS */
Packit Service 087331
Packit Service 087331
#define USE_FPRINTF
Packit Service 087331
#include "imaevm.h"
Packit Service 087331
Packit Service 087331
int tpm2_pcr_supported(void)
Packit Service 087331
{
Packit Service 087331
	if (imaevm_params.verbose > LOG_INFO)
Packit Service 087331
		log_info("Using %s to read PCRs.\n", LIB);
Packit Service 087331
Packit Service 087331
	return 1;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static int pcr_selections_match(TPML_PCR_SELECTION *a, TPML_PCR_SELECTION *b)
Packit Service 087331
{
Packit Service 087331
	int i, j;
Packit Service 087331
Packit Service 087331
	if (a->count != b->count)
Packit Service 087331
		return 0;
Packit Service 087331
Packit Service 087331
	for (i = 0; i < a->count; i++) {
Packit Service 087331
		if (a->pcrSelections[i].hash != b->pcrSelections[i].hash)
Packit Service 087331
			return 0;
Packit Service 087331
		if (a->pcrSelections[i].sizeofSelect != b->pcrSelections[i].sizeofSelect)
Packit Service 087331
			return 0;
Packit Service 087331
		for (j = 0; j < a->pcrSelections[i].sizeofSelect; j++) {
Packit Service 087331
			if (a->pcrSelections[i].pcrSelect[j] != b->pcrSelections[i].pcrSelect[j])
Packit Service 087331
				return 0;
Packit Service 087331
		}
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	return 1;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static inline int tpm2_set_errmsg(char **errmsg, const char *message, TSS2_RC ret)
Packit Service 087331
{
Packit Service 087331
#ifdef HAVE_LIBTSS2_RC
Packit Service 087331
		return asprintf(errmsg, "%s: %s", message, Tss2_RC_Decode(ret));
Packit Service 087331
#else
Packit Service 087331
		return asprintf(errmsg, "%s: #%d", message, ret);
Packit Service 087331
#endif
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
static TPM2_ALG_ID algo_to_tss2(const char *algo_name)
Packit Service 087331
{
Packit Service 087331
	if (!strcmp(algo_name, "sha1"))
Packit Service 087331
		return TPM2_ALG_SHA1;
Packit Service 087331
	else if (!strcmp(algo_name, "sha256"))
Packit Service 087331
		return TPM2_ALG_SHA256;
Packit Service 087331
Packit Service 087331
	return TPM2_ALG_ERROR;
Packit Service 087331
}
Packit Service 087331
Packit Service 087331
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
Packit Service 087331
		 int len, char **errmsg)
Packit Service 087331
{
Packit Service 087331
	TSS2_ABI_VERSION abi_version = {
Packit Service 087331
		.tssCreator = 1,
Packit Service 087331
		.tssFamily = 2,
Packit Service 087331
		.tssLevel = 1,
Packit Service 087331
		.tssVersion = 108,
Packit Service 087331
	};
Packit Service 087331
	ESYS_CONTEXT *ctx = NULL;
Packit Service 087331
	TSS2_RC ret = 0;
Packit Service 087331
	TPML_PCR_SELECTION *pcr_select_out;
Packit Service 087331
	TPML_DIGEST *pcr_digests;
Packit Service 087331
	UINT32 pcr_update_counter;
Packit Service 087331
Packit Service 087331
	TPM2_ALG_ID algid = algo_to_tss2(algo_name);
Packit Service 087331
	if (algid == TPM2_ALG_ERROR) {
Packit Service 087331
		ret = asprintf(errmsg, "unsupported tss2 algorithm");
Packit Service 087331
		if (ret == -1)	/* the contents of errmsg are undefined */
Packit Service 087331
			*errmsg = NULL;
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	TPML_PCR_SELECTION pcr_select_in = {
Packit Service 087331
		.count = 1,
Packit Service 087331
		.pcrSelections = {
Packit Service 087331
			{
Packit Service 087331
				.hash = algid,
Packit Service 087331
				.sizeofSelect = 3,
Packit Service 087331
				.pcrSelect = { 0x00, 0x00, 0x00 },
Packit Service 087331
			}
Packit Service 087331
		}
Packit Service 087331
	};
Packit Service 087331
Packit Service 087331
	pcr_select_in.pcrSelections[0].pcrSelect[idx / 8] = (1 << (idx % 8));
Packit Service 087331
Packit Service 087331
	ret = Esys_Initialize(&ctx, NULL, &abi_version);
Packit Service 087331
	if (ret != TPM2_RC_SUCCESS) {
Packit Service 087331
		ret = tpm2_set_errmsg(errmsg, "esys initialize failed", ret);
Packit Service 087331
		if (ret == -1)	/* the contents of errmsg are undefined */
Packit Service 087331
			*errmsg = NULL;
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	ret = Esys_PCR_Read(ctx,
Packit Service 087331
			    ESYS_TR_NONE,
Packit Service 087331
			    ESYS_TR_NONE,
Packit Service 087331
			    ESYS_TR_NONE,
Packit Service 087331
			    &pcr_select_in,
Packit Service 087331
			    &pcr_update_counter,
Packit Service 087331
			    &pcr_select_out,
Packit Service 087331
			    &pcr_digests);
Packit Service 087331
	Esys_Finalize(&ctx;;
Packit Service 087331
	if (ret != TPM2_RC_SUCCESS) {
Packit Service 087331
		ret = tpm2_set_errmsg(errmsg, "esys PCR reading failed", ret);
Packit Service 087331
		if (ret == -1)	/* the contents of errmsg is undefined */
Packit Service 087331
			*errmsg = NULL;
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	if (!pcr_selections_match(&pcr_select_in, pcr_select_out)) {
Packit Service 087331
		Esys_Free(pcr_select_out);
Packit Service 087331
		Esys_Free(pcr_digests);
Packit Service 087331
Packit Service 087331
		ret = asprintf(errmsg, "TPM returned incorrect PCRs");
Packit Service 087331
		if (ret == -1)	/* the contents of errmsg are undefined */
Packit Service 087331
			*errmsg = NULL;
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
	Esys_Free(pcr_select_out);
Packit Service 087331
Packit Service 087331
	if (pcr_digests->count != 1 || pcr_digests->digests[0].size != len) {
Packit Service 087331
		Esys_Free(pcr_digests);
Packit Service 087331
		ret = asprintf(errmsg, "TPM returned incorrect digests");
Packit Service 087331
		if (ret == -1)	/* the contents of errmsg is undefined */
Packit Service 087331
			*errmsg = NULL;
Packit Service 087331
		return -1;
Packit Service 087331
	}
Packit Service 087331
Packit Service 087331
	memcpy(hwpcr, pcr_digests->digests[0].buffer, len);
Packit Service 087331
	Esys_Free(pcr_digests);
Packit Service 087331
	return 0;
Packit Service 087331
}