Skip to content

Commit

Permalink
tcti/py: initial commit
Browse files Browse the repository at this point in the history
Implmenet a TCTI module that will allow folks to write TCTIs in Python3.
This will allow for more crazy and complex TCTI scenarios without having
to re-write everyones stacks to use tpm2-pytss.

Example Commandline:
```bash
PYTHONPATH=$HOME tpm2_getcap --verbose --tcti=py:pytctitabrmd properties-fixed
```

Example TCTI:
For the ultimate in mind-bending: C -> Python -> C and back for
efficiency :-p.

```python3
from tpm2_pytss import TCTILdr
from typing import Union

class MyPyTCTI(object):
    def __init__(self, args: str):
        c = args.split(":", maxsplit=1)
        mod = c[0]
        args = c[1] if len(c) > 1 else "None"
        print(f"PYTHON: Initializing TCTI Ldr with mod: {mod} args: {args}")
        self._tcti = TCTILdr(mod, args)

    @Property
    def magic(self) -> Union[bytes, int]:
        # Optional Method
        print("PYTHON magic")
        return 42

    def receive(self, timeout: int) -> bytes:
        print("PYTHON receive")
        return self._tcti.receive(timeout=timeout)

    def transmit(self, data: bytes) -> None:
        print("PYTHON transmit")
        return self._tcti.receive(timeout=timeout)

def tcti_init(args: str) -> MyPyTCTI:
    print(f"PYTHON tcti_init called with: {args}")
    return MyPyTCTI(args)

```

Signed-off-by: Bill Roberts <[email protected]>
  • Loading branch information
williamcroberts committed Feb 14, 2024
1 parent a7da221 commit dbb61bd
Show file tree
Hide file tree
Showing 16 changed files with 1,199 additions and 2 deletions.
12 changes: 12 additions & 0 deletions Makefile-test.am
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ endif
if ENABLE_TCTI_I2C_FTDI
TESTS_UNIT += test/unit/tcti-i2c-ftdi
endif
if ENABLE_TCTI_PY
TESTS_UNIT += test/unit/tcti-py
endif
if ESYS
TESTS_UNIT += \
test/unit/esys-context-null \
Expand Down Expand Up @@ -599,6 +602,15 @@ test_unit_tcti_i2c_ftdi_SOURCES = test/unit/tcti-i2c-ftdi.c \
src/tss2-tcti/tcti-i2c-ftdi.c
endif

if ENABLE_TCTI_PY
test_unit_tcti_py_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS) $(PYTHON3_EMBED_CFLAGS)
test_unit_tcti_py_LDFLAGS = $(PYTHON3_EMBED_LIBS) -ldl -lpthread -ltss2-mu -ltss2-esys
test_unit_tcti_py_LDADD = $(CMOCKA_LIBS) $(test_unit_log_LDADD)
test_unit_tcti_py_SOURCES = test/unit/tcti-py.c \
src/tss2-tcti/tcti-py.c \
src/tss2-tcti/tcti-common.c
endif

test_unit_tctildr_CFLAGS = $(CMOCKA_CFLAGS) $(TESTS_CFLAGS)
test_unit_tctildr_LDADD = $(CMOCKA_LIBS) $(libutil)
test_unit_tctildr_LDFLAGS = -Wl,--wrap=calloc,--wrap=free \
Expand Down
24 changes: 24 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,28 @@ src_tss2_tcti_libtss2_tcti_i2c_ftdi_la_SOURCES = \
src/tss2-tcti/tcti-i2c-ftdi.h
endif # ENABLE_TCTI_I2C_FTDI

# tcti library for python implemented TCTIs
if ENABLE_TCTI_PY
libtss2_tcti_py = src/tss2-tcti/libtss2-tcti-py.la
tss2_HEADERS += $(srcdir)/include/tss2/tss2_tcti_py.h
lib_LTLIBRARIES += $(libtss2_tcti_py)
pkgconfig_DATA += lib/tss2-tcti-py.pc
EXTRA_DIST += lib/tss2-tcti-py.map \
lib/tss2-tcti-py.def

src_tss2_tcti_libtss2_tcti_py_la_CFLAGS = $(AM_CFLAGS) $(PYTHON3_EMBED_CFLAGS) -Wno-deprecated-declarations
src_tss2_tcti_libtss2_tcti_py_la_LDFLAGS = -ldl -lpthread $(PYTHON3_EMBED_LIBS)
if HAVE_LD_VERSION_SCRIPT
src_tss2_tcti_libtss2_tcti_py_la_LDFLAGS += -Wl,--version-script=$(srcdir)/lib/tss2-tcti-py.map
endif # HAVE_LD_VERSION_SCRIPT
src_tss2_tcti_libtss2_tcti_py_la_LIBADD = $(libutil)
src_tss2_tcti_libtss2_tcti_py_la_SOURCES = \
src/tss2-tcti/tcti-common.c \
src/tss2-tcti/tcti-py.c \
src/tss2-tcti/tcti-py.h
endif # ENABLE_TCTI_PY


### TCG TSS SYS spec library ###
libtss2_sys = src/tss2-sys/libtss2-sys.la
tss2_HEADERS += $(srcdir)/include/tss2/tss2_sys.h
Expand Down Expand Up @@ -936,6 +958,7 @@ man7_MANS = \
man/man7/tss2-tcti-spi-ftdi.7 \
man/man7/tss2-tcti-i2c-helper.7 \
man/man7/tss2-tcti-i2c-ftdi.7 \
man/man7/tss2-tcti-py.7 \
man/man7/tss2-tctildr.7

if FAPI
Expand Down Expand Up @@ -1033,6 +1056,7 @@ EXTRA_DIST += \
man/tss2-tcti-spi-ftdi.7.in \
man/tss2-tcti-i2c-helper.7.in \
man/tss2-tcti-i2c-ftdi.7.in \
man/tss2-tcti-py.7.in \
man/tss2-tctildr.7.in

CLEANFILES += \
Expand Down
32 changes: 31 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ 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-spidev.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
lib/tss2-tcti-py.pc])

# propagate configure arguments to distcheck
AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],[$ac_configure_args])
Expand Down Expand Up @@ -390,6 +391,34 @@ AM_CONDITIONAL([ENABLE_TCTI_I2C_FTDI], [test "x$enable_tcti_i2c_ftdi" != xno])
AS_IF([test "x$enable_tcti_i2c_ftdi" = "xyes"],
AC_DEFINE([TCTI_I2C_FTDI],[1], [TCTI FOR USB BASED ACCESS TO I2C BASED TPM OVER THE FTDI MPSSE USB TO I2C BRIDGE]))

AC_ARG_ENABLE([tcti-py],
[AS_HELP_STRING([--enable-tcti-py],
[build the tcti-py module])],,
[enable_tcti_py=no])

AC_DEFUN([handle_tcti_py], [
PKG_CHECK_MODULES([PYTHON3_EMBED], [python3-embed])
AM_PATH_PYTHON([3.0],
[AC_SUBST([PYTHON_INTERPRETER], [$PYTHON])],
[AC_MSG_ERROR([Integration tests enabled but python >= 3.0 executable not found.])]
)
AC_DEFINE([TCTI_PY],[1], [TCTI FOR PYTHON3 BASED TCTI IMPLEMENTATIONS])
PYLIB=[$(pkg-config --libs python3-embed | python3 -c 'import sys; print(f"lib{sys.stdin.read()[2:].strip()}.so")')]
AC_DEFINE_UNQUOTED([TCTI_PYLIB], ["$PYLIB"],
[Library to dlopen(3) for bug workaround])
])

AM_CONDITIONAL([ENABLE_TCTI_PY], [test "x$enable_tcti_py" != xno])
AS_IF([test "x$enable_tcti_py" = "xyes"], [handle_tcti_py])

# If building tcti-py with unit tests you need ESAPI
AS_IF([test "x$enable_tcti_py" = "xyes" -a "x$enable_unit" = "xyes" -a "x$enable_esys" != "xyes" ],
[AC_MSG_ERROR(["Must enable esys with tss2-py-tcti])])

AC_ARG_ENABLE([tcti-fuzzing],
[AS_HELP_STRING([--enable-tcti-fuzzing],
[build the tcti-fuzzing module])],,
Expand Down Expand Up @@ -754,4 +783,5 @@ AC_MSG_RESULT([
tcti_spidev $enable_tcti_spidev
tcti_spi_ftdi $enable_tcti_spi_ftdi
tcti_i2c_ftdi $enable_tcti_i2c_ftdi
tcti_py $enable_tcti_py
])
63 changes: 63 additions & 0 deletions doc/tcti-py.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Python TCTI (py-tcti)

The Python TCTI can be used to write TCTI modules in Python3. This allows a user to make use of the
robust language features and modules that are available in Python3.

## Invoking the Python TCTI

Like implementing any TCTI, one can follow the friendly conventions or provide the full path of the shared
object to `Tss2_TCTILdr_Initialize` or one can instantiate the TCTI directly with `TSS2_TCTI_Py_Initialize`.

One needs to specify a module name (the name of a python file) and optionally arguments to pass to an init
function in that module. The signature of this method is: `def tcti_init(args: str) -> Object` and the
args string passed in is the args option appended on the configuration string.

One possible way to use it with the command line tools is via the `--tcti=py:<modname>:<args>`. For
example:
```bash
# Python3 file pytcti.py exists in $HOME
PYTHONPATH=$HOME tpm2_getcap --tcti=py:pytcti properties-fixed
```

## Example Python TCTI

The below sample code TCTI just uses tpm2-pytss package to call TCTILdr with whatever
argument string is provided. It just showcases full path delivery of commands. To invoke
the example code below, assuming that the python file is named pytcti.py and you want
to connect to tpm2-abrmd resource manager do:
```bash
PYTHONPATH=$HOME tpm2_getcap --tcti=py:pytcti:tabrmd properties-fixed
```

```python3
# SPDX-License-Identifier: BSD-2-Clause
from tpm2_pytss import TCTILdr


class MyPyTCTI(object):
def __init__(self, args: str):
c = args.split(":", maxsplit=1)
mod = c[0]
args = c[1] if len(c) > 1 else "None"
print(f"PYTHON: Initializing TCTI Ldr with mod: {mod} args: {args}")
self._tcti = TCTILdr(mod, args)

@property
def magic(self):
# Optional Method
print("PYTHON magic")
return 42

def receive(self, timeout: int) -> bytes:
print("PYTHON receive")
return self._tcti.receive(timeout=timeout)

def transmit(self, data: bytes):
print("PYTHON transmit")
self._tcti.transmit(data)


def tcti_init(args: str) -> MyPyTCTI:
print(f"PYTHON tcti_init called with: {args}")
return MyPyTCTI(args)
```
20 changes: 20 additions & 0 deletions include/tss2/tss2_tcti_py.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: BSD-2-Clause */
#ifndef TSS2_TCTI_CMD_H
#define TSS2_TCTI_CMD_H

#include "tss2_tcti.h"

#ifdef __cplusplus
extern "C" {
#endif

TSS2_RC Tss2_Tcti_Py_Init (
TSS2_TCTI_CONTEXT *tctiContext,
size_t *size,
const char *conf);

#ifdef __cplusplus
}
#endif

#endif /* TSS2_TCTI_CMD_H */
4 changes: 4 additions & 0 deletions lib/tss2-tcti-pc.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
LIBRARY tss2-tcti-py
EXPORTS
Tss2_Tcti_Info
Tss2_Tcti_Py_Init
7 changes: 7 additions & 0 deletions lib/tss2-tcti-pc.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
global:
Tss2_Tcti_Info;
Tss2_Tcti_Py_Init;
local:
*;
};
4 changes: 4 additions & 0 deletions lib/tss2-tcti-py.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
LIBRARY tss2-tcti-py
EXPORTS
Tss2_Tcti_Info
Tss2_Tcti_Py_Init
7 changes: 7 additions & 0 deletions lib/tss2-tcti-py.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
global:
Tss2_Tcti_Info;
Tss2_Tcti_Py_Init;
local:
*;
};
11 changes: 11 additions & 0 deletions lib/tss2-tcti-py.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-py
Description: TCTI library for implementing TCTIs in Python3.
URL: https://github.com/tpm2-software/tpm2-tss
Version: @VERSION@
Cflags: -I${includedir} -I${includedir}/tss2
Libs: -ltss2-py -L${libdir}
14 changes: 14 additions & 0 deletions man/tss2-tcti-py.7.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.\" Process this file with
.\" groff -man -Tascii foo.1
.\"
.TH TCTI-PY 7 "JANUARY 2023" "TPM2 Software Stack"
.SH NAME
tcti-py \- Launch Python3 TPM2 TCTIs
.SH SYNOPSIS
Write a TCTI in Python3.
.SH DESCRIPTION
tcti-py is a library that allows creating TCTIs in Python3 by implementing a
a TCTI interface in Python. More complete documentation can be found by
visiting this URL: https://github.com/tpm2-software/tpm2-tss/tree/master/doc/tcti-py.md

It is related to the TPM Command Transmission Interface Specification\*(rq specification.
Loading

0 comments on commit dbb61bd

Please sign in to comment.