From ace95cc2dc671ad2598d049d9c0f2082db1be7c2 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 2 Jul 2024 15:57:52 -0700 Subject: [PATCH] Added instructions for STM32H5 demo to `docs/flash-OTP.md`. --- .github/workflows/test-configs.yml | 12 +- .../stm32h5-tz-dualbank-otp-lms.config | 37 +++++ .../examples/stm32h5-tz-dualbank-otp.config | 3 +- ...-wolfcrypt-tz.config => stm32h5-tz.config} | 0 docs/STM32-TZ.md | 9 +- docs/Targets.md | 8 +- docs/flash-OTP.md | 127 +++++++++++++++++- hal/stm32h7.h | 10 +- tools/keytools/otp/otp-keystore-gen.c | 8 +- 9 files changed, 184 insertions(+), 30 deletions(-) create mode 100644 config/examples/stm32h5-tz-dualbank-otp-lms.config rename config/examples/{stm32h5-wolfcrypt-tz.config => stm32h5-tz.config} (100%) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 66f98961..eee92bd7 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 00000000..f14e7435 --- /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 e4a13939..0b881c67 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 d16dedd9..d928760a 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 cb51adba..bbfe6780 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 e3d99417..7c42619f 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,7 +24,7 @@ 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. @@ -39,11 +39,11 @@ And then, to create the image file `otp.bin`: 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 +59,120 @@ 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 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) + +6) Build wolfBoot and test application using `make` + +7) Flash the OTP keystore primer: + + - Flash `./tools/keytools/otp/otp-keystore-primer.bin` to `0x08000000` + +8) Disconnect the tool and reboot + - The primer will run and flash keystore.c to OTP. + - Verify you flashed the keystore in OTP + - Read memory from STM32CubeProgrammer at address `0x08FFF000` (should start with ASCII "WOLFBOOT") + +9) Mass erase the device + - STM32CubeProgrammer -> Full chip erase + +10) Flash wolfBoot and test-app + + - Flash `wolfboot.bin` at `0x0C000000` + - Flash `test-app/image_v1_signed.bin` at `0x08040000` + +13) Disconnect and reboot, the red LED should turn on. + +14) 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 +``` + +15) 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/stm32h7.h b/hal/stm32h7.h index 7cfb50de..e38c74ca 100644 --- a/hal/stm32h7.h +++ b/hal/stm32h7.h @@ -279,20 +279,12 @@ #define FLASH_OPT_KEY1 (0x08192A3BU) #define FLASH_OPT_KEY2 (0x4C5D6E7FU) -#ifndef FLASH_OTP_BASE +/* OTP FLASH AREA */ #define FLASH_OTP_BASE 0x08FFF000 -#endif -#ifndef FLASH_OTP_END #define FLASH_OTP_END 0x08FFF3FF -#endif -#ifndef OTP_SIZE #define OTP_SIZE 1024 -#endif -#ifndef OTP_BLOCKS #define OTP_BLOCKS 16 -#endif -#define OTP_BLOCK_SIZE (OTP_SIZE / OTP_BLOCKS) /* 64 bytes */ /* STM32H7: Due to ECC functionality, it is not possible to write partition/sector * flags and signature more than once. This flags_cache is used to intercept write operations and diff --git a/tools/keytools/otp/otp-keystore-gen.c b/tools/keytools/otp/otp-keystore-gen.c index afbe4329..6a998938 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,8 +30,6 @@ #include #include -#define OTP_SIZE 4096 - #include "wolfboot/wolfboot.h" #include "keystore.h" #include "otp_keystore.h" @@ -59,7 +57,7 @@ int main(void) 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); @@ -71,7 +69,7 @@ int main(void) 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));