Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental USB TPM support using libusb and the LetsTrust TPM2Go USB-Stick #263

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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