Skip to content

Commit 63c445f

Browse files
committed
Experimental USB TPM support using libusb and the LetsTrust TPM2Go USB-Stick.
1 parent 5e173bc commit 63c445f

File tree

12 files changed

+312
-34
lines changed

12 files changed

+312
-34
lines changed

configure.ac

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,27 @@ then
257257
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_WINAPI"
258258
fi
259259

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

261282
# STM ST33 Support
262283
AC_ARG_ENABLE([st33],,
@@ -422,6 +443,7 @@ AM_CONDITIONAL([BUILD_INFINEON], [test "x$ENABLED_INFINEON" != "xno"])
422443
AM_CONDITIONAL([BUILD_DEVTPM], [test "x$ENABLED_DEVTPM" = "xyes"])
423444
AM_CONDITIONAL([BUILD_SWTPM], [test "x$ENABLED_SWTPM" = "xyes"])
424445
AM_CONDITIONAL([BUILD_WINAPI], [test "x$ENABLED_WINAPI" = "xyes"])
446+
AM_CONDITIONAL([BUILD_USB], [test "x$ENABLED_USB" = "xyes"])
425447
AM_CONDITIONAL([BUILD_NUVOTON], [test "x$ENABLED_NUVOTON" = "xyes"])
426448
AM_CONDITIONAL([BUILD_CHECKWAITSTATE], [test "x$ENABLED_CHECKWAITSTATE" = "xyes"])
427449
AM_CONDITIONAL([BUILD_AUTODETECT], [test "x$ENABLED_AUTODETECT" = "xyes"])
@@ -542,6 +564,7 @@ echo " * I2C: $ENABLED_I2C"
542564
echo " * Linux kernel TPM device: $ENABLED_DEVTPM"
543565
echo " * SWTPM: $ENABLED_SWTPM"
544566
echo " * WINAPI: $ENABLED_WINAPI"
567+
echo " * LetsTrust TPM2Go USB: $ENABLED_USB"
545568
echo " * TIS/SPI Check Wait State: $ENABLED_CHECKWAITSTATE"
546569

547570
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: 10 additions & 10 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
#include <hal/tpm_io.h>
@@ -40,16 +37,19 @@ static volatile int gWolfCryptRefCount = 0;
4037
#endif
4138

4239
#ifdef WOLFTPM_LINUX_DEV
43-
#define INTERNAL_SEND_COMMAND TPM2_LINUX_SendCommand
40+
#define TPM2_INTERNAL_SENDCMD TPM2_LINUX_SendCommand
4441
#define TPM2_INTERNAL_CLEANUP(ctx)
4542
#elif defined(WOLFTPM_SWTPM)
46-
#define INTERNAL_SEND_COMMAND TPM2_SWTPM_SendCommand
43+
#define TPM2_INTERNAL_SENDCMD TPM2_SWTPM_SendCommand
4744
#define TPM2_INTERNAL_CLEANUP(ctx)
4845
#elif defined(WOLFTPM_WINAPI)
49-
#define INTERNAL_SEND_COMMAND TPM2_WinApi_SendCommand
46+
#define TPM2_INTERNAL_SENDCMD TPM2_WinApi_SendCommand
5047
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_WinApi_Cleanup(ctx)
48+
#elif defined(WOLFTPM_USB)
49+
#define TPM2_INTERNAL_SENDCMD TPM2_USB_SendCommand
50+
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_USB_Cleanup
5151
#else
52-
#define INTERNAL_SEND_COMMAND TPM2_TIS_SendCommand
52+
#define TPM2_INTERNAL_SENDCMD TPM2_TIS_SendCommand
5353
#define TPM2_INTERNAL_CLEANUP(ctx)
5454
#endif
5555

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

422422
/* submit command and wait for response */
423-
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
423+
rc = (TPM_RC)TPM2_INTERNAL_SENDCMD(ctx, packet);
424424
if (rc != 0)
425425
return rc;
426426

@@ -451,7 +451,7 @@ static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
451451
return BAD_FUNC_ARG;
452452

453453
/* submit command and wait for response */
454-
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
454+
rc = (TPM_RC)TPM2_INTERNAL_SENDCMD(ctx, packet);
455455
if (rc != 0)
456456
return rc;
457457

@@ -625,7 +625,7 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
625625
#endif
626626

627627
#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
628-
defined(WOLFTPM_WINAPI)
628+
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_USB)
629629
if (ioCb != NULL || userCtx != NULL) {
630630
return BAD_FUNC_ARG;
631631
}

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" */

wolftpm/tpm2_packet.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ WOLFTPM_LOCAL UINT32 TPM2_Packet_SwapU32(UINT32 data);
5555
WOLFTPM_LOCAL UINT64 TPM2_Packet_SwapU64(UINT64 data);
5656

5757
WOLFTPM_LOCAL void TPM2_Packet_InitBuf(TPM2_Packet* packet, byte* buf, int size);
58-
WOLFTPM_LOCAL void TPM2_Packet_Init(TPM2_CTX* ctx, TPM2_Packet* packet);
58+
WOLFTPM_LOCAL void TPM2_Packet_Init(struct TPM2_CTX* ctx, TPM2_Packet* packet);
5959
WOLFTPM_LOCAL void TPM2_Packet_AppendU8(TPM2_Packet* packet, UINT8 data);
6060
WOLFTPM_LOCAL void TPM2_Packet_ParseU8(TPM2_Packet* packet, UINT8* data);
6161
WOLFTPM_LOCAL void TPM2_Packet_AppendU16(TPM2_Packet* packet, UINT16 data);
@@ -71,7 +71,7 @@ WOLFTPM_LOCAL void TPM2_Packet_MarkU16(TPM2_Packet* packet, int* markSz);
7171
WOLFTPM_LOCAL int TPM2_Packet_PlaceU16(TPM2_Packet* packet, int markSz);
7272
WOLFTPM_LOCAL void TPM2_Packet_MarkU32(TPM2_Packet* packet, int* markSz);
7373
WOLFTPM_LOCAL void TPM2_Packet_PlaceU32(TPM2_Packet* packet, int markSz);
74-
WOLFTPM_LOCAL int TPM2_Packet_AppendAuth(TPM2_Packet* packet, TPM2_CTX* ctx);
74+
WOLFTPM_LOCAL int TPM2_Packet_AppendAuth(TPM2_Packet* packet, struct TPM2_CTX* ctx);
7575
WOLFTPM_LOCAL void TPM2_Packet_AppendAuthCmd(TPM2_Packet* packet, TPMS_AUTH_COMMAND* authCmd);
7676
WOLFTPM_LOCAL void TPM2_Packet_ParseAuth(TPM2_Packet* packet, TPMS_AUTH_RESPONSE* auth);
7777
WOLFTPM_LOCAL void TPM2_Packet_AppendPCR(TPM2_Packet* packet, TPML_PCR_SELECTION* pcr);

0 commit comments

Comments
 (0)