blob: 5d15876540c2a4e8309b3502202f0d96382f4631 [file] [log] [blame]
/*******************************************************************************
* Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 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.
*******************************************************************************/
#include <stdlib.h>
#include "tss2_esys.h"
#include "esys_iutil.h"
#include "esys_tcti_default.h"
#define LOGMODULE esys
#include "util/log.h"
/** Initialize an ESYS_CONTEXT for further use.
*
* Initialize an ESYS_CONTEXT that holds all the state and metadata information
* during an interaction with the TPM.
* If not specified, load a TCTI in this order:
* Library libtss2-tcti-default.so (link to the preferred TCTI)
* Library libtss2-tcti-tabrmd.so (tabrmd)
* Device /dev/tpmrm0 (kernel resident resource manager)
* Device /dev/tpm0 (hardware TPM)
* TCP socket localhost:2321 (TPM simulator)
* @param esys_context [OUT] The ESYS_CONTEXT.
* @param tcti [IN] The TCTI context used to connect to the TPM (may be NULL).
* @param abiVersion [INOUT] The abi version to check and the abi version
* supported by this implementation (may be NULL).
* @retval TSS2_RC_SUCCESS on Success \todo Add error RCs.
*/
TSS2_RC
Esys_Initialize(ESYS_CONTEXT ** esys_context, TSS2_TCTI_CONTEXT * tcti,
TSS2_ABI_VERSION * abiVersion)
{
TSS2_RC rc;
size_t syssize;
_ESYS_ASSERT_NON_NULL(esys_context);
*esys_context = NULL;
/* Allocate memory for the ESYS context; after that all errors must jump to
cleanup_return instead of returning ! */
*esys_context = calloc(1, sizeof(ESYS_CONTEXT));
if (esys_context == NULL) {
LOG_ERROR("Error: During malloc.");
return TSS2_ESYS_RC_MEMORY;
}
/* Allocate memory for the SYS context */
syssize = Tss2_Sys_GetContextSize(0);
(*esys_context)->sys = malloc(syssize);
if ((*esys_context)->sys == NULL) {
LOG_ERROR("Error: During malloc.");
rc = TSS2_ESYS_RC_MEMORY;
goto cleanup_return;
}
/* Store the application provided tcti to be return on Esys_GetTcti(). */
(*esys_context)->tcti_app_param = tcti;
/* If no tcti was provided, initialize the default one. */
if (tcti == NULL) {
rc = get_tcti_default(&tcti);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR("Initialize default tcti (%x).", rc);
goto cleanup_return;
}
}
/* Initialize the ESAPI */
rc = Tss2_Sys_Initialize((*esys_context)->sys, syssize, tcti, abiVersion);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR("Error: During syscontext initialization (%x).", rc);
goto cleanup_return;
}
/* Use random number for initial esys handle value to provide pseudo
namespace for handles */
(*esys_context)->esys_handle_cnt = ESYS_TR_MIN_OBJECT + (rand() % 6000000);
return TSS2_RC_SUCCESS;
cleanup_return:
/* If we created the tcti ourselves, we must clean it up */
if ((*esys_context)->tcti_app_param == NULL && tcti != NULL) {
Tss2_Tcti_Finalize(tcti);
free(tcti);
}
/* No need to finalize (*esys_context)->sys only free since
it is the last goto in this function. */
free((*esys_context)->sys);
free(*esys_context);
*esys_context = NULL;
return rc;
}
/** Finalize an ESYS_CONTEXT
*
* After interactions with the TPM the context holding the metadata needs to be
* freed. Since additional internal memory allocations may have happened during
* use of the context, it needs to be finalized correctly.
* @param esys_context [INOUT] The ESYS_CONTEXT. (will be freed and set to NULL)
*/
void
Esys_Finalize(ESYS_CONTEXT ** esys_context)
{
TSS2_RC rc;
TSS2_TCTI_CONTEXT *tctcontext = NULL;
if (esys_context == NULL || *esys_context == NULL) {
LOG_WARNING("Finalizing NULL context.");
return;
}
/* Flush from TPM and free all resource objects first */
iesys_DeleteAllResourceObjects(*esys_context);
/* If no tcti context was provided during initialization, then wen need to
finalize the tcti context */
if ((*esys_context)->tcti_app_param == NULL) {
rc = Tss2_Sys_GetTctiContext((*esys_context)->sys, &tctcontext);
if (rc != TSS2_RC_SUCCESS) {
LOG_WARNING("Internal error in SAPI.");
} else {
tctcontext = NULL;
}
}
/* Finalize the syscontext */
Tss2_Sys_Finalize((*esys_context)->sys);
free((*esys_context)->sys);
/* If no tcti context was provided during initialization, then wen need to
finalize the tcti context */
if (tctcontext != NULL) {
Tss2_Tcti_Finalize(tctcontext);
free(tctcontext);
}
/* Free esys_context */
free(*esys_context);
*esys_context = NULL;
}
/** Return the used TCTI context.
*
* If a tcti context was passed into Esys_Initialize then this tcti context is
* return. If NULL was passed in, then NULL will be returned.
* This function is useful before Esys_Finalize to retrieve the tcti context and
* perform a clean Tss2_Tcti_Finalize.
* @param esys_context [IN] The ESYS_CONTEXT.
* @param tcti [OUT] The TCTI context used to connect to the TPM (may be NULL).
* @retval TSS2_RC_SUCCESS on Success \todo Add error RCs.
*/
TSS2_RC
Esys_GetTcti(ESYS_CONTEXT * esys_context, TSS2_TCTI_CONTEXT ** tcti)
{
_ESYS_ASSERT_NON_NULL(esys_context);
_ESYS_ASSERT_NON_NULL(tcti);
*tcti = esys_context->tcti_app_param;
return TSS2_RC_SUCCESS;
}
/** Return the poll handles of the used TCTI.
*
* The connection to the TPM is held using a TCTI. These may optionally provide
* handles that can be used to poll for incoming data. This is useful when
* using the asynchronous function of ESAPI in an event-loop model.
* @param esys_context [IN] The ESYS_CONTEXT.
* @param handles [OUT] The poll handles (callee-allocated, use free())
* @param count [OUT] The number of poll handles.
* @retval TSS2_RC_SUCCESS on Success \todo Add error RCs.
*/
TSS2_RC
Esys_GetPollHandles(ESYS_CONTEXT * esys_context,
TSS2_TCTI_POLL_HANDLE ** handles, size_t * count)
{
TSS2_RC r;
TSS2_TCTI_CONTEXT *tcti_context;
_ESYS_ASSERT_NON_NULL(esys_context);
_ESYS_ASSERT_NON_NULL(handles);
_ESYS_ASSERT_NON_NULL(count);
/* Get the tcti-context to use */
r = Tss2_Sys_GetTctiContext(esys_context->sys, &tcti_context);
if (r != TSS2_RC_SUCCESS) {
LOG_ERROR("Invalid SAPI or TCTI context.");
return r;
}
/* Allocate the memory to hold the poll handles */
r = Tss2_Tcti_GetPollHandles(tcti_context, NULL, count);
return_if_error(r, "Error getting poll handle count.");
*handles = malloc(sizeof(TSS2_TCTI_POLL_HANDLE) * (*count));
if (*handles == NULL) {
LOG_ERROR("Out of memory.");
return TSS2_ESYS_RC_MEMORY;
}
/* Retrieve the poll handles */
r = Tss2_Tcti_GetPollHandles(tcti_context, *handles, count);
return_if_error(r, "Error getting poll handles.");
return r;
}
/** Set the timeout of Esys asynchronous functions.
*
* Sets the timeout for the _finish() functions in the asynchronous versions of
* the Esys commands.
* @param esys_context [IN] The ESYS_CONTEXT.
* @param timeout [IN] The timeout in ms or -1 to block indefinately.
* @retval TSS2_RC_SUCCESS on Success \todo Add error RCs.
*/
TSS2_RC
Esys_SetTimeout(ESYS_CONTEXT * esys_context, int32_t timeout)
{
_ESYS_ASSERT_NON_NULL(esys_context);
esys_context->timeout = timeout;
return TSS2_RC_SUCCESS;
}