From 80305efb86bb098a6f2b505d27bf6df53918a363 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 8 Nov 2021 11:54:14 -0800 Subject: [PATCH] Added experimental support for Das U-Boot bootloader * Recommended to use the SOFT SPI driver in U-boot * wolfTPM serves as a TPM 2.0 driver thanks to its internal TIS layer * wolfTPM provides native API with full access to all TPM 2.0 commands * wolfTPM offers wrappers API for complex and common TPM 2.0 operations --- examples/include.am | 1 + examples/tpm_io.c | 4 ++ examples/tpm_io.h | 4 ++ examples/tpm_io_uboot.c | 127 ++++++++++++++++++++++++++++++++++++++ examples/u-boot/README.md | 92 +++++++++++++++++++++++++++ examples/u-boot/options.h | 48 ++++++++++++++ 6 files changed, 276 insertions(+) create mode 100644 examples/tpm_io_uboot.c create mode 100644 examples/u-boot/README.md create mode 100644 examples/u-boot/options.h diff --git a/examples/include.am b/examples/include.am index 03bf7931..65d2f6ae 100644 --- a/examples/include.am +++ b/examples/include.am @@ -23,6 +23,7 @@ dist_example_DATA+= examples/README.md \ examples/tpm_io_linux.c \ examples/tpm_io_st.c \ examples/tpm_io_qnx.c \ + examples/tpm_io_uboot.c \ examples/tpm_io_xilinx.c \ examples/tpm_io.h \ examples/tpm_test_keys.c \ diff --git a/examples/tpm_io.c b/examples/tpm_io.c index ff482ba2..b6778e7e 100644 --- a/examples/tpm_io.c +++ b/examples/tpm_io.c @@ -56,6 +56,8 @@ #include "examples/tpm_io_barebox.c" #elif defined(__QNX__) || defined(__QNXNTO__) #include "examples/tpm_io_qnx.c" +#elif defined(__UBOOT__) +#include "examples/tpm_io_uboot.c" #elif defined(__XILINX__) #include "examples/tpm_io_xilinx.c" #endif @@ -76,6 +78,8 @@ static int TPM2_IoCb_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, 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(__UBOOT__) + ret = TPM2_IoCb_Uboot_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #elif defined(__XILINX__) ret = TPM2_IoCb_Xilinx_SPI(ctx, txBuf, rxBuf, xferSz, userCtx); #else diff --git a/examples/tpm_io.h b/examples/tpm_io.h index 2e27b1bd..4ee06152 100644 --- a/examples/tpm_io.h +++ b/examples/tpm_io.h @@ -48,6 +48,7 @@ * * Xilinx Zynq * * Barebox * * QNX + * * Uboot * * Using custom IO Callback is always possible. * @@ -91,6 +92,9 @@ int TPM2_IoCb_STCubeMX_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, #elif defined(__QNX__) || defined(__QNXTO__) int TPM2_IoCb_QNX_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx); +#elif defined(__UBOOT__) +int TPM2_IoCb_Uboot_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx); #elif defined(__XILINX__) int TPM2_IoCb_Xilinx_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx); diff --git a/examples/tpm_io_uboot.c b/examples/tpm_io_uboot.c new file mode 100644 index 00000000..9005d550 --- /dev/null +++ b/examples/tpm_io_uboot.c @@ -0,0 +1,127 @@ +/* tpm_io_uboot.c + * + * Copyright (C) 2006-2021 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 2 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-1301, USA + */ + +/* This example shows IO interfaces for Uboot */ + + +#include +#include +#include "tpm_io.h" + +/******************************************************************************/ +/* --- BEGIN IO Callback Logic -- */ +/******************************************************************************/ + +/* Included via tpm_io.c if WOLFTPM_INCLUDE_IO_FILE is defined */ +#ifdef WOLFTPM_INCLUDE_IO_FILE + +#if ! (defined(WOLFTPM_LINUX_DEV) || \ + defined(WOLFTPM_SWTPM) || \ + defined(WOLFTPM_WINAPI) ) + +/* Use the max speed by default - see tpm2_types.h for chip specific max values */ +#ifndef TPM2_SPI_HZ + #define TPM2_SPI_HZ TPM2_SPI_MAX_HZ +#endif + +#ifndef CONFIG_DEFAULT_SPI_BUS + #define CONFIG_DEFAULT_SPI_BUS 1 + #define CONFIG_DEFAULT_SPI_CS 0 + #define CONFIG_DEFAULT_SPI_FREQ 1000000 + #define CONFIG_DEFAULT_SPI_MODE SPI_MODE_3 + #define CONFIG_DEFAULT_SPI_NAME "generic_1:0\0" +#endif + +#if defined(__UBOOT__) + #include + #include + #include + + int TPM2_IoCb_Uboot_SPI(TPM2_CTX* ctx, const byte* txBuf, + byte* rxBuf, word16 xferSz, void* userCtx) + { + int ret = TPM_RC_FAILURE; + struct udevice *udev = NULL; /* u-boot device */ + struct spi_slave *slave = NULL; + + #ifdef WOLFTPM_CHECK_WAIT_STATE + #error SPI check wait state logic not supported for U-boot + #endif + + if (userCtx == NULL) { + #ifdef DEBUG_WOLFTPM + printf("userCtx is NULL, can not acccess udev\n"); + #endif + return TPM_RC_FAILURE; + } + + #if CONFIG_IS_ENABLED(DM_SPI) + /* If Driver-model is enabled, we can acquire SPI udevice using bus number */ + ret = spi_get_bus_and_cs(CONFIG_DEFAULT_SPI_BUS, CONFIG_DEFAULT_SPI_CS, + CONFIG_DEFAULT_SPI_FREQ, CONFIG_DEFAULT_SPI_MODE, + "spi_generic_drv", CONFIG_DEFAULT_SPI_NAME, + &dev, &slave); + if (ret) { + return ret; + } + + #else + /* Acquire the SPI bus from manually passed udevice through wolfTPM2_Init */ + udev = (struct udevice*)userCtx; + slave = dev_get_parent_priv(dev); + #endif + + ret = spi_claim_bus(slave); + if (ret < 0) { + #ifdef DEBUG_WOLFTPM + printf("Failed to acquire access to u-boot spi bus\n"); + return ret; + #endif + } + + ret = spi_xfer(slave, xferSz * 8, tx_buf, rx_buf, + SPI_XFER_BEGIN | /* Assert CS before transfer */ + SPI_XFER_END); /* Deassert CS after transfer */ + #ifdef DEBUG_WOLFTPM + if (ret < 0) { + printf("Failed to transmit data over the SPI bus\n"); + } + #endif + + /* Regardless of the SPI operation outcome, release the SPI bus */ + spi_release_bus(slave); + + if (ret == 0) { + ret = TPM_RC_SUCCESS; + } + + (void)ctx; + + return ret; + } + +#endif +#endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */ +#endif /* WOLFTPM_INCLUDE_IO_FILE */ + +/******************************************************************************/ +/* --- END IO Callback Logic -- */ +/******************************************************************************/ diff --git a/examples/u-boot/README.md b/examples/u-boot/README.md new file mode 100644 index 00000000..e781a9bd --- /dev/null +++ b/examples/u-boot/README.md @@ -0,0 +1,92 @@ +# Experimental support for Das U-boot + +wolfTPM could be used with all platforms that have hardware SPI support or can use the U-boot software bit-bang implementation(SPI_SOFT). + +The example wolfTPM IO Callback was tested on RPI3 model B with ST33 TPM 2.0 module, using `make rpi_3_32b_defconfig` and changes to the DeviceTree as described below in `U-boot preparations`. + +https://source.denx.de/u-boot/u-boot + +## Current state of TPM support in U-boot + +The internal U-boot support for TPM is limited to only several commands: + +* TPM2_PCR_Read +* TPM2_PCR_Extend +* TPM2_GetCapability + +and few others for maintenance purposes, like TPM2_Clear. + +## Using wolfTPM with U-boot + +Thanks to wolfTPM, U-boot can perform all TPM 2.0 operations, including TPM2_Seal/Unseal, TPM2_Quote, TPM2_EncryptDecrypt2 and TPM2_NV_Write/TPM2_NV_Read. + +### U-boot preparation + +wolfTPM has a internal TPM Interface Command(TIS) layer and allows wolfTPM to be used as TPM 2.0 driver for baremetal and embedded systems. + +Our example IO callback in examples/tpm_io_uboot.c uses the existing SPI driver in U-boot. It is up to the developer to choose between hardware SPI driver or U-boot's software SPI driver. Best compatibility is offered through the software SPI driver that uses bit-bang GPIO to implement SPI interface. For example, U-boot does not offer hardware SPI for Raspberry Pi boards and other Broadcom SoC systems. + +To enable U-boot's software SPI driver make sure to enable SPI_SOFT in your U-boot's configuration manually or using `make menuconfig` under Device Drivers, SPI Support. + +Once enabled, it is also needed to add Device Tree entry for SPI Slave device + +``` + +tpm2-spi { + + compatible = "spi-gpio"; /* Selection the SPI_SOFT driver */ + cs-gpios = <&gpio 24 0>; /* Pinout from ST33 RPI Eval Board */ + gpio-sck = <&gpio 23 0>; + gpio-miso = <&gpio 21 0>; + gpio-mosi = <&gpio 19 0>; + spi-delay-us = <10>; + cs@0 { + }; + }; + +``` + +Note: + +U-boot should use the new Driver Model or when initializing wolfTPM in U-boot it is required to pass handle to the SPI device registered as the user context. Example below: + +``` + +struct udevice *uDev = &spiDev; /* replace with correct udevice instance */ +WOLFTPM2_DEV tpmDev; +wolfTPM2_Init(&tpmDev, TPM2_IoCb_SPI, uDev); + +``` + +In case U-boot's driver model is used, then the Io Callback will try to automatically acquire the spi device at the default SPI bus. + +### wolfTPM compilation + +To build static version of wolfTPM for U-boot, use the configure script or use the example options.h file in examples/u-boot. + +To use configure: + +./configure --disable-shared --enable-autodetect --disable-wolfcrypt + +This way u-boot can be later linked together with wolfTPM. + +## Benefits of using wolfTPM with U-boot + +### Native API + +wolfTPM provides native API with full access to all TPM 2.0 commands. For example: + +* TPM2_Seal/TPM2_Unseal +* TPM2_DefineSpace/TPM2_UndefineSpace +* TPM2_CreatePrimary/TPM2_Create +* TPM2_EncryptDecrypt2 + +Internal U-boot TPM support for these commands is missing. By adding wolfTPM the system can perform symmetric and asymmetric key generation, PCR operations, TPM 2.0 Quote, TPM 2.0 Certify Creation, Key import, extra GPIO for safety-critical systems, Signature verification, Hash generation and all other TPM 2.0 capabilities. + +### Wrappers + +wolfTPM's rich API provides wrappers for performing complete TPM 2.0 operations. There are wolfTPM wrappers for the most common and complex TPM 2.0 operations. The wrappers also protect from wrong TPM 2.0 settings and execute all necessary TPM 2.0 commands to achieve the end goal. + +wolfTPM wrappers also provide templates for the most commonly used types of TPM 2.0 keys. + +Please contact us at facts@wolfssl.com if you are interested in using wolfTPM with U-boot. diff --git a/examples/u-boot/options.h b/examples/u-boot/options.h new file mode 100644 index 00000000..b8f6ba43 --- /dev/null +++ b/examples/u-boot/options.h @@ -0,0 +1,48 @@ +/* examples/u-boot/options.h + * + * Copyright (C) 2006-2021 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 2 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 + */ + +/* Example wolfTPM options.h for U-boot compilation */ + +#ifndef WOLFTPM_OPTIONS_H +#define WOLFTPM_OPTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#undef __UBOOT__ +#define __UBOOT__ + +#undef SIZEOF_LONG +#define SIZEOF_LONG 8 + +#undef WOLFTPM2_NO_WOLFCRYPT +#define WOLFTPM2_NO_WOLFCRYPT + +#undef WOLFTPM_AUTODETECT +#define WOLFTPM_AUTODETECT + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFTPM_OPTIONS_H */ +