From ed1ec8c52ddd9a124158de8b6d626860fa59918d Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Jun 2021 10:34:28 -0700 Subject: [PATCH] Support for QNX with wolfTPM: * Fix for `wolfTPM2_NVCreateAuth` to return `TPM_RC_NV_DEFINED` if already exists (it used to do this, but broke with GPIO changes). * Fixes for building wolfTPM with wolfCrypt only (no TLS). * Fix for building without RSA and ECC. * Fix for `--enable-smallstack` with parameter encryption, * Fix for nvram/store unused variable. --- IDE/QNX/README.md | 165 ++++++++++++++++++++++++++++++++ IDE/QNX/include.am | 5 + IDE/include.am | 1 + configure.ac | 8 +- examples/gpio/gpio_config.c | 2 +- examples/seal/unseal.c | 4 +- examples/tls/tls_client_notpm.c | 4 +- examples/tls/tls_common.h | 2 +- examples/tpm_io.c | 99 ++++++++++++++++++- examples/wrap/wrap_test.c | 2 + src/tpm2_wrap.c | 11 ++- wolftpm/tpm2_socket.h | 2 +- 12 files changed, 292 insertions(+), 13 deletions(-) create mode 100644 IDE/QNX/README.md create mode 100644 IDE/QNX/include.am diff --git a/IDE/QNX/README.md b/IDE/QNX/README.md new file mode 100644 index 0000000..eef90c6 --- /dev/null +++ b/IDE/QNX/README.md @@ -0,0 +1,165 @@ +# wolfTPM with QNX + +Instructions for creating a QNX Momentics wolfTPM Project... + +## Create a new QNX Application + +1) Create folder for libraries (lib) and includes (inc) +2) Add library sources into "lib" directory as "wolfssl" and "wolftpm" +3) Edit Makefile to build sources and include directories. + +``` +# wolfSSL and wolfTPM library includes/sources +INCLUDES += -I./inc -I./lib/wolftpm -I./lib/wolfssl +CCFLAGS_all += -DWOLFSSL_USER_SETTINGS -DWOLFTPM_USER_SETTINGS + +SRCS += $(call wildcard, lib/wolfssl/wolfcrypt/src/*.c) +SRCS += $(call wildcard, lib/wolfssl/wolfcrypt/src/port/arm/*.c) +SRCS += $(call wildcard, lib/wolfssl/wolfcrypt/src/port/xilinx/*.c) +SRCS += $(call wildcard, lib/wolftpm/src/*.c) + +# The QNX SPI Driver +LIBS += -lspi-master +``` + +4) Create `inc/user_settings.h` for all wolf specific settings: + +Here is a template: + +``` +#ifndef WOLF_USER_SETTINGS_H +#define WOLF_USER_SETTINGS_H + +/* TPM */ +#define WOLFTPM_AUTODETECT +#define WOLFTPM_CHECK_WAIT_STATE +#define WOLFTPM_ADV_IO /* use advanced IO HAL callback */ +#define TPM_TIMEOUT_TRIES 100000 + +/* always perform self-test (some chips require) */ +#define WOLFTPM_PERFORM_SELFTEST + +/* Reduce stack use */ +#define MAX_COMMAND_SIZE 1024 +#define MAX_RESPONSE_SIZE 1024 +#define WOLFTPM2_MAX_BUFFER 1500 +#define MAX_DIGEST_BUFFER 973 + +/* Debugging */ +#if 1 + #define DEBUG_WOLFTPM + //#define WOLFTPM_DEBUG_VERBOSE + //#define WOLFTPM_DEBUG_IO + //#define WOLFTPM_DEBUG_TIMEOUT +#endif + +/* Platform */ +#define WOLFCRYPT_ONLY +#define SINGLE_THREADED +#define NO_FILESYSTEM +#define WOLFSSL_IGNORE_FILE_WARN +#define WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MAX + +/* Math */ +#define ECC_TIMING_RESISTANT +#define TFM_TIMING_RESISTANT +#define USE_FAST_MATH +#define FP_MAX_BITS (2 * 4096) +#define WOLFSSL_NO_HASH_RAW +#define ALT_ECC_SIZE + +/* Enables */ +#define HAVE_ECC +#define ECC_SHAMIR +#define HAVE_AESGCM +#define GCM_TABLE_4BIT + +/* Disables */ +#define NO_MAIN_DRIVER +#define NO_WOLFSSL_MEMORY +#define NO_ASN +#define NO_ASN_TIME +#define NO_CODING +#define NO_CERTS +#define NO_PSK + +#define NO_PWDBASED +#define NO_DSA +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 +#define NO_SHA +#define NO_HC128 +#define NO_RABBIT +#define NO_DES3 + +#endif /* !WOLF_USER_SETTINGS_H */ +``` + +5) wolfTPM HAL: Use either `tpm_io.c` directly or copy the required HAL interface into your own .c. + +6) Add wolfTPM example code into your own .c. + +7) Consider QNX BSP SPI master patch for handling multiple calls with CS asserted, which is required for the SPI wait states. + +## QNX SPI Master Patch for Manual Chip Select + +Edit the following QNX BSP files: + +1) `bsp/src/hardware/spi/xzynq/aarch64/dll.le.zcu102/xzynq_spi.c` + +``` +@@ -442,7 +442,7 @@ static void xzynq_setup(xzynq_spi_t *dev, uint32_t device) + spi_debug1("%s: CONFIG_SPI_REG = 0x%x", __func__, dev->ctrl[id]); + #endif + +- if(dev->fcs) { ++ if(dev->fcs || (devlist[id].cfg.mode & SPI_MODE_MAN_CS)) { + out32(base + XZYNQ_SPI_CR_OFFSET, dev->ctrl[id] | XZYNQ_SPI_CR_MAN_CS); + } else { + out32(base + XZYNQ_SPI_CR_OFFSET, dev->ctrl[id]); +@@ -621,7 +621,7 @@ void *xzynq_xfer(void *hdl, uint32_t device, uint8_t *buf, int *len) + reset = 1; + } + +- if(!dev->fcs) { ++ if(!dev->fcs && !(devlist[id].cfg.mode & SPI_MODE_MAN_CS)) { + xzynq_spi_slave_select(dev, id, 0); + } +``` + +2) `bsp/src/hardware/spi/xzynq/config.c` + +``` +@@ -72,6 +73,16 @@ int xzynq_cfg(void *hdl, spi_cfg_t *cfg, int cs) + /* Enable ModeFail generation */ + ctrl |= XZYNQ_SPI_CR_MFAIL_EN; + ++ if (cfg->mode & SPI_MODE_MAN_CS) ++ ctrl |= XZYNQ_SPI_CR_MAN_CS; /* enable manual CS mode */ ++ ++ if (cfg->mode & SPI_MODE_CLEAR_CS) { ++ /* make sure all chip selects are de-asserted */ ++ /* set all CS bits high to de-assert */ ++ out32(base + XZYNQ_SPI_CR_OFFSET, ++ in32(base + XZYNQ_SPI_CR_OFFSET) | XZYNQ_SPI_CR_CS); ++ } ++ +``` + +3) `target/qnx7/usr/include/hw/spi-master.h` + +``` +@@ -71,6 +71,8 @@ typedef struct { + #define SPI_MODE_RDY_LEVEL (2 << 14) /* Low level signal */ + #define SPI_MODE_IDLE_INSERT (1 << 16) ++#define SPI_MODE_MAN_CS (1 << 17) /* Manual Chip select */ ++#define SPI_MODE_CLEAR_CS (1 << 18) /* Clear all chip selects (used with SPI_MODE_MAN_CS) */ + + #define SPI_MODE_LOCKED (1 << 31) /* The device is locked by another client */ +``` + +## Support + +For questions please email support@wolfssl.com diff --git a/IDE/QNX/include.am b/IDE/QNX/include.am new file mode 100644 index 0000000..08bda6e --- /dev/null +++ b/IDE/QNX/include.am @@ -0,0 +1,5 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST+= IDE/QNX/README.md diff --git a/IDE/include.am b/IDE/include.am index 5967fcf..b6a8123 100644 --- a/IDE/include.am +++ b/IDE/include.am @@ -4,3 +4,4 @@ include IDE/OPENSTM32/include.am include IDE/IAR-EWARM/include.am +include IDE/QNX/include.am diff --git a/configure.ac b/configure.ac index 7e6d598..1cd04f4 100644 --- a/configure.ac +++ b/configure.ac @@ -341,7 +341,13 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_SMALL_STACK" # Reduces max packet and buffer sizes to 1024 bytes - AM_CFLAGS="$AM_CFLAGS -DMAX_COMMAND_SIZE=1024 -DMAX_RESPONSE_SIZE=1024 -DWOLFTPM2_MAX_BUFFER=1500 -DMAX_SESSION_NUM=1 -DMAX_DIGEST_BUFFER=973" + AM_CFLAGS="$AM_CFLAGS -DMAX_COMMAND_SIZE=1024 -DMAX_RESPONSE_SIZE=1024 -DWOLFTPM2_MAX_BUFFER=1500 -DMAX_DIGEST_BUFFER=973" + + # If parameter encryption is not used then maximum session count is one + if test "x$ENABLED_WOLFCRYPT" = "xno" + then + AM_CFLAGS="$AM_CFLAGS -DMAX_SESSION_NUM=1" + fi fi # Runtime Module Detection diff --git a/examples/gpio/gpio_config.c b/examples/gpio/gpio_config.c index 835cffa..6f2f0e4 100644 --- a/examples/gpio/gpio_config.c +++ b/examples/gpio/gpio_config.c @@ -218,7 +218,7 @@ int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[]) /* Define NV Index for GPIO */ rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, nvIndex, nvAttributes, sizeof(BYTE), (byte*)gNvAuth, sizeof(gNvAuth)-1); - if (rc != 0) { + if (rc != 0 && rc != TPM_RC_NV_DEFINED) { printf("Creating NV Index for GPIO acccess failed\n"); goto exit; } diff --git a/examples/seal/unseal.c b/examples/seal/unseal.c index 5924810..d51cc66 100644 --- a/examples/seal/unseal.c +++ b/examples/seal/unseal.c @@ -41,7 +41,7 @@ static void usage(void) { printf("Expected usage:\n"); printf("./examples/seal/unseal [filename]\n"); - printf("* filename - File containg a TPM seal key\n"); + printf("* filename - File contaning a TPM seal key\n"); printf("Demo usage, without arguments, uses keyblob.bin file input.\n"); } @@ -144,7 +144,7 @@ int main(int argc, char *argv[]) { int rc = -1; -#ifndef WOLFTPM2_NO_WRAPPER +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(NO_FILESYSTEM) rc = TPM2_Unseal_Example(NULL, argc, argv); #else printf("Wrapper code not compiled in\n"); diff --git a/examples/tls/tls_client_notpm.c b/examples/tls/tls_client_notpm.c index ad2bf81..948e6d9 100644 --- a/examples/tls/tls_client_notpm.c +++ b/examples/tls/tls_client_notpm.c @@ -24,7 +24,7 @@ #include #if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ - !defined(NO_WOLFSSL_CLIENT) + !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFCRYPT_ONLY) #include #include @@ -305,7 +305,7 @@ int main(int argc, char *argv[]) int rc = -1; #if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \ - !defined(NO_WOLFSSL_CLIENT) + !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFCRYPT_ONLY) rc = TLS_ClientArgs(argc, argv); #else printf("WolfSSL Client code not compiled in\n"); diff --git a/examples/tls/tls_common.h b/examples/tls/tls_common.h index e0b71dd..b07336d 100644 --- a/examples/tls/tls_common.h +++ b/examples/tls/tls_common.h @@ -25,7 +25,7 @@ #include #include -#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(WOLFCRYPT_ONLY) #include diff --git a/examples/tpm_io.c b/examples/tpm_io.c index 15e8ec2..b2bb893 100644 --- a/examples/tpm_io.c +++ b/examples/tpm_io.c @@ -101,6 +101,13 @@ #include #include +#elif defined(__QNX__) || defined(__QNXNTO__) + /* QNX */ + #include "hw/spi-master.h" + #ifndef TPM2_SPI_DEV + #define TPM2_SPI_DEV "/dev/spi0" + #endif + #elif defined(__XILINX__) #include "xspips.h" @@ -623,6 +630,95 @@ return ret; } +#elif defined(__QNX__) || defined(__QNXNTO__) + + /* customization to QNX SPI master to allow keeping + CS asserted (low) till spi_close. See IDE/QNX for spi_master patch */ + #ifndef SPI_MODE_MAN_CS + #define SPI_MODE_MAN_CS (1 << 17) /* Manual Chip select */ + #endif + #ifndef SPI_MODE_CLEAR_CS + #define SPI_MODE_CLEAR_CS (1 << 18) /* Clear all chip selects (used with SPI_MODE_MAN_CS) */ + #endif + static int TPM2_IoCb_QNX_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx) + { + int fd; + int ret = TPM_RC_FAILURE; + int status; + #ifdef WOLFTPM_CHECK_WAIT_STATE + int timeout = TPM_SPI_WAIT_RETRY; + #endif + spi_cfg_t cfg; + + /* open device */ + fd = spi_open(TPM2_SPI_DEV); + if (fd == -1) { + return TPM_RC_FAILURE; + } + XMEMSET(&cfg, 0, sizeof(cfg)); + cfg.mode = 8; /* 8-bits - CPOL=0/CPHA=0 */ + cfg.mode |= SPI_MODE_MAN_CS; /* manual chip select - leave asserted */ + cfg.clock_rate = TPM2_SPI_HZ; + status = spi_setcfg(fd, SPI_DEV_DEFAULT, &cfg); + if (status != 0) { + spi_close(fd); + return ret; + } + + #ifdef WOLFTPM_CHECK_WAIT_STATE + /* Send Header */ + status = spi_xchange(fd, SPI_DEV_DEFAULT, + (byte*)txBuf, rxBuf, TPM_TIS_HEADER_SZ); + if (status == -1) { + spi_close(fd); + return ret; + } + + /* Check for wait states */ + if ((rxBuf[TPM_TIS_HEADER_SZ-1] & TPM_TIS_READY_MASK) == 0) { + do { + /* Check for SPI ready */ + status = spi_xchange(fd, SPI_DEV_DEFAULT, + (byte*)txBuf, rxBuf, 1); + if (status != -1 && rxBuf[0] & TPM_TIS_READY_MASK) + break; + } while (--timeout > 0); + #ifdef WOLFTPM_DEBUG_TIMEOUT + printf("SPI Ready Wait %d\n", TPM_SPI_WAIT_RETRY - timeout); + #endif + if (timeout <= 0) { + spi_close(fd); + return TPM_RC_FAILURE; + } + } + + /* Send remainder of payload */ + status = spi_xchange(fd, SPI_DEV_DEFAULT, + (byte*)&txBuf[TPM_TIS_HEADER_SZ], + &rxBuf[TPM_TIS_HEADER_SZ], + xferSz - TPM_TIS_HEADER_SZ); + + /* inform spi_master we are done... de-assert SPI */ + cfg.mode |= (SPI_MODE_MAN_CS | SPI_MODE_CLEAR_CS); + (void)spi_setcfg(fd, SPI_DEV_DEFAULT, &cfg); + #else + /* Send Entire Message - no wait states */ + status = spi_xchange(fd, SPI_DEV_DEFAULT, + (byte*)txBuf, rxBuf, xferSz); + #endif /* WOLFTPM_CHECK_WAIT_STATE */ + if (status != -1) { + ret = TPM_RC_SUCCESS; + } + + spi_close(fd); + + (void)userCtx; + (void)ctx; + + return ret; + } + #elif defined(__XILINX__) #define XSpiPs_SendByte(BaseAddress, Data) \ @@ -799,7 +895,6 @@ return ret; } - #endif @@ -817,6 +912,8 @@ static int TPM2_IoCb_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, ret = TPM2_IoCb_Atmel_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(__BAREBOX__) ret = TPM2_IoCb_Barebox_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); +#elif defined(__QNX__) || defined(__QNXNTO__) + ret = TPM2_IoCb_QNX_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(__XILINX__) ret = TPM2_IoCb_Xilinx_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #else diff --git a/examples/wrap/wrap_test.c b/examples/wrap/wrap_test.c index 9911b53..f810ae5 100644 --- a/examples/wrap/wrap_test.c +++ b/examples/wrap/wrap_test.c @@ -107,8 +107,10 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[]) "\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7"; #ifndef WOLFTPM2_NO_WOLFCRYPT +#if defined(HAVE_ECC) || !defined(NO_RSA) int tpmDevId = INVALID_DEVID; word32 idx; +#endif #ifndef NO_RSA RsaKey wolfRsaPubKey; RsaKey wolfRsaPrivKey; diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index e3dba87..25e016c 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -653,6 +653,7 @@ int wolfTPM2_EncryptSalt(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey, #endif /* !WOLFTPM2_NO_WOLFCRYPT */ (void)bindAuth; /* TODO: Add bind support */ + (void)dev; return rc; } @@ -2567,7 +2568,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, WOLFTPM2_NV* nv, word32 nvIndex, word32 nvAttributes, word32 maxSize, const byte* auth, int authSz) { - int rc; + int rc, alreadyExists = 0; NV_DefineSpace_In in; if (dev == NULL || nv == NULL) @@ -2593,6 +2594,7 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, rc = TPM2_NV_DefineSpace(&in); if (rc == TPM_RC_NV_DEFINED) { + alreadyExists = 1; #ifdef DEBUG_WOLFTPM printf("TPM2_NV_DefineSpace: handle already exists\n"); #endif @@ -2629,7 +2631,8 @@ int wolfTPM2_NVCreateAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* parent, in.publicInfo.nvPublic.dataSize); #endif - return rc; + /* if handle already existed then return `TPM_RC_NV_DEFINED` */ + return (rc == TPM_RC_SUCCESS && alreadyExists) ? TPM_RC_NV_DEFINED : rc; } /* older API kept for compatibility, recommend using wolfTPM2_NVCreateAuth */ @@ -2928,11 +2931,11 @@ int wolfTPM2_NVDelete(WOLFTPM2_DEV* dev, TPM_HANDLE authHandle, #ifndef WOLFTPM2_NO_WOLFCRYPT struct WC_RNG* wolfTPM2_GetRng(WOLFTPM2_DEV* dev) { -#ifdef WOLFTPM2_USE_WOLF_RNG if (dev) { + #ifdef WOLFTPM2_USE_WOLF_RNG return &dev->ctx.rng; + #endif } -#endif return NULL; } #endif diff --git a/wolftpm/tpm2_socket.h b/wolftpm/tpm2_socket.h index f1f8767..15ff7a2 100644 --- a/wolftpm/tpm2_socket.h +++ b/wolftpm/tpm2_socket.h @@ -22,7 +22,7 @@ #ifndef _TPM2_SOCKET_H_ #define _TPM2_SOCKET_H_ -#ifndef WOLFTPM2_NO_WOLFCRYPT +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(WOLFCRYPT_ONLY) #include #endif