From 5134eea96a62be4dadfcc45648a2f0accfeaea85 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Sat, 13 Dec 2025 04:05:32 +0100 Subject: [PATCH 1/4] Support WOLFCRYPT_TZ and PKCS11 on nRF5340 --- config/examples/nrf5340-tz.config | 15 ++-- config/examples/nrf5340-wolfcrypt-tz.config | 79 +++++++++++++++++++++ hal/nrf5340.c | 54 +++++++++++++- hal/nrf5340.h | 31 ++++++++ include/user_settings.h | 6 +- test-app/app_nrf5340.c | 33 +++++++++ tools/scripts/nrf5340/build_flash.sh | 40 ++++++----- 7 files changed, 232 insertions(+), 26 deletions(-) create mode 100644 config/examples/nrf5340-wolfcrypt-tz.config diff --git a/config/examples/nrf5340-tz.config b/config/examples/nrf5340-tz.config index 112708a668..ccd473b48f 100644 --- a/config/examples/nrf5340-tz.config +++ b/config/examples/nrf5340-tz.config @@ -26,13 +26,16 @@ QSPI_FLASH?=1 # Flash is 4KB pages (app) WOLFBOOT_SECTOR_SIZE?=0x1000 -# Flash keyvault: 112K +# Flash keyvault: 124K WOLFBOOT_KEYVAULT_ADDRESS?=0x20000 -WOLFBOOT_KEYVAULT_SIZE?=0x1C000 - -# Flash NSC: 16K -WOLFBOOT_NSC_ADDRESS?=0x3C000 -WOLFBOOT_NSC_SIZE?=0x04000 +WOLFBOOT_KEYVAULT_SIZE?=0x1F000 + +# Flash NSC: 4K +# Note: the NSC area must be defined so that: +# - Its size is exactly 32, 64, 128, 256, 512, 1024, 2048 or 4096 bytes +# - Its end is 16K-aligned +WOLFBOOT_NSC_ADDRESS?=0x3F000 +WOLFBOOT_NSC_SIZE?=0x01000 # Application offset (reserve 256K for wolfBoot + keyvault + NSC) WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x40000 diff --git a/config/examples/nrf5340-wolfcrypt-tz.config b/config/examples/nrf5340-wolfcrypt-tz.config new file mode 100644 index 0000000000..ecb0d3cb1a --- /dev/null +++ b/config/examples/nrf5340-wolfcrypt-tz.config @@ -0,0 +1,79 @@ +ARCH?=ARM +TZEN?=1 +TARGET?=nrf5340 +SIGN?=ECC384 +HASH?=SHA384 +WOLFBOOT_VERSION?=1 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 +DELTA_UPDATES?=1 + +SPMATH?=1 +RAM_CODE?=1 + +DUALBANK_SWAP?=0 +FLAGS_HOME=0 +DISABLE_BACKUP=0 +EXT_FLASH?=1 +SPI_FLASH?=0 +QSPI_FLASH?=1 + +WOLFCRYPT_TZ?=1 +WOLFCRYPT_TZ_PKCS11?=1 + +# Flash is 4KB pages (app) +WOLFBOOT_SECTOR_SIZE?=0x1000 + +# Flash keyvault: 104K +WOLFBOOT_KEYVAULT_ADDRESS?=0x45000 +WOLFBOOT_KEYVAULT_SIZE?=0x1A000 + +# Flash NSC: 4K +# Note: the NSC area must be defined so that: +# - Its size is exactly 32, 64, 128, 256, 512, 1024, 2048 or 4096 bytes +# - Its end is 16K-aligned +WOLFBOOT_NSC_ADDRESS?=0x5F000 +WOLFBOOT_NSC_SIZE?=0x01000 + +# Application offset (reserve 384K for wolfBoot + keyvault + NSC) +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x60000 + +# Application Partition Size (640KB) +WOLFBOOT_PARTITION_SIZE?=0xA0000 + +# External Flash offset for application update (1MB) +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0 + +# External Flash offset for network update at 0x100000 (size=256KB) + +# External Flash offset for swap (4KB) +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x140000 + +V?=0 +DEBUG?=0 +DEBUG_UART?=1 +USE_GCC=1 +OPTIMIZATION_LEVEL=2 + +# Optionally wait for network core to boot before starting application core +CFLAGS_EXTRA+=-DNRF_SYNC_CORES + +# Use larger block size for swapping sectors (performance improvement) +CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 + +# Enable optional power control pin (active low) P1.00 +#CFLAGS_EXTRA+=-DQSPI_PWR_CTRL_PORT=1 -DQSPI_PWR_CTRL_PIN=0 + +# Use UART0 on P0.22 +#CFLAGS_EXTRA+=-DUART_PORT=0 -DUART_PIN=22 + +#CFLAGS_EXTRA+=-DDEBUG_FLASH +#CFLAGS_EXTRA+=-DDEBUG_QSPI=1 + +# Hard fault debugging +#CFLAGS_EXTRA+=-DDEBUG_HARDFAULT diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 282c324417..4d541c8708 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -136,7 +136,8 @@ static SharedMem_t* shm = (SharedMem_t*)&shm_shadow; #endif #ifdef TZEN -static void hal_spu_init(void) { +static void hal_spu_init(void) +{ uint8_t nsc_size_index; uint8_t region; uint8_t start_region; @@ -177,6 +178,54 @@ static void hal_spu_init(void) { ~SPU_RAMREGION_PERM_SECATTR) | SPU_RAMREGION_PERM_LOCK; } } + +#ifdef WOLFCRYPT_SECURE_MODE +void hal_trng_init(void) +{ + CRYPTOCELL_ENABLE = 1; + CC_RNG_CLK = 1; + CC_RNG_SW_RESET = 1; + + do { + CC_RNG_CLK = 1; + CC_RNG_SAMPLE_CNT = FICR_TRNG90B_ROSC1; + } while (CC_RNG_SAMPLE_CNT != FICR_TRNG90B_ROSC1); + + CC_RNG_TRNG_CONFIG = 0; + CC_RNG_NOISE_SOURCE = 1; +} + +void hal_trng_fini(void) +{ + CC_RNG_NOISE_SOURCE = 0; + CC_RNG_CLK = 0; + CC_RNG_SW_RESET = 1; + + /* TODO: it might be a bad idea to disable the whole CryptoCell engine in + * case other parts of it are used -- that is not the case right now */ + CRYPTOCELL_ENABLE = 0; +} + +int hal_trng_get_entropy(unsigned char *out, unsigned int len) +{ + unsigned int i = 0; + + while (i < len) { + while (!((CC_RNG_ISR & 0x01) && (CC_RNG_TRNG_VALID & 0x01))) {} + + uint32_t data[6]; + uint8_t *data_bytes = (uint8_t *)data; + for (unsigned int word = 0; word < 6; word++) { + data[word] = CC_RNG_EHR_DATA(word); + } + for (unsigned int byte = 0; byte < 24 && i < len; byte++) { + out[i++] = (unsigned char)data_bytes[byte]; + } + } + + return 0; +} +#endif #endif void uart_init(void) @@ -804,7 +853,8 @@ int hal_flash_protect(uint32_t start, uint32_t len) } #ifdef TZEN -static void periph_unsecure() { +static void periph_unsecure() +{ /* Unsecure both GPIO ports */ SPU_PERIPHID_PERM(GPIO_PERIPHID) &= ~SPU_PERIPHID_PERM_SECATTR; SPU_GPIOPORT_PERM(0) = 0; diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 83aaee167f..080cc3b1c9 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -451,6 +451,37 @@ void uart_write_sz(const char* c, unsigned int sz); #undef QSPI_FLASH #endif +/* CryptoCell */ +#ifdef TARGET_nrf5340_app + #define CRYPTOCELL_BASE 0x50844000 + #define CRYPTOCELL_ENABLE (*(volatile uint32_t *)(CRYPTOCELL_BASE + 0x500)) + + #define FICR_BASE 0x00FF0000 + #define FICR_TRNG90B_ROSC1 (*(volatile uint32_t *)(FICR_BASE + 0xC10)) + + #define CC_RNG_BASE 0x50845000 + #define CC_RNG_ISR (*(volatile uint32_t *)(CC_RNG_BASE + 0x104)) + #define CC_RNG_ICR (*(volatile uint32_t *)(CC_RNG_BASE + 0x108)) + #define CC_RNG_TRNG_CONFIG (*(volatile uint32_t *)(CC_RNG_BASE + 0x10C)) + #define CC_RNG_TRNG_VALID (*(volatile uint32_t *)(CC_RNG_BASE + 0x110)) + #define CC_RNG_EHR_DATA(n) (*(volatile uint32_t *)(CC_RNG_BASE + 0x114 + (n) * 0x4)) + #define CC_RNG_NOISE_SOURCE (*(volatile uint32_t *)(CC_RNG_BASE + 0x12C)) + #define CC_RNG_SAMPLE_CNT (*(volatile uint32_t *)(CC_RNG_BASE + 0x130)) + #define CC_RNG_AUTOCORR_STATISTIC (*(volatile uint32_t *)(CC_RNG_BASE + 0x134)) + #define CC_RNG_TRNG_DEBUG (*(volatile uint32_t *)(CC_RNG_BASE + 0x138)) + #define CC_RNG_SW_RESET (*(volatile uint32_t *)(CC_RNG_BASE + 0x140)) + #define CC_RNG_BUSY (*(volatile uint32_t *)(CC_RNG_BASE + 0x1B8)) + #define CC_RNG_TRNG_RESET (*(volatile uint32_t *)(CC_RNG_BASE + 0x1BC)) + #define CC_RNG_HW_FLAGS (*(volatile uint32_t *)(CC_RNG_BASE + 0x1C0)) + #define CC_RNG_CLK (*(volatile uint32_t *)(CC_RNG_BASE + 0x1C4)) + #define CC_RNG_DMA (*(volatile uint32_t *)(CC_RNG_BASE + 0x1C8)) + #define CC_RNG_DMA_ROSC_LEN (*(volatile uint32_t *)(CC_RNG_BASE + 0x1CC)) + #define CC_RNG_DMA_SRAM_ADDR (*(volatile uint32_t *)(CC_RNG_BASE + 0x1D0)) + #define CC_RNG_DMA_SAMPLES_NUM (*(volatile uint32_t *)(CC_RNG_BASE + 0x1D4)) + #define CC_RNG_WATCHDOG_VAL (*(volatile uint32_t *)(CC_RNG_BASE + 0x1D8)) + #define CC_RNG_DMA_BUSY (*(volatile uint32_t *)(CC_RNG_BASE + 0x1DC)) +#endif + /* interprocessor communication (IPC) peripheral */ #ifdef TARGET_nrf5340_app #if TZ_SECURE() diff --git a/include/user_settings.h b/include/user_settings.h index ec2cc236cd..9a82b62922 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -162,11 +162,13 @@ extern int tolower(int c); # if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFCRYPT_SECURE_MODE) || \ defined(WOLFBOOT_SIGN_SECONDARY_ECC256) # define HAVE_ECC256 -# elif defined(WOLFBOOT_SIGN_ECC384) || \ +# endif +# if defined(WOLFBOOT_SIGN_ECC384) || \ defined(WOLFBOOT_SIGN_SECONDARY_ECC384) # define HAVE_ECC384 # define WOLFSSL_SP_384 -# elif defined(WOLFBOOT_SIGN_ECC521) || \ +# endif +# if defined(WOLFBOOT_SIGN_ECC521) || \ defined(WOLFBOOT_SIGN_SECONDARY_ECC521) # define HAVE_ECC521 # define WOLFSSL_SP_521 diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c index a75b45cac9..2cece58a44 100644 --- a/test-app/app_nrf5340.c +++ b/test-app/app_nrf5340.c @@ -27,6 +27,11 @@ #include "hal/nrf5340.h" #include "printf.h" +#ifdef WOLFCRYPT_SECURE_MODE +#include "wcs/user_settings.h" +#include "wolfssl/wolfcrypt/random.h" +#endif + void gpiotoggle(uint32_t port, uint32_t pin) { uint32_t reg_val = GPIO_OUT(port); @@ -34,6 +39,31 @@ void gpiotoggle(uint32_t port, uint32_t pin) GPIO_OUTSET(port) = (~reg_val) & (1 << pin); } +#ifdef WOLFCRYPT_SECURE_MODE +static int print_random_number(void) +{ + WC_RNG rng; + int ret; + uint32_t rand; + + ret = wc_InitRng(&rng); + if (ret != 0) { + wolfBoot_printf("Failed to initialize RNG\r\n"); + return -1; + } + ret = wc_RNG_GenerateBlock(&rng, (byte *)&rand, sizeof(rand)); + if (ret != 0) { + wolfBoot_printf("Failed to generate random number\r\n"); + wc_FreeRng(&rng); + return -1; + } + wolfBoot_printf("Today's lucky number: 0x%08lX\r\n", rand); + wc_FreeRng(&rng); + + return 0; +} +#endif + void main(void) { int i; @@ -64,6 +94,9 @@ void main(void) wolfBoot_printf("Compiled: " __DATE__ ":" __TIME__ "\n"); #ifdef TZEN wolfBoot_printf("TrustZone enabled: yes\n"); +#ifdef WOLFCRYPT_SECURE_MODE + print_random_number(); +#endif #else wolfBoot_printf("TrustZone enabled: no\n"); #endif diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 175bcbb1fd..79248be398 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -54,21 +54,22 @@ while test $# -gt 0; do echo "default: build, erase and program" echo " " echo "options:" - echo "-h, --help show brief help" - echo "-c, --clean cleanup build artifacts" - echo "-b, --build build release with symbols" - echo "-tz, --trustzone" use TrustZone configuration - echo "-d, --debug build debug" - echo "-v, --verbose build verbose" - echo "--version use custom version" - echo "-e, --erase do erase of internal/external flash" - echo "-ei, --erase-int do erase of internal flash" - echo "-ee, --erase-ext do erase of external flash" - echo "-p, --program program images built" - echo "-pi, --program-int program internal image (boot)" - echo "-pe, --program-ext program external image (update)" - echo "-u, --update build update, sign and program external flash" - echo "-t, --delta build update, sign delta and program external flash" + echo "-h, --help show brief help" + echo "-c, --clean cleanup build artifacts" + echo "-b, --build build release with symbols" + echo "-tz, --trustzone" use TrustZone configuration + echo "-wtz, --wc-trustzone" use TrustZone + wolfCrypt configuration + echo "-d, --debug build debug" + echo "-v, --verbose build verbose" + echo "--version use custom version" + echo "-e, --erase do erase of internal/external flash" + echo "-ei, --erase-int do erase of internal flash" + echo "-ee, --erase-ext do erase of external flash" + echo "-p, --program program images built" + echo "-pi, --program-int program internal image (boot)" + echo "-pe, --program-ext program external image (update)" + echo "-u, --update build update, sign and program external flash" + echo "-t, --delta build update, sign delta and program external flash" exit 0 ;; -c|--clean) @@ -86,6 +87,11 @@ while test $# -gt 0; do echo "Build with TrustZone config" shift ;; + -wtz|--wolfcrypt-trustzone) + DO_WOLFCRYPT_TRUSTZONE=1 + echo "Build with TrustZone + wolfCrypt config" + shift + ;; -d|--debug) DO_BUILD=1 MAKE_ARGS+=" DEBUG=1" @@ -174,7 +180,9 @@ fi if [[ $DO_BUILD == 1 ]]; then # Build internal flash images for both cores - if [[ $DO_TRUSTZONE == 1 ]]; then + if [[ $DO_WOLFCRYPT_TRUSTZONE == 1 ]]; then + config_app=config/examples/nrf5340-wolfcrypt-tz.config + elif [[ $DO_TRUSTZONE == 1 ]]; then config_app=config/examples/nrf5340-tz.config else config_app=config/examples/nrf5340.config From 99b49fe69e8ac1dabdd6880c6ece2ce17acf6bd3 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Sat, 13 Dec 2025 04:06:58 +0100 Subject: [PATCH 2/4] Add new config to CI --- .github/workflows/test-configs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index dbc46f391f..1ce825fc6d 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -145,6 +145,12 @@ jobs: arch: arm config-file: ./config/examples/nrf5340-tz.config + nrf5340_app_wolfcrypt_tz_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/nrf5340-wolfcrypt-tz.config + nrf5340_net_test: uses: ./.github/workflows/test-build.yml with: From dd226cad0c728ab891494efa41c42a8b7a45e74b Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Mon, 15 Dec 2025 15:02:17 +0100 Subject: [PATCH 3/4] Minor cleanup --- hal/nrf5340.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 4d541c8708..8f8246ecb7 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -211,14 +211,16 @@ int hal_trng_get_entropy(unsigned char *out, unsigned int len) unsigned int i = 0; while (i < len) { - while (!((CC_RNG_ISR & 0x01) && (CC_RNG_TRNG_VALID & 0x01))) {} - uint32_t data[6]; uint8_t *data_bytes = (uint8_t *)data; - for (unsigned int word = 0; word < 6; word++) { + unsigned int word, byte; + + while (!((CC_RNG_ISR & 0x01) && (CC_RNG_TRNG_VALID & 0x01))) {} + + for (word = 0; word < 6; word++) { data[word] = CC_RNG_EHR_DATA(word); } - for (unsigned int byte = 0; byte < 24 && i < len; byte++) { + for (byte = 0; byte < 24 && i < len; byte++) { out[i++] = (unsigned char)data_bytes[byte]; } } From 26171affe0cf786674b47ee589e96040923f65df Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Mon, 15 Dec 2025 17:29:00 +0100 Subject: [PATCH 4/4] Preserve CRYPTOCELL_ENABLE; don't hardcode RNG FIFO depth --- hal/nrf5340.c | 13 +++++++------ hal/nrf5340.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 8f8246ecb7..7dce15ad8f 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -180,8 +180,11 @@ static void hal_spu_init(void) } #ifdef WOLFCRYPT_SECURE_MODE +static uint32_t cryptocell_enable_prev = 0; + void hal_trng_init(void) { + cryptocell_enable_prev = CRYPTOCELL_ENABLE; CRYPTOCELL_ENABLE = 1; CC_RNG_CLK = 1; CC_RNG_SW_RESET = 1; @@ -201,9 +204,7 @@ void hal_trng_fini(void) CC_RNG_CLK = 0; CC_RNG_SW_RESET = 1; - /* TODO: it might be a bad idea to disable the whole CryptoCell engine in - * case other parts of it are used -- that is not the case right now */ - CRYPTOCELL_ENABLE = 0; + CRYPTOCELL_ENABLE = cryptocell_enable_prev; } int hal_trng_get_entropy(unsigned char *out, unsigned int len) @@ -211,16 +212,16 @@ int hal_trng_get_entropy(unsigned char *out, unsigned int len) unsigned int i = 0; while (i < len) { - uint32_t data[6]; + uint32_t data[CC_RNG_EHR_DATA_LEN]; uint8_t *data_bytes = (uint8_t *)data; unsigned int word, byte; while (!((CC_RNG_ISR & 0x01) && (CC_RNG_TRNG_VALID & 0x01))) {} - for (word = 0; word < 6; word++) { + for (word = 0; word < CC_RNG_EHR_DATA_LEN; word++) { data[word] = CC_RNG_EHR_DATA(word); } - for (byte = 0; byte < 24 && i < len; byte++) { + for (byte = 0; byte < 4 * CC_RNG_EHR_DATA_LEN && i < len; byte++) { out[i++] = (unsigned char)data_bytes[byte]; } } diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 080cc3b1c9..d128ca9b1f 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -465,6 +465,7 @@ void uart_write_sz(const char* c, unsigned int sz); #define CC_RNG_TRNG_CONFIG (*(volatile uint32_t *)(CC_RNG_BASE + 0x10C)) #define CC_RNG_TRNG_VALID (*(volatile uint32_t *)(CC_RNG_BASE + 0x110)) #define CC_RNG_EHR_DATA(n) (*(volatile uint32_t *)(CC_RNG_BASE + 0x114 + (n) * 0x4)) + #define CC_RNG_EHR_DATA_LEN 6 #define CC_RNG_NOISE_SOURCE (*(volatile uint32_t *)(CC_RNG_BASE + 0x12C)) #define CC_RNG_SAMPLE_CNT (*(volatile uint32_t *)(CC_RNG_BASE + 0x130)) #define CC_RNG_AUTOCORR_STATISTIC (*(volatile uint32_t *)(CC_RNG_BASE + 0x134))