From f8c1ff6075b5825c33c2fc55e7b7977e21f7dde0 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Tue, 30 May 2023 14:11:50 +0000 Subject: [PATCH] tis: support memory mapped tpm --- README.md | 2 +- configure.ac | 13 ++++++- src/tpm2.c | 9 ++++- src/tpm2_tis.c | 88 +++++++++++++++++++++++++++++++++++++++++++++- wolftpm/tpm2_tis.h | 5 +++ 5 files changed, 113 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 81316e6..4131a05 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Portable TPM 2.0 project designed for embedded use. * This implementation provides all TPM 2.0 API’s in compliance with the specification. * Wrappers provided to simplify Key Generation/Loading, RSA encrypt/decrypt, ECC sign/verify, ECDH, NV, Hashing/Hmac and AES. * Testing done using the following TPM 2.0 modules: STM ST33TP* SPI/I2C, Infineon OPTIGA SLB9670/SLB9672, Microchip ATTPM20, Nations Tech Z32H330TC and Nuvoton NPCT650/NPCT750. -* wolfTPM uses the TPM Interface Specification (TIS) to communicate over SPI. +* wolfTPM uses the TPM Interface Specification (TIS) to communicate either over SPI, or using a memory mapped I/O range. * wolfTPM can also use the Linux TPM kernel interface (/dev/tpmX) to talk with any physical TPM on SPI, I2C and even LPC bus. * Platform support for Raspberry Pi, STM32 with CubeMX, Atmel ASF, Xilinx, Infineon TriCore and Barebox. * The design allows for easy portability to different platforms: diff --git a/configure.ac b/configure.ac index f6ac66e..befc999 100644 --- a/configure.ac +++ b/configure.ac @@ -203,6 +203,17 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_I2C" fi +# WOLFTPM_MMIO_BUILTIN_CB +AC_ARG_ENABLE([mmio], + [AS_HELP_STRING([--enable-mmio],[Enable built-in MMIO callbacks (default: disabled)])], + [ ENABLED_MMIO=$enableval ], + [ ENABLED_MMIO=no ] + ) + +if test "x$ENABLED_MMIO" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_MMIO_BUILTIN_CB" +fi # Advanced IO AC_ARG_ENABLE([advio], @@ -211,7 +222,7 @@ AC_ARG_ENABLE([advio], [ ENABLED_ADVIO=no ] ) -if test "x$ENABLED_ADVIO" = "xyes" || test "x$ENABLED_I2C" = "xyes" +if test "x$ENABLED_ADVIO" = "xyes" || test "x$ENABLED_I2C" = "xyes" || test "x$ENABLED_MMIO" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_ADV_IO" fi diff --git a/src/tpm2.c b/src/tpm2.c index 0479ee3..147edc5 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -622,7 +622,8 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx, ctx->tcpCtx.fd = -1; #endif - #if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || defined(WOLFTPM_WINAPI) + #if defined(WOLFTPM_LINUX_DEV) || defined(WOLFTPM_SWTPM) || defined(WOLFTPM_WINAPI) \ + || defined(WOLFTPM_MMIO_BUILTIN_CB) if (ioCb != NULL || userCtx != NULL) { return BAD_FUNC_ARG; } @@ -633,6 +634,12 @@ TPM_RC TPM2_Init_ex(TPM2_CTX* ctx, TPM2HalIoCb ioCb, void* userCtx, return rc; #endif +#ifdef WOLFTPM_MMIO_BUILTIN_CB + rc = TPM2_SetHalIoCb(ctx, TPM2_Mmio_Cb, NULL); + if (rc != TPM_RC_SUCCESS) + return rc; +#endif /* WOLFTPM_MMIO_BUILTIN_CB */ + /* Set the active TPM global */ TPM2_SetActiveCtx(ctx); diff --git a/src/tpm2_tis.c b/src/tpm2_tis.c index ea24753..da25182 100644 --- a/src/tpm2_tis.c +++ b/src/tpm2_tis.c @@ -57,8 +57,13 @@ enum tpm_tis_int_flags { TPM_INTF_DATA_AVAIL_INT = 0x001, }; - +#ifndef TPM_BASE_ADDRESS +#ifdef WOLFTPM_MMIO_BUILTIN_CB +#define TPM_BASE_ADDRESS (0xFED40000u) +#else #define TPM_BASE_ADDRESS (0xD40000u) +#endif +#endif #ifdef WOLFTPM_I2C /* For I2C only the lower 8-bits of the address are used */ @@ -569,6 +574,87 @@ exit: return rc; } + +#ifdef WOLFTPM_MMIO_BUILTIN_CB + +#ifndef WOLFTPM_ADV_IO +#error "WOLFTPM_MMIO_BUILTIN_CB requires WOLFTPM_ADV_IO" +#endif + +#ifdef __GNUC__ +/* this will prevent the compiler to re-order memory accesses across + * sw_barrier() invocation. + */ +#define sw_barrier() __asm__ __volatile__ ("":::"memory") +#endif /* __GNUC__ */ + +static void TPM2_Mmio_Read32(word32 addr, byte *buf) +{ + volatile word32 *_addr = (volatile word32*)(wordptr)addr; + word32 v; + + v = *_addr; + sw_barrier(); + memcpy(buf, (byte*)&v, sizeof(word32)); +} + +static void TPM2_Mmio_Write32(word32 addr, byte *buf) +{ + volatile word32 *_addr = (volatile word32*)(wordptr)addr; + word32 v; + + memcpy((uint8_t*)&v, buf, sizeof(word32)); + *_addr = v; + sw_barrier(); +} + +static void TPM2_Mmio_Read8(word32 addr, byte *buf) +{ + volatile byte *_addr = (volatile byte*)(wordptr)addr; + + *buf = *_addr; + sw_barrier(); +} + +static void TPM2_Mmio_Write8(word32 addr, byte *buf) +{ + volatile byte *_addr = (volatile byte*)(wordptr)addr; + + *_addr = *buf; + sw_barrier(); +} + +int TPM2_Mmio_Cb(TPM2_CTX *ctx, int isRead, word32 addr, byte* buf, word16 size, + void* userCtx) +{ + unsigned int i; + + (void)ctx; + (void)userCtx; +#ifdef WOLFTPM_DEBUG_VERBOSE + printf("mmio %s @ 0x%x size: %d\r\n", (isRead) ? "read" : "write", + addr, (word32)size); +#endif + for (i = 0; (size - i) >= sizeof(word32); i += sizeof(word32)) { + if (isRead) + TPM2_Mmio_Read32(addr, buf + i); + else + TPM2_Mmio_Write32(addr, buf + i); + } + + for (; i < size; i++) { + if (isRead) + TPM2_Mmio_Read8(addr, buf + i); + else + TPM2_Mmio_Write8(addr, buf + i); + } + + return 0; +} + +#endif /* WOLFTPM_MMIO_BUILTIN_CB */ + + /******************************************************************************/ /* --- END TPM Interface Layer -- */ /******************************************************************************/ diff --git a/wolftpm/tpm2_tis.h b/wolftpm/tpm2_tis.h index 2edff41..c3f7e17 100644 --- a/wolftpm/tpm2_tis.h +++ b/wolftpm/tpm2_tis.h @@ -54,6 +54,11 @@ WOLFTPM_LOCAL int TPM2_TIS_StartupWait(TPM2_CTX* ctx, int timeout); WOLFTPM_LOCAL int TPM2_TIS_Write(TPM2_CTX* ctx, word32 addr, const byte* value, word32 len); WOLFTPM_LOCAL int TPM2_TIS_Read(TPM2_CTX* ctx, word32 addr, byte* result, word32 len); +#ifdef WOLFTPM_MMIO_BUILTIN_CB +WOLFTPM_LOCAL int TPM2_Mmio_Cb(TPM2_CTX *ctx, int isRead, word32 addr, byte* buf, word16 size, + void* userCtx); +#endif /* WOLFTPM_MMIO_BUILTIN_CB */ + #ifdef __cplusplus } /* extern "C" */ #endif