Skip to content
Open
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
8 changes: 8 additions & 0 deletions .github/workflows/test-elf-scattered.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ jobs:
- name: Run bootloader with no arguments
run: |
./wolfboot.elf

- name: Build wolfboot.elf (ELF_SCATTERED, ONESHOT_HASH)
run: |
make clean && make test-sim-internal-flash-with-update ELF=1 ELF_SCATTERED=1 WOLFBOOT_IMG_HASH_ONESHOT=1

- name: Run bootloader with no arguments (ONESHOT_HASH)
run: |
./wolfboot.elf
24 changes: 24 additions & 0 deletions .github/workflows/test-sunnyday-simulator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,30 @@ jobs:
run: |
tools/scripts/sim-sunnyday-update.sh

- name: Build wolfboot.elf (ECC256, ONESHOT_HASH, SHA256)
run: |
make clean && make test-sim-internal-flash-with-update SIGN=ECC256 SPMATH=1 WOLFBOOT_IMG_HASH_ONESHOT=1

- name: Run sunny day update test (ONESHOT_HASH, SHA256)
run: |
tools/scripts/sim-sunnyday-update.sh

- name: Build wolfboot.elf (ECC256, ONESHOT_HASH, SHA384)
run: |
make clean && make test-sim-internal-flash-with-update SIGN=ECC256 SPMATH=1 HASH=SHA384 WOLFBOOT_IMG_HASH_ONESHOT=1

- name: Run sunny day update test (ONESHOT_HASH, SHA384)
run: |
tools/scripts/sim-sunnyday-update.sh

- name: Build wolfboot.elf (ECC256, ONESHOT_HASH, SHA3)
run: |
make clean && make test-sim-internal-flash-with-update SIGN=ECC256 SPMATH=1 HASH=SHA3 WOLFBOOT_IMG_HASH_ONESHOT=1

- name: Run sunny day update test (ONESHOT_HASH, SHA3)
run: |
tools/scripts/sim-sunnyday-update.sh

- name: Cleanup to change key type
run: |
make keysclean
Expand Down
16 changes: 16 additions & 0 deletions docs/compile.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,22 @@ falls in one of these cases, wolfBoot compilation will terminate with an explici
In some cases you might have enough memory available to allow large stack allocations.
To circumvent the compile-time checks on the maximum allowed stack size, use `WOLFBOOT_HUGE_STACK=1`.

### One-shot hash verification

By default, wolfBoot hashes firmware images in blocks of `WOLFBOOT_SHA_BLOCK_SIZE` bytes during
verification. This block-by-block approach is required when firmware resides in external flash or
other non-memory-mapped storage, where data must be read through intermediate buffers.

When firmware images are stored in directly memory-mapped flash (e.g. internal flash with
execute-in-place support), the block-by-block overhead can be eliminated by enabling
`WOLFBOOT_IMG_HASH_ONESHOT=1`. With this option, the entire image buffer is passed to the wolfCrypt
hash function in a single call, which can improve verification performance.

**warning** This option assumes that `fw_base` pointers are directly dereferenceable for the full
firmware size. It is incompatible with `EXT_FLASH=1` configurations where partitions reside on
external SPI or UART flash. Only use `WOLFBOOT_IMG_HASH_ONESHOT=1` when all firmware partitions are
in directly addressable, memory-mapped flash.

### Disable Backup of current running firmware

Optionally, it is possible to disable the backup copy of the current running firmware upon the installation of the
Expand Down
4 changes: 4 additions & 0 deletions options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,10 @@ ifeq ($(ARMORED),1)
CFLAGS+=-DWOLFBOOT_ARMORED
endif

ifeq ($(WOLFBOOT_IMG_HASH_ONESHOT),1)
CFLAGS+=-DWOLFBOOT_IMG_HASH_ONESHOT
endif

ifeq ($(WOLFBOOT_HUGE_STACK),1)
CFLAGS+=-DWOLFBOOT_HUGE_STACK
endif
Expand Down
185 changes: 122 additions & 63 deletions src/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,8 +973,7 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
{
uint8_t *stored_sha, *end_sha;
uint16_t stored_sha_len;
uint8_t *p;
int blksz;
uint8_t* p;
if (!img)
return -1;

Expand All @@ -988,13 +987,22 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
wc_InitSha256(sha256_ctx);
#endif
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha256Update(sha256_ctx, p, blksz);
p += blksz;
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
if (end_sha <= p)
return -1;
wc_Sha256Update(sha256_ctx, p, (word32)(end_sha - p));
#else
{
int blksz;
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha256Update(sha256_ctx, p, blksz);
p += blksz;
}
}
#endif
return 0;
}

Expand All @@ -1007,23 +1015,31 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
*/
static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
{
uint32_t position = 0;
uint8_t *p;
int blksz;
wc_Sha256 sha256_ctx;

if (header_sha256(&sha256_ctx, img) != 0)
return -1;
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wc_Sha256Update(&sha256_ctx, p, blksz);
position += blksz;
} while(position < img->fw_size);
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
if (img->fw_base == NULL)
return -1;
wc_Sha256Update(&sha256_ctx, img->fw_base, img->fw_size);
#else
{
uint32_t position = 0;
uint8_t* p;
int blksz;
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wc_Sha256Update(&sha256_ctx, p, blksz);
position += blksz;
} while (position < img->fw_size);
}
#endif

wc_Sha256Final(&sha256_ctx, hash);
wc_Sha256Free(&sha256_ctx);
Expand Down Expand Up @@ -1064,8 +1080,7 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
{
uint16_t stored_sha_len;
uint8_t *stored_sha, *end_sha;
uint8_t *p;
int blksz;
uint8_t* p;
if (!img)
return -1;

Expand All @@ -1079,13 +1094,22 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
wc_InitSha384(sha384_ctx);
#endif
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha384Update(sha384_ctx, p, blksz);
p += blksz;
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
if (end_sha <= p)
return -1;
wc_Sha384Update(sha384_ctx, p, (word32)(end_sha - p));
#else
{
int blksz;
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha384Update(sha384_ctx, p, blksz);
p += blksz;
}
}
#endif
return 0;
}

Expand All @@ -1101,23 +1125,31 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
*/
static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
{
uint32_t position = 0;
uint8_t *p;
int blksz;
wc_Sha384 sha384_ctx;

if (header_sha384(&sha384_ctx, img) != 0)
return -1;
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wc_Sha384Update(&sha384_ctx, p, blksz);
position += blksz;
} while(position < img->fw_size);
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
if (img->fw_base == NULL)
return -1;
wc_Sha384Update(&sha384_ctx, img->fw_base, img->fw_size);
#else
{
uint32_t position = 0;
uint8_t* p;
int blksz;
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wc_Sha384Update(&sha384_ctx, p, blksz);
position += blksz;
} while (position < img->fw_size);
}
#endif

wc_Sha384Final(&sha384_ctx, hash);
wc_Sha384Free(&sha384_ctx);
Expand Down Expand Up @@ -1164,8 +1196,7 @@ static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
{
uint16_t stored_sha_len;
uint8_t *stored_sha, *end_sha;
uint8_t *p;
int blksz;
uint8_t* p;

if (!img)
return -1;
Expand All @@ -1176,13 +1207,22 @@ static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
return -1;
wc_InitSha3_384(sha3_ctx, NULL, INVALID_DEVID);
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha3_384_Update(sha3_ctx, p, blksz);
p += blksz;
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
if (end_sha <= p)
return -1;
wc_Sha3_384_Update(sha3_ctx, p, (word32)(end_sha - p));
#else
{
int blksz;
while (p < end_sha) {
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (end_sha - p < blksz)
blksz = end_sha - p;
wc_Sha3_384_Update(sha3_ctx, p, blksz);
p += blksz;
}
}
#endif
return 0;
}

Expand All @@ -1197,23 +1237,31 @@ static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
*/
static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
{
uint8_t *p;
int blksz;
uint32_t position = 0;
wc_Sha3 sha3_ctx;

if (header_sha3_384(&sha3_ctx, img) != 0)
return -1;
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wc_Sha3_384_Update(&sha3_ctx, p, blksz);
position += blksz;
} while(position < img->fw_size);
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
if (img->fw_base == NULL)
return -1;
wc_Sha3_384_Update(&sha3_ctx, img->fw_base, img->fw_size);
#else
{
uint8_t* p;
int blksz;
uint32_t position = 0;
do {
p = get_sha_block(img, position);
if (p == NULL)
break;
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
if (position + blksz > img->fw_size)
blksz = img->fw_size - position;
wc_Sha3_384_Update(&sha3_ctx, p, blksz);
position += blksz;
} while (position < img->fw_size);
}
#endif

wc_Sha3_384_Final(&sha3_ctx, hash);
wc_Sha3_384_Free(&sha3_ctx);
Expand Down Expand Up @@ -1728,6 +1776,10 @@ static int update_hash_flash_fwimg(wolfBoot_hash_t* ctx,
struct wolfBoot_image* img, uint32_t offset,
uint32_t size)
{
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
update_hash(ctx, img->fw_base + offset, size);
return 0;
#else
uint32_t current_offset = offset;
uint32_t remaining_size = size;
uint8_t read_buf[WOLFBOOT_SHA_BLOCK_SIZE] XALIGNED_STACK(4); /* Use local buffer */
Expand All @@ -1750,6 +1802,7 @@ static int update_hash_flash_fwimg(wolfBoot_hash_t* ctx,
current_offset += read_size;
}
return 0;
#endif
}

/*
Expand All @@ -1759,6 +1812,11 @@ static int update_hash_flash_fwimg(wolfBoot_hash_t* ctx,
static int update_hash_flash_addr(wolfBoot_hash_t* ctx, uintptr_t addr,
uint32_t size, int src_ext)
{
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
(void)src_ext;
update_hash(ctx, (uint8_t*)addr, size);
return 0;
#else
uint8_t buffer[WOLFBOOT_SHA_BLOCK_SIZE] XALIGNED_STACK(4);
uint32_t remaining_size = size;
uintptr_t current_addr = addr;
Expand All @@ -1783,6 +1841,7 @@ static int update_hash_flash_addr(wolfBoot_hash_t* ctx, uintptr_t addr,
}

return 0;
#endif
}

int wolfBoot_check_flash_image_elf(uint8_t part, unsigned long* entry_out)
Expand Down
3 changes: 2 additions & 1 deletion tools/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ ifeq ($(ARCH),)
WOLFBOOT_SMALL_STACK?=0
DELTA_UPDATES?=0
DELTA_BLOCK_SIZE?=256
WOLFBOOT_IMG_HASH_ONESHOT?=0
WOLFBOOT_HUGE_STACK?=0
ARMORED?=0
ELF?=0
Expand Down Expand Up @@ -107,7 +108,7 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
WOLFBOOT_LOAD_DTS_ADDRESS WOLFBOOT_DTS_BOOT_ADDRESS WOLFBOOT_DTS_UPDATE_ADDRESS \
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE \
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE WOLFBOOT_IMG_HASH_ONESHOT \
WOLFBOOT_HUGE_STACK FORCE_32BIT\
ENCRYPT_WITH_CHACHA ENCRYPT_WITH_AES128 ENCRYPT_WITH_AES256 ARMORED \
LMS_LEVELS LMS_HEIGHT LMS_WINTERNITZ \
Expand Down
Loading