Skip to content

Commit 4dc5d12

Browse files
committed
Experimental USB TPM support using libusb and the LetsTrust TPM2Go USB-Stick.
1 parent ee2f766 commit 4dc5d12

12 files changed

+320
-41
lines changed

configure.ac

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ then
183183

184184
if test "x$ac_cv_libwolfssl" = "xno" && test "x$ENABLED_WOLFCRYPT" != "xno"; then
185185
AC_MSG_ERROR([WolfSSL library not found. You can get it from $WOLFSSL_URL
186-
If it's already installed, specify its path using --with-wolfcrypt=/dir or --prefix=/dir])
186+
If it is already installed, specify its path using --with-wolfcrypt=/dir or --prefix=/dir])
187187
fi
188188
else
189189
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM2_NO_WOLFCRYPT"
@@ -263,6 +263,27 @@ then
263263
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_WINAPI"
264264
fi
265265

266+
# libusb support for USB 2 SPI bridge such as found in LetsTrust TPM2Go USB-Stick
267+
AC_ARG_ENABLE([usb],
268+
[AS_HELP_STRING([--enable-usb],[Enable use of TPM through a USB2SPI bridge (default: disabled)])],
269+
[ ENABLED_USB=$enableval ],
270+
[ ENABLED_USB=no ]
271+
)
272+
273+
if test "x$ENABLED_USB" = "xyes"
274+
then
275+
if test "x$ENABLED_DEVTPM" = "xyes"
276+
then
277+
AC_MSG_ERROR([Cannot enable both usb and devtpm])
278+
fi
279+
280+
PKG_CHECK_MODULES([LIBUSB_1_0], libusb-1.0 >= 0.9.1)
281+
AC_SUBST(LIBUSB_1_0_CFLAGS)
282+
AC_SUBST(LIBUSB_1_0_LIBS)
283+
284+
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_USB $LIBUSB_1_0_CFLAGS"
285+
AM_LDFLAGS="$AM_LDFLAGS $LIBUSB_1_0_LIBS"
286+
fi
266287

267288
# STM ST33 Support
268289
AC_ARG_ENABLE([st33],,
@@ -427,6 +448,7 @@ AM_CONDITIONAL([BUILD_INFINEON], [test "x$ENABLED_INFINEON" != "xno"])
427448
AM_CONDITIONAL([BUILD_DEVTPM], [test "x$ENABLED_DEVTPM" = "xyes"])
428449
AM_CONDITIONAL([BUILD_SWTPM], [test "x$ENABLED_SWTPM" = "xyes"])
429450
AM_CONDITIONAL([BUILD_WINAPI], [test "x$ENABLED_WINAPI" = "xyes"])
451+
AM_CONDITIONAL([BUILD_USB], [test "x$ENABLED_USB" = "xyes"])
430452
AM_CONDITIONAL([BUILD_NUVOTON], [test "x$ENABLED_NUVOTON" = "xyes"])
431453
AM_CONDITIONAL([BUILD_CHECKWAITSTATE], [test "x$ENABLED_CHECKWAITSTATE" = "xyes"])
432454
AM_CONDITIONAL([BUILD_AUTODETECT], [test "x$ENABLED_AUTODETECT" = "xyes"])
@@ -547,6 +569,7 @@ echo " * I2C: $ENABLED_I2C"
547569
echo " * Linux kernel TPM device: $ENABLED_DEVTPM"
548570
echo " * SWTPM: $ENABLED_SWTPM"
549571
echo " * WINAPI: $ENABLED_WINAPI"
572+
echo " * LetsTrust TPM2Go USB: $ENABLED_USB"
550573
echo " * TIS/SPI Check Wait State: $ENABLED_CHECKWAITSTATE"
551574

552575
echo " * Infineon SLB967X $ENABLED_INFINEON"

src/include.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ if BUILD_WINAPI
2121
src_libwolftpm_la_SOURCES += src/tpm2_winapi.c
2222
src_libwolftpm_la_LIBADD = -ltbs
2323
endif
24+
if BUILD_USB
25+
src_libwolftpm_la_SOURCES += src/tpm2_usb.c
26+
endif
2427

2528
src_libwolftpm_la_CFLAGS = $(src_libwolftpm_la_EXTRAS) -DBUILDING_WOLFTPM $(AM_CFLAGS)
2629
src_libwolftpm_la_CPPFLAGS = -DBUILDING_WOLFTPM $(AM_CPPFLAGS)
27-
src_libwolftpm_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFTPM_LIBRARY_VERSION}
30+
src_libwolftpm_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFTPM_LIBRARY_VERSION}
2831

2932
#src_libwolftpm_la_DEPENDENCIES =
3033
#EXTRA_DIST +=

src/tpm2.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
#include <wolftpm/tpm2.h>
2424
#include <wolftpm/tpm2_packet.h>
2525
#include <wolftpm/tpm2_tis.h>
26-
#include <wolftpm/tpm2_linux.h>
27-
#include <wolftpm/tpm2_swtpm.h>
28-
#include <wolftpm/tpm2_winapi.h>
2926
#include <wolftpm/tpm2_param_enc.h>
3027

3128
/******************************************************************************/
@@ -38,16 +35,19 @@ static volatile int gWolfCryptRefCount = 0;
3835
#endif
3936

4037
#ifdef WOLFTPM_LINUX_DEV
41-
#define INTERNAL_SEND_COMMAND TPM2_LINUX_SendCommand
38+
#define TPM2_INTERNAL_SENDCMD TPM2_LINUX_SendCommand
4239
#define TPM2_INTERNAL_CLEANUP(ctx)
4340
#elif defined(WOLFTPM_SWTPM)
44-
#define INTERNAL_SEND_COMMAND TPM2_SWTPM_SendCommand
41+
#define TPM2_INTERNAL_SENDCMD TPM2_SWTPM_SendCommand
4542
#define TPM2_INTERNAL_CLEANUP(ctx)
4643
#elif defined(WOLFTPM_WINAPI)
47-
#define INTERNAL_SEND_COMMAND TPM2_WinApi_SendCommand
44+
#define TPM2_INTERNAL_SENDCMD TPM2_WinApi_SendCommand
4845
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_WinApi_Cleanup(ctx)
46+
#elif defined(WOLFTPM_USB)
47+
#define TPM2_INTERNAL_SENDCMD TPM2_USB_SendCommand
48+
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_USB_Cleanup
4949
#else
50-
#define INTERNAL_SEND_COMMAND TPM2_TIS_SendCommand
50+
#define TPM2_INTERNAL_SENDCMD TPM2_TIS_SendCommand
5151
#define TPM2_INTERNAL_CLEANUP(ctx)
5252
#endif
5353

@@ -415,7 +415,7 @@ static TPM_RC TPM2_SendCommandAuth(TPM2_CTX* ctx, TPM2_Packet* packet,
415415
packet->pos = cmdSz;
416416

417417
/* submit command and wait for response */
418-
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
418+
rc = (TPM_RC)TPM2_INTERNAL_SENDCMD(ctx, packet);
419419
if (rc != 0)
420420
return rc;
421421

@@ -446,7 +446,7 @@ static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
446446
return BAD_FUNC_ARG;
447447

448448
/* submit command and wait for response */
449-
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
449+
rc = (TPM_RC)TPM2_INTERNAL_SENDCMD(ctx, packet);
450450
if (rc != 0)
451451
return rc;
452452

@@ -609,16 +609,17 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
609609
ctx->tcpCtx.fd = -1;
610610
#endif
611611

612-
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || defined(WOLFTPM_WINAPI)
613-
if (ioCb != NULL || userCtx != NULL) {
614-
return BAD_FUNC_ARG;
615-
}
616-
#else
617612
/* Setup HAL IO Callback */
618613
rc = TPM2_SetHalIoCb(ctx, ioCb, userCtx);
619-
if (rc != TPM_RC_SUCCESS)
620-
return rc;
614+
if (rc != TPM_RC_SUCCESS) {
615+
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
616+
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_USB)
617+
/* these do not require a HAL IO callback or context - ignore error */
618+
rc = 0;
619+
#else
620+
return rc;
621621
#endif
622+
}
622623

623624
/* Set the active TPM global */
624625
TPM2_SetActiveCtx(ctx);

src/tpm2_usb.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/* tpm2_usb.c
2+
*
3+
* Copyright (C) 2006-2023 wolfSSL Inc.
4+
*
5+
* This file is part of wolfTPM.
6+
*
7+
* wolfTPM is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfTPM is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
23+
#ifdef WOLFTPM_USB
24+
25+
#include <wolftpm/tpm2_packet.h>
26+
#include <wolftpm/tpm2_usb.h>
27+
28+
29+
30+
#define VID_CYPRESS 0x04B4u
31+
#define PID_CYUSBSPI 0x0004u
32+
33+
#define CTRL_SET 0xC0u
34+
#define CTRL_GET 0x40u
35+
36+
#define CY_CMD_SPI 0xCAu
37+
#define CY_CMD_GPIO_SET 0xDBu
38+
#define CY_SPI_WRITEREAD 0x03u
39+
40+
#define EP_OUT 0x01u
41+
#define EP_IN 0x82u
42+
43+
#define SPI_TIMEOUT 1000
44+
#define SPI_MAX_TRANSFER (4 + 64)
45+
46+
static int TPM2_USB_Init(TPM2_CTX* ctx)
47+
{
48+
int ret;
49+
int nb_ifaces = 0;
50+
libusb_device *dev = NULL;
51+
struct libusb_config_descriptor *conf_desc = NULL;
52+
53+
if (ctx->usbCtx.dev_ctx != NULL) {
54+
return 0; /* already initialized */
55+
}
56+
57+
ret = libusb_init(&ctx->usbCtx.dev_ctx);
58+
if (ret == 0) {
59+
ctx->usbCtx.dev_handle = libusb_open_device_with_vid_pid(ctx->usbCtx.dev_ctx,
60+
VID_CYPRESS, PID_CYUSBSPI);
61+
if (ctx->usbCtx.dev_handle == NULL) {
62+
ret = -1;
63+
}
64+
}
65+
if (ret == 0) {
66+
dev = libusb_get_device(ctx->usbCtx.dev_handle);
67+
if (dev == NULL) {
68+
ret = -1;
69+
}
70+
}
71+
if (ret == 0) {
72+
ret = libusb_get_config_descriptor(dev, 0, &conf_desc);
73+
if (ret == 0) {
74+
nb_ifaces = conf_desc->bNumInterfaces;
75+
if (nb_ifaces <= 0) {
76+
ret = -1;
77+
}
78+
libusb_free_config_descriptor(conf_desc);
79+
}
80+
}
81+
if (ret == 0) {
82+
ret = libusb_set_auto_detach_kernel_driver(ctx->usbCtx.dev_handle, 1);
83+
}
84+
if (ret == 0) {
85+
ret = libusb_claim_interface(ctx->usbCtx.dev_handle, 0);
86+
}
87+
88+
ctx->usbCtx.spi_dma_buffer = libusb_dev_mem_alloc(ctx->usbCtx.dev_handle, SPI_MAX_TRANSFER);
89+
/* failure to allocate DMA, means we will use the buffer directly */
90+
91+
if (ret != 0) {
92+
TPM2_USB_Cleanup(ctx);
93+
}
94+
return ret;
95+
}
96+
97+
98+
int TPM2_USB_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
99+
{
100+
int ret;
101+
int act_len = 0;
102+
int retry = 0;
103+
int transferred = 0;
104+
int length;
105+
uint8_t* buffer;
106+
107+
ret = TPM2_USB_Init(ctx);
108+
109+
/* start transfer */
110+
if (ret == 0) {
111+
length = packet->pos;
112+
if (ctx->usbCtx.spi_dma_buffer != NULL && length < SPI_MAX_TRANSFER) {
113+
buffer = ctx->usbCtx.spi_dma_buffer;
114+
XMEMCPY(buffer, packet->buf, length);
115+
}
116+
else {
117+
buffer = packet->buf;
118+
}
119+
120+
ret = libusb_control_transfer(ctx->usbCtx.dev_handle, CTRL_SET, CY_CMD_SPI,
121+
CY_SPI_WRITEREAD, length, NULL, 0, SPI_TIMEOUT);
122+
123+
/* do send */
124+
while (ret == 0 && transferred < length) {
125+
ret = libusb_bulk_transfer(ctx->usbCtx.dev_handle, EP_OUT,
126+
ctx->usbCtx.spi_dma_buffer + transferred, length, &act_len, SPI_TIMEOUT);
127+
if (ret == 0) {
128+
transferred += act_len;
129+
length -= act_len;
130+
}
131+
}
132+
133+
/* do receive */
134+
transferred = 0;
135+
length = packet->pos;
136+
while (ret == 0 && transferred < length) {
137+
ret = libusb_bulk_transfer(ctx->usbCtx.dev_handle, EP_IN,
138+
ctx->usbCtx.spi_dma_buffer + transferred, length, &act_len, SPI_TIMEOUT);
139+
if (ret != 0) {
140+
/* allow retry up to 5 times */
141+
if (retry++ > 5) {
142+
ret = -1;
143+
break;
144+
}
145+
continue;
146+
}
147+
transferred += act_len;
148+
length -= act_len;
149+
}
150+
}
151+
152+
return ret;
153+
}
154+
155+
int TPM2_USB_Cleanup(TPM2_CTX* ctx)
156+
{
157+
if (ctx->usbCtx.dev_handle != NULL) {
158+
if (ctx->usbCtx.spi_dma_buffer != NULL) {
159+
libusb_dev_mem_free(ctx->usbCtx.dev_handle,
160+
ctx->usbCtx.spi_dma_buffer, SPI_MAX_TRANSFER);
161+
}
162+
163+
libusb_release_interface(ctx->usbCtx.dev_handle, 0);
164+
libusb_close(ctx->usbCtx.dev_handle);
165+
ctx->usbCtx.dev_handle = NULL;
166+
}
167+
if (ctx->usbCtx.dev_ctx != NULL) {
168+
libusb_exit(ctx->usbCtx.dev_ctx);
169+
ctx->usbCtx.dev_ctx = NULL;
170+
}
171+
return 0;
172+
}
173+
174+
#endif /* WOLFTPM_USB */

src/tpm2_wrap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static int wolfTPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
6060
return BAD_FUNC_ARG;
6161

6262
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
63-
defined(WOLFTPM_WINAPI)
63+
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_USB)
6464
rc = TPM2_Init_minimal(ctx);
6565
/* Using standard file I/O for the Linux TPM device */
6666
(void)ioCb;

wolftpm/include.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ nobase_include_HEADERS+= \
1111
wolftpm/tpm2_linux.h \
1212
wolftpm/tpm2_swtpm.h \
1313
wolftpm/tpm2_winapi.h \
14+
wolftpm/tpm2_usb.h \
1415
wolftpm/tpm2_param_enc.h \
1516
wolftpm/tpm2_socket.h \
1617
wolftpm/version.h \

wolftpm/tpm2.h

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,25 +1651,14 @@ static const BYTE TPM_20_EK_AUTH_POLICY[] = {
16511651

16521652
/* HAL IO Callbacks */
16531653
struct TPM2_CTX;
1654+
struct TPM2_Packet;
16541655

1655-
#ifdef WOLFTPM_SWTPM
1656-
struct wolfTPM_tcpContext {
1657-
int fd;
1658-
};
1659-
#endif /* WOLFTPM_SWTPM */
1656+
#include <wolftpm/tpm2_linux.h>
1657+
#include <wolftpm/tpm2_swtpm.h>
1658+
#include <wolftpm/tpm2_winapi.h>
1659+
#include <wolftpm/tpm2_usb.h>
16601660

16611661
#ifdef WOLFTPM_WINAPI
1662-
#include <tbs.h>
1663-
#include <winerror.h>
1664-
1665-
struct wolfTPM_winContext {
1666-
TBS_HCONTEXT tbs_context;
1667-
};
1668-
/* may be needed with msys */
1669-
#ifndef TPM_E_COMMAND_BLOCKED
1670-
#define TPM_E_COMMAND_BLOCKED (0x80280400)
1671-
#endif
1672-
16731662
#define WOLFTPM_IS_COMMAND_UNAVAILABLE(code) ((code) == (int)TPM_RC_COMMAND_CODE || (code) == (int)TPM_E_COMMAND_BLOCKED)
16741663
#else
16751664
#define WOLFTPM_IS_COMMAND_UNAVAILABLE(code) (code == (int)TPM_RC_COMMAND_CODE)
@@ -1703,6 +1692,9 @@ typedef struct TPM2_CTX {
17031692
#ifdef WOLFTPM_WINAPI
17041693
struct wolfTPM_winContext winCtx;
17051694
#endif
1695+
#ifdef WOLFTPM_USB
1696+
struct tpmUsbCtx usbCtx;
1697+
#endif
17061698
#ifndef WOLFTPM2_NO_WOLFCRYPT
17071699
#ifndef SINGLE_THREADED
17081700
wolfSSL_Mutex hwLock;

wolftpm/tpm2_linux.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@
2929
extern "C" {
3030
#endif
3131

32+
#ifdef WOLFTPM_LINUX_DEV
33+
3234
/* TPM2 IO for using TPM through the Linux kernel driver */
33-
WOLFTPM_LOCAL int TPM2_LINUX_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet);
35+
WOLFTPM_LOCAL int TPM2_LINUX_SendCommand(struct TPM2_CTX* ctx,
36+
struct TPM2_Packet* packet);
37+
38+
#endif /* WOLFTPM_LINUX_DEV */
3439

3540
#ifdef __cplusplus
3641
} /* extern "C" */

0 commit comments

Comments
 (0)