Skip to content

Commit

Permalink
TCTI: Add tcti-spidev
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
AndreasFuchsTPM committed Nov 27, 2023
1 parent ede63dd commit eb53dc4
Show file tree
Hide file tree
Showing 10 changed files with 558 additions and 1 deletion.
15 changes: 15 additions & 0 deletions Makefile-test.am
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ endif
if ENABLE_TCTI_SPI_LTT2GO
TESTS_UNIT += test/unit/tcti-spi-ltt2go
endif
if ENABLE_TCTI_SPIDEV
TESTS_UNIT += test/unit/tcti-spidev
endif
if ENABLE_TCTI_SPI_FTDI
TESTS_UNIT += test/unit/tcti-spi-ftdi
endif
Expand Down Expand Up @@ -570,6 +573,18 @@ test_unit_tcti_spi_ltt2go_SOURCES = test/unit/tcti-spi-ltt2go.c \
src/tss2-tcti/tcti-spi-ltt2go.c
endif

if ENABLE_TCTI_SPIDEV
test_unit_tcti_spidev_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
test_unit_tcti_spidev_LDADD = $(CMOCKA_LIBS) $(libtss2_tcti_spi_helper)
test_unit_tcti_spidev_LDFLAGS = -Wl,--wrap=open \
-Wl,--wrap=close \
-Wl,--wrap=ioctl \
-Wl,--wrap=select \
-Wl,--wrap=gettimeofday
test_unit_tcti_spidev_SOURCES = test/unit/tcti-spidev.c \
src/tss2-tcti/tcti-spidev.c
endif

if ENABLE_TCTI_SPI_FTDI
test_unit_tcti_spi_ftdi_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
test_unit_tcti_spi_ftdi_LDADD = $(CMOCKA_LIBS) $(libtss2_tcti_spi_helper)
Expand Down
20 changes: 20 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,26 @@ endif # ENABLE_TCTI_SPI_LTT2GO
EXTRA_DIST += lib/tss2-tcti-spi-ltt2go.map \
lib/tss2-tcti-spi-ltt2go.def

# tcti library for letstrust-tpm2go usb tpm
if ENABLE_TCTI_SPIDEV
libtss2_tcti_spidev = src/tss2-tcti/libtss2-tcti-spidev.la
lib_LTLIBRARIES += $(libtss2_tcti_spidev)
pkgconfig_DATA += lib/tss2-tcti-spidev.pc

src_tss2_tcti_libtss2_tcti_spidev_la_LDFLAGS =

if HAVE_LD_VERSION_SCRIPT
src_tss2_tcti_libtss2_tcti_spidev_la_LDFLAGS += -Wl,--version-script=$(srcdir)/lib/tss2-tcti-spidev.map
endif # HAVE_LD_VERSION_SCRIPT
src_tss2_tcti_libtss2_tcti_spidev_la_LIBADD = $(libutil) $(libtss2_mu) $(libtss2_tcti_spi_helper)
src_tss2_tcti_libtss2_tcti_spidev_la_SOURCES = \
src/tss2-tcti/tcti-common.c \
src/tss2-tcti/tcti-spidev.c \
src/tss2-tcti/tcti-spidev.h
endif # ENABLE_TCTI_SPIDEV
EXTRA_DIST += lib/tss2-tcti-spidev.map \
lib/tss2-tcti-spidev.def

# tcti library for ftdi connected tpm
if ENABLE_TCTI_SPI_FTDI
libtss2_tcti_spi_ftdi = src/tss2-tcti/libtss2-tcti-spi-ftdi.la
Expand Down
12 changes: 11 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) #Backward compatible setti

AC_CONFIG_HEADERS([config.h])

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])
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])

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

AC_ARG_ENABLE([tcti-spidev],
[AS_HELP_STRING([--disable-tcti-spidev],
[don't build the tcti-spidev module])],,
[enable_tcti_spidev=yes])
AM_CONDITIONAL([ENABLE_TCTI_SPIDEV], [test "x$enable_tcti_spidev" != xno])

AS_IF([test "x$enable_tcti_spidev" = "xyes"],
AC_DEFINE([TCTI_SPIDEV],[1], [TCTI FOR SPIDEV BASED ACCESS TO TPM]))

PKG_CHECK_MODULES([LIBFTDI],
[libftdi],
[AC_DEFINE(LIBFTDI_VERSION, [0], [libftdi version 0.x])]
Expand Down Expand Up @@ -721,6 +730,7 @@ AC_MSG_RESULT([
sysmeasurements: $sysmeasurements
imameasurements: $imameasurements
tcti_spi_ltt2go $enable_tcti_spi_ltt2go
tcti_spidev $enable_tcti_spidev
tcti_spi_ftdi $enable_tcti_spi_ftdi
tcti_i2c_ftdi $enable_tcti_i2c_ftdi
])
48 changes: 48 additions & 0 deletions doc/tcti-spidev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# SPI TCTI LTT2GO
The SPI TCTI LTT2GO can be used for communication with LetsTrust-TPM2Go USB TPM.
The LTT2GO module utilizes the `tcti-spi-helper` library for PTP SPI protocol handling
and the `libusb-1.0-0-dev` library for USB communication.

# EXAMPLES

Set udev rules for LetsTrust-TPM2Go by creating a file `/etc/udev/rules.d/60-tpm2go.rules`:
```
ATTRS{idVendor}=="365d", ATTRS{idProduct}=="1337", TAG+="uaccess"
```

Activate the udev rules:
```console
sudo udevadm control --reload
```

You should see the following after plugging in the LetsTrust-TPM2Go:
```
dmesg
[ 1019.115823] usb 3-2: new full-speed USB device number 5 using xhci_hcd
[ 1019.480333] usb 3-2: New USB device found, idVendor=365d, idProduct=1337, bcdDevice= 0.00
[ 1019.480360] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1019.480382] usb 3-2: Product: LetsTrust-TPM2Go
[ 1019.480405] usb 3-2: Manufacturer: www.pi3g.com
[ 1019.480426] usb 3-2: SerialNumber: Y23CW29NR00000RND987654321012
sudo udevadm info -e | grep LetsTrust
E: ID_MODEL=LetsTrust-TPM2Go
E: ID_MODEL_ENC=LetsTrust-TPM2Go
E: ID_SERIAL=www.pi3g.com_LetsTrust-TPM2Go_Y23CW29NR00000RND987654321012
```

Use tcti-spi-ltt2go to communicate with LetsTrust-TPM2Go:
```console
tpm2_startup -Tspi-ltt2go -c
tpm2_getrandom -Tspi-ltt2go 8 --hex
```

Enable abrmd:
```console
export DBUS_SESSION_BUS_ADDRESS=`dbus-daemon --session --print-address --fork`
tpm2-abrmd --allow-root --session --tcti=spi-ltt2go &

export TPM2TOOLS_TCTI="tabrmd:bus_name=com.intel.tss2.Tabrmd,bus_type=session"
tpm2_startup -c
tpm2_getrandom 8 --hex
```
25 changes: 25 additions & 0 deletions include/tss2/tss2_tcti_spidev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright 2023 Infineon Technologies AG
*/
#ifndef TSS2_TCTI_SPIDEV_H
#define TSS2_TCTI_SPIDEV_H

#include <stdbool.h>
#include "tss2_tcti.h"

#ifdef __cplusplus
extern "C" {
#endif

TSS2_RC Tss2_Tcti_Spidev_Init (
TSS2_TCTI_CONTEXT *tctiContext,
size_t *size,
const char *config);


#ifdef __cplusplus
}
#endif

#endif /* TSS2_TCTI_SPIDEV_H */
4 changes: 4 additions & 0 deletions lib/tss2-tcti-spidev.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
LIBRARY tss2-tcti-spidev
EXPORTS
Tss2_Tcti_Info
Tss2_Tcti_Spidev_Init
7 changes: 7 additions & 0 deletions lib/tss2-tcti-spidev.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
global:
Tss2_Tcti_Info;
Tss2_Tcti_Spidev_Init;
local:
*;
};
11 changes: 11 additions & 0 deletions lib/tss2-tcti-spidev.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@

Name: tss2-tcti-spidev
Description: TCTI library for communicating with the TPM over spidev.
URL: https://github.com/tpm2-software/tpm2-tss
Version: @VERSION@
Cflags: -I${includedir} -I${includedir}/tss
Libs: -ltss2-tcti-spi-helper -ltss2-tcti-spi-ltt2go -L${libdir}
202 changes: 202 additions & 0 deletions src/tss2-tcti/tcti-spidev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright 2020 Peter Huewe
*/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>
#include <unistd.h>
#include <assert.h>
#include <linux/spi/spidev.h>

#include "tss2_tcti.h"
#include "tss2_tcti_spidev.h"
#include "tss2_tcti_spi_helper.h"
#include "tcti-common.h"
#include "tss2_mu.h"
#define LOGMODULE tcti
#include "util/log.h"

typedef struct {
struct timeval timeout;
int fd;
} PLATFORM_USERDATA;

struct spi_ioc_transfer tr = {

Check notice

Code scanning / CodeQL

Short global name Note

Poor global variable name 'tr'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
.delay_usecs = 0,
.speed_hz = 5000000,
.bits_per_word = 8,
};

TSS2_RC
platform_spi_acquire (void *user_data)
{
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
tr.cs_change = 1;
tr.len = 0;
int ret = ioctl(platform_data->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0) {
LOG_ERROR("SPI acquire failed: %s", strerror(errno));
return TSS2_TCTI_RC_IO_ERROR;
}
return TSS2_RC_SUCCESS;
}

TSS2_RC
platform_spi_release (void *user_data)
{
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
tr.cs_change = 0;
tr.len = 0;
int ret = ioctl(platform_data->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0) {
LOG_ERROR("SPI release failed: %s", strerror(errno));
return TSS2_TCTI_RC_IO_ERROR;
}
return TSS2_RC_SUCCESS;
}

TSS2_RC
platform_spi_transfer (void *user_data, const void *data_out, void *data_in, size_t cnt)
{
LOGBLOB_DEBUG(data_out, cnt, "Transferring data over ioctl:");
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;

tr.cs_change = 1;
tr.len = cnt;
tr.tx_buf = (unsigned long) data_out;
tr.rx_buf = (unsigned long) data_in;
int ret = ioctl(platform_data->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 0) {
LOG_ERROR("SPI acquire failed: %s", strerror(errno));
return TSS2_TCTI_RC_IO_ERROR;
}
LOGBLOB_DEBUG(data_in, cnt, "Received data over ioctl:");
return TSS2_RC_SUCCESS;
}

TSS2_RC
platform_sleep_ms (void *user_data, int32_t milliseconds)
{
(void) user_data;
struct timeval tv = {milliseconds/1000, (milliseconds%1000)*1000};
select (0, NULL, NULL, NULL, &tv);

return TSS2_RC_SUCCESS;
}

TSS2_RC
platform_start_timeout (void *user_data, int32_t milliseconds)
{
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;

memset (&platform_data->timeout, 0, sizeof (struct timeval));

if (gettimeofday (&platform_data->timeout, NULL)) {
LOG_ERROR ("getimeofday failed with errno: %d.", errno);
return TSS2_TCTI_RC_GENERAL_FAILURE;
}

platform_data->timeout.tv_sec += (milliseconds/1000);
platform_data->timeout.tv_usec += (milliseconds%1000)*1000;
if (platform_data->timeout.tv_usec > 999999) {
platform_data->timeout.tv_sec++;
platform_data->timeout.tv_usec -= 1000000;
}

return TSS2_RC_SUCCESS;
}

TSS2_RC
platform_timeout_expired (void *user_data, bool *is_timeout_expired)
{
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;

struct timeval now;
if (gettimeofday (&now, NULL)) {
LOG_ERROR ("getimeofday failed with errno: %d.", errno);
return TSS2_TCTI_RC_GENERAL_FAILURE;
}

if (now.tv_sec > platform_data->timeout.tv_sec) {
*is_timeout_expired = true;
} else if ((now.tv_sec == platform_data->timeout.tv_sec)
&& (now.tv_usec > platform_data->timeout.tv_usec)) {
*is_timeout_expired = true;
} else {
*is_timeout_expired = false;
}

return TSS2_RC_SUCCESS;
}

void
platform_finalize(void *user_data)
{
PLATFORM_USERDATA *platform_data = (PLATFORM_USERDATA *) user_data;
close(platform_data->fd);
free(platform_data);
}

TSS2_RC
Tss2_Tcti_Spidev_Init (TSS2_TCTI_CONTEXT* tcti_context, size_t* size, const char* config)
{
TSS2_TCTI_SPI_HELPER_PLATFORM platform = {0};

if (!config || config[0] == '\0')
config = "/dev/spidev0.1";

/* Check if context size is requested */
if (tcti_context == NULL) {
return Tss2_Tcti_Spi_Helper_Init (NULL, size, NULL);
}

/* Create required platform user data */
PLATFORM_USERDATA *platform_data = calloc (1, sizeof (PLATFORM_USERDATA));
if (platform_data == NULL) {
return TSS2_BASE_RC_MEMORY;
}

platform_data->fd = open(config, O_RDWR);
if (!platform_data->fd) {
LOG_ERROR("%s cannot be opened: %s", config, strerror(errno));
free(platform_data);
return TSS2_TCTI_RC_IO_ERROR;
}

/* Create TCTI SPI platform struct with custom platform methods */
platform.user_data = platform_data;
platform.sleep_ms = platform_sleep_ms;
platform.start_timeout = platform_start_timeout;
platform.timeout_expired = platform_timeout_expired;
platform.spi_acquire = platform_spi_acquire;
platform.spi_release = platform_spi_release;
platform.spi_transfer = platform_spi_transfer;
platform.finalize = platform_finalize;

/* Initialize TCTI context */
return Tss2_Tcti_Spi_Helper_Init (tcti_context, size, &platform);
}

const TSS2_TCTI_INFO tss2_tcti_info = {
.version = TCTI_VERSION,
.name = "tcti-spidev",
.description = "TCTI for communicating with a TPM via spidev.",
.config_help = "Path to spidev (Default: /dev/spidev0.1).",
.init = Tss2_Tcti_Spidev_Init
};

const TSS2_TCTI_INFO *
Tss2_Tcti_Info (void)
{
return &tss2_tcti_info;
}
Loading

0 comments on commit eb53dc4

Please sign in to comment.