[Skiboot] [PATCH v2 04/12] libstb/tss2: add skiboot wrappers for TSS commands

Stefan Berger stefanb at linux.ibm.com
Thu Jan 23 08:00:38 AEDT 2020


On 1/19/20 9:36 PM, Eric Richter wrote:
> While the TSS does most of the heavy lifting for serialization and
> deserialization of TSS commands, there is still a little bit of legwork to
> utilize the library effectively.
>
> This patch introduces a set of functions that simplify TPM commands to a
> single function call that does not depend on any other TPM or TSS-related
> headers.
>
> Signed-off-by: Eric Richter <erichte at linux.ibm.com>
> ---
>   libstb/tss2/Makefile.inc |   2 +-
>   libstb/tss2/tssskiboot.c | 527 +++++++++++++++++++++++++++++++++++++++
>   libstb/tss2/tssskiboot.h |  62 +++++
>   3 files changed, 590 insertions(+), 1 deletion(-)
>   create mode 100644 libstb/tss2/tssskiboot.c
>   create mode 100644 libstb/tss2/tssskiboot.h
>
> diff --git a/libstb/tss2/Makefile.inc b/libstb/tss2/Makefile.inc
> index b2536faf..804ba519 100644
> --- a/libstb/tss2/Makefile.inc
> +++ b/libstb/tss2/Makefile.inc
> @@ -16,7 +16,7 @@ TSS2LIB_SRCS += Commands.c CommandAttributeData.c Unmarshal.c
>   TSS2LIB_SRCS += tssdevskiboot.c
>   
>   TSS2_SRCS = $(addprefix ibmtpm20tss/utils/,$(TSS2LIB_SRCS))
> -TSS2_SRCS += tpm2.c
> +TSS2_SRCS += tpm2.c tssskiboot.c
>   
>   #tsscryptombed.c tsscryptouv.c tssdevuv.c tssuv.c
>   #tssskiboot.c eventlog.c eventlib.c tpm_nv.c opalcreate.c
> diff --git a/libstb/tss2/tssskiboot.c b/libstb/tss2/tssskiboot.c
> new file mode 100644
> index 00000000..3888e2b6
> --- /dev/null
> +++ b/libstb/tss2/tssskiboot.c
> @@ -0,0 +1,527 @@
> +/********************************************************************************/
> +/*										*/
> +/*			 Skiboot Support Interface  				*/
> +/*										*/
> +/* (c) Copyright IBM Corporation 2019						*/
> +/*										*/
> +/* All rights reserved.								*/
> +/* 										*/
> +/* Redistribution and use in source and binary forms, with or without		*/
> +/* modification, are permitted provided that the following conditions are	*/
> +/* met:										*/
> +/* 										*/
> +/* Redistributions of source code must retain the above copyright notice,	*/
> +/* this list of conditions and the following disclaimer.			*/
> +/* 										*/
> +/* Redistributions in binary form must reproduce the above copyright		*/
> +/* notice, this list of conditions and the following disclaimer in the		*/
> +/* documentation and/or other materials provided with the distribution.		*/
> +/* 										*/
> +/* Neither the names of the IBM Corporation nor the names of its		*/
> +/* contributors may be used to endorse or promote products derived from		*/
> +/* this software without specific prior written permission.			*/
> +/* 										*/
> +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS		*/
> +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT		*/
> +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR	*/
> +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT		*/
> +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,	*/
> +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT		*/
> +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,	*/
> +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY	*/
> +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT		*/
> +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE	*/
> +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.		*/
> +/********************************************************************************/
> +
> +#ifdef __SKIBOOT__
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdint.h>
> +
> +#include <ibmtss/tss.h>
> +#include <ibmtss/tssfile.h>
> +#include <ibmtss/tssmarshal.h>
> +#include <ibmtss/tssresponsecode.h>
> +#include <ibmtss/Startup_fp.h>
> +#include <ibmtss/tssprint.h>
> +#include <tpm2.h>
> +#include "tssproperties.h"
> +#include "tssskiboot.h"
> +
> +static TSS_CONTEXT *context = NULL;
> +
> +static TPM_RC get_context(void){
> +	TPM_RC rc = TPM_RC_SUCCESS;
> +
> +	if(!context){
> +		rc = TSS_Create(&context);
> +		if(rc)
> +			return rc;
> +
> +		context->tpm_device = tpm2_get_device();
> +		context->tpm_driver = tpm2_get_driver();
> +		context->tssInterfaceType = "skiboot";
> +	}
> +
> +	return rc;
> +}
> +
> +static void traceError(const char *command, TPM_RC rc)
> +{
> +    const char *msg;


different indentation.


> +    const char *submsg;
> +    const char *num;

Empty line after variable declarations in skiboot ?


> +    printf("%s: failed, rc %08x\n", command, rc);
> +    TSS_ResponseCode_toString(&msg, &submsg, &num, rc);
> +    printf("%s%s%s\n", msg, submsg, num);
> +}
> +
> +
> +int TSS_NV_Read_Public(TPMI_RH_NV_INDEX nvIndex)
> +{
> +	TPM_RC rc;
> +
empty line?
> +        TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RH_NULL;
> +        TPMI_SH_AUTH_SESSION sessionHandle1 = TPM_RH_NULL;
> +        TPMI_SH_AUTH_SESSION sessionHandle2 = TPM_RH_NULL;
check indentation; looks like spaces here
> +        unsigned int sessionAttributes0 = 0;
> +        unsigned int sessionAttributes1 = 0;
> +        unsigned int sessionAttributes2 = 0;
> +
> +	NV_ReadPublic_In *in;
> +	NV_ReadPublic_Out *out;
> +
> +	in = zalloc(sizeof(NV_ReadPublic_In));
> +	if (!in)
> +		return -1;
> +	out = zalloc(sizeof(NV_ReadPublic_Out));
> +	if (!out) {
> +		free(in);
> +		return -1;
> +	}
> +
> +	in->nvIndex = nvIndex;
> +
> +	rc = get_context();
> +	if (rc)
> +		goto cleanup;
> +
> +	rc = TSS_Execute(context,
> +		(RESPONSE_PARAMETERS *) out,
> +		(COMMAND_PARAMETERS *) in,
> +		NULL,
> +		TPM_CC_NV_ReadPublic,
> +		sessionHandle0, NULL, sessionAttributes0,
> +		sessionHandle1, NULL, sessionAttributes1,
> +		sessionHandle2, NULL, sessionAttributes2,
> +		TPM_RH_NULL, NULL, 0);
> +
> +cleanup:
> +	free(in);
> +	free(out);
> +
> +	return rc;
> +}
> +
> +
> +int TSS_NV_Read(uint32_t nvIndex, void *buf, size_t bufsize, uint64_t off)
> +{
> +	int rc;
> +
> +        TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
> +        TPMI_SH_AUTH_SESSION sessionHandle1 = TPM_RH_NULL;
> +        TPMI_SH_AUTH_SESSION sessionHandle2 = TPM_RH_NULL;
> +        unsigned int sessionAttributes0 = 0;
> +        unsigned int sessionAttributes1 = 0;
> +        unsigned int sessionAttributes2 = 0;
also indentation here and in next function
> +
> +	NV_Read_In *in;
> +	NV_Read_Out *out;
> +
> +	in = zalloc(sizeof(NV_Read_In));
> +	if (!in)
> +		return -1;
> +	out = zalloc(sizeof(NV_Read_Out));
> +	if (!out) {
> +		free(in);
> +		return -1;
> +	}
> +
> +	in->nvIndex = nvIndex;
> +	in->offset = off;
> +	in->size = bufsize;
> +	in->authHandle = nvIndex;
> +
> +	rc = get_context();
> +	if (rc)
> +		goto cleanup;
> +
> +	// TODO: Wrap this in multiple reads based on NV Buffer Max (1024)
> +	// TODO: Maybe use getcap to make sure.
> +	rc = TSS_Execute(context,
> +		(RESPONSE_PARAMETERS *) out,
> +		(COMMAND_PARAMETERS *) in,
> +		NULL,
> +		TPM_CC_NV_Read,
> +		sessionHandle0, NULL, sessionAttributes0,
> +		sessionHandle1, NULL, sessionAttributes1,
> +		sessionHandle2, NULL, sessionAttributes2,
> +		TPM_RH_NULL, NULL, 0);
> +
> +	if (!rc) {
> +		if (out->data.b.size < bufsize)
> +			bufsize = out->data.b.size;
> +		memcpy(buf, out->data.b.buffer, bufsize);
> +	}
> +
> +	if(rc)
> +		traceError("TSS_NV_Read", rc);
> +
> +cleanup:
> +	free(in);
> +	free(out);
> +
> +	return rc;
> +
> +
empty lines?
> +}
> +
> +
> +int TSS_NV_Write(uint32_t nvIndex, void *buf, size_t bufsize, uint64_t off)
> +{
> +	int rc;
> +
> +        TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
> +        TPMI_SH_AUTH_SESSION sessionHandle1 = TPM_RH_NULL;
> +        TPMI_SH_AUTH_SESSION sessionHandle2 = TPM_RH_NULL;
> +        unsigned int sessionAttributes0 = 0;
> +        unsigned int sessionAttributes1 = 0;
> +        unsigned int sessionAttributes2 = 0;
> +
> +	NV_Write_In *in;
> +
> +	in = zalloc(sizeof(NV_Write_In));
> +	if (!in)
> +		return -1;
> +
> +	in->nvIndex = nvIndex;
> +	in->offset = off;
> +	in->authHandle = nvIndex;
> +
> +	rc = TSS_TPM2B_Create(&in->data.b, buf, bufsize, sizeof(in->data.t.buffer));
> +	if (rc)
> +		goto cleanup;
> +
> +	rc = get_context();
> +	if (rc)
> +		goto cleanup;
> +
> +	// TODO: Wrap this in multiple writes based on NV Buffer Max (1024)
> +	rc = TSS_Execute(context,
> +		NULL,
> +		(COMMAND_PARAMETERS *) in,
> +		NULL,
> +		TPM_CC_NV_Write,
> +		sessionHandle0, NULL, sessionAttributes0,
> +		sessionHandle1, NULL, sessionAttributes1,
> +		sessionHandle2, NULL, sessionAttributes2,
> +		TPM_RH_NULL, NULL, 0);
> +
> +	if (rc)
> +		traceError("TSS_NV_Write", rc);
> +
> +cleanup:
> +	free(in);
> +
> +	return rc;
> +
> +
> +}

> +	/*
> +	 * This carries the flags set according to default settings, excepting
> +	 * for what is set by this function parameters. Further customization
> +	 * will require a different setup for nvAttribute flags as is done in
> +	 * TSS's code.
> +	 * */
> +	in->publicInfo.nvPublic.attributes = nvAttributes;
> +
> +	in->publicInfo.nvPublic.attributes.val |= setAttributes.val;
> +	in->publicInfo.nvPublic.attributes.val &= ~(clearAttributes.val);
> +
> +	in->publicInfo.nvPublic.dataSize = dataSize;
> +
> +	rc = TSS_Execute(context,
> +			 NULL,
> +			 (COMMAND_PARAMETERS *)in,
> +			 NULL,
> +			 TPM_CC_NV_DefineSpace,
> +			 sessionHandle0, parentPassword, sessionAttributes0,
> +			 sessionHandle1, NULL, sessionAttributes1,
> +			 sessionHandle2, NULL, sessionAttributes2,
> +			 TPM_RH_NULL, NULL, 0);
> +	if(rc)
> +		traceError("TSS_NV_Define_Space", rc);
> +
> +
> +cleanup:
> +	free(in);
> +	return rc? 1: 0 ;

Other functions return -1, this one returns '1' presumably on error. 
Seems inconsistent. Also below.


> +}
> +
> +/**
> + * @brief Extends a PCR using the given hashes and digest
> + * @param pcrHandle	The PCR to be extended
> + * @param hashes	A pointer to an array of hash algorithms, each one
> + * 			used to extend its respective PCR bank.
> + * @param hashes_len	The length of hashes array.
> + * @param digest	The digest data.
> + */
> +int TSS_PCR_Extend(TPMI_DH_PCR pcrHandle, TPMI_ALG_HASH *hashes,
> +		      uint8_t hashes_len, const char *digest)
> +{
> +	PCR_Extend_In *in = calloc(1, sizeof(PCR_Extend_In));
> +
> +	uint32_t rc = 1;
> +
> +	if(!in || (strlen(digest) > sizeof(TPMU_HA)) )
> +		return 1;
-1 ?
> +
> +	if(hashes_len >= HASH_COUNT)
> +		goto exit;
> +
> +	rc = get_context();
> +	if(rc)
> +		goto exit;
> +
> +	in->digests.count = hashes_len;
> +	in->pcrHandle = pcrHandle;
> +	for(int i=0; i < hashes_len; i++){
> +		in->digests.digests[i].hashAlg = hashes[i];
> +		// memset zeroes first to assure the digest data is zero padded.
> +		memset((uint8_t*) &in->digests.digests[i].digest, 0, sizeof(TPMU_HA));
> +		memcpy((uint8_t*) &in->digests.digests[i].digest, digest, strlen(digest));
> +	}
> +	rc = TSS_Execute(context,
> +			 NULL,
> +			 (COMMAND_PARAMETERS *) in,
> +			 NULL,
> +			 TPM_CC_PCR_Extend,
> +			 TPM_RS_PW, NULL, 0,
> +			 TPM_RH_NULL, NULL, 0);
> +
> +	if (rc !=  0){
> +		traceError("TSS_PCR_Extend", rc);
> +	}
> +
> +exit:
> +	free(in);
> +	return rc? 1: 0;
> +}
> +
> +/**
> + * @brief Reads the PCR content
> + * @param
> + */
> +int TSS_PCR_Read(TPMI_DH_PCR pcrHandle, TPMI_ALG_HASH *hashes,
> +		 uint8_t hashes_len)
> +{
> +	TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RH_NULL;
> +	unsigned int sessionAttributes0 = 0;
> +	PCR_Read_Out *out;
> +	PCR_Read_In *in;
> +	uint32_t rc = 1;
> +
> +	TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "2");
> +
> +	if (hashes_len >= HASH_COUNT)
> +		return 1;
> +
> +	in = calloc(1, sizeof(PCR_Read_In));
> +	if (!in)
> +		return 1;
> +
> +	out = calloc(1, sizeof(PCR_Read_Out));
> +	if (!out)
> +		goto cleanup_in;
> +
> +	rc = get_context();
> +
> +	if (rc)
> +		goto cleanup_all;
> +
> +	in->pcrSelectionIn.count = hashes_len;
> +	for( int i=0; i < hashes_len; i++){
> +		in->pcrSelectionIn.pcrSelections[i].hash = hashes[i];
> +		in->pcrSelectionIn.pcrSelections[i].sizeofSelect = 3;
> +		in->pcrSelectionIn.pcrSelections[i].pcrSelect[0] = 0;
> +		in->pcrSelectionIn.pcrSelections[i].pcrSelect[1] = 0;
> +		in->pcrSelectionIn.pcrSelections[i].pcrSelect[2] = 0;
> +		in->pcrSelectionIn.pcrSelections[i].pcrSelect[pcrHandle/8] = 1 << (pcrHandle % 8);
> +	}
> +
> +	rc = TSS_Execute(context,
> +			 (RESPONSE_PARAMETERS *) out,
> +			 (COMMAND_PARAMETERS *) in,
> +			 NULL,
> +			 TPM_CC_PCR_Read,
> +                         sessionHandle0, NULL, sessionAttributes0,
> +			 TPM_RH_NULL, NULL, 0);
> +
> +	if (rc !=  0)
> +		traceError("newTSS_PCR_Read", rc);
> +
> +
> +cleanup_all:
> +	free(out);
> +cleanup_in:
> +	free(in);
> +	return rc? 1: 0;
> +}
> +#endif /* __SKIBOOT__ */
> diff --git a/libstb/tss2/tssskiboot.h b/libstb/tss2/tssskiboot.h
> new file mode 100644
> index 00000000..b1990130
> --- /dev/null
> +++ b/libstb/tss2/tssskiboot.h
> @@ -0,0 +1,62 @@
> +/********************************************************************************/
> +/*										*/
> +/*		SKIBOOT Interface			  			*/
> +/*										*/
> +/* (c) Copyright IBM Corporation 2019.						*/
> +/*										*/
> +/* All rights reserved.								*/
> +/* 										*/
> +/* Redistribution and use in source and binary forms, with or without		*/
> +/* modification, are permitted provided that the following conditions are	*/
> +/* met:										*/
> +/* 										*/
> +/* Redistributions of source code must retain the above copyright notice,	*/
> +/* this list of conditions and the following disclaimer.			*/
> +/* 										*/
> +/* Redistributions in binary form must reproduce the above copyright		*/
> +/* notice, this list of conditions and the following disclaimer in the		*/
> +/* documentation and/or other materials provided with the distribution.		*/
> +/* 										*/
> +/* Neither the names of the IBM Corporation nor the names of its		*/
> +/* contributors may be used to endorse or promote products derived from		*/
> +/* this software without specific prior written permission.			*/
> +/* 										*/
> +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS		*/
> +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT		*/
> +/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR	*/
> +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT		*/
> +/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,	*/
> +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT		*/
> +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,	*/
> +/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY	*/
> +/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT		*/
> +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE	*/
> +/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.		*/
> +/********************************************************************************/
> +#ifdef __SKIBOOT__
> +
> +#ifndef TSSSKIBOOT_H
> +#define TSSSKIBOOT_H
> +
> +#ifndef TPM_POSIX
> +#define TPM_POSIX
> +#endif
> +
> +#include "tssproperties.h"
> +
> +int TSS_PCR_Read(TPMI_DH_PCR pcrHandle, TPMI_ALG_HASH *hashes,
> +		 uint8_t hashes_len);
> +int TSS_PCR_Extend(TPMI_DH_PCR pcrHandle, TPMI_ALG_HASH *v_hashes,
> +                   uint8_t hashes_len, const char *digest);
> +
> +int TSS_NV_Read_Public(TPMI_RH_NV_INDEX nvIndex);
> +int TSS_NV_Read(uint32_t nvIndex, void *buf, size_t bufsize, uint64_t off);
> +int TSS_NV_Write(uint32_t nvIndex, void *buf, size_t bufsize, uint64_t off);
> +int TSS_NV_WriteLock(TPMI_RH_NV_INDEX nvIndex);
> +
> +int TSS_NV_Define_Space(uint32_t nvIndex, const char hierarchy,
> +			const char hierarchy_authorization,
> +			uint16_t dataSize);
> +
> +#endif /* TSSSKIBOOT_H */
> +#endif /* __SKIBOOT__ */




More information about the Skiboot mailing list