diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index d3752fe8d5..7c3372d5ab 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -178,6 +178,20 @@ 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_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..fc22b2ebb7 100644 --- a/.github/workflows/trustzone-emulator-tests.yml +++ b/.github/workflows/trustzone-emulator-tests.yml @@ -168,3 +168,54 @@ 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) + shell: bash + 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: | + 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 + grep -q '^HWPUF?=1' .config + grep -q '^WOLFBOOT_HWPUF_PROVISION?=1' .config + grep -q '^WOLFBOOT_UDS_UID_FALLBACK_FORTEST?=0' .config + make MCUXSDK=1 MCUXPRESSO="$GITHUB_WORKSPACE/mcuxpresso-sdk/mcuxsdk" MCUXPRESSO_CMSIS="$GITHUB_WORKSPACE/CMSIS_5/CMSIS" + + # Single boot: enroll the PUF, store the record, attest. + # TODO: add a second --persist boot checking the stored record is reused + # (same UEID) once the CI image ships an m33mu with lpc55s69 --persist + # support (m33mu c2d903e, after v1.23). + - name: Run DICE attestation + HW PUF (lpc55s69) + run: | + set -o pipefail + m33mu wolfboot.bin test-app/image_v1_signed.bin:0x48000 --cpu lpc55s69 --uart-stdout --expect-bkpt 0x7f --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 + grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-lpc55s69-dice-hwpuf.log diff --git a/arch.mk b/arch.mk index 38f1c682c7..4d0002fc78 100644 --- a/arch.mk +++ b/arch.mk @@ -2121,6 +2121,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 @@ -2137,10 +2138,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 @@ -2152,6 +2153,12 @@ 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_NXP_HWPUF + OBJS+=\ + $(MCUXPRESSO)/drivers/puf/fsl_puf.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-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 c51bedc972..5d4e9f2ba4 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -3427,14 +3427,74 @@ Basic hardware acceleration supported: - AES-ECB (128, 192, 256 key sizes) - AES-CBC (128, 192, 256 key sizes) - AES-OFB (128, 192, 256 key sizes) - - Only supports full 16-byte blocks - AES-CFB (128, 192, 256 key sizes) - - Only supports full 16-byte blocks - AES-CTR (128, 192, 256 key sizes) - User must avoid counter wrap of all ff's to 0, as this fails in the hardware 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-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. +- `WOLFBOOT_HWPUF_PROV_ADDRESS` : Flash address of the 4 KB PUF provisioning +record (default `0x80000`, page aligned). The build fails if it overlaps the +boot, update or swap partition or the protected flash region (`0x9DE00` and +up), or if it lies below the boot partition (wolfBoot, keyvault and NSC). +The activation code and key code are written first and verified, then a +commit word is written in the last page of the record. Provisioning only +runs when that commit page is erased (or all `0xFF`), so a provisioning +interrupted before the commit is redone on the next boot. A record in any +other state is never silently replaced, because that would change the device +identity: attestation fails until the region is erased. This includes the +rare case where power is lost while the commit page itself is being erased or +programmed. + +`HWPUF=1` cannot be combined with `WOLFBOOT_UDS_UID_FALLBACK_FORTEST=1`. With +`TZEN=1` the PUF is reachable only from the secure world (it is excluded from +the non-secure SAU regions and is not linked into the non-secure test-app). + ### LPC55S69: Configuring and compiling Copy the example configuration file and build with make: @@ -3444,9 +3504,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..299247c8d9 100644 --- a/hal/lpc55s69.c +++ b/hal/lpc55s69.c @@ -28,23 +28,395 @@ #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" +#include "printf.h" + +#include #ifdef TZEN #include "hal/armv8m_tz.h" #endif +#ifdef WOLFSSL_NXP_HWPUF +#include +#endif + +#if defined(WOLFCRYPT_TZ_PSA) +#include + +# 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 /* WOLFCRYPT_TZ_PSA */ + 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_NXP_HWPUF) && \ + (defined(WOLFCRYPT_TZ_PSA) || defined(WOLFBOOT_HWPUF_PROVISION)) +#ifndef WOLFBOOT_HWPUF_PROV_ADDRESS +#define WOLFBOOT_HWPUF_PROV_ADDRESS 0x80000ul +#endif +#define HWPUF_PROV_MAGIC 0x564f5250ul /* "PROV" */ +#define HWPUF_PROV_FLASH_LEN 0x1000ul +#define HWPUF_PROV_PAGE_SIZE 512ul +/* The commit word lives alone in the last page of the region and is written + * only after the payload has been written and verified, so an interrupted + * provisioning never leaves a valid-looking record behind. */ +#define HWPUF_PROV_COMMIT_ADDRESS (WOLFBOOT_HWPUF_PROV_ADDRESS + \ + HWPUF_PROV_FLASH_LEN - HWPUF_PROV_PAGE_SIZE) +#define HWPUF_PROV_UDS_KEY_INDEX 14 /* NOT the one in PFR */ +#define HWPUF_PROV_UDS_KEY_SIZE 32 + +#if (WOLFBOOT_HWPUF_PROV_ADDRESS % HWPUF_PROV_PAGE_SIZE) != 0 +#error "WOLFBOOT_HWPUF_PROV_ADDRESS must be aligned to the flash page size" +#endif +#define HWPUF_PROV_OVERLAPS(base, len) \ + ((WOLFBOOT_HWPUF_PROV_ADDRESS < ((base) + (len))) && \ + ((base) < (WOLFBOOT_HWPUF_PROV_ADDRESS + HWPUF_PROV_FLASH_LEN))) +#if HWPUF_PROV_OVERLAPS(WOLFBOOT_PARTITION_BOOT_ADDRESS, WOLFBOOT_PARTITION_SIZE) +#error "WOLFBOOT_HWPUF_PROV_ADDRESS overlaps the boot partition" +#endif +#if HWPUF_PROV_OVERLAPS(WOLFBOOT_PARTITION_UPDATE_ADDRESS, WOLFBOOT_PARTITION_SIZE) +#error "WOLFBOOT_HWPUF_PROV_ADDRESS overlaps the update partition" +#endif +#if HWPUF_PROV_OVERLAPS(WOLFBOOT_PARTITION_SWAP_ADDRESS, WOLFBOOT_SECTOR_SIZE) +#error "WOLFBOOT_HWPUF_PROV_ADDRESS overlaps the swap partition" +#endif +/* wolfBoot itself, the keyvault and the NSC region sit below the boot + * partition */ +#if WOLFBOOT_HWPUF_PROV_ADDRESS < WOLFBOOT_PARTITION_BOOT_ADDRESS +#error "WOLFBOOT_HWPUF_PROV_ADDRESS must be above the wolfBoot image" +#endif +/* Protected flash region (PFR) starts at 0x9DE00 */ +#if (WOLFBOOT_HWPUF_PROV_ADDRESS + HWPUF_PROV_FLASH_LEN) > 0x9DE00ul +#error "WOLFBOOT_HWPUF_PROV_ADDRESS overlaps the protected flash region" +#endif + +typedef struct hwpuf_prov { + byte ac[PUF_ACTIVATION_CODE_SIZE]; + byte uds_kc[PUF_GET_KEY_CODE_SIZE_FOR_KEY_SIZE(HWPUF_PROV_UDS_KEY_SIZE)]; +} hwpuf_prov; + +/* The payload must end before the commit page */ +typedef char hwpuf_prov_size_check[ + (sizeof(hwpuf_prov) <= HWPUF_PROV_FLASH_LEN - HWPUF_PROV_PAGE_SIZE) ? + 1 : -1]; + +/* prov holds no secure information, so does not need aggressive zeroing */ +static hwpuf_prov prov; + +#define HWPUF_PROV_BLANK 1 + +/* Load the stored record into rec. + * Returns 0 if a committed record was loaded, HWPUF_PROV_BLANK if the commit + * page is erased or all 0xFF (never provisioned, or interrupted before the + * commit), -1 for anything else. A record in any other state may be a + * committed one that got damaged, so it is never treated as blank: that + * would silently re-enroll the PUF and change the device identity. */ +static int hwpuf_provision_get(hwpuf_prov *rec) +{ + uint32_t addr; + uint32_t end = WOLFBOOT_HWPUF_PROV_ADDRESS + + ((sizeof(*rec) + HWPUF_PROV_PAGE_SIZE - 1) & + ~(HWPUF_PROV_PAGE_SIZE - 1)); + uint32_t commit_page[HWPUF_PROV_PAGE_SIZE / sizeof(uint32_t)]; + uint32_t failed_addr, failed_data; + + flashInit(); + + /* Reading a never-programmed page faults on ECC, check before reading */ + if (FLASH_VerifyErase(&pflash, HWPUF_PROV_COMMIT_ADDRESS, + HWPUF_PROV_PAGE_SIZE) == kStatus_FLASH_Success) + return HWPUF_PROV_BLANK; + + /* A page whose programming was cut short may fail ECC as well. Compare + * through the flash controller, which reports errors instead of + * faulting, and only read the page once it matches. */ + XMEMSET(commit_page, 0xFF, sizeof(commit_page)); + /* Programmed as 0xFF by hal_flash_erase(): erased, not committed */ + if (FLASH_VerifyProgram(&pflash, HWPUF_PROV_COMMIT_ADDRESS, + HWPUF_PROV_PAGE_SIZE, (const uint8_t *)commit_page, + &failed_addr, &failed_data) == kStatus_FLASH_Success && + *(volatile uint32_t *)HWPUF_PROV_COMMIT_ADDRESS == 0xFFFFFFFFul) + return HWPUF_PROV_BLANK; + + commit_page[0] = HWPUF_PROV_MAGIC; + if (FLASH_VerifyProgram(&pflash, HWPUF_PROV_COMMIT_ADDRESS, + HWPUF_PROV_PAGE_SIZE, (const uint8_t *)commit_page, + &failed_addr, &failed_data) != kStatus_FLASH_Success) + return -1; + + if (*(volatile uint32_t *)HWPUF_PROV_COMMIT_ADDRESS != HWPUF_PROV_MAGIC) + return -1; + + for (addr = WOLFBOOT_HWPUF_PROV_ADDRESS; addr < end; + addr += HWPUF_PROV_PAGE_SIZE) { + if (FLASH_VerifyErase(&pflash, addr, HWPUF_PROV_PAGE_SIZE) + == kStatus_FLASH_Success) + return -1; + } + + XMEMCPY(rec, (const void *)WOLFBOOT_HWPUF_PROV_ADDRESS, sizeof(*rec)); + return 0; +} + +#ifdef WOLFBOOT_HWPUF_PROVISION +/* Enroll the PUF and store the record, unless one is already stored. + * Returns 0 when newly or previously provisioned, -1 otherwise. Only a blank + * region is provisioned: a damaged record is left alone (attestation fails + * until the region is erased), so the device identity never changes + * silently. */ +static int hwpuf_provision_set(void) +{ + uint32_t magic = HWPUF_PROV_MAGIC; + int ret; + + ret = hwpuf_provision_get(&prov); + if (ret != HWPUF_PROV_BLANK) + return ret; + ret = -1; + + hal_zeroize(&prov, sizeof(prov)); + + if (nxp_hwpuf_Init() != 0) + goto error_out; + + if (nxp_hwpuf_Enroll(prov.ac, sizeof(prov.ac)) != 0) + goto error_out; + + if (nxp_hwpuf_Deinit() != 0) + goto error_out; + + if (nxp_hwpuf_Init() != 0) + goto error_out; + + if (nxp_hwpuf_Start(prov.ac, sizeof(prov.ac)) != 0) + goto error_out; + + if (nxp_hwpuf_GenerateKey(HWPUF_PROV_UDS_KEY_INDEX, HWPUF_PROV_UDS_KEY_SIZE, + prov.uds_kc, sizeof(prov.uds_kc)) != 0) + goto error_out; + + flashInit(); + + hal_flash_unlock(); + if (hal_flash_erase(WOLFBOOT_HWPUF_PROV_ADDRESS, HWPUF_PROV_FLASH_LEN) != 0) + goto unlock_out; + if (hal_flash_write(WOLFBOOT_HWPUF_PROV_ADDRESS, + (const uint8_t *)&prov, sizeof(prov)) != 0) + goto unlock_out; + if (XMEMCMP((const void *)WOLFBOOT_HWPUF_PROV_ADDRESS, &prov, + sizeof(prov)) != 0) + goto unlock_out; + if (hal_flash_write(HWPUF_PROV_COMMIT_ADDRESS, + (const uint8_t *)&magic, sizeof(magic)) != 0) + goto unlock_out; + if (*(volatile uint32_t *)HWPUF_PROV_COMMIT_ADDRESS != HWPUF_PROV_MAGIC) + goto unlock_out; + + ret = 0; + +unlock_out: + hal_flash_lock(); +error_out: + (void)nxp_hwpuf_Deinit(); + 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(&prov) != 0) + return -1; + + if (nxp_hwpuf_Init() != 0) + goto error_out; + + if (nxp_hwpuf_Start(prov.ac, sizeof(prov.ac)) != 0) + goto error_out; + + ret = nxp_hwpuf_GetKey(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); + +error_out: + hal_zeroize(uds, sizeof(uds)); + (void)nxp_hwpuf_Deinit(); + return ret == 0 ? 0 : -1; +} +#endif /* WOLFCRYPT_TZ_PSA */ +#endif /* __WOLFBOOT && WOLFSSL_NXP_HWPUF && (TZ_PSA || HWPUF_PROVISION) */ + +#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) +#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) + wc_Sha256 hash; + uint8_t digest[SHA256_DIGEST_SIZE]; +#elif defined(WOLFBOOT_HASH_SHA384) + wc_Sha384 hash; + uint8_t digest[SHA384_DIGEST_SIZE]; +#elif defined(WOLFBOOT_HASH_SHA3_384) + wc_Sha3 hash; + 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) + 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) + 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) + 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) { + if (copy_len > out_len) + copy_len = out_len; + XMEMCPY(out, digest, copy_len); + } + + hal_zeroize(uid, sizeof(uid)); + hal_zeroize(digest, sizeof(digest)); + hal_zeroize(&hash, sizeof(hash)); + return ret == 0 ? 0 : -1; +} +#endif /* WOLFBOOT_UDS_UID_FALLBACK_FORTEST */ + +/* Derive UDS: from the device UID when WOLFBOOT_UDS_UID_FALLBACK_FORTEST (test + * only), otherwise from the HW PUF. There is no runtime fallback. */ +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_NXP_HWPUF) + return uds_from_hwpuf(out, out_len); +#else + return -1; +#endif +} +#endif /* __WOLFBOOT && WOLFCRYPT_TZ_PSA */ + #ifdef TZEN +/* AHB_SECURE_CTRL (AHBSC) gates SRAM at the bus level on this part: the SAU + * alone does not make an SRAM block non-secure. The boot ROM leaves every + * 4 KB block secure+privileged; hand SRAM2 (0x20020000..0x2002FFFF, the NS + * app RAM) to the NS world as non-secure+privileged before the NS jump. + * Unprivileged NS code is intentionally kept out of SRAM2: the NS test-app + * runs privileged. */ +#define AHBSC_SRAM2_RULE0 (*(volatile uint32_t *)(AHB_SECURE_CTRL_BASE + 0xA0u)) +#define AHBSC_SRAM2_RULE1 (*(volatile uint32_t *)(AHB_SECURE_CTRL_BASE + 0xA4u)) + +static void hal_ahbsc_init(void) +{ + AHBSC_SRAM2_RULE0 = 0x11111111u; /* blocks 0-7: NS + privileged */ + AHBSC_SRAM2_RULE1 = 0x11111111u; /* blocks 8-15: NS + privileged */ +} + static void hal_sau_init(void) { + hal_ahbsc_init(); + /* Non-secure callable area */ sau_init_region(0, WOLFBOOT_NSC_ADDRESS, WOLFBOOT_NSC_ADDRESS + WOLFBOOT_NSC_SIZE - 1, 1); @@ -55,12 +427,11 @@ 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); - sau_init_region(4, 0x40080000, 0x400AFFFF, 0); - sau_init_region(5, 0x40100000, 0x4010FFFF, 0); + sau_init_region(3, 0x40086000, 0x40086FFF, 0); /* uart on flexcomm0 */ + sau_init_region(4, 0x4008c000, 0x4008FFFF, 0); /* gpio for leds */ /* Enable SAU */ SAU_CTRL = SAU_INIT_CTRL_ENABLE; @@ -71,19 +442,17 @@ static void hal_sau_init(void) static void periph_unsecure(void) { - CLOCK_EnableClock(kCLOCK_Iocon); - CLOCK_EnableClock(kCLOCK_Gpio1); } -#endif +#endif /* TZEN */ static void hal_flash_fix_ecc(void) { uint8_t page_buf[512]; uint32_t addr; - uint32_t start = WOLFBOOT_PARTITION_BOOT_ADDRESS; + uint32_t start = ARCH_FLASH_OFFSET; uint32_t end = WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE; - memset(page_buf, 0xFF, sizeof(page_buf)); + XMEMSET(page_buf, 0xFF, sizeof(page_buf)); for (addr = start; addr < end; addr += pflash_page_size) { if (FLASH_VerifyErase(&pflash, addr, pflash_page_size) @@ -93,6 +462,47 @@ static void hal_flash_fix_ecc(void) } } +#ifdef __WOLFBOOT +#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */ +#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ +#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */ +#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */ +#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ +#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */ + +#define RED_LED 6 +#define GREEN_LED 7 +#define BLUE_LED 4 + +static void leds_pin_init(void) +{ + /* red output off */ + GPIO->SET[1] = 1UL << RED_LED; + GPIO->DIR[1] |= 1UL << RED_LED; + /* green output off */ + GPIO->SET[1] = 1UL << GREEN_LED; + GPIO->DIR[1] |= 1UL << GREEN_LED; + /* blue output off */ + GPIO->SET[1] = 1UL << BLUE_LED; + GPIO->DIR[1] |= 1UL << BLUE_LED; + + const uint32_t LED_PINMUX_CONFIG = (/* Pin is configured as PIO */ + IOCON_PIO_FUNC0 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + IOCON_PinMuxSet(IOCON, 1, RED_LED, LED_PINMUX_CONFIG); + IOCON_PinMuxSet(IOCON, 1, GREEN_LED, LED_PINMUX_CONFIG); + IOCON_PinMuxSet(IOCON, 1, BLUE_LED, LED_PINMUX_CONFIG); +} +#endif /* __WOLFBOOT */ extern int wc_hashcrypt_init(void); extern int wc_casper_init(void); @@ -103,6 +513,9 @@ void hal_init(void) /* lpc55s69 must run < 100 MHz for flash write/erase to work */ BOARD_BootClockFROHF96M(); + CLOCK_EnableClock(kCLOCK_Iocon); + CLOCK_EnableClock(kCLOCK_Gpio1); + # ifdef DEBUG_UART uart_init(); uart_write("lpc55s69 init\n", 14); @@ -118,17 +531,35 @@ void hal_init(void) CLOCK_EnableClock(kCLOCK_Rng); RESET_PeripheralReset(kRNG_RST_SHIFT_RSTn); RNG_Init(RNG); + + leds_pin_init(); #endif /* __WOLFBOOT */ +#if defined(WOLFSSL_NXP_HWPUF) && (defined(__WOLFBOOT) || !defined(TZEN)) + /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL: PUF_Init() won't do this */ + CLOCK_EnableClock(kCLOCK_Puf); +#endif + #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 + +#if defined(__WOLFBOOT) && \ + (defined(WOLFCRYPT_TZ_PSA) || defined(WOLFSSL_NXP_HWPUF)) + if (wolfCrypt_Init() != 0) + wolfBoot_printf("wolfCrypt_Init failed\n"); +#endif + +#if defined(__WOLFBOOT) && defined(WOLFBOOT_HWPUF_PROVISION) + /* Provisioning failure does not stop the boot, will run again next boot */ + if (hwpuf_provision_set() != 0) + wolfBoot_printf("hwpuf provision failed\n"); +#endif } #ifdef __WOLFBOOT @@ -149,7 +580,7 @@ void hal_prepare_boot(void) periph_unsecure(); #endif } -#endif +#endif /* __WOLFBOOT */ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) { @@ -167,16 +598,16 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) if (FLASH_VerifyErase(&pflash, page_addr, pflash_page_size) == kStatus_FLASH_Success) { - memset(page_buf, 0xFF, pflash_page_size); + XMEMSET(page_buf, 0xFF, pflash_page_size); } else { - memcpy(page_buf, (void *)page_addr, pflash_page_size); + XMEMCPY(page_buf, (void *)page_addr, pflash_page_size); if (FLASH_Erase(&pflash, page_addr, pflash_page_size, kFLASH_ApiEraseKey) != kStatus_FLASH_Success) return -1; } - memcpy(page_buf + offset, data, chunk); + XMEMCPY(page_buf + offset, data, chunk); if (FLASH_Program(&pflash, page_addr, page_buf, pflash_page_size) != kStatus_FLASH_Success) @@ -206,7 +637,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) if (address % pflash_page_size != 0 || len % pflash_page_size != 0) return -1; - memset(page_buf, 0xFF, sizeof(page_buf)); + XMEMSET(page_buf, 0xFF, sizeof(page_buf)); for (pos = address; pos < address + (uint32_t)len; pos += pflash_page_size) { if (FLASH_Erase(&pflash, pos, pflash_page_size, kFLASH_ApiEraseKey) @@ -238,7 +669,7 @@ int hal_trng_get_entropy(unsigned char *out, unsigned int len) return -1; } -#endif +#endif /* WOLFCRYPT_SECURE_MODE */ #define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ @@ -251,7 +682,6 @@ int hal_trng_get_entropy(unsigned char *out, unsigned int len) #ifdef DEBUG_UART void uart_init(void) { - CLOCK_EnableClock(kCLOCK_Iocon); const uint32_t port0_pin29_config = (/* Pin is configured as FC0_RXD_SDA_MOSI_DATA */ IOCON_PIO_FUNC1 | /* No addition pin function */ @@ -316,4 +746,4 @@ void uart_write(const char *buf, unsigned int sz) sz -= line_sz + 1U; } } -#endif +#endif /* DEBUG_UART */ diff --git a/lib/wolfssl b/lib/wolfssl index f99453320f..bc9c079025 160000 --- a/lib/wolfssl +++ b/lib/wolfssl @@ -1 +1 @@ -Subproject commit f99453320ff306fe5bfb10788117f18c9bfeaf6b +Subproject commit bc9c0790253382e73198689dbef57b5c5c4792a5 diff --git a/options.mk b/options.mk index ec2edff8b3..d723193c11 100644 --- a/options.mk +++ b/options.mk @@ -1190,6 +1190,22 @@ 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 ($(HWPUF),1) + ifeq ($(WOLFBOOT_UDS_UID_FALLBACK_FORTEST),1) + $(error HWPUF=1 cannot be combined with WOLFBOOT_UDS_UID_FALLBACK_FORTEST=1: the UDS would come from the public UID instead of the PUF) + endif + ifneq ($(WOLFBOOT_HWPUF_PROV_ADDRESS),) + CFLAGS+=-DWOLFBOOT_HWPUF_PROV_ADDRESS=$(WOLFBOOT_HWPUF_PROV_ADDRESS) + endif +endif + ifeq ($(PKCS11_STORE_STATS),1) CFLAGS+=-DPKCS11_STORE_STATS endif 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 103bef92d0..38fb4fc7f2 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -1197,6 +1197,15 @@ ifeq ($(TARGET),lpc55s69) $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/casper_port.o \ $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hashcrypt_port.o endif + # Under TZEN the PUF belongs to the secure world only + ifeq ($(HWPUF),1) + ifneq ($(TZEN),1) + CFLAGS+=-DWOLFSSL_NXP_HWPUF + APP_OBJS+=\ + $(MCUXPRESSO)/drivers/puf/fsl_puf.o \ + $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/hwpuf_port.o + endif + 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..1901134b6d 100644 --- a/test-app/app_lpc55s69.c +++ b/test-app/app_lpc55s69.c @@ -20,9 +20,7 @@ */ #include -#include "fsl_clock.h" #include "fsl_gpio.h" -#include "fsl_iocon.h" #include "target.h" #include "wolfboot/wolfboot.h" @@ -41,6 +39,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 @@ -62,20 +66,8 @@ static void systick_init(void) } #endif -#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */ -#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ -#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */ -#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */ -#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ -#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */ - static void leds_init(void) { -#ifndef TZEN - CLOCK_EnableClock(kCLOCK_Iocon); - CLOCK_EnableClock(kCLOCK_Gpio1); -#endif - /* red output off */ GPIO->SET[1] = 1UL << RED_LED; GPIO->DIR[1] |= 1UL << RED_LED; @@ -85,22 +77,6 @@ static void leds_init(void) /* blue output off */ GPIO->SET[1] = 1UL << BLUE_LED; GPIO->DIR[1] |= 1UL << BLUE_LED; - - const uint32_t LED_PINMUX_CONFIG = (/* Pin is configured as PIO */ - IOCON_PIO_FUNC0 | - /* Selects pull-up function */ - IOCON_PIO_MODE_PULLUP | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - IOCON_PinMuxSet(IOCON, 1, RED_LED, LED_PINMUX_CONFIG); - IOCON_PinMuxSet(IOCON, 1, GREEN_LED, LED_PINMUX_CONFIG); - IOCON_PinMuxSet(IOCON, 1, BLUE_LED, LED_PINMUX_CONFIG); } static void check_parts( @@ -128,6 +104,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 +224,17 @@ void main(void) GPIO_PinWrite(GPIO, 1, GREEN_LED, 0); } +#if defined(WOLFBOOT_ATTESTATION_TEST) && defined(WOLFCRYPT_TZ_PSA) + if (run_attestation_test() == 0) { + __asm__ volatile ("bkpt #0x7f"); + } + else { + wolfBoot_printf("attest: failed (with HWPUF=1, the PUF must have been " + "provisioned: WOLFBOOT_HWPUF_PROVISION=1)\n"); + __asm__ volatile ("bkpt #0x7e"); + } +#endif + #if defined(WOLFCRYPT_TEST) || defined(WOLFCRYPT_BENCHMARK) wolfCrypt_Init(); diff --git a/tools/config.mk b/tools/config.mk index 1fad0cbab0..94f82444ec 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -53,6 +53,9 @@ ifeq ($(ARCH),) DUALBANK_SWAP?=0 IMAGE_HEADER_SIZE?=256 PKA?=1 + HWPUF?=0 + WOLFBOOT_HWPUF_PROVISION?=0 + WOLFBOOT_HWPUF_PROV_ADDRESS?= PSOC6_CRYPTO?=1 WOLFTPM?=0 WOLFBOOT_TPM_VERIFY?=0 @@ -117,6 +120,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 WOLFBOOT_HWPUF_PROV_ADDRESS \ WOLFCRYPT_TZ WOLFCRYPT_TZ_PKCS11 \ WOLFCRYPT_TZ_PSA \ WOLFBOOT_DICE_HW \ diff --git a/tools/test.mk b/tools/test.mk index 1ca12493be..8f39c6e66c 100644 --- a/tools/test.mk +++ b/tools/test.mk @@ -1297,5 +1297,5 @@ test-size-all: LIMIT=8980 NO_ARM_ASM=1 make keysclean make clean - make test-size SIGN=ML_DSA ML_DSA_LEVEL=2 LIMIT=19862 \ + make test-size SIGN=ML_DSA ML_DSA_LEVEL=2 LIMIT=19902 \ IMAGE_SIGNATURE_SIZE=2420 IMAGE_HEADER_SIZE?=8192