Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/workflows/pikeos-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: PikeOS Build (WOLFTPM_PIKEOS)

# Compile-only check of the PikeOS TPM driver transport (--enable-pikeos).
# The PikeOS SDK is not available in CI, so minimal p4.h/vm.h stubs supply the
# types and prototypes used by src/tpm2_pikeos.c with the SDK's signatures.

on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]
types: [opened, synchronize, reopened, ready_for_review]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
pikeos:
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
runs-on: ubuntu-latest
container:
image: ghcr.io/wolfssl/wolftpm-ci:v1.1
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Write PikeOS p4.h/vm.h stubs
run: |
mkdir -p pikeos_stub
cat > pikeos_stub/p4.h <<'EOF'
#ifndef PIKEOS_STUB_P4_H
#define PIKEOS_STUB_P4_H
typedef int P4_e_t;
typedef unsigned long P4_size_t;
typedef unsigned long long P4_time_t;
#define P4_E_OK 0
#define P4_MSEC(to) ((to) * 1000000ULL)
P4_e_t p4_sleep(P4_time_t timeout);
P4_time_t p4_get_time(void);
#endif
EOF
cat > pikeos_stub/vm.h <<'EOF'
#ifndef PIKEOS_STUB_VM_H
#define PIKEOS_STUB_VM_H
#include <p4.h>
typedef struct { unsigned int gdh; } vm_file_desc_t;
#define VM_O_RD_WR 3
P4_e_t vm_open(const char *name, unsigned int oflags,
vm_file_desc_t *fd);
P4_e_t vm_read(vm_file_desc_t *fd, void *buff, P4_size_t buff_size,
P4_size_t *read_size);
P4_e_t vm_write(vm_file_desc_t *fd, const void *buff,
P4_size_t buff_size, P4_size_t *written_size);
P4_e_t vm_close(vm_file_desc_t *fd);
#endif
EOF

- name: Configure (PikeOS transport, no wolfCrypt)
run: |
./autogen.sh
./configure --enable-pikeos --disable-wolfcrypt --disable-examples

- name: Build library
run: |
make src/libwolftpm.la CFLAGS="-Ipikeos_stub -Werror"

- name: Build library (debug)
run: |
make clean
make src/libwolftpm.la \
CFLAGS="-Ipikeos_stub -Werror -DDEBUG_WOLFTPM -DWOLFTPM_DEBUG_VERBOSE"
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ set(TPM_SOURCES
src/tpm2.c
src/tpm2_linux.c
src/tpm2_packet.c
src/tpm2_pikeos.c
src/tpm2_param_enc.c
src/tpm2_swtpm.c
src/tpm2_tis.c
Expand Down Expand Up @@ -196,7 +197,7 @@ endif()
set(WOLFTPM_INTERFACE "auto" CACHE STRING
"Select interface to TPM")
set_property(CACHE WOLFTPM_INTERFACE
PROPERTY STRINGS "auto;SWTPM;WINAPI;DEVTPM;SPI;I2C;MMIO")
PROPERTY STRINGS "auto;SWTPM;WINAPI;DEVTPM;PIKEOS;SPI;I2C;MMIO")

# automatically set
message("INTERFACE ${WOLFTPM_INTERFACE}")
Expand Down Expand Up @@ -236,6 +237,9 @@ if("${WOLFTPM_INTERFACE}" STREQUAL "SWTPM")
elseif("${WOLFTPM_INTERFACE}" STREQUAL "DEVTPM")
list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_LINUX_DEV")

elseif("${WOLFTPM_INTERFACE}" STREQUAL "PIKEOS")
list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_PIKEOS")

elseif("${WOLFTPM_INTERFACE}" STREQUAL "WINAPI")
list(APPEND WOLFTPM_DEFINITIONS "-DWOLFTPM_WINAPI")
if(BUILD_WOLFTPM_LIB)
Expand Down
28 changes: 25 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,22 @@ then
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_LINUX_DEV"
fi

# PikeOS TPM driver through the vm_open/vm_read/vm_write file provider
AC_ARG_ENABLE([pikeos],
[AS_HELP_STRING([--enable-pikeos],[Enable use of TPM through the PikeOS driver file provider (default: disabled)])],
[ ENABLED_PIKEOS=$enableval ],
[ ENABLED_PIKEOS=no ]
)

if test "x$ENABLED_PIKEOS" = "xyes"
then
if test "x$ENABLED_DEVTPM" = "xyes"
then
AC_MSG_ERROR([Cannot enable both pikeos and devtpm])
fi
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_PIKEOS"
fi

# If the user explicitly picked any hardware path (vendor, bus, kernel
# driver, autodetect), don't default-enable the software TPMs — the SPI HAL
# in hal/tpm_io_linux.c is excluded when WOLFTPM_SWTPM is defined.
Expand All @@ -255,7 +271,7 @@ for _wt_v in "$enable_infineon" "$enable_st" "$enable_st33" \
"$enable_microchip" "$enable_mchp" \
"$enable_nuvoton" "$enable_nations" "$enable_sealsq" \
"$enable_spi" "$enable_i2c" "$enable_mmio" \
"$enable_devtpm" "$enable_autodetect" \
"$enable_devtpm" "$enable_pikeos" "$enable_autodetect" \
"$enable_winapi" "$enable_wintbs"; do
if test -n "$_wt_v" && test "x$_wt_v" != "xno"; then
WOLFTPM_HW_SELECTED=yes
Expand Down Expand Up @@ -284,7 +300,7 @@ fi

# SW TPM device Support
AC_ARG_ENABLE([swtpm],
[AS_HELP_STRING([--enable-swtpm],[Enable use of TPM through the SW socket driver (default: enabled on Linux x86_64/aarch64, disabled elsewhere or when any --enable-<vendor>/--enable-spi/--enable-i2c/--enable-mmio/--enable-devtpm/--enable-autodetect is explicitly set)])],
[AS_HELP_STRING([--enable-swtpm],[Enable use of TPM through the SW socket driver (default: enabled on Linux x86_64/aarch64, disabled elsewhere or when any --enable-<vendor>/--enable-spi/--enable-i2c/--enable-mmio/--enable-devtpm/--enable-pikeos/--enable-autodetect is explicitly set)])],
[ ENABLED_SWTPM=$enableval ],
[ ENABLED_SWTPM=$WOLFTPM_DEFAULT_SWTPM ]
)
Expand All @@ -306,6 +322,10 @@ then
then
AC_MSG_ERROR([Cannot enable both swtpm and devtpm])
fi
if test "x$ENABLED_PIKEOS" = "xyes"
then
AC_MSG_ERROR([Cannot enable both swtpm and pikeos])
fi

AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_SWTPM"

Expand Down Expand Up @@ -345,7 +365,7 @@ AC_SUBST([DISTCHECK_SWTPM_PORT_FLAG])

# Firmware TPM (fwTPM) - software TPM 2.0 simulator
AC_ARG_ENABLE([fwtpm],
[AS_HELP_STRING([--enable-fwtpm],[Enable firmware TPM (fwTPM) server (default: enabled on Linux x86_64/aarch64, disabled elsewhere or when any --enable-<vendor>/--enable-spi/--enable-i2c/--enable-mmio/--enable-devtpm/--enable-autodetect is explicitly set)])],
[AS_HELP_STRING([--enable-fwtpm],[Enable firmware TPM (fwTPM) server (default: enabled on Linux x86_64/aarch64, disabled elsewhere or when any --enable-<vendor>/--enable-spi/--enable-i2c/--enable-mmio/--enable-devtpm/--enable-pikeos/--enable-autodetect is explicitly set)])],
[ ENABLED_FWTPM=$enableval ],
[ ENABLED_FWTPM=$WOLFTPM_DEFAULT_FWTPM ]
)
Expand Down Expand Up @@ -1253,13 +1273,15 @@ SPI_ACTUAL=yes
if test "x$ENABLED_I2C" = "xyes" || \
test "x$ENABLED_SWTPM" = "xyes" || test "x$ENABLED_SWTPM" = "xuart" || \
test "x$ENABLED_DEVTPM" = "xyes" || \
test "x$ENABLED_PIKEOS" = "xyes" || \
test "x$ENABLED_WINAPI" = "xyes"
then
SPI_ACTUAL=no
fi
echo " * SPI: $SPI_ACTUAL"
echo " * I2C: $ENABLED_I2C"
echo " * Linux kernel TPM device: $ENABLED_DEVTPM"
echo " * PikeOS TPM driver: $ENABLED_PIKEOS"
echo " * SWTPM: $ENABLED_SWTPM"
if test "x$ENABLED_SWTPM" = "xyes"; then
echo " * SWTPM Port: $SWTPM_PORT"
Expand Down
3 changes: 2 additions & 1 deletion docs/build-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Selecting an Infineon device with its argument looks like this:
| Option | Default | Effect and macros |
| --- | --- | --- |
| `--enable-devtpm` | disabled | Use the Linux kernel driver (`/dev/tpmrm0` or `/dev/tpm0`). Defines `WOLFTPM_LINUX_DEV`. Cannot be combined with swTPM. |
| `--enable-pikeos` | disabled | Use the PikeOS TPM driver through its file provider (`vm_open`/`vm_write`/`vm_read`). Defines `WOLFTPM_PIKEOS`. The device defaults to `/dev/tpm0`; override with `-DTPM2_PIKEOS_DEV="..."`. The application must call `vm_init()` first. PikeOS native has no `ssize_t`, so build the examples with `-DNO_FILESYSTEM`. Cannot be combined with swTPM or devtpm. |
| `--enable-swtpm` | see below | Talk to a simulator over the swtpm TCP protocol. Defines `WOLFTPM_SWTPM` and `TPM2_SWTPM_PORT`. |
| `--enable-swtpm=uart` | disabled | swtpm protocol over a UART serial port, for fwTPM on embedded targets such as STM32H5. Defines `WOLFTPM_SWTPM`, `WOLFTPM_SWTPM_UART` and `TPM2_SWTPM_PORT`, where the port value is the baud rate (default 115200). |
| `--with-swtpm-port=PORT` | 2321 | Sets `TPM2_SWTPM_PORT`. For `--enable-swtpm=uart` it sets the baud rate instead. |
Expand All @@ -88,7 +89,7 @@ Selecting an Infineon device with its argument looks like this:
- the host CPU is x86_64, amd64 or aarch64;
- the host OS is not Windows (mingw, cygwin, msys, win32);
- wolfCrypt is enabled;
- no hardware path was selected with any of `--enable-spi`, `--enable-i2c`, `--enable-mmio`, `--enable-devtpm`, `--enable-autodetect`, `--enable-winapi`, `--enable-infineon`, `--enable-st`, `--enable-st33`, `--enable-microchip`, `--enable-nuvoton`, `--enable-nations` or `--enable-sealsq`.
- no hardware path was selected with any of `--enable-spi`, `--enable-i2c`, `--enable-mmio`, `--enable-devtpm`, `--enable-pikeos`, `--enable-autodetect`, `--enable-winapi`, `--enable-infineon`, `--enable-st`, `--enable-st33`, `--enable-microchip`, `--enable-nuvoton`, `--enable-nations` or `--enable-sealsq`.

This applies to macOS and BSD as well as Linux. Everywhere else the default is off.

Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ make
```

!!! note
On any non-Windows x86_64/aarch64 host (Linux, macOS, or BSD), a bare `./configure` automatically enables the software TPM backends (swTPM and fwTPM). This lets `make check` run without any TPM hardware attached. Selecting a hardware path turns this default off: any `--enable-<vendor>`, or `--enable-spi`, `--enable-i2c`, `--enable-mmio`, `--enable-devtpm`, `--enable-autodetect`, `--enable-winapi`, or `--enable-wintbs`. See [System Interfaces](system-interfaces.md).
On any non-Windows x86_64/aarch64 host (Linux, macOS, or BSD), a bare `./configure` automatically enables the software TPM backends (swTPM and fwTPM). This lets `make check` run without any TPM hardware attached. Selecting a hardware path turns this default off: any `--enable-<vendor>`, or `--enable-spi`, `--enable-i2c`, `--enable-mmio`, `--enable-devtpm`, `--enable-pikeos`, `--enable-autodetect`, `--enable-winapi`, or `--enable-wintbs`. See [System Interfaces](system-interfaces.md).

For hardware specific build steps, see [Supported Hardware](supported-hardware.md).

Expand Down
1 change: 1 addition & 0 deletions docs/hal-io-callback.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The available system TPM interfaces are:

* Linux `/dev/tpm0`: enabled with `WOLFTPM_LINUX_DEV` or `--enable-devtpm`.
* Windows TBS: enabled with `WOLFTPM_WINAPI` or `--enable-winapi`.
* PikeOS TPM driver: enabled with `WOLFTPM_PIKEOS` or `--enable-pikeos`.
* Software TPM simulator: enabled with `WOLFTPM_SWTPM` or `--enable-swtpm`.

If you use a HAL IO callback, it is registered on library initialization with:
Expand Down
6 changes: 6 additions & 0 deletions examples/tpm_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ static const char pemFileKey[] = PEM_FILE_KEY;
#include "system/time/sys_time.h"
#elif defined(WOLFTPM_ZEPHYR)
#include <zephyr/kernel.h>
#elif defined(WOLFTPM_PIKEOS)
#include <p4.h>
#else
#include <sys/time.h>
#endif
Expand All @@ -139,6 +141,10 @@ static const char pemFileKey[] = PEM_FILE_KEY;
#elif defined(WOLFTPM_ZEPHYR)
(void)reset;
return (double)k_uptime_get() / 1000.0;
#elif defined(WOLFTPM_PIKEOS)
P4_time_t now = p4_get_time(); /* nanoseconds since boot */
(void)reset;
return (double)now / 1000000000.0;
#else
struct timeval tv;
gettimeofday(&tv, 0);
Expand Down
3 changes: 2 additions & 1 deletion hal/tpm_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
/* Native Windows, native Linux and TPM Simulator do not need an IO callback */
#if ! (defined(WOLFTPM_LINUX_DEV) || \
defined(WOLFTPM_SWTPM) || \
defined(WOLFTPM_WINAPI) ) && \
defined(WOLFTPM_WINAPI) || \
defined(WOLFTPM_PIKEOS) ) && \
(defined(WOLFTPM_EXAMPLE_HAL) || defined(WOLFTPM_MMIO) || \
defined(WOLFTPM_FWTPM_HAL))

Expand Down
2 changes: 1 addition & 1 deletion hal/tpm_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
*/

#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
defined(WOLFTPM_WINAPI)
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_PIKEOS)

/* HAL not required, so use NULL */
#define TPM2_IoCb NULL
Expand Down
3 changes: 2 additions & 1 deletion src/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ src_libwolftpm_la_SOURCES = \
src/tpm2_crypto.c \
src/tpm2_param_enc.c \
src/tpm2_cryptocb.c \
src/tpm2_linux.c
src/tpm2_linux.c \
src/tpm2_pikeos.c
if BUILD_SWTPM
src_libwolftpm_la_SOURCES += src/tpm2_swtpm.c
endif
Expand Down
8 changes: 7 additions & 1 deletion src/tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#ifdef WOLFTPM_WINAPI
#include <wolftpm/tpm2_winapi.h>
#endif
#ifdef WOLFTPM_PIKEOS
#include <wolftpm/tpm2_pikeos.h>
#endif
#include <wolftpm/tpm2_param_enc.h>
#ifdef WOLFTPM_SPDM
#include <wolftpm/tpm2_spdm.h>
Expand Down Expand Up @@ -81,6 +84,9 @@ static THREAD_LS_T TPM2_CTX* gActiveTPM;
#elif defined(WOLFTPM_WINAPI)
#define INTERNAL_SEND_COMMAND TPM2_WinApi_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_WinApi_Cleanup(ctx)
#elif defined(WOLFTPM_PIKEOS)
#define INTERNAL_SEND_COMMAND TPM2_PIKEOS_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx) TPM2_PIKEOS_Cleanup(ctx)
#else
#define INTERNAL_SEND_COMMAND TPM2_TIS_SendCommand
#define TPM2_INTERNAL_CLEANUP(ctx)
Expand Down Expand Up @@ -1072,7 +1078,7 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx,
#endif

#if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || \
defined(WOLFTPM_WINAPI)
defined(WOLFTPM_WINAPI) || defined(WOLFTPM_PIKEOS)
if (ioCb != NULL || userCtx != NULL) {
rc = BAD_FUNC_ARG;
goto exit;
Expand Down
106 changes: 106 additions & 0 deletions src/tpm2_pikeos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* tpm2_pikeos.c
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfTPM.
*
* wolfTPM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfTPM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <wolftpm/tpm2_types.h>

#ifdef WOLFTPM_PIKEOS
#include <wolftpm/tpm2_pikeos.h>

/* The PikeOS TPM driver is reached through a file provider that takes a
* complete TPM command per vm_write and returns the complete response per
* vm_read. The task must have called vm_init() before the first command. */
#ifndef TPM2_PIKEOS_DEV
#define TPM2_PIKEOS_DEV "/dev/tpm0"
#endif

int TPM2_PIKEOS_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
{
P4_e_t e;
P4_size_t written = 0;
P4_size_t readSz = 0;

if (ctx == NULL || packet == NULL) {
return BAD_FUNC_ARG;
}

if (!ctx->pikeosCtx.isOpen) {
e = vm_open(TPM2_PIKEOS_DEV, VM_O_RD_WR, &ctx->pikeosCtx.fd);
if (e != P4_E_OK) {
#ifdef DEBUG_WOLFTPM
printf("Failed to open %s: %d\n", TPM2_PIKEOS_DEV, (int)e);
#endif
return TPM_RC_FAILURE;
}
ctx->pikeosCtx.isOpen = 1;
}

#ifdef WOLFTPM_DEBUG_VERBOSE
printf("Command size: %d\n", packet->pos);
TPM2_PrintBin(packet->buf, packet->pos);
#endif

e = vm_write(&ctx->pikeosCtx.fd, packet->buf, (P4_size_t)packet->pos,
&written);
if (e != P4_E_OK || written != (P4_size_t)packet->pos) {
#ifdef DEBUG_WOLFTPM
printf("Failed write to %s: %d\n", TPM2_PIKEOS_DEV, (int)e);
#endif
return TPM_RC_FAILURE;
}

e = vm_read(&ctx->pikeosCtx.fd, packet->buf, (P4_size_t)packet->size,
&readSz);
/* The caller parses the TPM_Packet for correctness */
if (e != P4_E_OK || readSz < TPM2_HEADER_SIZE) {
#ifdef DEBUG_WOLFTPM
printf("Failed read from %s: %d (size %d)\n", TPM2_PIKEOS_DEV,
(int)e, (int)readSz);
#endif
return TPM_RC_FAILURE;
}

#ifdef WOLFTPM_DEBUG_VERBOSE
printf("Response size: %d\n", (int)readSz);
TPM2_PrintBin(packet->buf, (int)readSz);
#endif

return TPM_RC_SUCCESS;
}

int TPM2_PIKEOS_Cleanup(TPM2_CTX* ctx)
{
int rc = TPM_RC_SUCCESS;

if (ctx != NULL && ctx->pikeosCtx.isOpen) {
if (vm_close(&ctx->pikeosCtx.fd) != P4_E_OK) {
rc = TPM_RC_FAILURE;
}
ctx->pikeosCtx.isOpen = 0;
}

return rc;
}

#endif /* WOLFTPM_PIKEOS */
Loading
Loading