blob: 2eb78e3f83f43cb83515671eb151f74d1924263a [file] [log] [blame]
/***********************************************************************
* Copyright (c) 2015 - 2017 Intel Corporation
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "sapi/tpm20.h"
#include "sapi/tss2_mu.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "common/debug.h"
#include "tcti.h"
#include "tcti/tcti_device.h"
#include "logging.h"
TSS2_RC LocalTpmSendTpmCommand(
TSS2_TCTI_CONTEXT *tctiContext,
size_t command_size,
uint8_t *command_buffer
)
{
TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
TSS2_RC rval = TSS2_RC_SUCCESS;
ssize_t size;
#ifdef DEBUG
UINT32 commandCode;
UINT32 cnt;
#endif
printf_type rmPrefix;
rval = tcti_send_checks (tctiContext, command_buffer);
if (rval != TSS2_RC_SUCCESS) {
return rval;
}
if (tcti_intel->status.rmDebugPrefix == 1) {
rmPrefix = RM_PREFIX;
} else {
rmPrefix = NO_PREFIX;
}
#ifdef DEBUG
TSS2_RC rc;
size_t offset = sizeof (TPM_ST);
rc = Tss2_MU_TPM_ST_Unmarshal (command_buffer,
command_size,
&offset,
&commandCode);
rc = Tss2_MU_UINT32_Unmarshal (command_buffer,
command_size,
&offset,
&cnt);
if (tcti_intel->status.debugMsgEnabled == 1) {
TCTI_LOG (tctiContext, rmPrefix, "");
TCTI_LOG (tctiContext,
rmPrefix,
"Cmd sent: %s\n",
strTpmCommandCode (commandCode));
DEBUG_PRINT_BUFFER (rmPrefix, command_buffer, cnt);
}
#endif
size = write (tcti_intel->devFile, command_buffer, command_size);
if (size < 0) {
TCTI_LOG (tctiContext,
rmPrefix,
"send failed with error: %d\n",
errno);
return TSS2_TCTI_RC_IO_ERROR;
} else if ((size_t)size != command_size) {
return TSS2_TCTI_RC_IO_ERROR;
}
tcti_intel->previousStage = TCTI_STAGE_SEND_COMMAND;
tcti_intel->status.tagReceived = 0;
tcti_intel->status.responseSizeReceived = 0;
tcti_intel->status.protocolResponseSizeReceived = 0;
return TSS2_RC_SUCCESS;
}
TSS2_RC LocalTpmReceiveTpmResponse(
TSS2_TCTI_CONTEXT *tctiContext,
size_t *response_size,
unsigned char *response_buffer,
int32_t timeout
)
{
TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
TSS2_RC rval = TSS2_RC_SUCCESS;
ssize_t size;
unsigned int i;
printf_type rmPrefix;
rval = tcti_receive_checks (tctiContext, response_size, response_buffer);
if (rval != TSS2_RC_SUCCESS) {
goto retLocalTpmReceive;
}
if (tcti_intel->status.rmDebugPrefix == 1) {
rmPrefix = RM_PREFIX;
} else {
rmPrefix = NO_PREFIX;
}
if (tcti_intel->status.tagReceived == 0) {
size = read (tcti_intel->devFile, tcti_intel->responseBuffer, 4096);
if (size < 0) {
TCTI_LOG (tctiContext,
rmPrefix,
"read failed with error: %d\n",
errno);
rval = TSS2_TCTI_RC_IO_ERROR;
goto retLocalTpmReceive;
} else {
tcti_intel->status.tagReceived = 1;
tcti_intel->responseSize = size;
}
tcti_intel->responseSize = size;
}
if (response_buffer == NULL) {
*response_size = tcti_intel->responseSize;
goto retLocalTpmReceive;
}
if (*response_size < tcti_intel->responseSize) {
rval = TSS2_TCTI_RC_INSUFFICIENT_BUFFER;
*response_size = tcti_intel->responseSize;
goto retLocalTpmReceive;
}
*response_size = tcti_intel->responseSize;
for (i = 0; i < *response_size; i++) {
response_buffer[i] = tcti_intel->responseBuffer[i];
}
#ifdef DEBUG
if (tcti_intel->status.debugMsgEnabled == 1 &&
tcti_intel->responseSize > 0)
{
TCTI_LOG (tctiContext, rmPrefix, "\n");
TCTI_LOG (tctiContext, rmPrefix, "Response Received: ");
DEBUG_PRINT_BUFFER (rmPrefix,
response_buffer,
tcti_intel->responseSize);
}
#endif
tcti_intel->status.commandSent = 0;
retLocalTpmReceive:
if (rval == TSS2_RC_SUCCESS && response_buffer != NULL ) {
tcti_intel->previousStage = TCTI_STAGE_RECEIVE_RESPONSE;
}
return rval;
}
void LocalTpmFinalize(
TSS2_TCTI_CONTEXT *tctiContext
)
{
TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
if (tctiContext != NULL) {
close(tcti_intel->devFile);
}
}
TSS2_RC LocalTpmCancel(
TSS2_TCTI_CONTEXT *tctiContext
)
{
/* Linux driver doesn't expose a mechanism to cancel commands. */
return TSS2_TCTI_RC_NOT_IMPLEMENTED;
}
TSS2_RC LocalTpmGetPollHandles(
TSS2_TCTI_CONTEXT *tctiContext,
TSS2_TCTI_POLL_HANDLE *handles,
size_t *num_handles)
{
/* Linux driver doesn't support polling. */
return TSS2_TCTI_RC_NOT_IMPLEMENTED;
}
TSS2_RC LocalTpmSetLocality(
TSS2_TCTI_CONTEXT *tctiContext,
uint8_t locality
)
{
/*
* Linux driver doesn't expose a mechanism for user space applications
* to set locality.
*/
return TSS2_TCTI_RC_NOT_IMPLEMENTED;
}
TSS2_RC InitDeviceTcti (
TSS2_TCTI_CONTEXT *tctiContext,
size_t *contextSize,
const TCTI_DEVICE_CONF *config
)
{
TSS2_TCTI_CONTEXT_INTEL *tcti_intel = tcti_context_intel_cast (tctiContext);
TSS2_RC rval = TSS2_RC_SUCCESS;
if (tctiContext == NULL && contextSize == NULL) {
return TSS2_TCTI_RC_BAD_VALUE;
} else if (tctiContext == NULL) {
*contextSize = sizeof (TSS2_TCTI_CONTEXT_INTEL);
return TSS2_RC_SUCCESS;
}
if (config == NULL) {
return TSS2_TCTI_RC_BAD_VALUE;
}
/* Init TCTI context */
TSS2_TCTI_MAGIC (tctiContext) = TCTI_MAGIC;
TSS2_TCTI_VERSION (tctiContext) = TCTI_VERSION;
TSS2_TCTI_TRANSMIT (tctiContext) = LocalTpmSendTpmCommand;
TSS2_TCTI_RECEIVE (tctiContext) = LocalTpmReceiveTpmResponse;
TSS2_TCTI_FINALIZE (tctiContext) = LocalTpmFinalize;
TSS2_TCTI_CANCEL (tctiContext) = LocalTpmCancel;
TSS2_TCTI_GET_POLL_HANDLES (tctiContext) = LocalTpmGetPollHandles;
TSS2_TCTI_SET_LOCALITY (tctiContext) = LocalTpmSetLocality;
tcti_intel->status.locality = 3;
tcti_intel->status.commandSent = 0;
tcti_intel->status.rmDebugPrefix = 0;
tcti_intel->currentTctiContext = 0;
tcti_intel->previousStage = TCTI_STAGE_INITIALIZE;
TCTI_LOG_CALLBACK (tctiContext) = config->logCallback;
TCTI_LOG_DATA (tctiContext) = config->logData;
tcti_intel->devFile = open (config->device_path, O_RDWR);
if (tcti_intel->devFile < 0) {
return TSS2_TCTI_RC_IO_ERROR;
}
return rval;
}