diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 66f989613..eee92bd74 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -251,18 +251,24 @@ jobs: arch: arm config-file: ./config/examples/stm32h5-dualbank.config - stm32h5_wolfcrypt_tz: + stm32h5_tz_test: uses: ./.github/workflows/test-build.yml with: arch: arm - config-file: ./config/examples/stm32h5-wolfcrypt-tz.config + config-file: ./config/examples/stm32h5-tz.config - stm32h5_tz_dualbank_otp: + stm32h5_tz_dualbank_otp_test: uses: ./.github/workflows/test-build.yml with: arch: arm config-file: ./config/examples/stm32h5-tz-dualbank-otp.config + stm32h5_tz_dualbank_otp_lms_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/stm32h5-tz-dualbank-otp-lms.config + stm32h7_test: uses: ./.github/workflows/test-build.yml with: diff --git a/config/examples/stm32h5-tz-dualbank-otp-lms.config b/config/examples/stm32h5-tz-dualbank-otp-lms.config new file mode 100644 index 000000000..f14e7435b --- /dev/null +++ b/config/examples/stm32h5-tz-dualbank-otp-lms.config @@ -0,0 +1,37 @@ +ARCH?=ARM +TZEN?=1 +TARGET?=stm32h5 +SIGN?=LMS +HASH?=SHA256 +DEBUG?=0 +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 +WOLFBOOT_VERSION?=1 +V?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=1 +WOLFBOOT_PARTITION_SIZE?=0xC0000 +WOLFBOOT_SECTOR_SIZE?=0x2000 +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08040000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x8140000 +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF +FLAGS_HOME=0 +DISABLE_BACKUP=0 +FLASH_OTP_KEYSTORE=1 +WOLFCRYPT_TZ=1 +WOLFCRYPT_TZ_PKCS11=1 +ARMORED=1 + +LMS_LEVELS=2 +LMS_HEIGHT=5 +LMS_WINTERNITZ=8 +IMAGE_SIGNATURE_SIZE=2644 +IMAGE_HEADER_SIZE?=8192 diff --git a/config/examples/stm32h5-tz-dualbank-otp.config b/config/examples/stm32h5-tz-dualbank-otp.config index e4a13939f..0b881c67b 100644 --- a/config/examples/stm32h5-tz-dualbank-otp.config +++ b/config/examples/stm32h5-tz-dualbank-otp.config @@ -16,7 +16,7 @@ NVM_FLASH_WRITEONCE?=1 WOLFBOOT_VERSION?=1 V?=0 SPMATH?=1 -RAM_CODE?=0 +RAM_CODE?=1 DUALBANK_SWAP?=1 WOLFBOOT_PARTITION_SIZE?=0xC0000 WOLFBOOT_SECTOR_SIZE?=0x2000 @@ -28,3 +28,4 @@ DISABLE_BACKUP=0 FLASH_OTP_KEYSTORE=1 WOLFCRYPT_TZ=1 WOLFCRYPT_TZ_PKCS11=1 +ARMORED=1 \ No newline at end of file diff --git a/config/examples/stm32h5-wolfcrypt-tz.config b/config/examples/stm32h5-tz.config similarity index 100% rename from config/examples/stm32h5-wolfcrypt-tz.config rename to config/examples/stm32h5-tz.config diff --git a/docs/STM32-TZ.md b/docs/STM32-TZ.md index d16dedd91..d928760a7 100644 --- a/docs/STM32-TZ.md +++ b/docs/STM32-TZ.md @@ -27,7 +27,7 @@ non-secure domain can access wolfCrypt through a standard PKCS11 interface and use the crypto library with pre-provisioned keys that are never exposed to the non-secure domain. -### Example using STM32-L552 +### Example using STM32L552 - Copy the example configuration for STM32-L5 with support for wolfCrypt in TrustZone-M and PKCS11 interface: `cp config/examples/stm32l5-wolfcrypt-tz.config .config` @@ -117,9 +117,10 @@ STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08040000 ### Example using STM32H563 - - - Copy the example configuration for STM32-L5 with support for wolfCrypt in - TrustZone-M and PKCS11 interface: `cp config/examples/stm32l5-wolfcrypt-tz.config .config` + - Copy one of the example configurations for STM32H5 with support for TrustZone and PKCS11 to `.config`: + `cp config/examples/stm32h5-tz.config .config` + `cp config/examples/stm32h5-tz-dualbank-otp.config .config` (with Dual Bank) + `cp config/examples/stm32h5-tz-dualbank-otp-lms.config .config` (with Dual Bank and PQ LMS) - Run `make`. `wolfboot.elf` and the test applications are built as separate objects. The application is signed and stored as `test-app/image_v1_signed.bin`. diff --git a/docs/Targets.md b/docs/Targets.md index cb51adba0..bbfe6780f 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -884,7 +884,7 @@ The example configuration for this scenario is available in [/config/examples/st For a full list of all the option bytes tested with this configuration, refer to [STM32-TZ.md](/docs/STM32-TZ.md). -### Scenario 2: Trustzone Enabled, wolfCrypt as secure engine for NS applications +### Scenario 2: TrustZone Enabled, wolfCrypt as secure engine for NS applications This is similar to Scenario 1, but also includes wolfCrypt in secure mode, and that can be accessed via PKCS11 interface by non-secure applications. @@ -893,15 +893,17 @@ This option can be enabled with the `WOLFCRYPT_TZ=1` and `WOLFCRYPT_TZ_PKCS11=1` options in your configuration. This enables a PKCS11 accessible from NS domain via non-secure callables (NSC). -The example configuration for this scenario is available in [/config/examples/stm32h5-wolfcrypt-tz.config](/config/examples/stm32h5-wolfcrypt-tz.config). +The example configuration for this scenario is available in [/config/examples/stm32h5-tz.config](/config/examples/stm32h5-tz.config). For more information, see [/docs/STM32-TZ.md](/docs/STM32-TZ.md). -### Scenario 3: DUALBANK mode (Trustzone disabled) +### Scenario 3: DUALBANK mode The STM32H5 can be configured to use hardware-assisted bank swapping to facilitate the update. The configuration file to copy into `.config` is `config/examples/stm32h5-dualbank.config`. +For DUALBANK with TrustZone use `stm32h5-tz-dualbank-otp.config`. + DUALBANK configuration (Tested on NUCLEO-STM32H563ZI): BANK A: 0x08000000 to 0x080FFFFFF (1MB) diff --git a/docs/flash-OTP.md b/docs/flash-OTP.md index e3d994176..4b2bcca2f 100644 --- a/docs/flash-OTP.md +++ b/docs/flash-OTP.md @@ -1,4 +1,4 @@ -## Using One-Time Programmable (OTP) flash area for keystore +# Using One-Time Programmable (OTP) flash area for keystore Some microcontrollers provide a special area in flash memory that can only be written once and cannot be erased. @@ -9,7 +9,7 @@ key is a cryptographic key that can be freely distributed and is used to verify of the firmware update image. By storing the public keys in the OTP area, you can ensure that they are immutable and cannot be tampered with. -### Compiling wolfBoot to access OTP as keystore +## Compiling wolfBoot to access OTP as keystore To use the OTP area as a keystore, you need to compile wolfBoot with the `FLASH_OTP_KEYSTORE` option enabled. This option is disabled by default, which means that the keystore is incorporated into @@ -24,26 +24,29 @@ must be provisioned to the OTP area in a separate step, as described in the next Depending on the target device, you can either prepare a binary image of the OTP area content, or use `otp-keystore-primer` firmware to directly provision the keys on the target. -### Creating an image of the OTP area content +## Creating an image of the OTP area content It is possible to create a binary image of the content for the OTP area. The resulting file (otp.bin) can be manually provisioned using any external tool that allows writing to the target OTP area. To compile the otp-keystore-gen tool using the current keystore content: -``` +```sh make otpgen ``` And then, to create the image file `otp.bin`: -tools/keytools/otp/otp-keystore-gen + +```sh +./tools/keytools/otp/otp-keystore-gen +``` -### Directly provisioning the public keys to the OTP area (primer) +## Directly provisioning the public keys to the OTP area (primer) After enabling the `FLASH_OTP_KEYSTORE` option in your `.config` file, when you compile wolfBoot by running "make", an additional application called `otp-keystore-primer` is generated under `tools/keytools/otp`. This application is used to -provision the public keys to the OTP area. By flashing this application to the microcontroller, the public keys contained +provision the public keys to the OTP area. By flashing this application to the microcontroller, the public keys contained in your keystore (previously generated by `keygen`) are written to the OTP area. The `otp-keystore-primer` application is generated with the public keys embedded in it. The keys are retrieved from the `keystore.c` file, @@ -59,3 +62,130 @@ After generating a new `keystore.c` with the `keygen` application, you can gener > [!CAUTION] > ** Be very careful when using the `otp-keystore-primer` application. Use it at your own risk. ** + +## Examples + +### STM32H5 OTP KeyStore + +Example for NULCLEO-STM32H563ZI with TrustZone (via PKCS11), DualBank and signing with PQ LMS: + +1) Setup the configuration and key tools: + +```sh +cp config/examples/stm32h5-tz-dualbank-otp-lms.config .config +make include/target.h +make keytools +``` + +2) Generate key(s) to write to OTP + + - `./examples/keytools/keygen --lms -g 1.key -g 2.key -g 3.key -g 4.key -g 5.key` + +3) Backup the generated keys and `src/keystore.c` + - Save to safe place outside of the wolfBoot tree + +4) Set the signing key to use + + - Copy one of the generated keys to `wolfboot_signing_private_key.der` + - `cp 1.key wolfboot_signing_private_key.der` + +5) Setup the OTP keystore + + Flash the OTP keystore primer: + - Run `make otp` + - Flash `./tools/keytools/otp/otp-keystore-primer.bin` to `0x08000000` + - Disconnect the tool and hit reset button + - The primer will run and flash keystore.c to OTP and enable write protection on those blocks + + OR + + Generate OTP (otp.bin) and flash using external tool + - Run `make otpgen` + - Run `./tools/keytools/otp/otp-keystore-gen` to generate an otp.bin file + - Program otp.bin to `0x08FFF000` using external tool like STM32CubeProgrammer + +6) Verify OTP keystore + - Read memory at address `0x08FFF000` (should start with ASCII "WOLFBOOT") + - Typically use STM32CubeProgrammer for this + +7) Setup the option bytes + - User Configuration 2 -> TrustZone Enable (TZEN=0xB4) + - Bank1 - Flash Watermark area (SECWM1_START=0x00, SECWM1_END=0x1F) + - Bank2 - Flash Watermark area (SECWM2_START=0x00, SECWM2_END=0x1F) + +8) Mass erase the device + - STM32CubeProgrammer -> Full chip erase + +9) Build wolfBoot and test application using `make` + +10) Flash wolfBoot and test-app + + - Flash `wolfboot.bin` at `0x0C000000` + - Flash `test-app/image_v1_signed.bin` at `0x08040000` + +11) Disconnect and reboot, the red LED should turn on. + +12) Connect to USB UART on NUCLEO board for console + +Explore the command line (run help) + +```sh +======================== +STM32H5 wolfBoot demo Application +Copyright 2024 wolfSSL Inc +GPL v3 +Version : 0x1 +======================== + +cmd> help +help : shows this help message +info : display information about the system and partitions +success : confirm a successful update +pkcs11 : enable and test crypto calls with PKCS11 in secure mode +random : generate a random number +timestamp : print the current timestamp +benchmark : run the wolfCrypt benchmark +test : run the wolfCrypt test +update : update the firmware via XMODEM +reboot : reboot the system +``` + +13) Test Update + + - Sign a new version of the firmware: `./tools/keytools/sign --lms test-app/image.bin wolfboot_signing_private_key.der 2` + - Run "update" command on the shell and wait for xmodem transfer + - Use serial terminal that supports xmodem like "minicom" or "CoolTerm". + * Run `minicom` on `/dev/ttyACM0` and start file transfer using "CTRL+A; S" + * Select xmodem then navigate to the new signed firmware file `test-app/image_v2_signed.bin` + - During the transfer, the yellow LED will flash. + - The green LED is dim because it's sync with the UART RX + - At the end of the transfer, the new image will be in the update partition. + - Reset board to install new firmware and confirm new version number. + +Example update output: + +```sh +cmd> update +Erasing update partition...Done. +Waiting for XMODEM transfer... +....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................... + + + + +End of transfer. ret: 0 +New firmware version: 0x2 +Triggering update... +Update completed successfully. + +cmd> reboot + +======================== +STM32H5 wolfBoot demo Application +Copyright 2024 wolfSSL Inc +GPL v3 +Version : 0x2 +======================== + +cmd> +``` diff --git a/hal/stm32_tz.c b/hal/stm32_tz.c index 7f1f6534b..d4103b87b 100644 --- a/hal/stm32_tz.c +++ b/hal/stm32_tz.c @@ -48,8 +48,6 @@ static void RAMFUNCTION hal_flash_nonsecure_unlock(void) DMB(); FLASH_NS_KEYR = FLASH_KEY2; DMB(); - while ((FLASH_NS_CR & FLASH_CR_LOCK) != 0) - ; } } @@ -97,45 +95,57 @@ void hal_tz_claim_nonsecure_area(uint32_t address, int len) int page_n, reg_idx; uint32_t reg; uint32_t end = address + len; + uint32_t start_address = address; uint32_t bank = 0; int pos; if (!is_range_nonsecure(address, len)) return; + + if (address < FLASH_BANK2_BASE) { + page_n = (address - ARCH_FLASH_OFFSET) / FLASH_PAGE_SIZE; + bank = 0; + } else { + page_n = (address - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE; + bank = 1; + } +#ifdef PLATFORM_stm32h5 + /* Take into account current swap configuration */ + if ((FLASH_OPTSR_CUR & FLASH_OPTSR_SWAP_BANK) >> 31) + bank = !bank; +#endif while (address < end) { - if (address < FLASH_BANK2_BASE) { - page_n = (address - ARCH_FLASH_OFFSET) / FLASH_PAGE_SIZE; - bank = 1; - } else { - page_n = (address - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE; - bank = 2; - } reg_idx = page_n / 32; pos = page_n % 32; hal_flash_wait_complete(bank); hal_flash_clear_errors(bank); - hal_flash_nonsecure_unlock(); - if (bank == 1) + if (bank == 0) FLASH_SECBB1[reg_idx] |= ( 1 << pos); else FLASH_SECBB2[reg_idx] |= ( 1 << pos); ISB(); hal_flash_wait_complete(bank); - hal_flash_nonsecure_lock(); + address += FLASH_PAGE_SIZE; + page_n++; + } + address = start_address; + while (address < end) { /* Erase claimed non-secure page, in secure mode */ #ifndef PLATFORM_stm32h5 reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_PER | FLASH_CR_BKER | FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_MER2)); FLASH_CR = reg | ((page_n << FLASH_CR_PNB_SHIFT) | FLASH_CR_PER); #else reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | FLASH_CR_BER | FLASH_CR_PG | FLASH_CR_MER)); - FLASH_CR = reg | ((page_n << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER); + FLASH_CR = reg | ((page_n << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | (bank << 31)); #endif DMB(); + ISB(); FLASH_CR |= FLASH_CR_STRT; ISB(); hal_flash_wait_complete(bank); address += FLASH_PAGE_SIZE; + page_n++; } #ifndef PLATFORM_stm32h5 FLASH_CR &= ~FLASH_CR_PER ; @@ -150,9 +160,48 @@ void hal_tz_claim_nonsecure_area(uint32_t address, int len) #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) void hal_tz_release_nonsecure_area(void) { +#ifndef DUALBANK_SWAP int i; for (i = 0; i < FLASH_SECBB_NREGS; i++) FLASH_SECBB2[i] = 0; +#else + uint32_t addr; + int bank_swp = 0; + /* Take into account current swap configuration */ + if ((FLASH_OPTSR_CUR & FLASH_OPTSR_SWAP_BANK) >> 31) + bank_swp = 1; + + /* Bank 1 */ + for(addr = WOLFBOOT_PARTITION_BOOT_ADDRESS; + addr < FLASH_BANK2_BASE; addr += FLASH_PAGE_SIZE) { + uint32_t page_n = (addr - FLASHMEM_ADDRESS_SPACE) / FLASH_PAGE_SIZE; + uint32_t reg_idx = page_n / 32; + uint32_t pos = page_n % 32; + hal_flash_wait_complete(0); + hal_flash_clear_errors(0); + if (!bank_swp) + FLASH_SECBB1[reg_idx] &= ~( 1 << pos); + else + FLASH_SECBB2[reg_idx] &= ~( 1 << pos); + ISB(); + hal_flash_wait_complete(0); + } + /* Bank 2 */ + for(addr = WOLFBOOT_PARTITION_UPDATE_ADDRESS; + addr < FLASH_TOP; addr += FLASH_PAGE_SIZE) { + uint32_t page_n = (addr - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE; + uint32_t reg_idx = page_n / 32; + uint32_t pos = page_n % 32; + hal_flash_wait_complete(1); + hal_flash_clear_errors(1); + if (!bank_swp) + FLASH_SECBB2[reg_idx] &= ~( 1 << pos); + else + FLASH_SECBB1[reg_idx] &= ~( 1 << pos); + ISB(); + hal_flash_wait_complete(1); + } +#endif } #else #define release_nonsecure_area(...) do{}while(0) @@ -237,13 +286,14 @@ void hal_tz_sau_init(void) { uint32_t page_n = 0; /* SAU is set up before staging. Set up all areas as secure. */ + /* Non-secure callable: NSC functions area */ sau_init_region(0, 0x0C038000, 0x0C040000, 1); - /* Non-Secure: application flash area (first bank) */ + /* Secure: application flash area (first bank) */ sau_init_region(1, WOLFBOOT_PARTITION_BOOT_ADDRESS, FLASH_BANK2_BASE - 1, 0); - /* Non-Secure: application flash area (second bank) */ + /* Secure: application flash area (second bank) */ sau_init_region(2, WOLFBOOT_PARTITION_UPDATE_ADDRESS, FLASH_TOP -1, 0); /* Secure RAM regions in SRAM1/SRAM2 */ @@ -255,8 +305,11 @@ void hal_tz_sau_init(void) /* Non-secure: internal peripherals */ sau_init_region(5, 0x40000000, 0x4FFFFFFF, 0); + /* Secure mapped peripherals */ + sau_init_region(6, 0x50000000, 0x5FFFFFFF, 1); + /* Set as non-secure: OTP + RO area */ - sau_init_region(6, 0x08FFF000, 0x08FFFFFF, 0); + sau_init_region(7, 0x08FFF000, 0x08FFFFFF, 0); /* Enable SAU */ SAU_CTRL = SAU_INIT_CTRL_ENABLE; diff --git a/hal/stm32h5.c b/hal/stm32h5.c index c102234d5..14e0f5d6e 100644 --- a/hal/stm32h5.c +++ b/hal/stm32h5.c @@ -26,6 +26,27 @@ #include "hal.h" #include "hal/stm32h5.h" +#define PLL_SRC_HSE 1 + +#if TZ_SECURE() +static int is_flash_nonsecure(uint32_t address) +{ + uint32_t in_bank_offset = address & 0x000FFFFF; +#ifdef DUALBANK_SWAP + if (in_bank_offset >= (WOLFBOOT_PARTITION_BOOT_ADDRESS - FLASHMEM_ADDRESS_SPACE)) + return 1; + else + return 0; +#else + if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) + return 1; + else + return 0; +#endif +} +#endif + + static void RAMFUNCTION flash_set_waitstates(unsigned int waitstates) { uint32_t reg = FLASH_ACR; @@ -72,38 +93,42 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) int i = 0; uint32_t *src, *dst; uint32_t dword[2]; - volatile uint32_t *sr, *cr; - - cr = &FLASH_CR; - sr = &FLASH_SR; + uint32_t off = 0; + uint32_t una_len = 0; hal_flash_clear_errors(0); src = (uint32_t *)data; dst = (uint32_t *)address; #if (TZ_SECURE()) - if ( ((address < FLASH_BANK2_BASE) && (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS)) || - (address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS)) + if (is_flash_nonsecure(address)) { hal_tz_claim_nonsecure_area(address, len); - /* Convert into secure address space */ - dst = (uint32_t *)((address & (~FLASHMEM_ADDRESS_SPACE)) | FLASH_SECURE_MMAP_BASE); + } else if (((uint32_t)dst & 0x0F000000) == 0x08000000) { + /* Convert into secure address space */ + dst = (uint32_t *)((address & (~FLASHMEM_ADDRESS_SPACE)) | FLASH_SECURE_MMAP_BASE); + } #endif - while (i < len) { dword[0] = src[i >> 2]; - dword[1] = src[(i >> 2) + 1]; - *cr |= FLASH_CR_PG; + if (len > i + 1) + dword[1] = src[(i >> 2) + 1]; + else + dword[1] = 0xFFFFFFFF; + FLASH_CR |= FLASH_CR_PG; dst[i >> 2] = dword[0]; ISB(); dst[(i >> 2) + 1] = dword[1]; + ISB(); hal_flash_wait_complete(0); - if ((*sr & FLASH_SR_EOP) != 0) - *sr |= FLASH_SR_EOP; - *cr &= ~FLASH_CR_PG; + if ((FLASH_SR & FLASH_SR_EOP) != 0) + FLASH_SR |= FLASH_SR_EOP; + FLASH_CR &= ~FLASH_CR_PG; i+=8; } #if (TZ_SECURE()) - hal_tz_release_nonsecure_area(); + if (is_flash_nonsecure(address)) { + hal_tz_release_nonsecure_area(); + } #endif return 0; } @@ -151,6 +176,7 @@ void RAMFUNCTION hal_flash_opt_lock(void) } + int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { uint32_t end_address; @@ -170,22 +196,24 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) uint32_t bnksel = 0; base = FLASHMEM_ADDRESS_SPACE; reg = FLASH_CR & (~((FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT) | FLASH_CR_BER)); - if(p >= (FLASH_BANK2_BASE) && (p <= (FLASH_TOP) )) { -#if TZ_SECURE() - /* When in secure mode, skip erasing non-secure pages: will be erased upon claim */ - return 0; -#endif base = FLASH_BANK2_BASE; bnksel = 1; - } else { - FLASH_CR &= ~FLASH_CR_SER ; - return 0; /* Address out of range */ } + +#if TZ_SECURE() + /* When in secure mode, skip erasing non-secure pages: will be erased upon claim */ + if (is_flash_nonsecure(address)) { + return 0; + } +#endif + /* Check for swapped banks to invert bnksel */ + if ((FLASH_OPTSR_CUR & FLASH_OPTSR_SWAP_BANK) >> 31) + bnksel = !bnksel; reg |= ((((p - base) >> 13) << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | (bnksel << 31)); FLASH_CR = reg; - DMB(); + ISB(); FLASH_CR |= FLASH_CR_STRT; hal_flash_wait_complete(0); } @@ -201,16 +229,26 @@ static void clock_pll_off(void) /* Select HSI as SYSCLK source. */ RCC_CFGR1 &= ~(0x07 << RCC_CFGR1_SW_SHIFT); DMB(); + /* Turn off PLL1 */ - RCC_PLL1CFGR &= ~RCC_PLL1CFGR_PLL1PEN; + RCC_PLL1CFGR &= ~RCC_PLLCFGR_PLL1PEN; DMB(); RCC_CR &= ~RCC_CR_PLL1ON; DMB(); - /* Wait until PLL1 is disabled */ while ((RCC_CR & RCC_CR_PLL1RDY) != 0) ; + /* Turn off PLL2 */ + RCC_PLL2CFGR &= ~RCC_PLLCFGR_PLLPEN; + DMB(); + RCC_CR &= ~RCC_CR_PLL2ON; + DMB(); + /* Wait until PLL2 is disabled */ + while ((RCC_CR & RCC_CR_PLL2RDY) != 0) + ; + + } /*This implementation will setup MSI 48 MHz as PLL Source Mux, PLLCLK as System Clock Source*/ @@ -220,14 +258,30 @@ static void clock_pll_on(void) uint32_t reg32; uint32_t plln, pllm, pllq, pllp, pllr, hpre, apb1pre, apb2pre, apb3pre, flash_waitstates; - /* Select clock parameters (CPU Speed = 125 MHz) */ + +#if PLL_SRC_HSE pllm = 4; - plln = 125; /* TODO: increase to 250 MHz */ + plln = 250; pllp = 2; pllq = 2; pllr = 2; +#else + pllm = 1; + plln = 129; + pllp = 2; + pllq = 2; + pllr = 2; +#endif flash_waitstates = 5; + /* Set voltage scaler */ + reg32 = PWR_VOSCR & (~PWR_VOS_MASK); + PWR_VOSCR = reg32 | PWR_VOS_SCALE_0; + + /* Wait until scale has changed */ + while ((PWR_VOSSR & PWR_VOSRDY) == 0) + ; + /* Disable PLL1 */ RCC_CR &= ~RCC_CR_PLL1ON; @@ -238,8 +292,9 @@ static void clock_pll_on(void) /* Set flash wait states */ flash_set_waitstates(flash_waitstates); +#if PLL_SRC_HSE /* PLL Oscillator configuration */ - RCC_CR |= RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_HSEEXT; + RCC_CR |= RCC_CR_HSEON | RCC_CR_HSEBYP; /* Wait until HSE is Ready */ while ((RCC_CR & RCC_CR_HSERDY) == 0) @@ -247,18 +302,38 @@ static void clock_pll_on(void) /* Configure PLL1 div/mul factors */ reg32 = RCC_PLL1CFGR; - reg32 &= ~((0x3F << RCC_PLL1CFGR_PLL1M_SHIFT) | (0x03)); - reg32 |= (pllm << RCC_PLL1CFGR_PLL1M_SHIFT) | RCC_PLL1CFGR_PLL1SRC_HSE; + reg32 &= ~((0x3F << RCC_PLLCFGR_PLLM_SHIFT) | (0x03)); + reg32 |= (pllm << RCC_PLLCFGR_PLLM_SHIFT) | RCC_PLLCFGR_PLLSRC_HSE; + RCC_PLL1CFGR = reg32; +#else + RCC_CR |= RCC_CR_HSION; + + /* Wait until HSI is Ready */ + while ((RCC_CR & RCC_CR_HSIRDY) == 0) + ; + + RCC_CR |= RCC_CR_CSION; + + /* Wait until CSI is Ready */ + while ((RCC_CR & RCC_CR_HSIRDY) == 0) + ; + + /* Configure PLL1 div/mul factors */ + reg32 = RCC_PLL1CFGR; + reg32 &= ~((0x3F << RCC_PLLCFGR_PLLM_SHIFT) | (0x03)); + reg32 |= (pllm << RCC_PLLCFGR_PLLM_SHIFT) | RCC_PLLCFGR_PLLSRC_CSI; RCC_PLL1CFGR = reg32; + +#endif DMB(); - RCC_PLL1DIVR = ((plln - 1) << RCC_PLL1DIVR_DIVN_SHIFT) | ((pllp - 1) << RCC_PLL1DIVR_DIVP_SHIFT) | - ((pllq - 1) << RCC_PLL1DIVR_DIVQ_SHIFT) | ((pllr - 1) << RCC_PLL1DIVR_DIVR_SHIFT); + RCC_PLL1DIVR = ((plln - 1) << RCC_PLLDIVR_DIVN_SHIFT) | ((pllp - 1) << RCC_PLLDIVR_DIVP_SHIFT) | + ((pllq - 1) << RCC_PLLDIVR_DIVQ_SHIFT) | ((pllr - 1) << RCC_PLLDIVR_DIVR_SHIFT); DMB(); /* Disable Fractional PLL */ - RCC_PLL1CFGR &= ~RCC_PLL1CFGR_PLL1FRACEN; + RCC_PLL1CFGR &= ~RCC_PLLCFGR_PLLFRACEN; DMB(); @@ -267,18 +342,18 @@ static void clock_pll_on(void) DMB(); /* Enable Fractional PLL */ - RCC_PLL1CFGR |= RCC_PLL1CFGR_PLL1FRACEN; + RCC_PLL1CFGR |= RCC_PLLCFGR_PLLFRACEN; DMB(); /* Select PLL1 Input frequency range: VCI */ - RCC_PLL1CFGR |= RCC_PLL1CFGR_RGE_1_2 << RCC_PLL1CFGR_PLL1RGE_SHIFT; + RCC_PLL1CFGR |= RCC_PLLCFGR_RGE_2_4 << RCC_PLLCFGR_PLLRGE_SHIFT; /* Select PLL1 Output frequency range: VCO = 0 */ - RCC_PLL1CFGR &= ~RCC_PLL1CFGR_PLL1VCOSEL; + RCC_PLL1CFGR &= ~RCC_PLLCFGR_PLLVCOSEL; DMB(); /* Enable PLL1 system clock out (DIV: P) */ - RCC_PLL1CFGR |= RCC_PLL1CFGR_PLL1PEN; + RCC_PLL1CFGR |= RCC_PLLCFGR_PLL1PEN; /* Enable PLL1 */ RCC_CR |= RCC_CR_PLL1ON; @@ -311,19 +386,45 @@ static void clock_pll_on(void) while ((RCC_CFGR1 & (RCC_CFGR1_SW_PLL1 << RCC_CFGR1_SWS_SHIFT)) == 0) ; + /* Set PLL1 as system clock */ + RCC_PLL1CFGR |= RCC_PLLCFGR_PLL1PEN; + } #if (TZ_SECURE()) + +#define NVIC_ISER_BASE (0xE000E100) +#define NVIC_ICER_BASE (0xE000E180) +#define NVIC_IPRI_BASE (0xE000E400) +#define NVIC_USART3_IRQ 60 + +/* Cortex M-33 has an extra register to set up non-secure interrupts */ +#define NVIC_ITNS_BASE (0xE000E380) + + + static void periph_unsecure(void) { uint32_t pin; + volatile uint32_t reg; + volatile uint32_t *nvic_itns; + uint32_t nvic_reg_pos, nvic_reg_off; /*Enable clock for User LED GPIOs */ RCC_AHB2_CLOCK_ER|= LED_AHB2_ENABLE; + /* Enable GPIO clock for accessing SECCFGR registers */ + RCC_AHB2_CLOCK_ER |= GPIOA_AHB2_CLOCK_ER; + RCC_AHB2_CLOCK_ER |= GPIOB_AHB2_CLOCK_ER; + RCC_AHB2_CLOCK_ER |= GPIOC_AHB2_CLOCK_ER; + RCC_AHB2_CLOCK_ER |= GPIOD_AHB2_CLOCK_ER; + /* Enable clock for LPUART1 */ RCC_APB2_CLOCK_ER |= UART1_APB2_CLOCK_ER_VAL; + /* Enable clock for USART3 */ + RCC_APB1L_CLOCK_ER |= UART3_APB1L_CLOCK_ER_VAL; + PWR_CR2 |= PWR_CR2_IOSV; /*Un-secure User LED GPIO pins */ @@ -331,13 +432,41 @@ static void periph_unsecure(void) GPIO_SECCFGR(GPIOB_BASE) &= ~(1 << 0); GPIO_SECCFGR(GPIOF_BASE) &= ~(1 << 4); -#if 0 /* Unsecure LPUART1 */ - TZSC_PRIVCFGR2 &= ~(TZSC_PRIVCFG2_LPUARTPRIV); - GPIO_SECCFGR(GPIOG_BASE) &= ~(1< +#include "hal/stm32h5.h" + +/* USE_UART1 + * Set to 0 for VCP over USB + * Set to 1 for Arduino D0, D1 pins on nucleo + * */ +#define USE_UART1 0 + +#define RCC_AHB2ENR1_CLOCK_ER (*(volatile uint32_t *)(RCC_BASE + 0x8C )) +#define GPIOB_AHB2ENR1_CLOCK_ER (1 << 1) +#define GPIOD_AHB2ENR1_CLOCK_ER (1 << 3) + + +#define GPIOB_MODE (*(volatile uint32_t *)(GPIOB_BASE + 0x00)) +#define GPIOB_OTYPE (*(volatile uint32_t *)(GPIOB_BASE + 0x04)) +#define GPIOB_OSPD (*(volatile uint32_t *)(GPIOB_BASE + 0x08)) +#define GPIOB_PUPD (*(volatile uint32_t *)(GPIOB_BASE + 0x0c)) +#define GPIOB_ODR (*(volatile uint32_t *)(GPIOB_BASE + 0x14)) +#define GPIOB_BSRR (*(volatile uint32_t *)(GPIOB_BASE + 0x18)) +#define GPIOB_AFL (*(volatile uint32_t *)(GPIOB_BASE + 0x20)) +#define GPIOB_AFH (*(volatile uint32_t *)(GPIOB_BASE + 0x24)) + +#define GPIOD_MODE (*(volatile uint32_t *)(GPIOD_BASE + 0x00)) +#define GPIOD_OTYPE (*(volatile uint32_t *)(GPIOD_BASE + 0x04)) +#define GPIOD_OSPD (*(volatile uint32_t *)(GPIOD_BASE + 0x08)) +#define GPIOD_PUPD (*(volatile uint32_t *)(GPIOD_BASE + 0x0c)) +#define GPIOD_ODR (*(volatile uint32_t *)(GPIOD_BASE + 0x14)) +#define GPIOD_BSRR (*(volatile uint32_t *)(GPIOD_BASE + 0x18)) +#define GPIOD_AFL (*(volatile uint32_t *)(GPIOD_BASE + 0x20)) +#define GPIOD_AFH (*(volatile uint32_t *)(GPIOD_BASE + 0x24)) + +#define CLOCK_FREQ (64000000) + +static void uart1_pins_setup(void) +{ + uint32_t reg; + RCC_AHB2ENR1_CLOCK_ER|= GPIOB_AHB2ENR1_CLOCK_ER; + /* Set mode = AF */ + reg = GPIOB_MODE & ~ (0x03 << (UART1_RX_PIN * 2)); + GPIOB_MODE = reg | (2 << (UART1_RX_PIN * 2)); + reg = GPIOB_MODE & ~ (0x03 << (UART1_TX_PIN * 2)); + GPIOB_MODE = reg | (2 << (UART1_TX_PIN * 2)); + + /* Alternate function: use low pins (6 and 7) */ + reg = GPIOB_AFL & ~(0xf << (UART1_TX_PIN * 4)); + GPIOB_AFL = reg | (UART1_PIN_AF << (UART1_TX_PIN * 4)); + reg = GPIOB_AFL & ~(0xf << ((UART1_RX_PIN) * 4)); + GPIOB_AFH = reg | (UART1_PIN_AF << ((UART1_RX_PIN) * 4)); + +} + +static void uart3_pins_setup(void) +{ + uint32_t reg; + RCC_AHB2ENR1_CLOCK_ER|= GPIOD_AHB2ENR1_CLOCK_ER; + /* Set mode = AF */ + reg = GPIOD_MODE & ~ (0x03 << (UART3_RX_PIN * 2)); + GPIOD_MODE = reg | (2 << (UART3_RX_PIN * 2)); + reg = GPIOD_MODE & ~ (0x03 << (UART3_TX_PIN * 2)); + GPIOD_MODE = reg | (2 << (UART3_TX_PIN * 2)); + + /* Alternate function: use hi pins (8 and 9) */ + reg = GPIOD_AFH & ~(0xf << ((UART3_TX_PIN - 8) * 4)); + GPIOD_AFH = reg | (UART3_PIN_AF << ((UART3_TX_PIN - 8) * 4)); + reg = GPIOD_AFH & ~(0xf << ((UART3_RX_PIN - 8) * 4)); + GPIOD_AFH = reg | (UART3_PIN_AF << ((UART3_RX_PIN - 8) * 4)); + +} + +static int uart1_init(uint32_t bitrate, uint8_t data, char parity, uint8_t stop) +{ + uint32_t reg; + /* Enable pins and configure for AF */ + uart1_pins_setup(); + + reg = RCC_CCIPR3 & (~ (RCC_CCIPR3_LPUART1SEL_MASK << RCC_CCIPR3_LPUART1SEL_SHIFT)); + RCC_CCIPR3 = reg | (0 << RCC_CCIPR3_LPUART1SEL_SHIFT); /* PLL2 */ + + /* Configure clock */ + UART1_BRR |= (uint16_t)(CLOCK_FREQ / bitrate) + 1; + + /* Configure data bits */ + if (data == 8) + UART1_CR1 &= ~UART_CR1_SYMBOL_LEN; + else + UART1_CR1 |= UART_CR1_SYMBOL_LEN; + + /* Configure parity */ + switch (parity) { + case 'O': + UART1_CR1 |= UART_CR1_PARITY_ODD; + /* fall through to enable parity */ + /* FALL THROUGH */ + case 'E': + UART1_CR1 |= UART_CR1_PARITY_ENABLED; + break; + default: + UART1_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD); + } + /* Set stop bits */ + reg = UART1_CR2 & ~UART_CR2_STOPBITS; + if (stop > 1) + UART1_CR2 = reg & (2 << 12); + else + UART1_CR2 = reg; + + /* Prescaler to DIV1 */ + UART1_PRE |= 2; + + /* Configure for RX+TX, turn on. */ + UART1_CR1 |= UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE | UART_CR1_UART_ENABLE; + + return 0; +} + +static void uart1_clear_errors(void) +{ + UART1_ICR = UART1_ISR & (UART_ENE | UART_EPE | UART_ORE | UART_EFE); +} + +static int uart1_tx(const uint8_t c) +{ + volatile uint32_t reg; + do { + reg = UART1_ISR; + if (reg & (UART_ENE | UART_EPE | UART_ORE | UART_EFE)) + uart1_clear_errors(); + } while ((reg & UART_ISR_TX_EMPTY) == 0); + UART1_TDR = c; + return 1; +} + +static int uart1_rx(uint8_t *c) +{ + volatile uint32_t reg; + int i = 0; + reg = UART1_ISR; + if (reg & (UART_ENE | UART_EPE | UART_ORE | UART_EFE)) + uart1_clear_errors(); + if (reg & UART_ISR_RX_NOTEMPTY) { + *c = (uint8_t)UART1_RDR; + return 1; + } + return 0; +} + +static int uart3_init(uint32_t bitrate, uint8_t data, char parity, uint8_t stop) +{ + uint32_t reg; + /* Enable pins and configure for AF */ + uart3_pins_setup(); + + reg = RCC_CCIPR1 & (~ (RCC_CCIPR1_USART3SEL_MASK << RCC_CCIPR1_USART3SEL_SHIFT)); + RCC_CCIPR1 = reg | (0 << RCC_CCIPR1_USART3SEL_SHIFT); /* PLL2 */ + + /* Configure clock */ + UART3_BRR = (uint16_t)(CLOCK_FREQ / bitrate) + 1; + + /* Configure data bits */ + if (data == 8) + UART3_CR1 &= ~UART_CR1_SYMBOL_LEN; + else + UART3_CR1 |= UART_CR1_SYMBOL_LEN; + + /* Configure parity */ + switch (parity) { + case 'O': + UART3_CR1 |= UART_CR1_PARITY_ODD; + /* fall through to enable parity */ + /* FALL THROUGH */ + case 'E': + UART3_CR1 |= UART_CR1_PARITY_ENABLED; + break; + default: + UART3_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD); + } + /* Set stop bits */ + reg = UART3_CR2 & ~UART_CR2_STOPBITS; + if (stop > 1) + UART3_CR2 = reg & (2 << 12); + else + UART3_CR2 = reg; + + /* Prescaler to DIV1 */ + UART3_PRE |= 2; + + /* Configure for RX+TX, turn on. */ + UART3_CR1 |= UART_CR1_TX_ENABLE | UART_CR1_RX_ENABLE | UART_CR1_UART_ENABLE; + + return 0; +} + +static void uart3_clear_errors(void) +{ + UART3_ICR = UART3_ISR & (UART_ENE | UART_EPE | UART_ORE | UART_EFE); +} + +static int uart3_tx(const uint8_t c) +{ + volatile uint32_t reg; + do { + reg = UART3_ISR; + if (reg & (UART_ENE | UART_EPE | UART_ORE | UART_EFE)) + uart3_clear_errors(); + } while ((reg & UART_ISR_TX_EMPTY) == 0); + UART3_TDR = c; + return 1; +} + +static int uart3_rx(uint8_t *c) +{ + volatile uint32_t reg; + int i = 0; + reg = UART3_ISR; + if (reg & (UART_ENE | UART_EPE | UART_ORE | UART_EFE)) + uart3_clear_errors(); + if (reg & UART_ISR_RX_NOTEMPTY) { + *c = (uint8_t)UART3_RDR; + return 1; + } + return 0; +} + +int uart_init(uint32_t bitrate, uint8_t data, char parity, uint8_t stop) +{ +#if USE_UART1 + return uart1_init(bitrate, data, parity, stop); +#else + return uart3_init(bitrate, data, parity, stop); +#endif +} + +int uart_tx(const uint8_t c) +{ +#if USE_UART1 + return uart1_tx(c); +#else + return uart3_tx(c); +#endif +} + +int uart_rx(uint8_t *c) +{ +#if USE_UART1 + return uart1_rx(c); +#else + return uart3_rx(c); +#endif +} + + diff --git a/include/user_settings.h b/include/user_settings.h index 7db539753..4636307c5 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -114,7 +114,9 @@ extern int tolower(int c); # endif # else # define HAVE_ECC_SIGN +#ifndef PKCS11_SMALL # define HAVE_ECC_CDH +#endif # define WOLFSSL_SP # define WOLFSSL_SP_MATH # define WOLFSSL_SP_SMALL @@ -173,7 +175,7 @@ extern int tolower(int c); #if defined(WOLFBOOT_SIGN_RSA2048) || \ defined(WOLFBOOT_SIGN_RSA3072) || \ defined(WOLFBOOT_SIGN_RSA4096) || \ - defined(WOLFCRYPT_SECURE_MODE) + (defined(WOLFCRYPT_SECURE_MODE) && (!defined(PKCS11_SMALL))) # define WC_RSA_BLINDING # define WC_RSA_DIRECT diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index a5985cc51..018da26d1 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -301,6 +301,8 @@ int wolfBoot_fallback_is_possible(void); int wolfBoot_dualboot_candidate(void); int wolfBoot_dualboot_candidate_addr(void**); +int wolfBoot_get_partition_state(uint8_t part, uint8_t *st); + #ifdef EXT_ENCRYPTED /* Encryption support */ diff --git a/src/boot_arm.c b/src/boot_arm.c index 6ef20b6ea..7468989be 100644 --- a/src/boot_arm.c +++ b/src/boot_arm.c @@ -364,6 +364,8 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset) /* Jump to non secure app_entry */ asm volatile("mov r7, %0" ::"r"(app_entry)); asm volatile("bic.w r7, r7, #1"); + /* Re-enable interrupts to allow non-secure OS handlers */ + asm volatile("cpsie i"); asm volatile("blxns r7" ); # else asm volatile("msr msp, %0" ::"r"(app_end_stack)); diff --git a/test-app/ARM-stm32h5-ns.ld b/test-app/ARM-stm32h5-ns.ld index cf53bb037..b8d713375 100644 --- a/test-app/ARM-stm32h5-ns.ld +++ b/test-app/ARM-stm32h5-ns.ld @@ -50,4 +50,5 @@ SECTIONS } PROVIDE(_start_heap = _end); +PROVIDE(_heap_size = 4K); PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/ARM-stm32h5.ld b/test-app/ARM-stm32h5.ld index 6e1091772..a225a39ab 100644 --- a/test-app/ARM-stm32h5.ld +++ b/test-app/ARM-stm32h5.ld @@ -50,4 +50,5 @@ SECTIONS } PROVIDE(_start_heap = _end); +PROVIDE(_heap_size = 4K); PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/Makefile b/test-app/Makefile index 49d1b51de..7dd98e8fc 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -157,13 +157,26 @@ ifeq ($(TARGET),stm32h5) ifeq ($(TZEN),1) LSCRIPT_TEMPLATE=ARM-stm32h5-ns.ld APP_OBJS+=wcs/wolfcrypt_secure.o + ifeq ($(WOLFCRYPT_TZ),1) + APP_OBJS+=../lib/wolfssl/wolfcrypt/src/logging.o + APP_OBJS+=../lib/wolfssl/wolfcrypt/benchmark/benchmark.o + APP_OBJS+=../lib/wolfssl/wolfcrypt/test/test.o + endif else LSCRIPT_TEMPLATE=ARM-stm32h5.ld endif + CFLAGS+=-DAPP_HAS_SYSTICK + CFLAGS+=-DRAMFUNCTION='__attribute__((used,section(".ramcode")))' CFLAGS+=-mcpu=cortex-m33 -ffunction-sections -fdata-sections -fno-common LDFLAGS+=-mcpu=cortex-m33 LDFLAGS+=-Wl,-gc-sections -Wl,-Map=image.map CFLAGS+=-I.. + APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o + ifeq ($(FLASH_OTP_KEYSTORE),1) + APP_OBJS+=../src/flash_otp_keystore.o + else + APP_OBJS+=../src/keystore.o + endif endif ifeq ($(TARGET),stm32u5) diff --git a/test-app/app_stm32h5.c b/test-app/app_stm32h5.c index 63a817d6b..91e431260 100644 --- a/test-app/app_stm32h5.c +++ b/test-app/app_stm32h5.c @@ -25,30 +25,46 @@ #include #include #include +#include #include "system.h" #include "hal.h" +#include "hal/stm32h5.h" +#include "uart_drv.h" #include "wolfboot/wolfboot.h" +#include "keystore.h" #ifdef SECURE_PKCS11 #include "wcs/user_settings.h" -#include -#include -#include +#include "wolfssl/wolfcrypt/settings.h" +#include "wolfssl/wolfcrypt/wc_pkcs11.h" +#include "wolfssl/wolfcrypt/random.h" +#include "wolfcrypt/benchmark/benchmark.h" +#include "wolfcrypt/test/test.h" extern const char pkcs11_library_name[]; extern const CK_FUNCTION_LIST wolfpkcs11nsFunctionList; #endif +volatile unsigned int jiffies = 0; + +/* Usart irq-based read function */ +static uint8_t uart_buf_rx[1024]; +static uint32_t uart_rx_bytes = 0; +static uint32_t uart_processed = 0; +static int uart_rx_isr(unsigned char *c, int len); +static int uart_poll(void); + #define LED_BOOT_PIN (4) /* PG4 - Nucleo - Red Led */ #define LED_USR_PIN (0) /* PB0 - Nucleo - Green Led */ #define LED_EXTRA_PIN (4) /* PF4 - Nucleo - Orange Led */ +#define NVIC_USART3_IRQN (60) + /*Non-Secure */ #define RCC_BASE (0x44020C00) /* RM0481 - Table 3 */ #define GPIOG_BASE 0x42021800 #define GPIOB_BASE 0x42020400 #define GPIOF_BASE 0x42021400 - #define GPIOG_MODER (*(volatile uint32_t *)(GPIOG_BASE + 0x00)) #define GPIOG_PUPDR (*(volatile uint32_t *)(GPIOG_BASE + 0x0C)) #define GPIOG_BSRR (*(volatile uint32_t *)(GPIOG_BASE + 0x18)) @@ -65,6 +81,36 @@ extern const CK_FUNCTION_LIST wolfpkcs11nsFunctionList; #define GPIOG_AHB2ENR1_CLOCK_ER (1 << 6) #define GPIOF_AHB2ENR1_CLOCK_ER (1 << 5) #define GPIOB_AHB2ENR1_CLOCK_ER (1 << 1) +#define GPIOD_AHB2ENR1_CLOCK_ER (1 << 3) + +/* SysTick */ +static uint32_t cpu_freq = 250000000; + +#define SYSTICK_BASE (0xE000E010) +#define SYSTICK_CSR (*(volatile uint32_t *)(SYSTICK_BASE + 0x00)) +#define SYSTICK_RVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x04)) +#define SYSTICK_CVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x08)) +#define SYSTICK_CALIB (*(volatile uint32_t *)(SYSTICK_BASE + 0x0C)) + +int clock_gettime (clockid_t clock_id, struct timespec *tp) +{ + (void)clock_id; + tp->tv_sec = jiffies / 1000; + tp->tv_nsec = (jiffies % 1000) * 1000000; + return 0; +} + +static void systick_enable(void) +{ + SYSTICK_RVR = ((cpu_freq / 1000) - 1); + SYSTICK_CVR = 0; + SYSTICK_CSR |= 0x07; +} + +void isr_systick(void) +{ + jiffies++; +} static void boot_led_on(void) { @@ -131,93 +177,694 @@ static uint8_t my_pubkey[200]; extern int ecdsa_sign_verify(int devId); +/* Command line commands */ +static int cmd_help(const char *args); +static int cmd_info(const char *args); +static int cmd_success(const char *args); +static int cmd_login_pkcs11(const char *args); +static int cmd_random(const char *args); +static int cmd_benchmark(const char *args); +static int cmd_test(const char *args); +static int cmd_timestamp(const char *args); +static int cmd_update(const char *args); +static int cmd_update_xmodem(const char *args); +static int cmd_reboot(const char *args); -void main(void) + + +#define CMD_BUFFER_SIZE 256 +#define CMD_NAME_MAX 64 + + + +/* Command parser */ +struct console_command { + int (*fn)(const char *args); + const char name[CMD_NAME_MAX]; + const char help[CMD_BUFFER_SIZE]; +}; + +struct console_command COMMANDS[] = { + { cmd_help, "help", "shows this help message"}, + { cmd_info, "info", "display information about the system and partitions"}, + { cmd_success, "success", "confirm a successful update"}, + { cmd_login_pkcs11, "pkcs11", "enable and test crypto calls with PKCS11 in secure mode" }, + { cmd_random, "random", "generate a random number"}, + { cmd_timestamp, "timestamp", "print the current timestamp"}, + { cmd_benchmark, "benchmark", "run the wolfCrypt benchmark"}, + { cmd_test, "test", "run the wolfCrypt test"}, + { cmd_update_xmodem, "update", "update the firmware via XMODEM"}, + { cmd_reboot, "reboot", "reboot the system"}, + { NULL, "", ""} +}; + +#define AIRCR *(volatile uint32_t *)(0xE000ED0C) +#define AIRCR_VKEY (0x05FA << 16) +# define AIRCR_SYSRESETREQ (1 << 2) + +int cmd_reboot(const char *args) +{ + (void)args; + AIRCR = AIRCR_SYSRESETREQ | AIRCR_VKEY; + while(1) + asm volatile("wfi"); + return 0; /* Never happens */ +} + +#define XSOH 0x01 +#define XEOT 0x04 +#define XACK 0x06 +#define XNAK 0x15 +#define XCAN 0x18 + + +static uint8_t crc8(uint8_t *data, size_t len) +{ + uint8_t checksum = 0; + for (int i = 0; i < len; i++) { + checksum += data[i]; + } + return checksum; +} + +#define XMODEM_PAYLOAD_SIZE 128 +#define XMODEM_PACKET_SIZE (3 + XMODEM_PAYLOAD_SIZE + 1) +#define XMODEM_TIMEOUT 1000 /* milliseconds */ + +static void xcancel(void) +{ + int i; + for (i = 0; i < 10; i++) + uart_tx(XCAN); +} + +static uint8_t xpkt_payload[XMODEM_PAYLOAD_SIZE]; + +static int cmd_update_xmodem(const char *args) +{ + int ret = -1; + uint8_t xpkt[XMODEM_PACKET_SIZE]; + uint32_t dst_flash = (uint32_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS; + uint8_t pkt_num = 0, pkt_num_expected=0xFF; + uint32_t pkt_size = XMODEM_PACKET_SIZE; + uint32_t update_ver = 0; + uint32_t now = jiffies; + uint32_t i = 0; + uint8_t pkt_num_inv; + uint8_t crc, calc_crc; + int transfer_started = 0; + + + printf("Erasing update partition..."); + fflush(stdout); + hal_flash_unlock(); + hal_flash_erase(dst_flash, WOLFBOOT_PARTITION_SIZE); + printf("Done.\r\n"); + + printf("Waiting for XMODEM transfer...\r\n"); + + while (1) { + now = jiffies; + i = 0; + + while(i < XMODEM_PACKET_SIZE) { + ret = uart_rx_isr(&xpkt[i], XMODEM_PACKET_SIZE - i); + if (ret == 0) { + if(jiffies > (now + XMODEM_TIMEOUT)) { + now = jiffies; + if (i == 0) + uart_tx(XNAK); + i = 0; + } else { + asm volatile("wfi"); + } + } else { + now = jiffies; + i += ret; + } + } + + if (xpkt[0] == XEOT) { + ret = 0; + uart_tx(XACK); + extra_led_on(); + break; + } + if (xpkt[0] != XSOH) { + continue; + } + pkt_num = xpkt[1]; + pkt_num_inv = ~xpkt[2]; + if (pkt_num == pkt_num_inv) { + if (!transfer_started) /* sync */ { + (pkt_num_expected = pkt_num); + transfer_started = 1; + } else if (pkt_num_expected != pkt_num) { + uart_tx(XNAK); + continue; + } + if ((pkt_num / 0x10) & 0x01) + extra_led_on(); + else + extra_led_off(); + + /* Packet is valid */ + crc = xpkt[XMODEM_PACKET_SIZE - 1]; + calc_crc = crc8(xpkt, XMODEM_PACKET_SIZE - 1); + if (crc == calc_crc) { + uint32_t t_size; + /* CRC is valid */ + memcpy(xpkt_payload, xpkt + 3, XMODEM_PAYLOAD_SIZE); + ret = hal_flash_write(dst_flash, xpkt_payload, XMODEM_PAYLOAD_SIZE); + if (ret != 0) { + xcancel(); + printf("Error writing to flash\r\n"); + break; + } + uart_tx(XACK); + pkt_num++; + pkt_num_expected++; + dst_flash += XMODEM_PAYLOAD_SIZE; + t_size = *((uint32_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 4)); + t_size += IMAGE_HEADER_SIZE; + if ((uint32_t)dst_flash >= (WOLFBOOT_PARTITION_UPDATE_ADDRESS + t_size)) { + ret = 0; + extra_led_off(); + break; + } + uart_tx(XACK); + } else { + uart_tx(XNAK); + } + } else { + uart_tx(XNAK); /* invalid packet number received */ + } + } + for (i = 0; i < 10; i++) + uart_tx('\r'); + + printf("End of transfer. ret: %d\r\n", ret); + update_ver = wolfBoot_update_firmware_version(); + if (update_ver != 0) { + printf("New firmware version: 0x%lx\r\n", update_ver); + printf("Triggering update...\r\n"); + wolfBoot_update_trigger(); + printf("Update completed successfully.\r\n"); + } else { + printf("No valid image in update partition\r\n"); + } + + hal_flash_lock(); + return ret; +} + +static int cmd_help(const char *args) +{ + int i; + for (i = 0;; i++) { + if(COMMANDS[i].fn == NULL) + break; + printf("%s : %s\r\n", COMMANDS[i].name, COMMANDS[i].help); + } + return 0; +} + +const char part_state_names[6][16] = { + "NEW", + "UPDATING", + "FFLAGS", + "TESTING", + "CONFIRMED", + "[Invalid state]" +}; + +static const char *part_state_name(uint8_t state) +{ + switch(state) { + case IMG_STATE_NEW: + return part_state_names[0]; + case IMG_STATE_UPDATING: + return part_state_names[1]; + case IMG_STATE_FINAL_FLAGS: + return part_state_names[2]; + case IMG_STATE_TESTING: + return part_state_names[3]; + case IMG_STATE_SUCCESS: + return part_state_names[4]; + default: + return part_state_names[5]; + } +} + +static int cmd_info(const char *args) +{ + int i, j; + uint32_t cur_fw_version, update_fw_version; + uint32_t n_keys; + uint16_t hdrSz; + uint8_t boot_part_state = IMG_STATE_NEW, update_part_state = IMG_STATE_NEW; + + cur_fw_version = wolfBoot_current_firmware_version(); + update_fw_version = wolfBoot_update_firmware_version(); + + wolfBoot_get_partition_state(PART_BOOT, &boot_part_state); + wolfBoot_get_partition_state(PART_UPDATE, &update_part_state); + + printf("\r\n"); + printf("System information\r\n"); + printf("====================================\r\n"); + printf("Flash banks are %sswapped.\r\n", ((FLASH_OPTSR_CUR & (FLASH_OPTSR_SWAP_BANK)) == 0)?"not ":""); + printf("Firmware version : 0x%lx\r\n", wolfBoot_current_firmware_version()); + printf("Current firmware state: %s\r\n", part_state_name(boot_part_state)); + if (update_fw_version != 0) { + if (update_part_state == IMG_STATE_UPDATING) + printf("Candidate firmware version : 0x%lx\r\n", update_fw_version); + else + printf("Backup firmware version : 0x%lx\r\n", update_fw_version); + printf("Update state: %s\r\n", part_state_name(update_part_state)); + if (update_fw_version > cur_fw_version) { + printf("'reboot' to initiate update.\r\n"); + } else { + printf("Update image older than current.\r\n"); + } + } else { + printf("No image in update partition.\r\n"); + } + + printf("\r\n"); + printf("Bootloader OTP keystore information\r\n"); + printf("====================================\r\n"); + n_keys = keystore_num_pubkeys(); + printf("Number of public keys: %lu\r\n", n_keys); + for (i = 0; i < n_keys; i++) { + uint32_t size = keystore_get_size(i); + uint32_t type = keystore_get_key_type(i); + uint32_t mask = keystore_get_mask(i); + uint8_t *keybuf = keystore_get_buffer(i); + + printf("\r\n"); + printf(" Public Key #%d: size %lu, type %lx, mask %08lx\r\n", i, + size, type, mask); + printf(" ====================================\r\n "); + for (j = 0; j < size; j++) { + printf("%02X ", keybuf[j]); + if (j % 16 == 15) { + printf("\r\n "); + } + } + printf("\r\n"); + } + return 0; +} + +static int cmd_success(const char *args) +{ + wolfBoot_success(); + printf("update success confirmed.\r\n"); + return 0; +} + +static int cmd_random(const char *args) +{ +#ifdef WOLFCRYPT_SECURE_MODE + WC_RNG rng; int ret; uint32_t rand; - uint32_t i; - uint32_t klen = 200; - int otherkey_slot; - unsigned int devId = 0; + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("Failed to initialize RNG\r\n"); + return -1; + } + ret = wc_RNG_GenerateBlock(&rng, (byte *)&rand, sizeof(rand)); + if (ret != 0) { + printf("Failed to generate random number\r\n"); + wc_FreeRng(&rng); + return -1; + } + printf("Today's lucky number: 0x%08lX\r\n", rand); + printf("Brought to you by wolfCrypt's DRBG fed by HW TRNG in Secure world\r\n"); + wc_FreeRng(&rng); +#else + printf("Feature only supported with WOLFCRYPT_TZ=1\n"); +#endif + return 0; +} + +static int cmd_timestamp(const char *args) +{ + struct timespec tp = {}; + clock_gettime(0, &tp); + printf("Current timestamp: %llu.%03lu\r\n", tp.tv_sec, tp.tv_nsec/1000000); + printf("Current systick: %u\r\n", jiffies); + printf("VTOR: %08lx\r\n", (*(volatile uint32_t *)(0xE000ED08))); + return 0; +} + +static int cmd_login_pkcs11(const char *args) +{ + int ret = -1; #ifdef SECURE_PKCS11 - WC_RNG rng; + unsigned int devId = 0; Pkcs11Token token; Pkcs11Dev PKCS11_d; unsigned long session; char TokenPin[] = "0123456789ABCDEF"; char UserPin[] = "ABCDEF0123456789"; char SoPinName[] = "SO-PIN"; -#endif - - /* Turn on boot LED */ - boot_led_on(); + static int pkcs11_initialized = 0; -#ifdef SECURE_PKCS11 + if (pkcs11_initialized) { + printf("PKCS11 already initialized.\r\n"); + return 0; + } + + printf("PKCS11 Login\r\n"); + + printf("Initializing wolfCrypt..."); + fflush(stdout); wolfCrypt_Init(); + printf("Done.\r\n"); PKCS11_d.heap = NULL, PKCS11_d.func = (CK_FUNCTION_LIST *)&wolfpkcs11nsFunctionList; + printf("Initializing EccKey token..."); + fflush(stdout); ret = wc_Pkcs11Token_Init(&token, &PKCS11_d, 1, "EccKey", (const byte*)TokenPin, strlen(TokenPin)); if (ret == 0) { + printf("Done.\r\n"); + printf("Retrieving crypto engine function list..."); + fflush(stdout); ret = wolfpkcs11nsFunctionList.C_OpenSession(1, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session); } if (ret == 0) { + printf("Done.\r\n"); + printf("Initializing token..."); + fflush(stdout); ret = wolfpkcs11nsFunctionList.C_InitToken(1, (byte *)TokenPin, strlen(TokenPin), (byte *)SoPinName); } if (ret == 0) { - extra_led_on(); + printf("Done.\r\n"); + printf("Logging in as SO..."); ret = wolfpkcs11nsFunctionList.C_Login(session, CKU_SO, (byte *)TokenPin, strlen(TokenPin)); } if (ret == 0) { + extra_led_on(); + printf("Done.\r\n"); + printf("Setting PIN..."); ret = wolfpkcs11nsFunctionList.C_InitPIN(session, (byte *)TokenPin, strlen(TokenPin)); } if (ret == 0) { + printf("Done.\r\n"); + printf("Logging out..."); ret = wolfpkcs11nsFunctionList.C_Logout(session); } - if (ret != 0) { - while(1) - ; - } if (ret == 0) { + printf("Done.\r\n"); + printf("Registering crypto calls with wolfCrypt..."); ret = wc_CryptoDev_RegisterDevice(devId, wc_Pkcs11_CryptoDevCb, &token); + } + if (ret == 0) { + printf("Done.\r\n"); +#ifdef HAVE_ECC + printf("Testing ECC..."); + ret = ecdsa_sign_verify(devId); if (ret != 0) { - while(1) - ; + ret = -1; + printf("Failed.\r\n"); + } + else { + usr_led_on(); + printf("Done.\r\n"); } - if (ret == 0) { -#ifdef HAVE_ECC - ret = ecdsa_sign_verify(devId); - if (ret != 0) - ret = 1; - else - usr_led_on(); #endif + } + if (ret == 0) { + printf("PKCS11 initialization completed successfully.\r\n"); + pkcs11_initialized = 1; + } +#else + printf("Feature only supported with WOLFCRYPT_TZ=1\n"); +#endif /* SECURE_PKCS11 */ + return ret; +} + +static int cmd_benchmark(const char *args) +{ +#ifdef WOLFCRYPT_SECURE_MODE + benchmark_test(NULL); +#endif + return 0; +} + +/* Test command */ +static int cmd_test(const char *args) +{ +#ifdef WOLFCRYPT_SECURE_MODE + wolfcrypt_test(NULL); +#endif + return 0; +} + +static int parse_cmd(const char *cmd) +{ + int retval = -2; + int i; + for (i = 0;; i++) { + if(COMMANDS[i].fn == NULL) + break; + if (strncmp(cmd, COMMANDS[i].name, strlen(COMMANDS[i].name)) == 0) { + retval = COMMANDS[i].fn(cmd); + break; } - wc_Pkcs11Token_Final(&token); } + return retval; +} -#else - /* Check if version > 1 and turn on user led */ - if (wolfBoot_current_firmware_version() > 1) { - usr_led_on(); + +/* Main loop reading commands from UART */ +static void console_loop(void) +{ + int ret; + int idx = 0; + char cmd[CMD_BUFFER_SIZE]; + unsigned char c; + while (1) { + printf("\r\n"); + printf("cmd> "); + fflush(stdout); + idx = 0; + do { + ret = uart_rx_isr((uint8_t *)&c, 1); + if (ret > 0) { + if ((c >= 32) && (c < 127)) { + printf("%c", c); + fflush(stdout); + cmd[idx++] = (char)c; + } else if (c == '\r') { + printf("\r\n"); + fflush(stdout); + break; /* End of command. Parse it. */ + } else if (c == 0x08) { /* Backspace */ + if (idx > 0) { + printf("%c", 0x08); + printf(" "); + printf("%c", 0x08); + fflush(stdout); + idx--; + } + } + } + } while (idx < (CMD_BUFFER_SIZE - 1)); + if (idx > 0) { + cmd[idx] = 0; + if (parse_cmd(cmd) == -2) { + printf("Unknown command: %s\r\n", cmd); + } + } } -#endif /* SECURE_PKCS11 */ +} + +void isr_usart3(void) +{ + volatile uint32_t reg; + usr_led_on(); + reg = UART3_ISR; + if (reg & UART_ISR_RX_NOTEMPTY) { + if (uart_rx_bytes >= 1023) + reg = UART3_RDR; + else + uart_buf_rx[uart_rx_bytes++] = (unsigned char)(UART3_RDR & 0xFF); + } +} + +static int uart_rx_isr(unsigned char *c, int len) +{ + UART3_CR1 &= ~UART_ISR_RX_NOTEMPTY; + if (len > (uart_rx_bytes - uart_processed)) + len = (uart_rx_bytes - uart_processed); + if (len > 0) { + memcpy(c, uart_buf_rx + uart_processed, len); + uart_processed += len; + if (uart_processed >= uart_rx_bytes) { + uart_processed = 0; + uart_rx_bytes = 0; + usr_led_off(); + } + } + UART3_CR1 |= UART_ISR_RX_NOTEMPTY; + return len; +} + +static int uart_poll(void) +{ + return (uart_rx_bytes > uart_processed)?1:0; +} + +void main(void) +{ + int ret; + uint32_t app_version; + + + /* Turn on boot LED */ + boot_led_on(); + + /* Enable SysTick */ + systick_enable(); + + app_version = wolfBoot_current_firmware_version(); + + + nvic_irq_setprio(NVIC_USART3_IRQN, 0); + nvic_irq_enable(NVIC_USART3_IRQN); + + uart_init(115200, 8, 'N', 1); + UART3_CR1 |= UART_ISR_RX_NOTEMPTY; + UART3_CR3 |= UART_CR3_RXFTIE; + + + printf("========================\r\n"); + printf("STM32H5 wolfBoot demo Application\r\n"); + printf("Copyright 2024 wolfSSL Inc\r\n"); + printf("GPL v3\r\n"); + printf("Version : 0x%lx\r\n", app_version); + printf("========================\r\n"); + + console_loop(); + + while(1) ; /* Never reached */ } + + + +/* Syscall helpers + UART interface for printf */ + + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + int ret; + return -1; +} + +int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + uart_tx(*ptr++); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +#ifndef WOLFCRYPT_SECURE_MODE +/* Back-end for malloc, used for token handling */ +extern unsigned int _start_heap; /* From linker script: heap memory */ +extern unsigned int _heap_size; /* From linker script: heap limit */ + +void * _sbrk(unsigned int incr) +{ + static unsigned char *heap = (unsigned char *)&_start_heap; + static uint32_t heapsize = (uint32_t)(&_heap_size); + void *old_heap = heap; + if (((incr >> 2) << 2) != incr) + incr = ((incr >> 2) + 1) << 2; + + if (heap == NULL) + heap = (unsigned char *)&_start_heap; + else + heap += incr; + if (((uint32_t)heap - (uint32_t)(&_start_heap)) > heapsize) { + heap -= incr; + return NULL; + } + return old_heap; +} +#endif \ No newline at end of file diff --git a/test-app/startup_arm.c b/test-app/startup_arm.c index 4910b4164..ae33b4613 100644 --- a/test-app/startup_arm.c +++ b/test-app/startup_arm.c @@ -33,6 +33,14 @@ extern unsigned int _start_heap; extern void isr_tim2(void); #endif +#ifdef PLATFORM_stm32h5 +extern void isr_usart3(void); +#endif + +#ifdef APP_HAS_SYSTICK +extern void isr_systick(void); +#endif + #ifndef STACK_PAINTING #define STACK_PAINTING 0 #endif @@ -127,7 +135,11 @@ void (* const IV[])(void) = isr_empty, // DebugMonitor 0, // reserved isr_empty, // PendSV +#ifdef APP_HAS_SYSTICK + isr_systick, // SysTick +#else isr_empty, // SysTick +#endif /* Device specific IRQs for LM3S */ @@ -286,6 +298,139 @@ void (* const IV[])(void) = isr_empty, // UCPD1_IRQHandler isr_empty, // ICACHE_IRQHandler isr_empty, // OTFDEC1_IRQHandler + // +#elif defined(PLATFORM_stm32h5) + isr_empty, // WWDG_IRQHandler + isr_empty, // PVD_PVM_IRQHandler + isr_empty, // RTC_IRQHandler + isr_empty, // RTC_S_IRQHandler + isr_empty, // TAMP_IRQHandler + isr_empty, // RAMCFG_IRQHandler + isr_empty, // FLASH_IRQHandler + isr_empty, // FLASH_S_IRQHandler + isr_empty, // GTZC_IRQHandler + isr_empty, // RCC_IRQHandler + isr_empty, // RCC_S_IRQHandler + isr_empty, // EXTI0_IRQHandler + isr_empty, // EXTI1_IRQHandler + isr_empty, // EXTI2_IRQHandler + isr_empty, // EXTI3_IRQHandler + isr_empty, // EXTI4_IRQHandler + isr_empty, // EXTI5_IRQHandler + isr_empty, // EXTI6_IRQHandler + isr_empty, // EXTI7_IRQHandler + isr_empty, // EXTI8_IRQHandler + isr_empty, // EXTI9_IRQHandler + isr_empty, // EXTI10_IRQHandler + isr_empty, // EXTI11_IRQHandler + isr_empty, // EXTI12_IRQHandler + isr_empty, // EXTI13_IRQHandler + isr_empty, // EXTI14_IRQHandler + isr_empty, // EXTI15_IRQHandler + isr_empty, // GPDMA1CH0_IRQHandler + isr_empty, // GPDMA1CH1_IRQHandler + isr_empty, // GPDMA1CH2_IRQHandler + isr_empty, // GPDMA1CH3_IRQHandler + isr_empty, // GPDMA1CH4_IRQHandler + isr_empty, // GPDMA1CH5_IRQHandler + isr_empty, // GPDMA1CH6_IRQHandler + isr_empty, // GPDMA1CH7_IRQHandler + isr_empty, // IWDG_IRQHandler + isr_empty, // SAES_IRQHandler + isr_empty, // ADC1_IRQHandler + isr_empty, // DAC1_IRQHandler + isr_empty, // FDCAN1_IT0_IRQHandler + isr_empty, // FDCAN1_IT1_IRQHandler + isr_empty, // TIM1_BRK_IRQHandler + isr_empty, // TIM1_UP_IRQHandler + isr_empty, // TIM1_TRG_COM_IRQHandler + isr_empty, // TIM1_CC_IRQHandler + isr_empty, // TIM2_IRQHandler + isr_empty, // TIM3_IRQHandler + isr_empty, // TIM4_IRQHandler + isr_empty, // TIM5_IRQHandler + isr_empty, // TIM6_IRQHandler + isr_empty, // TIM7_IRQHandler + isr_empty, // I2C1_EV_IRQHandler + isr_empty, // I2C1_ER_IRQHandler + isr_empty, // I2C2_EV_IRQHandler + isr_empty, // I2C2_ER_IRQHandler + isr_empty, // SPI1_IRQHandler + isr_empty, // SPI2_IRQHandler + isr_empty, // SPI3_IRQHandler + isr_empty, // USART1_IRQHandler + isr_empty, // USART2_IRQHandler + isr_usart3, // USART3_IRQHandler + isr_empty, // UART4_IRQHandler + isr_empty, // UART5_IRQHandler + isr_empty, // LPUART1_IRQHandler + isr_empty, // LPTIM1_IRQHandler + isr_empty, // TIM8_BRK_IRQHandler + isr_empty, // TIM8_UP_IRQHandler + isr_empty, // TIM8_TRG_COM_IRQHandler + isr_empty, // TIM8_CC_IRQHandler + isr_empty, // ADC2_IRQHandler + isr_empty, // LPTIM2_IRQHandler + isr_empty, // TIM15_IRQHandler + isr_empty, // TIM16_IRQHandler + isr_empty, // TIM17_IRQHandler + isr_empty, // USB_FS_IRQHandler + isr_empty, // CRS_IRQHandler + isr_empty, // UCPD1_IRQHandler + isr_empty, // FMC_IRQHandler + isr_empty, // OCTOSPI1_IRQHandler + isr_empty, // SDMMC1_IRQHandler + isr_empty, // I2C3_EV_IRQHandler + isr_empty, // I2C3_ER_IRQHandler + isr_empty, // SPI4_IRQHandler + isr_empty, // SPI5_IRQHandler + isr_empty, // SPI6_IRQHandler + isr_empty, // USART6_IRQHandler + isr_empty, // USART10_IRQHandler + isr_empty, // USART11_IRQHandler + isr_empty, // SAI1_IRQHandler + isr_empty, // SAI2_IRQHandler + isr_empty, // GPDMA2CH0_IRQHandler + isr_empty, // GPDMA2CH1_IRQHandler + isr_empty, // GPDMA2CH2_IRQHandler + isr_empty, // GPDMA2CH3_IRQHandler + isr_empty, // GPDMA2CH4_IRQHandler + isr_empty, // GPDMA2CH5_IRQHandler + isr_empty, // GPDMA2CH6_IRQHandler + isr_empty, // GPDMA2CH7_IRQHandler + isr_empty, // UART7_IRQHandler + isr_empty, // UART8_IRQHandler + isr_empty, // UART9_IRQHandler + isr_empty, // UART12_IRQHandler + isr_empty, // SDMMC2_IRQHandler + isr_empty, // FPU_IRQHandler + isr_empty, // ICACHE_IRQHandler + isr_empty, // DCACHE_IRQHandler + isr_empty, // ETH1_IRQHandler + isr_empty, // DCMI_PSSI_IRQHandler + isr_empty, // FDCAN2_IT0_IRQHandler + isr_empty, // FDCAN2_IT1_IRQHandler + isr_empty, // CORDIC_IRQHandler + isr_empty, // FMAC_IRQHandler + isr_empty, // DTS_IRQHandler + isr_empty, // RNG_IRQHandler + isr_empty, // OTFDEC1_IRQHandler + isr_empty, // AES_IRQHandler + isr_empty, // HASH_IRQHandler + isr_empty, // PKA_IRQHandler + isr_empty, // CEC_IRQHandler + isr_empty, // TIM12_IRQHandler + isr_empty, // TIM13_IRQHandler + isr_empty, // TIM14_IRQHandler + isr_empty, // I3C1_EV_IRQHandler + isr_empty, // I3C1_ER_IRQHandler + isr_empty, // I2C4_EV_IRQHandler + isr_empty, // I2C4_ER_IRQHandler + isr_empty, // LPTIM3_IRQHandler + isr_empty, // LPTIM4_IRQHandler + isr_empty, // LPTIM5_IRQHandler + isr_empty, // LPTIM6_IRQHandler + #elif defined(STM32) /* For STM32 */ isr_empty, // NVIC_WWDG_IRQ 0 isr_empty, // PVD_IRQ 1 diff --git a/test-app/system.h b/test-app/system.h index 441b56915..e68762326 100644 --- a/test-app/system.h +++ b/test-app/system.h @@ -28,12 +28,13 @@ #define PLL_FULL_MASK (0x7F037FFF) /* Assembly helpers */ +#ifndef DMB #define DMB() asm volatile ("dmb"); +#endif #define WFI() asm volatile ("wfi"); /* Master clock setting */ void clock_config(void); -void flash_set_waitstates(void); /* NVIC */ diff --git a/test-app/wcs/user_settings.h b/test-app/wcs/user_settings.h index 7125ae6c6..9140f2b17 100644 --- a/test-app/wcs/user_settings.h +++ b/test-app/wcs/user_settings.h @@ -132,10 +132,10 @@ extern int tolower(int c); #define NO_ERROR_STRINGS #define BENCH_EMBEDDED -#define NO_CRYPT_TEST -#define NO_CRYPT_BENCHMARK +#ifdef SECURE_PKCS11 #define CUSTOM_RAND_GENERATE_BLOCK wcs_get_random +#endif /* Disable VLAs */ #define WOLFSSL_SP_NO_DYN_STACK diff --git a/tools/keytools/otp/Makefile b/tools/keytools/otp/Makefile index 6b89980b3..7b44f3b14 100644 --- a/tools/keytools/otp/Makefile +++ b/tools/keytools/otp/Makefile @@ -32,6 +32,10 @@ CC=$(CROSS_COMPILE)gcc OBJCOPY?=$(CROSS_COMPILE)objcopy SIZE?=$(CROSS_COMPILE)size +ifeq ($(ENABLE_OTP_WP),1) + CFLAGS+=-DENABLE_OTP_WP +endif + all: otp-keystore-primer.bin otp-keystore-gen otp-keystore-gen: otp-keystore-gen.c @@ -56,7 +60,7 @@ stm32h5.o: ../../../hal/stm32h5.c $(Q)$(CC) $(CFLAGS) -c -o $@ $< - + clean: $(Q)rm -rf $(PRI_KS_OBJS) *.bin *.elf diff --git a/tools/keytools/otp/otp-keystore-gen.c b/tools/keytools/otp/otp-keystore-gen.c index afbe43298..9a242a3be 100644 --- a/tools/keytools/otp/otp-keystore-gen.c +++ b/tools/keytools/otp/otp-keystore-gen.c @@ -1,4 +1,4 @@ -/* otp-keystore-primer.c +/* otp-keystore-gen.c * * Command line utility to create a OTP image * @@ -30,7 +30,10 @@ #include #include +/* Define a generic max OTP size to appease otp_keystore.h */ +#ifndef OTP_SIZE #define OTP_SIZE 4096 +#endif #include "wolfboot/wolfboot.h" #include "keystore.h" @@ -56,22 +59,24 @@ int main(void) /* Sanity check to avoid writing an empty keystore */ if (n_keys < 1) { - fprintf(stderr, "Error: too few keys (%d), refusing to create %s\n", n_keys, outfile); + fprintf(stderr, "Error: too few keys (%d), refusing to create %s\n", + n_keys, outfile); exit(1); } - + slot_size = keystore_get_size(0); slot_size += KEYSTORE_HDR_SIZE; fprintf(stderr, "Slot size: %d\n", slot_size); fprintf(stderr, "Number of slots: %d\n", n_keys); - fprintf(stderr, "%s size: %d\n", outfile, slot_size * n_keys + sizeof(struct wolfBoot_otp_hdr)); + fprintf(stderr, "%s size: %d\n", outfile, (slot_size * n_keys) + + (int)sizeof(struct wolfBoot_otp_hdr)); ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0600); if (ofd < 0) { perror("opening output file"); exit(2); } - + /* Write the header to the beginning of the OTP binary file */ if (write(ofd, &hdr, sizeof(hdr)) != sizeof(hdr)) { fprintf(stderr, "Error writing to %s: %s\n", outfile, strerror(errno)); @@ -81,11 +86,13 @@ int main(void) /* Write each public key to its slot in OTP */ if (write(ofd, &PubKeys[i], slot_size) < 0) { - fprintf(stderr, "Error adding key %d to %s: %s\n", i, outfile, strerror(errno)); - exit(3); + fprintf(stderr, "Error adding key %d to %s: %s\n", i, outfile, + strerror(errno)); + exit(3); } } fprintf(stderr, "%s successfully created.\nGoodbye.\n", outfile); close(ofd); + return 0; } diff --git a/tools/keytools/otp/otp-keystore-primer.c b/tools/keytools/otp/otp-keystore-primer.c index ed15c40e6..1a56754a2 100644 --- a/tools/keytools/otp/otp-keystore-primer.c +++ b/tools/keytools/otp/otp-keystore-primer.c @@ -59,10 +59,13 @@ void main(void) sizeof(struct keystore_slot)); } - /* Protect the OTP area just written */ tot_len = OTP_HDR_SIZE + n_keys * SIZEOF_KEYSTORE_SLOT; - hal_flash_otp_set_readonly(FLASH_OTP_BASE, tot_len); +#ifdef ENABLE_OTP_WP + /* Protect the OTP area just written */ + hal_flash_otp_set_readonly(FLASH_OTP_BASE, tot_len); +#endif + (void)tot_len; /* Done! */ while(1)