Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ ifeq ($(TARGET),stm32n6)
endif
endif # TZEN=1

ifeq ($(TARGET),pic32cz)
MAIN_TARGET:=wolfboot.bin test-app/image_v1_signed.bin
endif

ifeq ($(TARGET),x86_64_efi)
MAIN_TARGET:=wolfboot.efi
endif
Expand Down Expand Up @@ -485,6 +489,14 @@ endif
ifeq ($(WOLFHSM_SERVER),1)
_DO_WH_NVMTOOL:=1
endif
# Not every wolfHSM port provisions keys from a pre-built NVM image. A HAL may
# instead install the verification key into the server's key cache at boot (see
# hal_hsm_init_connect on pic32cz), which is the only option on targets whose
# server wipes its NVM partition on startup. Those set WOLFHSM_NVM_IMAGE=0.
WOLFHSM_NVM_IMAGE?=1
ifeq ($(WOLFHSM_NVM_IMAGE),0)
_DO_WH_NVMTOOL:=
endif
# Disable NVM image generation if user-provided keys without explicit USER_NVM_INIT
# (providing USER_NVM_INIT allows users to supply keys and still generate a custom NVM image)
ifeq ($(_USER_PROVIDED_KEYS),1)
Expand Down
40 changes: 40 additions & 0 deletions arch.mk
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,46 @@ ifeq ($(ARCH),ARM)
ARCH_FLASH_OFFSET=0x08000000
CORTEX_M7=1
OBJS+=hal/pic32c.o

ifeq ($(WOLFHSM_CLIENT),1)
ifeq ($(WOLFHSM_MICROCHIP_PIC32CZ),)
$(error WOLFHSM_MICROCHIP_PIC32CZ is not set: point it at the wolfHSM \
PIC32CZ client port directory (the one containing port/))
endif

CFLAGS+=-I$(WOLFHSM_MICROCHIP_PIC32CZ) \
-DWOLFHSM_CFG_NO_SYS_TIME \
-DWOLFHSM_CFG_TRANSPORT_MEM \
-DWOLFHSM_CFG_CLIENT_ID=WOLFBOOT_WOLFHSM_CLIENT_ID \
-DPIC32CZ_CFG_SHARED_MEM_PHYS_BASE=0x20100000U \
-DPIC32CZ_CFG_SHARED_MEM_REQ_SIZE=4096 \
-DPIC32CZ_CFG_SHARED_MEM_RESP_SIZE=4096 \
'-DPIC32CZ_CFG_SHARED_MEM_TOTAL_SIZE=(PIC32CZ_CFG_SHARED_MEM_REQ_SIZE+PIC32CZ_CFG_SHARED_MEM_RESP_SIZE)'

OBJS+=$(WOLFHSM_MICROCHIP_PIC32CZ)/port/mailbox.o \
$(WOLFHSM_MICROCHIP_PIC32CZ)/port/client/czhsm_client.o \
$(WOLFHSM_MICROCHIP_PIC32CZ)/port/client/fwmetadata.o \
$(WOLFBOOT_LIB_WOLFHSM)/src/wh_transport_mem.o

# HSM server firmware. Optional: set HSM_FW_BIN to have wolfBoot load/boot
# the HSM core from it at boot; leave it unset when the firmware is already
# resident and wolfBoot must not touch it.
ifneq ($(HSM_FW_BIN),)
ifeq ($(wildcard $(HSM_FW_BIN)),)
$(error HSM_FW_BIN=$(HSM_FW_BIN) not found: build the wolfHSM server \
firmware before wolfBoot)
endif
HSM_FW_ADDR?=0x0c1c0000
HSM_FW_SIZE:=$(shell stat -c %s $(HSM_FW_BIN))
CFLAGS+=-DHSM_FW_ADDR=$(HSM_FW_ADDR) -DHSM_FW_SIZE=$(HSM_FW_SIZE)
endif

# Signing pubkey header. Optional: set HSM_PUBKEY_HEADER to have the HAL
# push the key into the HSM at boot; leave it unset when pre-provisioned.
ifneq ($(HSM_PUBKEY_HEADER),)
CFLAGS+=-DHSM_PUBKEY_HEADER='"$(HSM_PUBKEY_HEADER)"'
endif
endif
endif

ifeq ($(TARGET),pic32ck)
Expand Down
30 changes: 30 additions & 0 deletions config/examples/pic32cz-wolfHSM.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
ARCH=ARM
TARGET=pic32cz
SIGN?=ECC256
HASH?=SHA256
VTOR?=1
SPMATH?=1
NO_MPU=1
DEBUG_UART=1

WOLFHSM_CLIENT=1

# Must match the client ID the server provisions keys under.
WOLFHSM_CLIENT_ID=12

WOLFHSM_NVM_IMAGE=0

# MUST equal the czhsm-server build's WOLFHSM_CFG_COMM_DATA_LEN
WOLFHSM_CFG_COMM_DATA_LEN=1280

BOOTLOADER_PARTITION_SIZE=0x10000

HSM_FW_ADDR=0x0c1c0000

WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_SIZE=0x100000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x0c000000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0c200000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0c1ff000

DUALBANK_SWAP=1
15 changes: 15 additions & 0 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -5129,6 +5129,21 @@ The test behavior depends on whether the `DUALBANK_SWAP` feature is enabled:
- **If `DUALBANK_SWAP=1`:** The higher version of the application will be automatically selected, and LED1 will turn on.
- **If `DUALBANK_SWAP=0`:** The application version 1 will boot first. The application will trigger the update and light LED0. On the next reset, wolfBoot will update the application, boot application version 2, and turn on LED1.

### PIC32CZ with wolfHSM

On Microchip PIC32CZ CA9x devices, wolfBoot can run on the Cortex-M7 host core as
a [wolfHSM](https://www.wolfssl.com/products/wolfhsm/) client, offloading the
image digest and signature verification to the wolfHSM server running on the
Cortex-M0+ HSM core.

Currently, wolfBoot as wolfHSM for PIC32CZ is distributed as part of the wolfHSM
PIC32CZ platform release bundle, not as a standalone package. This bundle is
under NDA and is not publicly available.

For access to the PIC32CZ platform release or for more information on using
wolfBoot and wolfHSM on PIC32CZ devices, contact
[facts@wolfssl.com](mailto:facts@wolfssl.com).


## Microchip SAME51

Expand Down
1 change: 1 addition & 0 deletions docs/wolfHSM.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ wolfBoot supports using wolfHSM on the following platforms:

- wolfBoot simulator (using wolfHSM POSIX TCP transport)
- AURIX TC3xx (shared memory transport)
- Microchip PIC32CZ CA9x (shared memory transport)
- STM32H5 TrustZone (the secure-side wolfBoot hosts a wolfHSM server and exposes it to the non-secure application through a single NSC veneer; see [STM32H5 TrustZone Engine](#stm32h5-trustzone-engine) below)

Details on configuring wolfBoot to use wolfHSM on each of these platforms can be found in the wolfBoot (and wolfHSM) documentation specific to that target, with the exception of the simulator, which is documented here. The remainder of this document focuses on the generic wolfHSM-related configuration options.
Expand Down
139 changes: 139 additions & 0 deletions hal/pic32cz.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,41 @@

#include <hal/pic32c.h>

#ifdef DEBUG_UART
#include "uart_drv.h"
#endif

#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT)

/* wolfHSM */
#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_client_crypto.h"
#include "wolfhsm/wh_transport_mem.h"

/* PIC32CZ wolfHSM port (shared with the czhsm-client reference application) */
#include "port/client/czhsm_client.h"
#include "port/client/fwmetadata.h"
/* PIC32CZ_CFG_* (shared-memory window) comes from arch.mk, not a header: unlike
* the czhsm-client application, wolfBoot does not define WOLFHSM_CFG, so the
* port sources skip "pic32cz_cfg.h" and take the configuration on the command
* line instead. */

/* FCW_BASE */
#include "hal/pic32cz_registers.h"

#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn.h>

#ifndef WOLFBOOT_WOLFHSM_CLIENT_ID
#error "WOLFBOOT_WOLFHSM_CLIENT_ID is not defined. Set WOLFHSM_CLIENT_ID in your .config."
#endif

#define FCW_MUTEX (*(volatile uint32_t*)(FCW_BASE + 0x08U))
#define FCW_MUTEX_RELEASE (0x2)

#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */

#define SUPC_BASE (0x44020000U)
#define SUPC_VREGCTRL (*(volatile uint32_t *)(SUPC_BASE + 0x1CU))
#define SUPC_STATUS (*(volatile uint32_t *)(SUPC_BASE + 0x0CU))
Expand Down Expand Up @@ -88,6 +123,12 @@ void hal_init(void)
pic32_clock_pll0_init(12, 225, 1, 3);
pic32_clock_gclk_gen0(2, 1);
pic32_delay_cnt(700);
#ifdef DEBUG_UART
/* Must follow the PLL setup above: the SERCOM baud divisor assumes
* GCLK1 = PLL0/2 = 150 MHz. */
uart_init(115200, 8, 'N', 1);
uart_write("wolfBoot PIC32CZ\r\n", 18);
#endif
#if defined(TEST_FLASH)
pic32_flash_test();
while (1) {}
Expand All @@ -106,3 +147,101 @@ void hal_prepare_boot(void)
pic32_clock_reset();
#endif
}

#if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT)

/* wolfBoot's signing public key, DER encoded, as a 'hsm_pubkey_der[]' C array.
*/
#ifdef HSM_PUBKEY_HEADER
#include HSM_PUBKEY_HEADER
#endif

whClientContext hsmClientCtx = {0};

const int hsmDevIdHash = WH_DEV_ID;
const int hsmDevIdPubKey = WH_DEV_ID;

/* Key slot the verification key lives at on the server; image.c references it by
* this id (wh_Client_EccSetKeyId(hsmKeyIdPubKey)). wolfBoot either pushes the key
* here at boot (HSM_PUBKEY_HEADER) or relies on it being pre-provisioned. */
const int hsmKeyIdPubKey = 0xFF;

/*
* Boot the HSM core and connect to the wolfHSM server running on it.
*/
int hal_hsm_init_connect(void)
{
int rc;
whClientConfig cfg;

memset((void*)PIC32CZ_CFG_SHARED_MEM_PHYS_BASE, 0,
PIC32CZ_CFG_SHARED_MEM_TOTAL_SIZE);

FCW_MUTEX = FCW_MUTEX_RELEASE;

#if defined(HSM_FW_ADDR) && defined(HSM_FW_SIZE)
/* Load/boot the HSM core from the firmware image; blocks until it has booted
* and acknowledged. Skipped when HSM_FW_BIN is unset: the firmware is then
* assumed already resident and wolfBoot connects to the running server. */
rc = czhsm_load_hsm_firmware(HSM_FW_ADDR, HSM_FW_SIZE);
if (rc != 0) {
return rc;
}
#endif

rc = czhsm_setup(&cfg);
if (rc != 0) {
return rc;
}

rc = wh_Client_Init(&hsmClientCtx, &cfg);
if (rc != WH_ERROR_OK) {
return rc;
}

rc = wh_Client_CommInit(&hsmClientCtx, NULL, NULL);
if (rc != WH_ERROR_OK) {
return rc;
}

#ifdef HSM_PUBKEY_HEADER
{
ecc_key pubkey;
whKeyId keyId = (whKeyId)hsmKeyIdPubKey;
word32 idx = 0;

rc = wc_ecc_init_ex(&pubkey, NULL, INVALID_DEVID);
if (rc != 0) {
return rc;
}

rc = wc_EccPublicKeyDecode(hsm_pubkey_der, &idx, &pubkey,
(word32)sizeof(hsm_pubkey_der));
if (rc == 0) {
rc = wh_Client_EccImportKey(&hsmClientCtx, &pubkey, &keyId,
WH_NVM_FLAGS_USAGE_VERIFY, 0, NULL);
}

wc_ecc_free(&pubkey);
}
#endif /* HSM_PUBKEY_HEADER */

return rc;
}

/*
* Close the wolfHSM session before handing control to the application.
*/
int hal_hsm_disconnect(void)
{
int rc;

rc = wh_Client_CommClose(&hsmClientCtx);
if (rc != WH_ERROR_OK) {
return rc;
}

return wh_Client_Cleanup(&hsmClientCtx);
}

#endif /* WOLFBOOT_ENABLE_WOLFHSM_CLIENT */
Loading
Loading