Skip to content

Commit 0b9782d

Browse files
TCTI: Add tcti-spidev
Add a new TCTI module that can talk to TPMs connected via spidev to the host. Signed-off-by: Andreas Fuchs <andreas.fuchs@infineon.com>
1 parent 5412bca commit 0b9782d

File tree

10 files changed

+560
-1
lines changed

10 files changed

+560
-1
lines changed

Makefile-test.am

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ endif
158158
if ENABLE_TCTI_SPI_LTT2GO
159159
TESTS_UNIT += test/unit/tcti-spi-ltt2go
160160
endif
161+
if ENABLE_TCTI_SPIDEV
162+
TESTS_UNIT += test/unit/tcti-spidev
163+
endif
161164
if ENABLE_TCTI_SPI_FTDI
162165
TESTS_UNIT += test/unit/tcti-spi-ftdi
163166
endif
@@ -570,6 +573,18 @@ test_unit_tcti_spi_ltt2go_SOURCES = test/unit/tcti-spi-ltt2go.c \
570573
src/tss2-tcti/tcti-spi-ltt2go.c
571574
endif
572575

576+
if ENABLE_TCTI_SPIDEV
577+
test_unit_tcti_spidev_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
578+
test_unit_tcti_spidev_LDADD = $(CMOCKA_LIBS) $(libtss2_tcti_spi_helper)
579+
test_unit_tcti_spidev_LDFLAGS = -Wl,--wrap=open \
580+
-Wl,--wrap=close \
581+
-Wl,--wrap=ioctl \
582+
-Wl,--wrap=select \
583+
-Wl,--wrap=gettimeofday
584+
test_unit_tcti_spidev_SOURCES = test/unit/tcti-spidev.c \
585+
src/tss2-tcti/tcti-spidev.c
586+
endif
587+
573588
if ENABLE_TCTI_SPI_FTDI
574589
test_unit_tcti_spi_ftdi_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
575590
test_unit_tcti_spi_ftdi_LDADD = $(CMOCKA_LIBS) $(libtss2_tcti_spi_helper)

Makefile.am

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,27 @@ endif # ENABLE_TCTI_SPI_LTT2GO
444444
EXTRA_DIST += lib/tss2-tcti-spi-ltt2go.map \
445445
lib/tss2-tcti-spi-ltt2go.def
446446

447+
# tcti library for letstrust-tpm2go usb tpm
448+
if ENABLE_TCTI_SPIDEV
449+
libtss2_tcti_spidev = src/tss2-tcti/libtss2-tcti-spidev.la
450+
tss2_HEADERS += $(srcdir)/include/tss2/tss2_tcti_spidev.h
451+
lib_LTLIBRARIES += $(libtss2_tcti_spidev)
452+
pkgconfig_DATA += lib/tss2-tcti-spidev.pc
453+
454+
src_tss2_tcti_libtss2_tcti_spidev_la_LDFLAGS =
455+
456+
if HAVE_LD_VERSION_SCRIPT
457+
src_tss2_tcti_libtss2_tcti_spidev_la_LDFLAGS += -Wl,--version-script=$(srcdir)/lib/tss2-tcti-spidev.map
458+
endif # HAVE_LD_VERSION_SCRIPT
459+
src_tss2_tcti_libtss2_tcti_spidev_la_LIBADD = $(libutil) $(libtss2_mu) $(libtss2_tcti_spi_helper)
460+
src_tss2_tcti_libtss2_tcti_spidev_la_SOURCES = \
461+
src/tss2-tcti/tcti-common.c \
462+
src/tss2-tcti/tcti-spidev.c \
463+
src/tss2-tcti/tcti-spidev.h
464+
endif # ENABLE_TCTI_SPIDEV
465+
EXTRA_DIST += lib/tss2-tcti-spidev.map \
466+
lib/tss2-tcti-spidev.def
467+
447468
# tcti library for ftdi connected tpm
448469
if ENABLE_TCTI_SPI_FTDI
449470
libtss2_tcti_spi_ftdi = src/tss2-tcti/libtss2-tcti-spi-ftdi.la

configure.ac

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) #Backward compatible setti
1515

1616
AC_CONFIG_HEADERS([config.h])
1717

18-
AC_CONFIG_FILES([Makefile Doxyfile lib/tss2-sys.pc lib/tss2-esys.pc lib/tss2-mu.pc lib/tss2-tcti-device.pc lib/tss2-tcti-mssim.pc lib/tss2-tcti-swtpm.pc lib/tss2-tcti-pcap.pc lib/tss2-tcti-libtpms.pc lib/tss2-rc.pc lib/tss2-tctildr.pc lib/tss2-fapi.pc lib/tss2-tcti-cmd.pc lib/tss2-policy.pc lib/tss2-tcti-spi-helper.pc lib/tss2-tcti-spi-ltt2go.pc lib/tss2-tcti-spi-ftdi.pc lib/tss2-tcti-i2c-helper.pc lib/tss2-tcti-i2c-ftdi.pc])
18+
AC_CONFIG_FILES([Makefile Doxyfile lib/tss2-sys.pc lib/tss2-esys.pc lib/tss2-mu.pc lib/tss2-tcti-device.pc lib/tss2-tcti-mssim.pc lib/tss2-tcti-swtpm.pc lib/tss2-tcti-pcap.pc lib/tss2-tcti-libtpms.pc lib/tss2-rc.pc lib/tss2-tctildr.pc lib/tss2-fapi.pc lib/tss2-tcti-cmd.pc lib/tss2-policy.pc lib/tss2-tcti-spi-helper.pc lib/tss2-tcti-spi-ltt2go.pc lib/tss2-tcti-spidev.pc lib/tss2-tcti-spi-ftdi.pc lib/tss2-tcti-i2c-helper.pc lib/tss2-tcti-i2c-ftdi.pc])
1919

2020
# propagate configure arguments to distcheck
2121
AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],[$ac_configure_args])
@@ -321,6 +321,15 @@ AM_CONDITIONAL([ENABLE_TCTI_SPI_LTT2GO], [test "x$enable_tcti_spi_ltt2go" != xno
321321
AS_IF([test "x$enable_tcti_spi_ltt2go" = "xyes"],
322322
AC_DEFINE([TCTI_SPI_LTT2GO],[1], [TCTI FOR USB BASED ACCESS TO LETSTRUST-TPM2GO]))
323323

324+
AC_ARG_ENABLE([tcti-spidev],
325+
[AS_HELP_STRING([--disable-tcti-spidev],
326+
[don't build the tcti-spidev module])],
327+
[])
328+
AM_CONDITIONAL([ENABLE_TCTI_SPIDEV], [test "x$enable_tcti_spidev" != xno])
329+
330+
AS_IF([test "x$enable_tcti_spidev" = "xyes"],
331+
AC_DEFINE([TCTI_SPIDEV],[1], [TCTI FOR SPIDEV BASED ACCESS TO TPM]))
332+
324333
PKG_CHECK_MODULES([LIBFTDI],
325334
[libftdi],
326335
[AC_DEFINE(LIBFTDI_VERSION, [0], [libftdi version 0.x])]
@@ -717,6 +726,7 @@ AC_MSG_RESULT([
717726
sysmeasurements: $sysmeasurements
718727
imameasurements: $imameasurements
719728
tcti_spi_ltt2go $enable_tcti_spi_ltt2go
729+
tcti_spidev $enable_tcti_spidev
720730
tcti_spi_ftdi $enable_tcti_spi_ftdi
721731
tcti_i2c_ftdi $enable_tcti_i2c_ftdi
722732
])

doc/tcti-spidev.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# SPI TCTI LTT2GO
2+
The SPI TCTI LTT2GO can be used for communication with LetsTrust-TPM2Go USB TPM.
3+
The LTT2GO module utilizes the `tcti-spi-helper` library for PTP SPI protocol handling
4+
and the `libusb-1.0-0-dev` library for USB communication.
5+
6+
# EXAMPLES
7+
8+
Set udev rules for LetsTrust-TPM2Go by creating a file `/etc/udev/rules.d/60-tpm2go.rules`:
9+
```
10+
ATTRS{idVendor}=="365d", ATTRS{idProduct}=="1337", TAG+="uaccess"
11+
```
12+
13+
Activate the udev rules:
14+
```console
15+
sudo udevadm control --reload
16+
```
17+
18+
You should see the following after plugging in the LetsTrust-TPM2Go:
19+
```
20+
dmesg
21+
[ 1019.115823] usb 3-2: new full-speed USB device number 5 using xhci_hcd
22+
[ 1019.480333] usb 3-2: New USB device found, idVendor=365d, idProduct=1337, bcdDevice= 0.00
23+
[ 1019.480360] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
24+
[ 1019.480382] usb 3-2: Product: LetsTrust-TPM2Go
25+
[ 1019.480405] usb 3-2: Manufacturer: www.pi3g.com
26+
[ 1019.480426] usb 3-2: SerialNumber: Y23CW29NR00000RND987654321012
27+
28+
sudo udevadm info -e | grep LetsTrust
29+
E: ID_MODEL=LetsTrust-TPM2Go
30+
E: ID_MODEL_ENC=LetsTrust-TPM2Go
31+
E: ID_SERIAL=www.pi3g.com_LetsTrust-TPM2Go_Y23CW29NR00000RND987654321012
32+
```
33+
34+
Use tcti-spi-ltt2go to communicate with LetsTrust-TPM2Go:
35+
```console
36+
tpm2_startup -Tspi-ltt2go -c
37+
tpm2_getrandom -Tspi-ltt2go 8 --hex
38+
```
39+
40+
Enable abrmd:
41+
```console
42+
export DBUS_SESSION_BUS_ADDRESS=`dbus-daemon --session --print-address --fork`
43+
tpm2-abrmd --allow-root --session --tcti=spi-ltt2go &
44+
45+
export TPM2TOOLS_TCTI="tabrmd:bus_name=com.intel.tss2.Tabrmd,bus_type=session"
46+
tpm2_startup -c
47+
tpm2_getrandom 8 --hex
48+
```

include/tss2/tss2_tcti_spidev.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: BSD-2-Clause */
2+
/*
3+
* Copyright 2023 Infineon Technologies AG
4+
*/
5+
#ifndef TSS2_TCTI_SPIDEV_H
6+
#define TSS2_TCTI_SPIDEV_H
7+
8+
#include <stdbool.h>
9+
#include "tss2_tcti.h"
10+
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
TSS2_RC Tss2_Tcti_Spidev_Init (
16+
TSS2_TCTI_CONTEXT *tctiContext,
17+
size_t *size,
18+
const char *config);
19+
20+
21+
#ifdef __cplusplus
22+
}
23+
#endif
24+
25+
#endif /* TSS2_TCTI_SPIDEV_H */

lib/tss2-tcti-spidev.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
LIBRARY tss2-tcti-spidev
2+
EXPORTS
3+
Tss2_Tcti_Info
4+
Tss2_Tcti_Spidev_Init

lib/tss2-tcti-spidev.map

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
global:
3+
Tss2_Tcti_Info;
4+
Tss2_Tcti_Spidev_Init;
5+
local:
6+
*;
7+
};

lib/tss2-tcti-spidev.pc.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
prefix=@prefix@
2+
exec_prefix=@exec_prefix@
3+
libdir=@libdir@
4+
includedir=@includedir@
5+
6+
Name: tss2-tcti-spidev
7+
Description: TCTI library for communicating with the TPM over spidev.
8+
URL: https://github.com/tpm2-software/tpm2-tss
9+
Version: @VERSION@
10+
Cflags: -I${includedir} -I${includedir}/tss
11+
Libs: -ltss2-tcti-spi-helper -ltss2-tcti-spi-ltt2go -L${libdir}

src/tss2-tcti/tcti-spidev.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/* SPDX-License-Identifier: BSD-2-Clause */
2+
/*
3+
* Copyright 2020 Peter Huewe
4+
*/
5+
#include <errno.h>
6+
#include <fcntl.h>
7+
#include <inttypes.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <stdbool.h>
11+
#include <string.h>
12+
#include <sys/stat.h>
13+
#include <sys/select.h>
14+
#include <sys/time.h>
15+
#include <sys/ioctl.h>
16+
#include <linux/ioctl.h>
17+
#include <unistd.h>
18+
#include <assert.h>
19+
#include <linux/spi/spidev.h>
20+
21+
#include "tss2_tcti.h"
22+
#include "tss2_tcti_spidev.h"
23+
#include "tss2_tcti_spi_helper.h"
24+
#include "tcti-common.h"
25+
#include "tss2_mu.h"
26+
#include "util/io.h"
27+
#define LOGMODULE tcti
28+
#include "util/log.h"
29+
30+
typedef struct {
31+
struct timeval timeout;
32+
int fd;
33+
} PLATFORM_USERDATA;
34+
35+
struct spi_ioc_transfer tr = {
36+
.delay_usecs = 0,
37+
.speed_hz = 5000000,
38+
.bits_per_word = 8,
39+
};
40+
41+
TSS2_RC
42+
platform_spi_acquire (void *user_data)
43+
{
44+
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
45+
tr.cs_change = 1;
46+
tr.len = 0;
47+
int ret = ioctl(platform_data->fd, SPI_IOC_MESSAGE(1), &tr);
48+
if (ret < 0) {
49+
LOG_ERROR("SPI acquire failed: %s", strerror(errno));
50+
return TSS2_TCTI_RC_IO_ERROR;
51+
}
52+
return TSS2_RC_SUCCESS;
53+
}
54+
55+
TSS2_RC
56+
platform_spi_release (void *user_data)
57+
{
58+
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
59+
tr.cs_change = 0;
60+
tr.len = 0;
61+
int ret = ioctl(platform_data->fd, SPI_IOC_MESSAGE(1), &tr);
62+
if (ret < 0) {
63+
LOG_ERROR("SPI release failed: %s", strerror(errno));
64+
return TSS2_TCTI_RC_IO_ERROR;
65+
}
66+
return TSS2_RC_SUCCESS;
67+
}
68+
69+
TSS2_RC
70+
platform_spi_transfer (void *user_data, const void *data_out, void *data_in, size_t cnt)
71+
{
72+
LOGBLOB_DEBUG(data_out, cnt, "Transferring data over ioctl:");
73+
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
74+
75+
tr.cs_change = 1;
76+
tr.len = cnt;
77+
tr.tx_buf = (unsigned long) data_out;
78+
tr.rx_buf = (unsigned long) data_in;
79+
int ret = ioctl(platform_data->fd, SPI_IOC_MESSAGE(1), &tr);
80+
if (ret < 0) {
81+
LOG_ERROR("SPI acquire failed: %s", strerror(errno));
82+
return TSS2_TCTI_RC_IO_ERROR;
83+
}
84+
LOGBLOB_DEBUG(data_in, cnt, "Received data over ioctl:");
85+
return TSS2_RC_SUCCESS;
86+
}
87+
88+
TSS2_RC
89+
platform_sleep_ms (void *user_data, int32_t milliseconds)
90+
{
91+
(void) user_data;
92+
struct timeval tv = {milliseconds/1000, (milliseconds%1000)*1000};
93+
select (0, NULL, NULL, NULL, &tv);
94+
95+
return TSS2_RC_SUCCESS;
96+
}
97+
98+
TSS2_RC
99+
platform_start_timeout (void *user_data, int32_t milliseconds)
100+
{
101+
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
102+
103+
memset (&platform_data->timeout, 0, sizeof (struct timeval));
104+
105+
if (gettimeofday (&platform_data->timeout, NULL)) {
106+
LOG_ERROR ("getimeofday failed with errno: %d.", errno);
107+
return TSS2_TCTI_RC_GENERAL_FAILURE;
108+
}
109+
110+
platform_data->timeout.tv_sec += (milliseconds/1000);
111+
platform_data->timeout.tv_usec += (milliseconds%1000)*1000;
112+
if (platform_data->timeout.tv_usec > 999999) {
113+
platform_data->timeout.tv_sec++;
114+
platform_data->timeout.tv_usec -= 1000000;
115+
}
116+
117+
return TSS2_RC_SUCCESS;
118+
}
119+
120+
TSS2_RC
121+
platform_timeout_expired (void *user_data, bool *is_timeout_expired)
122+
{
123+
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
124+
125+
struct timeval now;
126+
if (gettimeofday (&now, NULL)) {
127+
LOG_ERROR ("getimeofday failed with errno: %d.", errno);
128+
return TSS2_TCTI_RC_GENERAL_FAILURE;
129+
}
130+
131+
if (now.tv_sec > platform_data->timeout.tv_sec) {
132+
*is_timeout_expired = true;
133+
} else if ((now.tv_sec == platform_data->timeout.tv_sec)
134+
&& (now.tv_usec > platform_data->timeout.tv_usec)) {
135+
*is_timeout_expired = true;
136+
} else {
137+
*is_timeout_expired = false;
138+
}
139+
140+
return TSS2_RC_SUCCESS;
141+
}
142+
143+
void
144+
platform_finalize(void *user_data)
145+
{
146+
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
147+
close(platform_data->fd);
148+
free(platform_data);
149+
}
150+
151+
TSS2_RC
152+
Tss2_Tcti_Spidev_Init (TSS2_TCTI_CONTEXT* tcti_context, size_t* size, const char* config)
153+
{
154+
TSS2_TCTI_SPI_HELPER_PLATFORM platform = {0};
155+
156+
if (!config || config[0] == '\0')
157+
config = "/dev/spidev0.1";
158+
159+
/* Check if context size is requested */
160+
if (tcti_context == NULL) {
161+
return Tss2_Tcti_Spi_Helper_Init (NULL, size, NULL);
162+
}
163+
164+
/* Create required platform user data */
165+
PLATFORM_USERDATA *platform_data = calloc (1, sizeof (PLATFORM_USERDATA));
166+
if (platform_data == NULL) {
167+
return TSS2_BASE_RC_MEMORY;
168+
}
169+
170+
platform_data->fd = open(config, O_RDWR);
171+
if (!platform_data->fd) {
172+
LOG_ERROR("%s cannot be opened: %s", config, strerror(errno));
173+
free(platform_data);
174+
return TSS2_TCTI_RC_IO_ERROR;
175+
}
176+
177+
/* Create TCTI SPI platform struct with custom platform methods */
178+
platform.user_data = platform_data;
179+
platform.sleep_ms = platform_sleep_ms;
180+
platform.start_timeout = platform_start_timeout;
181+
platform.timeout_expired = platform_timeout_expired;
182+
platform.spi_acquire = platform_spi_acquire;
183+
platform.spi_release = platform_spi_release;
184+
platform.spi_transfer = platform_spi_transfer;
185+
platform.finalize = platform_finalize;
186+
187+
/* Initialize TCTI context */
188+
return Tss2_Tcti_Spi_Helper_Init (tcti_context, size, &platform);
189+
}
190+
191+
const TSS2_TCTI_INFO tss2_tcti_info = {
192+
.version = TCTI_VERSION,
193+
.name = "tcti-spidev",
194+
.description = "TCTI for communicating with a TPM via spidev.",
195+
.config_help = "Path to spidev (Default: /dev/spidev0.1).",
196+
.init = Tss2_Tcti_Spidev_Init
197+
};
198+
199+
const TSS2_TCTI_INFO *
200+
Tss2_Tcti_Info (void)
201+
{
202+
return &tss2_tcti_info;
203+
}

0 commit comments

Comments
 (0)