diff mbox series

[3/5] ima-evm-utils: Change tpm2_pcr_read() to use C code

Message ID 76ae7cf8-d955-2001-f8dd-67fd7737c5c6@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series Updates to use IBM TSS C API rather than command line tools | expand

Commit Message

Ken Goldman Oct. 9, 2020, 3:51 p.m. UTC
Replace the call out to the command line tools with C functions.

The algorithm_string_to_algid() function supports only the digest
algorithms in use.  The table has place holders for other algorithms as
they are needed and the C strings are defined.

The table can also be used for an algorithm ID to string function if
it's ever needed.

When using the IBM TSS, link in its library.

Signed-off-by: Ken Goldman <kgoldman@us.ibm.com>
---
  src/Makefile.am      |   1 +
  src/pcr_tsspcrread.c | 156 +++++++++++++++++++++++++++++++++----------
  2 files changed, 123 insertions(+), 34 deletions(-)
diff mbox series

Patch

diff --git a/src/Makefile.am b/src/Makefile.am
index d6c779f..bf18caf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,6 +26,7 @@  if USE_PCRTSS
  evmctl_SOURCES += pcr_tss.c
  else
  evmctl_SOURCES += pcr_tsspcrread.c
+evmctl_LDADD += -libmtss
  endif

  AM_CPPFLAGS = -I$(top_srcdir) -include config.h
diff --git a/src/pcr_tsspcrread.c b/src/pcr_tsspcrread.c
index 118c7d2..eae68b7 100644
--- a/src/pcr_tsspcrread.c
+++ b/src/pcr_tsspcrread.c
@@ -50,6 +50,10 @@ 
  #include "utils.h"
  #include "imaevm.h"

+#define TPM_POSIX	/* use Posix, not Windows constructs in TSS */
+#undef MAX_DIGEST_SIZE	/* imaevm uses a different value than the TSS */
+#include <ibmtss/tss.h>
+
  #define CMD "tsspcrread"

  static char path[PATH_MAX];
@@ -68,44 +72,128 @@  int tpm2_pcr_supported(void)
  	return 1;
  }

-int tpm2_pcr_read(const char *algo_name, uint32_t pcrHandle, uint8_t *hwpcr,
-		 int len, char **errmsg)
-{
-	FILE *fp;
-	char pcr[100];	/* may contain an error */
-	char cmd[PATH_MAX + 50];
-	int ret;
-
-	sprintf(cmd, "%s -halg %s -ha %d -ns 2> /dev/null",
-		path, algo_name, pcrHandle);
-	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;
-	}
+/* Table mapping C strings to TCG algorithm identifiers */
+
+typedef struct tdAlgorithm_Map {
+    const char *algorithm_string;
+    TPMI_ALG_HASH algid;
+} Algorithm_Map;

-	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;
+Algorithm_Map algorithm_map[] = {
+				 { "sha1", TPM_ALG_SHA1},
+				 { "sha256", TPM_ALG_SHA256},
+#if 0	/* uncomment as these digest algorithms are supported */
+				 { "", TPM_ALG_SHA384},
+				 { "", TPM_ALG_SHA512},
+				 { "", TPM_ALG_SM3_256},
+				 { "", TPM_ALG_SHA3_256},
+				 { "", TPM_ALG_SHA3_384},
+				 { "", TPM_ALG_SHA3_512},
+#endif
+};
+
+/* algorithm_string_to_algid() converts a digest algorithm from a C string to a TCG algorithm
+   identifier as defined in the TCG Algorithm Regisrty..
+
+   Returns TPM_ALG_ERROR if the string has an unsupported value.
+*/
+
+static TPMI_ALG_HASH algorithm_string_to_algid(const char *algorithm_string)
+{
+    size_t 	i;
+    for (i=0 ; i < sizeof(algorithm_map)/sizeof(Algorithm_Map) ; i++) {
+	if (strcmp(algorithm_string, algorithm_map[i].algorithm_string) == 0) {
+	    return algorithm_map[i].algid; /* if match */
  	}
+    }
+    return TPM_ALG_ERROR;
+}

-	/* get the popen "cmd" return code */
-	ret = pclose(fp);
+/* tpm2_pcr_read() reads the PCR

-	/* Treat an unallocated bank as an error */
-	if (!ret && (strlen(pcr) < SHA_DIGEST_LENGTH))
-		ret = -1;
+   algo_name is the PCR digest algorithm (the PCR bank) as a C string
+   pcrHandle is the PCR number to read
+   hwpcr is a buffer for the PCR output in binary
+   len is the allocated size of hwpcr and should match the digest algorithm
+*/

-	if (!ret)
-		hex2bin(hwpcr, pcr, len);
-	else
-		*errmsg = strndup(pcr, strlen(pcr) - 1); /* remove newline */
+int tpm2_pcr_read(const char *algo_name, uint32_t pcrHandle, uint8_t *hwpcr,
+		 int len, char **errmsg)
+{
+        int 			ret = 0;	/* function return code */
+	TPM_RC			rc = 0;		/* TCG return code */
+	PCR_Read_In 		pcrReadIn;	/* command input */
+	PCR_Read_Out 		pcrReadOut;	/* response output */
+	TSS_CONTEXT		*tssContext = NULL;
+	TPMI_ALG_HASH 		alg_id;		/* PCR algorithm */

-	return ret;
+	if (rc == 0) {		/* map algorithm string to TCG value */
+	    alg_id = algorithm_string_to_algid(algo_name);
+	    if (alg_id == TPM_ALG_ERROR) {
+		ret = asprintf(errmsg, "tpm2_pcr_read: unknown algorithm %s", algo_name);
+		if (ret == -1) {	/* the contents of errmsg is undefined */
+		    *errmsg = NULL;
+		}
+		rc = 1;
+	    }
+	}
+	if (rc == 0) {
+	    rc = TSS_Create(&tssContext);
+	}
+	/* call TSS to execute the command */
+	if (rc == 0) {
+	    pcrReadIn.pcrSelectionIn.count = 1;
+	    pcrReadIn.pcrSelectionIn.pcrSelections[0].hash = alg_id;
+	    pcrReadIn.pcrSelectionIn.pcrSelections[0].sizeofSelect = 3;
+	    pcrReadIn.pcrSelectionIn.pcrSelections[0].pcrSelect[0] = 0;
+	    pcrReadIn.pcrSelectionIn.pcrSelections[0].pcrSelect[1] = 0;
+	    pcrReadIn.pcrSelectionIn.pcrSelections[0].pcrSelect[2] = 0;
+	    pcrReadIn.pcrSelectionIn.pcrSelections[0].pcrSelect[pcrHandle / 8] =
+		1 << (pcrHandle % 8);
+	    rc = TSS_Execute(tssContext,
+			     (RESPONSE_PARAMETERS *)&pcrReadOut,
+			     (COMMAND_PARAMETERS *)&pcrReadIn,
+			     NULL,
+			     TPM_CC_PCR_Read,
+			     TPM_RH_NULL, NULL, 0);
+	}
+	if (rc == 0) {
+	    /* nothing read, bank missing */
+	    if (pcrReadOut.pcrValues.count == 0) {
+		ret = asprintf(errmsg, "tpm2_pcr_read: returned count 0 for %s", algo_name);
+		if (ret == -1) {	/* the contents of errmsg is undefined */
+		    *errmsg = NULL;
+		}
+		rc = 1;
+	    }
+	    /* len parameter did not match the digest algorithm */
+	    else if (pcrReadOut.pcrValues.digests[0].t.size != len) {
+		ret = asprintf(errmsg,
+			       "tpm2_pcr_read: expected length %d actual %u for %s",
+			       len, pcrReadOut.pcrValues.digests[0].t.size, algo_name);
+		if (ret == -1) {	/* the contents of errmsg is undefined */
+		    *errmsg = NULL;
+		}
+		rc = 1;
+	    }
+	    else {
+		memcpy(hwpcr,
+		       pcrReadOut.pcrValues.digests[0].t.buffer,
+		       pcrReadOut.pcrValues.digests[0].t.size);
+	    }
+	}
+	{
+	    TPM_RC rc1 = TSS_Delete(tssContext);
+	    if (rc == 0) {
+		rc = rc1;
+	    }
+	}
+	/* map TCG return code to function return code */
+	if (rc == 0) {
+	    return 0;
+	}
+	else {
+	    return -1;
+	}
  }
+