mirror of
				https://git.code.sf.net/p/linux-ima/ima-evm-utils
				synced 2025-10-31 05:00:41 +01:00 
			
		
		
		
	Create alternative tpm2_pcr_read() that uses IBM TSS
Use the IBM TSS to implement the functions as an alternative to the command line tools. 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> [zohar@linux.ibm.com: updated configure.ac, replaced license with SPDX, added comment before TSS_Delete and modified rc1 testing.] Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
This commit is contained in:
		| @@ -30,10 +30,15 @@ AC_SUBST(KERNEL_HEADERS) | ||||
| AC_CHECK_HEADER(unistd.h) | ||||
| AC_CHECK_HEADERS(openssl/conf.h) | ||||
|  | ||||
| # Intel TSS | ||||
| AC_CHECK_LIB([tss2-esys], [Esys_Free]) | ||||
| AC_CHECK_LIB([tss2-rc], [Tss2_RC_Decode]) | ||||
| AM_CONDITIONAL([USE_PCRTSS], [test "x$ac_cv_lib_tss2_esys_Esys_Free" = "xyes"]) | ||||
|  | ||||
| # IBM TSS include files | ||||
| AC_CHECK_HEADER(ibmtss/tss.h, [], [], [[#define TPM_POSIX]]) | ||||
| AM_CONDITIONAL([USE_IBMTSS], [test "x$ac_cv_header_ibmtss_tss_h" = "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(keyutils.h, , [AC_MSG_ERROR([keyutils.h header not found. You need the libkeyutils development package.])]) | ||||
|  | ||||
| @@ -79,5 +84,6 @@ echo	"          debug: $pkg_cv_enable_debug" | ||||
| echo	"   openssl-conf: $enable_openssl_conf" | ||||
| echo	"      tss2-esys: $ac_cv_lib_tss2_esys_Esys_Free" | ||||
| echo	" tss2-rc-decode: $ac_cv_lib_tss2_rc_Tss2_RC_Decode" | ||||
| echo    "         ibmtss: $ac_cv_header_ibmtss_tss_h" | ||||
| echo	"            doc: $have_doc" | ||||
| echo | ||||
|   | ||||
| @@ -22,10 +22,21 @@ evmctl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCRYPTO_CFLAGS) | ||||
| evmctl_LDFLAGS = $(LDFLAGS_READLINE) | ||||
| evmctl_LDADD =  $(LIBCRYPTO_LIBS) -lkeyutils libimaevm.la | ||||
|  | ||||
| # USE_PCRTSS uses the Intel TSS | ||||
| if USE_PCRTSS | ||||
| evmctl_SOURCES += pcr_tss.c | ||||
|  evmctl_SOURCES += pcr_tss.c | ||||
|  | ||||
| # USE_IBMTSS uses the IBM TSS | ||||
| else | ||||
| evmctl_SOURCES += pcr_tsspcrread.c | ||||
| if USE_IBMTSS | ||||
|  evmctl_SOURCES += pcr_ibmtss.c | ||||
|  evmctl_LDADD += -libmtss | ||||
|  | ||||
| # uses the IBM TSS command line utilities | ||||
| else | ||||
|  evmctl_SOURCES += pcr_tsspcrread.c | ||||
|  | ||||
| endif | ||||
| endif | ||||
|  | ||||
| AM_CPPFLAGS = -I$(top_srcdir) -include config.h | ||||
|   | ||||
							
								
								
									
										164
									
								
								src/pcr_ibmtss.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								src/pcr_ibmtss.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * Support PCR reading implementation based on IBM TSS2 | ||||
|  * | ||||
|  * Copyright (C) 2021 IBM Ken Goldman <kgoldman@us.ibm.com> | ||||
|  */ | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #include <openssl/sha.h> | ||||
|  | ||||
| #define USE_FPRINTF | ||||
| #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]; | ||||
|  | ||||
| int tpm2_pcr_supported(void) | ||||
| { | ||||
| 	if (imaevm_params.verbose > LOG_INFO) | ||||
| 		log_info("Using %s to read PCRs.\n", CMD); | ||||
|  | ||||
| 	if (get_cmd_path(CMD, path, sizeof(path))) { | ||||
| 		log_debug("Couldn't find '%s' in $PATH\n", CMD); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	log_debug("Found '%s' in $PATH\n", CMD); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| /* Table mapping C strings to TCG algorithm identifiers */ | ||||
| typedef struct tdAlgorithm_Map { | ||||
| 	const char *algorithm_string; | ||||
| 	TPMI_ALG_HASH algid; | ||||
| } Algorithm_Map; | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * tpm2_pcr_read - read the PCR | ||||
|  * | ||||
|  * algo_name: PCR digest algorithm (the PCR bank) as a C string | ||||
|  * pcr_handle: PCR number to read | ||||
|  * hwpcr: buffer for the PCR output in binary | ||||
|  * len: allocated size of hwpcr and should match the digest algorithm | ||||
|  */ | ||||
| int tpm2_pcr_read(const char *algo_name, uint32_t pcr_handle, uint8_t *hwpcr, | ||||
| 		  int len, char **errmsg) | ||||
| { | ||||
|         int 			ret = 0;	/* function return code */ | ||||
| 	TPM_RC			rc = 0;		/* TCG return code */ | ||||
| 	TPM_RC 			rc1 = 0;	/* secondary return code */ | ||||
| 	PCR_Read_In 		pcr_read_in;	/* command input */ | ||||
| 	PCR_Read_Out 		pcr_read_out;	/* response output */ | ||||
| 	TSS_CONTEXT		*tss_context = NULL; | ||||
| 	TPMI_ALG_HASH 		alg_id;		/* PCR algorithm */ | ||||
|  | ||||
| 	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; | ||||
| 		goto end; | ||||
| 	} | ||||
|  | ||||
| 	rc = TSS_Create(&tss_context); | ||||
| 	if (rc != 0) | ||||
| 		goto end; | ||||
|  | ||||
| 	/* call TSS to execute the command */ | ||||
| 	pcr_read_in.pcrSelectionIn.count = 1; | ||||
| 	pcr_read_in.pcrSelectionIn.pcrSelections[0].hash = alg_id; | ||||
| 	pcr_read_in.pcrSelectionIn.pcrSelections[0].sizeofSelect = 3; | ||||
| 	pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[0] = 0; | ||||
| 	pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[1] = 0; | ||||
| 	pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[2] = 0; | ||||
| 	pcr_read_in.pcrSelectionIn.pcrSelections[0].pcrSelect[pcr_handle / 8] = | ||||
| 		1 << (pcr_handle % 8); | ||||
| 	rc = TSS_Execute(tss_context, | ||||
| 			 (RESPONSE_PARAMETERS *)&pcr_read_out, | ||||
| 			 (COMMAND_PARAMETERS *)&pcr_read_in, | ||||
| 			 NULL, | ||||
| 			 TPM_CC_PCR_Read, | ||||
| 			 TPM_RH_NULL, NULL, 0); | ||||
| 	if (rc != 0) | ||||
| 		goto end; | ||||
|  | ||||
| 	/* nothing read, bank missing */ | ||||
| 	if (pcr_read_out.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; | ||||
| 		goto end; | ||||
| 	} | ||||
| 	/* len parameter did not match the digest algorithm */ | ||||
| 	else if (pcr_read_out.pcrValues.digests[0].t.size != len) { | ||||
| 		ret = asprintf(errmsg, | ||||
| 			       "tpm2_pcr_read: " | ||||
| 			       "expected length %d actual %u for %s", | ||||
| 			       len, pcr_read_out.pcrValues.digests[0].t.size, | ||||
| 			       algo_name); | ||||
| 		if (ret == -1)	/* the contents of errmsg is undefined */ | ||||
| 			*errmsg = NULL; | ||||
| 		rc = 1; | ||||
| 		goto end; | ||||
| 	} else { | ||||
| 		memcpy(hwpcr, | ||||
| 		       pcr_read_out.pcrValues.digests[0].t.buffer, | ||||
| 		       pcr_read_out.pcrValues.digests[0].t.size); | ||||
| 	} | ||||
| end: | ||||
| 	/* Call delete even on errors to free context resources */ | ||||
| 	rc1 = TSS_Delete(tss_context); | ||||
|  | ||||
| 	/* map TCG return code to function return code */ | ||||
| 	if ((rc == 0) && (rc1 == 0)) | ||||
| 		return 0; | ||||
| 	else | ||||
| 		return -1; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Ken Goldman
					Ken Goldman