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.
pull/156/head
David Garske 2021-06-01 10:34:28 -07:00
parent 55a22350c9
commit ed1ec8c52d
12 changed files with 292 additions and 13 deletions

165
IDE/QNX/README.md 100644
View File

@ -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

View File

@ -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

View File

@ -4,3 +4,4 @@
include IDE/OPENSTM32/include.am
include IDE/IAR-EWARM/include.am
include IDE/QNX/include.am

View File

@ -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

View File

@ -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;
}

View File

@ -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");

View File

@ -24,7 +24,7 @@
#include <wolftpm/tpm2_wrap.h>
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && \
!defined(NO_WOLFSSL_CLIENT)
!defined(NO_WOLFSSL_CLIENT) && !defined(WOLFCRYPT_ONLY)
#include <examples/tpm_io.h>
#include <examples/tpm_test.h>
@ -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");

View File

@ -25,7 +25,7 @@
#include <wolftpm/tpm2.h>
#include <wolftpm/tpm2_wrap.h>
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(WOLFCRYPT_ONLY)
#include <wolftpm/tpm2_socket.h>

View File

@ -101,6 +101,13 @@
#include <spi/spi.h>
#include <spi/spi_gpio.h>
#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

View File

@ -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;

View File

@ -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

View File

@ -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 <wolfssl/wolfio.h>
#endif