Add socket connection option for using with TPM2 simulator

This is largely based on and tested against http://ibmswtpm.sourceforge.net/
pull/121/head
Elms 2020-09-21 11:37:25 -07:00
parent 913318707f
commit 63736417b2
11 changed files with 382 additions and 9 deletions

View File

@ -179,6 +179,23 @@ then
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_LINUX_DEV"
fi
# Socket TPM device Support
AC_ARG_ENABLE([socket],
[AS_HELP_STRING([--enable-socket],[Enable use of TPM through the socket driver (default: disabled)])],
[ ENABLED_SOCKET=$enableval ],
[ ENABLED_SOCKET=no ]
)
if test "x$ENABLED_SOCKET" = "xyes"
then
if test "x$ENABLED_DEVTPM" = "xyes"
then
AC_MSG_ERROR([Cannot enable both socket and devtpm])
fi
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_SOCKET"
fi
# STM ST33 Support
AC_ARG_ENABLE([st33],,
@ -318,6 +335,7 @@ AM_CONDITIONAL([BUILD_ST], [test "x$ENABLED_ST" = "xyes"])
AM_CONDITIONAL([BUILD_MICROCHIP], [test "x$ENABLED_MICROCHIP" = "xyes"])
AM_CONDITIONAL([BUILD_INFINEON], [test "x$ENABLED_INFINEON" = "xyes"])
AM_CONDITIONAL([BUILD_DEVTPM], [test "x$ENABLED_DEVTPM" = "xyes"])
AM_CONDITIONAL([BUILD_SOCKET], [test "x$ENABLED_SOCKET" = "xyes"])
AM_CONDITIONAL([BUILD_NUVOTON], [test "x$ENABLED_NUVOTON" = "xyes"])
AM_CONDITIONAL([BUILD_CHECKWAITSTATE], [test "x$ENABLED_CHECKWAITSTATE" = "xyes"])
AM_CONDITIONAL([BUILD_AUTODETECT], [test "x$ENABLED_AUTODETECT" = "xyes"])

View File

@ -13,6 +13,9 @@ src_libwolftpm_la_SOURCES = \
if BUILD_DEVTPM
src_libwolftpm_la_SOURCES += src/tpm2_linux.c
endif
if BUILD_SOCKET
src_libwolftpm_la_SOURCES += src/tpm2_socket.c
endif
src_libwolftpm_la_CFLAGS = -DBUILDING_WOLFTPM $(AM_CFLAGS)
src_libwolftpm_la_CPPFLAGS = -DBUILDING_WOLFTPM $(AM_CPPFLAGS)

View File

@ -24,6 +24,7 @@
#include <wolftpm/tpm2_packet.h>
#include <wolftpm/tpm2_tis.h>
#include <wolftpm/tpm2_linux.h>
#include <wolftpm/tpm2_socket.h>
/******************************************************************************/
/* --- Local Variables -- */
@ -169,6 +170,8 @@ static TPM_RC TPM2_SendCommandAuth(TPM2_CTX* ctx, TPM2_Packet* packet,
/* submit command and wait for response */
#ifdef WOLFTPM_LINUX_DEV
rc = (TPM_RC)TPM2_LINUX_SendCommand(ctx, cmd, cmdSz);
#elif defined(WOLFTPM_SOCKET)
rc = (TPM_RC)TPM2_SOCKET_SendCommand(ctx, cmd, cmdSz);
#else
rc = (TPM_RC)TPM2_TIS_SendCommand(ctx, cmd, cmdSz);
#endif
@ -237,10 +240,12 @@ static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
return BAD_FUNC_ARG;
/* submit command and wait for response */
#ifndef WOLFTPM_LINUX_DEV
rc = (TPM_RC)TPM2_TIS_SendCommand(ctx, packet->buf, packet->pos);
#else
#ifdef WOLFTPM_LINUX_DEV
rc = (TPM_RC)TPM2_LINUX_SendCommand(ctx, packet->buf, packet->pos);
#elif defined(WOLFTPM_SOCKET)
rc = (TPM_RC)TPM2_SOCKET_SendCommand(ctx, packet->buf, packet->pos);
#else
rc = (TPM_RC)TPM2_TIS_SendCommand(ctx, packet->buf, packet->pos);
#endif
return TPM2_Packet_Parse(rc, packet);

View File

@ -72,6 +72,7 @@ int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, byte* cmd, word16 cmdSz)
/* Wait for response to be available */
rc_poll = poll(&fds, nfds, TPM2_LINUX_DEV_POLL_TIMEOUT);
if (rc_poll > 0 && fds.revents == POLLIN) {
// TODO: could cmdSz be smaller than the response?
rspSz = read(fd, cmd, TPM2_LINUX_DEV_RSP_SIZE);
/* The caller parses the TPM_Packet for correctness */
if (rspSz >= TPM2_HEADER_SIZE) {

284
src/tpm2_socket.c 100644
View File

@ -0,0 +1,284 @@
/* tpm2_socket.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfTPM.
*
* wolfTPM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfTPM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/**
* This implements a subset of TPM TCP protocol as described in
* "TPM-Rev-2.0-Part-4-Supporting-Routines-01.38-code"
*
* This is intended for testing with a simulator such as
* http://ibmswtpm.sourceforge.net/ or
* https://github.com/stefanberger/swtpm
*/
#ifdef WOLFTPM_SOCKET
#include <wolftpm/tpm2.h>
#include <wolftpm/tpm2_socket.h>
#include <wolftpm/tpm2_packet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#ifndef TPM2_SOCKET_HOST
#define TPM2_SOCKET_HOST "localhost"
#endif
#ifndef TPM2_SOCKET_PORT
#define TPM2_SOCKET_PORT "2321"
#endif
static TPM_RC tpm_tcp_transmit(TPM2_CTX* ctx, const void* buffer, ssize_t bufSz)
{
TPM_RC rc = TPM_RC_SUCCESS;
ssize_t wrc = 0;
if (ctx == NULL || ctx->tcpCtx.fd <= 0 || buffer == NULL) {
return BAD_FUNC_ARG;
}
/* send start */
wrc = write(ctx->tcpCtx.fd, buffer, bufSz);
if (bufSz != wrc) {
rc = SOCKET_ERROR_E;
}
#ifdef WOLFTPM_DEBUG_VERBOSE
if (wrc < 0) {
printf("Failed to send the TPM command to fd %d, got errno %d ="
"%s\n", ctx->tcpCtx.fd, errno, strerror(errno));
}
#endif
return rc;
}
static TPM_RC tpm_tcp_receive(TPM2_CTX* ctx, void* buffer, size_t rxSz) {
TPM_RC rc = TPM_RC_SUCCESS;
ssize_t wrc = 0;
size_t bytes_remaining = rxSz;
char* ptr = buffer;
if (ctx == NULL || ctx->tcpCtx.fd <= 0 || buffer == NULL) {
return BAD_FUNC_ARG;
}
while (bytes_remaining > 0) {
wrc = read(ctx->tcpCtx.fd, ptr, bytes_remaining);
if (wrc <= 0) {
#ifdef DEBUG_WOLFTPM
if (wrc == 0) {
printf("Failed to read from TPM socket: EOF\n");
} else {
printf("Failed to read from TPM socket %d, got errno %d"
" = %s\n", ctx->tcpCtx.fd, errno, strerror(errno));
}
#endif
rc = SOCKET_ERROR_E;
break;
}
bytes_remaining -= wrc;
ptr += wrc;
#ifdef WOLFTPM_DEBUG_VERBOSE
printf("TPM socket received %zd waiting for %zu more\n",
wrc, bytes_remaining);
#endif
}
return rc;
}
static TPM_RC tpm_tcp_connect(TPM2_CTX* ctx, const char* host, const char* port)
{
TPM_RC rc = SOCKET_ERROR_E;
struct addrinfo hints;
struct addrinfo *result, *rp;
int s;
int fd;
if (ctx == NULL) {
return BAD_FUNC_ARG;
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
s = getaddrinfo(host, port, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (fd == -1)
continue;
if (connect(fd, rp->ai_addr, rp->ai_addrlen) == -1) {
close(fd);
} else {
break;
}
}
freeaddrinfo(result);
if (rp != NULL) {
ctx->tcpCtx.fd = fd;
rc = TPM_RC_SUCCESS;
} else {
#ifdef DEBUG_WOLFTPM
printf("Failed to connect to %s %s\n", host, port);
#endif
}
return rc;
}
static TPM_RC tpm_tcp_disconnect(TPM2_CTX* ctx)
{
TPM_RC rc = TPM_RC_SUCCESS;
uint32_t tss_cmd;
if (ctx == NULL || ctx->tcpCtx.fd <= 0) {
return BAD_FUNC_ARG;
}
/* end swtpm session */
tss_cmd = htonl(TPM_SESSION_END);
rc = tpm_tcp_transmit(ctx, &tss_cmd, sizeof(uint32_t));
#ifdef WOLFTPM_DEBUG_VERBOSE
if (rc != TPM_RC_SUCCESS) {
printf("Failed to transmit SESSION_END\n");
}
#endif
if (0 != close(ctx->tcpCtx.fd)) {
rc = SOCKET_ERROR_E;
#ifdef WOLFTPM_DEBUG_VERBOSE
printf("Failed to close fd %d, got errno %d ="
"%s\n", ctx->tcpCtx.fd, errno, strerror(errno));
#endif
}
ctx->tcpCtx.fd = -1;
return rc;
}
/* Talk to a TPM through socket */
int TPM2_SOCKET_SendCommand(TPM2_CTX* ctx, byte* cmd, word16 cmdSz)
{
int rc = TPM_RC_FAILURE;
word32 rspSz = 0;
uint32_t tss_word;
if (ctx == NULL) {
return BAD_FUNC_ARG;
}
if (ctx->tcpCtx.fd <= 0) {
rc = tpm_tcp_connect(ctx, TPM2_SOCKET_HOST, TPM2_SOCKET_PORT);
}
#ifdef WOLFTPM_DEBUG_VERBOSE
printf("Command size: %d\n", cmdSz);
TPM2_PrintBin(cmd, cmdSz);
#endif
/* send start */
tss_word = htonl(TPM_SEND_COMMAND);
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_transmit(ctx, &tss_word, sizeof(uint32_t));
}
/* locality */
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_transmit(ctx, &ctx->locality, sizeof(uint8_t));
}
/* buffer size */
tss_word = htonl(cmdSz);
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_transmit(ctx, &tss_word, sizeof(uint32_t));
}
/* Send the TPM command buffer */
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_transmit(ctx, cmd, cmdSz);
}
/* receive response */
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_receive(ctx, &tss_word, sizeof(uint32_t));
rspSz = ntohl(tss_word);
if (rspSz > cmdSz) {
#ifdef WOLFTPM_DEBUG_VERBOSE
printf("Response size(%d) larger than command buffer(%d)\n",
rspSz, cmdSz);
#endif
/* TODO: return error, for figure out way to avoid buffer overflow */
//rc = SOCKET_ERROR_E;
}
}
/* TODO: could hang as currently implemented, but is not TSS complient */
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_receive(ctx, cmd, rspSz);
}
/* receive ack */
if (rc == TPM_RC_SUCCESS) {
rc = tpm_tcp_receive(ctx, &tss_word, sizeof(uint32_t));
tss_word = ntohl(tss_word);
#ifdef WOLFTPM_DEBUG
if (tss_word != 0) {
printf("SWTPM ack %d\n", tss_word);
}
#endif
}
#ifdef WOLFTPM_DEBUG_VERBOSE
if (rspSz > 0) {
printf("Response size: %d\n", rspSz);
TPM2_PrintBin(cmd, rspSz);
}
#endif
if (ctx->tcpCtx.fd > 0) {
TPM_RC rc_disconnect = tpm_tcp_disconnect(ctx);
if (rc == TPM_RC_SUCCESS) {
rc = rc_disconnect;
}
}
return rc;
}
#endif /* WOLFTPM_SOCKET */

View File

@ -97,8 +97,8 @@ static int wolfTPM2_Init_NoDev(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
return rc;
}
#ifdef WOLFTPM_LINUX_DEV
static int wolfTPM2_Init_LinuxDev(TPM2_CTX* ctx, void* userCtx)
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SOCKET)
static int wolfTPM2_Init_NonTIS(TPM2_CTX* ctx, void* userCtx)
{
int rc;
@ -162,8 +162,8 @@ int wolfTPM2_Init(WOLFTPM2_DEV* dev, TPM2HalIoCb ioCb, void* userCtx)
XMEMSET(dev, 0, sizeof(WOLFTPM2_DEV));
#ifdef WOLFTPM_LINUX_DEV
rc = wolfTPM2_Init_LinuxDev(&dev->ctx, userCtx);
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SOCKET)
rc = wolfTPM2_Init_NonTIS(&dev->ctx, userCtx);
(void)ioCb; /* Using standard file I/O for the Linux TPM device */
#else

View File

@ -93,7 +93,7 @@ static void test_wolfTPM2_Init(void)
AssertIntNE(rc, 0);
/* Test second argument, TPM2 IO Callbacks */
rc = wolfTPM2_Init(&dev, NULL, NULL);
#ifdef WOLFTPM_LINUX_DEV
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SOCKET)
/* Custom IO Callbacks are not needed for Linux TIS driver */
AssertIntEQ(rc, 0);
#else

View File

@ -9,6 +9,7 @@ nobase_include_HEADERS+= \
wolftpm/tpm2_types.h \
wolftpm/tpm2_wrap.h \
wolftpm/tpm2_linux.h \
wolftpm/tpm2_socket.h \
wolftpm/version.h \
wolftpm/visibility.h \
wolftpm/options.h

View File

@ -1612,6 +1612,11 @@ static const BYTE TPM_20_EK_AUTH_POLICY[] = {
/* HAL IO Callbacks */
struct TPM2_CTX;
#ifdef WOLFTPM_SOCKET
struct wolfTPM_tcpContext {
int fd;
};
#endif /* WOLFTPM_SOCKET */
/* make sure advanced IO is enabled for I2C */
#ifdef WOLFTPM_I2C
@ -1635,6 +1640,9 @@ typedef int (*TPM2HalIoCb)(struct TPM2_CTX*, const BYTE* txBuf, BYTE* rxBuf,
typedef struct TPM2_CTX {
TPM2HalIoCb ioCb;
void* userCtx;
#ifdef WOLFTPM_SOCKET
struct wolfTPM_tcpContext tcpCtx;
#endif
#ifndef WOLFTPM2_NO_WOLFCRYPT
#ifndef SINGLE_THREADED
wolfSSL_Mutex hwLock;

View File

@ -0,0 +1,48 @@
/* tpm2_socket.h
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfTPM.
*
* wolfTPM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfTPM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _TPM2_SOCKET_H_
#define _TPM2_SOCKET_H_
#include <wolftpm/tpm2.h>
#ifdef __cplusplus
extern "C" {
#endif
/* copy from TpmTcpProtocol.h */
#define TPM_SIGNAL_POWER_ON 1
#define TPM_SIGNAL_POWER_OFF 2
#define TPM_SIGNAL_NV_ON 11
#define TPM_SEND_COMMAND 8
#define TPM_SESSION_END 20
#define TPM_STOP 21
/* TPM2 IO for using TPM through a Socket connection */
int TPM2_SOCKET_SendCommand(TPM2_CTX* ctx, byte* cmd, word16 cmdSz);
/* int TPM2_SOCKET_PowerOn(TPM2_CTX* ctx); */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _TPM2_SOCKET_H_ */

View File

@ -75,6 +75,7 @@ typedef int64_t INT64;
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/error-ssl.h>
#include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/ecc.h>
@ -110,12 +111,16 @@ typedef int64_t INT64;
typedef uint32_t word32;
typedef uint64_t word64;
/* Errors from wolfssl/wolfcrypt/error-crypt.h */
#define BAD_FUNC_ARG -173 /* Bad function argument provided */
#define BUFFER_E -132 /* output buffer too small or input too large */
#define NOT_COMPILED_IN -174 /* Feature not compiled in */
#define BAD_MUTEX_E -106 /* Bad mutex operation */
#define WC_TIMEOUT_E -107 /* timeout error */
/* Errors from wolfssl/error-ssl.h */
#define SOCKET_ERROR_E -308 /* error state on socket */
#ifndef WOLFTPM_CUSTOM_TYPES
#define XMEMCPY(d,s,l) memcpy((d),(s),(l))
#define XMEMSET(b,c,l) memset((b),(c),(l))
@ -265,7 +270,7 @@ typedef int64_t INT64;
#endif
#ifndef TPM_TIMEOUT_TRIES
#ifdef WOLFTPM_LINUX_DEV
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SOCKET)
#define TPM_TIMEOUT_TRIES 0
#else
#define TPM_TIMEOUT_TRIES 1000000