Skip to content

Commit c8aa838

Browse files
committed
Add oneshot hash build option
1 parent 5222385 commit c8aa838

6 files changed

Lines changed: 164 additions & 64 deletions

File tree

.github/workflows/test-elf-scattered.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,11 @@ jobs:
3535
- name: Run bootloader with no arguments
3636
run: |
3737
./wolfboot.elf
38+
39+
- name: Build wolfboot.elf (ELF_SCATTERED, ONESHOT_HASH)
40+
run: |
41+
make clean && make test-sim-internal-flash-with-update ELF=1 ELF_SCATTERED=1 WOLFBOOT_IMG_HASH_ONESHOT=1
42+
43+
- name: Run bootloader with no arguments (ONESHOT_HASH)
44+
run: |
45+
./wolfboot.elf

.github/workflows/test-sunnyday-simulator.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,30 @@ jobs:
379379
run: |
380380
tools/scripts/sim-sunnyday-update.sh
381381
382+
- name: Build wolfboot.elf (ECC256, ONESHOT_HASH, SHA256)
383+
run: |
384+
make clean && make test-sim-internal-flash-with-update SIGN=ECC256 SPMATH=1 WOLFBOOT_IMG_HASH_ONESHOT=1
385+
386+
- name: Run sunny day update test (ONESHOT_HASH, SHA256)
387+
run: |
388+
tools/scripts/sim-sunnyday-update.sh
389+
390+
- name: Build wolfboot.elf (ECC256, ONESHOT_HASH, SHA384)
391+
run: |
392+
make clean && make test-sim-internal-flash-with-update SIGN=ECC256 SPMATH=1 HASH=SHA384 WOLFBOOT_IMG_HASH_ONESHOT=1
393+
394+
- name: Run sunny day update test (ONESHOT_HASH, SHA384)
395+
run: |
396+
tools/scripts/sim-sunnyday-update.sh
397+
398+
- name: Build wolfboot.elf (ECC256, ONESHOT_HASH, SHA3)
399+
run: |
400+
make clean && make test-sim-internal-flash-with-update SIGN=ECC256 SPMATH=1 HASH=SHA3 WOLFBOOT_IMG_HASH_ONESHOT=1
401+
402+
- name: Run sunny day update test (ONESHOT_HASH, SHA3)
403+
run: |
404+
tools/scripts/sim-sunnyday-update.sh
405+
382406
- name: Cleanup to change key type
383407
run: |
384408
make keysclean

docs/compile.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,22 @@ falls in one of these cases, wolfBoot compilation will terminate with an explici
189189
In some cases you might have enough memory available to allow large stack allocations.
190190
To circumvent the compile-time checks on the maximum allowed stack size, use `WOLFBOOT_HUGE_STACK=1`.
191191

192+
### One-shot hash verification
193+
194+
By default, wolfBoot hashes firmware images in blocks of `WOLFBOOT_SHA_BLOCK_SIZE` bytes during
195+
verification. This block-by-block approach is required when firmware resides in external flash or
196+
other non-memory-mapped storage, where data must be read through intermediate buffers.
197+
198+
When firmware images are stored in directly memory-mapped flash (e.g. internal flash with
199+
execute-in-place support), the block-by-block overhead can be eliminated by enabling
200+
`WOLFBOOT_IMG_HASH_ONESHOT=1`. With this option, the entire image buffer is passed to the wolfCrypt
201+
hash function in a single call, which can improve verification performance.
202+
203+
**warning** This option assumes that `fw_base` pointers are directly dereferenceable for the full
204+
firmware size. It is incompatible with `EXT_FLASH=1` configurations where partitions reside on
205+
external SPI or UART flash. Only use `WOLFBOOT_IMG_HASH_ONESHOT=1` when all firmware partitions are
206+
in directly addressable, memory-mapped flash.
207+
192208
### Disable Backup of current running firmware
193209

194210
Optionally, it is possible to disable the backup copy of the current running firmware upon the installation of the

options.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,10 @@ ifeq ($(ARMORED),1)
779779
CFLAGS+=-DWOLFBOOT_ARMORED
780780
endif
781781

782+
ifeq ($(WOLFBOOT_IMG_HASH_ONESHOT),1)
783+
CFLAGS+=-DWOLFBOOT_IMG_HASH_ONESHOT
784+
endif
785+
782786
ifeq ($(WOLFBOOT_HUGE_STACK),1)
783787
CFLAGS+=-DWOLFBOOT_HUGE_STACK
784788
endif

src/image.c

Lines changed: 110 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -973,8 +973,7 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
973973
{
974974
uint8_t *stored_sha, *end_sha;
975975
uint16_t stored_sha_len;
976-
uint8_t *p;
977-
int blksz;
976+
uint8_t* p;
978977
if (!img)
979978
return -1;
980979

@@ -988,13 +987,20 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
988987
wc_InitSha256(sha256_ctx);
989988
#endif
990989
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
991-
while (p < end_sha) {
992-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
993-
if (end_sha - p < blksz)
994-
blksz = end_sha - p;
995-
wc_Sha256Update(sha256_ctx, p, blksz);
996-
p += blksz;
990+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
991+
wc_Sha256Update(sha256_ctx, p, (word32)(end_sha - p));
992+
#else
993+
{
994+
int blksz;
995+
while (p < end_sha) {
996+
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
997+
if (end_sha - p < blksz)
998+
blksz = end_sha - p;
999+
wc_Sha256Update(sha256_ctx, p, blksz);
1000+
p += blksz;
1001+
}
9971002
}
1003+
#endif
9981004
return 0;
9991005
}
10001006

@@ -1007,23 +1013,29 @@ static int header_sha256(wc_Sha256 *sha256_ctx, struct wolfBoot_image *img)
10071013
*/
10081014
static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
10091015
{
1010-
uint32_t position = 0;
1011-
uint8_t *p;
1012-
int blksz;
10131016
wc_Sha256 sha256_ctx;
10141017

10151018
if (header_sha256(&sha256_ctx, img) != 0)
10161019
return -1;
1017-
do {
1018-
p = get_sha_block(img, position);
1019-
if (p == NULL)
1020-
break;
1021-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1022-
if (position + blksz > img->fw_size)
1023-
blksz = img->fw_size - position;
1024-
wc_Sha256Update(&sha256_ctx, p, blksz);
1025-
position += blksz;
1026-
} while(position < img->fw_size);
1020+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1021+
wc_Sha256Update(&sha256_ctx, img->fw_base, img->fw_size);
1022+
#else
1023+
{
1024+
uint32_t position = 0;
1025+
uint8_t* p;
1026+
int blksz;
1027+
do {
1028+
p = get_sha_block(img, position);
1029+
if (p == NULL)
1030+
break;
1031+
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1032+
if (position + blksz > img->fw_size)
1033+
blksz = img->fw_size - position;
1034+
wc_Sha256Update(&sha256_ctx, p, blksz);
1035+
position += blksz;
1036+
} while (position < img->fw_size);
1037+
}
1038+
#endif
10271039

10281040
wc_Sha256Final(&sha256_ctx, hash);
10291041
wc_Sha256Free(&sha256_ctx);
@@ -1064,8 +1076,7 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
10641076
{
10651077
uint16_t stored_sha_len;
10661078
uint8_t *stored_sha, *end_sha;
1067-
uint8_t *p;
1068-
int blksz;
1079+
uint8_t* p;
10691080
if (!img)
10701081
return -1;
10711082

@@ -1079,13 +1090,20 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
10791090
wc_InitSha384(sha384_ctx);
10801091
#endif
10811092
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
1082-
while (p < end_sha) {
1083-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1084-
if (end_sha - p < blksz)
1085-
blksz = end_sha - p;
1086-
wc_Sha384Update(sha384_ctx, p, blksz);
1087-
p += blksz;
1093+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1094+
wc_Sha384Update(sha384_ctx, p, (word32)(end_sha - p));
1095+
#else
1096+
{
1097+
int blksz;
1098+
while (p < end_sha) {
1099+
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1100+
if (end_sha - p < blksz)
1101+
blksz = end_sha - p;
1102+
wc_Sha384Update(sha384_ctx, p, blksz);
1103+
p += blksz;
1104+
}
10881105
}
1106+
#endif
10891107
return 0;
10901108
}
10911109

@@ -1101,23 +1119,29 @@ static int header_sha384(wc_Sha384 *sha384_ctx, struct wolfBoot_image *img)
11011119
*/
11021120
static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
11031121
{
1104-
uint32_t position = 0;
1105-
uint8_t *p;
1106-
int blksz;
11071122
wc_Sha384 sha384_ctx;
11081123

11091124
if (header_sha384(&sha384_ctx, img) != 0)
11101125
return -1;
1111-
do {
1112-
p = get_sha_block(img, position);
1113-
if (p == NULL)
1114-
break;
1115-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1116-
if (position + blksz > img->fw_size)
1117-
blksz = img->fw_size - position;
1118-
wc_Sha384Update(&sha384_ctx, p, blksz);
1119-
position += blksz;
1120-
} while(position < img->fw_size);
1126+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1127+
wc_Sha384Update(&sha384_ctx, img->fw_base, img->fw_size);
1128+
#else
1129+
{
1130+
uint32_t position = 0;
1131+
uint8_t* p;
1132+
int blksz;
1133+
do {
1134+
p = get_sha_block(img, position);
1135+
if (p == NULL)
1136+
break;
1137+
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1138+
if (position + blksz > img->fw_size)
1139+
blksz = img->fw_size - position;
1140+
wc_Sha384Update(&sha384_ctx, p, blksz);
1141+
position += blksz;
1142+
} while (position < img->fw_size);
1143+
}
1144+
#endif
11211145

11221146
wc_Sha384Final(&sha384_ctx, hash);
11231147
wc_Sha384Free(&sha384_ctx);
@@ -1164,8 +1188,7 @@ static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
11641188
{
11651189
uint16_t stored_sha_len;
11661190
uint8_t *stored_sha, *end_sha;
1167-
uint8_t *p;
1168-
int blksz;
1191+
uint8_t* p;
11691192

11701193
if (!img)
11711194
return -1;
@@ -1176,13 +1199,20 @@ static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
11761199
return -1;
11771200
wc_InitSha3_384(sha3_ctx, NULL, INVALID_DEVID);
11781201
end_sha = stored_sha - (2 * sizeof(uint16_t)); /* Subtract 2 Type + 2 Len */
1179-
while (p < end_sha) {
1180-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1181-
if (end_sha - p < blksz)
1182-
blksz = end_sha - p;
1183-
wc_Sha3_384_Update(sha3_ctx, p, blksz);
1184-
p += blksz;
1202+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1203+
wc_Sha3_384_Update(sha3_ctx, p, (word32)(end_sha - p));
1204+
#else
1205+
{
1206+
int blksz;
1207+
while (p < end_sha) {
1208+
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1209+
if (end_sha - p < blksz)
1210+
blksz = end_sha - p;
1211+
wc_Sha3_384_Update(sha3_ctx, p, blksz);
1212+
p += blksz;
1213+
}
11851214
}
1215+
#endif
11861216
return 0;
11871217
}
11881218

@@ -1197,23 +1227,29 @@ static int header_sha3_384(wc_Sha3 *sha3_ctx, struct wolfBoot_image *img)
11971227
*/
11981228
static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
11991229
{
1200-
uint8_t *p;
1201-
int blksz;
1202-
uint32_t position = 0;
12031230
wc_Sha3 sha3_ctx;
12041231

12051232
if (header_sha3_384(&sha3_ctx, img) != 0)
12061233
return -1;
1207-
do {
1208-
p = get_sha_block(img, position);
1209-
if (p == NULL)
1210-
break;
1211-
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1212-
if (position + blksz > img->fw_size)
1213-
blksz = img->fw_size - position;
1214-
wc_Sha3_384_Update(&sha3_ctx, p, blksz);
1215-
position += blksz;
1216-
} while(position < img->fw_size);
1234+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1235+
wc_Sha3_384_Update(&sha3_ctx, img->fw_base, img->fw_size);
1236+
#else
1237+
{
1238+
uint8_t* p;
1239+
int blksz;
1240+
uint32_t position = 0;
1241+
do {
1242+
p = get_sha_block(img, position);
1243+
if (p == NULL)
1244+
break;
1245+
blksz = WOLFBOOT_SHA_BLOCK_SIZE;
1246+
if (position + blksz > img->fw_size)
1247+
blksz = img->fw_size - position;
1248+
wc_Sha3_384_Update(&sha3_ctx, p, blksz);
1249+
position += blksz;
1250+
} while (position < img->fw_size);
1251+
}
1252+
#endif
12171253

12181254
wc_Sha3_384_Final(&sha3_ctx, hash);
12191255
wc_Sha3_384_Free(&sha3_ctx);
@@ -1728,6 +1764,10 @@ static int update_hash_flash_fwimg(wolfBoot_hash_t* ctx,
17281764
struct wolfBoot_image* img, uint32_t offset,
17291765
uint32_t size)
17301766
{
1767+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1768+
update_hash(ctx, img->fw_base + offset, size);
1769+
return 0;
1770+
#else
17311771
uint32_t current_offset = offset;
17321772
uint32_t remaining_size = size;
17331773
uint8_t read_buf[WOLFBOOT_SHA_BLOCK_SIZE] XALIGNED_STACK(4); /* Use local buffer */
@@ -1750,6 +1790,7 @@ static int update_hash_flash_fwimg(wolfBoot_hash_t* ctx,
17501790
current_offset += read_size;
17511791
}
17521792
return 0;
1793+
#endif
17531794
}
17541795

17551796
/*
@@ -1759,6 +1800,11 @@ static int update_hash_flash_fwimg(wolfBoot_hash_t* ctx,
17591800
static int update_hash_flash_addr(wolfBoot_hash_t* ctx, uintptr_t addr,
17601801
uint32_t size, int src_ext)
17611802
{
1803+
#ifdef WOLFBOOT_IMG_HASH_ONESHOT
1804+
(void)src_ext;
1805+
update_hash(ctx, (uint8_t*)addr, size);
1806+
return 0;
1807+
#else
17621808
uint8_t buffer[WOLFBOOT_SHA_BLOCK_SIZE] XALIGNED_STACK(4);
17631809
uint32_t remaining_size = size;
17641810
uintptr_t current_addr = addr;
@@ -1783,6 +1829,7 @@ static int update_hash_flash_addr(wolfBoot_hash_t* ctx, uintptr_t addr,
17831829
}
17841830

17851831
return 0;
1832+
#endif
17861833
}
17871834

17881835
int wolfBoot_check_flash_image_elf(uint8_t part, unsigned long* entry_out)

tools/config.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ ifeq ($(ARCH),)
7878
WOLFBOOT_SMALL_STACK?=0
7979
DELTA_UPDATES?=0
8080
DELTA_BLOCK_SIZE?=256
81+
WOLFBOOT_IMG_HASH_ONESHOT?=0
8182
WOLFBOOT_HUGE_STACK?=0
8283
ARMORED?=0
8384
ELF?=0
@@ -107,7 +108,7 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO
107108
WOLFBOOT_PARTITION_BOOT_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS \
108109
WOLFBOOT_PARTITION_SWAP_ADDRESS WOLFBOOT_LOAD_ADDRESS \
109110
WOLFBOOT_LOAD_DTS_ADDRESS WOLFBOOT_DTS_BOOT_ADDRESS WOLFBOOT_DTS_UPDATE_ADDRESS \
110-
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE \
111+
WOLFBOOT_SMALL_STACK DELTA_UPDATES DELTA_BLOCK_SIZE WOLFBOOT_IMG_HASH_ONESHOT \
111112
WOLFBOOT_HUGE_STACK FORCE_32BIT\
112113
ENCRYPT_WITH_CHACHA ENCRYPT_WITH_AES128 ENCRYPT_WITH_AES256 ARMORED \
113114
LMS_LEVELS LMS_HEIGHT LMS_WINTERNITZ \

0 commit comments

Comments
 (0)