Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/examples/stm32h5-tz-dualbank-otp-lms.config
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ DUALBANK_SWAP?=1
WOLFBOOT_PARTITION_SIZE?=0xA0000
WOLFBOOT_SECTOR_SIZE?=0x2000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08160000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C160000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF
FLAGS_HOME=0
DISABLE_BACKUP=0
Expand Down
2 changes: 1 addition & 1 deletion config/examples/stm32h5-tz-dualbank-otp.config
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ DUALBANK_SWAP?=1
WOLFBOOT_PARTITION_SIZE?=0xA0000
WOLFBOOT_SECTOR_SIZE?=0x2000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08160000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C160000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFFFFFF
FLAGS_HOME=0
DISABLE_BACKUP=0
Expand Down
4 changes: 2 additions & 2 deletions config/examples/stm32h5-tz.config
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ DUALBANK_SWAP?=0
WOLFBOOT_PARTITION_SIZE?=0xA0000
WOLFBOOT_SECTOR_SIZE?=0x2000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x08060000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x08100000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x081A0000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0C100000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x0C1A0000
FLAGS_HOME=0
DISABLE_BACKUP=0
WOLFCRYPT_TZ=1
Expand Down
32 changes: 32 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,35 @@ the two images again.
For more information about the update process, see [Firmware Update](firmware_update.md)

For the image format, see [Firmware Image](firmware_image.md)

## NSC API

If you're running wolfBoot on an ARM TrustZone-enabled device (see for example
[STM32-TZ](STM32-TZ.md)) you may wish to run your application in non-secure
mode, while keeping the UPDATE and SWAP partitions in the secure domain. In
order to accomplish this, any operation by the application that requires access
to those partitions needs to be performed via wolfBoot code running in the
secure domain. For this purpose, wolfBoot provides Non-Secure Callable (NSC)
APIs that allow code running in the non-secure domain to call into the secure
domain managed by wolfBoot.

These APIs are listed below.

- `void wolfBoot_nsc_success(void)`: wrapper for `wolfBoot_success()`
- `void wolfBoot_nsc_update_trigger(void)`: wrapper for
`wolfBoot_update_trigger()`
- `uint32_t wolfBoot_nsc_get_image_version(uint8_t part)`: wrapper for
`wolfBoot_get_image_version()`
- `uint32_t wolfBoot_nsc_current_firmware_version(void)`: wrapper for
`wolfBoot_current_firmware_version()`
- `uint32_t wolfBoot_nsc_update_firmware_version(void)`: wrapper for
`wolfBoot_update_firmware_version()`
- `int wolfBoot_nsc_get_partition_state(uint8_t part, uint8_t *st)`: wrapper
for `wolfBoot_get_partition_state()`
- `int wolfBoot_nsc_erase_update(uint32_t address, uint32_t len)`: allows the
application to erase the update partition in secure mode. The `address`
parameter is an offset from the beginning of the partition.
- `int wolfBoot_nsc_write_update(uint32_t address, const uint8_t *buf, uint32_t
len)`: allows the application to write to the update partition in secure
mode. The `address` parameter is an offset from the beginning of the
partition.
14 changes: 10 additions & 4 deletions docs/STM32-TZ.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ image header size must be supplied as an environment variable. For example:
IMAGE_HEADER_SIZE=1024 ./tools/keytools/sign --sha256 --ecc256 myapp.bin wolfboot_signing_private_key.der 1
```

### NSC API

wolfBoot provides a few Non-Secure Callable functions to allow a non-secure
application to perform certain operations that must be run from the secure
domain. For more information, see [API](API.md#nsc-api).

### Example using STM32L552

- Copy the example configuration for STM32-L5 with support for wolfCrypt in
Expand Down Expand Up @@ -192,7 +198,7 @@ OPTION BYTES BANK: 2

Boot Configuration:

NSBOOTADD : 0x80400 (0x8040000)
NSBOOTADD : 0x80600 (0x8060000)
NSBOOT_LOCK : 0xC3 (The SWAP_BANK and NSBOOTADD can still be modified following their individual rules.)
SECBOOT_LOCK : 0xC3 (The BOOT_UBE, SWAP_BANK and SECBOOTADD can still be modified following their individual rules.)
SECBOOTADD : 0xC0000 (0xC000000)
Expand All @@ -201,7 +207,7 @@ OPTION BYTES BANK: 3
Bank1 - Flash watermark area definition:

SECWM1_STRT : 0x0 (0x8000000)
SECWM1_END : 0x1F (0x803E000)
SECWM1_END : 0x2F (0x805e000)

Write sector group protection 1:

Expand All @@ -211,7 +217,7 @@ OPTION BYTES BANK: 4
Bank2 - Flash watermark area definition:

SECWM2_STRT : 0x0 (0x08100000)
SECWM2_END : 0x1F (0x0813e000)
SECWM2_END : 0x7F (0x081fe0000)

Write sector group protection 2:

Expand Down Expand Up @@ -251,7 +257,7 @@ OPTION BYTES BANK: 9

```
STM32_Programmer_CLI -c port=swd -d wolfboot.bin 0x0C000000
STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08040000
STM32_Programmer_CLI -c port=swd -d test-app/image_v1_signed.bin 0x08060000
```

- After rebooting, the LED on the board should turn on sequentially:
Expand Down
37 changes: 25 additions & 12 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,10 @@ The example configuration for this scenario is available in [/config/examples/st
- User Option Bytes requirement (with STM32CubeProgrammer tool - see below for instructions)

```
TZEN = 1 System with TrustZone-M enabled
DBANK = 1 Dual bank mode
SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F All 128 pages of internal Flash Bank1 set as secure
SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
TZEN = 1 System with TrustZone-M enabled
DBANK = 1 Dual bank mode
SECWM1_STRT=0x0 SECWM1_END=0x7F All 128 pages of internal Flash Bank1 set as secure
SECWM2_STRT=0x1 SECWM2_END=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
```

- NOTE: STM32CubeProgrammer V2.3.0 is required (v2.4.0 has a known bug for STM32L5)
Expand All @@ -189,7 +189,7 @@ SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secur
2. `make`
3. Prepare board with option bytes configuration reported above
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob TZEN=1 DBANK=1`
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F SECWM2_PSTRT=0x1 SECWM2_PEND=0x0`
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_STRT=0x0 SECWM1_END=0x7F SECWM2_STRT=0x1 SECWM2_END=0x0`
4. flash wolfBoot.bin to 0x0c00 0000
- `STM32_Programmer_CLI -c port=swd -d ./wolfboot.bin 0x0C000000`
5. flash .\test-app\image_v1_signed.bin to 0x0804 0000
Expand Down Expand Up @@ -316,10 +316,10 @@ SRAM memories into two parts:
- User Option Bytes requirement (with STM32CubeProgrammer tool - see below for instructions)

```
TZEN = 1 System with TrustZone-M enabled
DBANK = 1 Dual bank mode
SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F All 128 pages of internal Flash Bank1 set as secure
SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
TZEN = 1 System with TrustZone-M enabled
DBANK = 1 Dual bank mode
SECWM1_STRT=0x0 SECWM1_END=0x7F All 128 pages of internal Flash Bank1 set as secure
SECWM2_STRT=0x1 SECWM2_END=0x0 No page of internal Flash Bank2 set as secure, hence Bank2 non-secure
```

- NOTE: STM32CubeProgrammer V2.8.0 or newer is required
Expand All @@ -330,7 +330,7 @@ SECWM2_PSTRT=0x1 SECWM2_PEND=0x0 No page of internal Flash Bank2 set as secur
2. `make TZEN=1`
3. Prepare board with option bytes configuration reported above
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob TZEN=1 DBANK=1`
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_PSTRT=0x0 SECWM1_PEND=0x7F SECWM2_PSTRT=0x1 SECWM2_PEND=0x0`
- `STM32_Programmer_CLI -c port=swd mode=hotplug -ob SECWM1_STRT=0x0 SECWM1_END=0x7F SECWM2_STRT=0x1 SECWM2_END=0x0`
4. flash wolfBoot.bin to 0x0c000000
- `STM32_Programmer_CLI -c port=swd -d ./wolfboot.bin 0x0C000000`
5. flash .\test-app\image_v1_signed.bin to 0x08010000
Expand Down Expand Up @@ -915,7 +915,7 @@ The example configuration for this scenario is available in [/config/examples/st
`STM32_Programmer_CLI -c port=swd -ob TZEN=0xB4`

- set the option bytes to enable flash secure protection of first 384KB and remainder as non-secure:
`STM32_Programmer_CLI -c port=swd -ob SECWM1_PSTRT=0x0 SECWM1_PEND=0x2F SECWM2_PSTRT=0x2F SECWM2_PEND=0x0`
`STM32_Programmer_CLI -c port=swd -ob SECWM1_STRT=0x0 SECWM1_END=0x2F SECWM2_STRT=0x0 SECWM2_END=0x7F`

- flash the wolfboot image to the secure partition:
`STM32_Programmer_CLI -c port=swd -d wolfboot.bin 0x0C000000`
Expand All @@ -925,6 +925,19 @@ 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).

You can use the "update" command and XMODEM to send a newly signed update (see docs/flash-OTP.md) or use the steps below using the STM32_Programmer:

```sh
IMAGE_HEADER_SIZE=1024 tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2
echo -n "pBOOT" > trigger_magic.bin
./tools/bin-assemble/bin-assemble \
update.bin \
0x0 test-app/image_v2_signed.bin \
0x9FFFB trigger_magic.bin
STM32_Programmer_CLI -c port=swd -d update.bin 0x0C100000
```


### 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
Expand Down Expand Up @@ -975,7 +988,7 @@ To initiate an update, sign a new version of the app and upload the v3 to the up
on the second bank:

```sh
tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 3
IMAGE_HEADER_SIZE=1024 tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 3
STM32_Programmer_CLI -c port=swd -d test-app/image_v3_signed.bin 0x08160000
```

Expand Down
14 changes: 10 additions & 4 deletions hal/stm32_tz.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,21 @@ void hal_tz_claim_nonsecure_area(uint32_t address, int len)
uint32_t reg;
uint32_t end = address + len;
uint32_t start_address = address;
uint32_t start_page_n;
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;
start_page_n = (address - ARCH_FLASH_OFFSET) / FLASH_PAGE_SIZE;
bank = 0;
} else {
page_n = (address - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE;
start_page_n = (address - FLASH_BANK2_BASE) / FLASH_PAGE_SIZE;
bank = 1;
}
page_n = start_page_n;
#ifdef TARGET_stm32h5
/* Take into account current swap configuration */
if ((FLASH_OPTSR_CUR & FLASH_OPTSR_SWAP_BANK) >> 31)
Expand All @@ -129,13 +131,14 @@ void hal_tz_claim_nonsecure_area(uint32_t address, int len)
page_n++;
}
address = start_address;
page_n = start_page_n;
while (address < end) {
/* Erase claimed non-secure page, in secure mode */
#ifndef TARGET_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));
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_BKSEL));
FLASH_CR = reg | ((page_n << FLASH_CR_PNB_SHIFT) | FLASH_CR_SER | (bank << 31));
#endif

Expand All @@ -162,8 +165,11 @@ void hal_tz_release_nonsecure_area(void)
{
#ifndef DUALBANK_SWAP
int i;
for (i = 0; i < FLASH_SECBB_NREGS; i++)
/* Set all banks as non-secure */
for (i = 0; i < FLASH_SECBB_NREGS; i++) {
FLASH_SECBB1[i] = 0;
FLASH_SECBB2[i] = 0;
}
#else
uint32_t addr;
int bank_swp = 0;
Expand Down
48 changes: 30 additions & 18 deletions hal/stm32h5.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,11 @@
#define PLL_SRC_HSE 1

#if TZ_SECURE()

/* This function assumes that the boot and the update
* partitions are at the same address in the two banks,
* regardless if DUALBANK_SWAP is active or not.
*/
static int is_flash_nonsecure(uint32_t address)
{
uint32_t in_bank_offset = (address & 0x000FFFFF);
if (in_bank_offset >= (WOLFBOOT_PARTITION_BOOT_ADDRESS - FLASHMEM_ADDRESS_SPACE)) {
if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS &&
address < WOLFBOOT_PARTITION_BOOT_ADDRESS +
WOLFBOOT_PARTITION_SIZE) {
return 1;
}
return 0;
Expand Down Expand Up @@ -189,6 +185,7 @@ void RAMFUNCTION hal_flash_opt_lock(void)

int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
{
uint32_t start_address;
uint32_t end_address;
uint32_t p;

Expand All @@ -199,35 +196,50 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
if (address < 0x08000000)
return -1;

end_address = address + len - 1;
for (p = address; p < end_address; p += FLASH_PAGE_SIZE) {
#if TZ_SECURE()
if (address & FLASH_SECURE_MMAP_BIT) {
/* Get address in non-secure address space */
start_address = address & ~FLASH_SECURE_MMAP_BIT;
}
else {
if (is_flash_nonsecure(address)) {
hal_tz_claim_nonsecure_area(address, len);
}
start_address = address;
}
#else
start_address = address;
#endif

end_address = start_address + len - 1;
for (p = start_address; p < end_address; p += FLASH_PAGE_SIZE) {
uint32_t reg;
uint32_t base;
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) ))
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_BKSEL));
if (p >= FLASH_BANK2_BASE && p <= FLASH_TOP)
{
base = FLASH_BANK2_BASE;
bnksel = 1;
}
#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;
ISB();
FLASH_CR |= FLASH_CR_STRT;
hal_flash_wait_complete(0);
hal_flash_wait_complete(bnksel);
}
/* If the erase operation is completed, disable the associated bits */
FLASH_CR &= ~FLASH_CR_SER ;

#if TZ_SECURE()
if (!(address & FLASH_SECURE_MMAP_BIT) && is_flash_nonsecure(address)) {
hal_tz_release_nonsecure_area();
}
#endif
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions hal/stm32h5.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#endif

#define FLASH_SECURE_MMAP_BASE (0x0C000000)
#define FLASH_SECURE_MMAP_BIT (0x04000000)

#define RCC_CR (*(volatile uint32_t *)(RCC_BASE + 0x00)) /* RM0481 - Table 108 */
#define RCC_CR_PLL3RDY (1 << 29) /* RM0481 - Table 108 */
Expand Down
11 changes: 10 additions & 1 deletion include/wolfboot/wolfboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,14 +420,23 @@ int wolfBoot_erase_encrypt_key(void);
*/

/* Call wolfBoot_success from non-secure application */

__attribute__((cmse_nonsecure_entry))
void wolfBoot_nsc_success(void);

/* Call wolfBoot_update_trigger from non-secure application */
__attribute__((cmse_nonsecure_entry))
void wolfBoot_nsc_update_trigger(void);

/* Call wolfBoot_get_image_version from non-secure application */
__attribute__((cmse_nonsecure_entry))
uint32_t wolfBoot_nsc_get_image_version(uint8_t part);
#define wolfBoot_nsc_current_firmware_version() wolfBoot_nsc_get_image_version(PART_BOOT)
#define wolfBoot_nsc_update_firmware_version() wolfBoot_nsc_get_image_version(PART_UPDATE)

/* Call wolfBoot_get_partition_state from non-secure application */
__attribute__((cmse_nonsecure_entry))
int wolfBoot_nsc_get_partition_state(uint8_t part, uint8_t *st);

/* Erase one or more sectors in the update partition.
* - address: offset within the update partition ('0' corresponds to PARTITION_UPDATE_ADDRESS)
* - len: size, in bytes
Expand Down
Loading