mirror of
https://git.code.sf.net/p/linux-ima/ima-evm-utils
synced 2025-04-28 06:33:36 +02:00
ima-evm-utils: Add support for Intel TSS2 for PCR reading
This patch makes it possible to use the Intel TSS2 for getting PCR values from the SHA1/SHA256 banks on a TPM2. It is somewhat naive as it doesn't use the multi-PCR selection that TSS2 is capable of, that is for a future patch. Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org> [zohar@linux.ibm.com: added missing "stdint.h" in pcr_tsspcrread.c] Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
This commit is contained in:
parent
e532fb65fd
commit
03f99ea6d0
@ -34,6 +34,11 @@ AC_CHECK_PROG(TSSPCRREAD, [tsspcrread], yes, no)
|
|||||||
if test "x$TSSPCRREAD" = "xyes"; then
|
if test "x$TSSPCRREAD" = "xyes"; then
|
||||||
AC_DEFINE(HAVE_TSSPCRREAD, 1, [Define to 1 if you have tsspcrread binary installed])
|
AC_DEFINE(HAVE_TSSPCRREAD, 1, [Define to 1 if you have tsspcrread binary installed])
|
||||||
fi
|
fi
|
||||||
|
AM_CONDITIONAL([USE_PCRTSSPCRREAD], [test "x$TSSPCRREAD" = "xyes"])
|
||||||
|
|
||||||
|
AC_CHECK_LIB([tss2-esys], [Esys_PCR_Read])
|
||||||
|
AC_CHECK_LIB([tss2-rc], [Tss2_RC_Decode])
|
||||||
|
AM_CONDITIONAL([USE_PCRTSS], [test "x$ac_cv_lib_tss2_esys_Esys_PCR_Read" = "xyes"])
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/xattr.h, , [AC_MSG_ERROR([sys/xattr.h header not found. You need the c-library development package.])])
|
AC_CHECK_HEADERS(sys/xattr.h, , [AC_MSG_ERROR([sys/xattr.h header not found. You need the c-library development package.])])
|
||||||
AC_CHECK_HEADERS(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])])
|
AC_CHECK_HEADERS(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])])
|
||||||
@ -78,4 +83,6 @@ echo "Configuration:"
|
|||||||
echo " debug: $pkg_cv_enable_debug"
|
echo " debug: $pkg_cv_enable_debug"
|
||||||
echo " openssl-conf: $enable_openssl_conf"
|
echo " openssl-conf: $enable_openssl_conf"
|
||||||
echo " tsspcrread: $TSSPCRREAD"
|
echo " tsspcrread: $TSSPCRREAD"
|
||||||
|
echo " tss2-esys: $ac_cv_lib_tss2_esys_Esys_PCR_Read"
|
||||||
|
echo " tss2-rc-decode: $ac_cv_lib_tss2_rc_Tss2_RC_Decode"
|
||||||
echo
|
echo
|
||||||
|
@ -17,11 +17,21 @@ hash_info.h: Makefile
|
|||||||
|
|
||||||
bin_PROGRAMS = evmctl
|
bin_PROGRAMS = evmctl
|
||||||
|
|
||||||
evmctl_SOURCES = evmctl.c
|
evmctl_SOURCES = evmctl.c utils.c
|
||||||
evmctl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCRYPTO_CFLAGS)
|
evmctl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCRYPTO_CFLAGS)
|
||||||
evmctl_LDFLAGS = $(LDFLAGS_READLINE)
|
evmctl_LDFLAGS = $(LDFLAGS_READLINE)
|
||||||
evmctl_LDADD = $(LIBCRYPTO_LIBS) -lkeyutils libimaevm.la
|
evmctl_LDADD = $(LIBCRYPTO_LIBS) -lkeyutils libimaevm.la
|
||||||
|
|
||||||
|
if USE_PCRTSS
|
||||||
|
evmctl_SOURCES += pcr_tss.c
|
||||||
|
else
|
||||||
|
if USE_PCRTSSPCRREAD
|
||||||
|
evmctl_SOURCES += pcr_tsspcrread.c
|
||||||
|
else
|
||||||
|
evmctl_SOURCES += pcr_none.c
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir) -include config.h
|
AM_CPPFLAGS = -I$(top_srcdir) -include config.h
|
||||||
|
|
||||||
CLEANFILES = hash_info.h
|
CLEANFILES = hash_info.h
|
||||||
|
85
src/evmctl.c
85
src/evmctl.c
@ -64,6 +64,8 @@
|
|||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
#include "hash_info.h"
|
#include "hash_info.h"
|
||||||
|
#include "pcr.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#ifndef XATTR_APPAARMOR_SUFFIX
|
#ifndef XATTR_APPAARMOR_SUFFIX
|
||||||
#define XATTR_APPARMOR_SUFFIX "apparmor"
|
#define XATTR_APPARMOR_SUFFIX "apparmor"
|
||||||
@ -230,35 +232,6 @@ static int find_xattr(const char *list, int list_size, const char *xattr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hex_to_bin(char ch)
|
|
||||||
{
|
|
||||||
if ((ch >= '0') && (ch <= '9'))
|
|
||||||
return ch - '0';
|
|
||||||
ch = tolower(ch);
|
|
||||||
if ((ch >= 'a') && (ch <= 'f'))
|
|
||||||
return ch - 'a' + 10;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hex2bin(void *dst, const char *src, size_t count)
|
|
||||||
{
|
|
||||||
int hi, lo;
|
|
||||||
|
|
||||||
while (count--) {
|
|
||||||
if (*src == ' ')
|
|
||||||
src++;
|
|
||||||
|
|
||||||
hi = hex_to_bin(*src++);
|
|
||||||
lo = hex_to_bin(*src++);
|
|
||||||
|
|
||||||
if ((hi < 0) || (lo < 0))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
*(uint8_t *)dst++ = (hi << 4) | lo;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
|
#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
|
||||||
#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
|
#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
|
||||||
|
|
||||||
@ -1422,58 +1395,6 @@ static int tpm_pcr_read(int idx, uint8_t *pcr, int len)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_TSSPCRREAD
|
|
||||||
static int tpm2_pcrread = 1;
|
|
||||||
static int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
|
|
||||||
int len, char **errmsg)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char pcr[100]; /* may contain an error */
|
|
||||||
char cmd[50];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
sprintf(cmd, "tsspcrread -halg %s -ha %d -ns 2> /dev/null",
|
|
||||||
algo_name, idx);
|
|
||||||
fp = popen(cmd, "r");
|
|
||||||
if (!fp) {
|
|
||||||
ret = asprintf(errmsg, "popen failed: %s", strerror(errno));
|
|
||||||
if (ret == -1) /* the contents of errmsg is undefined */
|
|
||||||
*errmsg = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fgets(pcr, sizeof(pcr), fp) == NULL) {
|
|
||||||
ret = asprintf(errmsg, "tsspcrread failed: %s",
|
|
||||||
strerror(errno));
|
|
||||||
if (ret == -1) /* the contents of errmsg is undefined */
|
|
||||||
*errmsg = NULL;
|
|
||||||
ret = pclose(fp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the popen "cmd" return code */
|
|
||||||
ret = pclose(fp);
|
|
||||||
|
|
||||||
/* Treat an unallocated bank as an error */
|
|
||||||
if (!ret && (strlen(pcr) < SHA_DIGEST_LENGTH))
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
hex2bin(hwpcr, pcr, len);
|
|
||||||
else
|
|
||||||
*errmsg = strndup(pcr, strlen(pcr) - 1); /* remove newline */
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static int tpm2_pcrread = 0;
|
|
||||||
static int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
|
|
||||||
int len, char **errmsg)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TCG_EVENT_NAME_LEN_MAX 255
|
#define TCG_EVENT_NAME_LEN_MAX 255
|
||||||
|
|
||||||
struct template_entry {
|
struct template_entry {
|
||||||
@ -1866,7 +1787,7 @@ static int read_tpm_banks(int num_banks, struct tpm_bank_info *bank)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Any userspace applications available for reading TPM 2.0 PCRs? */
|
/* Any userspace applications available for reading TPM 2.0 PCRs? */
|
||||||
if (!tpm2_pcrread) {
|
if (!tpm2_pcr_supported()) {
|
||||||
log_debug("Failed to read TPM 2.0 PCRs\n");
|
log_debug("Failed to read TPM 2.0 PCRs\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
3
src/pcr.h
Normal file
3
src/pcr.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
int tpm2_pcr_supported(void);
|
||||||
|
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
|
||||||
|
int len, char **errmsg);
|
52
src/pcr_none.c
Normal file
52
src/pcr_none.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* ima-evm-utils - IMA/EVM support utilities
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Nokia Corporation
|
||||||
|
* Copyright (C) 2011,2012,2013 Intel Corporation
|
||||||
|
* Copyright (C) 2013,2014 Samsung Electronics
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
|
||||||
|
* <dmitry.kasatkin@intel.com>
|
||||||
|
* <d.kasatkin@samsung.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, the copyright holders give permission to link the
|
||||||
|
* code of portions of this program with the OpenSSL library under certain
|
||||||
|
* conditions as described in each individual source file and distribute
|
||||||
|
* linked combinations including the program with the OpenSSL library. You
|
||||||
|
* must comply with the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than as permitted herein. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you do not
|
||||||
|
* wish to do so, delete this exception statement from your version. If you
|
||||||
|
* delete this exception statement from all source files in the program,
|
||||||
|
* then also delete it in the license file.
|
||||||
|
*
|
||||||
|
* File: pcr_none.c
|
||||||
|
* PCR reading implementation that always fails
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int tpm2_pcr_supported(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
|
||||||
|
int len, char **errmsg)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
178
src/pcr_tss.c
Normal file
178
src/pcr_tss.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* ima-evm-utils - IMA/EVM support utilities
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Nokia Corporation
|
||||||
|
* Copyright (C) 2011,2012,2013 Intel Corporation
|
||||||
|
* Copyright (C) 2013,2014 Samsung Electronics
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
|
||||||
|
* <dmitry.kasatkin@intel.com>
|
||||||
|
* <d.kasatkin@samsung.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, the copyright holders give permission to link the
|
||||||
|
* code of portions of this program with the OpenSSL library under certain
|
||||||
|
* conditions as described in each individual source file and distribute
|
||||||
|
* linked combinations including the program with the OpenSSL library. You
|
||||||
|
* must comply with the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than as permitted herein. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you do not
|
||||||
|
* wish to do so, delete this exception statement from your version. If you
|
||||||
|
* delete this exception statement from all source files in the program,
|
||||||
|
* then also delete it in the license file.
|
||||||
|
*
|
||||||
|
* File: pcr_tss.c
|
||||||
|
* PCR reading implementation based on Intel TSS2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTSS2_ESYS
|
||||||
|
#include <tss2/tss2_esys.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTSS2_RC
|
||||||
|
#include <tss2/tss2_rc.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int tpm2_pcr_supported(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pcr_selections_match(TPML_PCR_SELECTION *a, TPML_PCR_SELECTION *b)
|
||||||
|
{
|
||||||
|
if (a->count != b->count)
|
||||||
|
return 0;
|
||||||
|
for (int i = 0; i < a->count; i++) {
|
||||||
|
if (a->pcrSelections[i].hash != b->pcrSelections[i].hash)
|
||||||
|
return 0;
|
||||||
|
if (a->pcrSelections[i].sizeofSelect != b->pcrSelections[i].sizeofSelect)
|
||||||
|
return 0;
|
||||||
|
for (int j = 0; j < a->pcrSelections[i].sizeofSelect; j++) {
|
||||||
|
if (a->pcrSelections[i].pcrSelect[j] != b->pcrSelections[i].pcrSelect[j])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int tpm2_set_errmsg(char **errmsg, const char *message, TSS2_RC ret)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LIBTSS2_RC
|
||||||
|
return asprintf(errmsg, "%s: %s", message, Tss2_RC_Decode(ret));
|
||||||
|
#else
|
||||||
|
return asprintf(errmsg, "%s: #%d", message, ret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static TPM2_ALG_ID algo_to_tss2(const char *algo_name)
|
||||||
|
{
|
||||||
|
if (!strcmp(algo_name, "sha1"))
|
||||||
|
return TPM2_ALG_SHA1;
|
||||||
|
else if (!strcmp(algo_name, "sha256"))
|
||||||
|
return TPM2_ALG_SHA256;
|
||||||
|
|
||||||
|
return TPM2_ALG_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
|
||||||
|
int len, char **errmsg)
|
||||||
|
{
|
||||||
|
TSS2_ABI_VERSION abi_version = {
|
||||||
|
.tssCreator = 1,
|
||||||
|
.tssFamily = 2,
|
||||||
|
.tssLevel = 1,
|
||||||
|
.tssVersion = 108,
|
||||||
|
};
|
||||||
|
ESYS_CONTEXT *ctx = NULL;
|
||||||
|
TSS2_RC ret = 0;
|
||||||
|
TPML_PCR_SELECTION *pcr_select_out;
|
||||||
|
TPML_DIGEST *pcr_digests;
|
||||||
|
UINT32 pcr_update_counter;
|
||||||
|
|
||||||
|
TPM2_ALG_ID algid = algo_to_tss2(algo_name);
|
||||||
|
if (algid == TPM2_ALG_ERROR) {
|
||||||
|
ret = asprintf(errmsg, "unsupported tss2 algorithm");
|
||||||
|
if (ret == -1) /* the contents of errmsg are undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TPML_PCR_SELECTION pcr_select_in = {
|
||||||
|
.count = 1,
|
||||||
|
.pcrSelections = {
|
||||||
|
{
|
||||||
|
.hash = algid,
|
||||||
|
.sizeofSelect = 3,
|
||||||
|
.pcrSelect = { 0x00, 0x00, 0x00 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pcr_select_in.pcrSelections[0].pcrSelect[idx / 8] = (1 << (idx % 8));
|
||||||
|
|
||||||
|
ret = Esys_Initialize(&ctx, NULL, &abi_version);
|
||||||
|
if (ret != TPM2_RC_SUCCESS) {
|
||||||
|
ret = tpm2_set_errmsg(errmsg, "esys initialize failed", ret);
|
||||||
|
if (ret == -1) /* the contents of errmsg are undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = Esys_PCR_Read(ctx,
|
||||||
|
ESYS_TR_NONE,
|
||||||
|
ESYS_TR_NONE,
|
||||||
|
ESYS_TR_NONE,
|
||||||
|
&pcr_select_in,
|
||||||
|
&pcr_update_counter,
|
||||||
|
&pcr_select_out,
|
||||||
|
&pcr_digests);
|
||||||
|
Esys_Finalize(&ctx);
|
||||||
|
if (ret != TPM2_RC_SUCCESS) {
|
||||||
|
ret = tpm2_set_errmsg(errmsg, "esys PCR reading failed", ret);
|
||||||
|
if (ret == -1) /* the contents of errmsg is undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pcr_selections_match(&pcr_select_in, pcr_select_out)) {
|
||||||
|
Esys_Free(pcr_select_out);
|
||||||
|
Esys_Free(pcr_digests);
|
||||||
|
|
||||||
|
ret = asprintf(errmsg, "TPM returned incorrect PCRs");
|
||||||
|
if (ret == -1) /* the contents of errmsg are undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Esys_Free(pcr_select_out);
|
||||||
|
|
||||||
|
if (pcr_digests->count != 1 || pcr_digests->digests[0].size != len) {
|
||||||
|
Esys_Free(pcr_digests);
|
||||||
|
ret = asprintf(errmsg, "TPM returned incorrect digests");
|
||||||
|
if (ret == -1) /* the contents of errmsg is undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(hwpcr, pcr_digests->digests[0].buffer, len);
|
||||||
|
Esys_Free(pcr_digests);
|
||||||
|
return 0;
|
||||||
|
}
|
95
src/pcr_tsspcrread.c
Normal file
95
src/pcr_tsspcrread.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* ima-evm-utils - IMA/EVM support utilities
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Nokia Corporation
|
||||||
|
* Copyright (C) 2011,2012,2013 Intel Corporation
|
||||||
|
* Copyright (C) 2013,2014 Samsung Electronics
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
|
||||||
|
* <dmitry.kasatkin@intel.com>
|
||||||
|
* <d.kasatkin@samsung.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, the copyright holders give permission to link the
|
||||||
|
* code of portions of this program with the OpenSSL library under certain
|
||||||
|
* conditions as described in each individual source file and distribute
|
||||||
|
* linked combinations including the program with the OpenSSL library. You
|
||||||
|
* must comply with the GNU General Public License in all respects
|
||||||
|
* for all of the code used other than as permitted herein. If you modify
|
||||||
|
* file(s) with this exception, you may extend this exception to your
|
||||||
|
* version of the file(s), but you are not obligated to do so. If you do not
|
||||||
|
* wish to do so, delete this exception statement from your version. If you
|
||||||
|
* delete this exception statement from all source files in the program,
|
||||||
|
* then also delete it in the license file.
|
||||||
|
*
|
||||||
|
* File: pcr_tsspcrread.c
|
||||||
|
* PCR reading implementation based on IBM TSS2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int tpm2_pcr_supported(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tpm2_pcr_read(const char *algo_name, int idx, uint8_t *hwpcr,
|
||||||
|
int len, char **errmsg)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char pcr[100]; /* may contain an error */
|
||||||
|
char cmd[50];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sprintf(cmd, "tsspcrread -halg %s -ha %d -ns 2> /dev/null",
|
||||||
|
algo_name, idx);
|
||||||
|
fp = popen(cmd, "r");
|
||||||
|
if (!fp) {
|
||||||
|
ret = asprintf(errmsg, "popen failed: %s", strerror(errno));
|
||||||
|
if (ret == -1) /* the contents of errmsg is undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fgets(pcr, sizeof(pcr), fp) == NULL) {
|
||||||
|
ret = asprintf(errmsg, "tsspcrread failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
if (ret == -1) /* the contents of errmsg is undefined */
|
||||||
|
*errmsg = NULL;
|
||||||
|
ret = pclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the popen "cmd" return code */
|
||||||
|
ret = pclose(fp);
|
||||||
|
|
||||||
|
/* Treat an unallocated bank as an error */
|
||||||
|
if (!ret && (strlen(pcr) < SHA_DIGEST_LENGTH))
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
hex2bin(hwpcr, pcr, len);
|
||||||
|
else
|
||||||
|
*errmsg = strndup(pcr, strlen(pcr) - 1); /* remove newline */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
32
src/utils.c
Normal file
32
src/utils.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int hex_to_bin(char ch)
|
||||||
|
{
|
||||||
|
if ((ch >= '0') && (ch <= '9'))
|
||||||
|
return ch - '0';
|
||||||
|
ch = tolower(ch);
|
||||||
|
if ((ch >= 'a') && (ch <= 'f'))
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hex2bin(void *dst, const char *src, size_t count)
|
||||||
|
{
|
||||||
|
int hi, lo;
|
||||||
|
|
||||||
|
while (count--) {
|
||||||
|
if (*src == ' ')
|
||||||
|
src++;
|
||||||
|
|
||||||
|
hi = hex_to_bin(*src++);
|
||||||
|
lo = hex_to_bin(*src++);
|
||||||
|
|
||||||
|
if ((hi < 0) || (lo < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*(uint8_t *)dst++ = (hi << 4) | lo;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
5
src/utils.h
Normal file
5
src/utils.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
int hex_to_bin(char ch);
|
||||||
|
int hex2bin(void *dst, const char *src, size_t count);
|
Loading…
x
Reference in New Issue
Block a user