Skip to content

Commit

Permalink
Experimental USB TPM support using libusb and the LetsTrust TPM2Go US…
Browse files Browse the repository at this point in the history
…B-Stick.
  • Loading branch information
dgarske committed Jul 20, 2023
1 parent 5e173bc commit 63c445f
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 34 deletions.
23 changes: 23 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,27 @@ then
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_WINAPI"
fi

# libusb support for USB 2 SPI bridge such as found in LetsTrust TPM2Go USB-Stick
AC_ARG_ENABLE([usb],
[AS_HELP_STRING([--enable-usb],[Enable use of TPM through a USB2SPI bridge (default: disabled)])],
[ ENABLED_USB=$enableval ],
[ ENABLED_USB=no ]
)

if test "x$ENABLED_USB" = "xyes"
then
if test "x$ENABLED_DEVTPM" = "xyes"
then
AC_MSG_ERROR([Cannot enable both usb and devtpm])
fi

PKG_CHECK_MODULES([LIBUSB_1_0], libusb-1.0 >= 0.9.1)
AC_SUBST(LIBUSB_1_0_CFLAGS)
AC_SUBST(LIBUSB_1_0_LIBS)

AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_USB $LIBUSB_1_0_CFLAGS"
AM_LDFLAGS="$AM_LDFLAGS $LIBUSB_1_0_LIBS"
fi

# STM ST33 Support
AC_ARG_ENABLE([st33],,
Expand Down Expand Up @@ -422,6 +443,7 @@ AM_CONDITIONAL([BUILD_INFINEON], [test "x$ENABLED_INFINEON" != "xno"])
AM_CONDITIONAL([BUILD_DEVTPM], [test "x$ENABLED_DEVTPM" = "xyes"])
AM_CONDITIONAL([BUILD_SWTPM], [test "x$ENABLED_SWTPM" = "xyes"])
AM_CONDITIONAL([BUILD_WINAPI], [test "x$ENABLED_WINAPI" = "xyes"])
AM_CONDITIONAL([BUILD_USB], [test "x$ENABLED_USB" = "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"])
Expand Down Expand Up @@ -542,6 +564,7 @@ echo " * I2C: $ENABLED_I2C"
echo " * Linux kernel TPM device: $ENABLED_DEVTPM"
echo " * SWTPM: $ENABLED_SWTPM"
echo " * WINAPI: $ENABLED_WINAPI"
echo " * LetsTrust TPM2Go USB: $ENABLED_USB"
echo " * TIS/SPI Check Wait State: $ENABLED_CHECKWAITSTATE"

echo " * Infineon SLB967X $ENABLED_INFINEON"
Expand Down
5 changes: 4 additions & 1 deletion src/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ if BUILD_WINAPI
src_libwolftpm_la_SOURCES += src/tpm2_winapi.c
src_libwolftpm_la_LIBADD = -ltbs
endif
if BUILD_USB
src_libwolftpm_la_SOURCES += src/tpm2_usb.c
endif

src_libwolftpm_la_CFLAGS = $(src_libwolftpm_la_EXTRAS) -DBUILDING_WOLFTPM $(AM_CFLAGS)
src_libwolftpm_la_CPPFLAGS = -DBUILDING_WOLFTPM $(AM_CPPFLAGS)
src_libwolftpm_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFTPM_LIBRARY_VERSION}
src_libwolftpm_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFTPM_LIBRARY_VERSION}

#src_libwolftpm_la_DEPENDENCIES =
#EXTRA_DIST +=
20 changes: 10 additions & 10 deletions src/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
#include <wolftpm/tpm2.h>
#include <wolftpm/tpm2_packet.h>
#include <wolftpm/tpm2_tis.h>
#include <wolftpm/tpm2_linux.h>
#include <wolftpm/tpm2_swtpm.h>
#include <wolftpm/tpm2_winapi.h>
#include <wolftpm/tpm2_param_enc.h>

#include <hal/tpm_io.h>
Expand All @@ -40,16 +37,19 @@ static volatile int gWolfCryptRefCount = 0;
#endif

#ifdef WOLFTPM_LINUX_DEV
#define INTERNAL_SEND_COMMAND TPM2_LINUX_SendCommand
#define TPM2_INTERNAL_SENDCMD TPM2_LINUX_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx)
#elif defined(WOLFTPM_SWTPM)
#define INTERNAL_SEND_COMMAND TPM2_SWTPM_SendCommand
#define TPM2_INTERNAL_SENDCMD TPM2_SWTPM_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx)
#elif defined(WOLFTPM_WINAPI)
#define INTERNAL_SEND_COMMAND TPM2_WinApi_SendCommand
#define TPM2_INTERNAL_SENDCMD TPM2_WinApi_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_WinApi_Cleanup(ctx)
#elif defined(WOLFTPM_USB)
#define TPM2_INTERNAL_SENDCMD TPM2_USB_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_USB_Cleanup
#else
#define INTERNAL_SEND_COMMAND TPM2_TIS_SendCommand
#define TPM2_INTERNAL_SENDCMD TPM2_TIS_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx)
#endif

Expand Down Expand Up @@ -420,7 +420,7 @@ static TPM_RC TPM2_SendCommandAuth(TPM2_CTX* ctx, TPM2_Packet* packet,
packet->pos = cmdSz;

/* submit command and wait for response */
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
rc = (TPM_RC)TPM2_INTERNAL_SENDCMD(ctx, packet);
if (rc != 0)
return rc;

Expand Down Expand Up @@ -451,7 +451,7 @@ static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
return BAD_FUNC_ARG;

/* submit command and wait for response */
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
rc = (TPM_RC)TPM2_INTERNAL_SENDCMD(ctx, packet);
if (rc != 0)
return rc;

Expand Down Expand Up @@ -625,7 +625,7 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
#endif

#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
defined(WOLFTPM_WINAPI)
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_USB)
if (ioCb != NULL || userCtx != NULL) {
return BAD_FUNC_ARG;
}
Expand Down
174 changes: 174 additions & 0 deletions src/tpm2_usb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/* tpm2_usb.c
*
* Copyright (C) 2006-2023 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
*/


#ifdef WOLFTPM_USB

#include <wolftpm/tpm2_packet.h>
#include <wolftpm/tpm2_usb.h>



#define VID_CYPRESS 0x04B4u
#define PID_CYUSBSPI 0x0004u

#define CTRL_SET 0xC0u
#define CTRL_GET 0x40u

#define CY_CMD_SPI 0xCAu
#define CY_CMD_GPIO_SET 0xDBu
#define CY_SPI_WRITEREAD 0x03u

#define EP_OUT 0x01u
#define EP_IN 0x82u

#define SPI_TIMEOUT 1000
#define SPI_MAX_TRANSFER (4 + 64)

static int TPM2_USB_Init(TPM2_CTX* ctx)
{
int ret;
int nb_ifaces = 0;
libusb_device *dev = NULL;
struct libusb_config_descriptor *conf_desc = NULL;

if (ctx->usbCtx.dev_ctx != NULL) {
return 0; /* already initialized */
}

ret = libusb_init(&ctx->usbCtx.dev_ctx);
if (ret == 0) {
ctx->usbCtx.dev_handle = libusb_open_device_with_vid_pid(ctx->usbCtx.dev_ctx,
VID_CYPRESS, PID_CYUSBSPI);
if (ctx->usbCtx.dev_handle == NULL) {
ret = -1;
}
}
if (ret == 0) {
dev = libusb_get_device(ctx->usbCtx.dev_handle);
if (dev == NULL) {
ret = -1;
}
}
if (ret == 0) {
ret = libusb_get_config_descriptor(dev, 0, &conf_desc);
if (ret == 0) {
nb_ifaces = conf_desc->bNumInterfaces;
if (nb_ifaces <= 0) {
ret = -1;
}
libusb_free_config_descriptor(conf_desc);
}
}
if (ret == 0) {
ret = libusb_set_auto_detach_kernel_driver(ctx->usbCtx.dev_handle, 1);
}
if (ret == 0) {
ret = libusb_claim_interface(ctx->usbCtx.dev_handle, 0);
}

ctx->usbCtx.spi_dma_buffer = libusb_dev_mem_alloc(ctx->usbCtx.dev_handle, SPI_MAX_TRANSFER);
/* failure to allocate DMA, means we will use the buffer directly */

if (ret != 0) {
TPM2_USB_Cleanup(ctx);
}
return ret;
}


int TPM2_USB_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
{
int ret;
int act_len = 0;
int retry = 0;
int transferred = 0;
int length;
uint8_t* buffer;

ret = TPM2_USB_Init(ctx);

/* start transfer */
if (ret == 0) {
length = packet->pos;
if (ctx->usbCtx.spi_dma_buffer != NULL && length < SPI_MAX_TRANSFER) {
buffer = ctx->usbCtx.spi_dma_buffer;
XMEMCPY(buffer, packet->buf, length);
}
else {
buffer = packet->buf;
}

ret = libusb_control_transfer(ctx->usbCtx.dev_handle, CTRL_SET, CY_CMD_SPI,
CY_SPI_WRITEREAD, length, NULL, 0, SPI_TIMEOUT);

/* do send */
while (ret == 0 && transferred < length) {
ret = libusb_bulk_transfer(ctx->usbCtx.dev_handle, EP_OUT,
ctx->usbCtx.spi_dma_buffer + transferred, length, &act_len, SPI_TIMEOUT);
if (ret == 0) {
transferred += act_len;
length -= act_len;
}
}

/* do receive */
transferred = 0;
length = packet->pos;
while (ret == 0 && transferred < length) {
ret = libusb_bulk_transfer(ctx->usbCtx.dev_handle, EP_IN,
ctx->usbCtx.spi_dma_buffer + transferred, length, &act_len, SPI_TIMEOUT);
if (ret != 0) {
/* allow retry up to 5 times */
if (retry++ > 5) {
ret = -1;
break;
}
continue;
}
transferred += act_len;
length -= act_len;
}
}

return ret;
}

int TPM2_USB_Cleanup(TPM2_CTX* ctx)
{
if (ctx->usbCtx.dev_handle != NULL) {
if (ctx->usbCtx.spi_dma_buffer != NULL) {
libusb_dev_mem_free(ctx->usbCtx.dev_handle,
ctx->usbCtx.spi_dma_buffer, SPI_MAX_TRANSFER);
}

libusb_release_interface(ctx->usbCtx.dev_handle, 0);
libusb_close(ctx->usbCtx.dev_handle);
ctx->usbCtx.dev_handle = NULL;
}
if (ctx->usbCtx.dev_ctx != NULL) {
libusb_exit(ctx->usbCtx.dev_ctx);
ctx->usbCtx.dev_ctx = NULL;
}
return 0;
}

#endif /* WOLFTPM_USB */
2 changes: 1 addition & 1 deletion src/tpm2_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static int wolfTPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
return BAD_FUNC_ARG;

#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
defined(WOLFTPM_WINAPI)
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_USB)
rc = TPM2_Init_minimal(ctx);
/* Using standard file I/O for the Linux TPM device */
(void)ioCb;
Expand Down
1 change: 1 addition & 0 deletions wolftpm/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ nobase_include_HEADERS+= \
wolftpm/tpm2_linux.h \
wolftpm/tpm2_swtpm.h \
wolftpm/tpm2_winapi.h \
wolftpm/tpm2_usb.h \
wolftpm/tpm2_param_enc.h \
wolftpm/tpm2_socket.h \
wolftpm/version.h \
Expand Down
24 changes: 8 additions & 16 deletions wolftpm/tpm2.h
Original file line number Diff line number Diff line change
Expand Up @@ -1651,25 +1651,14 @@ static const BYTE TPM_20_EK_AUTH_POLICY[] = {

/* HAL IO Callbacks */
struct TPM2_CTX;
struct TPM2_Packet;

#ifdef WOLFTPM_SWTPM
struct wolfTPM_tcpContext {
int fd;
};
#endif /* WOLFTPM_SWTPM */
#include <wolftpm/tpm2_linux.h>
#include <wolftpm/tpm2_swtpm.h>
#include <wolftpm/tpm2_winapi.h>
#include <wolftpm/tpm2_usb.h>

#ifdef WOLFTPM_WINAPI
#include <tbs.h>
#include <winerror.h>

struct wolfTPM_winContext {
TBS_HCONTEXT tbs_context;
};
/* may be needed with msys */
#ifndef TPM_E_COMMAND_BLOCKED
#define TPM_E_COMMAND_BLOCKED (0x80280400)
#endif

#define WOLFTPM_IS_COMMAND_UNAVAILABLE(code) ((code) == (int)TPM_RC_COMMAND_CODE || (code) == (int)TPM_E_COMMAND_BLOCKED)
#else
#define WOLFTPM_IS_COMMAND_UNAVAILABLE(code) (code == (int)TPM_RC_COMMAND_CODE)
Expand Down Expand Up @@ -1703,6 +1692,9 @@ typedef struct TPM2_CTX {
#ifdef WOLFTPM_WINAPI
struct wolfTPM_winContext winCtx;
#endif
#ifdef WOLFTPM_USB
struct tpmUsbCtx usbCtx;
#endif
#ifndef WOLFTPM2_NO_WOLFCRYPT
#ifndef SINGLE_THREADED
wolfSSL_Mutex hwLock;
Expand Down
7 changes: 6 additions & 1 deletion wolftpm/tpm2_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@
extern "C" {
#endif

#ifdef WOLFTPM_LINUX_DEV

/* TPM2 IO for using TPM through the Linux kernel driver */
WOLFTPM_LOCAL int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet);
WOLFTPM_LOCAL int TPM2_LINUX_SendCommand(struct TPM2_CTX* ctx,
struct TPM2_Packet* packet);

#endif /* WOLFTPM_LINUX_DEV */

#ifdef __cplusplus
} /* extern "C" */
Expand Down
4 changes: 2 additions & 2 deletions wolftpm/tpm2_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ WOLFTPM_LOCAL UINT32 TPM2_Packet_SwapU32(UINT32 data);
WOLFTPM_LOCAL UINT64 TPM2_Packet_SwapU64(UINT64 data);

WOLFTPM_LOCAL void TPM2_Packet_InitBuf(TPM2_Packet* packet, byte* buf, int size);
WOLFTPM_LOCAL void TPM2_Packet_Init(TPM2_CTX* ctx, TPM2_Packet* packet);
WOLFTPM_LOCAL void TPM2_Packet_Init(struct TPM2_CTX* ctx, TPM2_Packet* packet);
WOLFTPM_LOCAL void TPM2_Packet_AppendU8(TPM2_Packet* packet, UINT8 data);
WOLFTPM_LOCAL void TPM2_Packet_ParseU8(TPM2_Packet* packet, UINT8* data);
WOLFTPM_LOCAL void TPM2_Packet_AppendU16(TPM2_Packet* packet, UINT16 data);
Expand All @@ -71,7 +71,7 @@ WOLFTPM_LOCAL void TPM2_Packet_MarkU16(TPM2_Packet* packet, int* markSz);
WOLFTPM_LOCAL int TPM2_Packet_PlaceU16(TPM2_Packet* packet, int markSz);
WOLFTPM_LOCAL void TPM2_Packet_MarkU32(TPM2_Packet* packet, int* markSz);
WOLFTPM_LOCAL void TPM2_Packet_PlaceU32(TPM2_Packet* packet, int markSz);
WOLFTPM_LOCAL int TPM2_Packet_AppendAuth(TPM2_Packet* packet, TPM2_CTX* ctx);
WOLFTPM_LOCAL int TPM2_Packet_AppendAuth(TPM2_Packet* packet, struct TPM2_CTX* ctx);
WOLFTPM_LOCAL void TPM2_Packet_AppendAuthCmd(TPM2_Packet* packet, TPMS_AUTH_COMMAND* authCmd);
WOLFTPM_LOCAL void TPM2_Packet_ParseAuth(TPM2_Packet* packet, TPMS_AUTH_RESPONSE* auth);
WOLFTPM_LOCAL void TPM2_Packet_AppendPCR(TPM2_Packet* packet, TPML_PCR_SELECTION* pcr);
Expand Down
Loading

0 comments on commit 63c445f

Please sign in to comment.