Added support for TPM2.0 module via wolfTPM. Tested with STM32F4. Build using `make SIGN=ECC256 WOLFTPM=1`.

pull/27/head
David Garske 2019-11-26 10:23:56 -08:00
parent 4d49a7a0db
commit 041ca75793
12 changed files with 255 additions and 51 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "lib/wolfssl"]
path = lib/wolfssl
url = https://github.com/wolfSSL/wolfssl.git
[submodule "lib/wolfTPM"]
path = lib/wolfTPM
url = https://github.com/wolfssl/wolfTPM

View File

@ -17,6 +17,7 @@ OBJS:= \
./src/string.o \
./src/image.o \
./src/libwolfboot.o
WOLFCRYPT_OBJS:=
## Architecture/CPU configuration
@ -27,7 +28,7 @@ ifeq ($(SIGN),ECC256)
KEYGEN_OPTIONS=--ecc256
SIGN_OPTIONS=--ecc256
PRIVATE_KEY=ecc256.der
OBJS+= \
WOLFCRYPT_OBJS+= \
$(ECC_EXTRA_OBJS) \
$(MATH_OBJS) \
./lib/wolfssl/wolfcrypt/src/ecc.o \
@ -45,7 +46,7 @@ ifeq ($(SIGN),ED25519)
KEYGEN_OPTIONS=--ed25519
SIGN_OPTIONS=--ed25519
PRIVATE_KEY=ed25519.der
OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \
WOLFCRYPT_OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \
./lib/wolfssl/wolfcrypt/src/ed25519.o \
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
./lib/wolfssl/wolfcrypt/src/sha256.o \
@ -63,7 +64,7 @@ ifeq ($(SIGN),RSA2048)
SIGN_OPTIONS=--rsa2048
PRIVATE_KEY=rsa2048.der
IMAGE_HEADER_SIZE=512
OBJS+= \
WOLFCRYPT_OBJS+= \
$(RSA_EXTRA_OBJS) \
$(MATH_OBJS) \
./lib/wolfssl/wolfcrypt/src/rsa.o \
@ -93,7 +94,8 @@ endif
ifeq ($(SPI_FLASH),1)
EXT_FLASH=1
CFLAGS+= -DSPI_FLASH=1
OBJS+= src/spi_flash.o hal/spi/spi_drv_$(TARGET).o
OBJS+= src/spi_flash.o
WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(TARGET).o
endif
ifeq ($(EXT_FLASH),1)
@ -124,6 +126,21 @@ ifeq ($(VTOR),0)
CFLAGS+=-DNO_VTOR
endif
ifeq ($(WOLFTPM),1)
OBJS += lib/wolfTPM/src/tpm2.o \
lib/wolfTPM/src/tpm2_packet.o \
lib/wolfTPM/src/tpm2_tis.o \
lib/wolfTPM/src/tpm2_wrap.o \
src/ecc256_pub_key.o \
hal/spi/spi_drv_$(TARGET).o
CFLAGS+=-DWOLFTPM_SLB9670 -DWOLFTPM2_NO_WOLFCRYPT -DSIZEOF_LONG=4 -Ilib/wolfTPM \
-DMAX_COMMAND_SIZE=1024 -DMAX_RESPONSE_SIZE=1024 -DWOLFTPM2_MAX_BUFFER=1500 -DMAX_SESSION_NUM=1 -DMAX_DIGEST_BUFFER=973 \
-DWOLFTPM_SMALL_STACK
else
OBJS+=$(WOLFCRYPT_OBJS)
endif
ASFLAGS:=$(CFLAGS)
all: factory.bin

View File

@ -352,6 +352,8 @@ reset
halt
```
`openocd --file openocd.cfg`
OpenOCD can be either run in background (to allow remote GDB and monitor terminal connections), or
directly from command line, to execute terminal scripts.
@ -395,9 +397,10 @@ Use the OpenOCD configuration from the previous section to run OpenOCD.
From another console, connect using gdb, e.g.:
Add wolfboot.elf to the make.
```
arm-none-eabi-gdb
(gdb) target remote:3333
arm-none-eabi-gdb wolfboot.elf -ex "set remotetimeout 240" -ex "target extended-remote localhost:3333"
(gdb) add-symbol-file test-app/image.elf 0x08020000
(gdb) add-symbol-file wolfboot.elf 0x08000000
```

View File

@ -28,17 +28,17 @@
#include "spi_drv.h"
#include "spi_drv_stm32f4.h"
void spi_cs_off(void)
void spi_cs_off(int pin)
{
GPIOE_BSRR |= (1 << SPI_FLASH_PIN);
while(!(GPIOE_ODR & (1 << SPI_FLASH_PIN)))
GPIOE_BSRR |= (1 << pin);
while(!(GPIOE_ODR & (1 << pin)))
;
}
void spi_cs_on(void)
void spi_cs_on(int pin)
{
GPIOE_BSRR |= (1 << (SPI_FLASH_PIN + 16));
while(GPIOE_ODR & (1 << SPI_FLASH_PIN))
GPIOE_BSRR |= (1 << (pin + 16));
while(GPIOE_ODR & (1 << pin))
;
}
@ -47,15 +47,28 @@ static void spi_flash_pin_setup(void)
{
uint32_t reg;
AHB1_CLOCK_ER |= GPIOE_AHB1_CLOCK_ER;
reg = GPIOE_MODE & ~ (0x03 << (SPI_FLASH_PIN * 2));
GPIOE_MODE = reg | (1 << (SPI_FLASH_PIN * 2));
reg = GPIOE_PUPD & ~(0x03 << (SPI_FLASH_PIN * 2));
GPIOE_PUPD = reg | (0x01 << (SPI_FLASH_PIN * 2));
reg = GPIOE_OSPD & ~(0x03 << (SPI_FLASH_PIN * 2));
GPIOE_OSPD |= (0x03 << (SPI_FLASH_PIN * 2));
reg = GPIOE_MODE & ~ (0x03 << (SPI_CS_FLASH * 2));
GPIOE_MODE = reg | (1 << (SPI_CS_FLASH * 2));
reg = GPIOE_PUPD & ~(0x03 << (SPI_CS_FLASH * 2));
GPIOE_PUPD = reg | (0x01 << (SPI_CS_FLASH * 2));
reg = GPIOE_OSPD & ~(0x03 << (SPI_CS_FLASH * 2));
GPIOE_OSPD |= (0x03 << (SPI_CS_FLASH * 2));
spi_cs_off(SPI_CS_FLASH);
}
static void spi_tpm2_pin_setup(void)
{
#ifdef WOLFTPM2_NO_WOLFCRYPT
uint32_t reg;
AHB1_CLOCK_ER |= GPIOE_AHB1_CLOCK_ER;
reg = GPIOE_MODE & ~ (0x03 << (SPI_CS_TPM * 2));
GPIOE_MODE = reg | (1 << (SPI_CS_TPM * 2));
reg = GPIOE_PUPD & ~(0x03 << (SPI_CS_TPM * 2));
GPIOE_PUPD = reg | (0x01 << (SPI_CS_TPM * 2));
reg = GPIOE_OSPD & ~(0x03 << (SPI_CS_TPM * 2));
GPIOE_OSPD |= (0x03 << (SPI_CS_TPM * 2));
spi_cs_off(SPI_CS_TPM);
#endif
}
static void spi1_pins_setup(void)
@ -98,8 +111,8 @@ static void spi_pins_release(void)
GPIOB_PUPD &= ~ (0x03 << (SPI1_MISO_PIN * 2));
/* Release CS */
GPIOE_MODE &= ~ (0x03 << (SPI_FLASH_PIN * 2));
GPIOE_PUPD &= ~ (0x03 << (SPI_FLASH_PIN * 2));
GPIOE_MODE &= ~ (0x03 << (SPI_CS_FLASH * 2));
GPIOE_PUPD &= ~ (0x03 << (SPI_CS_TPM * 2));
/* Disable GPIOB+GPIOE clock */
AHB1_CLOCK_ER &= ~(GPIOB_AHB1_CLOCK_ER | GPIOE_AHB1_CLOCK_ER);
@ -136,13 +149,18 @@ void spi_write(const char byte)
void spi_init(int polarity, int phase)
{
spi1_pins_setup();
spi_flash_pin_setup();
APB2_CLOCK_ER |= SPI1_APB2_CLOCK_ER_VAL;
spi1_reset();
SPI1_CR1 = SPI_CR1_MASTER | (5 << 3) | (polarity << 1) | (phase << 0);
SPI1_CR2 |= SPI_CR2_SSOE;
SPI1_CR1 |= SPI_CR1_SPI_EN;
static int initialized = 0;
if (!initialized) {
initialized++;
spi1_pins_setup();
spi_flash_pin_setup();
spi_tpm2_pin_setup();
APB2_CLOCK_ER |= SPI1_APB2_CLOCK_ER_VAL;
spi1_reset();
SPI1_CR1 = SPI_CR1_MASTER | (5 << 3) | (polarity << 1) | (phase << 0);
SPI1_CR2 |= SPI_CR2_SSOE;
SPI1_CR1 |= SPI_CR1_SPI_EN;
}
}
void spi_release(void)

View File

@ -4,7 +4,8 @@
/** SPI settings **/
#define SPI1 (0x40013000)/* SPI1 base address */
#define SPI_FLASH_PIN 1 /* Flash CS connected to GPIOE1 */
#define SPI_CS_FLASH 3 /* Flash CS connected to GPIOE1 */
#define SPI_CS_TPM 1 /* TPM CS connected to GPIOE0 */
#define SPI1_PIN_AF 5 /* Alternate function for SPI pins */
#define SPI1_CLOCK_PIN 3 /* SPI_SCK: PB3 */
#define SPI1_MISO_PIN 4 /* SPI_MISO PB4 */

View File

@ -47,5 +47,7 @@
# error "No public key available for given signing algorithm."
#endif /* Algorithm selection */
#ifdef WOLFTPM2_NO_WOLFCRYPT
int wolfBoot_tpm2_init(void);
#endif
#endif /* LOADER_H */

View File

@ -30,11 +30,14 @@
#define SPI_DRV_H_INCLUDED
#include <stdint.h>
#ifdef PLATFORM_stm32f4
#include "hal/spi/spi_drv_stm32f4.h"
#endif
void spi_init(int polarity, int phase);
void spi_write(const char byte);
uint8_t spi_read(void);
void spi_cs_on(void);
void spi_cs_off(void);
void spi_cs_on(int pin);
void spi_cs_off(int pin);
#endif /* !SPI_DRV_H_INCLUDED */

1
lib/wolfTPM 160000

@ -0,0 +1 @@
Subproject commit b37ac1d98aa4834ca1779051409032b39d206fdf

View File

@ -22,7 +22,9 @@
#include "loader.h"
#include "image.h"
#include "hal.h"
#include "spi_drv.h"
#ifndef WOLFTPM2_NO_WOLFCRYPT
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/sha256.h>
@ -49,6 +51,7 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
}
return 0;
}
#endif /* WOLFBOOT_SIGN_ED25519 */
#ifdef WOLFBOOT_SIGN_ECC256
@ -66,6 +69,7 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
/* Failed to initialize key */
return -1;
}
/* Import public key */
ret = wc_ecc_import_unsigned(&ecc, (byte*)KEY_BUFFER, (byte*)(KEY_BUFFER + 32), NULL, ECC_SECP256R1);
if ((ret < 0) || ecc.type != ECC_PUBLICKEY) {
@ -111,7 +115,7 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
/* Failed to import rsa key */
return -1;
}
ret = wc_RsaSSL_Verify(sig, RSA_SIG_SIZE, digest_out, RSA_SIG_SIZE, &rsa);
ret = wc_RsaSSL_Verify(sig, RSA_SIG_SIZE, digest_out, RSA_SIG_SIZE, &rsa);
if (ret == SHA256_DIGEST_SIZE) {
if (memcmp(digest_out, hash, ret) == 0)
return 0;
@ -120,6 +124,18 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
}
#endif /* WOLFBOOT_SIGN_RSA2048 */
#else
#include <stdlib.h>
#include <string.h>
#include "wolftpm/tpm2.h"
#include "wolftpm/tpm2_wrap.h"
static WOLFTPM2_DEV wolftpm_dev;
#define SHA256_BLOCK_SIZE 16
#define SHA256_DIGEST_SIZE 32
#endif /* WOLFTPM2_NO_WOLFCRYPT */
static uint16_t get_header_ext(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr);
static uint16_t get_header(struct wolfBoot_image *img, uint16_t type, uint8_t **ptr)
@ -179,6 +195,7 @@ static uint8_t *get_img_hdr(struct wolfBoot_image *img)
return (uint8_t *)(img->hdr);
}
#ifndef WOLFTPM2_NO_WOLFCRYPT
static int image_hash(struct wolfBoot_image *img, uint8_t *hash)
{
uint8_t *stored_sha, *end_sha;
@ -234,6 +251,141 @@ static void key_hash(uint8_t *hash)
wc_Sha256Final(&sha256_ctx, hash);
}
#else /* WOLFTPM2_NO_WOLFCRYPT */
static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
word16 xferSz, void* userCtx)
{
(void)userCtx;
(void)ctx;
word16 i;
spi_cs_on(SPI_CS_TPM);
memset(rxBuf, 0, xferSz);
for (i = 0; i < xferSz; i++)
{
spi_write(txBuf[i]);
rxBuf[i] = spi_read();
}
spi_cs_off(SPI_CS_TPM);
/*
printf("\r\nSPI TX: ");
printbin(txBuf, xferSz);
printf("SPI RX: ");
printbin(rxBuf, xferSz);
printf("\r\n");
*/
return 0;
}
#define ECC_INT_SIZE 32
static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
{
int rc;
int curve_id = TPM_ECC_NIST_P256;
WOLFTPM2_KEY tpmKey;
/* Load public key into TPM */
rc = wolfTPM2_LoadEccPublicKey(&wolftpm_dev, &tpmKey, TPM_ECC_NIST_P256,
KEY_BUFFER, ECC_INT_SIZE,
KEY_BUFFER + ECC_INT_SIZE, ECC_INT_SIZE);
if (rc < 0)
return -1;
rc = wolfTPM2_VerifyHash(&wolftpm_dev, &tpmKey, sig, 2 * ECC_INT_SIZE, hash, SHA256_DIGEST_SIZE);
wolfTPM2_UnloadHandle(&wolftpm_dev, &tpmKey.handle);
if (rc < 0)
return -1;
return 0;
}
int wolfBoot_tpm2_init(void)
{
int rc;
word32 idx;
WOLFTPM2_CAPS caps;
spi_init(0,0);
/* Init the TPM2 device */
rc = wolfTPM2_Init(&wolftpm_dev, TPM2_IoCb, NULL);
if (rc != 0) {
return rc;
}
/* Get device capabilities + options */
rc = wolfTPM2_GetCapabilities(&wolftpm_dev, &caps);
if (rc != 0) {
return rc;
}
return 0;
}
static void key_hash(uint8_t *hashBuf)
{
int blksz, rc;
unsigned int i = 0;
const char gUsageAuth[]="wolfBoot TPM Usage Auth";
uint32_t hashSz = SHA256_DIGEST_SIZE;
WOLFTPM2_HASH hash;
XMEMSET(&hash, 0, sizeof(hash));
rc = wolfTPM2_HashStart(&wolftpm_dev, &hash, TPM_ALG_SHA256,
(const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
if (rc != 0)
return;
while(i < KEY_LEN)
{
blksz = SHA256_BLOCK_SIZE;
if ((i + blksz) > KEY_LEN)
blksz = KEY_LEN - i;
wolfTPM2_HashUpdate(&wolftpm_dev, &hash, KEY_BUFFER + i, blksz);
i += blksz;
}
wolfTPM2_HashFinish(&wolftpm_dev, &hash, hashBuf, &hashSz);
}
static int image_hash(struct wolfBoot_image *img, uint8_t *hashBuf)
{
const char gUsageAuth[]="wolfBoot TPM Usage Auth";
uint8_t *stored_sha, *end_sha;
uint8_t stored_sha_len;
uint8_t *p;
int blksz;
uint32_t position = 0;
WOLFTPM2_HASH hash;
uint32_t hashSz = SHA256_DIGEST_SIZE;
int rc;
if (!img)
return -1;
p = get_img_hdr(img);
stored_sha_len = get_header(img, HDR_SHA256, &stored_sha);
if (stored_sha_len != SHA256_DIGEST_SIZE)
return -1;
XMEMSET(&hash, 0, sizeof(hash));
rc = wolfTPM2_HashStart(&wolftpm_dev, &hash, TPM_ALG_SHA256,
(const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
if (rc != 0)
return -1;
end_sha = stored_sha - 2;
while (p < end_sha) {
blksz = SHA256_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wolfTPM2_HashUpdate(&wolftpm_dev, &hash, p, blksz);
p += blksz;
}
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = SHA256_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wolfTPM2_HashUpdate(&wolftpm_dev, &hash, p, blksz);
position += blksz;
} while(position < img->fw_size);
return wolfTPM2_HashFinish(&wolftpm_dev, &hash, hashBuf, &hashSz);
}
#endif

View File

@ -360,6 +360,9 @@ int main(void)
{
hal_init();
spi_flash_probe();
#ifdef WOLFTPM2_NO_WOLFCRYPT
wolfBoot_tpm2_init();
#endif
wolfBoot_start();
while(1)
;

View File

@ -66,21 +66,21 @@ static void write_address(uint32_t address)
static uint8_t read_status(void)
{
uint8_t status;
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(RDSR);
spi_read();
spi_write(0xFF);
status = spi_read();
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
return status;
}
static void spi_cmd(uint8_t cmd)
{
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(cmd);
spi_read();
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
}
static void flash_write_enable(void)
@ -114,7 +114,7 @@ static int spi_flash_write_page(uint32_t address, const void *data, int len)
flash_write_enable();
wait_busy();
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(BYTE_WRITE);
spi_read();
write_address(address);
@ -124,7 +124,7 @@ static int spi_flash_write_page(uint32_t address, const void *data, int len)
spi_read();
len--;
} while ((address & (SPI_FLASH_PAGE_SIZE - 1)) != 0);
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
}
wait_busy();
return j;
@ -140,13 +140,13 @@ static int spi_flash_write_sb(uint32_t address, const void *data, int len)
return -1;
while (len > 0) {
flash_write_enable();
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(BYTE_WRITE);
spi_read();
write_address(address);
spi_write(buf[j]);
spi_read();
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
wait_busy();
spi_flash_read(address, &verify, 1);
if ((verify & ~(buf[j])) == 0) {
@ -169,7 +169,7 @@ uint16_t spi_flash_probe(void)
int i;
spi_init(0,0);
wait_busy();
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(MDID);
b0 = spi_read();
@ -178,7 +178,7 @@ uint16_t spi_flash_probe(void)
manuf = spi_read();
spi_write(0xFF);
product = spi_read();
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
if (manuf == 0xBF)
chip_write_mode = SST_SINGLEBYTE;
if (manuf == 0xEF)
@ -186,12 +186,12 @@ uint16_t spi_flash_probe(void)
#ifndef READONLY
spi_cmd(EWSR);
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(WRSR);
spi_read();
spi_write(0x00);
spi_read();
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
#endif
return (uint16_t)(manuf << 8 | product);
}
@ -204,11 +204,11 @@ void spi_flash_sector_erase(uint32_t address)
wait_busy();
flash_write_enable();
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(SECTOR_ERASE);
spi_read();
write_address(address);
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
wait_busy();
}
@ -217,7 +217,7 @@ int spi_flash_read(uint32_t address, void *data, int len)
uint8_t *buf = data;
int i = 0;
wait_busy();
spi_cs_on();
spi_cs_on(SPI_CS_FLASH);
spi_write(BYTE_READ);
spi_read();
write_address(address);
@ -226,7 +226,7 @@ int spi_flash_read(uint32_t address, void *data, int len)
buf[i++] = spi_read();
len--;
}
spi_cs_off();
spi_cs_off(SPI_CS_FLASH);
return i;
}

View File

@ -24,6 +24,7 @@ ifeq ($(ARCH),)
DUALBANK_SWAP=0
IMAGE_HEADER_SIZE?=256
PKA=1
WOLFTPM=0
WOLFBOOT_PARTITION_SIZE?=0x20000
WOLFBOOT_SECTOR_SIZE?=0x20000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000
@ -35,7 +36,7 @@ endif
CONFIG_VARS:= ARCH TARGET SIGN KINETIS KINETIS_CPU KINETIS_DRIVERS \
KINETIS_CMSIS FREEDOM_E_SDK STM32CUBE DEBUG VTOR CORTEX_M0 NO_ASM EXT_FLASH \
SPI_FLASH ALLOW_DOWNGRADE NVM_FLASH_WRITEONCE WOLFBOOT_VERSION V \
SPMATH RAM_CODE DUALBANK_SWAP IMAGE_HEADER_SIZE PKA \
SPMATH RAM_CODE DUALBANK_SWAP IMAGE_HEADER_SIZE PKA WOLFTPM \
WOLFBOOT_PARTITION_SIZE WOLFBOOT_SECTOR_SIZE \
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
WOLFBOOT_PARTITION_SWAP_ADDRESS