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 Mar 27, 2023
1 parent ee2f766 commit 4dc5d12
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 41 deletions.
25 changes: 24 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ then

if test "x$ac_cv_libwolfssl" = "xno" && test "x$ENABLED_WOLFCRYPT" != "xno"; then
AC_MSG_ERROR([WolfSSL library not found. You can get it from $WOLFSSL_URL
If it's already installed, specify its path using --with-wolfcrypt=/dir or --prefix=/dir])
If it is already installed, specify its path using --with-wolfcrypt=/dir or --prefix=/dir])
fi
else
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM2_NO_WOLFCRYPT"
Expand Down Expand Up @@ -263,6 +263,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 @@ -427,6 +448,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 @@ -547,6 +569,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 +=
33 changes: 17 additions & 16 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>

/******************************************************************************/
Expand All @@ -38,16 +35,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 @@ -415,7 +415,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 @@ -446,7 +446,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 @@ -609,16 +609,17 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
ctx->tcpCtx.fd = -1;
#endif

#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || defined(WOLFTPM_WINAPI)
if (ioCb != NULL || userCtx != NULL) {
return BAD_FUNC_ARG;
}
#else
/* Setup HAL IO Callback */
rc = TPM2_SetHalIoCb(ctx, ioCb, userCtx);
if (rc != TPM_RC_SUCCESS)
return rc;
if (rc != TPM_RC_SUCCESS) {
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_USB)
/* these do not require a HAL IO callback or context - ignore error */
rc = 0;
#else
return rc;
#endif
}

/* Set the active TPM global */
TPM2_SetActiveCtx(ctx);
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
Loading

0 comments on commit 4dc5d12

Please sign in to comment.