diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 825ec1f000..b8146025d6 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -172,6 +172,28 @@ jobs: config-file: ./config/examples/lpc55s69-tz.config board-name: lpcxpresso55s69 + lpc55s69_tz_psa_test: + uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml + with: + arch: arm + config-file: ./config/examples/lpc55s69-tz-psa.config + board-name: lpcxpresso55s69 + + lpc55s69_hwpuf_test: + uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml + with: + arch: arm + config-file: ./config/examples/lpc55s69-hwpuf.config + board-name: lpcxpresso55s69 + make-args: HWPUF=1 + + lpc55s69_benchmark_test: + uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml + with: + arch: arm + config-file: ./config/examples/lpc55s69-benchmark.config + board-name: lpcxpresso55s69 + m2354_test: uses: ./.github/workflows/test-build.yml with: diff --git a/.github/workflows/trustzone-emulator-tests.yml b/.github/workflows/trustzone-emulator-tests.yml index 34b255fb67..60b3c3be1e 100644 --- a/.github/workflows/trustzone-emulator-tests.yml +++ b/.github/workflows/trustzone-emulator-tests.yml @@ -168,3 +168,42 @@ jobs: ./tools/keytools/otp/otp-keystore-gen m33mu tools/keytools/otp/otp-keystore-primer.bin --persist --timeout 10 || true m33mu wolfboot.bin test-app/image_v1_signed.bin:0x60000 --uart-stdout --expect-bkpt 0x7f --timeout 600 --persist + + # LPC55S69 DICE attestation + HW PUF. The PUF root key is provisioned + # at first boot (WOLFBOOT_HWPUF_PROVISION=1) and used for DICE key + # derivation on subsequent boots. Requires m33mu with lpc55s69 PUF/RNG + # models (wolfboot-ci >= 1.22). + # The lpc55s69 HAL needs MCUXpresso SDK headers (fsl_common.h); same + # west-based setup as the lpc55s69 jobs in test-configs.yml. + - name: Checkout CMSIS (lpc55s69) + uses: actions/checkout@main + with: + repository: nxp-mcuxpresso/CMSIS_5 + path: CMSIS_5 + + - name: Setup MCUXpresso SDK (lpc55s69) + run: | + python3 -m venv venv + source venv/bin/activate + pip install west + west init -m https://github.com/nxp-mcuxpresso/mcuxsdk-manifests.git mcuxpresso-sdk + cd mcuxpresso-sdk + sed -i '/se_hostlib\|emwin/d' manifests/boards/lpcxpresso55s69.yml + west update_board --set board lpcxpresso55s69 + + - name: Clean and build test with DICE attestation + HW PUF (lpc55s69) + run: | + set -o pipefail + make clean distclean + cp config/examples/lpc55s69-tz-psa.config .config + sed -i 's/^HWPUF?=0/HWPUF?=1/' .config + sed -i 's/^WOLFBOOT_HWPUF_PROVISION?=0/WOLFBOOT_HWPUF_PROVISION?=1/' .config + sed -i 's/^WOLFBOOT_UDS_UID_FALLBACK_FORTEST?=1/WOLFBOOT_UDS_UID_FALLBACK_FORTEST?=0/' .config + make MCUXSDK=1 MCUXPRESSO="$GITHUB_WORKSPACE/mcuxpresso-sdk/mcuxsdk" MCUXPRESSO_CMSIS="$GITHUB_WORKSPACE/CMSIS_5/CMSIS" + m33mu wolfboot.bin test-app/image_v1_signed.bin:0x48000 --cpu lpc55s69 --uart-stdout --timeout 300 \ + | tee /tmp/m33mu-lpc55s69-dice-hwpuf.log + grep -q "Booting version:" /tmp/m33mu-lpc55s69-dice-hwpuf.log + grep -q "Checking integrity...done" /tmp/m33mu-lpc55s69-dice-hwpuf.log + grep -q "Verifying signature...done" /tmp/m33mu-lpc55s69-dice-hwpuf.log + grep -q "attest: token size" /tmp/m33mu-lpc55s69-dice-hwpuf.log + grep -q "state=0x00" /tmp/m33mu-lpc55s69-dice-hwpuf.log diff --git a/arch.mk b/arch.mk index f7c7d720ce..0d152f7fde 100644 --- a/arch.mk +++ b/arch.mk @@ -1922,6 +1922,7 @@ ifeq ($(TARGET),lpc55s69) -I$(MCUXPRESSO)/drivers/iap1 \ -I$(MCUXPRESSO)/drivers/lpc_gpio \ -I$(MCUXPRESSO)/drivers/lpc_iocon \ + -I$(MCUXPRESSO)/drivers/puf \ -I$(MCUXPRESSO)/drivers/rng_1 \ -I$(MCUXPRESSO_CMSIS)/Include \ -I$(MCUXPRESSO_CMSIS)/Core/Include @@ -1938,10 +1939,10 @@ ifeq ($(TARGET),lpc55s69) $(MCUXPRESSO)/drivers/common/fsl_common_arm.o \ $(MCUXPRESSO)/drivers/iap1/fsl_iap.o \ $(MCUXPRESSO)/drivers/lpc_gpio/fsl_gpio.o \ - $(MCUXPRESSO)/drivers/rng_1/fsl_rng.o + $(MCUXPRESSO)/drivers/rng_1/fsl_rng.o \ + $(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o ifeq ($(DEBUG_UART),1) OBJS+=\ - $(MCUXPRESSO_DRIVERS)/drivers/fsl_reset.o \ $(MCUXPRESSO)/drivers/flexcomm/fsl_flexcomm.o \ $(MCUXPRESSO)/drivers/flexcomm/usart/fsl_usart.o endif @@ -1953,6 +1954,13 @@ ifeq ($(TARGET),lpc55s69) $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/casper_port.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hashcrypt_port.o endif + ifeq ($(HWPUF),1) + CFLAGS+=-DWOLFSSL_HWPUF -DWOLFSSL_NXP_HWPUF + OBJS+=\ + $(MCUXPRESSO)/drivers/puf/fsl_puf.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hwpuf_port.o + endif endif ifeq ($(TARGET),psoc6) diff --git a/config/examples/lpc55s69-benchmark.config b/config/examples/lpc55s69-benchmark.config index 9804dedae5..c22fddd540 100644 --- a/config/examples/lpc55s69-benchmark.config +++ b/config/examples/lpc55s69-benchmark.config @@ -30,16 +30,16 @@ FLASH_MULTI_SECTOR_ERASE?=1 # Turn on or off hw acceleration of crypto algs in the lpc55s69 PKA?=0 +# Turn on or off hw puf +HWPUF?=0 -# use 1024-byte sector to accommodate RSA4096 signature -# WOLFBOOT_SECTOR_SIZE?=0x400 WOLFBOOT_SECTOR_SIZE?=0x200 # use these for test/benchmark -WOLFBOOT_PARTITION_SIZE?=0x2b000 +WOLFBOOT_PARTITION_SIZE?=0x30000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x10000 -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x3b000 -WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x66000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x40000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x70000 WOLFCRYPT_TEST?=1 WOLFCRYPT_BENCHMARK?=1 diff --git a/config/examples/lpc55s69-hwpuf.config b/config/examples/lpc55s69-hwpuf.config new file mode 100644 index 0000000000..1269bf095f --- /dev/null +++ b/config/examples/lpc55s69-hwpuf.config @@ -0,0 +1,44 @@ +ARCH?=ARM +TZEN?=0 +TARGET?=lpc55s69 +SIGN?=ECC384 +HASH?=SHA256 +MCUXSDK?=1 +MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk +MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS +MCUXPRESSO_CPU?=LPC55S69JBD100_cm33_core0 +MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/LPC/LPC5500/LPC55S69 +MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/lpcxpresso55s69/project_template +DEBUG?=0 +DEBUG_UART?=1 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=1 +NO_ARM_ASM=1 +WOLFBOOT_VERSION?=0 +V?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 +FLASH_MULTI_SECTOR_ERASE?=1 + +# Turn on or off hw acceleration of crypto algs in the lpc55s69 +PKA?=0 +# Turn on or off hw puf +HWPUF?=0 + +WOLFBOOT_SECTOR_SIZE?=0x200 + +# use these for test/benchmark +WOLFBOOT_PARTITION_SIZE?=0x30000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x10000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x40000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x70000 + +WOLFCRYPT_TEST?=1 diff --git a/config/examples/lpc55s69-tz-psa.config b/config/examples/lpc55s69-tz-psa.config new file mode 100644 index 0000000000..eb3a9e5bbf --- /dev/null +++ b/config/examples/lpc55s69-tz-psa.config @@ -0,0 +1,52 @@ +ARCH?=ARM +TZEN?=1 +TARGET?=lpc55s69 +SIGN?=ECC384 +HASH?=SHA256 +MCUXSDK?=1 +MCUXPRESSO?=$(PWD)/../NXP/mcuxpresso-sdk/mcuxsdk +MCUXPRESSO_CMSIS?=$(PWD)/../NXP/CMSIS_5/CMSIS +MCUXPRESSO_CPU?=LPC55S69JBD100_cm33_core0 +MCUXPRESSO_DRIVERS?=$(MCUXPRESSO)/devices/LPC/LPC5500/LPC55S69 +MCUXPRESSO_PROJECT_TEMPLATE?=$(MCUXPRESSO)/examples/_boards/lpcxpresso55s69/project_template +DEBUG?=0 +DEBUG_UART?=1 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=1 +NO_ARM_ASM=1 +WOLFBOOT_VERSION?=0 +V?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 +FLASH_MULTI_SECTOR_ERASE?=1 +WOLFCRYPT_TZ?=1 +WOLFCRYPT_TZ_PSA?=1 + +WOLFBOOT_ATTESTATION_TEST?=1 +WOLFBOOT_UDS_UID_FALLBACK_FORTEST?=1 + +# Turn on or off hw acceleration of crypto algs in the lpc55s69 +PKA?=0 +# Turn on or off hw puf +HWPUF?=0 +WOLFBOOT_HWPUF_PROVISION?=0 + +WOLFBOOT_SECTOR_SIZE?=0x200 + +# 200KB boot, 80KB keyvault, 8KB NSC, 56KB partitions, 512 swap +WOLFBOOT_KEYVAULT_ADDRESS?=0x10032000 +WOLFBOOT_KEYVAULT_SIZE?=0x14000 +WOLFBOOT_NSC_ADDRESS?=0x10046000 +WOLFBOOT_NSC_SIZE?=0x2000 +WOLFBOOT_PARTITION_SIZE?=0xE000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x00048000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x00056000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x00064000 diff --git a/config/examples/lpc55s69-tz.config b/config/examples/lpc55s69-tz.config index 58d4fb6f6a..6214a6f942 100644 --- a/config/examples/lpc55s69-tz.config +++ b/config/examples/lpc55s69-tz.config @@ -32,12 +32,12 @@ WOLFCRYPT_TZ_PKCS11?=1 # Turn on or off hw acceleration of crypto algs in the lpc55s69 PKA?=0 +# Turn on or off hw puf +HWPUF?=0 -# use 1024-byte sector to accommodate RSA4096 signature -# WOLFBOOT_SECTOR_SIZE?=0x400 WOLFBOOT_SECTOR_SIZE?=0x200 -# 200KB boot, 80KB keyvault, 8KB NSC, 56KB partitions, 512/1024 swap +# 200KB boot, 80KB keyvault, 8KB NSC, 56KB partitions, 512 swap WOLFBOOT_KEYVAULT_ADDRESS?=0x10032000 WOLFBOOT_KEYVAULT_SIZE?=0x14000 WOLFBOOT_NSC_ADDRESS?=0x10046000 diff --git a/config/examples/lpc55s69.config b/config/examples/lpc55s69.config index 57c6647c3f..9556b039b7 100644 --- a/config/examples/lpc55s69.config +++ b/config/examples/lpc55s69.config @@ -30,13 +30,13 @@ FLASH_MULTI_SECTOR_ERASE?=1 # Turn on or off hw acceleration of crypto algs in the lpc55s69 PKA?=0 +# Turn on or off hw puf +HWPUF?=0 -# use 1024-byte sector to accommodate RSA4096 signature -# WOLFBOOT_SECTOR_SIZE?=0x400 WOLFBOOT_SECTOR_SIZE?=0x200 # Default configuration -# 44KB boot, 52KB partitions, 512/1024 swap +# 44KB boot, 52KB partitions, 512 swap WOLFBOOT_PARTITION_SIZE?=0xB000 WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xD000 WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x18000 diff --git a/docs/Targets.md b/docs/Targets.md index 7a7710f767..53f2351517 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -3167,6 +3167,57 @@ Basic hardware acceleration supported: See [Test and Benchmark](#lpc55s69-test-and-benchmark) for a comparison with and without hardware acceleration. +### LPC55S69: Hardware PUF (HWPUF) + +wolfBoot / wolfCrypt provide support for the LPC55S69's SRAM PUF (Physically +Unclonable Function), which provides root of trust, identity, and key +generation & storage, without the need to expose keys during manufacturing. +Keys of size 128, 192, and 256 bits are supported. +To turn on HWPUF, set HWPUF=1 in the config file (see below). + +### LPC55S69: Example Configurations + +#### The following example configurations are provided: + +- [lpc55s69.config](/config/examples/lpc55s69.config): + - Both wolfBoot and the test-app live in the non-secure realm + - Set PKA=1 in the config file to turn on hardware acceleration + (off by default) + +- [lpc55s69-benchmark.config](/config/examples/lpc55s69-benchmark.config): + - Same as `lpc55s69.config`, but turns on test and benchmark code + - Set PKA=1 in the config file to turn on hardware acceleration + (off by default) + +- [lpc55s69-hwpuf.config](/config/examples/lpc55s69-hwpuf.config): + - Same as `lpc55s69.config`, but turns on test code showing how to use the + hwpuf api + - Set HWPUF=1 in the config file to turn on HWPUF support (off by default) + +- [lpc55s69-tz.config](/config/examples/lpc55s69-tz.config): + - wolfBoot lives in the secure realm, test-app lives in the non-secure realm + - Provides a standard PKCS #11 api to interface with crypto algs in the secure + realm + +- [lpc55s69-tz-psa.config](/config/examples/lpc55s69-tz-psa.config): + - wolfBoot lives in the secure realm, test-app lives in the non-secure realm + - Provides a standard PSA api to interface with crypto algs in the secure + realm + - Provides an example of PSA Attestation + - To turn on HWPUF for use with attestation, set the following in the config + file: + - WOLFBOOT_UDS_UID_FALLBACK_FORTEST=0 + - HWPUF=1 + - WOLFBOOT_HWPUF_PROVISION=1 + +#### Summary of configurables applicable to all lpc55s69 example configurations: +- `PKA` : Turn on/off hardware acceleration of crypto algs +- `HWPUF` : Turn on/off support for the hardware PUF +- `WOLFBOOT_HWPUF_PROVISION` : Turn on/off auto-provisioning of the HWPUF on +first boot. Performs PUF enrollment and generates a UDS key for device +attestation. Stores PUF keycodes in a known flash location and uses them when +necessary. + ### LPC55S69: Configuring and compiling Copy the example configuration file and build with make: @@ -3176,9 +3227,6 @@ cp config/examples/lpc55s69.config .config make ``` -We also provide a TrustZone configuration at `config/examples/lpc55s69-tz.config` -and a benchmarking configuration at `config/examples/lpc55s69-benchmark.config`. - ### LPC55S69: Loading the firmware Download and install the LinkServer tool: diff --git a/hal/lpc55s69.c b/hal/lpc55s69.c index 7e461c3195..0e247e7690 100644 --- a/hal/lpc55s69.c +++ b/hal/lpc55s69.c @@ -28,20 +28,331 @@ #include "clock_config.h" #include "fsl_clock.h" #include "fsl_iap.h" +#include "fsl_iap_ffr.h" #include "fsl_iocon.h" +#include "fsl_puf.h" #include "fsl_reset.h" #include "fsl_rng.h" #include "fsl_usart.h" +#include "hal.h" #include "loader.h" #ifdef TZEN #include "hal/armv8m_tz.h" #endif +#include +#include +#include +#include + +#ifdef WOLFSSL_NXP_HWPUF +#include +#endif + +#if defined(WOLFCRYPT_TZ_PSA) +# if defined(WOLFBOOT_HASH_SHA256) +# include +# define HAL_KDF_HASH_TYPE WC_HASH_TYPE_SHA256 +# elif defined(WOLFBOOT_HASH_SHA384) +# include +# define HAL_KDF_HASH_TYPE WC_HASH_TYPE_SHA384 +# elif defined(WOLFBOOT_HASH_SHA3_384) +# include +# define HAL_KDF_HASH_TYPE WC_HASH_TYPE_SHA3_384 +# else +# error "No supported hash type for HAL_KDF" +# endif +#endif + static flash_config_t pflash; static const uint32_t pflash_page_size = 512U; uint32_t SystemCoreClock; /* set in clock_config.c */ +static void flashInit(void) +{ + static int initialized = 0; + + if (!initialized) { + XMEMSET(&pflash, 0, sizeof(pflash)); + FLASH_Init(&pflash); + FFR_Init(&pflash); + initialized = 1; + } +} + +static NOINLINEFUNCTION void hal_zeroize(void *ptr, size_t len) +{ + volatile uint8_t *p = (volatile uint8_t *)ptr; + while (len-- > 0U) { + *p++ = 0U; + } +} + + +#if defined(__WOLFBOOT) && defined(WOLFSSL_HWPUF) +#define HWPUF_PROV_MAGIC 0x564f5250ul /* "PROV" */ +#define HWPUF_PROV_FLASH_BASEADR 0x80000ul +#define HWPUF_PROV_FLASH_LEN 0x1000ul +#define HWPUF_PROV_UDS_KEY_INDEX 14 /* NOT the one in PFR */ +#define HWPUF_PROV_UDS_KEY_SIZE 32 + +typedef struct hwpuf_prov { + word32 magic; + byte ac[PUF_ACTIVATION_CODE_SIZE]; + byte uds_kc[PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(HWPUF_PROV_UDS_KEY_SIZE)]; +} hwpuf_prov; + +static hwpuf_prov prov; + +static int hwpuf_provision_get(void) +{ + if (sizeof(prov) > HWPUF_PROV_FLASH_LEN) + return -1; + + flashInit(); + + /* verify none of sectors in erased state */ + { + uint32_t addr; + uint32_t start = HWPUF_PROV_FLASH_BASEADR; + uint32_t end = HWPUF_PROV_FLASH_BASEADR + HWPUF_PROV_FLASH_LEN; + + for (addr = start; addr < end; addr += pflash_page_size) { + if (FLASH_VerifyErase(&pflash, addr, pflash_page_size) + == kStatus_FLASH_Success) { + return -1; + } + } + } + + XMEMCPY(&prov, (byte *)HWPUF_PROV_FLASH_BASEADR, sizeof(prov)); + + if (prov.magic != HWPUF_PROV_MAGIC) + return -1; + + return 0; +} + +#ifdef WOLFBOOT_HWPUF_PROVISION +static int hwpuf_provision_set(int force) +{ + int ret = -1; + + if (sizeof(prov) > HWPUF_PROV_FLASH_LEN) + return -1; + + if (!force) { + if (hwpuf_provision_get() == 0) + return -1; + } + + XMEMSET(&prov, 0, sizeof(prov)); + + if (nxp_hwpuf_RegisterDevice() != 0) + return -1; + + if (wc_CryptoCb_HwpufInit(WOLFSSL_NXP_HWPUF_DEVID) != 0) + goto error_out; + + if (wc_CryptoCb_HwpufEnroll(WOLFSSL_NXP_HWPUF_DEVID, prov.ac, sizeof(prov.ac)) != 0) + goto error_out; + + (void)wc_CryptoCb_HwpufDeinit(WOLFSSL_NXP_HWPUF_DEVID); + (void)wc_CryptoCb_HwpufInit(WOLFSSL_NXP_HWPUF_DEVID); + + if (wc_CryptoCb_HwpufStart(WOLFSSL_NXP_HWPUF_DEVID, prov.ac, sizeof(prov.ac)) != 0) + goto error_out; + + if (wc_CryptoCb_HwpufGenerateKey(WOLFSSL_NXP_HWPUF_DEVID, + HWPUF_PROV_UDS_KEY_INDEX, HWPUF_PROV_UDS_KEY_SIZE, + prov.uds_kc, sizeof(prov.uds_kc)) != 0) + goto error_out; + + prov.magic = HWPUF_PROV_MAGIC; + + flashInit(); + + hal_flash_unlock(); + ret = hal_flash_erase(HWPUF_PROV_FLASH_BASEADR, HWPUF_PROV_FLASH_LEN); + if (ret != 0) { + hal_flash_lock(); + goto error_out; + } + ret = hal_flash_write(HWPUF_PROV_FLASH_BASEADR, + (const uint8_t *)&prov, sizeof(prov)); + hal_flash_lock(); + if (ret != 0) + goto error_out; + + ret = 0; + +error_out: + hal_zeroize(&prov, sizeof(prov)); + (void)wc_CryptoCb_HwpufZeroize(WOLFSSL_NXP_HWPUF_DEVID); + (void)wc_CryptoCb_HwpufDeinit(WOLFSSL_NXP_HWPUF_DEVID); + (void)nxp_hwpuf_UnregisterDevice(); + return ret; +} +#endif /* WOLFBOOT_HWPUF_PROVISION */ + +#if defined(WOLFCRYPT_TZ_PSA) +static int uds_from_hwpuf(uint8_t *out, size_t out_len) +{ + int ret = -1; + byte uds[HWPUF_PROV_UDS_KEY_SIZE]; + + if (hwpuf_provision_get() != 0) + return -1; + + if (nxp_hwpuf_RegisterDevice() != 0) + return -1; + + if (wc_CryptoCb_HwpufInit(WOLFSSL_NXP_HWPUF_DEVID) != 0) + goto error_out; + + if (wc_CryptoCb_HwpufStart(WOLFSSL_NXP_HWPUF_DEVID, prov.ac, sizeof(prov.ac)) != 0) + goto error_out; + + ret = wc_CryptoCb_HwpufGetKey(WOLFSSL_NXP_HWPUF_DEVID, prov.uds_kc, sizeof(prov.uds_kc), + uds, sizeof(uds)); + if (ret != 0) + goto error_out; + + ret = wc_HKDF_ex((int)HAL_KDF_HASH_TYPE, uds, (word32)sizeof(uds), + (const byte *)"WOLFBOOT-UDS", (word32)12, + (const byte *)"WOLFBOOT-UDS", (word32)12, + (byte *)out, (word32)out_len, + NULL, INVALID_DEVID); + if (ret != 0) + goto error_out; + +error_out: + hal_zeroize(uds, sizeof(uds)); + hal_zeroize(&prov, sizeof(prov)); + (void)wc_CryptoCb_HwpufZeroize(WOLFSSL_NXP_HWPUF_DEVID); + (void)wc_CryptoCb_HwpufDeinit(WOLFSSL_NXP_HWPUF_DEVID); + (void)nxp_hwpuf_UnregisterDevice(); + return ret == 0 ? 0 : -1; +} +#endif /* WOLFCRYPT_TZ_PSA */ +#endif /* __WOLFBOOT && WOLFSSL_HWPUF */ + +#if defined(__WOLFBOOT) && defined(WOLFCRYPT_TZ_PSA) +static void reverse_array(byte *s, int len) +{ + int up, dn; + + if (s == NULL) + return; + + up = 0; + dn = len - 1; + while (up < dn) { + byte t = s[up]; + s[up] = s[dn]; + s[dn] = t; + ++up; + --dn; + } +} +#endif + +#if defined(__WOLFBOOT) && defined(WOLFCRYPT_TZ_PSA) && !defined(WOLFBOOT_DICE_HW) +#ifdef WOLFBOOT_UDS_UID_FALLBACK_FORTEST +static int uds_from_uid(uint8_t *out, size_t out_len) +{ + uint8_t uid[16]; +#if defined(WOLFBOOT_HASH_SHA256) + uint8_t digest[SHA256_DIGEST_SIZE]; +#elif defined(WOLFBOOT_HASH_SHA384) + uint8_t digest[SHA384_DIGEST_SIZE]; +#elif defined(WOLFBOOT_HASH_SHA3_384) + uint8_t digest[SHA3_384_DIGEST_SIZE]; +#endif + size_t copy_len = sizeof(digest); + int ret; + + flashInit(); + + if (FFR_GetUUID(&pflash, uid) != kStatus_Success) + return -1; + reverse_array(uid, sizeof(uid)); + +#if defined(WOLFBOOT_HASH_SHA256) + { + wc_Sha256 hash; + ret = wc_InitSha256(&hash); + if (ret == 0) { + ret = wc_Sha256Update(&hash, uid, sizeof(uid)); + if (ret == 0) + ret = wc_Sha256Final(&hash, digest); + wc_Sha256Free(&hash); + } + } +#elif defined(WOLFBOOT_HASH_SHA384) + { + wc_Sha384 hash; + ret = wc_InitSha384(&hash); + if (ret == 0) { + ret = wc_Sha384Update(&hash, uid, sizeof(uid)); + if (ret == 0) + ret = wc_Sha384Final(&hash, digest); + wc_Sha384Free(&hash); + } + } +#elif defined(WOLFBOOT_HASH_SHA3_384) + { + wc_Sha3 hash; + ret = wc_InitSha3_384(&hash, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha3_384_Update(&hash, uid, sizeof(uid)); + if (ret == 0) + ret = wc_Sha3_384_Final(&hash, digest); + wc_Sha3_384_Free(&hash); + } + } +#endif + + if (ret != 0) { + wc_ForceZero(uid, sizeof(uid)); + wc_ForceZero(digest, sizeof(digest)); + return -1; + } + + if (copy_len > out_len) { + copy_len = out_len; + } + memcpy(out, digest, copy_len); +#ifdef DEBUG + { + int idx; + wolfBoot_printf("[ATTEST] UDS FORTEST:"); + for (idx = 0; idx < (int)out_len; ++idx) + wolfBoot_printf(" %02x", out[idx]); + wolfBoot_printf("\n"); + } +#endif + return 0; +} +#endif /* WOLFBOOT_UDS_UID_FALLBACK_FORTEST */ + +/* Derive UDS from hw puf, fall back to derive from uid */ +int hal_uds_derive_key(uint8_t *out, size_t out_len) +{ + if (out == NULL || out_len == 0) + return -1; + +#ifdef WOLFBOOT_UDS_UID_FALLBACK_FORTEST + return uds_from_uid(out, out_len); +#elif defined(WOLFSSL_HWPUF) + return uds_from_hwpuf(out, out_len); +#else + return -1; +#endif +} +#endif /* __WOLFBOOT && WOLFCRYPT_TZ_PSA && !WOLFBOOT_DICE_HW */ + #ifdef TZEN static void hal_sau_init(void) { @@ -55,7 +366,7 @@ static void hal_sau_init(void) 0); /* Non-secure RAM */ - sau_init_region(2, 0x20020000, 0x20027FFF, 0); + sau_init_region(2, 0x20020000, 0x2002FFFF, 0); /* Peripherals */ sau_init_region(3, 0x40000000, 0x4003FFFF, 0); @@ -121,14 +432,23 @@ void hal_init(void) #endif /* __WOLFBOOT */ #if defined(__WOLFBOOT) || !defined(TZEN) - memset(&pflash, 0, sizeof(pflash)); - FLASH_Init(&pflash); + flashInit(); hal_flash_fix_ecc(); #endif #if defined(TZEN) && !defined(NONSECURE_APP) hal_sau_init(); #endif + +#ifdef __WOLFBOOT + wolfCrypt_Init(); +#endif + +#if defined(__WOLFBOOT) && defined(WOLFBOOT_HWPUF_PROVISION) + /* Provisioning failure is non-fatal: the UID fallback still derives + * the UDS, so the boot continues. */ + (void)hwpuf_provision_set(0); +#endif } #ifdef __WOLFBOOT diff --git a/options.mk b/options.mk index cd8719d03d..605c5ebed6 100644 --- a/options.mk +++ b/options.mk @@ -1170,6 +1170,13 @@ ifeq ($(WOLFBOOT_DICE_HW),1) endif endif +ifeq ($(WOLFBOOT_HWPUF_PROVISION),1) + ifneq ($(HWPUF),1) + $(error WOLFBOOT_HWPUF_PROVISION requires HWPUF=1) + endif + CFLAGS+=-DWOLFBOOT_HWPUF_PROVISION +endif + ifeq ($(PKCS11_STORE_STATS),1) CFLAGS+=-DPKCS11_STORE_STATS endif diff --git a/src/update_flash.c b/src/update_flash.c index c25297537f..8032288e05 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -1698,7 +1698,6 @@ void RAMFUNCTION wolfBoot_start(void) WP11_Library_Init(); #endif #endif /* !WOLFBOOT_SELF_UPDATE_MONOLITHIC */ - bootRet = wolfBoot_open_image(&boot, PART_BOOT); wolfBoot_printf("Booting version: 0x%x\n", wolfBoot_get_blob_version(boot.hdr)); diff --git a/test-app/ARM-lpc55s69-ns.ld b/test-app/ARM-lpc55s69-ns.ld index aa3200f9eb..ea288a69a2 100644 --- a/test-app/ARM-lpc55s69-ns.ld +++ b/test-app/ARM-lpc55s69-ns.ld @@ -1,7 +1,10 @@ +_Min_Heap_Size = 0x00000100; /* minimal heap (not using malloc) */ +_Min_Stack_Size = 0x00008000; /* required amount of stack */ + MEMORY { FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ - RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 32K + RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 64K } SECTIONS @@ -46,13 +49,22 @@ SECTIONS _end_bss = .; _end = .; } > RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + PROVIDE ( _start_heap = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + PROVIDE ( END_STACK = . ); + PROVIDE ( _end_stack = . ); + } > RAM } _wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; _wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; _wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; _wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@; - -PROVIDE(_start_heap = _end); -PROVIDE(end = _end); -PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/Makefile b/test-app/Makefile index 7089046bd3..7e2196fa90 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -1063,6 +1063,13 @@ ifeq ($(TARGET),lpc55s69) $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/casper_port.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hashcrypt_port.o endif + ifeq ($(HWPUF),1) + CFLAGS+=-DWOLFSSL_HWPUF -DWOLFSSL_NXP_HWPUF + APP_OBJS+=\ + $(MCUXPRESSO)/drivers/puf/fsl_puf.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hwpuf_port.o + endif ifeq ($(WOLFCRYPT_SUPPORT),1) LDFLAGS+=--specs=nano.specs endif diff --git a/test-app/app_lpc55s69.c b/test-app/app_lpc55s69.c index 5bacdf98fb..72c85df307 100644 --- a/test-app/app_lpc55s69.c +++ b/test-app/app_lpc55s69.c @@ -41,6 +41,12 @@ int wolfcrypt_test(void *args); int benchmark_test(void *args); #endif +#ifdef WOLFCRYPT_TZ_PSA +#include "psa/crypto.h" +#include "psa/error.h" +#include "psa/initial_attestation.h" +#endif + #define RED_LED 6 #define GREEN_LED 7 #define BLUE_LED 4 @@ -128,6 +134,70 @@ static void check_parts( wolfBoot_printf(" update: ver=0x%lx state=0x%02x\n", *pupdate_ver, *pupdate_state); } +#if defined(WOLFBOOT_ATTESTATION_TEST) && defined(WOLFCRYPT_TZ_PSA) + +#define LINE_LEN 16 +static void print_hex(const uint8_t *buffer, uint32_t length, int dumpChars) +{ + uint32_t i, sz; + + if (!buffer) { + wolfBoot_printf("\tNULL\n"); + return; + } + + while (length > 0) { + sz = length; + if (sz > LINE_LEN) + sz = LINE_LEN; + + wolfBoot_printf("\t"); + for (i = 0; i < LINE_LEN; i++) { + if (i < sz) + wolfBoot_printf("%02x ", buffer[i]); + else + wolfBoot_printf(" "); + } + if (dumpChars) { + wolfBoot_printf("| "); + for (i = 0; i < sz; i++) { + if (buffer[i] > 31 && buffer[i] < 127) + wolfBoot_printf("%c", buffer[i]); + else + wolfBoot_printf("."); + } + } + wolfBoot_printf("\n"); + + buffer += sz; + length -= sz; + } +} + +static int run_attestation_test(void) +{ + uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64]; + uint8_t token[1024]; + size_t token_size = 0; + psa_status_t status; + size_t i; + + for (i = 0; i < sizeof(challenge); i++) { + challenge[i] = (uint8_t)i; + } + + status = psa_initial_attest_get_token(challenge, sizeof(challenge), + token, sizeof(token), &token_size); + if (status != PSA_SUCCESS) { + wolfBoot_printf("attest: get token failed (%d)\n", status); + return -1; + } + wolfBoot_printf("attest: token size %lu bytes\n", (unsigned long)token_size); + print_hex(token, (uint32_t)token_size, 1); + return 0; +} +#endif /* WOLFBOOT_ATTESTATION_TEST && WOLFCRYPT_TZ_PSA */ + void main(void) { uint32_t boot_ver, update_ver; @@ -184,6 +254,11 @@ void main(void) GPIO_PinWrite(GPIO, 1, GREEN_LED, 0); } +#if defined(WOLFBOOT_ATTESTATION_TEST) && defined(WOLFCRYPT_TZ_PSA) + if (run_attestation_test() != 0) + wolfBoot_printf("Make sure WOLFBOOT_HWPUF_PROVISION is set\n"); +#endif + #if defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK) wolfCrypt_Init(); diff --git a/tools/config.mk b/tools/config.mk index 1fad0cbab0..ae30fc149e 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -53,6 +53,8 @@ ifeq ($(ARCH),) DUALBANK_SWAP?=0 IMAGE_HEADER_SIZE?=256 PKA?=1 + HWPUF?=0 + WOLFBOOT_HWPUF_PROVISION?=0 PSOC6_CRYPTO?=1 WOLFTPM?=0 WOLFBOOT_TPM_VERIFY?=0 @@ -117,6 +119,7 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO WOLFBOOT_ATTESTATION_TEST \ WOLFBOOT_UDS_UID_FALLBACK_FORTEST \ WOLFBOOT_UDS_OBKEYS \ + HWPUF WOLFBOOT_HWPUF_PROVISION \ WOLFCRYPT_TZ WOLFCRYPT_TZ_PKCS11 \ WOLFCRYPT_TZ_PSA \ WOLFBOOT_DICE_HW \